static void postExpr(Expr *x) { if (x->op == CND_FETCH) { instFetchExpr(x); } else { if (x->arg1) { postExpr(x->arg1); if (x->arg2) postExpr(x->arg2); } } }
/* fetch expression */ Expr * fetchExpr(char *mname, StringArray hnames, StringArray inames, Interval times) { Expr *x; Metric *marr, *m; int fsz, dsz; int sum; int i; /* calculate samplecounts for fetch and delay */ if (times.t1 == 0) { fsz = times.t2 - times.t1 + 1; dsz = 0; } else { fsz = times.t1 + 1; dsz = times.t2 - times.t1 + 1; } /* default host */ if (hnames.n == 0) { hnames.n = 1; } /* construct Metrics array */ marr = m = (Metric *) zalloc(hnames.n * sizeof(Metric)); sum = 0; for (i = 0; i < hnames.n; i++) { m->mname = symIntern(&metrics, mname); if (hnames.ss) { /* Explicitly specified host name, but is it a hostname or a connection-string? Depends on whether we're in archive-mode or not! In archive-mode, it's a host name, which we resolve to the archive file name by a search; if in live-mode, it's a connection string. */ if (archives) { m->hname = symIntern(&hosts, hnames.ss[i]); Archive *a = archives; while (a) { /* find archive for host */ if (strcmp(a->hname, hnames.ss[i]) == 0) break; a = a->next; } if (a) m->hconn = symIntern(&hosts, a->fname); else m->hconn = symIntern(&hosts, "unknown archive"); } else { m->hconn = symIntern(&hosts, hnames.ss[i]); /* We don't know the host name yet. We don't really want to connect at this time just to fish it out. See newContext. */ m->hname = symIntern(&hosts, ""); } } else { m->hconn = symIntern(&hosts, dfltHostConn); m->hname = symIntern(&hosts, ""); /* Filled in at newContext. */ } m->desc.sem = SEM_UNKNOWN; m->m_idom = -1; if (inames.n > 0) { m->specinst = inames.n; m->iids = alloc(inames.n * sizeof(int)); m->inames = inames.ss; } else { m->specinst = 0; m->iids = NULL; m->inames = NULL; } if (errs == 0) { int sts = initMetric(m); if (sts < 0) errs++; if (m->m_idom > 0) sum += m->m_idom; } m++; } if (sum == 0) sum = -1; /* error exit */ if (errs) { m = marr; for (i = 0; i < hnames.n; i++) { if (m->iids) free(m->iids); m++; } free(marr); return NULL; } /* construct fetch node */ x = newExpr(CND_FETCH, NULL, NULL, hnames.n, sum, fsz, fsz, SEM_UNKNOWN); newRingBfr(x); x->metrics = marr; findEval(x); instFetchExpr(x); /* patch in fetch node reference in each Metric */ m = marr; for (i = 0; i < hnames.n; i++) { m->expr = x; m++; } /* construct delay node */ if (dsz) { x = newExpr(CND_DELAY, x, NULL, x->hdom, x->e_idom, dsz, dsz, SEM_UNKNOWN); newRingBfr(x); findEval(x); } return x; }
/* reinitialize Metric - only for live host */ int /* 1: ok, 0: try again later, -1: fail */ reinitMetric(Metric *m) { char *hname = symName(m->hname); char *mname = symName(m->mname); char **inames; int *iids; int handle; int ret = 1; int sts; int i, j; /* set up temporary context */ if ((handle = newContext(hname)) < 0) return 0; host_state_changed(hname, STATE_RECONN); if ((sts = pmLookupName(1, &mname, &m->desc.pmid)) < 0) { ret = 0; goto end; } /* fill in performance metric descriptor */ if ((sts = pmLookupDesc(m->desc.pmid, &m->desc)) < 0) { ret = 0; goto end; } if (m->desc.type == PM_TYPE_STRING || m->desc.type == PM_TYPE_AGGREGATE || m->desc.type == PM_TYPE_AGGREGATE_STATIC || m->desc.type == PM_TYPE_EVENT || m->desc.type == PM_TYPE_HIGHRES_EVENT || m->desc.type == PM_TYPE_UNKNOWN) { fprintf(stderr, "%s: metric %s has non-numeric type\n", pmProgname, mname); ret = -1; } else if (m->desc.indom == PM_INDOM_NULL) { if (m->specinst != 0) { fprintf(stderr, "%s: metric %s has no instances\n", pmProgname, mname); ret = -1; } else m->m_idom = 1; } else { if ((sts = pmGetInDom(m->desc.indom, &iids, &inames)) < 0) { /* full profile */ ret = 0; } else { if (m->specinst == 0) { /* all instances */ m->iids = iids; m->m_idom = sts; m->inames = alloc(m->m_idom*sizeof(char *)); for (i = 0; i < m->m_idom; i++) { m->inames[i] = sdup(inames[i]); } } else { /* explicit instance profile */ m->m_idom = 0; for (i = 0; i < m->specinst; i++) { /* look for first matching instance name */ for (j = 0; j < sts; j++) { if (eqinst(m->inames[i], inames[j])) { m->iids[i] = iids[j]; m->m_idom++; break; } } if (j == sts) { m->iids[i] = PM_IN_NULL; ret = 0; } } if (sts > 0) { /* * pmGetInDom or pmGetInDomArchive returned some * instances above */ free(iids); } /* * if specinst != m_idom, then some not found ... move these * to the end of the list */ for (j = m->specinst-1; j >= 0; j--) { if (m->iids[j] != PM_IN_NULL) break; } for (i = 0; i < j; i++) { if (m->iids[i] == PM_IN_NULL) { /* need to swap */ char *tp; tp = m->inames[i]; m->inames[i] = m->inames[j]; m->iids[i] = m->iids[j]; m->inames[j] = tp; m->iids[j] = PM_IN_NULL; j--; } } } #if PCP_DEBUG if (pmDebug & DBG_TRACE_APPL1) { int numinst; fprintf(stderr, "reinitMetric: %s from %s: instance domain specinst=%d\n", mname, hname, m->specinst); if (m->m_idom < 1) fprintf(stderr, " %d instances!\n", m->m_idom); if (m->specinst == 0) numinst = m->m_idom; else numinst = m->specinst; for (i = 0; i < numinst; i++) { fprintf(stderr, " indom[%d]", i); if (m->iids[i] == PM_IN_NULL) fprintf(stderr, " ?missing"); else fprintf(stderr, " %d", m->iids[i]); fprintf(stderr, " \"%s\"\n", m->inames[i]); } } #endif if (sts > 0) { /* * pmGetInDom or pmGetInDomArchive returned some instances * above */ free(inames); } } } if (ret == 1) { /* compute conversion factor into canonical units - non-zero conversion factor flags initialized metric */ m->conv = scale(m->desc.units); /* automatic rate computation */ if (m->desc.sem == PM_SEM_COUNTER) { m->vals = (double *) ralloc(m->vals, m->m_idom * sizeof(double)); for (j = 0; j < m->m_idom; j++) m->vals[j] = 0; } } if (ret >= 0) { /* * re-shape, starting here are working up the expression until * we reach the top of the tree or the designated metrics * associated with the node are not the same */ Expr *x = m->expr; while (x) { /* * only re-shape expressions that may have set values */ if (x->op == CND_FETCH || x->op == CND_NEG || x->op == CND_ADD || x->op == CND_SUB || x->op == CND_MUL || x->op == CND_DIV || x->op == CND_SUM_HOST || x->op == CND_SUM_INST || x->op == CND_SUM_TIME || x->op == CND_AVG_HOST || x->op == CND_AVG_INST || x->op == CND_AVG_TIME || x->op == CND_MAX_HOST || x->op == CND_MAX_INST || x->op == CND_MAX_TIME || x->op == CND_MIN_HOST || x->op == CND_MIN_INST || x->op == CND_MIN_TIME || x->op == CND_EQ || x->op == CND_NEQ || x->op == CND_LT || x->op == CND_LTE || x->op == CND_GT || x->op == CND_GTE || x->op == CND_NOT || x->op == CND_AND || x->op == CND_OR || x->op == CND_RISE || x->op == CND_FALL || x->op == CND_INSTANT || x->op == CND_MATCH || x->op == CND_NOMATCH) { instFetchExpr(x); findEval(x); #if PCP_DEBUG if (pmDebug & DBG_TRACE_APPL1) { fprintf(stderr, "reinitMetric: re-shaped ...\n"); dumpExpr(x); } #endif } if (x->parent) { x = x->parent; if (x->metrics == m) continue; } break; } } end: /* destroy temporary context */ pmDestroyContext(handle); return ret; }