NAME
PMDA - introduction to the Performance Metrics Domain
Agent support library
C SYNOPSIS
#include <pcp/pmapi.h>
#include <pcp/impl.h>
#include <pcp/pmda.h>
cc ... -lpcp_pmda -lpcp
DESCRIPTION
To assist in the development of Performance Metric Domain
Agents (PMDAs) for the Performance Co-Pilot (PCP), a pro
cedural interface is provided that extends the Performance
Metrics Application Programming Interface ( PMAPI(3))
library. These procedures are designed to enable a pro
grammer to quickly build a PMDA which can then be tested
and refined. However, this also implies that a PMDA has a
particular structure which may not be suitable for all
applications.
Once you are familiar with the PCP and PMDA frameworks,
you can quickly implement a new PMDA with only a few data
structures and functions. This is covered in far greater
detail in the Performance Co-Pilot Programmer's Guide.
A PMDA is responsible for a set of performance metrics, in
the sense that it must respond to requests from pmcd(1)
for information about performance metrics, instance
domains, and instantiated values. The pmcd(1) process
generates requests on behalf of performance tools that
make requests using PMAPI(3) routines.
This man page contains sections of the simple PMDA which
is located at $PCP_PMDAS_DIR/simple.
COMMUNICATING WITH PMCD
Two approaches may be used for connecting a PMDA to a
pmcd(1) process. A Dynamic Shared Object (DSO) can be
attached by pmcd(1) using dlopen(3) when the pmcd(1) pro
cess is started. A procedural interface referenced
through a shared data structure is used to handle requests
from pmcd(1) to the PMDA.
The preferred approach is for a separate process (daemon)
to communicate with pmcd(1) using the Performance Data
Units (PDU) Inter-Process Communication (IPC) protocol.
All PMDAs are launched and controlled by the pmcd(1) pro
cess on the local host. The requests from the clients are
received by pmcd(1) and forwarded to the appropriate
pmcd(1) to the clients. The requests (PDUs) that may be
sent to a PMDA from pmcd(1) are PDU_FETCH, PDU_PROFILE,
PDU_INSTANCE_REQ, PDU_DESC_REQ, PDU_TEXT_REQ and
PDU_RESULT.
DEFAULT CALLBACKS FOR HANDLING PDUs
To allow a consistent framework, pmdaMain(3) can be used
by a daemon PMDA to handle the communication protocol
using the same callbacks as a DSO PMDA. The structure
pmdaInterface is used to convey the common procedural
interface and state information that is used by pmcd(1)
and a PMDA. This state information includes tables
describing the supported metrics and instance domains.
As most of the procedural interface is identical for all
PMDAs, they are provided as part of this support library
(pmdaProfile(3), pmdaFetch(3), pmdaInstance(3),
pmdaDesc(3), pmdaText(3) and pmdaStore(3)). However,
these routines require access to the pmdaInterface state
information so it must be correctly initialized using
pmdaConnect(3), pmdaDaemon(3), pmdaOpenLog(3), pmdaDSO(3),
pmdaGetOpt(3) and pmdaInit(3).
INSTANCES AND INSTANCE DOMAINS
Three structures are declared in /usr/include/pcp/pmda.h
which provide a framework for declaring the metrics and
instances supported by the PMDA.
Every instance requires a unique integer identifier and a
unique name, as defined by the structure pmdaInstid:
/*
* Instance description: index and name
*/
typedef struct {
int i_inst; /* internal instance identifier */
char *i_name; /* external instance identifier */
} pmdaInstid;
An instance domain requires its own unique identification
(pmInDom), the number of instances the domain represents,
and a pointer to an array of instance descriptions. This
is defined in the structure pmdaIndom:
/*
* Instance domain description: unique instance id,
* number of instances in this domain, and the list of
* instances (not null terminated).
*/
typedef struct {
pmInDom it_indom; /* indom, filled in */
pmdaInstid *it_set; /* instance identifiers */
} pmdaIndom;
The simple PMDA has one instance domain for simple.color
with three instances (red, green and blue), and a second
instance domain for simple.now with instances which can be
specified at run-time. These instance domains are defined
as:
static pmdaInstid _color[] = {
{ 0, "red" }, { 1, "green" }, { 2, "blue" }
};
static pmdaInstid *_timenow = NULL;
static pmdaIndom indomtab[] = {
#define COLOR_INDOM 0
{ COLOR_INDOM, 3, _color },
#define NOW_INDOM 1
{ NOW_INDOM, 0, NULL },
};
The preprocessor macros COLOR_INDOM and NOW_INDOM are used
in the metric description table to identify the instance
domains of individual metrics. These correspond to the
serial value in the instance domain pmInDom structure (the
domain field is set by pmdaInit(3) at run-time). The
serial value must be unique for each instance domain
within the PMDA.
The indom table shown above which is usually passed to
pmdaInit(3) does not need to be created if one wants to
write one's own Fetch and Instance functions. See
pmdaInit(3) for more details.
NAMESPACE
Every PMDA has its own unique namespace using the format
defined in pmns(4). In summary, the namespace matches the
names of the metrics to the unique identifier. The simple
PMDA defines five metrics: simple.numfetch, simple.color,
simple.time.user, simple.time.sys and simple.now. The
namespace for these metrics is defined in
$PCP_PMDAS_DIR/simple/pmns and is installed as:
simple {
numfetch 253:0:0
color 253:0:1
time
now 253:2:4
}
simple.time {
user 253:1:2
sys 253:1:3
The domain number of 253 is obtained from
$PCP_VAR_DIR/pmns/stdpmid. New PMDAs should specify a
unique domain number in this file, and obtain the number
during installation. This allows the domain number to
change by modifying only the file $PCP_VAR_DIR/pmns/stdp
mid.
The simple.time and simple.now metrics are defined in sep
arate clusters to the other metrics which allows a PMDA to
support more than 1024 metrics, as well as grouping simi
lar metrics together. Therefore, the item numbers for a
new cluster may be identical to the item numbers in other
clusters. The simple PMDA continues to increment the item
numbers to permit direct mapping (see pmdaInit(3)).
The namespace file should be installed and removed with
the agent using pmnsadd(1) and pmnsdel(1). See the later
sections on INSTALLATION and REMOVAL.
A simple ASCII namespace can be constructed by creating a
file similar to $PCP_PMDAS_DIR/simple/root:
/*
* fake "root" for validating the local PMNS subtree
*/
#include "$PCP_VAR_DIR/pmns/stdpmid"
root { simple }
#include "pmns"
and can be referred to with the -n option in most PCP
tools.
METRIC DESCRIPTIONS
Each metric requires a description (pmDesc), which con
tains its PMID, data type specification, instance domain,
semantics and units (see pmLookupDesc(3)). A handle is
also provided for application specific information in the
pmdaMetric structure:
/*
* Metric description: handle for extending description,
* and the description.
*/
typedef struct {
void* m_user; /* for users external use */
pmDesc m_desc; /* metric description */
} pmdaMetric;
static pmdaMetric metrictab[] = {
/* numfetch */
{ (void *)0,
{ PMDA_PMID(0,0), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT,
{ 0,0,0,0,0,0} }, },
/* color */
{ (void *)0,
{ PMDA_PMID(0,1), PM_TYPE_32, COLOR_INDOM, PM_SEM_INSTANT,
{ 0,0,0,0,0,0} }, },
/* time.user */
{ (void*)0,
{ PMDA_PMID(1,2), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_COUNTER,
{ 0, 1, 0, 0, PM_TIME_SEC, 0 } }, },
/* time.sys */
{ (void*)0,
{ PMDA_PMID(1,3), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_COUNTER,
{ 0, 1, 0, 0, PM_TIME_SEC, 0 } }, },
/* now */
{ NULL,
{ PMDA_PMID(2,4), PM_TYPE_U32, NOW_INDOM, PM_SEM_INSTANT,
{ 0,0,0,0,0,0 } }, },
};
The macro PMDA_PMID (defined in /usr/include/pcp/pmda.h)
is used to specify each metric's cluster and unit number
in the __pmID_int structure defined in
/usr/include/pcp/impl.h. As with instance domains, the
domain field is set by pmdaInit(3) at run-time, however,
the default domain is assumed to be defined by the PMDA in
the macro MYDOMAIN.
The metric table shown above which is usually passed to
pmdaInit(3) does not need to be created if one wants to
write one's own Fetch and Descriptor functions. See
pmdaInit(3) for more details.
DSO PMDA
A PMDA that is run as a DSO is opened by pmcd(1) with
dlopen(3). pmcd will call the PMDA's initialization func
tion that is specified in $PCP_PMCDCONF_PATH. This func
tion is passed a pointer to a pmdaInterface structure
which must be completed. Any callbacks which are not the
default PMDA support library callbacks must be specified
in the pmdaInterface structure.
The simple PMDA uses its own store and fetch callback.
simple_fetch() calls pmdaFetch(3) which requires a call
back to be set with pmdaSetFetchCallBack(3) as can be seen
in $PCP_PMDAS_DIR/simple/simple.c.
The flag _isDSO is used to determine if the PMDA is a dae
mon or a DSO so that the correct initialization routine,
DAEMON PMDA
A PMDA that is run as a daemon is forked and executed by
pmcd(1). Therefore, unlike a DSO PMDA, the starting point
for a daemon PMDA is main(). The agent should parse the
command line arguments, create a log file and initialize
some data structures that pmcd would initialize for a DSO
agent.
The pmdaInterface structure must be completely defined by
the daemon PMDA. The function pmdaDaemon(3) can be called
at the start of main() to set most of these fields. Com
mand line parsing can be simplified by using pmdaGe
tOpt(3), which is similar to getopt(2), but extracts a
common set of options into the pmdaInterface structure.
stderr can be mapped to a log file using pmdaOpenLog(3) to
simplify debugging and error messages. The connection to
pmcd can be made with pmdaConnect(3) and the loop which
handles the incoming PDUs, pmdaMain(3), should be the last
function called. This can be seen in $PCP_PMDAS_DIR/sim
ple/simple.c.
The simple_init() routine is common to an agent that can
be run as both a Daemon and DSO PMDA.
HELP TEXT
Each PMDA must be able to provide pmcd with the help text
for each metric. Most PMDAs use specially created files
with indexes to support efficient retrieval of the help
text. Tools are provided with PCP to create the help text
files of appropriate format. See newhelp(1).
INSTALLATION AND REMOVAL
A series of shell procedures are defined in
$PCP_SHARE_DIR/lib/pmdaproc.sh which greatly simplify the
installation and removal of a PMDA. The Install scripts
for most PMDAs should only need to specify the name of the
PMDA in iam, call _setup which check licenses and whether
the PMDA has been previously installed, specify the commu
nication protocols, and finally call _install. The Remove
scripts are even simpler as the communication protocols
are not required. Further information is contained in the
$PCP_SHARE_DIR/lib/pmdaproc.sh file.
DIAGNOSTICS
Any PMDA which uses this library can set PMAPI(3) debug
control variable pmDebug (with -D on the command line) to
DBG_TRACE_LIBPMDA to enable the display of debugging
information which may be useful during development (see
pmdbg(1)).
The status field of the pmdaInterface structure should be
zero after pmdaDaemon, pmdaDSO, pmdaGetOpt, pmdaConnect
that initialization has failed.
Some error messages that are common to most functions in
this library are:
PMDA interface version interface not supported
Most of the functions require that the
comm.version field of the pmdaInterface
structure be set to PMDA_INTERFACE_2 or
later. This implies that the version.two
fields are correctly initialized (see
pmdaDaemon(3) and pmdaDSO(3)).
CAVEAT
Failing to complete any of the data structures or calling
any of the library routines out of order may cause unex
pected behavior in the PMDA.
Due to changes to the PMAPI(3) and PMDA(3) API in the PCP
2.0 release, as described in the product release notes,
PMDAs built using PCP 2.0 must specify PMDA_INTERFACE_2 or
later and link with libpcp_pmda.so.2 and libpcp.so.2.
Pre-existing Daemon PMDAs specifying PMDA_PROTOCOL_1 will
continue to function using the backwards compatible
libpcp_pmda.so.1 and libpcp.so.1 libraries and may be
recompiled using the headers installed in
/usr/include/pcp1.x/ without any modification. These
backwards compatible headers and libraries are contained
in the pcp.sw.compat subsystem.
FILES
/usr/include/pcp/pmda.h
Header file for the PMDA support library.
/usr/lib/libpcp_pmda.so
Dynamic library containing PMDA support library
routines.
$PCP_PMDAS_DIR/trivial
The source of the trivial PMDA.
$PCP_PMDAS_DIR/simple
The source of the simple PMDA.
$PCP_PMDAS_DIR/txmon
The source of the txmon PMDA.
$PCP_PMCDCONF_PATH
Configuration file for pmcd(1).
$PCP_VAR_DIR/pmns
Location of namespace descriptions for every
PMDA.
The unique domain identifiers for each PMDA.
$PCP_SHARE_DIR/lib/pmdaproc.sh
Shell procedures for installing and removing a
PMDA.
PCP ENVIRONMENT
Environment variables with the prefix PCP_ are used to
parameterize the file and directory names used by PCP. On
each installation, the file /etc/pcp.conf contains the
local values for these variables. The $PCP_CONF variable
may be used to specify an alternative configuration file,
as described in pcp.conf(4). Values for these variables
may be obtained programatically using the pmGetConfig(3)
function.
SEE ALSO
dbpmda(1), newhelp(1), pmcd(1), pmnsadd(1), pmnsdel(1),
PMAPI(3), pmdaConnect(3), pmdaDaemon(3), pmdaDesc(3),
pmdaDSO(3), pmdaFetch(3), pmdaGetOpt(3), pmdaInit(3),
pmdaInstance(3), pmdaMain(3), pmdaOpenLog(3), pmdaPro
file(3), pmdaStore(3), pmdaText(3), pmLookupDesc(3) and
pmns(4).
For a complete description of the pcp_pmda library and the
PMDA development process, refer to the Insight book Per
formance Co-Pilot Programmer's Guide.
Man(1) output converted with
man2html