diff options
Diffstat (limited to 'qa/src/unpack.c')
-rw-r--r-- | qa/src/unpack.c | 479 |
1 files changed, 479 insertions, 0 deletions
diff --git a/qa/src/unpack.c b/qa/src/unpack.c new file mode 100644 index 0000000..71bacdc --- /dev/null +++ b/qa/src/unpack.c @@ -0,0 +1,479 @@ +#include <pcp/pmapi.h> +#include <pcp/impl.h> +#include <pcp/pmda.h> + +/* === begin largely copied from samplepmda events.c === */ + +static int mydomain = 29; + +static pmValueSet vs; +static char *ebuf; +static int ebuflen; +static char *eptr; +static char *ebufend; +static pmEventArray *eap; +static pmEventRecord *erp; + +static int +check_buf(int need) +{ + int offset = eptr - ebuf; + + while (&eptr[need] >= ebufend) { + ebuflen *= 2; + if ((ebuf = (char *)realloc(ebuf, ebuflen)) == NULL) + return -errno; + eptr = &ebuf[offset]; + ebufend = &ebuf[ebuflen-1]; + vs.vlist[0].value.pval = (pmValueBlock *)ebuf; + } + return 0; +} + +static int +add_param(pmID pmid, int type, pmAtomValue *avp) +{ + int need; /* bytes in the buffer */ + int vlen; /* value only length */ + int sts; + pmEventParameter *epp; + void *src; + + need = sizeof(pmEventParameter); + switch (type) { + case PM_TYPE_32: + case PM_TYPE_U32: + vlen = sizeof(avp->l); + need += vlen; + src = &avp->l; + break; + case PM_TYPE_64: + case PM_TYPE_U64: + vlen = sizeof(avp->ll); + need += vlen; + src = &avp->ll; + break; + case PM_TYPE_FLOAT: + vlen = sizeof(avp->f); + need += vlen; + src = &avp->f; + break; + case PM_TYPE_DOUBLE: + vlen = sizeof(avp->d); + need += vlen; + src = &avp->d; + break; + case PM_TYPE_STRING: + vlen = strlen(avp->cp); + need += PM_PDU_SIZE_BYTES(vlen); + src = avp->cp; + break; + case PM_TYPE_AGGREGATE: + case PM_TYPE_AGGREGATE_STATIC: + vlen = avp->vbp->vlen - PM_VAL_HDR_SIZE; + need += PM_PDU_SIZE_BYTES(vlen); + src = avp->vbp->vbuf; + break; + default: + fprintf(stderr, "add_parameter failed: bad type (%d)\n", type); + exit(1); + } + if ((sts = check_buf(need)) < 0) { + fprintf(stderr, "add_parameter failed: %s\n", pmErrStr(sts)); + exit(1); + } + epp = (pmEventParameter *)eptr; + epp->ep_pmid = pmid; + epp->ep_len = PM_VAL_HDR_SIZE + vlen; + epp->ep_type = type; + memcpy((void *)(eptr + sizeof(pmEventParameter)), src, vlen); + eptr += need; + erp->er_nparams++; + return 0; +} + +static void +reset(void) +{ + eptr = ebuf; + eap = (pmEventArray *)eptr; + eap->ea_nrecords = 0; + eptr += sizeof(pmEventArray) - sizeof(pmEventRecord); + vs.numval = 1; + vs.valfmt = PM_VAL_DPTR; + vs.vlist[0].inst = PM_IN_NULL; +} + +static int +add_record(struct timeval *tp, int flags) +{ + int sts; + + if ((sts = check_buf(sizeof(pmEventRecord) - sizeof(pmEventParameter))) < 0) { + fprintf(stderr, "add_record failed: %s\n", pmErrStr(sts)); + exit(1); + } + eap->ea_nrecords++; + erp = (pmEventRecord *)eptr; + erp->er_timestamp.tv_sec = (__int32_t)tp->tv_sec; + erp->er_timestamp.tv_usec = (__int32_t)tp->tv_usec; + erp->er_nparams = 0; + erp->er_flags = flags; + eptr += sizeof(pmEventRecord) - sizeof(pmEventParameter); + return 0; +} +/* === end copied from samplepmda events.c === */ + +static void +dump(char *xpect) +{ + pmResult **res; + int nmissed; + int nrecords; + int r; + int k; + static pmID pmid_flags = 0; + static pmID pmid_missed; + + fprintf(stderr, "Expecting ... %s\n", xpect); + + for (k = 0; k < vs.numval || vs.numval == PM_ERR_GENERIC; k++) { + if (vs.vlist[k].inst != PM_IN_NULL) + fprintf(stderr, "[instance %d]\n", vs.vlist[k].inst); + nrecords = pmUnpackEventRecords(&vs, k, &res); + + if (nrecords < 0) { + fprintf(stderr, "pmUnpackEventRecords: %s\n", pmErrStr(nrecords)); + return; + } + + /* lifted from pminfo.c */ + if (pmid_flags == 0) { + /* + * get PMID for event.flags and event.missed + * note that pmUnpackEventRecords() will have called + * __pmRegisterAnon(), so the anon metrics + * should now be in the PMNS + */ + char *name_flags = "event.flags"; + char *name_missed = "event.missed"; + int sts; + sts = pmLookupName(1, &name_flags, &pmid_flags); + if (sts < 0) { + /* should not happen! */ + fprintf(stderr, "Warning: cannot get PMID for %s: %s\n", name_flags, pmErrStr(sts)); + /* avoid subsequent warnings ... */ + __pmid_int(&pmid_flags)->item = 1; + } + sts = pmLookupName(1, &name_missed, &pmid_missed); + if (sts < 0) { + /* should not happen! */ + fprintf(stderr, "Warning: cannot get PMID for %s: %s\n", name_missed, pmErrStr(sts)); + /* avoid subsequent warnings ... */ + __pmid_int(&pmid_missed)->item = 1; + } + } + + nmissed = 0; + for (r = 0; r < nrecords; r++) { + if (res[r]->numpmid == 2 && res[r]->vset[0]->pmid == pmid_flags && + (res[r]->vset[0]->vlist[0].value.lval & PM_EVENT_FLAG_MISSED) && + res[r]->vset[1]->pmid == pmid_missed) { + nmissed += res[r]->vset[1]->vlist[0].value.lval; + } + } + + fprintf(stderr, "Array contains %d records and %d missed records\n", nrecords, nmissed); + if (nrecords == 0) + continue; + + for (r = 0; r < nrecords; r++) { + fprintf(stderr, "pmResult[%d]\n", r); + __pmDumpResult(stderr, res[r]); + } + pmFreeEventResult(res); + } +} + +int +main(int argc, char **argv) +{ + int errflag = 0; + int sts; + int c; + struct timeval stamp; + pmAtomValue atom; + int savelen; + pmEventParameter *epp; +/* === begin largely copied from samplepmda events.c === */ + static pmValueBlock *aggr; + static char aggrval[] = { '\01', '\03', '\07', '\017', '\037', '\077', '\177', '\377' }; + pmID pmid_array = PMDA_PMID(4095,0); /* event.records */ + pmID pmid_type = PMDA_PMID(0,127); /* event.type */ + pmID pmid_32 = PMDA_PMID(0,128); /* event.param_32 */ + pmID pmid_u32 = PMDA_PMID(0,129); /* event.param_u32 */ + pmID pmid_64 = PMDA_PMID(0,130); /* event.param_64 */ + pmID pmid_u64 = PMDA_PMID(0,131); /* event.param_u64 */ + pmID pmid_float = PMDA_PMID(0,132); /* event.param_float */ + pmID pmid_double = PMDA_PMID(0,133); /* event.param_double */ + pmID pmid_string = PMDA_PMID(0,134); /* event.param_string */ + pmID pmid_aggregate = PMDA_PMID(0,135); /* event.param_string */ + + /* first time, punt on a 512 byte buffer */ + ebuflen = 512; + ebuf = eptr = (char *)malloc(ebuflen); + if (ebuf == NULL) { + fprintf(stderr, "initial ebuf malloc failed: %s\n", strerror(errno)); + exit(1); + } + ebufend = &ebuf[ebuflen-1]; + /* + * also, fix the domain field in the event parameter PMIDs ... + * note these PMIDs must match the corresponding metrics in + * desctab[] and this cannot easily be done automatically + */ + ((__pmID_int *)&pmid_array)->domain = mydomain; + ((__pmID_int *)&pmid_type)->domain = mydomain; + ((__pmID_int *)&pmid_32)->domain = mydomain; + ((__pmID_int *)&pmid_u32)->domain = mydomain; + ((__pmID_int *)&pmid_64)->domain = mydomain; + ((__pmID_int *)&pmid_u64)->domain = mydomain; + ((__pmID_int *)&pmid_float)->domain = mydomain; + ((__pmID_int *)&pmid_double)->domain = mydomain; + ((__pmID_int *)&pmid_string)->domain = mydomain; + ((__pmID_int *)&pmid_aggregate)->domain = mydomain; + /* build pmValueBlock for aggregate value */ + aggr = (pmValueBlock *)malloc(PM_VAL_HDR_SIZE + sizeof(aggrval)); + aggr->vtype = PM_TYPE_AGGREGATE; + aggr->vlen = PM_VAL_HDR_SIZE + sizeof(aggrval); + memcpy(aggr->vbuf, (void *)aggrval, sizeof(aggrval)); + +/* === end copied from samplepmda events.c === */ + + vs.pmid = pmid_array; + vs.numval = 1; + vs.valfmt = PM_VAL_DPTR; + vs.vlist[0].inst = PM_IN_NULL; + vs.vlist[0].value.pval = (pmValueBlock *)ebuf; + + __pmSetProgname(argv[0]); + + + while ((c = getopt(argc, argv, "D:")) != EOF) { + switch (c) { + + case 'D': /* debug flag */ + sts = __pmParseDebug(optarg); + if (sts < 0) { + fprintf(stderr, "%s: unrecognized debug flag specification (%s)\n", + pmProgname, optarg); + errflag++; + } + else + pmDebug |= sts; + break; + + case '?': + default: + errflag++; + break; + } + } + + if (errflag) { + fprintf(stderr, "Usage: %s ...\n", pmProgname); + fprintf(stderr, "options:\n"); + fprintf(stderr, "-D debug\n"); + exit(1); + } + + reset(); + gettimeofday(&stamp, NULL); + /* rebase event records 10 secs in past, add 1 sec for each new record */ + stamp.tv_sec -= 10; + + eap->ea_type = 0; + eap->ea_len = 0; + dump("Unknown or illegal metric type"); + eap->ea_type = PM_TYPE_EVENT; + + eap->ea_nrecords = -1; + eap->ea_len = eptr - ebuf; + dump("Error - ea_nrecords < 0"); + eap->ea_nrecords = 0; + + eap->ea_len = PM_VAL_HDR_SIZE; + dump("Error - vlen way too small"); + + eap->ea_len = eptr - ebuf; + dump("No records"); + + add_record(&stamp, 0); + stamp.tv_sec++; + eap->ea_len = eptr - ebuf; + dump("1 record, no params"); + + reset(); + add_record(&stamp, 0); + stamp.tv_sec++; + atom.ul = 1; + add_param(pmid_type, PM_TYPE_U32, &atom); + eap->ea_len = eptr - ebuf; + dump("1 record, u32 param = 1"); + + reset(); + add_record(&stamp, 1); + stamp.tv_sec++; + atom.ul = 2; + add_param(pmid_type, PM_TYPE_U32, &atom); + atom.ll = -3; + add_param(pmid_64, PM_TYPE_64, &atom); + eap->ea_len = eptr - ebuf; + dump("1 record, u32 param = 2, u64 param = -3"); + eap->ea_len--; + dump("Error - buffer overrun @ parameter"); + + reset(); + add_record(&stamp, PM_EVENT_FLAG_MISSED); + stamp.tv_sec++; + erp->er_nparams = 3; + add_record(&stamp, 0); + stamp.tv_sec++; + atom.ul = 4; + add_param(pmid_type, PM_TYPE_U32, &atom); + atom.ull = 5; + add_param(pmid_u64, PM_TYPE_U64, &atom); + atom.cp = "6"; + add_param(pmid_string, PM_TYPE_STRING, &atom); + add_record(&stamp, 0); + stamp.tv_sec++; + atom.ul = 7; + add_param(pmid_type, PM_TYPE_U32, &atom); + atom.d = 8; + add_param(pmid_double, PM_TYPE_DOUBLE, &atom); + atom.d = -9; + add_param(pmid_double, PM_TYPE_DOUBLE, &atom); + add_record(&stamp, 2); + stamp.tv_sec++; + atom.ul = 10; + add_param(pmid_type, PM_TYPE_U32, &atom); + atom.ull = 11; + add_param(pmid_u64, PM_TYPE_U64, &atom); + atom.cp = "twelve"; + add_param(pmid_string, PM_TYPE_STRING, &atom); + atom.cp = "thirteen"; + add_param(pmid_string, PM_TYPE_STRING, &atom); + atom.l = 14; + add_param(pmid_32, PM_TYPE_32, &atom); + atom.ul = 15; + add_param(pmid_u32, PM_TYPE_U32, &atom); + add_record(&stamp, PM_EVENT_FLAG_MISSED); + stamp.tv_sec++; + erp->er_nparams = 4; + savelen = eptr - ebuf; + add_record(&stamp,0); + stamp.tv_sec++; + atom.ul = 16; + add_param(pmid_type, PM_TYPE_U32, &atom); + atom.f = -17; + add_param(pmid_float, PM_TYPE_FLOAT, &atom); + atom.vbp = aggr; + add_param(pmid_aggregate, PM_TYPE_AGGREGATE, &atom); + eap->ea_len = eptr - ebuf; + dump("6 records, 7 missed [u32=4 u64=5 str=\"6\"][u32=7 d=8 d=-9][u32=10 u64=11 str=\"twelve\" str=\"thirteen\" 32=-14 u32=15][u32=16 f=-17 aggr=...]"); + + eap->ea_len = savelen; + dump("Error - buffer overrun @ record"); + + reset(); + add_record(&stamp, 0); + stamp.tv_sec++; + atom.ul = 1; + add_param(pmid_type, PM_TYPE_U32, &atom); + eap->ea_len = eptr - ebuf; + vs.numval = PM_ERR_GENERIC; + dump("bad numval"); + + reset(); + add_record(&stamp, 0); + stamp.tv_sec++; + atom.ul = 1; + add_param(pmid_type, PM_TYPE_U32, &atom); + eap->ea_len = eptr - ebuf; + vs.valfmt = 42; + dump("bad valfmt"); + + reset(); + add_record(&stamp, 0); + stamp.tv_sec++; + atom.ul = 1; + add_param(pmid_type, PM_TYPE_U32, &atom); + eap->ea_len = eptr - ebuf; + vs.vlist[0].inst = 42; + dump("odd instance"); + + reset(); + add_record(&stamp, 0); + stamp.tv_sec++; + atom.vbp = aggr; + epp = (pmEventParameter *)eptr; + add_param(pmid_aggregate, PM_TYPE_AGGREGATE, &atom); + epp->ep_type = PM_TYPE_EVENT; + eap->ea_len = eptr - ebuf; + dump("1 record, nested event type @ 1st parameter"); + + reset(); + add_record(&stamp, 0); + stamp.tv_sec++; + atom.ul = 18; + add_param(pmid_type, PM_TYPE_U32, &atom); + add_record(&stamp, 0); + stamp.tv_sec++; + atom.ul = 19; + add_param(pmid_type, PM_TYPE_U32, &atom); + atom.vbp = aggr; + epp = (pmEventParameter *)eptr; + add_param(pmid_aggregate, PM_TYPE_AGGREGATE, &atom); + epp->ep_type = PM_TYPE_EVENT; + atom.ul = 20; + add_param(pmid_type, PM_TYPE_U32, &atom); + add_record(&stamp, 0); + stamp.tv_sec++; + atom.ul = 21; + add_param(pmid_type, PM_TYPE_U32, &atom); + eap->ea_len = eptr - ebuf; + dump("3 records, nested event type @ 2nd parameter of 2nd record"); + + printf("\n"); + printf("__pmDumpEventRecords coverage test ...\n"); + reset(); + add_record(&stamp, 0); + stamp.tv_sec++; + atom.l = 22; + add_param(pmid_type, PM_TYPE_32, &atom); + atom.ul = 23; + add_param(pmid_u32, PM_TYPE_U32, &atom); + atom.ll = -24; + add_param(pmid_64, PM_TYPE_64, &atom); + atom.ull = 25; + add_param(pmid_u64, PM_TYPE_U64, &atom); + atom.f = -26; + add_param(pmid_float, PM_TYPE_FLOAT, &atom); + atom.d = 27; + add_param(pmid_double, PM_TYPE_DOUBLE, &atom); + atom.cp = "minus twenty-eight"; + add_param(pmid_string, PM_TYPE_STRING, &atom); + atom.vbp = aggr; + add_param(pmid_aggregate, PM_TYPE_AGGREGATE, &atom); + add_param(pmid_aggregate, PM_TYPE_AGGREGATE_STATIC, &atom); + epp = (pmEventParameter *)eptr; + atom.l = 29; + add_param(pmid_32, PM_TYPE_32, &atom); + eap->ea_len = eptr - ebuf; + pmDebug |= DBG_TRACE_FETCH; + dump("all good"); + epp->ep_type = PM_TYPE_UNKNOWN; + __pmDumpEventRecords(stdout, &vs, 0); + + return 0; +} |