int pmiWrite(int sec, int usec) { int sts; if (current == NULL) return PM_ERR_NOCONTEXT; if (current->result == NULL) return current->last_sts = PMI_ERR_NODATA; if (sec < 0) { pmtimevalNow(¤t->result->timestamp); } else { current->result->timestamp.tv_sec = sec; current->result->timestamp.tv_usec = usec; } if ((sts = check_timestamp()) == 0) { sts = _pmi_put_result(current, current->result); current->last_stamp = current->result->timestamp; } pmFreeResult(current->result); current->result = NULL; return current->last_sts = sts; }
void setup_globals(pmOptions *opts) { pmID pmids[HOST_NMETRICS]; pmDesc descs[HOST_NMETRICS]; pmResult *result; setup_context(opts); setup_metrics(hostmetrics, &pmids[0], &descs[0], HOST_NMETRICS); fetch_metrics("host", HOST_NMETRICS, pmids, &result); if (HOST_NMETRICS != result->numpmid) { fprintf(stderr, "%s: pmFetch failed to fetch initial metric value(s)\n", pmProgname); cleanstop(1); } hertz = extract_integer(result, descs, HOST_HERTZ); pagesize = extract_integer(result, descs, HOST_PAGESIZE); extract_string(result, descs, HOST_RELEASE, sysname.release, sizeof(sysname.release)); extract_string(result, descs, HOST_VERSION, sysname.version, sizeof(sysname.version)); extract_string(result, descs, HOST_MACHINE, sysname.machine, sizeof(sysname.machine)); extract_string(result, descs, HOST_NODENAME, sysname.nodename, sizeof(sysname.nodename)); nodenamelen = strlen(sysname.nodename); pmFreeResult(result); }
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 main() { pthread_t tid1; pthread_t tid2; int sts; char *msg; #if darwin_hack /* * This is just too bizarre! * On Mac OS X, if one falls into the "CoreFoundation" libraries * in a thread, without first having run the initialization code * from the mainline, you die with a SIGTRAP! Calling dlopen() with * doomed to fail parameters suffices. * * See also the -framework CoreFoundation glue needed in * GNUmakefile. * * I am not making this up, check out * http://openradar.appspot.com/7209349 */ dlopen("/no/such/dso", RTLD_LAZY); #endif sts = pthread_barrier_init(&barrier, NULL, 2); if (sts != 0) { printf("pthread_barrier_init: sts=%d\n", sts); exit(1); } sts = pthread_create(&tid1, NULL, func1, NULL); if (sts != 0) { printf("pthread_create: tid1: sts=%d\n", sts); exit(1); } sts = pthread_create(&tid2, NULL, func2, NULL); if (sts != 0) { printf("pthread_create: tid2: 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); if (rp != NULL) pmFreeResult(rp); exit(0); }
int photoproc(struct tstat *tasks, int *taskslen) { static int setup; static pmID pmids[TASK_NMETRICS]; static pmDesc descs[TASK_NMETRICS]; pmResult *result; char **insts; int *pids, count, i; if (!setup) { setup_metrics(procmetrics, pmids, descs, TASK_NMETRICS); setup = 1; } fetch_metrics("task", TASK_NMETRICS, pmids, &result); /* extract external process names (insts) */ count = get_instances("task", TASK_GEN_NAME, descs, &pids, &insts); if (count > *taskslen) { size_t size; int ents = (*taskslen + PROCCHUNK); if (count > ents) ents = count; size = ents * sizeof(struct tstat); tasks = (struct tstat *)realloc(tasks, size); ptrverify(tasks, "photoproc [%ld]\n", (long)size); *taskslen = ents; } for (i=0; i < count; i++) { if (pmDebug & DBG_TRACE_APPL0) fprintf(stderr, "%s: updating process %d: %s\n", pmProgname, pids[i], insts[i]); update_task(&tasks[i], pids[i], insts[i], result, descs); } if (pmDebug & DBG_TRACE_APPL0) fprintf(stderr, "%s: done %d processes\n", pmProgname, count); pmFreeResult(result); free(insts); free(pids); return count; }
void freeFetch(Fetch *f) { if (f->profiles == NULL) { if (f->next) f->next->prev = f->prev; if (f->prev) f->prev->next = f->next; else { f->host->fetches = f->next; freeHost(f->host); } pmDestroyContext(f->handle); if (f->result) pmFreeResult(f->result); if (f->pmids) free(f->pmids); free(f); } }
/* * fetch pmidlist[i] ... pmidlist[NMETRIC-1] */ static void foo(FILE *f, char *fn, int i) { int sts; int j; pmResult *rp; if ((sts = pmFetch(NMETRIC-i, &pmidlist[i], &rp)) < 0) { fprintf(f, "%s: %s ...: pmFetch Error: %s\n", fn, namelist[i], pmErrStr(sts)); pthread_exit("botch"); } fprintf(f, "%s:", fn); for (j = 0; j < rp->numpmid; j++) fprintf(f, " %s: %d values", namelist[i+j], rp->vset[j]->numval); fputc('\n', f); pmFreeResult(rp); }
int pmiWrite(int sec, int usec) { int sts; if (current == NULL) return PM_ERR_NOCONTEXT; if (current->result == NULL) return current->last_sts = PMI_ERR_NODATA; if (sec < 0) { __pmtimevalNow(¤t->result->timestamp); } else { current->result->timestamp.tv_sec = sec; current->result->timestamp.tv_usec = usec; } if (current->result->timestamp.tv_sec < current->last_stamp.tv_sec || (current->result->timestamp.tv_sec == current->last_stamp.tv_sec && current->result->timestamp.tv_usec < current->last_stamp.tv_usec)) { fprintf(stderr, "Fatal Error: timestamp "); printstamp(stderr, ¤t->result->timestamp); fprintf(stderr, " not greater than previous valid timestamp "); printstamp(stderr, ¤t->last_stamp); fputc('\n', stderr); sts = PMI_ERR_BADTIMESTAMP; } else { sts = _pmi_put_result(current, current->result); current->last_stamp = current->result->timestamp; } pmFreeResult(current->result); current->result = NULL; return current->last_sts = sts; }
void test_store(void) { int sts; pmResult *result; print_banner_start("store"); sts = pmFetch(nmetrics, pmids, &result); if (sts < 0) { printf("%s: fetch failed : %s\n", pmProgname, pmErrStr(sts)); exit(1); } if ((sts = pmStore(result)) != -EACCES && sts != PM_ERR_PERMISSION) { printf("%s: Error: pmStore did not fail correctly\n", pmProgname); printf("Expected: %s\n", pmErrStr(-EACCES)); printf("or: %s\n", pmErrStr(PM_ERR_PERMISSION)); printf("Got: %s\n", pmErrStr(sts)); exit(1); } pmFreeResult(result); print_banner_end("store"); }
int main(int argc, char **argv) { int sts; char *msg; pmResult *irp; /* input pmResult */ pmResult *orp; /* output pmResult */ __pmPDU *pb; /* pdu buffer */ struct timeval unused; unsigned long peek_offset; /* process cmd line args */ if (parseargs(argc, argv) < 0) { pmUsageMessage(&opts); exit(1); } /* input archive name is argv[opts.optind] */ /* output archive name is argv[argc-1]) */ /* output archive */ oname = argv[argc-1]; /* input archive */ iname = argv[opts.optind]; /* * This is the interp mode context */ if ((ictx_a = pmNewContext(PM_CONTEXT_ARCHIVE, iname)) < 0) { fprintf(stderr, "%s: Error: cannot open archive \"%s\" (ctx_a): %s\n", pmProgname, iname, pmErrStr(ictx_a)); exit(1); } if ((sts = pmGetArchiveLabel(&ilabel)) < 0) { fprintf(stderr, "%s: Error: cannot get archive label record (%s): %s\n", pmProgname, iname, pmErrStr(sts)); exit(1); } /* start time */ logstart_tval.tv_sec = ilabel.ll_start.tv_sec; logstart_tval.tv_usec = ilabel.ll_start.tv_usec; /* end time */ if ((sts = pmGetArchiveEnd(&logend_tval)) < 0) { fprintf(stderr, "%s: Error: cannot get end of archive (%s): %s\n", pmProgname, iname, pmErrStr(sts)); exit(1); } if (zarg) { /* use TZ from metrics source (input-archive) */ if ((sts = pmNewZone(ilabel.ll_tz)) < 0) { fprintf(stderr, "%s: Cannot set context timezone: %s\n", pmProgname, pmErrStr(sts)); exit(1); } printf("Note: timezone set to local timezone of host \"%s\" from archive\n\n", ilabel.ll_hostname); } else if (tz != NULL) { /* use TZ as specified by user */ if ((sts = pmNewZone(tz)) < 0) { fprintf(stderr, "%s: Cannot set timezone to \"%s\": %s\n", pmProgname, tz, pmErrStr(sts)); exit(1); } printf("Note: timezone set to \"TZ=%s\"\n\n", tz); } else { char *tz; tz = __pmTimezone(); /* use TZ from local host */ if ((sts = pmNewZone(tz)) < 0) { fprintf(stderr, "%s: Cannot set local host's timezone: %s\n", pmProgname, pmErrStr(sts)); exit(1); } } /* set winstart and winend timevals */ sts = pmParseTimeWindow(Sarg, Targ, Aarg, Oarg, &logstart_tval, &logend_tval, &winstart_tval, &winend_tval, &unused, &msg); if (sts < 0) { fprintf(stderr, "%s: Invalid time window specified: %s\n", pmProgname, msg); exit(1); } #if PCP_DEBUG if (pmDebug & DBG_TRACE_APPL0) { char buf[26]; pmCtime((const time_t *)&winstart_tval.tv_sec, buf); fprintf(stderr, "Start time: %s", buf); pmCtime((const time_t *)&winend_tval.tv_sec, buf); fprintf(stderr, "End time: %s", buf); } #endif if ((sts = pmSetMode(PM_MODE_INTERP | PM_XTB_SET(PM_TIME_SEC), &winstart_tval, (int)targ)) < 0) { fprintf(stderr, "%s: pmSetMode(PM_MODE_INTERP ...) failed: %s\n", pmProgname, pmErrStr(sts)); exit(1); } /* create output log - must be done before writing label */ if ((sts = __pmLogCreate("", oname, PM_LOG_VERS02, &logctl)) < 0) { fprintf(stderr, "%s: Error: __pmLogCreate: %s\n", pmProgname, pmErrStr(sts)); exit(1); } /* This must be done after log is created: * - checks that archive version, host, and timezone are ok * - set archive version, host, and timezone of output archive * - set start time * - write labels */ newlabel(); current.tv_sec = logctl.l_label.ill_start.tv_sec = winstart_tval.tv_sec; current.tv_usec = logctl.l_label.ill_start.tv_usec = winstart_tval.tv_usec; /* write label record */ writelabel(); /* * Supress any automatic label creation in libpcp at the first * pmResult write. */ logctl.l_state = PM_LOG_STATE_INIT; /* * Traverse the PMNS to get all the metrics and their metadata */ if ((sts = pmTraversePMNS ("", dometric)) < 0) { fprintf(stderr, "%s: Error traversing namespace ... %s\n", pmProgname, pmErrStr(sts)); goto cleanup; } /* * All the initial metadata has been generated, add timestamp */ fflush(logctl.l_mdfp); __pmLogPutIndex(&logctl, ¤t); written = 0; /* * main loop */ while (sarg == -1 || written < sarg) { /* * do stuff */ if ((sts = pmUseContext(ictx_a)) < 0) { fprintf(stderr, "%s: Error: cannot use context (%s): %s\n", pmProgname, iname, pmErrStr(sts)); goto cleanup; } if ((sts = pmFetch(numpmid, pmidlist, &irp)) < 0) { if (sts == PM_ERR_EOL) break; fprintf(stderr, "%s: Error: pmFetch failed: %s\n", pmProgname, pmErrStr(sts)); exit(1); } if (irp->timestamp.tv_sec > winend_tval.tv_sec || (irp->timestamp.tv_sec == winend_tval.tv_sec && irp->timestamp.tv_usec > winend_tval.tv_usec)) { /* past end time as per -T */ break; } #if PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) { fprintf(stderr, "input record ...\n"); __pmDumpResult(stderr, irp); } #endif /* * traverse the interval, looking at every archive record ... * we are particularly interested in: * - metric-values that are interpolated but not present in * this interval * - counter wraps * - mark records */ doscan(&irp->timestamp); if ((sts = pmUseContext(ictx_a)) < 0) { fprintf(stderr, "%s: Error: cannot use context (%s): %s\n", pmProgname, iname, pmErrStr(sts)); goto cleanup; } orp = rewrite(irp); #if PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) { if (orp == NULL) fprintf(stderr, "output record ... none!\n"); else { fprintf(stderr, "output record ...\n"); __pmDumpResult(stderr, orp); } } #endif if (orp == NULL) goto next; /* * convert log record to a PDU, and enforce V2 encoding semantics, * then write it out */ sts = __pmEncodeResult(PDU_OVERRIDE2, orp, &pb); if (sts < 0) { fprintf(stderr, "%s: Error: __pmEncodeResult: %s\n", pmProgname, pmErrStr(sts)); goto cleanup; } /* switch volumes if required */ if (varg > 0) { if (written > 0 && (written % varg) == 0) { __pmTimeval next_stamp; next_stamp.tv_sec = irp->timestamp.tv_sec; next_stamp.tv_usec = irp->timestamp.tv_usec; newvolume(oname, &next_stamp); } } /* * Even without a -v option, we may need to switch volumes * if the data file exceeds 2^31-1 bytes */ peek_offset = ftell(logctl.l_mfp); peek_offset += ((__pmPDUHdr *)pb)->len - sizeof(__pmPDUHdr) + 2*sizeof(int); if (peek_offset > 0x7fffffff) { __pmTimeval next_stamp; next_stamp.tv_sec = irp->timestamp.tv_sec; next_stamp.tv_usec = irp->timestamp.tv_usec; newvolume(oname, &next_stamp); } current.tv_sec = orp->timestamp.tv_sec; current.tv_usec = orp->timestamp.tv_usec; doindom(orp); /* write out log record */ sts = __pmLogPutResult2(&logctl, pb); __pmUnpinPDUBuf(pb); if (sts < 0) { fprintf(stderr, "%s: Error: __pmLogPutResult2: log data: %s\n", pmProgname, pmErrStr(sts)); goto cleanup; } written++; rewrite_free(); next: pmFreeResult(irp); } /* write the last time stamp */ fflush(logctl.l_mfp); fflush(logctl.l_mdfp); __pmLogPutIndex(&logctl, ¤t); exit(exit_status); cleanup: { char fname[MAXNAMELEN]; fprintf(stderr, "Archive \"%s\" not created.\n", oname); snprintf(fname, sizeof(fname), "%s.0", oname); unlink(fname); snprintf(fname, sizeof(fname), "%s.meta", oname); unlink(fname); snprintf(fname, sizeof(fname), "%s.index", oname); unlink(fname); exit(1); } }
/* Fetch metric values. */ static int getvals(Context *x, /* in - full pm description */ pmResult **vs) /* alloc - pm values */ { pmResult *r; int e; int i; if (rawArchive) { /* * for -U mode, read until we find either a pmResult with the * pmid we are after, or a mark record */ for ( ; ; ) { e = pmFetchArchive(&r); if (e < 0) break; if (r->numpmid == 0) { if (opts.guiflag || opts.context == PM_CONTEXT_ARCHIVE) __pmPrintStamp(stdout, &r->timestamp); printf(" Archive logging suspended\n"); pmFreeResult(r); return -1; } for (i = 0; i < r->numpmid; i++) { if (r->vset[i]->pmid == x->pmid) break; } if (i != r->numpmid) break; pmFreeResult(r); } } else { e = pmFetch(1, &(x->pmid), &r); i = 0; } if (e < 0) { if (e == PM_ERR_EOL && opts.guiflag) { pmTimeStateBounds(&controls, pmtime); return -1; } if (rawArchive) fprintf(stderr, "\n%s: pmFetchArchive: %s\n", pmProgname, pmErrStr(e)); else fprintf(stderr, "\n%s: pmFetch: %s\n", pmProgname, pmErrStr(e)); exit(EXIT_FAILURE); } if (opts.guiflag) pmTimeStateAck(&controls, pmtime); if (__pmtimevalToReal(&r->timestamp) > __pmtimevalToReal(&opts.finish)) { pmFreeResult(r); return -2; } if (r->vset[i]->numval == 0) { if (opts.guiflag || opts.context == PM_CONTEXT_ARCHIVE) { __pmPrintStamp(stdout, &r->timestamp); printf(" "); } printf("No values available\n"); pmFreeResult(r); return -1; } else if (r->vset[i]->numval < 0) { if (rawArchive) fprintf(stderr, "\n%s: pmFetchArchive: %s\n", pmProgname, pmErrStr(r->vset[i]->numval)); else fprintf(stderr, "\n%s: pmFetch: %s\n", pmProgname, pmErrStr(r->vset[i]->numval)); pmFreeResult(r); return -1; } *vs = r; qsort(r->vset[i]->vlist, (size_t)r->vset[i]->numval, sizeof(pmValue), compare); return i; }
/* 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 int do_control(__pmPDU *pb) { int sts; int control; int state; int delta; pmResult *request; pmResult *result; int siamised = 0; /* the verb from siamese (as in twins) */ int i; int j; int val; pmValueSet *vsp; optreq_t *rqp; task_t *tp; time_t now; int reqstate = 0; /* * TODO - encoding for logging interval in requests and results? */ if ((sts = __pmDecodeLogControl(pb, &request, &control, &state, &delta)) < 0) return sts; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOG) { fprintf(stderr, "do_control: control=%d state=%d delta=%d request ...\n", control, state, delta); dumpcontrol(stderr, request, 0); } #endif if (control == PM_LOG_MANDATORY || control == PM_LOG_ADVISORY) { time(&now); fprintf(stderr, "\n%s", ctime(&now)); fprintf(stderr, "pmlc request from %s: %s", pmlc_host, control == PM_LOG_MANDATORY ? "mandatory" : "advisory"); if (state == PM_LOG_ON) { if (delta == 0) fprintf(stderr, " on once\n"); else fprintf(stderr, " on %.1f sec\n", (float)delta/1000); } else if (state == PM_LOG_OFF) fprintf(stderr, " off\n"); else fprintf(stderr, " maybe\n"); } /* * access control checks */ sts = 0; switch (control) { case PM_LOG_MANDATORY: if (denyops & PM_OP_LOG_MAND) sts = PM_ERR_PERMISSION; break; case PM_LOG_ADVISORY: if (denyops & PM_OP_LOG_ADV) sts = PM_ERR_PERMISSION; break; case PM_LOG_ENQUIRE: /* * Don't need to check [access] as you have to have _some_ * permission (at least one of PM_OP_LOG_ADV or PM_OP_LOG_MAND * and PM_OP_LOG_ENQ) to make a connection ... and if you * have either PM_OP_LOG_ADV or PM_OP_LOG_MAND it makes no * sense to deny PM_OP_LOG_ENQ operations. */ break; default: fprintf(stderr, "Bad control PDU type %d\n", control); sts = PM_ERR_IPC; break; } if (sts < 0) { fprintf(stderr, "Error: %s\n", pmErrStr(sts)); if ((sts = __pmSendError(clientfd, FROM_ANON, sts)) < 0) __pmNotifyErr(LOG_ERR, "do_control: error sending Error PDU to client: %s\n", pmErrStr(sts)); pmFreeResult(request); return sts; } /* handle everything except PM_LOG_ENQUIRE */ if (control == PM_LOG_MANDATORY || control == PM_LOG_ADVISORY) { /* update the logging status of metrics */ task_t *newtp = NULL; /* task for metrics/insts in request */ struct timeval tdelta = { 0 }; int newtask; int mflags; /* convert state and control to the bitmask used in pmlogger and values * returned in results. Remember that reqstate starts with nothing on. */ if (state == PM_LOG_ON) PMLC_SET_ON(reqstate, 1); else PMLC_SET_ON(reqstate, 0); if (control == PM_LOG_MANDATORY) { if (state == PM_LOG_MAYBE) /* mandatory+maybe => maybe+advisory+off */ PMLC_SET_MAYBE(reqstate, 1); else PMLC_SET_MAND(reqstate, 1); } /* try to find an existing task for the request * Never return a "once only" task, it may have gone off already and just * be hanging around like a bad smell. */ if (delta != 0) { tdelta.tv_sec = delta / 1000; tdelta.tv_usec = (delta % 1000) * 1000; newtp = find_task(reqstate, &tdelta); } newtask = (newtp == NULL); for (i = 0; i < request->numpmid; i++) { vsp = request->vset[i]; if (vsp->numval < 0) /* * request is malformed, as we cannot control logging * for an undefined instance ... there is no way to * return an error from here, so simply ignore this * metric */ continue; mflags = find_metric(vsp->pmid); if (mflags < 0) { /* only add new metrics if they are ON or MANDATORY OFF * Careful: mandatory+maybe is mandatory+maybe+off */ if (PMLC_GET_ON(reqstate) || (PMLC_GET_MAND(reqstate) && !PMLC_GET_MAYBE(reqstate))) add_metric(vsp, &newtp); } else /* already a specification for this metric */ update_metric(vsp, reqstate, mflags, &newtp); } /* schedule new logging task if new metric(s) specified */ if (newtask && newtp != NULL) { if (newtp->t_fetch == NULL) { /* the new task ended up with no fetch groups, throw it away */ if (newtp->t_pmidlist != NULL) free(newtp->t_pmidlist); free(newtp); } else { /* link new task into tasklist */ newtp->t_next = tasklist; tasklist = newtp; /* use only the MAND/ADV and ON/OFF bits of reqstate */ newtp->t_state = PMLC_GET_STATE(reqstate); if (PMLC_GET_ON(reqstate)) { newtp->t_delta = tdelta; newtp->t_afid = __pmAFregister(&tdelta, (void *)newtp, log_callback); } else newtp->t_delta.tv_sec = newtp->t_delta.tv_usec = 0; linkback(newtp); } } } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL0) dumpit(); #endif /* just ignore advisory+maybe---the returned pmResult will have the metrics * in their original state indicating that the request could not be * satisfied. */ result = request; result->timestamp.tv_sec = result->timestamp.tv_usec = 0; /* for purify */ /* write the current state of affairs into the result _pmResult */ for (i = 0; i < request->numpmid; i++) { if (control == PM_LOG_MANDATORY || control == PM_LOG_ADVISORY) { char **names; sts = pmNameAll(request->vset[i]->pmid, &names); if (sts < 0) fprintf(stderr, " metric: %s", pmIDStr(request->vset[i]->pmid)); else { fprintf(stderr, " metric: "); __pmPrintMetricNames(stderr, sts, names, " or "); free(names); } } if (request->vset[i]->numval <= 0 && !siamised) { result = siamise_request(request); siamised = 1; } /* * pmids with numval <= 0 in the request have a null vset ptr in the * in the corresponding place in the siamised result. */ if (result->vset[i] != NULL) vsp = result->vset[i]; else { /* the result should also contain the history for an all instances * enquire request. Control requests just get the current indom * since the user of pmlc really wants to see what's being logged * now rather than in the past. */ vsp = build_vset(request->vset[i]->pmid, control == PM_LOG_ENQUIRE); result->vset[i] = vsp; } vsp->valfmt = PM_VAL_INSITU; for (j = 0; j < vsp->numval; j++) { rqp = findoptreq(vsp->pmid, vsp->vlist[j].inst); val = 0; if (rqp == NULL) { PMLC_SET_STATE(val, 0); PMLC_SET_DELTA(val, 0); } else { tp = rqp->r_fetch->f_aux; PMLC_SET_STATE(val, tp->t_state); PMLC_SET_DELTA(val, (tp->t_delta.tv_sec*1000 + tp->t_delta.tv_usec/1000)); } val |= gethistflags(vsp->pmid, vsp->vlist[j].inst); vsp->vlist[j].value.lval = val; if (control == PM_LOG_MANDATORY || control == PM_LOG_ADVISORY) { int expstate = 0; int statemask = 0; int expdelta; if (rqp != NULL && rqp->r_desc->indom != PM_INDOM_NULL) { char *p; if (j == 0) fputc('\n', stderr); if (pmNameInDom(rqp->r_desc->indom, vsp->vlist[j].inst, &p) >= 0) { fprintf(stderr, " instance: %s", p); free(p); } else fprintf(stderr, " instance: #%d", vsp->vlist[j].inst); } else { /* no pmDesc ... punt */ if (vsp->numval > 1 || vsp->vlist[j].inst != PM_IN_NULL) { if (j == 0) fputc('\n', stderr); fprintf(stderr, " instance: #%d", vsp->vlist[j].inst); } } if (state != PM_LOG_MAYBE) { if (control == PM_LOG_MANDATORY) PMLC_SET_MAND(expstate, 1); else PMLC_SET_MAND(expstate, 0); if (state == PM_LOG_ON) PMLC_SET_ON(expstate, 1); else PMLC_SET_ON(expstate, 0); PMLC_SET_MAND(statemask, 1); PMLC_SET_ON(statemask, 1); } else { PMLC_SET_MAND(expstate, 0); PMLC_SET_MAND(statemask, 1); } expdelta = PMLC_GET_ON(expstate) ? delta : 0; if ((PMLC_GET_STATE(val) & statemask) != expstate || PMLC_GET_DELTA(val) != expdelta) fprintf(stderr, " [request failed]"); fputc('\n', stderr); } } } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOG) { __pmDumpResult(stderr, result); } #endif if ((sts = __pmSendResult(clientfd, FROM_ANON, result)) < 0) __pmNotifyErr(LOG_ERR, "do_control: error sending Error PDU to client: %s\n", pmErrStr(sts)); if (siamised) { for (i = 0; i < request->numpmid; i++) if (request->vset[i]->numval <= 0) free(result->vset[i]); free(result); } pmFreeResult(request); return 0; }
void service_client(__pmPDU *pb) { int n; int i; int j; pmDesc desc; pmDesc foundDesc; pmResult *resp; pmValueSet *vsp; __pmPDUHdr *ph = (__pmPDUHdr *)pb; switch (ph->type) { case PDU_DESC: if ((n = __pmDecodeDesc(pb, &desc)) < 0) { fprintf(stderr, "service_client: __pmDecodeDesc failed: %s\n", pmErrStr(n)); exit(1); } if (desc.indom != PM_INDOM_NULL) { fprintf(stderr, "service_client: Warning: ignored desc for pmid=%s: indom is not singular\n", pmIDStr(desc.pmid)); return; } if (summary_desc(desc.pmid, &foundDesc, NULL) == 0) { /* already in table */ fprintf(stderr, "service_client: Warning: duplicate desc for pmid=%s\n", pmIDStr(desc.pmid)); return; } nmeta++; if ((meta = (meta_t *)realloc(meta, nmeta * sizeof(meta_t))) == NULL) { __pmNoMem("service_client: meta realloc", nmeta * sizeof(meta_t), PM_FATAL_ERR); } memcpy(&meta[nmeta-1].desc, &desc, sizeof(pmDesc)); break; case PDU_RESULT: if ((n = __pmDecodeResult(pb, &resp)) < 0) { fprintf(stderr, "service_client: __pmDecodeResult failed: %s\n", pmErrStr(n)); exit(1); } if (cachedResult == NULL) { int need; need = (int)sizeof(pmResult) - (int)sizeof(pmValueSet *); if ((cachedResult = (pmResult *)malloc(need)) == NULL) { __pmNoMem("service_client: result malloc", need, PM_FATAL_ERR); } cachedResult->numpmid = 0; } /* * swap values from resp with those in cachedResult, expanding * cachedResult if there are metrics we've not seen before */ for (i = 0; i < resp->numpmid; i++) { for (j = 0; j < cachedResult->numpmid; j++) { if (resp->vset[i]->pmid == cachedResult->vset[j]->pmid) { /* found matching PMID, update this value */ break; } } if (j == cachedResult->numpmid) { /* new PMID, expand cachedResult and initialize vset */ int need; cachedResult->numpmid++; need = (int)sizeof(pmResult) + (cachedResult->numpmid-1) * (int)sizeof(pmValueSet *); if ((cachedResult = (pmResult *)realloc(cachedResult, need)) == NULL) { __pmNoMem("service_client: result realloc", need, PM_FATAL_ERR); } if ((cachedResult->vset[j] = (pmValueSet *)malloc(sizeof(pmValueSet))) == NULL) { __pmNoMem("service_client: vset[]", sizeof(pmValueSet), PM_FATAL_ERR); } cachedResult->vset[j]->pmid = resp->vset[i]->pmid; cachedResult->vset[j]->numval = 0; } /* * swap vsets */ vsp = cachedResult->vset[j]; cachedResult->vset[j] = resp->vset[i]; resp->vset[i] = vsp; } pmFreeResult(resp); break; case PDU_ERROR: if ((n = __pmDecodeError(pb, &i)) < 0) { fprintf(stderr, "service_client: __pmDecodeError failed: %s\n", pmErrStr(n)); exit(1); } fprintf(stderr, "service_client: Error PDU! %s\n", pmErrStr(i)); break; default: fprintf(stderr, "service_client: Bogus PDU type %d\n", ph->type); exit(1); } }
int pass3(__pmContext *ctxp, char *archname, pmOptions *opts) { struct timeval timespan; int sts; pmResult *result; struct timeval last_stamp; struct timeval delta_stamp; l_ctxp = ctxp; l_archname = archname; if (vflag) fprintf(stderr, "%s: start pass3\n", archname); if ((sts = pmSetMode(PM_MODE_FORW, &opts->start, 0)) < 0) { fprintf(stderr, "%s: pmSetMode failed: %s\n", l_archname, pmErrStr(sts)); return STS_FATAL; } /* check which timestamp print format we should be using */ timespan = opts->finish; tsub(×pan, &opts->start); if (timespan.tv_sec > 86400) /* seconds per day: 60*60*24 */ dayflag = 1; sts = 0; last_stamp = opts->start; for ( ; ; ) { /* * we need the next record with no fancy checks or record * skipping in libpcp, so use __pmLogRead() in preference * to pmFetchArchive() */ if ((sts = __pmLogRead(l_ctxp->c_archctl->ac_log, l_ctxp->c_mode, NULL, &result, PMLOGREAD_NEXT)) < 0) break; result_count++; delta_stamp = result->timestamp; tsub(&delta_stamp, &last_stamp); #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL0) { int i; int sum_val = 0; int cnt_noval = 0; int cnt_err = 0; pmValueSet *vsp; fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); for (i = 0; i < result->numpmid; i++) { vsp = result->vset[i]; if (vsp->numval > 0) sum_val += vsp->numval; else if (vsp->numval == 0) cnt_noval++; else cnt_err++; } fprintf(stderr, "] delta(stamp)=%.3fsec", __pmtimevalToReal(&delta_stamp)); fprintf(stderr, " numpmid=%d sum(numval)=%d", result->numpmid, sum_val); if (cnt_noval > 0) fprintf(stderr, " count(numval=0)=%d", cnt_noval); if (cnt_err > 0) fprintf(stderr, " count(numval<0)=%d", cnt_err); fputc('\n', stderr); } #endif if (delta_stamp.tv_sec < 0) { /* time went backwards! */ fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); fprintf(stderr, "]: timestamp went backwards, prior timestamp: "); print_stamp(stderr, &last_stamp); fprintf(stderr, "\n"); } last_stamp = result->timestamp; if ((opts->finish.tv_sec > result->timestamp.tv_sec) || ((opts->finish.tv_sec == result->timestamp.tv_sec) && (opts->finish.tv_usec >= result->timestamp.tv_usec))) { if (result->numpmid == 0) { /* * MARK record ... make sure wrap check is not done * at next fetch (mimic interp.c from libpcp) */ __pmHashNode *hptr; checkData *checkdata; int k; for (hptr = __pmHashWalk(&hashlist, PM_HASH_WALK_START); hptr != NULL; hptr = __pmHashWalk(&hashlist, PM_HASH_WALK_NEXT)) { checkdata = (checkData *)hptr->data; for (k = 0; k < checkdata->listsize; k++) { checkdata->instlist[k]->lasttime.tv_sec = 0; } } mark_count++; } else docheck(result); pmFreeResult(result); } else { pmFreeResult(result); sts = PM_ERR_EOL; break; } } if (sts != PM_ERR_EOL) { fprintf(stderr, "[after "); print_stamp(stderr, &last_stamp); fprintf(stderr, "]: pmFetch: error: %s\n", pmErrStr(sts)); return STS_FATAL; } return STS_OK; }
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 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; }
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; }
/* * Tests 4. and 5. * Set up an explicit profile of ourself and our parent * If any of the metrics are not in the proc indom, we'll get no values back. * Checks if profile is being handled correctly. * Checks if fetch is using profile correctly. */ void test_prof_fetch(void) { int sts; int i; int pids[2]; pmResult *result1, *result2; print_banner_start("profile/fetch"); pids[0] = (int)getpid(); pids[1] = (int)getppid(); pmDelProfile(indom, 0, NULL); pmAddProfile(indom, 2, pids); printf("\n--- Check profile in context dump... ---\n"); if ((sts = pmWhichContext()) < 0) { printf("%s: pmWhichContext: %s\n", pmProgname, pmErrStr(sts)); exit(1); } __pmDumpContext(stdout, sts, PM_INDOM_NULL); printf("--- End Check profile in context dump... ---\n"); printf("\n--- Fetch Over Restricted Instance Domain ... ---\n"); for (i=0; i < iterations; i++) { int j,k; sts = pmFetch(nmetrics, pmids, &result1); if (sts < 0) { printf("%s: iteration %d : %s\n", pmProgname, i, pmErrStr(sts)); exit(1); } __pmDumpResult(stdout, result1); for (j = 0; j < result1->numpmid; j++) { pmValueSet *set = result1->vset[j]; if (set->numval != 2) { printf("%s: Error: num of inst == %d\n", pmProgname, set->numval); } for (k = 0; k < set->numval; k++) { pmValue *val = &set->vlist[k]; if (val->inst != pids[0] && val->inst != pids[1]) { printf("%s: Error: inst ids do not match pids\n", pmProgname); exit(1); } } } pmFreeResult(result1); } printf("--- End Fetch Over Restricted Instance Domain ... ---\n"); printf("\n--- Fetch Over Entire Instance Domain ... ---\n"); if (indom != PM_INDOM_NULL) { pmDelProfile(indom, 0, NULL); pmAddProfile(indom, all_n, all_inst); } sts = pmFetch(nmetrics, pmids, &result2); if (sts < 0) { printf("%s: fetch all %d instances : %s\n", pmProgname, all_n, pmErrStr(sts)); exit(1); } __pmDumpResult(stdout, result2); pmFreeResult(result2); printf("--- End Fetch Over Entire Instance Domain ... ---\n"); print_banner_end("profile/fetch"); }
void doit(void) { int i, r, m, v, sts; static double now = 0, then = 0; double delta_d; static unsigned long num_times = 0; static pmResult *result[2]; int num_entries; num_times++; if (num_times > 2) { pmFreeResult(result[0]); /* if forever, ensure no wrapping */ if (num_samples < 0) num_times = 3; } if (num_times > 1) { result[0] = result[1]; } get_indom(); if ((sts = pmFetch(num_pmid, pmidlist, &result[1])) < 0) { for (i = 0; i < num_pmid; i++) fprintf(stderr, "%s: pmFetch: %s\n", namelist[i], pmErrStr(sts)); exit(1); } if (num_times > 1) { then = result[0]->timestamp.tv_sec + result[0]->timestamp.tv_usec/1000000; now = result[1]->timestamp.tv_sec + result[1]->timestamp.tv_usec/1000000; delta_d = now - then; if (result[1]->numpmid != num_pmid) { fprintf(stderr, "%s: Failed to fetch all metrics (%d out of %d)\n", pmProgname, result[1]->numpmid, num_pmid); exit(1); } /* --- build value table --- */ for(i=0; i<num_inst; i++) { val_tab[i].num = 0; } /* go thru each result */ for(r=0; r<2; r++) { /* go thru each metric */ for(m=0; m<num_pmid; m++) { pmValueSet *vset = result[r]->vset[m]; if (vset->numval < 0) { fprintf(stderr, "%s: Error when fetching metric %s: %s\n", pmProgname, namelist[m], pmErrStr(vset->numval)); continue; } if (vset->numval == 0) continue; valfmt_tab[m] = vset->valfmt; /* handle global metrics */ if (((show_spec & (SHOW_CPU | SHOW_SYS)) && m == kernel_stime) || ((show_spec & (SHOW_CPU | SHOW_USR)) && m == kernel_utime) || ((show_spec & SHOW_SYSCALLS) && m == kernel_sysc) || ((show_spec & SHOW_CTX) && m == kernel_ctx)) { if (vset->numval != 1) { fprintf(stderr, "%s: Wrong num of values for kernel metric: %d\n", pmProgname, vset->numval); exit(1); } global_val[m][r] = vset->vlist[0]; continue; } /* handle proc-instance metrics */ /* Find result inst * Would be faster to start from where left off * last time. Need to remember this for a metric/result. */ for(v=0; v<vset->numval; v++) { pmValue val = vset->vlist[v]; /* go thru each possible inst */ for(i=0; i<num_inst; i++) { if (instances[i] == val.inst) { val_tab[i].num++; /* needs to be zeroed at start */ val_tab[i].values[m][r] = val; break; } } } } } /* --- calculate rates --- */ /* handle global metrics */ if (show_spec & SHOW_CPU) { __uint64_t utime[2], stime[2]; double cpuburn_val; utime[0] = get_value(kernel_utime, &global_val[kernel_utime][0]); utime[1] = get_value(kernel_utime, &global_val[kernel_utime][1]); stime[0] = get_value(kernel_stime, &global_val[kernel_stime][0]); stime[1] = get_value(kernel_stime, &global_val[kernel_stime][1]); cpuburn_val = (utime[1] - utime[0] + stime[1] - stime[0]) / delta_d; cpuburn_val /= 10; cpuburn_val = cpuburn_val > 100 ? 100 : cpuburn_val; global_rates[CPU_VAL] = cpuburn_val; } if (show_spec & SHOW_SYSCALLS) { __uint64_t sysc[2]; sysc[0] = get_value(kernel_sysc, &global_val[kernel_sysc][0]); sysc[1] = get_value(kernel_sysc, &global_val[kernel_sysc][1]); global_rates[SYSCALLS_VAL] = (sysc[1] - sysc[0]) / delta_d; } if (show_spec & SHOW_CTX) { __uint64_t ctx[2]; ctx[0] = get_value(kernel_ctx, &global_val[kernel_ctx][0]); ctx[1] = get_value(kernel_ctx, &global_val[kernel_ctx][1]); global_rates[CTX_VAL] = (ctx[1] - ctx[0]) / delta_d; } if (show_spec & SHOW_SYS) { __uint64_t stime[2]; stime[0] = get_value(kernel_stime, &global_val[kernel_stime][0]); stime[1] = get_value(kernel_stime, &global_val[kernel_stime][1]); global_rates[SYS_VAL] = ((stime[1] - stime[0]) / delta_d) / 10; } if (show_spec & SHOW_USR) { __uint64_t utime[2]; utime[0] = get_value(kernel_utime, &global_val[kernel_utime][0]); utime[1] = get_value(kernel_utime, &global_val[kernel_utime][1]); global_rates[USR_VAL] = ((utime[1] - utime[0]) / delta_d) / 10; } /* handle proc-instance metrics */ num_entries = 0; for(i=0; i<num_inst; i++) { val_entry_t *vt = &val_tab[i]; rate_entry_t *rt; if (vt->num < (num_proc_pmid*2)) { /* couldn't get instances for all proc metrics for both(*2) results */ continue; } rt = &rate_tab[num_entries]; rt->inst = i; /* create cpuburn values */ if (show_spec & SHOW_CPU) { __uint64_t utime[2], stime[2]; double cpuburn_val; utime[0] = get_value(pu_utime, &vt->values[pu_utime][0]); utime[1] = get_value(pu_utime, &vt->values[pu_utime][1]); stime[0] = get_value(pu_stime, &vt->values[pu_stime][0]); stime[1] = get_value(pu_stime, &vt->values[pu_stime][1]); cpuburn_val = (utime[1] - utime[0] + stime[1] - stime[0]) / delta_d; cpuburn_val /= 10; cpuburn_val = cpuburn_val > 100 ? 100 : cpuburn_val; rt->values[CPU_VAL] = cpuburn_val; } /* create syscalls values */ if (show_spec & SHOW_SYSCALLS) { __uint64_t sysc[2]; sysc[0] = get_value(pu_sysc, &vt->values[pu_sysc][0]); sysc[1] = get_value(pu_sysc, &vt->values[pu_sysc][1]); rt->values[SYSCALLS_VAL] = (sysc[1] - sysc[0]) / delta_d; } /* create ctx values */ if (show_spec & SHOW_CTX) { double ictx, vctx; vctx = get_value(pu_vctx, &vt->values[pu_vctx][1]) - get_value(pu_vctx, &vt->values[pu_vctx][0]); ictx = get_value(pu_ictx, &vt->values[pu_ictx][1]) - get_value(pu_ictx, &vt->values[pu_ictx][0]); rt->values[CTX_VAL] = (vctx + ictx) / delta_d; } /* create reads values */ if (show_spec & SHOW_READS) { double br, gbr; br = get_value(pu_bread, &vt->values[pu_bread][1]) - get_value(pu_bread, &vt->values[pu_bread][0]); gbr = get_value(pu_gbread, &vt->values[pu_gbread][1]) - get_value(pu_gbread, &vt->values[pu_gbread][0]); rt->values[READS_VAL] = (gbr * 1024 * 1024 + br / 1024) / delta_d; } /* create writes values */ if (show_spec & SHOW_WRITES) { double bw, gbw; bw = get_value(pu_bwrit, &vt->values[pu_bwrit][1]) - get_value(pu_bwrit, &vt->values[pu_bwrit][0]); gbw = get_value(pu_gbwrit, &vt->values[pu_gbwrit][1]) - get_value(pu_gbwrit, &vt->values[pu_gbwrit][0]); rt->values[WRITES_VAL] = (gbw * 1024 * 1024 + bw / 1024) / delta_d; } /* create rss values */ if (show_spec & SHOW_RSS) { rt->values[RSS_VAL] = get_value(pu_rss, &vt->values[pu_rss][1]); } /* create sys cpu time values */ if (show_spec & SHOW_SYS) { __uint64_t stime[2]; stime[0] = get_value(pu_stime, &vt->values[pu_stime][0]); stime[1] = get_value(pu_stime, &vt->values[pu_stime][1]); rt->values[SYS_VAL] = ((stime[1] - stime[0]) / delta_d) / 10; rt->values[SYS_VAL] = rt->values[SYS_VAL] > 100 ? 100 : rt->values[SYS_VAL]; } /* create user cpu time values */ if (show_spec & SHOW_USR) { __uint64_t utime[2]; utime[0] = get_value(pu_utime, &vt->values[pu_utime][0]); utime[1] = get_value(pu_utime, &vt->values[pu_utime][1]); rt->values[USR_VAL] = ((utime[1] - utime[0]) / delta_d) / 10; rt->values[USR_VAL] = rt->values[USR_VAL] > 100 ? 100 : rt->values[USR_VAL]; } num_entries++; } /* --- report values --- */ printf("HOST: %s\n", hostname); printf("DATE: %s\n\n", get_time()); if (show_spec & SHOW_CPU) { qsort(rate_tab, num_entries, sizeof(rate_entry_t), cpuburn_cmp); calc_sum_rates(num_entries, CPU_VAL); print_top(rate_tab, num_entries, CPU_VAL); } if (show_spec & SHOW_SYSCALLS) { qsort(rate_tab, num_entries, sizeof(rate_entry_t), syscall_cmp); calc_sum_rates(num_entries, SYSCALLS_VAL); print_top(rate_tab, num_entries, SYSCALLS_VAL); } if (show_spec & SHOW_CTX) { qsort(rate_tab, num_entries, sizeof(rate_entry_t), ctx_cmp); calc_sum_rates(num_entries, CTX_VAL); print_top(rate_tab, num_entries, CTX_VAL); } if (show_spec & SHOW_WRITES) { qsort(rate_tab, num_entries, sizeof(rate_entry_t), write_cmp); print_top(rate_tab, num_entries, WRITES_VAL); } if (show_spec & SHOW_READS) { qsort(rate_tab, num_entries, sizeof(rate_entry_t), read_cmp); print_top(rate_tab, num_entries, READS_VAL); } if (show_spec & SHOW_RSS) { qsort(rate_tab, num_entries, sizeof(rate_entry_t), rss_cmp); print_top(rate_tab, num_entries, RSS_VAL); } if (show_spec & SHOW_SYS) { qsort(rate_tab, num_entries, sizeof(rate_entry_t), sys_cmp); calc_sum_rates(num_entries, SYS_VAL); print_top(rate_tab, num_entries, SYS_VAL); } if (show_spec & SHOW_USR) { qsort(rate_tab, num_entries, sizeof(rate_entry_t), usr_cmp); calc_sum_rates(num_entries, USR_VAL); print_top(rate_tab, num_entries, USR_VAL); } } if (num_times-1 == num_samples) { exit(0); } }
int QmcContext::fetch(bool update) { int i, sts; pmResult *result; for (i = 0; i < my.metrics.size(); i++) { QmcMetric *metric = my.metrics[i]; if (metric->status() < 0) continue; metric->shiftValues(); } // Inform each indom that we are about to do a new fetch so any // indom changes are now irrelevant for (i = 0; i < my.indoms.size(); i++) my.indoms[i]->newFetch(); sts = pmUseContext(my.context); if (sts >= 0) { for (i = 0; i < my.indoms.size(); i++) { if (my.indoms[i]->diffProfile()) sts = my.indoms[i]->genProfile(); } } else if (pmDebug & DBG_TRACE_OPTFETCH) { QTextStream cerr(stderr); cerr << "QmcContext::fetch: Unable to switch to this context: " << pmErrStr(sts) << endl; } if (sts >= 0 && my.needReconnect) { sts = pmReconnectContext(my.context); if (sts >= 0) { my.needReconnect = false; if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcContext::fetch: Reconnected context \"" << *my.source << endl; } } else if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcContext::fetch: Reconnect failed: " << pmErrStr(sts) << endl; } } if (sts >= 0 && my.pmids.size()) { if (pmDebug & DBG_TRACE_OPTFETCH) { QTextStream cerr(stderr); cerr << "QmcContext::fetch: fetching context " << *this << endl; } sts = pmFetch(my.pmids.size(), (pmID *)(my.pmids.toVector().data()), &result); if (sts >= 0) { my.previousTime = my.currentTime; my.currentTime = result->timestamp; my.delta = __pmtimevalSub(&my.currentTime, &my.previousTime); for (i = 0; i < my.metrics.size(); i++) { QmcMetric *metric = my.metrics[i]; if (metric->status() < 0) continue; Q_ASSERT((int)metric->idIndex() < result->numpmid); metric->extractValues(result->vset[metric->idIndex()]); } pmFreeResult(result); } else { if (pmDebug & DBG_TRACE_OPTFETCH) { QTextStream cerr(stderr); cerr << "QmcContext::fetch: pmFetch: " << pmErrStr(sts) << endl; } for (i = 0; i < my.metrics.size(); i++) { QmcMetric *metric = my.metrics[i]; if (metric->status() < 0) continue; metric->setError(sts); } if (sts == PM_ERR_IPC || sts == PM_ERR_TIMEOUT) my.needReconnect = true; } if (update) { if (pmDebug & DBG_TRACE_OPTFETCH) { QTextStream cerr(stderr); cerr << "QmcContext::fetch: Updating metrics" << endl; } for (i = 0; i < my.metrics.size(); i++) { QmcMetric *metric = my.metrics[i]; if (metric->status() < 0) continue; metric->update(); } } } else if (pmDebug & DBG_TRACE_OPTFETCH) { QTextStream cerr(stderr); cerr << "QmcContext::fetch: nothing to fetch" << endl; } return sts; }
/* * 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 c; int sts; int e_sts = 0; int errflag = 0; int ahtype = 0; int verbose = 0; int quick = 0; char *host = NULL; /* pander to gcc */ pmResult *result; pmResult *prev = NULL; struct timeval start = { 0,0 }; struct timeval end; int tzh; off_t trunc_size = 0; __pmSetProgname(argv[0]); while ((c = getopt(argc, argv, "a:D:t:qv?")) != EOF) { switch (c) { case 'a': /* archive name */ if (ahtype != 0) { fprintf(stderr, "%s: at most one of -a and/or -h allowed\n", pmProgname); errflag++; } ahtype = PM_CONTEXT_ARCHIVE; host = optarg; break; #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 't': /* truncate */ trunc_size = atol(optarg); break; case 'q': /* quick */ quick = 1; break; case 'v': /* verbose */ verbose++; break; case '?': default: errflag++; break; } } if (errflag || optind < argc) { fprintf(stderr, "Usage: %s options ...\n\ \n\ Options\n\ -a archive metrics source is an archive log\n\ -t size truncate archive to size bytes\n\ -q quick (read last 3 records, not the whole archive)\n\ -v verbose\n", pmProgname); exit(1); } if (ahtype != PM_CONTEXT_ARCHIVE) { fprintf(stderr, "%s: -a is not optional!\n", pmProgname); exit(1); } /* truncate if -t specified, _before_ opening archive */ if (trunc_size != 0) { if (access(host, W_OK) == 0) { if (truncate(host, trunc_size) != 0) { fprintf(stderr, "%s: file %s exists, but cannot truncate\n", pmProgname, host); exit(1); } } else { char path[MAXPATHLEN]; sprintf(path, "%s.0", host); if (access(path, W_OK) == 0) { if (truncate(path, trunc_size) != 0) { fprintf(stderr, "%s: file %s exists, but cannot truncate\n", pmProgname, path); exit(1); } } else { fprintf(stderr, "%s: cannot find writeable %s or %s\n", pmProgname, host, path); exit(1); } } } if ((sts = pmNewContext(ahtype, host)) < 0) { fprintf(stderr, "%s: Cannot open archive \"%s\": %s\n", pmProgname, host, pmErrStr(sts)); exit(1); } /* force -z (timezone of archive */ if ((tzh = pmNewContextZone()) < 0) { fprintf(stderr, "%s: Cannot set context timezone: %s\n", pmProgname, pmErrStr(tzh)); exit(1); } sts = pmGetArchiveEnd(&end); if (sts < 0) { printf("pmGetArchiveEnd: %s\n", pmErrStr(sts)); } else { if (verbose) { printf("pmGetArchiveEnd time: "); printstamp(&end); printf("\n"); } } sts = pmSetMode(PM_MODE_BACK, &end, 0); if (sts < 0) { printf("pmSetMode PM_MODE_BACK: %s\n", pmErrStr(sts)); exit(1); } sts = pmFetchArchive(&result); if (sts < 0) { printf("pmFetchArchive: %s\n", pmErrStr(sts)); e_sts = 1; } else { if (verbose) { printf("last result time (direct): "); printstamp(&result->timestamp); printf("\n"); } if (result->timestamp.tv_sec != end.tv_sec || result->timestamp.tv_usec != end.tv_usec) { printf("Mismatch: end="); printstamp(&end); printf(" direct="); printstamp(&result->timestamp); printf("\n"); e_sts = 1; } start.tv_sec = result->timestamp.tv_sec; start.tv_usec = result->timestamp.tv_usec; pmFreeResult(result); } if (quick && e_sts == 0) { int i; for (i = 0; i < 2; i++) { sts = pmFetchArchive(&result); if (sts >= 0) { start.tv_sec = result->timestamp.tv_sec; start.tv_usec = result->timestamp.tv_usec; pmFreeResult(result); } } } else { /* start from the epoch and move forward */ start.tv_sec = 0; start.tv_usec = 0; } sts = pmSetMode(PM_MODE_FORW, &start, 0); if (sts < 0) { printf("pmSetMode PM_MODE_FORW: %s\n", pmErrStr(sts)); exit(1); } while ((sts = pmFetchArchive(&result)) >= 0) { if (prev != NULL) pmFreeResult(prev); prev = result; } if (verbose) printf("pmFetchArchive: %s\n", pmErrStr(sts)); if (prev == NULL) { printf("no results!\n"); } else { if (verbose) { printf("last result time (serial): "); printstamp(&prev->timestamp); printf("\n"); } if (prev->timestamp.tv_sec != end.tv_sec || prev->timestamp.tv_usec != end.tv_usec) { printf("Mismatch: end="); printstamp(&end); printf(" serial="); printstamp(&prev->timestamp); printf("\n"); e_sts = 1; } pmFreeResult(prev); } exit(e_sts); }
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); }
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 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); }
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 DoFetch(ClientInfo *cip, __pmPDU* pb) { int i, j; int sts; int ctxnum; __pmTimeval when; int nPmids; pmID *pmidList; static pmResult *endResult = NULL; static int maxnpmids = 0; /* sizes endResult */ DomPmidList *dList; /* NOTE: NOT indexed by agent index */ static int nDoms = 0; static pmResult **results = NULL; static int *resIndex = NULL; __pmFdSet waitFds; __pmFdSet readyFds; int nWait; int maxFd; struct timeval timeout; if (nAgents > nDoms) { if (results != NULL) free(results); if (resIndex != NULL) free(resIndex); results = (pmResult **)malloc((nAgents + 1) * sizeof (pmResult *)); resIndex = (int *)malloc((nAgents + 1) * sizeof(int)); if (results == NULL || resIndex == NULL) { __pmNoMem("DoFetch.results", (nAgents + 1) * sizeof (pmResult *) + (nAgents + 1) * sizeof(int), PM_FATAL_ERR); } nDoms = nAgents; } memset(results, 0, (nAgents + 1) * sizeof(results[0])); sts = __pmDecodeFetch(pb, &ctxnum, &when, &nPmids, &pmidList); if (sts < 0) return sts; /* Check that a profile has been received from the specified context */ if (ctxnum < 0 || ctxnum >= cip->szProfile || cip->profile[ctxnum] == NULL) { __pmUnpinPDUBuf(pb); if (ctxnum < 0 || ctxnum >= cip->szProfile) __pmNotifyErr(LOG_ERR, "DoFetch: bad ctxnum=%d\n", ctxnum); else __pmNotifyErr(LOG_ERR, "DoFetch: no profile for ctxnum=%d\n", ctxnum); return PM_ERR_NOPROFILE; } if (nPmids > maxnpmids) { int need; if (endResult != NULL) free(endResult); need = (int)sizeof(pmResult) + (nPmids - 1) * (int)sizeof(pmValueSet *); if ((endResult = (pmResult *)malloc(need)) == NULL) { __pmNoMem("DoFetch.endResult", need, PM_FATAL_ERR); } maxnpmids = nPmids; } dList = SplitPmidList(nPmids, pmidList); /* For each domain in the split pmidList, dispatch the per-domain subset * of pmIDs to the appropriate agent. For DSO agents, the pmResult will * come back immediately. If a request cannot be sent to an agent, a * suitable pmResult (containing metric not available values) will be * returned. */ __pmFD_ZERO(&waitFds); nWait = 0; maxFd = -1; for (i = 0; dList[i].domain != -1; i++) { j = mapdom[dList[i].domain]; results[j] = SendFetch(&dList[i], &agent[j], cip, ctxnum); if (results[j] == NULL) { /* Wait for agent's response */ int fd = agent[j].outFd; agent[j].status.busy = 1; __pmFD_SET(fd, &waitFds); if (fd > maxFd) maxFd = fd; nWait++; } } /* Construct pmResult for bad-pmID list */ if (dList[i].listSize != 0) results[nAgents] = MakeBadResult(dList[i].listSize, dList[i].list, PM_ERR_NOAGENT); /* Wait for results to roll in from agents */ while (nWait > 0) { __pmFD_COPY(&readyFds, &waitFds); if (nWait > 1) { timeout.tv_sec = _pmcd_timeout; timeout.tv_usec = 0; retry: setoserror(0); sts = __pmSelectRead(maxFd+1, &readyFds, &timeout); if (sts == 0) { __pmNotifyErr(LOG_INFO, "DoFetch: select timeout"); /* Timeout, terminate agents with undelivered results */ for (i = 0; i < nAgents; i++) { if (agent[i].status.busy) { /* Find entry in dList for this agent */ for (j = 0; dList[j].domain != -1; j++) if (dList[j].domain == agent[i].pmDomainId) break; results[i] = MakeBadResult(dList[j].listSize, dList[j].list, PM_ERR_NOAGENT); pmcd_trace(TR_RECV_TIMEOUT, agent[i].outFd, PDU_RESULT, 0); CleanupAgent(&agent[i], AT_COMM, agent[i].inFd); } } break; } else if (sts < 0) { if (neterror() == EINTR) goto retry; /* this is not expected to happen! */ __pmNotifyErr(LOG_ERR, "DoFetch: fatal select failure: %s\n", netstrerror()); Shutdown(); exit(1); } } /* Read results from agents that have them ready */ for (i = 0; i < nAgents; i++) { AgentInfo *ap = &agent[i]; int pinpdu; if (!ap->status.busy || !__pmFD_ISSET(ap->outFd, &readyFds)) continue; ap->status.busy = 0; __pmFD_CLR(ap->outFd, &waitFds); nWait--; pinpdu = sts = __pmGetPDU(ap->outFd, ANY_SIZE, _pmcd_timeout, &pb); if (sts > 0) pmcd_trace(TR_RECV_PDU, ap->outFd, sts, (int)((__psint_t)pb & 0xffffffff)); if (sts == PDU_RESULT) { if ((sts = __pmDecodeResult(pb, &results[i])) >= 0) if (results[i]->numpmid != aFreq[i]) { pmFreeResult(results[i]); sts = PM_ERR_IPC; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL0) __pmNotifyErr(LOG_ERR, "DoFetch: \"%s\" agent given %d pmIDs, returned %d\n", ap->pmDomainLabel, aFreq[i], results[i]->numpmid); #endif } } else { if (sts == PDU_ERROR) { int s; if ((s = __pmDecodeError(pb, &sts)) < 0) sts = s; else if (sts >= 0) sts = PM_ERR_GENERIC; pmcd_trace(TR_RECV_ERR, ap->outFd, PDU_RESULT, sts); } else if (sts >= 0) { pmcd_trace(TR_WRONG_PDU, ap->outFd, PDU_RESULT, sts); sts = PM_ERR_IPC; } } if (pinpdu > 0) __pmUnpinPDUBuf(pb); if (sts < 0) { /* Find entry in dList for this agent */ for (j = 0; dList[j].domain != -1; j++) if (dList[j].domain == agent[i].pmDomainId) break; results[i] = MakeBadResult(dList[j].listSize, dList[j].list, sts); if (sts == PM_ERR_PMDANOTREADY) { /* the agent is indicating it can't handle PDUs for now */ int k; extern int CheckError(AgentInfo *ap, int sts); for (k = 0; k < dList[j].listSize; k++) results[i]->vset[k]->numval = PM_ERR_AGAIN; sts = CheckError(&agent[i], sts); } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL0) { fprintf(stderr, "RESULT error from \"%s\" agent : %s\n", ap->pmDomainLabel, pmErrStr(sts)); } #endif if (sts == PM_ERR_IPC || sts == PM_ERR_TIMEOUT) CleanupAgent(ap, AT_COMM, ap->outFd); } } } endResult->numpmid = nPmids; __pmtimevalNow(&endResult->timestamp); /* The order of the pmIDs in the per-domain results is the same as in the * original request, but on a per-domain basis. resIndex is an array of * indices (one per agent) of the next metric to be retrieved from each * per-domain result's vset. */ memset(resIndex, 0, (nAgents + 1) * sizeof(resIndex[0])); for (i = 0; i < nPmids; i++) { j = mapdom[((__pmID_int *)&pmidList[i])->domain]; endResult->vset[i] = results[j]->vset[resIndex[j]++]; } pmcd_trace(TR_XMIT_PDU, cip->fd, PDU_RESULT, endResult->numpmid); sts = 0; if (cip->status.changes) { /* notify client of PMCD state change */ sts = __pmSendError(cip->fd, FROM_ANON, (int)cip->status.changes); if (sts > 0) sts = 0; cip->status.changes = 0; } if (sts == 0) sts = __pmSendResult(cip->fd, FROM_ANON, endResult); if (sts < 0) { pmcd_trace(TR_XMIT_ERR, cip->fd, PDU_RESULT, sts); CleanupClient(cip, sts); } /* * pmFreeResult() all the accumulated results. */ for (i = 0; dList[i].domain != -1; i++) { j = mapdom[dList[i].domain]; if (agent[j].ipcType == AGENT_DSO && agent[j].status.connected && !agent[j].status.madeDsoResult) /* Living DSO's manage their own pmResult skeleton unless * MakeBadResult was called to create the result. The value sets * within the skeleton need to be freed though! */ __pmFreeResultValues(results[j]); else /* For others it is dynamically allocated in __pmDecodeResult or * MakeBadResult */ pmFreeResult(results[j]); } if (results[nAgents] != NULL) pmFreeResult(results[nAgents]); __pmUnpinPDUBuf(pmidList); return 0; }
void dodso(int pdu) { int sts = 0; /* initialize to pander to gcc */ int length; pmDesc desc; pmDesc *desc_list = NULL; pmResult *result; __pmInResult *inresult; int i; int j; char *buffer; struct timeval start; struct timeval end; char name[32]; char **namelist; int *statuslist; pmID pmid; if (timer != 0) __pmtimevalNow(&start); switch (pdu) { case PDU_DESC_REQ: printf("PMID: %s\n", pmIDStr(param.pmid)); if ((sts = dodso_desc(param.pmid, &desc)) >= 0) __pmPrintDesc(stdout, &desc); else printf("Error: DSO desc() failed: %s\n", pmErrStr(sts)); break; case PDU_FETCH: printf("PMID(s):"); for (i = 0; i < param.numpmid; i++) printf(" %s", pmIDStr(param.pmidlist[i])); putchar('\n'); if (get_desc) { desc_list = (pmDesc *)malloc(param.numpmid * sizeof(pmDesc)); if (desc_list == NULL) { printf("Error: DSO fetch() failed: %s\n", pmErrStr(ENOMEM)); return; } for (i = 0; i < param.numpmid; i++) { if ((sts = dodso_desc(param.pmidlist[i], &desc_list[i])) < 0) { printf("Error: DSO desc() failed: %s\n", pmErrStr(sts)); free(desc_list); return; } } } sts = 0; if (profile_changed) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_PDU) fprintf(stderr, "DSO profile()\n"); #endif sts = dispatch.version.any.profile(profile, dispatch.version.any.ext); if (sts < 0) printf("Error: DSO profile() failed: %s\n", pmErrStr(sts)); else profile_changed = 0; } if (sts >= 0) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_PDU) fprintf(stderr, "DSO fetch()\n"); #endif sts = dispatch.version.any.fetch(param.numpmid, param.pmidlist, &result, dispatch.version.any.ext); if (sts >= 0) { if (desc_list) _dbDumpResult(stdout, result, desc_list); else __pmDumpResult(stdout, result); /* * DSO PMDA will manage the pmResult skelton, but * we need to free the pmValueSets and values here */ __pmFreeResultValues(result); } else { printf("Error: DSO fetch() failed: %s\n", pmErrStr(sts)); } } if (desc_list) free(desc_list); break; case PDU_INSTANCE_REQ: printf("pmInDom: %s\n", pmInDomStr(param.indom)); #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_PDU) fprintf(stderr, "DSO instance()\n"); #endif sts = dispatch.version.any.instance(param.indom, param.number, param.name, &inresult, dispatch.version.any.ext); if (sts >= 0) printindom(stdout, inresult); else printf("Error: DSO instance() failed: %s\n", pmErrStr(sts)); break; case PDU_RESULT: printf("PMID: %s\n", pmIDStr(param.pmid)); printf("Getting description...\n"); desc_list = &desc; if ((sts = dodso_desc(param.pmid, desc_list)) < 0) { printf("Error: DSO desc() failed: %s\n", pmErrStr(sts)); return; } if (profile_changed) { printf("Sending Profile...\n"); sts = dispatch.version.any.profile(profile, dispatch.version.any.ext); if (sts < 0) { printf("Error: DSO profile() failed: %s\n", pmErrStr(sts)); return; } else profile_changed = 0; } printf("Getting Result Structure...\n"); sts = dispatch.version.any.fetch(1, &(desc.pmid), &result, dispatch.version.any.ext); if (sts < 0) { printf("Error: DSO fetch() failed: %s\n", pmErrStr(sts)); return; } #ifdef PCP_DEBUG else if (pmDebug & DBG_TRACE_FETCH) _dbDumpResult(stdout, result, desc_list); #endif sts = fillResult(result, desc.type); if (sts < 0) { pmFreeResult(result); return; } sts = dispatch.version.any.store(result, dispatch.version.any.ext); if (sts < 0) printf("Error: DSO store() failed: %s\n", pmErrStr(sts)); break; case PDU_TEXT_REQ: if (param.number == PM_TEXT_PMID) { printf("PMID: %s\n", pmIDStr(param.pmid)); i = param.pmid; } else { printf("pmInDom: %s\n", pmInDomStr(param.indom)); i = param.indom; } for (j = 0; j < 2; j++) { if (j == 0) param.number |= PM_TEXT_ONELINE; else { param.number &= ~PM_TEXT_ONELINE; param.number |= PM_TEXT_HELP; } sts = dispatch.version.any.text(i, param.number, &buffer, dispatch.version.any.ext); if (sts >= 0) { if (j == 0) { if (*buffer != '\0') printf("[%s]\n", buffer); else printf("[<no one line help text specified>]\n"); } else if (*buffer != '\0') printf("%s\n", buffer); else printf("<no help text specified>\n"); } else printf("Error: DSO text() failed: %s\n", pmErrStr(sts)); } break; case PDU_PMNS_IDS: if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) { printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface); break; } printf("PMID: %s\n", pmIDStr(param.pmid)); sts = dispatch.version.four.name(param.pmid, &namelist, dispatch.version.four.ext); if (sts > 0) { for (i = 0; i < sts; i++) { printf(" %s\n", namelist[i]); } free(namelist); } else if (sts == 0) printf("Warning: DSO name() returns 0\n"); else printf("Error: DSO name() failed: %s\n", pmErrStr(sts)); break; case PDU_PMNS_NAMES: if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) { printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface); break; } printf("Metric: %s\n", param.name); sts = dispatch.version.four.pmid(param.name, &pmid, dispatch.version.four.ext); if (sts >= 0) printf(" %s\n", pmIDStr(pmid)); else printf("Error: DSO pmid() failed: %s\n", pmErrStr(sts)); break; case PDU_PMNS_CHILD: if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) { printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface); break; } printf("Metric: %s\n", param.name); sts = dispatch.version.four.children(param.name, 0, &namelist, &statuslist, dispatch.version.four.ext); if (sts > 0) { for (i = 0; i < sts; i++) { printf(" %8.8s %s\n", statuslist[i] == 1 ? "non-leaf" : "leaf", namelist[i]); } free(namelist); free(statuslist); } else if (sts == 0) printf("Warning: DSO children() returns 0\n"); else printf("Error: DSO children() failed: %s\n", pmErrStr(sts)); break; case PDU_PMNS_TRAVERSE: if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) { printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface); break; } printf("Metric: %s\n", param.name); sts = dispatch.version.four.children(param.name, 1, &namelist, &statuslist, dispatch.version.four.ext); if (sts > 0) { for (i = 0; i < sts; i++) { printf(" %8.8s %s\n", statuslist[i] == 1 ? "non-leaf" : "leaf", namelist[i]); } free(namelist); free(statuslist); } else if (sts == 0) printf("Warning: DSO children() returns 0\n"); else printf("Error: DSO children() failed: %s\n", pmErrStr(sts)); break; case PDU_AUTH: if (dispatch.comm.pmda_interface < PMDA_INTERFACE_6) { printf("Error: PMDA Interface %d does not support authentication\n", dispatch.comm.pmda_interface); break; } j = param.number; /* attribute key */ buffer = param.name; /* attribute value */ if (buffer) length = strlen(buffer) + 1; /* length of value */ else length = 0; i = 0; /* client ID */ __pmAttrKeyStr_r(j, name, sizeof(name)-1); name[sizeof(name)-1] = '\0'; printf("Attribute: %s=%s\n", name, buffer ? buffer : "''"); sts = dispatch.version.six.attribute(i, j, buffer, length, dispatch.version.six.ext); if (sts >= 0) printf("Success\n"); else printf("Error: DSO attribute() failed: %s\n", pmErrStr(sts)); break; default: printf("Error: DSO PDU (%s) botch!\n", __pmPDUTypeStr(pdu)); break; } if (sts >= 0 && timer != 0) { __pmtimevalNow(&end); printf("Timer: %f seconds\n", __pmtimevalSub(&end, &start)); } }
/* execute fetches for given Task */ void taskFetch(Task *t) { Host *h; Fetch *f; Profile *p; Metric *m; pmResult *r; pmValueSet **v; int i; int sts; /* do all fetches, quick as you can */ h = t->hosts; while (h) { f = h->fetches; while (f) { if (f->result) pmFreeResult(f->result); if (! h->down) { pmUseContext(f->handle); if ((sts = pmFetch(f->npmids, f->pmids, &f->result)) < 0) { if (! archives) { __pmNotifyErr(LOG_ERR, "pmFetch from %s failed: %s\n", symName(f->host->name), pmErrStr(sts)); host_state_changed(symName(f->host->name), STATE_LOSTCONN); h->down = 1; mark_all(h); } f->result = NULL; } } else f->result = NULL; f = f->next; } h = h->next; } /* sort and distribute pmValueSets to requesting Metrics */ h = t->hosts; while (h) { if (! h->down) { f = h->fetches; while (f && (r = f->result)) { /* sort all vlists in result r */ v = r->vset; for (i = 0; i < r->numpmid; i++) { if ((*v)->numval > 0) { qsort((*v)->vlist, (size_t)(*v)->numval, sizeof(pmValue), compair); } v++; } /* distribute pmValueSets to Metrics */ p = f->profiles; while (p) { m = p->metrics; while (m) { for (i = 0; i < r->numpmid; i++) { if (m->desc.pmid == r->vset[i]->pmid) { if (r->vset[i]->numval > 0) { m->vset = r->vset[i]; m->stamp = __pmtimevalToReal(&r->timestamp); } break; } } m = m->next; } p = p->next; } f = f->next; } } h = h->next; } }