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