Provided by: libpcp-pmda3-dev_3.8.12ubuntu1_amd64 bug

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 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 $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)  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, 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 */
                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  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(5).  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/stdpmid.

       The simple.time and simple.now 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 $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 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,
                  { 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 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 $PCP_PMDAS_DIR/simple/simple.c.

       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.

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.  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
       $PCP_PMDAS_DIR/simple/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 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/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 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 pmdaDSO(3)).

CAVEAT

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

       $PCP_VAR_DIR/pmns/stdpmid
                 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(5).
       Values for these variables may be obtained programmatically 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), pmdaProfile(3), pmdaStore(3), pmdaText(3), pmLookupDesc(3) and pmns(5).

       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.

Performance Co-Pilot                                   PCP                                               PMDA(3)