/* Convert the time scale but not the value nor the dimensionality. */ int convert_time_scale(void) { pmAtomValue ival; pmAtomValue oval; pmUnits iunits = PMDA_PMUNITS(1, -1, 0, PM_SPACE_KBYTE, PM_TIME_SEC, 0); pmUnits ounits = PMDA_PMUNITS(1, -1, 0, PM_SPACE_KBYTE, PM_TIME_NSEC, 0); ival.l = oval.l = 100; return(pmConvScale(PM_TYPE_32, &ival, &iunits, &oval, &ounits)); }
void SamplingItem::rescaleValues(pmUnits *new_units) { pmUnits *old_units = &ChartItem::my.units; pmAtomValue old_av, new_av; console->post("Chart::update change units from %s to %s", pmUnitsStr(old_units), pmUnitsStr(new_units)); for (int i = my.dataCount - 1; i >= 0; i--) { if (my.data[i] != qQNaN()) { old_av.d = my.data[i]; pmConvScale(PM_TYPE_DOUBLE, &old_av, old_units, &new_av, new_units); my.data[i] = new_av.d; } if (my.itemData[i] != qQNaN()) { old_av.d = my.itemData[i]; pmConvScale(PM_TYPE_DOUBLE, &old_av, old_units, &new_av, new_units); my.itemData[i] = new_av.d; } } }
void SamplingItem::updateValues(bool forward, bool rateConvert, pmUnits *units, int sampleHistory, int, double, double, double) { pmAtomValue scaled, raw; QmcMetric *metric = ChartItem::my.metric; double value; int sz; if (metric->numValues() < 1 || metric->error(0)) { value = qQNaN(); } else { // convert raw value to current chart scale raw.d = rateConvert ? metric->value(0) : metric->currentValue(0); pmConvScale(PM_TYPE_DOUBLE, &raw, &ChartItem::my.units, &scaled, units); value = scaled.d * my.scale; } if (my.dataCount < sampleHistory) sz = qMax(0, (int)(my.dataCount * sizeof(double))); else sz = qMax(0, (int)((my.dataCount - 1) * sizeof(double))); if (forward) { memmove(&my.data[1], &my.data[0], sz); memmove(&my.itemData[1], &my.itemData[0], sz); my.data[0] = value; } else { memmove(&my.data[0], &my.data[1], sz); memmove(&my.itemData[0], &my.itemData[1], sz); my.data[my.dataCount - 1] = value; } if (my.dataCount < sampleHistory) my.dataCount++; }
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; }
int QmcMetric::update() { uint i, err = 0; uint num = numValues(); int sts; pmAtomValue ival, oval; double delta = context()->timeDelta(); static int wrap = -1; if (num == 0 || my.status < 0) return my.status; // PCP_COUNTER_WRAP in environment enables "counter wrap" logic if (wrap == -1) wrap = (getenv("PCP_COUNTER_WRAP") != NULL); for (i = 0; i < num; i++) { my.values[i].setError(my.values[i].currentError()); if (my.values[i].error() < 0) err++; if (pmDebug & DBG_TRACE_VALUE) { QTextStream cerr(stderr); if (my.values[i].error() < 0) cerr << "QmcMetric::update: " << spec(true, true, i) << ": " << pmErrStr(my.values[i].error()) << endl; } } if (!real()) return err; if (desc().desc().sem == PM_SEM_COUNTER) { for (i = 0; i < num; i++) { QmcMetricValue& value = my.values[i]; if (value.error() < 0) { // we already know we value.setValue(0.0); // don't have this value continue; } if (value.previousError() < 0) { // we need two values value.setValue(0.0); // for a rate value.setError(value.previousError()); err++; if (pmDebug & DBG_TRACE_VALUE) { QTextStream cerr(stderr); cerr << "QmcMetric::update: Previous: " << spec(true, true, i) << ": " << pmErrStr(value.error()) << endl; } continue; } value.setValue(value.currentValue() - value.previousValue()); // wrapped going forwards if (value.value() < 0 && delta > 0) { if (wrap) { switch(desc().desc().type) { case PM_TYPE_32: case PM_TYPE_U32: value.addValue((double)UINT_MAX+1); break; case PM_TYPE_64: case PM_TYPE_U64: value.addValue((double)ULONGLONG_MAX+1); break; } } else { // counter not monotonic value.setValue(0.0); // increasing value.setError(PM_ERR_VALUE); err++; continue; } } // wrapped going backwards else if (value.value() > 0 && delta < 0) { if (wrap) { switch(desc().desc().type) { case PM_TYPE_32: case PM_TYPE_U32: value.subValue((double)UINT_MAX+1); break; case PM_TYPE_64: case PM_TYPE_U64: value.subValue((double)ULONGLONG_MAX+1); break; } } else { // counter not monotonic value.setValue(0.0); // increasing value.setError(PM_ERR_VALUE); err++; continue; } } if (delta != 0) // sign of delta and v value.divValue(delta); // should be the same else value.setValue(0.0); // nothing can have happened } } else { for (i = 0; i < num; i++) { QmcMetricValue& value = my.values[i]; if (value.error() < 0) value.setValue(0.0); else value.setValue(value.currentValue()); } } if (my.scale != 0.0) { for (i = 0; i < num; i++) { if (my.values[i].error() >= 0) my.values[i].divValue(my.scale); } } if (desc().useScaleUnits()) { for (i = 0; i < num; i++) { if (my.values[i].error() < 0) continue; ival.d = my.values[i].value(); pmUnits units = desc().desc().units; sts = pmConvScale(PM_TYPE_DOUBLE, &ival, &units, &oval, (pmUnits *)&(desc().scaleUnits())); if (sts < 0) my.values[i].setError(sts); else { my.values[i].setValue(oval.d); if (pmDebug & DBG_TRACE_VALUE) { QTextStream cerr(stderr); cerr << "QmcMetric::update: scaled " << my.name << " from " << ival.d << " to " << oval.d << endl; } } } } return err; }
int main(int argc, char **argv) { int c; int sts; int errflag = 0; static char *usage = "[-D debug] type value iunit ounit\n" "\n" "iunit and ounit are in the 6-integer format:\n" "dimspace:dimtime:dimcount:scalespace:scaletime:scalecount\n"; pmUnits iu; pmUnits ou; int type; int vbase; pmAtomValue iv; pmAtomValue ov; char *vp; char *q; __pmSetProgname(argv[0]); /* stop at type arg, so value may have leading "-" */ putenv("POSIXLY_CORRECT=yes"); 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 || argc - optind != 4) { fprintf(stderr, "Usage: %s %s\n", pmProgname, usage); exit(1); } /* non-flag args are argv[optind] ... argv[argc-1] */ type = atoi(argv[optind]); optind++; if (strncmp(argv[optind], "0x", 2) == 0) { vp = &argv[optind][2]; vbase = 16; } else { vp = argv[optind]; vbase = 10; } q = vp; switch (type) { case PM_TYPE_32: iv.l = strtol(vp, &q, vbase); break; case PM_TYPE_U32: iv.ul = strtoul(vp, &q, vbase); break; case PM_TYPE_64: iv.ll = strtoll(vp, &q, vbase); break; case PM_TYPE_U64: iv.ull = strtoull(vp, &q, vbase); break; case PM_TYPE_FLOAT: sts = sscanf(vp, "%f", &iv.f); if (sts == 1) q = ""; break; case PM_TYPE_DOUBLE: sts = sscanf(vp, "%lf", &iv.d); if (sts == 1) q = ""; break; default: case PM_TYPE_STRING: iv.cp = vp; q = ""; break; case PM_TYPE_AGGREGATE: case PM_TYPE_AGGREGATE_STATIC: iv.vbp = (pmValueBlock *)malloc(PM_VAL_HDR_SIZE+strlen(vp)); iv.vbp->vlen = PM_VAL_HDR_SIZE+strlen(vp); iv.vbp->vtype = type; strncpy(iv.vbp->vbuf, vp, strlen(vp)); q = ""; break; case PM_TYPE_EVENT: // ignore the value, force 0 event records iv.vbp = (pmValueBlock *)malloc(sizeof(pmEventArray)-sizeof(pmEventRecord)); iv.vbp->vlen = sizeof(pmEventArray)-sizeof(pmEventRecord); iv.vbp->vtype = type; memset((void *)iv.vbp->vbuf, 0, sizeof(int)); q = ""; break; case PM_TYPE_HIGHRES_EVENT: // ignore the value, force 0 event records iv.vbp = (pmValueBlock *)malloc(sizeof(pmHighResEventArray)-sizeof(pmHighResEventRecord)); iv.vbp->vlen = sizeof(pmHighResEventArray)-sizeof(pmHighResEventRecord); iv.vbp->vtype = type; memset((void *)iv.vbp->vbuf, 0, sizeof(int)); q = ""; break; } optind++; if (*q != '\0') { fprintf(stderr, "Value botched @ %s\n", q); exit(1); } vp = argv[optind]; iu.dimSpace = strtol(vp, &q, 10); if (*q != ':') goto bad_in; vp = ++q; iu.dimTime = strtol(vp, &q, 10); if (*q != ':') goto bad_in; vp = ++q; iu.dimCount = strtol(vp, &q, 10); if (*q != ':') goto bad_in; vp = ++q; iu.scaleSpace = strtol(vp, &q, 10); if (*q != ':') goto bad_in; vp = ++q; iu.scaleTime = strtol(vp, &q, 10); if (*q != ':') goto bad_in; vp = ++q; iu.scaleCount = strtol(vp, &q, 10); if (*q != '\0') goto bad_in; optind++; vp = argv[optind]; ou.dimSpace = strtol(vp, &q, 10); if (*q != ':') goto bad_out; vp = ++q; ou.dimTime = strtol(vp, &q, 10); if (*q != ':') goto bad_out; vp = ++q; ou.dimCount = strtol(vp, &q, 10); if (*q != ':') goto bad_out; vp = ++q; ou.scaleSpace = strtol(vp, &q, 10); if (*q != ':') goto bad_out; vp = ++q; ou.scaleTime = strtol(vp, &q, 10); if (*q != ':') goto bad_out; vp = ++q; ou.scaleCount = strtol(vp, &q, 10); if (*q != '\0') goto bad_out; printf("type=%d input units=%s value=%s\n", type, pmUnitsStr(&iu), pmAtomStr(&iv, type)); if ((sts = pmConvScale(type, &iv, &iu, &ov, &ou)) < 0) printf("pmConvScale Error: %s\n", pmErrStr(sts)); else printf("output units=%s value=%s\n", pmUnitsStr(&ou), pmAtomStr(&ov, type)); exit(0); bad_in: fprintf(stderr, "Input units botch @ %s\n", q); exit(1); bad_out: fprintf(stderr, "Output units botch @ %s\n", q); exit(1); }