int QmcEventRecord::setParameter(int index, pmID pmid, QmcContext *context, pmValueSet const *vsp) { QString *name; QmcDesc *desc; QmcIndom *indom; int sts, type; if (vsp->numval <= 0) // no value or an error return vsp->numval; if ((sts = context->lookup(pmid, &name, &desc, &indom)) < 0) return sts; QmcEventParameter ¶meter = my.parameters[index]; parameter.setPMID(pmid); parameter.setNamePtr(name); parameter.setDescPtr(desc); parameter.setIndomPtr(indom); parameter.setValueCount(vsp->numval); type = desc->desc().type; for (int i = 0; i < vsp->numval; i++) { pmAtomValue result; const pmValue *vp = &vsp->vlist[i]; QmcMetricValue *value = parameter.valuePtr(i); sts = PM_ERR_TYPE; // no nesting events if (QmcMetric::real(type) == true) { if ((sts = pmExtractValue(vsp->valfmt, vp, type, &result, PM_TYPE_DOUBLE)) >= 0) value->setCurrentValue(result.d); } else if (QmcMetric::aggregate(type) == true) { char buffer[32]; QmcMetric::aggregateAsString(vp, buffer, sizeof(buffer)); value->setStringValue(buffer); } else if (QmcMetric::event(type) == false) { if ((sts = pmExtractValue(vsp->valfmt, vp, type, &result, PM_TYPE_STRING)) >= 0) { value->setStringValue(result.cp); free(result.cp); } } value->setInstance(vp->inst); if (sts < 0) value->setCurrentError(sts); } return 0; }
static unsigned int get_ncpu(void) { /* there is only one metric in the pmclient_init group */ pmID pmidlist[1]; pmDesc desclist[1]; pmResult *rp; pmAtomValue atom; int sts; if ((sts = pmLookupName(1, pmclient_init, pmidlist)) < 0) { fprintf(stderr, "%s: pmLookupName: %s\n", pmProgname, pmErrStr(sts)); fprintf(stderr, "%s: metric \"%s\" not in name space\n", pmProgname, pmclient_init[0]); exit(1); } if ((sts = pmLookupDesc(pmidlist[0], desclist)) < 0) { fprintf(stderr, "%s: cannot retrieve description for metric \"%s\" (PMID: %s)\nReason: %s\n", pmProgname, pmclient_init[0], pmIDStr(pmidlist[0]), pmErrStr(sts)); exit(1); } if ((sts = pmFetch(1, pmidlist, &rp)) < 0) { fprintf(stderr, "%s: pmFetch: %s\n", pmProgname, pmErrStr(sts)); exit(1); } /* the thing we want is known to be the first value */ pmExtractValue(rp->vset[0]->valfmt, rp->vset[0]->vlist, desclist[0].type, &atom, PM_TYPE_U32); pmFreeResult(rp); return atom.ul; }
int pcpfastExtractValues(pmResult *rp, int *inst, pmAtomValue *atom, int vsetidx, int vlistidx, int type) { int status; *inst = rp->vset[vsetidx]->vlist[vlistidx].inst; status = pmExtractValue(rp->vset[vsetidx]->valfmt, &rp->vset[vsetidx]->vlist[vlistidx], type, atom, type); return status; }
static void newHashInst(pmValue *vp, checkData *checkdata, /* updated by this function */ int valfmt, struct timeval *timestamp, /* timestamp for this sample */ int pos) /* position of this inst in instlist */ { int sts; size_t size; pmAtomValue av; if ((sts = pmExtractValue(valfmt, vp, checkdata->desc.type, &av, PM_TYPE_DOUBLE)) < 0) { fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, timestamp); fprintf(stderr, "] "); print_metric(stderr, checkdata->desc.pmid); fprintf(stderr, ": pmExtractValue failed: %s\n", pmErrStr(sts)); fprintf(stderr, "%s: possibly corrupt archive?\n", pmProgname); exit(EXIT_FAILURE); } size = (pos+1)*sizeof(instData*); checkdata->instlist = (instData**) realloc(checkdata->instlist, size); if (!checkdata->instlist) __pmNoMem("newHashInst.instlist", size, PM_FATAL_ERR); size = sizeof(instData); checkdata->instlist[pos] = (instData*) malloc(size); if (!checkdata->instlist[pos]) __pmNoMem("newHashInst.instlist[pos]", size, PM_FATAL_ERR); checkdata->instlist[pos]->inst = vp->inst; checkdata->instlist[pos]->lastval = av.d; checkdata->instlist[pos]->lasttime = *timestamp; checkdata->listsize++; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL1) { char *name; fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, timestamp); fprintf(stderr, "] "); print_metric(stderr, checkdata->desc.pmid); if (vp->inst == PM_INDOM_NULL) fprintf(stderr, ": new singular metric\n"); else { fprintf(stderr, ": new metric-instance pair "); if (pmNameInDom(checkdata->desc.indom, vp->inst, &name) < 0) fprintf(stderr, "%d\n", vp->inst); else { fprintf(stderr, "\"%s\"\n", name); free(name); } } } #endif }
void QmcMetric::extractNumericMetric(pmValueSet const *set, pmValue const *value, QmcMetricValue &valueRef) { pmAtomValue result; int sts; if ((sts = pmExtractValue(set->valfmt, value, desc().desc().type, &result, PM_TYPE_DOUBLE)) >= 0) valueRef.setCurrentValue(result.d); else valueRef.setCurrentError(sts); }
/* ** extract values from a pmResult structure using given offset(s) ** "value" is always a macro identifier from a metric map file. */ int extract_integer_index(pmResult *result, pmDesc *descs, int value, int i) { pmAtomValue atom = { 0 }; pmValueSet *values = result->vset[value]; if (values->numval <= 0 || values->numval <= i) return 0; pmExtractValue(values->valfmt, &values->vlist[i], descs[value].type, &atom, PM_TYPE_32); return atom.l; }
/* Print single performance metric rate value */ static void printrate(int valfmt, /* from pmValueSet */ int type, /* from pmDesc */ pmValue *val1, /* current value */ pmValue *val2, /* previous value */ double delta, /* time difference between samples */ int minwidth) /* output is at least this wide */ { pmAtomValue a, b; double v; static int dowrap = -1; pmExtractValue(valfmt, val1, type, &a, PM_TYPE_DOUBLE); pmExtractValue(valfmt, val2, type, &b, PM_TYPE_DOUBLE); v = a.d - b.d; if (v < 0.0) { if (dowrap == -1) { /* PCP_COUNTER_WRAP in environment enables "counter wrap" logic */ if (getenv("PCP_COUNTER_WRAP") == NULL) dowrap = 0; else dowrap = 1; } if (dowrap) { switch (type) { case PM_TYPE_32: case PM_TYPE_U32: v += (double)UINT_MAX+1; break; case PM_TYPE_64: case PM_TYPE_U64: v += (double)ULONGLONG_MAX+1; break; } } } v /= delta; printreal(v, minwidth); }
static __uint64_t get_value(int metric, pmValue *value) { int sts; pmAtomValue val; if ((sts = pmExtractValue(valfmt_tab[metric], value, type_tab[metric], &val, PM_TYPE_U64)) < 0) { fprintf(stderr, "%s: Failed to extract metric value: %s\n", pmProgname, pmErrStr(sts)); exit(1); } return val.ull; }
char * extract_string_index(pmResult *result, pmDesc *descs, int value, char *buffer, int buflen, int i) { pmAtomValue atom = { 0 }; pmValueSet *values = result->vset[value]; if (values->numval <= 0 || values->numval <= i) return NULL; pmExtractValue(values->valfmt, &values->vlist[i], descs[value].type, &atom, PM_TYPE_STRING); strncpy(buffer, atom.cp, buflen); free(atom.cp); if (buflen > 1) /* might be a single character - e.g. process state */ buffer[buflen-1] = '\0'; return buffer; }
float extract_float_inst(pmResult *result, pmDesc *descs, int value, int inst) { pmAtomValue atom = { 0 }; pmValueSet *values = result->vset[value]; int i; for (i = 0; i < values->numval; i++) { if (values->vlist[i].inst != inst) continue; pmExtractValue(values->valfmt, &values->vlist[i], descs[value].type, &atom, PM_TYPE_FLOAT); break; } if (values->numval <= 0 || i == values->numval) return -1; return atom.f; }
void QmcMetric::extractArrayMetric(pmValueSet const *set, pmValue const *vp, QmcMetricValue &valueRef) { pmAtomValue result; int sts, type = desc().desc().type; if (aggregate(type)) { char buffer[32]; aggregateAsString(vp, buffer, sizeof(buffer)); valueRef.setStringValue(buffer); } else if ((sts = pmExtractValue(set->valfmt, vp, type, &result, PM_TYPE_STRING)) >= 0) { valueRef.setStringValue(result.cp); if (result.cp) free(result.cp); } else { valueRef.setCurrentError(sts); } }
static void get_sample(info_t *ip) { static pmResult *crp = NULL; /* current */ static pmResult *prp = NULL; /* prior */ static int first = 1; static int numpmid; static pmID *pmidlist; static pmDesc *desclist; static int inst1; static int inst15; static pmUnits mbyte_scale; int sts; int i; float u; pmAtomValue tmp; pmAtomValue atom; double dt; if (first) { /* first time initialization */ mbyte_scale.dimSpace = 1; mbyte_scale.scaleSpace = PM_SPACE_MBYTE; numpmid = sizeof(pmclient_sample) / sizeof(char *); if ((pmidlist = (pmID *)malloc(numpmid * sizeof(pmidlist[0]))) == NULL) { fprintf(stderr, "%s: get_sample: malloc: %s\n", pmProgname, osstrerror()); exit(1); } if ((desclist = (pmDesc *)malloc(numpmid * sizeof(desclist[0]))) == NULL) { fprintf(stderr, "%s: get_sample: malloc: %s\n", pmProgname, osstrerror()); exit(1); } if ((sts = pmLookupName(numpmid, pmclient_sample, pmidlist)) < 0) { printf("%s: pmLookupName: %s\n", pmProgname, pmErrStr(sts)); for (i = 0; i < numpmid; i++) { if (pmidlist[i] == PM_ID_NULL) fprintf(stderr, "%s: metric \"%s\" not in name space\n", pmProgname, pmclient_sample[i]); } exit(1); } for (i = 0; i < numpmid; i++) { if ((sts = pmLookupDesc(pmidlist[i], &desclist[i])) < 0) { fprintf(stderr, "%s: cannot retrieve description for metric \"%s\" (PMID: %s)\nReason: %s\n", pmProgname, pmclient_sample[i], pmIDStr(pmidlist[i]), pmErrStr(sts)); exit(1); } } } /* fetch the current metrics */ if ((sts = pmFetch(numpmid, pmidlist, &crp)) < 0) { fprintf(stderr, "%s: pmFetch: %s\n", pmProgname, pmErrStr(sts)); exit(1); } /* * minor gotcha ... for archives, it helps to do the first fetch of * real data before interrogating the instance domains ... this * forces us to be "after" the first batch of instance domain info * in the meta data files */ if (first) { /* * from now on, just want the 1 minute and 15 minute load averages, * so limit the instance profile for this metric */ pmDelProfile(desclist[LOADAV].indom, 0, NULL); /* all off */ if ((inst1 = pmLookupInDom(desclist[LOADAV].indom, "1 minute")) < 0) { fprintf(stderr, "%s: cannot translate instance for 1 minute load average\n", pmProgname); exit(1); } pmAddProfile(desclist[LOADAV].indom, 1, &inst1); if ((inst15 = pmLookupInDom(desclist[LOADAV].indom, "15 minute")) < 0) { fprintf(stderr, "%s: cannot translate instance for 15 minute load average\n", pmProgname); exit(1); } pmAddProfile(desclist[LOADAV].indom, 1, &inst15); first = 0; } /* if the second or later sample, pick the results apart */ if (prp != NULL) { dt = __pmtimevalSub(&crp->timestamp, &prp->timestamp); ip->cpu_util = 0; ip->peak_cpu_util = -1; /* force re-assignment at first CPU */ for (i = 0; i < ncpu; i++) { pmExtractValue(crp->vset[CPU_USR]->valfmt, &crp->vset[CPU_USR]->vlist[i], desclist[CPU_USR].type, &atom, PM_TYPE_FLOAT); u = atom.f; pmExtractValue(prp->vset[CPU_USR]->valfmt, &prp->vset[CPU_USR]->vlist[i], desclist[CPU_USR].type, &atom, PM_TYPE_FLOAT); u -= atom.f; pmExtractValue(crp->vset[CPU_SYS]->valfmt, &crp->vset[CPU_SYS]->vlist[i], desclist[CPU_SYS].type, &atom, PM_TYPE_FLOAT); u += atom.f; pmExtractValue(prp->vset[CPU_SYS]->valfmt, &prp->vset[CPU_SYS]->vlist[i], desclist[CPU_SYS].type, &atom, PM_TYPE_FLOAT); u -= atom.f; /* * really should use pmConvertValue, but I _know_ the times * are in msec! */ u = u / (1000 * dt); if (u > 1.0) /* small errors are possible, so clip the utilization at 1.0 */ u = 1.0; ip->cpu_util += u; if (u > ip->peak_cpu_util) { ip->peak_cpu_util = u; ip->peak_cpu = i; } } ip->cpu_util /= ncpu; /* freemem - expect just one value */ pmExtractValue(crp->vset[FREEMEM]->valfmt, crp->vset[FREEMEM]->vlist, desclist[FREEMEM].type, &tmp, PM_TYPE_FLOAT); /* convert from today's units at the collection site to Mbytes */ pmConvScale(PM_TYPE_FLOAT, &tmp, &desclist[FREEMEM].units, &atom, &mbyte_scale); ip->freemem = atom.f; /* disk IOPS - expect just one value, but need delta */ pmExtractValue(crp->vset[DKIOPS]->valfmt, crp->vset[DKIOPS]->vlist, desclist[DKIOPS].type, &atom, PM_TYPE_U32); ip->dkiops = atom.ul; pmExtractValue(prp->vset[DKIOPS]->valfmt, prp->vset[DKIOPS]->vlist, desclist[DKIOPS].type, &atom, PM_TYPE_U32); ip->dkiops -= atom.ul; ip->dkiops = ((float)(ip->dkiops) + 0.5) / dt; /* load average ... process all values, matching up the instances */ for (i = 0; i < crp->vset[LOADAV]->numval; i++) { pmExtractValue(crp->vset[LOADAV]->valfmt, &crp->vset[LOADAV]->vlist[i], desclist[LOADAV].type, &atom, PM_TYPE_FLOAT); if (crp->vset[LOADAV]->vlist[i].inst == inst1) ip->load1 = atom.f; else if (crp->vset[LOADAV]->vlist[i].inst == inst15) ip->load15 = atom.f; } /* free very old result */ pmFreeResult(prp); } ip->timestamp = crp->timestamp; /* swizzle result pointers */ prp = crp; }
/* Print performance metric values */ static void printvals(Context *x, pmValueSet *vset, int cols) { int i, j; pmAtomValue av; int doreal = 0; if (x->desc.type == PM_TYPE_FLOAT || x->desc.type == PM_TYPE_DOUBLE) doreal = 1; /* null instance domain */ if (x->desc.indom == PM_INDOM_NULL) { if (vset->numval == 1) { if (doreal) { pmExtractValue(vset->valfmt, &vset->vlist[0], x->desc.type, &av, PM_TYPE_DOUBLE); printreal(av.d, cols); } else pmPrintValue(stdout, vset->valfmt, x->desc.type, &vset->vlist[0], cols); } else printf("%*s", cols, "?"); putchar('\n'); } /* non-null instance domain */ else { for (i = 0; i < x->inum; i++) { for (j = 0; j < vset->numval; j++) { if (vset->vlist[j].inst == x->ipairs[i].id) break; } if (j < vset->numval) { if (doreal) { pmExtractValue(vset->valfmt, &vset->vlist[j], x->desc.type, &av, PM_TYPE_DOUBLE); printreal(av.d, cols); } else pmPrintValue(stdout, vset->valfmt, x->desc.type, &vset->vlist[j], cols); } else printf("%*s", cols, "?"); putchar(' '); } putchar('\n'); for (j = 0; j < vset->numval; j++) { for (i = 0; i < x->inum; i++) { if (vset->vlist[j].inst == x->ipairs[i].id) break; } if (x->iall == 1 && i == x->inum) { printf("Warning: value="); if (doreal) { pmExtractValue(vset->valfmt, &vset->vlist[j], x->desc.type, &av, PM_TYPE_DOUBLE); printreal(av.d, 1); } else pmPrintValue(stdout, vset->valfmt, x->desc.type, &vset->vlist[j], 1); printf(", but instance=%d is unknown\n", vset->vlist[j].inst); } } } }
int zbx_module_pcp_fetch_metric(AGENT_REQUEST *request, AGENT_RESULT *result) { int sts; char *metric[] = { request->key + strlen(ZBX_PCP_METRIC_PREFIX) }; char *inst; pmID pmid[1]; pmDesc desc[1]; pmResult *rp; pmAtomValue atom; int iid = 0; int i; /* Parameter is the instance. */ switch(request->nparam) { case 0: inst = NULL; break; case 1: inst = get_rparam(request, 0); break; default: SET_MSG_RESULT(result, strdup("Extraneous instance specification.")); return SYSINFO_RET_FAIL; break; } /* Preparations and sanity checks. */ sts = pmLookupName(1, metric, pmid); if (sts < 0) return SYSINFO_RET_FAIL; sts = pmLookupDesc(pmid[0], desc); if (sts < 0) return SYSINFO_RET_FAIL; if (inst != NULL && desc[0].indom == PM_INDOM_NULL) { SET_MSG_RESULT(result, strdup("Extraneous instance specification.")); return SYSINFO_RET_FAIL; } if ((inst == NULL && desc[0].indom != PM_INDOM_NULL) || (request->nparam == 1 && !strlen(inst))) { SET_MSG_RESULT(result, strdup("Missing instance specification.")); return SYSINFO_RET_FAIL; } if (desc[0].indom != PM_INDOM_NULL) { iid = pmLookupInDom(desc[0].indom, inst); if (iid < 0) { SET_MSG_RESULT(result, strdup("Instance not available.")); return SYSINFO_RET_FAIL; } } /* Fetch the metric values. */ sts = pmFetch(1, pmid, &rp); if (sts < 0) return SYSINFO_RET_FAIL; if (rp->vset[0]->numval < 1) { pmFreeResult(rp); SET_MSG_RESULT(result, strdup("No value available.")); return SYSINFO_RET_FAIL; } /* Locate the correct instance. */ for (i = 0; desc[0].indom != PM_INDOM_NULL && i < rp->vset[0]->numval; i++) { if (rp->vset[0]->vlist[i].inst == iid) { break; } } if (i == rp->vset[0]->numval) { pmFreeResult(rp); return SYSINFO_RET_FAIL; } /* Extract the wanted value. */ sts = pmExtractValue(rp->vset[0]->valfmt, &rp->vset[0]->vlist[i], desc[0].type, &atom, desc[0].type); pmFreeResult(rp); if (sts < 0) return SYSINFO_RET_FAIL; /* Hand it to the caller. */ switch(desc[0].type) { case PM_TYPE_32: SET_UI64_RESULT(result, atom.l); break; case PM_TYPE_U32: SET_UI64_RESULT(result, atom.ul); break; case PM_TYPE_64: SET_UI64_RESULT(result, atom.ll); break; case PM_TYPE_U64: SET_UI64_RESULT(result, atom.ull); break; case PM_TYPE_FLOAT: SET_DBL_RESULT(result, atom.f); break; case PM_TYPE_DOUBLE: SET_DBL_RESULT(result, atom.d); break; case PM_TYPE_STRING: SET_STR_RESULT(result, strdup(atom.cp)); break; default: SET_MSG_RESULT(result, strdup("Unsupported metric value type.")); return SYSINFO_RET_FAIL; break; } /* Success. */ return SYSINFO_RET_OK; }
static void docheck(pmResult *result) { int i, j, k; int sts; pmDesc desc; pmAtomValue av; pmValue *vp; pmValueSet *vsp; __pmHashNode *hptr = NULL; checkData *checkdata = NULL; double diff; struct timeval timediff; for (i = 0; i < result->numpmid; i++) { vsp = result->vset[i]; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL1) { if (vsp->numval == 0) { fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); fprintf(stderr, "] "); print_metric(stderr, vsp->pmid); fprintf(stderr, ": no values returned\n"); continue; } else if (vsp->numval < 0) { fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); fprintf(stderr, "] "); print_metric(stderr, vsp->pmid); fprintf(stderr, ": error from numval: %s\n", pmErrStr(vsp->numval)); continue; } } #endif if (vsp->numval <= 0) continue; /* check if pmid already in hash list */ if ((hptr = __pmHashSearch(vsp->pmid, &hashlist)) == NULL) { if ((sts = pmLookupDesc(vsp->pmid, &desc)) < 0) { fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); fprintf(stderr, "] "); print_metric(stderr, vsp->pmid); fprintf(stderr, ": pmLookupDesc failed: %s\n", pmErrStr(sts)); continue; } if (desc.type != PM_TYPE_32 && desc.type != PM_TYPE_U32 && desc.type != PM_TYPE_64 && desc.type != PM_TYPE_U64 && desc.type != PM_TYPE_FLOAT && desc.type != PM_TYPE_DOUBLE) { continue; /* no checks for non-numeric metrics */ } /* create a new one & add to list */ checkdata = (checkData*) malloc(sizeof(checkData)); newHashItem(vsp, &desc, checkdata, &result->timestamp); if (__pmHashAdd(checkdata->desc.pmid, (void*)checkdata, &hashlist) < 0) { fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); fprintf(stderr, "] "); print_metric(stderr, vsp->pmid); fprintf(stderr, ": __pmHashAdd failed (internal pmlogcheck error)\n"); /* free memory allocated above on insert failure */ for (j = 0; j < vsp->numval; j++) { if (checkdata->instlist[j] != NULL) free(checkdata->instlist[j]); } if (checkdata->instlist != NULL) free(checkdata->instlist); continue; } } else { /* pmid exists - update statistics */ checkdata = (checkData *)hptr->data; for (j = 0; j < vsp->numval; j++) { /* iterate thro result values */ vp = &vsp->vlist[j]; k = j; /* index into stored inst list, result may differ */ if ((vsp->numval > 1) || (checkdata->desc.indom != PM_INDOM_NULL)) { /* must store values using correct inst - probably in correct order already */ if ((k < checkdata->listsize) && (checkdata->instlist[k]->inst != vp->inst)) { for (k = 0; k < checkdata->listsize; k++) { if (vp->inst == checkdata->instlist[k]->inst) { break; /* k now correct */ } } if (k == checkdata->listsize) { /* no matching inst was found */ newHashInst(vp, checkdata, vsp->valfmt, &result->timestamp, k); continue; } } else if (k >= checkdata->listsize) { k = checkdata->listsize; newHashInst(vp, checkdata, vsp->valfmt, &result->timestamp, k); continue; } } if (k >= checkdata->listsize) { /* only error values observed so far */ k = checkdata->listsize; newHashInst(vp, checkdata, vsp->valfmt, &result->timestamp, k); continue; } timediff = result->timestamp; tsub(&timediff, &(checkdata->instlist[k]->lasttime)); if (timediff.tv_sec < 0) { /* clip negative values at zero */ timediff.tv_sec = 0; timediff.tv_usec = 0; } diff = __pmtimevalToReal(&timediff); if ((sts = pmExtractValue(vsp->valfmt, vp, checkdata->desc.type, &av, PM_TYPE_DOUBLE)) < 0) { fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); fprintf(stderr, "] "); print_metric(stderr, vsp->pmid); fprintf(stderr, ": pmExtractValue failed: %s\n", pmErrStr(sts)); continue; } if (checkdata->desc.sem == PM_SEM_COUNTER) { if (diff == 0.0) continue; diff *= checkdata->scale; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) { fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); fprintf(stderr, "] "); print_metric(stderr, checkdata->desc.pmid); fprintf(stderr, ": current counter value is %.0f\n", av.d); } #endif unwrap(av.d, &(result->timestamp), checkdata, k); } checkdata->instlist[k]->lastval = av.d; checkdata->instlist[k]->lasttime = result->timestamp; } } } }
static int papi_store(pmResult *result, pmdaExt *pmda) { int sts = 0; int sts2 = 0; int i, j; const char *delim = " ,"; char *substring; if (!permission_check(pmda->e_context)) return PM_ERR_PERMISSION; for (i = 0; i < result->numpmid; i++) { pmValueSet *vsp = result->vset[i]; __pmID_int *idp = (__pmID_int *)&(vsp->pmid); pmAtomValue av; if (idp->cluster != CLUSTER_CONTROL) { sts2 = PM_ERR_PERMISSION; continue; } switch (idp->item) { case CONTROL_ENABLE: case CONTROL_DISABLE: // NB: almost identical handling! if ((sts = pmExtractValue(vsp->valfmt, &vsp->vlist[0], PM_TYPE_STRING, &av, PM_TYPE_STRING)) < 0) { sts2 = sts; continue; } substring = strtok(av.cp, delim); while (substring != NULL) { for (j = 0; j < number_of_events; j++) { if (!strcmp(substring, papi_info[j].papi_string_code)) { papi_info[j].metric_enabled = (idp->item == CONTROL_ENABLE) ? METRIC_ENABLED_FOREVER : 0; break; } } if (j == number_of_events) { if (pmDebug & DBG_TRACE_APPL0) __pmNotifyErr(LOG_DEBUG, "metric name %s does not match any known metrics\n", substring); sts = 1; /* NB: continue for other event names that may succeed */ } substring = strtok(NULL, delim); } if (sts) { /* any unknown metric name encountered? */ sts = refresh_metrics(0); /* still enable those that we can */ if (sts == 0) sts = PM_ERR_BADSTORE; /* but return overall error */ } else { sts = refresh_metrics(0); } // NB: We could iterate the affected papi_info[j]'s again to see which // counters were successfully activated (position >= 0). Then again, // the user will find out soon enough, when attempting to fetch them. sts2 = sts; continue; case CONTROL_RESET: for (j = 0; j < number_of_events; j++) papi_info[j].metric_enabled = 0; sts = refresh_metrics(0); continue; case CONTROL_AUTO_ENABLE: if ((sts = pmExtractValue(vsp->valfmt, &vsp->vlist[0], PM_TYPE_U32, &av, PM_TYPE_U32)) < 0) { sts2 = sts; continue; } auto_enable_time = av.ul; sts = papi_setup_auto_af(); sts2 = sts; continue; case CONTROL_MULTIPLEX: if ((sts = pmExtractValue(vsp->valfmt, &vsp->vlist[0], PM_TYPE_U32, &av, PM_TYPE_U32)) < 0) { sts2 = sts; continue; } enable_multiplexing = av.ul; sts = refresh_metrics(0); sts2 = sts; continue; default: sts2 = PM_ERR_PMID; continue; } } if (sts == 0) sts = sts2; return sts; }