NAME¶
pmdaMain,
pmdaGetContext,
pmdaSetResultCallBack,
pmdaSetCheckCallBack,
pmdaSetDoneCallBack,
pmdaSetEndContextCallBack - generic PDU processing for a PMDA
C SYNOPSIS¶
#include <pcp/pmapi.h>
#include <pcp/impl.h>
#include <pcp/pmda.h>
cc ... -lpcp_pmda -lpcp
void pmdaMain(pmdaInterface *
dispatch);
void pmdaSetCheckCallBack(pmdaInterface *
dispatch,
pmdaCheckCallBack
callback);
void pmdaSetDoneCallBack(pmdaInterface *
dispatch,
pmdaDoneCallBack
callback);
void pmdaSetResultCallBack(pmdaInterface *
dispatch,
pmdaResultCallBack
callback);
void pmdaSetEndContextCallBack(pmdaInterface *
dispatch,
pmdaEndContextCallBack
callback);
int pmdaGetContext(void);
DESCRIPTION¶
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.
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; /* optional feature flags */
} comm; /* set/return communication and version info */
int status; /* return initialization status here */
union {
struct { /* PMDA_INTERFACE_2 or _3 */
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 *);
} two, three;
struct { /* PMDA_INTERFACE_4 or _5 */
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, five;
struct { /* PMDA_INTERFACE_6 */
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 *);
int (*attribute)(int, int, const char *, int, pmdaExt *);
} six;
} 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_2 or
PMDA_INTERFACE_3 will force
pmdaMain to use the callbacks in the
version.two or
version.three structure. A setting of
PMDA_INTERFACE_4 or
PMDA_INTERFACE_5 will force
pmdaMain to use the callbacks in the
version.four or
version.five structure, and similarly a
PMDA_INTERFACE_6 setting forces
pmdaMain to use the callbacks in
the
version.six 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.
pmdaMain executes as a continuous loop, returning only when an end of
file is encountered on the PDU input file descriptor.
CALLBACKS¶
In addition to the individual PDU processing callbacks -
pmdaProfile(3),
pmdaFetch(3),
pmdaDesc(3),
pmdaInstance(3),
pmdaText(3),
pmdaStore(3),
pmdaPMID(3),
pmdaName(3),
pmdaChildren(3), and
pmdaAttribute(3) there
are other callbacks that can affect or inform all PDU processing within a
PMDA, namely
check,
done and
end. These callbacks should
be set with
pmdaSetCheckCallBack,
pmdaSetDoneCallBack and
pmdaSetEndContextCallBack.
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
end callback allows a PMDA to keep track of state for individual
clients that are requesting it to perform actions (PDU processing). Using
pmdaGetContext a PMDA can determine, at any point, an integer
identifier that uniquely identifies the client tools at the remote end of PMCD
(for local context modes, this identifier is always zero). This becomes very
important for handling event metrics, where each event must be propogated once
only to each interested client. It also underlies the mechanism whereby
connection information is passed to the PMDA, such as the the credentials
(user and group identifiers) for the client tool.
One final 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.
DIAGNOSTICS¶
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.
SEE ALSO¶
pmcd(1),
PMAPI(3),
PMDA(3),
pmdaProfile(3),
pmdaFetch(3),
pmdaDesc(3),
pmdaInstance(3),
pmdaText(3),
pmdaStore(3),
pmdaPMID(3),
pmdaName(3),
pmdaChildren(3), and
pmdaAttribute(3).