---
name: "pmdaSetEndContextCallBack"
section: "3"
platform: "linux"
package: "pcp"
version: "7.2.2-2"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/pmdaMain"
---

# pmdaSetEndContextCallBack(3)

generic PDU processing for a PMDA

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

## NAME

**pmdaMain**, **pmdaGetContext**, **pmdaSetResultCallBack**, **pmdaSetCheckCallBack**, **pmdaSetDoneCallBack**, **pmdaSetEndContextCallBack** - generic PDU processing for a PMDA

## C SYNOPSIS

**#include \<pcp/pmapi.h\>**\
 **#include \<pcp/pmda.h\>**

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

**cc ... -lpcp\_pmda -lpcp**

## 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.

*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)](/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.`

**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)](/pmdaProfile/3.md), [**pmdaFetch**(3)](/pmdaFetch/3.md), [**pmdaDesc**(3)](/pmdaDesc/3.md), [**pmdaInstance**(3)](/pmdaInstance/3.md), [**pmdaText**(3)](/pmdaText/3.md), [**pmdaStore**(3)](/pmdaStore/3.md), [**pmdaPMID**(3)](/pmdaPMID/3.md), [**pmdaName**(3)](/pmdaName/3.md), [**pmdaChildren**(3)](/pmdaChildren/3.md), `and` [**pmdaAttribute**(3)](/pmdaAttribute/3.md) `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)](/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` *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 propagated 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)](/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**.

## 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) `debugging control options` ```have the ``libpmda'' option set then each PDU that is received is reported``` `in the PMDA's log file.`

## SEE ALSO

[**pmcd**(1)](/pmcd/1.md), [**PMAPI**(3)](/PMAPI/3.md), [**PMDA**(3)](/PMDA/3.md), [**pmdaProfile**(3)](/pmdaProfile/3.md), [**pmdaFetch**(3)](/pmdaFetch/3.md), [**pmdaDesc**(3)](/pmdaDesc/3.md), [**pmdaInstance**(3)](/pmdaInstance/3.md), [**pmdaText**(3)](/pmdaText/3.md), [**pmdaStore**(3)](/pmdaStore/3.md), [**pmdaPMID**(3)](/pmdaPMID/3.md), [**pmdaName**(3)](/pmdaName/3.md), [**pmdaChildren**(3)](/pmdaChildren/3.md), `and` [**pmdaAttribute**(3)](/pmdaAttribute/3.md).
