Man Linux: Main Page and Category List

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
       Programmers 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(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/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(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),      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
       Programmers Guide.