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


       pmdaMain,  pmdaMainLoop, pmdaSetResultCallBack, pmdaSetCheckCallBack, pmdaSetDoneCallBack,
       pmdaMainLoopFreeResultCallback - generic PDU processing for a PMDA


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

       cc ... -lpcp_pmda -lpcp

       PMDA Interface 2 or higher

       void pmdaMain(pmdaInterface *dispatch);
       void pmdaSetResultCallBack(pmdaInterface *dispatch, pmdaResultCallBack callback);
       void pmdaSetCheckCallBack(pmdaInterface *dispatch, pmdaCheckCallBack callback);
       void pmdaSetDoneCallBack(pmdaInterface *dispatch, pmdaDoneCallBack callback);

       PMDA Interface 1

       void pmdaMainLoop(char *name, int infd, int outfd, _pmPMDA *dispatch, int (*check)(void),
               void (*done)(void));
       void pmdaMainLoopFreeResultCallback(void (*callback)(pmResult *res));


       For  Performance  Metric  Domain  Agents  (PMDA(3))  using  the  binary  PDU  protocols to
       communicate with pmcd(1), the routine pmdaMain provides a generic  implementation  of  the
       PDU-driven main loop.

       pmdaMainLoop  and  pmdaMainLoopFreeResultCallback  implemented  an earlier version of this
       functionality.  Both functions will be removed in a later release and should not be used.

       The arguments that are now encapsulated  in  pmdaExt  that  were  passed  to  pmdaMainLoop
       include  the  name of the PMDA (used only in error messages) and the file descriptors infd
       and outfd used to receive and send PDUs to the pmcd(1) process.

       dispatch describes how to process each incoming PDU. It is a vector of function  pointers,
       one per request PDU type, as used in the DSO interface for a PMDA, namely:

        * Interface Definitions for PMDA Methods
       typedef struct {
           int domain;         /* set/return performance metrics domain id here */
           struct {
               unsigned int    pmda_interface: 8; /* PMDA DSO interface version */
               unsigned int    pmapi_version : 8; /* PMAPI version */
               unsigned int    flags : 16;        /* usage TBD */
           } comm;             /* set/return communication and version info */
           int status;         /* return initialization status here */

           union {
               struct {                              /* PMDA_INTERFACE_1 */
                   int (*profile)(__pmProfile *);
                   int (*fetch)(int, pmID *, pmResult **);
                   int (*desc)(pmID, pmDesc *);
                   int (*instance)(pmInDom, int, char *, __pmInResult **);
                   int (*text)(int, int, char **);
                   int (*control)(pmResult *, int, int, int);
                   int (*store)(pmResult *);
               } one;

               struct {                              /* PMDA_INTERFACE_2 or _3 */
                   pmdaExt *e_ext;
                   int (*profile)(__pmProfile *, pmdaExt *);
                   int (*fetch)(int, pmID *, pmResult **, pmdaExt *);
                   int (*desc)(pmID, pmDesc *, pmdaExt *);
                   int (*instance)(pmInDom, int, char *, __pmInResult **, pmdaExt *);
                   int (*text)(int, int, char **, pmdaExt *);
                   int (*store)(pmResult *, pmdaExt *);
               } two;

               struct {                              /* PMDA_INTERFACE_4 */
                   pmdaExt *ext;
                   int     (*profile)(__pmProfile *, pmdaExt *);
                   int     (*fetch)(int, pmID *, pmResult **, pmdaExt *);
                   int     (*desc)(pmID, pmDesc *, pmdaExt *);
                   int     (*instance)(pmInDom, int, char *, __pmInResult **, pmdaExt *);
                   int     (*text)(int, int, char **, pmdaExt *);
                   int     (*store)(pmResult *, pmdaExt *);
                   int     (*pmid)(char *, pmID *, pmdaExt *);
                   int     (*name)(pmID, char ***, pmdaExt *);
                   int     (*children)(char *, int, char ***, int **, pmdaExt *);
               } four;
           } version;

       } pmdaInterface;

       This  structure has been extended to incorporate the multiple interface versions that have
       evolved over time.  For pmdaMain, dispatch->domain and dispatch->status are ignored.   The
       comm.pmda_interface  field  is  used to determine the interface used by the PMDA.  Setting
       this field to PMDA_INTERFACE_1 will force pmdaMain to use the callbacks in the
       structure.   A  setting of PMDA_INTERFACE_2 or PMDA_INTERFACE_3 will force pmdaMain to use
       the callbacks in the version.two structure.  A  setting  of  PMDA_INTERFACE_4  will  force
       pmdaMain  to use the callbacks in the version.four structure.  Any other value will result
       in an error and termination of pmdaMain.

       Note that the use of dispatch as the interface between the pmcd(1) and the methods of  the
       PMDA allows each PMDA to be implemented as though it were a DSO, with pmdaMain providing a
       convenient wrapper that may be used to convert from the DSO interface to  the  binary  PDU
       (daemon PMDA) interface.

       pmdaMainLoop  provided  two  additional  callbacks, check and done.  If not null, check is
       called after each PDU is received (but before it was processed), and done is called  after
       each  PDU  is sent.  If check returns a value less than zero (typically PM_ERR_AGAIN), the
       PDU processing is skipped and in most cases the function value is returned as an error PDU
       to  pmcd(1)  - this may be used for PMDAs that require some sort of deferred connection or
       reconnect protocols for the underlying sources of performance metrics, e.g. a  DBMS.   The
       error  indication  from  check  is  not  passed  back  to  pmcd(1)  in  the cases where no
       acknowledgment is expected, e.g. for a PDU_PROFILE.

       The callback done would typically be used to monitor termination conditions,  or  do  PMDA
       housekeeping required after PDU processing.

       These  callbacks  should now be set with pmdaSetCheckCallBack and pmdaSetDoneCallBack when
       using pmdaMain.

       One further callback  mechanism  is  provided  for  handling  the  pmResult  built  for  a
       PDU_RESULT  in  response  to  a  PDU_FETCH  request.   By  default, pmdaMain will free the
       pmResult once the  result  has  been  sent  to  the  pmcd(1).   For  some  PMDAs  this  is
       inappropriate,  e.g.  the pmResult is statically allocated, or contains a hybrid of pinned
       PDU buffer information and dynamically allocated information.   pmdaSetResultCallback  may
       be    used   to   define   an   alternative   callback   from   pmdaMain.    The   routine
       pmdaMainLoopFreeResultCallback has been replaced by pmdaSetResultCallBack.

       pmdaMain executes as a continuous loop, returning only when an end of file is  encountered
       on the PDU input file descriptor.


       pmcd(1), pmdbg(1), PMAPI(3) and PMDA(3).


       These messages may be appended to the PMDA's log file:

       PMDA interface version interface not supported
                                The interface version is not supported by pmdaMain.

       Unrecognized pdu type    The  PMDA  received  a  PDU from pmcd that it does not recognize.
                                This may indicate that the pmcd process is using a more  advanced
                                interface than pmdaMain.

       If  the  PMAPI(3) debug control variable (pmdebug) has the DBG_TRACE_LIBPMDA flag set then
       each PDU that is received is reported in the PMDA's log file.