---
name: "pmdaMainLoop"
section: "3"
platform: "linux"
package: "libpcp-pmda3-dev"
version: "3.3.3-squeeze3"
release: "Debian 6.0 (Squeeze)"
platforms: ["linux"]
url: "https://new.carta.tech/pmdaMain"
---

# pmdaMainLoop(3)

generic PDU processing for a PMDA

Part of [pmdaMain(3)](/pmdaMain/3.md).

## NAME

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

## C SYNOPSIS

**#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));**

## DESCRIPTION

For Performance Metric Domain Agents  ([**PMDA**(3)](/PMDA/3.md)) using the binary PDU protocols to communicate with [**pmcd**(1)](/pmcd/1.md), 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)](/pmcd/1.md) 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` *version.one* `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)](/pmcd/1.md) `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)](/pmcd/1.md) `- 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)](/pmcd/1.md) `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)](/pmcd/1.md). `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.`

## SEE ALSO

[**pmcd**(1)](/pmcd/1.md), [**pmdbg**(1)](/pmdbg/1.md), [**PMAPI**(3)](/PMAPI/3.md) `and` [**PMDA**(3)](/PMDA/3.md).

## 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)](/PMAPI/3.md) `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.`
