Provided by: libpcp-pmda3-dev_3.5.11_amd64 bug


       PMDA - introduction to the Performance Metrics Domain Agent support library


       #include <pcp/pmapi.h>
       #include <pcp/impl.h>
       #include <pcp/pmda.h>

       cc ... -lpcp_pmda -lpcp


       To  assist  in  the  development  of  Performance  Metric  Domain  Agents  (PMDAs) for the
       Performance  Co-Pilot  (PCP),  a  procedural  interface  is  provided  that  extends   the
       Performance   Metrics  Application  Programming  Interface  (  PMAPI(3))  library.   These
       procedures are designed to enable a programmer 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


       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) process 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)  process  on  the  local  host.   The
       requests  from the clients are received by pmcd(1) and forwarded to the appropriate PMDAs.
       Responses, when required, are returned through  pmcd(1)  to  the  clients.   The  requests
       (PDUs)   that   may   be   sent  to  a  PMDA  from  pmcd(1)  are  PDU_FETCH,  PDU_PROFILE,


       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).


       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 */
                int         it_numinst;     /* number of instances */
                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 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.


       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  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
                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

       The simple.time and metrics are defined  in  separate  clusters  to  the  other
       metrics which allows a PMDA to support more than 1024 metrics, as well as grouping similar
       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

             * 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.


       Each  metric  requires  a  description  (pmDesc),  which  contains  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;

       The simple PMDA defines the metrics as:

            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,
                      { 0, 1, 0, 0, PM_TIME_SEC, 0 } }, },
            /* time.sys */
                { (void*)0,
                      { 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.


       A  PMDA  that  is  run  as  a DSO is opened by pmcd(1) with dlopen(3).  pmcd will call the
       PMDA's initialization function that is specified in $PCP_PMCDCONF_PATH.  This function  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 callback to be  set  with  pmdaSetFetchCallBack(3)  as  can  be  seen  in

       The  flag _isDSO is used to determine if the PMDA is a daemon or a DSO so that the correct
       initialization routine, pmdaDaemon(3) or pmdaDSO(3), is called.


       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.   Command
       line  parsing can be simplified by using pmdaGetOpt(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

       The simple_init() routine is common to an agent that can be run as both a Daemon  and  DSO


       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


       A series of shell procedures are defined in $PCP_SHARE_DIR/lib/  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 communication 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/ file.


       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  and  pmdaInit are called.  A value less than zero indicates 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.
                      PMDA_INTERFACE_2 or PMDA_INTERFACE_3 implies that  the  version.two  fields
                      are   correctly   initialized,  while  PMDA_INTERFACE_4  implies  that  the
                      version.four  fields  are  correctly  initialized  (see  pmdaDaemon(3)  and


       Failing  to complete any of the data structures or calling any of the library routines out
       of order may cause unexpected 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 and   Pre-existing  Daemon  PMDAs  specifying
       PMDA_PROTOCOL_1  will continue to function using the backwards compatible
       and  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.


                 Header file for the PMDA support library.

                 Dynamic library containing PMDA support library routines.

                 The source of the trivial PMDA.

                 The source of the simple PMDA.

                 The source of the txmon PMDA.

                 Configuration file for pmcd(1).

                 Location of namespace descriptions for every PMDA.

                 The unique domain identifiers for each PMDA.

                 Shell procedures for installing and removing a PMDA.


       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.


       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), pmdaProfile(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 Performance Co-Pilot Programmer's Guide.