PMDACACHE(3) | Library Functions Manual | PMDACACHE(3) |
pmdaCacheStore, pmdaCacheStoreKey, pmdaCacheLookup, pmdaCacheLookupName, pmdaCacheLookupKey, pmdaCacheOp, pmdaCachePurge, pmdaCacheResize - manage a cache of instance domain information for a PMDA
#include <pcp/pmapi.h>
#include <pcp/pmda.h>
int pmdaCacheStore(pmInDom indom, int flags,
const char *name, void *private);
int pmdaCacheStoreKey(pmInDom indom, int flags,
const char *name, int keylen, const
void *key, void *private);
int pmdaCacheLookup(pmInDom indom, int inst, char **name,
void **private);
int pmdaCacheLookupName(pmInDom indom, const char *name,
int *inst, void **private);
int pmdaCacheLookupKey(pmInDom indom, const char *name,
int keylen, const void *key, char
**oname, int *inst, void **private);
int pmdaCacheOp(pmInDom indom, int op);
int pmdaCachePurge(pmInDom indom, time_t recent);
int pmdaCacheResize(pmInDom indom, int maximum);
cc ... -lpcp_pmda -lpcp
The pmdaCache family of routines provide services to support the maintenance of complex instance domains for Performance Co-Pilot PMDAs. There is potentially one cache of information for each instance domain, and for each instance the cache maintains:
The semantics of a PCP instance domain require a number of rules to be followed, namely:
The visible interface to the cache is oriented towards the PMDA developer who is most concerned about the names of instances, while the details of how the rest of the PCP infrastructure expects the internal instance identifiers to be managed is not relevant.
Instances are updated in the cache for instance domain indom by calling pmdaCacheStore or pmdaCacheStoreKey with the external name of the instance passed via name. The opaque pointer private may be used to associate additional data with the entry in the cache; if no such data is required, private should be NULL. Any manipulation of the additional data (including allocation or freeing) is the responsibility of the PMDA caller, as the cache simply maintains the pointer to the data (passed via private).
The upper bound for identifiers allocated for any given indom cache can be optionally reduced from the default (2^31 - 1) to some lesser maximum, using pmdaCacheResize. This maximum will then be persisted and restored in the usual manner, and can thus be associated permanently with a cache once set. This has applications when using these interfaces as general purpose identifier caches, and is less applicable when using them for instance domain caching.
For cases where the PMDA developer wishes to influence the allocation of internal instance identifiers, e.g. for instance domains with more than one natural dimension, or where there is a desire to allocate the same instance identifier each time the PMDA is started, even on different hosts, pmdaCacheStoreKey may be used. In this case, an initial ``hint'' for the instance identifier is provided as an opaque key via the first keylen bytes in key (which could be any sort of data, including binary values) else if keylen is less than 1 or key is NULL then name is used as the ``hint''. The ``hint'' is hashed to produce an initial instance identifier in the range 0 to 2^31 - 1 (or lesser maximum, if set). If this instance identifier is already allocated, then the value is rehashed. This procedure is repeated until an unallocated instance identifier is found, or pmdaCacheStoreKey gives up and returns PM_ERR_GENERIC. For each instance domain, the ``hint'' must be unique across all instances, else pmdaCacheStoreKey returns PM_ERR_INST.
The flags argument controls how the instance should be processed in the cache as follows:
On success pmdaCacheStore or pmdaCacheStoreKey will return the internal instance identifier of the associated cache entry. Valid instance identifiers are guaranteed to be unique and non-negative. Failure will be indicated by a negative value (suitable for decoding with pmErrStr(3)) and most likely PM_ERR_INST to indicate the requested instance is not in the cache, or -EINVAL to indicate a potential violation of the short name uniqueness property (see the INSTANCE NAME MATCHING section below).
pmdaCacheLookup is used to search the entries in the cache based on the internal instance identifier inst.
On success the return value will be PMDA_CACHE_ACTIVE or PMDA_CACHE_INACTIVE (depending on the active or inactive state of the cache entry), name (if not NULL) and private (if not NULL) will be set to the external instance name and the associate additional data area as provided when the instance was last activated via pmdaCacheStore or pmdaCacheStoreKey.
pmdaCacheLookup failure is indicated by a negative return value suitable for decoding with pmErrStr(3).
The pmdaCacheLookup interface is required by the PMDA's
fetch callback that is registered via pmdaSetFetchCallBack(3). Here
the internal instance identifier is passed to the fetch callback to
identifier for which instance a value is required. Typical usage is shown in
the code fragment below.
static int foo_callback(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom) {
mydata *mdp;
char *name;
int sts;
sts = pmdaCacheLookup(mdesc->m_desc.indom, inst, &name, (void **)&mdp);
/*
* expect sts == PMDA_CACHE_ACTIVE except for cataclysmic events
* use mdp as required, name may be useful for diagnostics
*/
...
pmdaCacheLookupName is used to search the entries in the cache based on the external instance name name.
On success the return value will be PMDA_CACHE_ACTIVE or PMDA_CACHE_INACTIVE (depending on the active or inactive state of the cache entry), inst (if not NULL) and private (if not NULL) will be set to the internal instance identifier and the associate additional data area as provided when the instance was last activated via pmdaCacheStore or pmdaCacheStoreKey.
pmdaCacheLookupName failure is indicated by a negative return value suitable for decoding with pmErrStr(3).
The pmdaCacheLookupName interface is useful for PMDAs wishing to update an instance domain based on the external instance names.
pmdaCacheLookupKey is used to search the entries in the cache based on an opaque key (or ``hint'') previously used in a call to pmdaCacheStoreKey. The ``hint'' is provided via the first keylen bytes in key. For symmetry with pmdaCacheStoreKey, if keylen is less than 1 or key is NULL then name is used as the ``hint'' (although the results will be the same as calling pmdaCacheLookupName in this case).
On success the return value will be PMDA_CACHE_ACTIVE or PMDA_CACHE_INACTIVE (depending on the active or inactive state of the cache entry), oname (if not NULL), inst (if not NULL) and private (if not NULL) will be set to the external instance name, the internal instance identifier and the associate additional data area as provided when the instance was last activated via pmdaCacheStore or pmdaCacheStoreKey.
pmdaCacheLookupKey failure is indicated by a negative return value suitable for decoding with pmErrStr(3).
To avoid a persistent cache growing without bound, pmdaCachePurge can be used to cull all entries that have not been active in the last recent seconds. For performance reasons, the time accounting is imprecise and the entries are timestamped at the time of the next cache save operation after the entry has been added or marked active (refer to PMDA_CACHE_SAVE and PMDA_CACHE_SYNC below). On success pmdaCachePurge returns the number of culled entries, else in the case of an error the return value is negative (and suitable for decoding with pmErrStr(3)).
pmdaCacheOp may be used to perform additional operations on the cache as follows:
Returns the number of instances saved to the external file, else 0 if the external file was already up to date.
Returns the number of instances saved to the external file, else 0 if the external file was already synchronized.
Only one cache walk can be active at any given time, nesting calls to PMDA_CACHE_WALK and PMDA_CACHE_REWIND will interfere with each other.
pmdaCacheOp returns a non-negative value on success, and failure is indicated by a negative return value (suitable for decoding with pmErrStr(3)).
When the pmdaCache routines are used for particular instance domain, pmdaInstance(3) and the instance domain enumeration behind pmdaFetch(3) will attempt to extract instance domain information from the cache, thereby avoiding reference to the pmdaIndom data structures that have historically been used to define instance domains and service instance requests. A PMDA can adopt a hybrid approach and choose to implement some instance domains via the traditional pmdaIndom method, and others via the pmdaCache approach, however attempts to manage the same instance domain by both methods will result in the pmdaCache method silently prevailing.
If all instances in a PMDA are to be serviced from a
pmdaCache then a pmdaIndom is not required, and the
pmdaInit(3) call becomes
pmdaInit(dp, NULL, 0, metrictab, nmetrics);
However, the PMDA will need to explicitly initialize the indom field of
the pmDesc in the metrictab entries, as this cannot be done by
pmdaInit(3) if indomtab is missing entries for the instance
domains maintained in the cache.
Independent of how the instance domain is being maintained, to refresh an instance domain prior to a fetch or an instance domain operation, the standard methods of a ``wrapper'' to the pmdaInstance(3) and pmdaFetch(3) methods should be used.
Refer to the simple PMDA source code for an example use of the pmdaCache routines.
When using pmdaCacheStoreKey, if there is a desire to ensure the given ``hint'' generates the same initial instance identifier across all platforms, then the caller should ensure the endian and word-size issues are considered, e.g. if the natural data structure used for the key is an array of 32-bit integers, then htonl(3) should be used on each element of the array before calling pmdaCacheStoreKey or pmdaCacheLookupKey.
The following table summarizes the ``short name'' matching semantics for an instance domain (caches other than PMDA_CACHE_STRINGS style).
name in | pmdaCacheLookup | result |
cache | name | |
foodle | foo | no match (PM_ERR_INST) |
foo | foodle | no match (PM_ERR_INST) |
foo | foo | match |
foo bar | foo | match on short name (instance identifier) |
foo bar | foo bar | match on full name (instance identifier) |
foo | foo bar | bad match (-EDOM) |
foo bar | foo blah | bad match (-EDOM) |
Cache persistence uses files with names constructed from the indom within the $PCP_VAR_DIR/config/pmda directory.
BYTEORDER(3), PMAPI(3), PMDA(3), pmdaInit(3), pmdaInstance(3), pmdaFetch(3), pmdaLabel(3), pmErrStr(3) and pmGetInDom(3).
PCP | Performance Co-Pilot |