PMEXTRACTVALUE(3)

πŸ“¦
version 7.2.2 Β· 4 versions
, in arch rolling, centos-stream 10, fedora 43, fedora 44, ubuntu resolute, ubuntu stonking

PMEXTRACTVALUE(3) πŸ’–

okay bestie, this one's a library functions manual page from the Performance Co-Pilot crew, and it's literally the glow-up station for your performance metric values. pull up a chair 🫢


✨ NAME ✨

pmExtractValue β€” the girl whose whole job is extracting a performance metric value out of a pmResult structure πŸ’…


✨ C SYNOPSIS ✨

#include <pcp/pmapi.h>

int pmExtractValue(int valfmt, const pmValue *ival, int itype,
                   pmAtomValue *oval, int otype);

cc ... -lpcp

✨ DESCRIPTION ✨

so. the pmValue structure is embedded inside the pmResult structure, which is the thing that hands you back one or more performance metrics. go read pmFetch(3) if you need the lore 🌸

every performance metric value can be encoded in a pmAtomValue union, and it's defined like this:

typedef union {
    __int32_t    l;     /* 32-bit signed */
    __uint32_t   ul;    /* 32-bit unsigned */
    __int64_t    ll;    /* 64-bit signed */
    __uint64_t   ull;   /* 64-bit unsigned */
    float        f;     /* 32-bit floating point */
    double       d;     /* 64-bit floating point */
    char         *cp;   /* char ptr */
    pmValueBlock *vbp;  /* pmValueBlock ptr */
} pmAtomValue;

pmExtractValue is the convenient little mechanism that pulls values out of the pmValue part of a pmResult structure, optionally converts the data type, and then hands the result over to you, the application programmer. it's giving personal shopper energy πŸ›οΈ

itype is the data type of the input value sitting in ival, according to the storage format defined by valfmt (again, see pmFetch(3)). otype is the data type of the result that's gonna land in oval.

the value for itype is typically plucked out of a pmDesc structure, right after a call to pmLookupDesc(3) for whatever performance metric you're into πŸ‘‘

otype should be one of the defined PM_TYPE_... values β€” they have a 1:1 correspondence with the fields in the pmAtomValue union. no cap.

normally you'd yank the valfmt parameter straight out of the same pmResult structure that's feeding you the ival parameter. and here's the important part, bestie β€” if valfmt says PM_VAL_INSITU, then these input types are NOT allowed, because they literally cannot be encoded in 32-bits:

  • __int64_t
  • __uint64_t
  • double
  • char *
  • void *

and the matching itype values are PM_TYPE_64, PM_TYPE_U64, PM_TYPE_DOUBLE, PM_TYPE_STRING, PM_TYPE_AGGREGATE and PM_TYPE_EVENT (or PM_TYPE_HIGHRES_EVENT). respectively πŸ’€

if valfmt says PM_VAL_SPTR or PM_VAL_DPTR instead, then the value gets extracted from the associated pmValueBlock structure, and the __int32_t, __uint32_t and float options are not allowed (itype being PM_TYPE_32, PM_TYPE_U32 and PM_TYPE_FLOAT respectively) β€” because PM_VAL_INSITU is the appropriate encoding for those ones. slay, consistency ✨

the following table defines all the possibilities for the type conversion β€” input type (itype) runs vertically, output type (otype) runs horizontally:

  • Y means the conversion is always acceptable
  • N means the conversion can never be performed (the function returns PM_ERR_CONV)
  • P means the conversion may lose accuracy (but no error status is returned)
  • T means the result may be subject to high-order truncation (in which case the function returns PM_ERR_TRUNC)
  • S means the conversion may be impossible due to the sign of the input value (in which case the function returns PM_ERR_SIGN)

if an error occurs, the value represented by oval will be zero (or NULL). so like, don't trust it πŸ™ˆ

      | 32  |  U32  | 64  |  U64  | FLOAT | DBLE | STRNG | BLOB
======|=====|=======|=====|=======|=======|======|=======|======
32    |  Y  |   S   |  Y  |   S   |   P   |  P   |   Y   |  N
U32   |  T  |   Y   |  Y  |   Y   |   P   |  P   |   Y   |  N
64    |  T  |  T,S  |  Y  |   S   |   P   |  P   |   Y   |  N
U64   |  T  |   T   |  T  |   Y   |   P   |  P   |   Y   |  N
FLOAT | P,T | P,T,S | P,T | P,T,S |   Y   |  Y   |   P   |  N
DBLE  | P,T | P,T,S | P,T | P,T,S |   P   |  Y   |   P   |  N
STRNG |  N  |   N   |  N  |   N   |   N   |  N   |   Y   |  N
BLOB  |  N  |   N   |  N  |   N   |   N   |  N   |   N   |  N
no conversion involving the types PM_TYPE_EVENT, PM_TYPE_HIGHRES_EVENT or PM_TYPE_AGGR is supported, and the label BLOB in the table above covers all three of those types. so BLOB is the group chat name for the whole trio 🫢

and when multiple conversion errors could happen? only the first encountered error gets notified, and the order of checking is not defined. chaos but make it documented πŸ’…

if the output conversion is to one of the pointer types β€” meaning otype is PM_TYPE_STRING or PM_TYPE_AGGREGATE β€” then the value buffer will have been allocated by pmExtractValue(3) using malloc(3), and it is the caller's responsibility to free the space when it's no longer required. not me forgetting to free... couldn't be me 😭

even though this function looks kinda complex (it is, a little), it was built to assist the development of performance tools that wanna convert values whose type is only known via the type field in a pmDesc structure into a canonical type for local processing. if that sounds like a lot of work, see the pmFetchGroup functions for a simpler alternative πŸ‘‘


✨ DIAGNOSTICS ✨

  • PM_ERR_CONV β€” impossible conversion, marked by N in the table above πŸ’€
  • PM_ERR_TRUNC β€” high-order truncation occurred βœ‚οΈ
  • PM_ERR_SIGN β€” conversion of a negative value to an unsigned type was attempted πŸ™ˆ

✨ SEE ALSO ✨

PMAPI(3), pmAtomStr(3), pmConvScale(3), pmFetch(3), pmFetchGroup(3), pmLookupDesc(3), pmPrintValue(3), pmTypeStr(3), pmUnitsStr(3) and pmUnpackEventRecords(3). go read them, they ate πŸ”₯


and that's the whole page bestie 🌈 this little number lives in the Performance Co-Pilot corner of the world, brought to you by PCP itself β€” signed off with love, PMEXTRACTVALUE(3), bye bestie πŸ’–πŸ¦‹βœ¨

πŸ“¦ where this page comes from