int QmcGroup::setArchiveMode(int mode, const struct timeval *when, int interval) { int sts, result = 0; for (unsigned int i = 0; i < numContexts(); i++) { if (my.contexts[i]->source().type() != PM_CONTEXT_ARCHIVE) continue; sts = pmUseContext(my.contexts[i]->handle()); if (sts < 0) { pmprintf("%s: Error: Unable to switch to context for %s: %s\n", pmProgname, my.contexts[i]->source().sourceAscii(), pmErrStr(sts)); result = sts; continue; } sts = pmSetMode(mode, when, interval); if (sts < 0) { pmprintf("%s: Error: Unable to set context mode for %s: %s\n", pmProgname, my.contexts[i]->source().sourceAscii(), pmErrStr(sts)); result = sts; } } sts = useContext(); if (sts < 0) result = sts; return result; }
static void * func3(void *arg) { char *fn = "func3"; int i; int j; FILE *f; if ((f = fopen("/tmp/func3.out", "w")) == NULL) { perror("func3 fopen"); pthread_exit("botch"); } j = pmUseContext(ctx3); if ( j < 0) { fprintf(f, "Error: %s: pmUseContext(%d) -> %s\n", fn, ctx3, pmErrStr(j)); fclose(f); pthread_exit("botch"); } pthread_barrier_wait(&barrier); for (j = 0; j < 100; j++) { for (i = 0; i < NMETRIC; i += 2) foo(f, fn, i, &count3); for (i = 1; i < NMETRIC; i += 2) foo(f, fn, i, &count3); } fclose(f); pthread_exit(NULL); }
int QmcContext::traverse(const char *name, QStringList &list) { int sts; theStringList = &list; theStringList->clear(); if ((sts = pmUseContext(my.context)) < 0) return sts; sts = pmTraversePMNS(name, QmcContext::dometric); if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); if (sts >= 0) { cerr << "QmcContext::traverse: Found " << list.size() << " names from " << name << endl; } else cerr << "QmcContext::traverse: Failed: " << pmErrStr(sts) << endl; } return sts; }
int QmcContext::lookupName(pmID pmid, QString **name) { char *value; int sts = 0; if ((sts = pmUseContext(my.context)) < 0) return sts; if (my.pmidCache.contains(pmid) == false) { if ((sts = pmNameID(pmid, &value)) >= 0) { *name = new QString(value); my.pmidCache.insert(pmid, *name); free(value); } } else { QString *np = my.pmidCache.value(pmid); if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcContext::lookupName: Matched id " << pmIDStr(pmid) << " to \"" << *np << "\"" << endl; } *name = np; } return sts; }
int QmcContext::lookupDesc(pmID pmid, QmcDesc **descriptor) { int sts; QmcDesc *descPtr; if ((sts = pmUseContext(my.context)) < 0) return sts; if (my.descCache.contains(pmid) == false) { descPtr = new QmcDesc(pmid); if (descPtr->status() < 0) { sts = descPtr->status(); delete descPtr; return sts; } my.descCache.insert(pmid, descPtr); if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcContext::lookupDesc: Add descriptor for " << pmIDStr(descPtr->id()) << endl; } } else { descPtr = my.descCache.value(pmid); if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcContext::lookupDesc: Reusing descriptor " << pmIDStr(descPtr->id()) << endl; } } *descriptor = descPtr; return 0; }
static void * func2(void *arg) { char *fn = "func2"; int i; int j; FILE *f; if ((f = fopen("/tmp/func2.out", "w")) == NULL) { perror("func2 fopen"); pthread_exit("botch"); } j = pmUseContext(ctx2); if ( j < 0) { fprintf(f, "Error: %s: pmUseContext(%d) -> %s\n", fn, ctx2, pmErrStr(j)); fclose(f); pthread_exit("botch"); } pthread_barrier_wait(&barrier); for (j = 0; j < 100; j++) { for (i = NMETRIC-1; i >= 0; i--) { foo(f, fn, i); } } fclose(f); pthread_exit(NULL); }
int QmcGroup::useDefault() { if (numContexts() == 0) createLocalContext(); if (numContexts() == 0) return my.localSource->status(); my.use = 0; return pmUseContext(context()->handle()); }
int QmcGroup::useContext() { int sts = 0; if ((context()->status() == 0) && (sts = pmUseContext(context()->handle())) < 0) pmprintf("%s: Error: Unable to reuse context to %s: %s\n", pmProgname, context()->source().sourceAscii(), pmErrStr(sts)); return sts; }
static void * func2(void *arg) { char *fn = "func2"; int i; int j; int sts; FILE *f; if ((f = fopen("/tmp/func2.out", "w")) == NULL) { perror("func2 fopen"); pthread_exit("botch"); } j = pmUseContext(ctx2); if ( j < 0) { fprintf(f, "Error: %s: pmUseContext(%d) -> %s\n", fn, ctx2, pmErrStr(j)); fclose(f); pthread_exit("botch"); } pthread_barrier_wait(&barrier); for (j = 0; j < 100; j++) { for (i = NMETRIC-1; i >= 0; i--) { if (ctx2 != ctx1) { /* * limit pmcd.control.register [1] in context 2 * - select 5 instances below */ int instlist[] = { 0, 1, 2, 4, 8 }; pthread_mutex_lock(&mymutex); if ((sts = pmDelProfile(desclist[1].indom, 0, NULL)) < 0) { fprintf(f, "Error: pmDelProfile(%s) -> %s\n", namelist[1], pmErrStr(sts)); fclose(f); pthread_exit("botch"); } if ((sts = pmAddProfile(desclist[1].indom, sizeof(instlist)/sizeof(instlist[0]), instlist)) < 0) { fprintf(f, "Error: pmAddProfile(%s) -> %s\n", namelist[1], pmErrStr(sts)); fclose(f); pthread_exit("botch"); } } foo(f, fn, i); if (ctx2 != ctx1) pthread_mutex_unlock(&mymutex); } } fclose(f); pthread_exit(NULL); }
int QmcContext::lookupInDom(QmcDesc *descPtr, uint_t& indom) { int i, sts; QmcIndom *indomPtr; if ((sts = pmUseContext(my.context)) < 0) return sts; indom = UINT_MAX; if (descPtr->desc().indom != PM_INDOM_NULL) { for (i = 0; i < my.indoms.size(); i++) if (my.indoms[i]->id() == (int)descPtr->desc().indom) break; if (i == my.indoms.size()) { indomPtr = new QmcIndom(my.source->type(), *descPtr); if (indomPtr->status() < 0) { sts = indomPtr->status(); delete indomPtr; return sts; } my.indoms.append(indomPtr); indom = my.indoms.size() - 1; if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcContext::lookupInDom: Add indom for " << pmInDomStr(indomPtr->id()) << endl; } } else { indomPtr = my.indoms[i]; indom = i; if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcContext::lookupInDom: Reusing indom " << pmInDomStr(indomPtr->id()) << endl; } } } return 0; }
int QmcContext::lookupPMID(const char *name, pmID& id) { QString key = name; int sts; if ((sts = pmUseContext(my.context)) < 0) return sts; if (my.nameCache.contains(key) == false) { if ((sts = pmLookupName(1, (char **)(&name), &id)) >= 0) my.nameCache.insert(key, id); } else { id = my.nameCache.value(key); if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcContext::lookupPMID: Matched \"" << name << "\" to id " << pmIDStr(id) << endl; } sts = 1; } return sts; }
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); }
/* Return (in result) a list of active pmlogger ports on the specified machine. * The return value of the function is the number of elements in the array. * The caller must NOT free any part of the result stucture, it's storage is * managed here. Subsequent calls will overwrite the data so the caller should * copy it if persistence is required. */ int __pmLogFindPort(const char *host, int pid, __pmLogPort **lpp) { int ctx, oldctx; char *ctxhost; int sts, numval; int i, j; int findone = pid != PM_LOG_ALL_PIDS; int localcon = 0; /* > 0 for local connection */ pmDesc desc; pmResult *res; char *namelist[] = {"pmcd.pmlogger.port"}; pmID pmid; if (PM_MULTIPLE_THREADS(PM_SCOPE_LOGPORT)) return PM_ERR_THREAD; *lpp = NULL; /* pass null back in event of error */ localcon = __pmIsLocalhost(host); if (localcon > 0) /* do the work here instead of making PMCD do it */ return __pmLogFindLocalPorts(pid, lpp); else if (localcon < 0) return localcon; /* note: there may not be a current context */ ctx = 0; oldctx = pmWhichContext(); /* * Enclose ctxhost in [] in case it is an ipv6 address. This prevents * the first colon from being taken as a port separator by pmNewContext * and does no harm otherwise. */ ctxhost = malloc(strlen(host) + 2 + 1); if (ctxhost == NULL) { sts = -ENOMEM; goto ctxErr; } sprintf(ctxhost, "[%s]", host); ctx = pmNewContext(PM_CONTEXT_HOST, ctxhost); free(ctxhost); if (ctx < 0) return ctx; if ((sts = pmLookupName(1, namelist, &pmid)) < 0) goto ctxErr; if ((sts = pmLookupDesc(pmid, &desc)) < 0) goto ctxErr; if ((sts = pmFetch(1, &pmid, &res) < 0)) goto ctxErr; if ((sts = numval = res->vset[0]->numval) < 0) goto resErr; j = 0; if (numval) { if (resize_logports(findone ? 1 : numval) < 0) { sts = -oserror(); goto resErr; } /* scan the pmResult, copying matching pid(s) to logport */ for (i = j = 0; i < numval; i++) { __pmLogPort *p = &logport[j]; pmValue *vp = &res->vset[0]->vlist[i]; if (vp->inst == 1) /* old vcr instance (pseudo-init) */ continue; if (findone && vp->inst != pid) continue; p->pid = vp->inst; p->port = vp->value.lval; sts = pmNameInDom(desc.indom, p->pid, &p->name); if (sts < 0) { p->name = NULL; goto resErr; } j++; if (findone) /* found one, stop searching */ break; } *lpp = logport; } sts = j; /* the number actually added */ resErr: pmFreeResult(res); ctxErr: if (oldctx >= 0) pmUseContext(oldctx); if (ctx >= 0) pmDestroyContext(ctx); return sts; }
static void * func3(void *arg) { char *fn = "func3"; int i; int j; int sts; FILE *f; if ((f = fopen("/tmp/func3.out", "w")) == NULL) { perror("func3 fopen"); pthread_exit("botch"); } j = pmUseContext(ctx3); if ( j < 0) { fprintf(f, "Error: %s: pmUseContext(%d) -> %s\n", fn, ctx3, pmErrStr(j)); fclose(f); pthread_exit("botch"); } pthread_barrier_wait(&barrier); for (j = 0; j < 100; j++) { for (i = 0; i < NMETRIC; i += 2) { if (ctx3 != ctx2) { /* * limit sampledso.bin [2] in context 3 * - exclude instances below, leaving 7 instances 200, ... 800 */ int instlist[] = { 100, 900 }; if ((sts = pmAddProfile(desclist[2].indom, 0, NULL)) < 0) { fprintf(f, "Error: pmAddProfile(%s) -> %s\n", namelist[2], pmErrStr(sts)); fclose(f); pthread_exit("botch"); } if ((sts = pmDelProfile(desclist[2].indom, sizeof(instlist)/sizeof(instlist[0]), instlist)) < 0) { fprintf(f, "Error: pmDelProfile(%s) -> %s\n", namelist[2], pmErrStr(sts)); fclose(f); pthread_exit("botch"); } } else { pthread_mutex_lock(&mymutex); if ((sts = pmAddProfile(desclist[1].indom, 0, NULL)) < 0) { fprintf(f, "Error: pmAddProfile(%s) -> %s\n", namelist[1], pmErrStr(sts)); fclose(f); pthread_exit("botch"); } } foo(f, fn, i); if (ctx3 == ctx2) pthread_mutex_unlock(&mymutex); } for (i = 1; i < NMETRIC; i += 2) { /* inherit instance profile from loop above */ if (ctx3 == ctx2) { pthread_mutex_lock(&mymutex); if ((sts = pmAddProfile(desclist[1].indom, 0, NULL)) < 0) { fprintf(f, "Error: pmAddProfile(%s) -> %s\n", namelist[1], pmErrStr(sts)); fclose(f); pthread_exit("botch"); } } foo(f, fn, i); if (ctx3 == ctx2) pthread_mutex_unlock(&mymutex); } } fclose(f); pthread_exit(NULL); }
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; }
void QmcSource::retryConnect(int type, QString &source) { int oldTZ; int oldContext; int offset; int sts; char *tzs; QString name; QString hostSpec; switch (type) { case PM_CONTEXT_LOCAL: my.desc = "Local context"; my.host = my.source = localHost; my.proxy = ""; break; case PM_CONTEXT_HOST: my.desc = "host \""; my.desc.append(source); my.desc.append(QChar('\"')); my.host = source; my.proxy = getenv("PMPROXY_HOST"); if ((offset = my.host.indexOf('?')) >= 0) { my.attrs = my.host; my.attrs.remove(0, offset+1); my.host.truncate(offset); name = my.attrs.section(QString("container="), -1); if (name != QString::null && (offset = name.indexOf(',')) > 0) name.truncate(offset); my.context_container = name; } if ((offset = my.host.indexOf('@')) >= 0) { my.proxy = my.host; my.proxy.remove(0, offset+1); } my.source = my.host; break; case PM_CONTEXT_ARCHIVE: my.desc = "archive \""; my.desc.append(source); my.desc.append(QChar('\"')); my.source = source; my.proxy = ""; break; } oldContext = pmWhichContext(); hostSpec = source; my.status = pmNewContext(type | my.flags, (const char *)hostSpec.toAscii()); if (my.status >= 0) { my.handles.append(my.status); // Fetch the server-side host name for this context, properly as of pcp 3.8.3+. my.context_hostname = pmGetContextHostName(my.status); // NB: may leak memory if (my.context_hostname == "") // may be returned for errors or PM_CONTEXT_LOCAL my.context_hostname = localHost; if (my.type == PM_CONTEXT_ARCHIVE) { pmLogLabel lp; sts = pmGetArchiveLabel(&lp); if (sts < 0) { pmprintf("%s: Unable to obtain log label for \"%s\": %s\n", pmProgname, (const char *)my.desc.toAscii(), pmErrStr(sts)); my.host = "unknown?"; my.status = sts; goto done; } else { my.host = lp.ll_hostname; my.start = lp.ll_start; } sts = pmGetArchiveEnd(&my.end); if (sts < 0) { pmprintf("%s: Unable to determine end of \"%s\": %s\n", pmProgname, (const char *)my.desc.toAscii(), pmErrStr(sts)); my.status = sts; goto done; } } else { gettimeofday(&my.start, NULL); my.end = my.start; } if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcSource::QmcSource: Created context " << my.handles.last() << " to " << my.desc << endl; } oldTZ = pmWhichZone(&tzs); my.tz = pmNewContextZone(); if (my.tz < 0) pmprintf("%s: Warning: Unable to obtain timezone for %s: %s\n", pmProgname, (const char *)my.desc.toAscii(), pmErrStr(my.tz)); else { sts = pmWhichZone(&tzs); if (sts >= 0) my.timezone = tzs; else pmprintf("%s: Warning: Unable to obtain timezone for %s: %s\n", pmProgname, (const char *)my.desc.toAscii(), pmErrStr(sts)); } if (oldTZ >= 0) { sts = pmUseZone(oldTZ); if (sts < 0) { pmprintf("%s: Warning: Unable to switch timezones." " Using timezone for %s: %s\n", pmProgname, (const char *)my.desc.toAscii(), pmErrStr(sts)); } } } else if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcSource::QmcSource: Context to " << source << " failed: " << pmErrStr(my.status) << endl; } done: sourceList.append(this); if (oldContext >= 0) { sts = pmUseContext(oldContext); if (sts < 0) { pmprintf("%s: Warning: Unable to switch contexts." " Using context to %s: %s\n", pmProgname, (const char *)my.desc.toAscii(), pmErrStr(sts)); } } }
/* find Profile for Metric */ static Profile * findProfile(Fetch *f, Metric *m) { Profile *p; int sts; /* find existing Profile */ p = f->profiles; while (p) { if (p->indom == m->desc.indom) { m->next = p->metrics; if (p->metrics) p->metrics->prev = m; p->metrics = m; break; } p = p->next; } /* create new Profile */ if (p == NULL) { m->next = NULL; p = newProfile(f, m->desc.indom); p->next = f->profiles; if (f->profiles) f->profiles->prev = p; f->profiles = p; p->metrics = m; } /* add instances required by Metric to Profile */ if ((sts = pmUseContext(f->handle)) < 0) { fprintf(stderr, "%s: pmUseContext failed: %s\n", pmProgname, pmErrStr(sts)); exit(1); } /* * If any rule requires all instances, then ignore restricted * instance lists from all other rules */ if (m->specinst == 0 && p->need_all == 0) { sts = pmDelProfile(p->indom, 0, (int *)0); if (sts < 0) { fprintf(stderr, "%s: pmDelProfile failed: %s\n", pmProgname, pmErrStr(sts)); exit(1); } sts = pmAddProfile(p->indom, 0, (int *)0); p->need_all = 1; } else if (m->specinst > 0 && p->need_all == 0) sts = pmAddProfile(p->indom, m->m_idom, m->iids); else sts = 0; if (sts < 0) { fprintf(stderr, "%s: pmAddProfile failed: %s\n", pmProgname, pmErrStr(sts)); exit(1); } m->profile = p; return p; }
int QmcSource::dupContext() { int sts = 0; if (my.status < 0) return my.status; if (my.dupFlag == false && my.handles.size() == 1) { sts = pmUseContext(my.handles[0]); if (sts >= 0) { sts = my.handles[0]; my.dupFlag = true; if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcSource::dupContext: Using original context for " << my.desc << endl; } } else pmprintf("%s: Error: Unable to switch to context for \"%s\": %s\n", pmProgname, (const char *)my.desc.toAscii(), pmErrStr(sts)); } else if (my.handles.size()) { sts = pmUseContext(my.handles[0]); if (sts >= 0) { sts = pmDupContext(); if (sts >= 0) { my.handles.append(sts); if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcSource::dupContext: " << my.desc << " duplicated, handle[" << my.handles.size() - 1 << "] = " << sts << endl; } } else pmprintf("%s: Error: " "Unable to duplicate context to \"%s\": %s\n", pmProgname, (const char *)my.desc.toAscii(), pmErrStr(sts)); } else pmprintf("%s: Error: Unable to switch to context for \"%s\": %s\n", pmProgname, (const char *)my.desc.toAscii(), pmErrStr(sts)); } // No active contexts, create a new context else { sts = pmNewContext(my.type, sourceAscii()); if (sts >= 0) { my.handles.append(sts); if (pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcSource::dupContext: new context to " << my.desc << " created, handle = " << sts << endl; } } } if (sts < 0 && pmDebug & DBG_TRACE_PMC) { QTextStream cerr(stderr); cerr << "QmcSource::dupContext: context to " << my.desc << " failed: " << pmErrStr(my.status) << endl; } return sts; }
static void func(void) { int sts; char **children; char *p; if ((sts = pmUseContext(ctx)) < 0) { printf("pmUseContext(%d): %s\n", ctx, pmErrStr(sts)); pthread_exit(NULL); } /* * expect this to fail for the second thread through when * using PM_CONTEXT_LOCAL */ if ((sts = pmDupContext()) < 0) printf("pmDupContext: %s\n", pmErrStr(sts)); else printf("pmDupContext: -> %d\n", sts); if ((sts = pmUseContext(ctx)) < 0) { printf("pmUseContext(%d): %s\n", ctx, pmErrStr(sts)); pthread_exit(NULL); } else printf("pmUseContext(%d) -> %d\n", ctx, sts); if ((sts = pmLookupName(1, namelist, pmidlist)) < 0) printf("pmLookupName: %s\n", pmErrStr(sts)); else printf("pmLookupName: -> %s\n", pmIDStr(pmidlist[0])); pthread_barrier_wait(&barrier); if (pmidlist[0] == 0) pthread_exit("Loser failed to get pmid!"); if ((sts = pmGetPMNSLocation()) < 0) printf("pmGetPMNSLocation: %s\n", pmErrStr(sts)); else printf("pmGetPMNSLocation: -> %d\n", sts); /* leaf node, expect no children */ if ((sts = pmGetChildrenStatus(namelist[0], &children, NULL)) < 0) printf("pmGetChildrenStatus: %s\n", pmErrStr(sts)); else printf("pmGetChildrenStatus: -> %d\n", sts); if ((sts = pmLookupDesc(pmidlist[0], &desc)) < 0) printf("pmLookupDesc: %s\n", pmErrStr(sts)); else printf("pmLookupDesc: -> %s type=%s indom=%s\n", pmIDStr(desc.pmid), pmTypeStr(desc.type), pmInDomStr(desc.indom)); pthread_barrier_wait(&barrier); if (desc.pmid == 0) pthread_exit("Loser failed to get pmDesc!"); if ((sts = pmLookupText(pmidlist[0], PM_TEXT_ONELINE, &p)) < 0) printf("pmLookupText: %s\n", pmErrStr(sts)); else printf("pmLookupText: -> %s\n", p); if ((sts = pmGetInDom(desc.indom, &instance, &instname)) < 0) printf("pmGetInDom: %s: %s\n", pmInDomStr(desc.indom), pmErrStr(sts)); else printf("pmGetInDom: -> %d\n", sts); pthread_barrier_wait(&barrier); if (instance == NULL) pthread_exit("Loser failed to get indom!"); if ((sts = pmNameInDom(desc.indom, instance[0], &p)) < 0) printf("pmNameInDom: %s\n", pmErrStr(sts)); else printf("pmNameInDom: %d -> %s\n", instance[0], p); if ((sts = pmLookupInDom(desc.indom, instname[0])) < 0) printf("pmLookupInDom: %s\n", pmErrStr(sts)); else printf("pmLookupInDom: %s -> %d\n", instname[0], sts); if ((sts = pmFetch(1, pmidlist, &rp)) < 0) printf("pmFetch: %s\n", pmErrStr(sts)); else printf("pmFetch: -> OK\n"); pthread_barrier_wait(&barrier); if (rp == NULL) pthread_exit("Loser failed to get pmResult!"); if ((sts = pmStore(rp)) < 0) printf("pmStore: %s\n", pmErrStr(sts)); else printf("pmStore: -> OK\n"); pthread_exit(NULL); }
int main(int argc, char **argv) { 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); } }
/* 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; } }