static void setup_event_derived_metrics(void) { int sts; 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"; if ((sts = pmLookupName(1, &name_flags, &pmid_flags)) < 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; } } }
/* * with -e come here for every metric in the PMNS ... */ void dometric(const char *name) { int sts; pmID pmid; char *tp; sts = pmLookupName(1, (char **)&name, &pmid); if (sts < 0) { fprintf(stderr, "pmLookupName: failed for \"%s\": %s\n", name, pmErrStr(sts)); return; } if (sts == 0) { fprintf(stderr, "pmLookupName: failed for \"%s\"\n", name); return; } tp = pmdaGetHelp(handle, pmid, PM_TEXT_ONELINE); if (tp != NULL) return; tp = pmdaGetHelp(handle, pmid, PM_TEXT_HELP); if (tp != NULL) return; /* no help text, report metric */ printf("%s\n", name); }
/* Initialize API and fill in internal description for given Context. */ static void initapi(Context *x) { int e; x->handle = pmWhichContext(); if ((e = pmLookupName(1, &(x->metric), &(x->pmid))) < 0) { fprintf(stderr, "%s: pmLookupName(%s): %s\n", pmProgname, x->metric, pmErrStr(e)); exit(EXIT_FAILURE); } if ((e = pmLookupDesc(x->pmid, &(x->desc))) < 0) { fprintf(stderr, "%s: pmLookupDesc: %s\n", pmProgname, pmErrStr(e)); exit(EXIT_FAILURE); } if (x->desc.sem == PM_SEM_COUNTER) { if (x->desc.units.dimTime == 0) x->scale = 1.0; else { if (x->desc.units.scaleTime > PM_TIME_SEC) x->scale = pow(60, (PM_TIME_SEC - x->desc.units.scaleTime)); else x->scale = pow(1000, (PM_TIME_SEC - x->desc.units.scaleTime)); } } }
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; }
static void * func1(void *arg) { int sts; char *fn = "func1"; char **offspring; int *status; int i; int j; char *namelist[] = { "b", "a.three.foo", "d.f.fumble" }; pmID pmidlist[3]; pthread_barrier_wait(&barrier); __pmDumpNameSpace(stdout, 1); sts = pmGetChildrenStatus("", &offspring, &status); if (sts >= 0) { printf("%s: pmGetChildrenStatus -> %d\n", fn, sts); for (i = 0; i < sts; i++) { printf("[%d] %s %s\n", i, offspring[i], status[i] == PMNS_LEAF_STATUS ? "leaf" : "non-leaf"); } free(offspring); free(status); } else printf("%s: pmGetChildrenStatus -> %s\n", fn, pmErrStr(sts)); for (i = 0; i < 5; i++) { pthread_barrier_wait(&barrier); sts = pmLookupName(sizeof(namelist)/sizeof(namelist[0]), namelist, pmidlist); if (sts < 0) printf("%s: pmGetChildrenStatus[%d] -> %s\n", fn, i, pmErrStr(sts)); else { for (j = 0; j < sizeof(namelist)/sizeof(namelist[0]); j++) { printf("%s: [%d] %s -> %s", fn, i, namelist[j], pmIDStr(pmidlist[j])); if (pmidlist[j] == PM_ID_NULL) printf("\n"); else { char *name; sts = pmNameID(pmidlist[j], &name); if (sts < 0) printf(": pmNameID -> %s\n", pmErrStr(sts)); else { printf(" -> %s\n", name); free(name); } } } } pthread_barrier_wait(&barrier); } pthread_exit(NULL); }
pmID QmcEventRecord::eventMissed(void) { static pmID eventMissed = PM_IN_NULL; static const char *nameMissed[] = { "event.missed" }; if (eventMissed == PM_ID_NULL) if (pmLookupName(1, (char **)nameMissed, &eventMissed) < 0) eventMissed = PM_ID_NULL; return eventMissed; }
pmID QmcEventRecord::eventFlags(void) { static pmID eventFlags = PM_IN_NULL; static const char *nameFlags[] = { "event.flags" }; if (eventFlags == PM_ID_NULL) if (pmLookupName(1, (char **)nameFlags, &eventFlags) < 0) eventFlags = PM_ID_NULL; return eventFlags; }
/* translate new metric name to internal pmid for agent mode */ static pmID agentId(char *name) { int sts; pmID pmid; if ((sts = pmLookupName(1, &name, &pmid)) < 0) { fprintf(stderr, "%s: agentId: metric %s not found in namespace: %s\n", pmProgname, name, pmErrStr(sts)); exit(1); } return pmid; }
/* Initialize API and fill in internal description for given Context. */ static void initapi(Context *x, pmMetricSpec *msp, int argc, char **argv) { int e; x->metric = msp->metric; if (msp->ninst > 0) { x->inum = msp->ninst; x->iall = (x->inum == 0); x->inames = &msp->inst[0]; } x->handle = pmWhichContext(); if ((e = pmLookupName(1, &(x->metric), &(x->pmid))) < 0) { fprintf(stderr, "%s: pmLookupName(%s): %s\n", pmProgname, x->metric, pmErrStr(e)); exit(EXIT_FAILURE); } if ((e = pmLookupDesc(x->pmid, &(x->desc))) < 0) { fprintf(stderr, "%s: pmLookupDesc: %s\n", pmProgname, pmErrStr(e)); exit(EXIT_FAILURE); } if (x->desc.indom == PM_INDOM_NULL && msp->ninst > 0) { fprintf(stderr, "%s: %s: singular metrics do not have instances\n", pmProgname, msp->metric); exit(EXIT_FAILURE); } if (x->desc.type == PM_TYPE_EVENT || x->desc.type == PM_TYPE_HIGHRES_EVENT) { amode = PM_MODE_FORW; /* do no interpolate events */ rawArchive = archive; rawEvents = 1; } if (x->desc.sem == PM_SEM_COUNTER) { if (x->desc.units.dimTime == 0) x->scale = 1.0; else { if (x->desc.units.scaleTime > PM_TIME_SEC) x->scale = pow(60, (PM_TIME_SEC - x->desc.units.scaleTime)); else x->scale = pow(1000, (PM_TIME_SEC - x->desc.units.scaleTime)); } } }
static void dometric(const char *name) { int sts; if (*name == '\0') { printf("PMNS appears to be empty!\n"); return; } numpmid++; pmid = (pmID *)realloc(pmid, numpmid * sizeof(pmID)); if ((sts = pmLookupName(1, (char **)&name, &pmid[numpmid-1])) < 0) { fprintf(stderr, "%s: pmLookupName(%s): %s\n", pmProgname, name, pmErrStr(sts)); numpmid--; } }
int main(int argc, char *argv[]) { int ctx; int sts; char buf[1024]; char *name = buf; char *p; pmID pmid; pmDesc desc; ctx = pmNewContext(PM_CONTEXT_HOST, "local:"); if (ctx < 0) { fprintf(stderr, "Error: pmNewContext %s\n", pmErrStr(ctx)); exit(1); } printf("/* This file is automatically generated .. do not edit! */\n"); printf("#include \"metrics.h\"\n\n"); printf("metric_t metrics[] = {\n"); while (fgets(buf, sizeof(buf), stdin)) { if ((p = strrchr(buf, '\n')) != NULL) *p = '\0'; if ((sts = pmLookupName(1, &name, &pmid)) < 0) { fprintf(stderr, "Error: pmLookupName \"%s\": %s\n", name, pmErrStr(sts)); exit(1); } if ((sts = pmLookupDesc(pmid, &desc)) < 0) { fprintf(stderr, "Error: pmLookupDesc \"%s\": %s\n", name, pmErrStr(sts)); exit(1); } printf(" /* %-8s */ { \"%s\", { 0x%04x, PM_TYPE_%s, %s, %s,\n" " { .dimSpace=%d, .dimTime=%d, .dimCount=%d, " ".scaleSpace=%d, .scaleTime=%d, .scaleCount=%d } } },\n", pmIDStr(desc.pmid), name, desc.pmid, pmTypeStr(desc.type), indomStr(desc.indom), semStr[desc.sem], desc.units.dimSpace, desc.units.dimTime, desc.units.dimCount, desc.units.scaleSpace, desc.units.scaleTime, desc.units.scaleCount); } printf(" { NULL }\n};\n"); exit(0); }
void zbx_module_pcp_add_metric(const char *name) { int sts; pmID pmid[1]; pmDesc desc[1]; char *metric; unsigned flags = 0; char *param = NULL; int *instlist; char **namelist; ZBX_METRIC *mptr = metrics; /* PCP preparations. */ sts = pmLookupName(1, (char **)&name, pmid); if (sts < 0) return; sts = pmLookupDesc(pmid[0], desc); if (sts < 0) return; /* Construct the Zabbix metric name. */ metric = (char *)malloc(strlen(ZBX_PCP_METRIC_PREFIX) + strlen(name) + 1); if (metric == NULL) return; strcpy(metric, ZBX_PCP_METRIC_PREFIX); strcat(metric, name); /* Pick a PCP metric instance for use with zabbix_agentd -p. */ if (desc[0].indom != PM_INDOM_NULL) { sts = pmGetInDom(desc[0].indom, &instlist, &namelist); if (sts < 0) { free(metric); return; } if (sts) { flags = CF_HAVEPARAMS; param = strdup(namelist[0]); free(instlist); free(namelist); } } /* Ready for Zabbix. */ metrics = (ZBX_METRIC *)realloc(mptr, (metric_count + 1) * sizeof(ZBX_METRIC)); if (metrics == NULL) { metrics = mptr; free(metric); free(param); return; } metrics[metric_count].key = metric; metrics[metric_count].flags = flags; metrics[metric_count].function = zbx_module_pcp_fetch_metric; metrics[metric_count].test_param = param; metric_count++; }
/* * 0. * Does NOT really verify PMNS * get pmids for rest of pm functions */ void test_PMNS(void) { int sts; int i; print_banner_start("PMNS"); if ((sts = pmLookupName(nmetrics, metrics, pmids)) < 0) { printf("pmLookupName: %s\n", pmErrStr(sts)); for (i = 0; i < nmetrics; i++) { if (pmids[i] == PM_ID_NULL) printf(" %s - not known\n", metrics[i]); } exit(1); } print_banner_end("PMNS"); }
void setup_metrics(char **metrics, pmID *pmidlist, pmDesc *desclist, int nmetrics) { int i, sts; if ((sts = pmLookupName(nmetrics, metrics, pmidlist)) < 0) { fprintf(stderr, "%s: pmLookupName: %s\n", pmProgname, pmErrStr(sts)); cleanstop(1); } if (nmetrics != sts) { for (i=0; i < nmetrics; i++) { if (pmidlist[i] != PM_ID_NULL) continue; if (pmDebug & DBG_TRACE_APPL0) fprintf(stderr, "%s: pmLookupName failed for %s\n", pmProgname, metrics[i]); } } for (i=0; i < nmetrics; i++) { if (pmidlist[i] == PM_ID_NULL) { desclist[i].pmid = PM_ID_NULL; continue; } if ((sts = pmLookupDesc(pmidlist[i], &desclist[i])) < 0) { if (pmDebug & DBG_TRACE_APPL0) fprintf(stderr, "%s: pmLookupDesc failed for %s: %s\n", pmProgname, metrics[i], pmErrStr(sts)); pmidlist[i] = desclist[i].pmid = PM_ID_NULL; } } }
int QmcContext::lookupPMID(const char *name, pmID& id) { QString key = name; int sts; if ((sts = pmUseContext(my.context)) < 0) return sts; if (my.nameCache.contains(key) == false) { if ((sts = pmLookupName(1, (char **)(&name), &id)) >= 0) my.nameCache.insert(key, id); } else { id = my.nameCache.value(key); if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcContext::lookupPMID: Matched \"" << name << "\" to id " << pmIDStr(id) << endl; } sts = 1; } return sts; }
/* Return (in result) a list of active pmlogger ports on the specified machine. * The return value of the function is the number of elements in the array. * The caller must NOT free any part of the result stucture, it's storage is * managed here. Subsequent calls will overwrite the data so the caller should * copy it if persistence is required. */ int __pmLogFindPort(const char *host, int pid, __pmLogPort **lpp) { int ctx, oldctx; char *ctxhost; int sts, numval; int i, j; int findone = pid != PM_LOG_ALL_PIDS; int localcon = 0; /* > 0 for local connection */ pmDesc desc; pmResult *res; char *namelist[] = {"pmcd.pmlogger.port"}; pmID pmid; if (PM_MULTIPLE_THREADS(PM_SCOPE_LOGPORT)) return PM_ERR_THREAD; *lpp = NULL; /* pass null back in event of error */ localcon = __pmIsLocalhost(host); if (localcon > 0) /* do the work here instead of making PMCD do it */ return __pmLogFindLocalPorts(pid, lpp); else if (localcon < 0) return localcon; /* note: there may not be a current context */ ctx = 0; oldctx = pmWhichContext(); /* * Enclose ctxhost in [] in case it is an ipv6 address. This prevents * the first colon from being taken as a port separator by pmNewContext * and does no harm otherwise. */ ctxhost = malloc(strlen(host) + 2 + 1); if (ctxhost == NULL) { sts = -ENOMEM; goto ctxErr; } sprintf(ctxhost, "[%s]", host); ctx = pmNewContext(PM_CONTEXT_HOST, ctxhost); free(ctxhost); if (ctx < 0) return ctx; if ((sts = pmLookupName(1, namelist, &pmid)) < 0) goto ctxErr; if ((sts = pmLookupDesc(pmid, &desc)) < 0) goto ctxErr; if ((sts = pmFetch(1, &pmid, &res) < 0)) goto ctxErr; if ((sts = numval = res->vset[0]->numval) < 0) goto resErr; j = 0; if (numval) { if (resize_logports(findone ? 1 : numval) < 0) { sts = -oserror(); goto resErr; } /* scan the pmResult, copying matching pid(s) to logport */ for (i = j = 0; i < numval; i++) { __pmLogPort *p = &logport[j]; pmValue *vp = &res->vset[0]->vlist[i]; if (vp->inst == 1) /* old vcr instance (pseudo-init) */ continue; if (findone && vp->inst != pid) continue; p->pid = vp->inst; p->port = vp->value.lval; sts = pmNameInDom(desc.indom, p->pid, &p->name); if (sts < 0) { p->name = NULL; goto resErr; } j++; if (findone) /* found one, stop searching */ break; } *lpp = logport; } sts = j; /* the number actually added */ resErr: pmFreeResult(res); ctxErr: if (oldctx >= 0) pmUseContext(oldctx); if (ctx >= 0) pmDestroyContext(ctx); return 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; }
int main(int argc, char **argv) { int c; int i; int sts; int errflag = 0; int type = 0; int verbose = 0; char *host = NULL; /* pander to gcc */ int mode = PM_MODE_INTERP; /* mode for archives */ char *configfile = NULL; char *start = NULL; char *finish = NULL; char *align = NULL; char *offset = NULL; char *logfile = NULL; pmLogLabel label; /* get hostname for archives */ int zflag = 0; /* for -z */ char *tz = NULL; /* for -Z timezone */ int tzh; /* initial timezone handle */ char local[MAXHOSTNAMELEN]; char *pmnsfile = PM_NS_DEFAULT; int samples = -1; double delta = 1.0; char *endnum; struct timeval startTime; struct timeval endTime; struct timeval appStart; struct timeval appEnd; struct timeval appOffset; pmSetProgname(argv[0]); while ((c = getopt(argc, argv, "a:A:c:D:h:l:Ln:O:s:S:t:T:U:VzZ:?")) != EOF) { switch (c) { case 'a': /* archive name */ if (type != 0) { fprintf(stderr, "%s: at most one of -a, -h, -L and -U allowed\n", pmGetProgname()); errflag++; } type = PM_CONTEXT_ARCHIVE; host = optarg; break; case 'A': /* time alignment */ align = optarg; break; case 'c': /* configfile */ if (configfile != NULL) { fprintf(stderr, "%s: at most one -c option allowed\n", pmGetProgname()); errflag++; } configfile = optarg; break; case 'D': /* debug options */ sts = pmSetDebug(optarg); if (sts < 0) { fprintf(stderr, "%s: unrecognized debug options specification (%s)\n", pmGetProgname(), optarg); errflag++; } break; case 'h': /* contact PMCD on this hostname */ if (type != 0) { fprintf(stderr, "%s: at most one of -a, -h, -L and -U allowed\n", pmGetProgname()); errflag++; } host = optarg; type = PM_CONTEXT_HOST; break; case 'L': /* LOCAL, no PMCD */ if (type != 0) { fprintf(stderr, "%s: at most one of -a, -h, -L and -U allowed\n", pmGetProgname()); errflag++; } host = NULL; type = PM_CONTEXT_LOCAL; putenv("PMDA_LOCAL_PROC="); /* if proc PMDA needed */ putenv("PMDA_LOCAL_SAMPLE="); /* if sampledso PMDA needed */ break; case 'l': /* logfile */ logfile = optarg; break; case 'n': /* alternative name space file */ pmnsfile = optarg; break; case 'O': /* sample offset time */ offset = optarg; break; case 's': /* sample count */ samples = (int)strtol(optarg, &endnum, 10); if (*endnum != '\0' || samples < 0) { fprintf(stderr, "%s: -s requires numeric argument\n", pmGetProgname()); errflag++; } break; case 'S': /* start time */ start = optarg; break; case 't': /* delta seconds (double) */ delta = strtod(optarg, &endnum); if (*endnum != '\0' || delta <= 0.0) { fprintf(stderr, "%s: -t requires floating point argument\n", pmGetProgname()); errflag++; } break; case 'T': /* terminate time */ finish = optarg; break; case 'U': /* uninterpolated archive log */ if (type != 0) { fprintf(stderr, "%s: at most one of -a, -h, -L and -U allowed\n", pmGetProgname()); errflag++; } type = PM_CONTEXT_ARCHIVE; mode = PM_MODE_FORW; host = optarg; break; case 'V': /* verbose */ verbose++; break; case 'z': /* timezone from host */ if (tz != NULL) { fprintf(stderr, "%s: at most one of -Z and/or -z allowed\n", pmGetProgname()); errflag++; } zflag++; break; case 'Z': /* $TZ timezone */ if (zflag) { fprintf(stderr, "%s: at most one of -Z and/or -z allowed\n", pmGetProgname()); errflag++; } tz = optarg; break; case '?': default: errflag++; break; } } if (zflag && type == 0) { fprintf(stderr, "%s: -z requires an explicit -a, -h or -U option\n", pmGetProgname()); errflag++; } if (errflag) { fprintf(stderr, "Usage: %s options ...\n\ \n\ Options\n\ -a archive metrics source is an archive log\n\ -A align time alignment\n\ -c configfile file to load configuration from\n\ -D debug standard PCP debug options\n\ -h host metrics source is PMCD on host\n\ -l logfile redirect diagnostics and trace output\n\ -L use local context instead of PMCD\n\ -n pmnsfile use an alternative PMNS\n\ -O offset offset sample time\n\ -s samples terminate after this many iterations\n\ -S start start at this time\n\ -t delta sample interval in seconds(float) [default 1.0]\n\ -T finish finish at this time\n\ -U archive metrics source is an uninterpolated archive log\n\ -V verbose/diagnostic output\n\ -z set reporting timezone to local time for host from -a, -h or -U\n\ -Z timezone set reporting timezone\n", pmGetProgname()); exit(1); } if (logfile != NULL) { pmOpenLog(pmGetProgname(), logfile, stderr, &sts); if (sts < 0) { fprintf(stderr, "%s: Could not open logfile \"%s\"\n", pmGetProgname(), logfile); } } if (pmnsfile != PM_NS_DEFAULT && (sts = pmLoadNameSpace(pmnsfile)) < 0) { printf("%s: Cannot load namespace from \"%s\": %s\n", pmGetProgname(), pmnsfile, pmErrStr(sts)); exit(1); } if (type == 0) { type = PM_CONTEXT_HOST; gethostname(local, sizeof(local)); host = local; } if ((sts = pmNewContext(type, host)) < 0) { if (type == PM_CONTEXT_HOST) fprintf(stderr, "%s: Cannot connect to PMCD on host \"%s\": %s\n", pmGetProgname(), host, pmErrStr(sts)); else fprintf(stderr, "%s: Cannot open archive \"%s\": %s\n", pmGetProgname(), host, pmErrStr(sts)); exit(1); } if (type == PM_CONTEXT_ARCHIVE) { if ((sts = pmGetArchiveLabel(&label)) < 0) { fprintf(stderr, "%s: Cannot get archive label record: %s\n", pmGetProgname(), pmErrStr(sts)); exit(1); } if (mode != PM_MODE_INTERP) { if ((sts = pmSetMode(mode, &label.ll_start, 0)) < 0) { fprintf(stderr, "%s: pmSetMode: %s\n", pmGetProgname(), pmErrStr(sts)); exit(1); } } startTime = label.ll_start; sts = pmGetArchiveEnd(&endTime); if (sts < 0) { fprintf(stderr, "%s: pmGetArchiveEnd: %s\n", pmGetProgname(), pmErrStr(sts)); exit(1); } } else { gettimeofday(&startTime, NULL); endTime.tv_sec = INT_MAX; } if (zflag) { if ((tzh = pmNewContextZone()) < 0) { fprintf(stderr, "%s: Cannot set context timezone: %s\n", pmGetProgname(), pmErrStr(tzh)); exit(1); } if (type == PM_CONTEXT_ARCHIVE) printf("Note: timezone set to local timezone of host \"%s\" from archive\n\n", label.ll_hostname); else printf("Note: timezone set to local timezone of host \"%s\"\n\n", host); } else if (tz != NULL) { if ((tzh = pmNewZone(tz)) < 0) { fprintf(stderr, "%s: Cannot set timezone to \"%s\": %s\n", pmGetProgname(), tz, pmErrStr(tzh)); exit(1); } printf("Note: timezone set to \"TZ=%s\"\n\n", tz); } else tzh = pmNewContextZone(); /* non-flag args are argv[optind] ... argv[argc-1] */ while (optind < argc) { printf("extra argument[%d]: %s\n", optind, argv[optind]); optind++; } if (align != NULL && type != PM_CONTEXT_ARCHIVE) { fprintf(stderr, "%s: -A option only supported for PCP archives, alignment request ignored\n", pmGetProgname()); align = NULL; } sts = pmParseTimeWindow(start, finish, align, offset, &startTime, &endTime, &appStart, &appEnd, &appOffset, &endnum); if (sts < 0) { fprintf(stderr, "%s: %s\n", pmGetProgname(), endnum); exit(1); } if ((sts = pmLookupName(2, namelist, pmidlist)) < 0) { fprintf(stderr, "%s: pmLookupName failed: %s\n", pmGetProgname(), pmErrStr(sts)); exit(1); } /* goto the start */ if ((sts = pmSetMode(PM_MODE_INTERP, &appStart, (int)(delta * 1000))) < 0) { fprintf(stderr, "%s: pmSetMode failed: %s\n", pmGetProgname(), pmErrStr(sts)); exit(1); } pmCtime(&appStart.tv_sec, timebuf); printf("archive %s\nstartTime: %19.19s.%06d\n", host, timebuf, (int)appStart.tv_usec); pmCtime(&appEnd.tv_sec, timebuf); printf("endTime : %19.19s.%06d\nsamples=%d delta=%dms\n", timebuf, (int)appEnd.tv_usec, samples, (int)(delta * 1000)); /* play forwards over the mark */ for (i=0; i < samples; i++) { if ((sts = pmFetch(2, pmidlist, &result)) < 0) { fprintf(stderr, "%s: pmFetch failed: %s\n", pmGetProgname(), pmErrStr(sts)); exit(1); } check_result("forwards ", result); curpos = result->timestamp; /* struct cpy */ pmFreeResult(result); } /* rewind back over the mark */ if ((sts = pmSetMode(PM_MODE_INTERP, &curpos, (int)(delta * -1000))) < 0) { fprintf(stderr, "%s: pmSetMode failed: %s\n", pmGetProgname(), pmErrStr(sts)); exit(1); } for (i=0; i < samples; i++) { if ((sts = pmFetch(2, pmidlist, &result)) < 0) { fprintf(stderr, "%s: pmFetch failed: %s\n", pmGetProgname(), pmErrStr(sts)); exit(1); } check_result("rewinding", result); pmFreeResult(result); } return 0; }
static void foo(FILE *f, char *fn, int i, void *closure) { int sts; int numnames; int j; int leaf; pmID pmids[NMETRIC]; char **names; char *name; int *stsset; char strbuf[20]; if ((sts = pmLookupName(NMETRIC-i, &namelist[i], pmids)) < 0) { if (sts != PM_ERR_NONLEAF) { fprintf(f, "%s: %s ...: pmLookupName Error: %s\n", fn, namelist[i], pmErrStr(sts)); pthread_exit("botch"); } } for (j = i; j < NMETRIC; j++) { if (pmids[j-i] != pmidlist[j]) { fprintf(f, "%s: %s: Botch: expecting %s", fn, namelist[j], pmIDStr_r(pmidlist[j], strbuf, sizeof(strbuf))); fprintf(f, ", got %s\n", pmIDStr_r(pmids[j-i], strbuf, sizeof(strbuf))); pthread_exit("botch"); } } fprintf(f, "%s: %s ... pmLookupName OK\n", fn, namelist[i]); fprintf(f, "%s: %s", fn, namelist[i]); if (pmidlist[i] != PM_ID_NULL) { /* leaf node in PMNS */ if ((numnames = pmNameAll(pmidlist[i], &names)) < 0) { fprintf(f, "\n%s: %s ...: pmNameAll Error: %s\n", fn, namelist[i], pmErrStr(numnames)); pthread_exit("botch"); } for (j = 0; j < numnames; j++) { if (strcmp(names[j], namelist[i]) == 0) break; } if (j == numnames) { fprintf(f, "\n%s: %s: Botch: expecting %s, got {", fn, pmIDStr_r(pmidlist[i], strbuf, sizeof(strbuf)), namelist[i]); __pmPrintMetricNames(f, numnames, names, ","); fprintf(f, "}\n"); pthread_exit("botch"); } fprintf(f, " pmNameAll OK"); if ((sts = pmNameID(pmidlist[i], &name)) < 0) { fprintf(f, "\n%s: %s ...: pmNameID Error: %s\n", fn, namelist[i], pmErrStr(sts)); pthread_exit("botch"); } for (j = 0; j < numnames; j++) { if (strcmp(name, names[j]) == 0) break; } if (j == numnames) { fprintf(f, "\n%s: %s: Botch: expecting one of {", fn, pmIDStr_r(pmidlist[i], strbuf, sizeof(strbuf))); __pmPrintMetricNames(f, numnames, names, ","); fprintf(f, "}, got %s\n", name); pthread_exit("botch"); } free(names); free(name); fprintf(f, " pmNameID OK"); } else { /* non-leaf node in PMNS */ int keep = 0; if ((sts = pmGetChildrenStatus(namelist[i], &names, &stsset)) < 0) { fprintf(f, "\n%s: %s ...: pmGetChildrenStatus Error: %s\n", fn, namelist[i], pmErrStr(sts)); pthread_exit("botch"); } leaf = 0; for (j = 0; j < sts; j++) { if (stsset[j] == PMNS_LEAF_STATUS) leaf++; } PM_LOCK(chn_lock); if (leaf_chn[i] == -1) { leaf_chn[i] = leaf; nonleaf_chn[i] = sts - leaf; chn[i] = names; keep = 1; } else { if (leaf != leaf_chn[i] || sts - leaf != nonleaf_chn[i]) { fprintf(f, "\n%s: %s: Botch: expecting %d leaf & %d non-leaf, got %d leaf & %d non-leaf\n", fn, namelist[i], leaf_chn[i], nonleaf_chn[i], leaf, sts - leaf); pthread_exit("botch"); } for (j = 0; j < sts; j++) { if (strcmp(chn[i][j], names[j]) != 0) { fprintf(f, "\n%s: %s: Botch: child[%d] expecting %s, got %s\n", fn, namelist[i], j, chn[i][j], names[j]); PM_UNLOCK(chn_lock); pthread_exit("botch"); } } } if (keep == 0) { free(names); names = NULL; /* silence coverity */ } free(stsset); fprintf(f, " pmGetChildrenStatus OK"); if ((sts = pmGetChildren(namelist[i], &names)) < 0) { fprintf(f, "\n%s: %s ...: pmGetChildren Error: %s\n", fn, namelist[i], pmErrStr(sts)); PM_UNLOCK(chn_lock); pthread_exit("botch"); } if (sts != leaf_chn[i] + nonleaf_chn[i]) { fprintf(f, "\n%s: %s: Botch: expecting %d children, got %d\n", fn, namelist[i], leaf_chn[i] + nonleaf_chn[i], sts); PM_UNLOCK(chn_lock); pthread_exit("botch"); } for (j = 0; j < sts; j++) { if (strcmp(chn[i][j], names[j]) != 0) { fprintf(f, "\n%s: %s: Botch: child[%d] expecting %s, got %s\n", fn, namelist[i], j, chn[i][j], names[j]); PM_UNLOCK(chn_lock); pthread_exit("botch"); } } PM_UNLOCK(chn_lock); free(names); fprintf(f, " pmGetChildren OK"); *((int *)closure) = 0; if ((sts = pmTraversePMNS_r(namelist[i], dometric, closure)) < 0) { fprintf(f, "\n%s: %s ...: pmTraversePMNS_r Error: %s\n", fn, namelist[i], pmErrStr(sts)); pthread_exit("botch"); } if (sum_traverse[i] != *((int *)closure)) { fprintf(f, "\n%s: %s: Botch: sum strlen(descendent names) expecting %d, got %d\n", fn, namelist[i], sum_traverse[i], *((int *)closure)); pthread_exit("botch"); } fprintf(f, " pmTraversePMNS_r OK"); } fputc('\n', f); }
int main(int argc, char **argv) { pthread_t tid1; pthread_t tid2; pthread_t tid3; int sts; char *msg; int errflag = 0; int c; int i; pmSetProgname(argv[0]); while ((c = getopt(argc, argv, "D:")) != EOF) { switch (c) { case 'D': /* debug options */ sts = pmSetDebug(optarg); if (sts < 0) { fprintf(stderr, "%s: unrecognized debug options specification (%s)\n", pmGetProgname(), optarg); errflag++; } break; case '?': default: errflag++; break; } } if (errflag || optind == argc || argc-optind > 3) { fprintf(stderr, "Usage: %s [-D...] host1 [host2 [host3]]\n", pmGetProgname()); exit(1); } ctx1 = pmNewContext(PM_CONTEXT_HOST, argv[optind]); if (ctx1 < 0) { printf("Error: pmNewContext(%s) -> %s\n", argv[optind], pmErrStr(ctx1)); exit(1); } optind++; if (optind < argc) { ctx2 = pmNewContext(PM_CONTEXT_HOST, argv[optind]); if (ctx2 < 0) { printf("Error: pmNewContext(%s) -> %s\n", argv[optind], pmErrStr(ctx2)); exit(1); } optind++; } else ctx2 = ctx1; if (optind < argc) { ctx3 = pmNewContext(PM_CONTEXT_HOST, argv[optind]); if (ctx3 < 0) { printf("Error: pmNewContext(%s) -> %s\n", argv[optind], pmErrStr(ctx2)); exit(1); } optind++; } else ctx3 = ctx2; sts = pmLookupName(NMETRIC, namelist, pmidlist); if (sts != NMETRIC) { if (sts < 0) printf("Warning: pmLookupName -> %s\n", pmErrStr(sts)); else printf("Warning: pmLookupName returned %d, expected %d\n", sts, (int)(NMETRIC)); for (i = 0; i < NMETRIC; i++) { printf(" %s -> %s", namelist[i], pmIDStr(pmidlist[i])); if (pmidlist[i] == PM_ID_NULL) { sts = pmLookupName(1, &namelist[i], &pmidlist[i]); printf(": %s", pmErrStr(sts)); } putchar('\n'); } } for (i = 0; i < NMETRIC; i++) { if (pmidlist[i] != PM_ID_NULL) { if ((sts = pmLookupDesc(pmidlist[i], &desclist[i])) < 0) { printf("Error: pmLookupDesc(%s) -> %s\n", namelist[i], pmErrStr(sts)); exit(1); } } chn[i] = NULL; leaf_chn[i] = nonleaf_chn[i] = -1; } sts = pthread_barrier_init(&barrier, NULL, 3); if (sts != 0) { printf("pthread_barrier_init: sts=%d\n", sts); exit(1); } sts = pthread_create(&tid1, NULL, func1, NULL); if (sts != 0) { printf("thread_create: tid1: sts=%d\n", sts); exit(1); } sts = pthread_create(&tid2, NULL, func2, NULL); if (sts != 0) { printf("thread_create: tid2: sts=%d\n", sts); exit(1); } sts = pthread_create(&tid3, NULL, func3, NULL); if (sts != 0) { printf("thread_create: tid3: sts=%d\n", sts); exit(1); } pthread_join(tid1, (void *)&msg); if (msg != NULL) printf("tid1: %s\n", msg); pthread_join(tid2, (void *)&msg); if (msg != NULL) printf("tid2: %s\n", msg); pthread_join(tid3, (void *)&msg); if (msg != NULL) printf("tid3: %s\n", msg); exit(0); }
/* * Called when an error PDU containing PMCD_ADD_AGENT is received. * This function checks all of the configured metrics to make sure that * they have not changed. For example due to a PMDA being replaced by an * updated version */ void validate_metrics(void) { const task_t *tp; pmID *new_pmids; const pmDesc *old_desc; pmDesc new_desc; int index; int error; int sts; time_t now; char buf1[20], buf2[20]; time(&now); fprintf(stderr, "%s: Validating metrics after PMCD state changed at %s", pmProgname, ctime(&now)); /* * Check each metric in each element of the task list, whether it is * active or not. */ error = 0; for (tp = tasklist; tp != NULL; tp = tp->t_next) { /* We need at least one metric to look up. */ if (tp->t_numpmid < 1) continue; /* * Perform a bulk lookup and then check for consistency. * Lookup the metrics by name, since that's the way they are * specified in the pmlogger config file. * We need a temporary array for the new pmIDs */ new_pmids = malloc(tp->t_numpmid * sizeof(*tp->t_pmidlist)); if (new_pmids == NULL) { __pmNoMem("allocating pmID array for validating metrice", tp->t_numpmid * sizeof(*tp->t_pmidlist), PM_FATAL_ERR); } if ((sts = pmLookupName(tp->t_numpmid, tp->t_namelist, new_pmids)) < 0) { fprintf(stderr, "Error looking up metrics: Reason: %s\n", pmErrStr(sts)); exit(1); } /* Now check the individual metrics for problems. */ for (index = 0; index < tp->t_numpmid; ++index) { /* If there was an error looking up this metric, try again in order * to obtain the reason. If there is no error the second time * (possible), then the needed pmID will be fetched. */ if (new_pmids[index] == PM_ID_NULL) { if ((sts = pmLookupName(1, &tp->t_namelist[index], &new_pmids[index])) < 0) { /* The lookup of the metric is still in error. */ fprintf(stderr, "Error looking up %s: Reason: %s\n", tp->t_namelist[index], pmErrStr(sts)); ++error; continue; } /* No error the second time. Fall through */ } /* * Check that the pmid, type, semantics, instance domain and units * of the metric have not changed. */ if (new_pmids[index] != tp->t_pmidlist[index]) { fprintf(stderr, "PMID of metric \"%s\" has changed from %s to %s\n", tp->t_namelist[index], pmIDStr_r(tp->t_pmidlist[index], buf1, sizeof(buf1)), pmIDStr_r(new_pmids[index], buf2, sizeof(buf2))); ++error; } if ((sts = pmLookupDesc(new_pmids[index], &new_desc)) < 0) { fprintf(stderr, "Description unavailable for metric \"%s\": %s\n", tp->t_namelist[index], pmErrStr(sts)); ++error; continue; } old_desc = &tp->t_desclist[index]; if (new_desc.type != old_desc->type) { fprintf(stderr, "Type of metric \"%s\" has changed from %s to %s\n", tp->t_namelist[index], pmTypeStr_r(old_desc->type, buf1, sizeof(buf1)), pmTypeStr_r(new_desc.type, buf2, sizeof(buf2))); ++error; } if (new_desc.sem != old_desc->sem) { fprintf(stderr, "Semantics of metric \"%s\" have changed from %s to %s\n", tp->t_namelist[index], pmSemStr_r(old_desc->sem, buf1, sizeof(buf1)), pmSemStr_r(new_desc.sem, buf2, sizeof(buf2))); ++error; } if (new_desc.indom != old_desc->indom) { fprintf(stderr, "Instance domain of metric \"%s\" has changed from %s to %s\n", tp->t_namelist[index], pmInDomStr_r(old_desc->indom, buf1, sizeof(buf1)), pmInDomStr_r(new_desc.indom, buf2, sizeof(buf2))); ++error; } if (new_desc.units.dimSpace != old_desc->units.dimSpace || new_desc.units.dimTime != old_desc->units.dimTime || new_desc.units.dimCount != old_desc->units.dimCount || new_desc.units.scaleSpace != old_desc->units.scaleSpace || new_desc.units.scaleTime != old_desc->units.scaleTime || new_desc.units.scaleCount != old_desc->units.scaleCount) { ++error; fprintf(stderr, "Units of metric \"%s\" has changed from %s to %s\n", tp->t_namelist[index], pmUnitsStr_r(&old_desc->units, buf1, sizeof(buf1)), pmUnitsStr_r(&new_desc.units, buf2, sizeof(buf2))); } } /* loop over metrics */ free(new_pmids); } /* Loop over task list */ /* We cannot continue, if any of the metrics have changed. */ if (error) { fprintf(stderr, "One or more configured metrics have changed after pmcd state change. Exiting\n"); exit(1); } }
static void func(void) { int sts; char **children; char *p; if ((sts = pmUseContext(ctx)) < 0) { printf("pmUseContext(%d): %s\n", ctx, pmErrStr(sts)); pthread_exit(NULL); } /* * expect this to fail for the second thread through when * using PM_CONTEXT_LOCAL */ if ((sts = pmDupContext()) < 0) printf("pmDupContext: %s\n", pmErrStr(sts)); else printf("pmDupContext: -> %d\n", sts); if ((sts = pmUseContext(ctx)) < 0) { printf("pmUseContext(%d): %s\n", ctx, pmErrStr(sts)); pthread_exit(NULL); } else printf("pmUseContext(%d) -> %d\n", ctx, sts); if ((sts = pmLookupName(1, namelist, pmidlist)) < 0) printf("pmLookupName: %s\n", pmErrStr(sts)); else printf("pmLookupName: -> %s\n", pmIDStr(pmidlist[0])); pthread_barrier_wait(&barrier); if (pmidlist[0] == 0) pthread_exit("Loser failed to get pmid!"); if ((sts = pmGetPMNSLocation()) < 0) printf("pmGetPMNSLocation: %s\n", pmErrStr(sts)); else printf("pmGetPMNSLocation: -> %d\n", sts); /* leaf node, expect no children */ if ((sts = pmGetChildrenStatus(namelist[0], &children, NULL)) < 0) printf("pmGetChildrenStatus: %s\n", pmErrStr(sts)); else printf("pmGetChildrenStatus: -> %d\n", sts); if ((sts = pmLookupDesc(pmidlist[0], &desc)) < 0) printf("pmLookupDesc: %s\n", pmErrStr(sts)); else printf("pmLookupDesc: -> %s type=%s indom=%s\n", pmIDStr(desc.pmid), pmTypeStr(desc.type), pmInDomStr(desc.indom)); pthread_barrier_wait(&barrier); if (desc.pmid == 0) pthread_exit("Loser failed to get pmDesc!"); if ((sts = pmLookupText(pmidlist[0], PM_TEXT_ONELINE, &p)) < 0) printf("pmLookupText: %s\n", pmErrStr(sts)); else printf("pmLookupText: -> %s\n", p); if ((sts = pmGetInDom(desc.indom, &instance, &instname)) < 0) printf("pmGetInDom: %s: %s\n", pmInDomStr(desc.indom), pmErrStr(sts)); else printf("pmGetInDom: -> %d\n", sts); pthread_barrier_wait(&barrier); if (instance == NULL) pthread_exit("Loser failed to get indom!"); if ((sts = pmNameInDom(desc.indom, instance[0], &p)) < 0) printf("pmNameInDom: %s\n", pmErrStr(sts)); else printf("pmNameInDom: %d -> %s\n", instance[0], p); if ((sts = pmLookupInDom(desc.indom, instname[0])) < 0) printf("pmLookupInDom: %s\n", pmErrStr(sts)); else printf("pmLookupInDom: %s -> %d\n", instname[0], sts); if ((sts = pmFetch(1, pmidlist, &rp)) < 0) printf("pmFetch: %s\n", pmErrStr(sts)); else printf("pmFetch: -> OK\n"); pthread_barrier_wait(&barrier); if (rp == NULL) pthread_exit("Loser failed to get pmResult!"); if ((sts = pmStore(rp)) < 0) printf("pmStore: %s\n", pmErrStr(sts)); else printf("pmStore: -> OK\n"); pthread_exit(NULL); }
int main(int argc, char **argv) { pthread_t tid1; pthread_t tid2; pthread_t tid3; int sts; char *msg; int errflag = 0; int c; __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 || optind == argc || argc-optind > 3) { fprintf(stderr, "Usage: %s [-D...] host1 [host2 [host3]]\n", pmProgname); exit(1); } ctx1 = pmNewContext(PM_CONTEXT_HOST, argv[optind]); if (ctx1 < 0) { printf("Error: pmNewContext(%s) -> %s\n", argv[optind], pmErrStr(ctx1)); exit(1); } optind++; if (optind < argc) { ctx2 = pmNewContext(PM_CONTEXT_HOST, argv[optind]); if (ctx2 < 0) { printf("Error: pmNewContext(%s) -> %s\n", argv[optind], pmErrStr(ctx2)); exit(1); } optind++; } else ctx2 = ctx1; if (optind < argc) { ctx3 = pmNewContext(PM_CONTEXT_HOST, argv[optind]); if (ctx3 < 0) { printf("Error: pmNewContext(%s) -> %s\n", argv[optind], pmErrStr(ctx2)); exit(1); } optind++; } else ctx3 = ctx2; sts = pmLookupName(NMETRIC, namelist, pmidlist); if (sts != NMETRIC) { int i; printf("Error: pmLookupName -> %s\n", pmErrStr(sts)); for (i = 0; i < NMETRIC; i++) { printf(" %s -> %s\n", namelist[i], pmIDStr(pmidlist[i])); } exit(1); } sts = pthread_barrier_init(&barrier, NULL, 3); if (sts != 0) { printf("pthread_barrier_init: sts=%d\n", sts); exit(1); } sts = pthread_create(&tid1, NULL, func1, NULL); if (sts != 0) { printf("thread_create: tid1: sts=%d\n", sts); exit(1); } sts = pthread_create(&tid2, NULL, func2, NULL); if (sts != 0) { printf("thread_create: tid2: sts=%d\n", sts); exit(1); } sts = pthread_create(&tid3, NULL, func3, NULL); if (sts != 0) { printf("thread_create: tid3: sts=%d\n", sts); exit(1); } pthread_join(tid1, (void *)&msg); if (msg != NULL) printf("tid1: %s\n", msg); pthread_join(tid2, (void *)&msg); if (msg != NULL) printf("tid2: %s\n", msg); pthread_join(tid3, (void *)&msg); if (msg != NULL) printf("tid3: %s\n", msg); pthread_cancel(tid1); pthread_cancel(tid2); pthread_cancel(tid3); exit(0); }
/* * Determine the hostname associated with the given context. */ char * pmGetContextHostName_r(int ctxid, char *buf, int buflen) { __pmContext *ctxp; char *name; pmID pmid; pmResult *resp; int original; int sts; buf[0] = '\0'; if ((ctxp = __pmHandleToPtr(ctxid)) != NULL) { switch (ctxp->c_type) { case PM_CONTEXT_HOST: /* * Try and establish the hostname from PMCD (possibly remote). * Do not nest the successive actions. That way, if any one of * them fails, we take the default. * Note: we must *temporarily* switch context (see pmUseContext) * in the host case, then switch back afterward. We already hold * locks and have validated the context pointer, so we do a mini * context switch, then switch back. */ if (pmDebug & DBG_TRACE_CONTEXT) fprintf(stderr, "pmGetContextHostName_r context(%d) -> 0\n", ctxid); original = PM_TPD(curcontext); PM_TPD(curcontext) = ctxid; name = "pmcd.hostname"; sts = pmLookupName(1, &name, &pmid); if (sts >= 0) sts = pmFetch(1, &pmid, &resp); if (pmDebug & DBG_TRACE_CONTEXT) fprintf(stderr, "pmGetContextHostName_r reset(%d) -> 0\n", original); PM_TPD(curcontext) = original; if (sts >= 0) { if (resp->vset[0]->numval > 0) { /* pmcd.hostname present */ strncpy(buf, resp->vset[0]->vlist[0].value.pval->vbuf, buflen); pmFreeResult(resp); break; } pmFreeResult(resp); /* FALLTHROUGH */ } /* * We could not get the hostname from PMCD. If the name in the * context structure is a filesystem path (AF_UNIX address) or * 'localhost', then use gethostname(). Otherwise, use the name * from the context structure. */ name = ctxp->c_pmcd->pc_hosts[0].name; if (!name || name[0] == __pmPathSeparator() || /* AF_UNIX */ (strncmp(name, "localhost", 9) == 0)) /* localhost[46] */ gethostname(buf, buflen); else strncpy(buf, name, buflen-1); break; case PM_CONTEXT_LOCAL: gethostname(buf, buflen); break; case PM_CONTEXT_ARCHIVE: strncpy(buf, ctxp->c_archctl->ac_log->l_label.ill_hostname, buflen-1); break; } buf[buflen-1] = '\0'; PM_UNLOCK(ctxp->c_lock); } return buf; }
int main(int argc, char **argv) { int type = PM_CONTEXT_HOST; int c; int sts; int errflag = 0; char *host = "localhost"; static char *usage = "[-D N] [-h hostname] metric stringvalue"; int len; int n; char *namelist[1]; pmID pmidlist[1]; pmResult *res; __pmSetProgname(argv[0]); while ((c = getopt(argc, argv, "D:h:")) != EOF) { switch (c) { #ifdef PCP_DEBUG 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; #endif case 'h': /* hostname for PMCD to contact */ host = optarg; break; case '?': default: errflag++; break; } } if (errflag || optind != argc-2) { printf("Usage: %s %s\n", pmProgname, usage); exit(1); } if ((sts = pmNewContext(type, host)) < 0) { printf("%s: Cannot connect to PMCD on host \"%s\": %s\n", pmProgname, host, pmErrStr(sts)); exit(1); } namelist[0] = argv[optind]; n = pmLookupName(1, namelist, pmidlist); if (n < 0 || pmidlist[0] == PM_ID_NULL) { printf("pmLookupName: %s\n", pmErrStr(n)); exit(1); } if ((n = pmFetch(1, pmidlist, &res)) < 0) { printf("pmFetch: %s\n", pmErrStr(n)); exit(1); } /* * expecting one value and a pmValueBlock with a type * of PM_TYPE_AGGREGATE */ if (res->vset[0]->numval != 1) { printf("Expecting numval 1, found %d\n", res->vset[0]->numval); __pmDumpResult(stdout, res); exit(1); } if (res->vset[0]->valfmt == PM_VAL_INSITU) { printf("Not expecing PM_VAL_INSITU\n"); __pmDumpResult(stdout, res); exit(1); } if (res->vset[0]->vlist[0].value.pval->vtype != PM_TYPE_AGGREGATE) { printf("Not expecing type %s\n", pmTypeStr(res->vset[0]->vlist[0].value.pval->vtype)); __pmDumpResult(stdout, res); exit(1); } printf("%s old value: ", namelist[0]); pmPrintValue(stdout, res->vset[0]->valfmt, res->vset[0]->vlist[0].value.pval->vtype, &res->vset[0]->vlist[0], 0); /* * old value is probably from a pinned PDU buffer ... don't free * and accept small mem leak here */ len = strlen(argv[optind+1]); res->vset[0]->vlist[0].value.pval = (pmValueBlock *)malloc(len + PM_VAL_HDR_SIZE); res->vset[0]->vlist[0].value.pval->vtype = PM_TYPE_AGGREGATE; res->vset[0]->vlist[0].value.pval->vlen = len + PM_VAL_HDR_SIZE; memcpy(res->vset[0]->vlist[0].value.pval->vbuf, argv[optind+1], len); if ((n = pmStore(res)) < 0) { printf("pmStore: %s\n", pmErrStr(n)); exit(1); } pmFreeResult(res); if ((n = pmFetch(1, pmidlist, &res)) < 0) { printf("pmFetch again: %s\n", pmErrStr(n)); exit(1); } printf(" new value: "); pmPrintValue(stdout, res->vset[0]->valfmt, res->vset[0]->vlist[0].value.pval->vtype, &res->vset[0]->vlist[0], 0); putchar('\n'); pmFreeResult(res); exit(0); }
int main(int argc, char **argv) { int c; int sts; int sep = __pmPathSeparator(); int use_localtime = 0; int isdaemon = 0; char *pmnsfile = PM_NS_DEFAULT; char *username; char *logfile = "pmlogger.log"; /* default log (not archive) file name */ char *endnum; int i; task_t *tp; optcost_t ocp; __pmFdSet readyfds; char *p; char *runtime = NULL; int ctx; /* handle corresponding to ctxp below */ __pmContext *ctxp; /* pmlogger has just this one context */ int niter; pid_t target_pid = 0; __pmGetUsername(&username); /* * Warning: * If any of the pmlogger options change, make sure the * corresponding changes are made to pmnewlog when pmlogger * options are passed through from the control file */ while ((c = pmgetopt_r(argc, argv, &opts)) != EOF) { switch (c) { case 'c': /* config file */ if (access(opts.optarg, F_OK) == 0) configfile = opts.optarg; else { /* does not exist as given, try the standard place */ char *sysconf = pmGetConfig("PCP_VAR_DIR"); int sz = strlen(sysconf)+strlen("/config/pmlogger/")+strlen(opts.optarg)+1; if ((configfile = (char *)malloc(sz)) == NULL) __pmNoMem("config file name", sz, PM_FATAL_ERR); snprintf(configfile, sz, "%s%c" "config%c" "pmlogger%c" "%s", sysconf, sep, sep, sep, opts.optarg); if (access(configfile, F_OK) != 0) { /* still no good, error handling happens below */ free(configfile); configfile = opts.optarg; } } break; case 'D': /* debug flag */ sts = __pmParseDebug(opts.optarg); if (sts < 0) { pmprintf("%s: unrecognized debug flag specification (%s)\n", pmProgname, opts.optarg); opts.errors++; } else pmDebug |= sts; break; case 'h': /* hostname for PMCD to contact */ pmcd_host_conn = opts.optarg; break; case 'l': /* log file name */ logfile = opts.optarg; break; case 'L': /* linger if not primary logger */ linger = 1; break; case 'm': /* note for port map file */ note = opts.optarg; isdaemon = ((strcmp(note, "pmlogger_check") == 0) || (strcmp(note, "pmlogger_daily") == 0)); break; case 'n': /* alternative name space file */ pmnsfile = opts.optarg; break; case 'p': target_pid = (int)strtol(opts.optarg, &endnum, 10); if (*endnum != '\0') { pmprintf("%s: invalid process identifier (%s)\n", pmProgname, opts.optarg); opts.errors++; } else if (!__pmProcessExists(target_pid)) { pmprintf("%s: PID error - no such process (%d)\n", pmProgname, target_pid); opts.errors++; } break; case 'P': /* this is the primary pmlogger */ primary = 1; isdaemon = 1; break; case 'r': /* report sizes of pmResult records */ rflag = 1; break; case 's': /* exit size */ sts = ParseSize(opts.optarg, &exit_samples, &exit_bytes, &exit_time); if (sts < 0) { pmprintf("%s: illegal size argument '%s' for exit size\n", pmProgname, opts.optarg); opts.errors++; } else if (exit_time.tv_sec > 0) { __pmAFregister(&exit_time, NULL, run_done_callback); } break; case 'T': /* end time */ runtime = opts.optarg; break; case 't': /* change default logging interval */ if (pmParseInterval(opts.optarg, &delta, &p) < 0) { pmprintf("%s: illegal -t argument\n%s", pmProgname, p); free(p); opts.errors++; } break; case 'U': /* run as named user */ username = opts.optarg; isdaemon = 1; break; case 'u': /* flush output buffers after each fetch */ /* * all archive write I/O is unbuffered now, so maintain -u * for backwards compatibility only */ break; case 'v': /* volume switch after given size */ sts = ParseSize(opts.optarg, &vol_switch_samples, &vol_switch_bytes, &vol_switch_time); if (sts < 0) { pmprintf("%s: illegal size argument '%s' for volume size\n", pmProgname, opts.optarg); opts.errors++; } else if (vol_switch_time.tv_sec > 0) { vol_switch_afid = __pmAFregister(&vol_switch_time, NULL, vol_switch_callback); } break; case 'V': archive_version = (int)strtol(opts.optarg, &endnum, 10); if (*endnum != '\0' || archive_version != PM_LOG_VERS02) { pmprintf("%s: -V requires a version number of %d\n", pmProgname, PM_LOG_VERS02); opts.errors++; } break; case 'x': /* recording session control fd */ rsc_fd = (int)strtol(opts.optarg, &endnum, 10); if (*endnum != '\0' || rsc_fd < 0) { pmprintf("%s: -x requires a non-negative numeric argument\n", pmProgname); opts.errors++; } else { time(&rsc_start); } break; case 'y': use_localtime = 1; break; case '?': default: opts.errors++; break; } } if (primary && pmcd_host != NULL) { pmprintf( "%s: -P and -h are mutually exclusive; use -P only when running\n" "%s on the same (local) host as the PMCD to which it connects.\n", pmProgname, pmProgname); opts.errors++; } if (!opts.errors && opts.optind != argc - 1) { pmprintf("%s: insufficient arguments\n", pmProgname); opts.errors++; } if (opts.errors) { pmUsageMessage(&opts); exit(1); } if (rsc_fd != -1 && note == NULL) { /* add default note to indicate running with -x */ static char xnote[10]; snprintf(xnote, sizeof(xnote), "-x %d", rsc_fd); note = xnote; } /* if we are running as a daemon, change user early */ if (isdaemon) __pmSetProcessIdentity(username); __pmOpenLog("pmlogger", logfile, stderr, &sts); if (sts != 1) { fprintf(stderr, "%s: Warning: log file (%s) creation failed\n", pmProgname, logfile); /* continue on ... writing to stderr */ } /* base name for archive is here ... */ archBase = argv[opts.optind]; if (pmcd_host_conn == NULL) pmcd_host_conn = "local:"; /* initialise access control */ if (__pmAccAddOp(PM_OP_LOG_ADV) < 0 || __pmAccAddOp(PM_OP_LOG_MAND) < 0 || __pmAccAddOp(PM_OP_LOG_ENQ) < 0) { fprintf(stderr, "%s: access control initialisation failed\n", pmProgname); exit(1); } if (pmnsfile != PM_NS_DEFAULT) { if ((sts = pmLoadASCIINameSpace(pmnsfile, 1)) < 0) { fprintf(stderr, "%s: Cannot load namespace from \"%s\": %s\n", pmProgname, pmnsfile, pmErrStr(sts)); exit(1); } } if ((ctx = pmNewContext(PM_CONTEXT_HOST, pmcd_host_conn)) < 0) { fprintf(stderr, "%s: Cannot connect to PMCD on host \"%s\": %s\n", pmProgname, pmcd_host_conn, pmErrStr(ctx)); exit(1); } pmcd_host = (char *)pmGetContextHostName(ctx); if (strlen(pmcd_host) == 0) { fprintf(stderr, "%s: pmGetContextHostName(%d) failed\n", pmProgname, ctx); exit(1); } if (rsc_fd == -1) { /* no -x, so register client id with pmcd */ __pmSetClientIdArgv(argc, argv); } /* * discover fd for comms channel to PMCD ... */ if ((ctxp = __pmHandleToPtr(ctx)) == NULL) { fprintf(stderr, "%s: botch: __pmHandleToPtr(%d) returns NULL!\n", pmProgname, ctx); exit(1); } pmcdfd = ctxp->c_pmcd->pc_fd; PM_UNLOCK(ctxp->c_lock); if (configfile != NULL) { if ((yyin = fopen(configfile, "r")) == NULL) { fprintf(stderr, "%s: Cannot open config file \"%s\": %s\n", pmProgname, configfile, osstrerror()); exit(1); } } else { /* **ANY** Lex would read from stdin automagically */ configfile = "<stdin>"; } __pmOptFetchGetParams(&ocp); ocp.c_scope = 1; __pmOptFetchPutParams(&ocp); /* prevent early timer events ... */ __pmAFblock(); if (yyparse() != 0) exit(1); if (configfile != NULL) fclose(yyin); yyend(); #ifdef PCP_DEBUG fprintf(stderr, "Config parsed\n"); #endif fprintf(stderr, "Starting %slogger for host \"%s\" via \"%s\"\n", primary ? "primary " : "", pmcd_host, pmcd_host_conn); #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOG) { fprintf(stderr, "optFetch Cost Parameters: pmid=%d indom=%d fetch=%d scope=%d\n", ocp.c_pmid, ocp.c_indom, ocp.c_fetch, ocp.c_scope); fprintf(stderr, "\nAfter loading config ...\n"); for (tp = tasklist; tp != NULL; tp = tp->t_next) { if (tp->t_numvalid == 0) continue; fprintf(stderr, " state: %sin log, %savail, %s, %s", PMLC_GET_INLOG(tp->t_state) ? "" : "not ", PMLC_GET_AVAIL(tp->t_state) ? "" : "un", PMLC_GET_MAND(tp->t_state) ? "mand" : "adv", PMLC_GET_ON(tp->t_state) ? "on" : "off"); fprintf(stderr, " delta: %ld usec", (long)1000 * tp->t_delta.tv_sec + tp->t_delta.tv_usec); fprintf(stderr, " numpmid: %d\n", tp->t_numpmid); for (i = 0; i < tp->t_numpmid; i++) { fprintf(stderr, " %s (%s):\n", pmIDStr(tp->t_pmidlist[i]), tp->t_namelist[i]); } __pmOptFetchDump(stderr, tp->t_fetch); } } #endif if (!primary && tasklist == NULL && !linger) { fprintf(stderr, "Nothing to log, and not the primary logger instance ... good-bye\n"); exit(1); } if ((sts = __pmLogCreate(pmcd_host, archBase, archive_version, &logctl)) < 0) { fprintf(stderr, "__pmLogCreate: %s\n", pmErrStr(sts)); exit(1); } else { /* * try and establish $TZ from the remote PMCD ... * Note the label record has been set up, but not written yet */ char *name = "pmcd.timezone"; pmID pmid; pmResult *resp; __pmtimevalNow(&epoch); sts = pmUseContext(ctx); if (sts >= 0) sts = pmLookupName(1, &name, &pmid); if (sts >= 0) sts = pmFetch(1, &pmid, &resp); if (sts >= 0) { if (resp->vset[0]->numval > 0) { /* pmcd.timezone present */ strcpy(logctl.l_label.ill_tz, resp->vset[0]->vlist[0].value.pval->vbuf); /* prefer to use remote time to avoid clock drift problems */ epoch = resp->timestamp; /* struct assignment */ if (! use_localtime) pmNewZone(logctl.l_label.ill_tz); } #ifdef PCP_DEBUG else if (pmDebug & DBG_TRACE_LOG) { fprintf(stderr, "main: Could not get timezone from host %s\n", pmcd_host); } #endif pmFreeResult(resp); } } /* do ParseTimeWindow stuff for -T */ if (runtime) { struct timeval res_end; /* time window end */ struct timeval start; struct timeval end; struct timeval last_delta; char *err_msg; /* parsing error message */ time_t now; struct timeval now_tv; time(&now); now_tv.tv_sec = now; now_tv.tv_usec = 0; start = now_tv; end.tv_sec = INT_MAX; end.tv_usec = INT_MAX; sts = __pmParseTime(runtime, &start, &end, &res_end, &err_msg); if (sts < 0) { fprintf(stderr, "%s: illegal -T argument\n%s", pmProgname, err_msg); exit(1); } last_delta = res_end; tsub(&last_delta, &now_tv); __pmAFregister(&last_delta, NULL, run_done_callback); last_stamp = res_end; } fprintf(stderr, "Archive basename: %s\n", archBase); #ifndef IS_MINGW /* detach yourself from the launching process */ if (isdaemon) setpgid(getpid(), 0); #endif /* set up control port */ init_ports(); __pmFD_ZERO(&fds); for (i = 0; i < CFD_NUM; ++i) { if (ctlfds[i] >= 0) __pmFD_SET(ctlfds[i], &fds); } #ifndef IS_MINGW __pmFD_SET(pmcdfd, &fds); #endif if (rsc_fd != -1) __pmFD_SET(rsc_fd, &fds); numfds = maxfd() + 1; if ((sts = do_preamble()) < 0) fprintf(stderr, "Warning: problem writing archive preamble: %s\n", pmErrStr(sts)); sts = 0; /* default exit status */ parse_done = 1; /* enable callback processing */ __pmAFunblock(); for ( ; ; ) { int nready; #ifdef PCP_DEBUG if ((pmDebug & DBG_TRACE_APPL2) && (pmDebug & DBG_TRACE_DESPERATE)) { fprintf(stderr, "before __pmSelectRead(%d,...): run_done_alarm=%d vol_switch_alarm=%d log_alarm=%d\n", numfds, run_done_alarm, vol_switch_alarm, log_alarm); } #endif niter = 0; while (log_alarm && niter++ < 10) { __pmAFblock(); log_alarm = 0; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) fprintf(stderr, "delayed callback: log_alarm\n"); #endif for (tp = tasklist; tp != NULL; tp = tp->t_next) { if (tp->t_alarm) { tp->t_alarm = 0; do_work(tp); } } __pmAFunblock(); } if (vol_switch_alarm) { __pmAFblock(); vol_switch_alarm = 0; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) fprintf(stderr, "delayed callback: vol_switch_alarm\n"); #endif newvolume(VOL_SW_TIME); __pmAFunblock(); } if (run_done_alarm) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) fprintf(stderr, "delayed callback: run_done_alarm\n"); #endif run_done(0, NULL); /*NOTREACHED*/ } __pmFD_COPY(&readyfds, &fds); nready = __pmSelectRead(numfds, &readyfds, NULL); #ifdef PCP_DEBUG if ((pmDebug & DBG_TRACE_APPL2) && (pmDebug & DBG_TRACE_DESPERATE)) { fprintf(stderr, "__pmSelectRead(%d,...) done: nready=%d run_done_alarm=%d vol_switch_alarm=%d log_alarm=%d\n", numfds, nready, run_done_alarm, vol_switch_alarm, log_alarm); } #endif __pmAFblock(); if (nready > 0) { /* handle request on control port */ for (i = 0; i < CFD_NUM; ++i) { if (ctlfds[i] >= 0 && __pmFD_ISSET(ctlfds[i], &readyfds)) { if (control_req(ctlfds[i])) { /* new client has connected */ __pmFD_SET(clientfd, &fds); if (clientfd >= numfds) numfds = clientfd + 1; } } } if (clientfd >= 0 && __pmFD_ISSET(clientfd, &readyfds)) { /* process request from client, save clientfd in case client * closes connection, resetting clientfd to -1 */ int fd = clientfd; if (client_req()) { /* client closed connection */ __pmFD_CLR(fd, &fds); __pmCloseSocket(clientfd); clientfd = -1; numfds = maxfd() + 1; qa_case = 0; } } #ifndef IS_MINGW if (pmcdfd >= 0 && __pmFD_ISSET(pmcdfd, &readyfds)) { /* * do not expect this, given synchronous commumication with the * pmcd ... either pmcd has terminated, or bogus PDU ... or its * Win32 and we are operating under the different conditions of * our AF.c implementation there, which has to deal with a lack * of signal support on Windows - race condition exists between * this check and the async event timer callback. */ __pmPDU *pb; __pmPDUHdr *php; sts = __pmGetPDU(pmcdfd, ANY_SIZE, TIMEOUT_NEVER, &pb); if (sts <= 0) { if (sts < 0) fprintf(stderr, "Error: __pmGetPDU: %s\n", pmErrStr(sts)); disconnect(sts); } else { php = (__pmPDUHdr *)pb; fprintf(stderr, "Error: Unsolicited %s PDU from PMCD\n", __pmPDUTypeStr(php->type)); disconnect(PM_ERR_IPC); } if (sts > 0) __pmUnpinPDUBuf(pb); } #endif if (rsc_fd >= 0 && __pmFD_ISSET(rsc_fd, &readyfds)) { /* * some action on the recording session control fd * end-of-file means launcher has quit, otherwise we * expect one of these commands * V<number>\n - version * F<folio>\n - folio name * P<name>\n - launcher's name * R\n - launcher can replay * D\n - detach from launcher * Q\n - quit pmlogger */ char rsc_buf[MAXPATHLEN]; char *rp = rsc_buf; char myc; int fake_x = 0; for (rp = rsc_buf; ; rp++) { if (read(rsc_fd, &myc, 1) <= 0) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) fprintf(stderr, "recording session control: eof\n"); #endif if (rp != rsc_buf) { *rp = '\0'; fprintf(stderr, "Error: incomplete recording session control message: \"%s\"\n", rsc_buf); } fake_x = 1; break; } if (rp >= &rsc_buf[MAXPATHLEN]) { fprintf(stderr, "Error: absurd recording session control message: \"%100.100s ...\"\n", rsc_buf); fake_x = 1; break; } if (myc == '\n') { *rp = '\0'; break; } *rp = myc; } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) { if (fake_x == 0) fprintf(stderr, "recording session control: \"%s\"\n", rsc_buf); } #endif if (fake_x) do_dialog('X'); else if (strcmp(rsc_buf, "Q") == 0 || strcmp(rsc_buf, "D") == 0 || strcmp(rsc_buf, "?") == 0) do_dialog(rsc_buf[0]); else if (rsc_buf[0] == 'F') folio_name = strdup(&rsc_buf[1]); else if (rsc_buf[0] == 'P') rsc_prog = strdup(&rsc_buf[1]); else if (strcmp(rsc_buf, "R") == 0) rsc_replay = 1; else if (rsc_buf[0] == 'V' && rsc_buf[1] == '0') { /* * version 0 of the recording session control ... * this is all we grok at the moment */ ; } else { fprintf(stderr, "Error: illegal recording session control message: \"%s\"\n", rsc_buf); do_dialog('X'); } } } else if (vol_switch_flag) { newvolume(VOL_SW_SIGHUP); vol_switch_flag = 0; } else if (nready < 0 && neterror() != EINTR) fprintf(stderr, "Error: select: %s\n", netstrerror()); __pmAFunblock(); if (target_pid && !__pmProcessExists(target_pid)) exit(EXIT_SUCCESS); if (exit_code) break; } exit(exit_code); }
static void dometric(const char *name) { int n; pmID pmidlist[] = { PM_ID_NULL }; pmDesc desc; int *instlist = NULL; char **instname = NULL; pmResult *result; extern int pmDebug; _metrics++; /* cast const away as pmLookupName will not modify this string */ if ((n = pmLookupName(1, (char **)&name, pmidlist)) < 0) { printf("%s: pmLookupName: %s\n", name, pmErrStr(n)); return; } if ((n = pmLookupDesc(pmidlist[0], &desc)) < 0) { printf("%s: pmLookupDesc: %s\n", name, pmErrStr(n)); return; } if (desc.indom != PM_INDOM_NULL) { _indom++; if ((n = pmGetInDom(desc.indom, &instlist, &instname)) < 0) { printf("%s: pmGetInDom: %s\n", name, pmErrStr(n)); return; } if (instlist) free(instlist); if (instname) free(instname); } if ((n = pmFetch(1, pmidlist, &result)) < 0) { printf("%s: pmFetch: %s\n", name, pmErrStr(n)); return; } if (result->numpmid != 1) { printf("%s: pmFetch: numpmid=%d, not 1\n", name, result->numpmid); } else { if (result->vset[0]->numval == 0) printf("%s: pmFetch: no value available\n", name); else if (result->vset[0]->numval < 0) printf("%s: pmFetch: %s\n", name, pmErrStr(result->vset[0]->numval)); else { if (result->vset[0]->valfmt == PM_VAL_INSITU) { _insitu++; if (pmDebug && DBG_TRACE_APPL0) printf("%s: insitu type=%s\n", name, pmTypeStr(desc.type)); } else { _ptr++; if (pmDebug && DBG_TRACE_APPL0) printf("%s: ptr size=%d valtype=%d descrtype=%s\n", name, result->vset[0]->vlist[0].value.pval->vlen, result->vset[0]->vlist[0].value.pval->vtype, pmTypeStr(desc.type)); } } } pmFreeResult(result); }
int main(int argc, char *argv[]) { int c; int sts; char *endnum; pmDesc desc; int one_trip = 1; while ((c = pmGetOptions(argc, argv, &opts)) != EOF) { switch (c) { case 'w': /* wide flag */ line_fmt = "%.1024s"; break; case 'p': /* show flag */ if (one_trip) { show_spec = 0; one_trip = 0; } if ((sts = parse_show_spec(opts.optarg)) < 0) { pmprintf("%s: unrecognized print flag specification (%s)\n", pmProgname, opts.optarg); opts.errors++; } else { show_spec |= sts; } break; case 'm': /* top N */ top = (int)strtol(opts.optarg, &endnum, 10); if (top <= 0) { pmprintf("%s: -m requires a positive integer\n", pmProgname); opts.errors++; } break; } } if (opts.optind < argc) opts.errors++; if (opts.errors) { pmUsageMessage(&opts); exit(1); } create_namelist(); if (opts.interval.tv_sec == 0) opts.interval.tv_sec = 2; if (opts.nhosts > 0) hostname = opts.hosts[0]; else hostname = "local:"; if ((sts = c = pmNewContext(PM_CONTEXT_HOST, hostname)) < 0) { fprintf(stderr, "%s: Cannot connect to PMCD on host \"%s\": %s\n", pmProgname, hostname, pmErrStr(sts)); exit(1); } hostname = (char *)pmGetContextHostName(c); if (pmGetContextOptions(c, &opts)) { pmflush(); exit(1); } if ((sts = pmLookupName(num_pmid, namelist, pmidlist)) < 0) { fprintf(stderr, "%s: Failed to lookup metrics : %s\n", pmProgname, pmErrStr(sts)); exit(1); } for (c = 0; c < num_pmid; c++) { if ((sts = pmLookupDesc(pmidlist[c], &desc)) < 0) { fprintf(stderr, "%s: Failed to lookup descriptor for metric \"%s\": %s\n", pmProgname, namelist[c], pmErrStr(sts)); exit(1); } type_tab[c] = desc.type; /* ASSUMES that the first metric will always be a proc metric */ if (c == 0) { proc_indom = desc.indom; } } for (;;) { doit(); __pmtimevalSleep(opts.interval); } return 0; }
int main(int argc, char *argv[]) { int c; int sts; char *rawfile = NULL; int i; int ctxid; int first = 1; int dflag = 0; int iflag = 0; int Lflag = 0; int lflag = 0; int Mflag = 0; int mflag = 0; int tflag = 0; int vflag = 0; int mode = PM_MODE_FORW; __pmContext *ctxp; pmResult *raw_result; pmResult *skel_result = NULL; pmResult *result; struct timeval done; while ((c = pmGetOptions(argc, argv, &opts)) != EOF) { switch (c) { case 'a': /* dump everything */ dflag = iflag = lflag = mflag = sflag = tflag = 1; break; case 'd': /* dump pmDesc structures */ dflag = 1; break; case 'i': /* dump instance domains */ iflag = 1; break; case 'L': /* dump label, verbose */ Lflag = 1; lflag = 1; break; case 'l': /* dump label */ lflag = 1; break; case 'm': /* dump metrics in log */ mflag = 1; break; case 'M': /* report <mark> records */ Mflag = 1; break; case 'r': /* read log in reverse chornological order */ mode = PM_MODE_BACK; break; case 's': /* report data size in log */ sflag = 1; break; case 't': /* dump temporal index */ tflag = 1; break; case 'v': /* verbose, dump in raw format */ vflag = 1; rawfile = opts.optarg; break; case 'x': /* report Ddd Mmm DD <timestamp> YYYY */ /* -xx reports numeric timeval also */ xflag++; break; } } if (opts.errors || (vflag && opts.optind != argc) || (!vflag && opts.optind > argc - 1 && !opts.narchives)) { pmUsageMessage(&opts); exit(1); } if (vflag) { FILE *f; if ((f = fopen(rawfile, "r")) == NULL) { fprintf(stderr, "%s: Cannot open \"%s\": %s\n", pmProgname, rawfile, osstrerror()); exit(1); } printf("Raw dump of physical archive file \"%s\" ...\n", rawfile); rawdump(f); exit(0); } if (dflag + iflag + lflag + mflag + tflag == 0) mflag = 1; /* default */ /* delay option end processing until now that we have the archive name */ if (opts.narchives == 0) __pmAddOptArchive(&opts, argv[opts.optind++]); opts.flags &= ~PM_OPTFLAG_DONE; __pmEndOptions(&opts); if ((sts = ctxid = pmNewContext(PM_CONTEXT_ARCHIVE, opts.archives[0])) < 0) { fprintf(stderr, "%s: Cannot open archive \"%s\": %s\n", pmProgname, opts.archives[0], pmErrStr(sts)); exit(1); } /* complete TZ and time window option (origin) setup */ if (pmGetContextOptions(ctxid, &opts)) { pmflush(); exit(1); } numpmid = argc - opts.optind; if (numpmid) { numpmid = 0; pmid = NULL; for (i = 0; opts.optind < argc; i++, opts.optind++) { numpmid++; pmid = (pmID *)realloc(pmid, numpmid * sizeof(pmID)); if ((sts = pmLookupName(1, &argv[opts.optind], &pmid[numpmid-1])) < 0) { if (sts == PM_ERR_NONLEAF) { numpmid--; if ((sts = pmTraversePMNS(argv[opts.optind], dometric)) < 0) fprintf(stderr, "%s: pmTraversePMNS(%s): %s\n", pmProgname, argv[opts.optind], pmErrStr(sts)); } else fprintf(stderr, "%s: pmLookupName(%s): %s\n", pmProgname, argv[opts.optind], pmErrStr(sts)); if (sts < 0) numpmid--; } } if (numpmid == 0) { fprintf(stderr, "No metric names can be translated, dump abandoned\n"); exit(1); } } if ((sts = pmGetArchiveLabel(&label)) < 0) { fprintf(stderr, "%s: Cannot get archive label record: %s\n", pmProgname, pmErrStr(sts)); exit(1); } if (numpmid > 0) { /* * setup dummy pmResult */ skel_result = (pmResult *)malloc(sizeof(pmResult)+(numpmid-1)*sizeof(pmValueSet *)); if (skel_result == NULL) { fprintf(stderr, "%s: malloc(skel_result): %s\n", pmProgname, osstrerror()); exit(1); } } /* * Note: ctxp->c_lock remains locked throughout ... __pmHandleToPtr() * is only called once, and a single context is used throughout * ... so there is no PM_UNLOCK(ctxp->c_lock) anywhere in the * pmdumplog code. * This works because ctxp->c_lock is a recursive lock and * pmdumplog is single-threaded. */ if ((ctxp = __pmHandleToPtr(ctxid)) == NULL) { fprintf(stderr, "%s: botch: __pmHandleToPtr(%d) returns NULL!\n", pmProgname, ctxid); exit(1); } pmSetMode(mode, &opts.start, 0); if (lflag) dumpLabel(Lflag); if (dflag) dumpDesc(ctxp); if (iflag) dumpInDom(ctxp); if (tflag) dumpTI(ctxp); if (mflag) { if (mode == PM_MODE_FORW) { if (opts.start_optarg != NULL || opts.finish_optarg != NULL) { /* -S or -T */ sts = pmSetMode(mode, &opts.start, 0); done = opts.finish; } else { /* read the whole archive */ done.tv_sec = 0; done.tv_usec = 0; sts = pmSetMode(mode, &done, 0); done.tv_sec = INT_MAX; } } else { if (opts.start_optarg != NULL || opts.finish_optarg != NULL) { /* -S or -T */ done.tv_sec = INT_MAX; done.tv_usec = 0; sts = pmSetMode(mode, &done, 0); done = opts.start; } else { /* read the whole archive backwards */ done.tv_sec = INT_MAX; done.tv_usec = 0; sts = pmSetMode(mode, &done, 0); done.tv_sec = 0; } } if (sts < 0) { fprintf(stderr, "%s: pmSetMode: %s\n", pmProgname, pmErrStr(sts)); exit(1); } sts = 0; for ( ; ; ) { sts = __pmLogFetch(ctxp, 0, NULL, &raw_result); if (sts < 0) break; if (numpmid == 0 || (raw_result->numpmid == 0 && Mflag)) { /* * want 'em all or <mark> record ... */ result = raw_result; } else if (numpmid > 0) { /* * cherry pick from raw_result if pmid matches one * of interest */ int picked = 0; int j; skel_result->timestamp = raw_result->timestamp; for (j = 0; j < numpmid; j++) skel_result->vset[j] = NULL; for (i = 0; i < raw_result->numpmid; i++) { for (j = 0; j < numpmid; j++) { if (pmid[j] == raw_result->vset[i]->pmid) { skel_result->vset[j] = raw_result->vset[i]; picked++; break; } } } if (picked == 0) { /* no metrics of interest, skip this record */ pmFreeResult(raw_result); continue; } skel_result->numpmid = picked; if (picked != numpmid) { /* did not find 'em all ... shuffle time */ int j; i = 0; for (j = 0; j < numpmid; j++) { if (skel_result->vset[j] != NULL) skel_result->vset[i++] = skel_result->vset[j]; } } result = skel_result; } else { /* not interesting */ pmFreeResult(raw_result); continue; } if (first && mode == PM_MODE_BACK) { first = 0; printf("\nLog finished at %24.24s - dump in reverse order\n", pmCtime(&result->timestamp.tv_sec, timebuf)); } if ((mode == PM_MODE_FORW && tvcmp(result->timestamp, done) > 0) || (mode == PM_MODE_BACK && tvcmp(result->timestamp, done) < 0)) { sts = PM_ERR_EOL; break; } putchar('\n'); dump_result(result); pmFreeResult(raw_result); } if (sts != PM_ERR_EOL) { fprintf(stderr, "%s: pmFetch: %s\n", pmProgname, pmErrStr(sts)); exit(1); } } exit(0); }
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; }