/* action argument expression */ Expr * actArgExpr(Expr *arg1, Expr *arg2) { Expr *x; /* error guard */ if (arg1 == NULL) return NULL; /* construct expression node */ x = newExpr(ACT_ARG, arg1, arg2, -1, 1, -1, 1, SEM_CHAR); newRingBfr(x); findEval(x); return x; }
/* merge expression */ static Expr * mergeExpr(int op, Expr *arg) { Expr *x; /* force argument to buffer at least two samples */ if (arg->nsmpls < 2) changeSmpls(&arg, 2); /* construct expression node */ x = newExpr(op, arg, NULL, arg->hdom, arg->e_idom, arg->tdom, abs(arg->tdom), arg->sem); newRingBfr(x); findEval(x); return x; }
/* action expression */ Expr * actExpr(int op, Expr *arg1, Expr *arg2) { Expr *x; /* error guard */ if (arg1 == NULL) return NULL; /* construct expression node */ x = newExpr(op, arg1, arg2, -1, -1, -1, 1, SEM_BOOLEAN); newRingBfr(x); findEval(x); return x; }
/* unary operator expression */ Expr * unaryExpr(int op, Expr *arg) { Expr *x; /* error guard */ if (arg == NULL) return NULL; /* construct expression node */ x = newExpr(op, arg, NULL, arg->hdom, arg->e_idom, arg->tdom, abs(arg->tdom), arg->sem); newRingBfr(x); findEval(x); /* evaluate constant expression now */ evalConst(x); return x; }
/* construct rule Expr */ Expr * ruleExpr(Expr *cond, Expr *act) { Expr *x; if (cond == NULL) return act; if (act == NULL) return cond; if (cond->nvals != 1) { synerr(); fprintf(stderr, "rule condition must have a single boolean value\n"); } perf->numrules++; x = newExpr(RULE, cond, act, -1, -1, -1, 1, SEM_BOOLEAN); newRingBfr(x); findEval(x); return x; }
/* relational operator expression */ Expr * relExpr(int op, Expr *arg1, Expr *arg2) { Expr *x; Expr *arg; int i; int sts; /* error guard */ if (arg1 == NULL || arg2 == NULL) return NULL; /* check domains */ sts = checkDoms(arg1, arg2); /* decide primary argument for inheritance of Expr attributes */ arg = primary(arg1, arg2); /* construct expression node */ x = newExpr(op, arg1, arg2, arg->hdom, arg->e_idom, arg->tdom, abs(arg->tdom), SEM_BOOLEAN); #if PCP_DEBUG if (sts == 0 && (pmDebug & DBG_TRACE_APPL1)) { fprintf(stderr, "relExpr: checkDoms(" PRINTF_P_PFX "%p, " PRINTF_P_PFX "%p) failed ...\n", arg1, arg2); __dumpTree(1, x); } #endif newRingBfr(x); if (x->tspan > 0) { for (i = 0; i < x->nsmpls; i++) *((char *)x->ring + i) = B_UNKNOWN; } findEval(x); /* evaluate constant expression now */ evalConst(x); return x; }
/* 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; }
/* aggregation/quantification operator expression */ Expr * domainExpr(int op, int dom, Expr *arg) { Expr *x; int hdom; int idom; int tdom; /* error guard */ if (arg == NULL) return NULL; hdom = arg->hdom; idom = arg->e_idom; tdom = arg->tdom; switch (dom) { case HOST_DOM: if (hdom == -1) { synerr(); fprintf(stderr, "no host domain\n"); freeExpr(arg); return NULL; } hdom = -1; idom = -1; dom = 0; break; case INST_DOM: #if 0 /* * I believe this test is no longer correct ... the instance * domain may be unobtainable at this point, or may change * later so checking at the syntactic level is not helpful */ if (idom == -1) { synerr(); fprintf(stderr, "no instance domain\n"); freeExpr(arg); return NULL; } #endif idom = -1; dom = 1; break; case TIME_DOM: if (tdom == -1) { synerr(); fprintf(stderr, "no time domain\n"); freeExpr(arg); return NULL; } tdom = -1; dom = 2; } if (op == CND_COUNT_HOST) { x = newExpr(op + dom, arg, NULL, hdom, idom, tdom, abs(tdom), PM_SEM_INSTANT); newRingBfr(x); x->units = countUnits; } else { x = newExpr(op + dom, arg, NULL, hdom, idom, tdom, abs(tdom), arg->sem); newRingBfr(x); } findEval(x); return x; }
/* binary operator expression */ Expr * binaryExpr(int op, Expr *arg1, Expr *arg2) { Expr *x; Expr *arg = arg1; int sts = 0; /* error guard */ if (arg1 == NULL) return NULL; if (arg1 != NULL && arg2 != NULL) { if (op != CND_MATCH && op != CND_NOMATCH) { /* check domains */ sts = checkDoms(arg1, arg2); /* decide primary argument for inheritance of Expr attributes */ arg = primary(arg1, arg2); } else { regex_t *pat; pat = alloc(sizeof(*pat)); if (regcomp(pat, (char *)arg2->ring, REG_EXTENDED|REG_NOSUB) != 0) { /* bad pattern */ fprintf(stderr, "illegal regular expression \"%s\"\n", (char *)arg2->ring); free(pat); return NULL; } #if PCP_DEBUG if (pmDebug & DBG_TRACE_APPL1) { fprintf(stderr, "binaryExpr: regex=\"%s\" handle=" PRINTF_P_PFX "%p\n", (char *)arg2->ring, pat); } #endif /* * change operand from the string form of the pattern to the * compiled regex */ free(arg2->ring); arg2->tspan = 1; arg2->ring = pat; arg2->sem = SEM_REGEX; sts = 1; } } /* construct expression node */ x = newExpr(op, arg1, arg2, arg->hdom, arg->e_idom, arg->tdom, abs(arg->tdom), arg->sem); #if PCP_DEBUG if (sts == 0 && (pmDebug & DBG_TRACE_APPL1)) { fprintf(stderr, "binaryExpr: checkDoms(" PRINTF_P_PFX "%p, " PRINTF_P_PFX "%p) failed ...\n", arg1, arg2); __dumpTree(1, x); } #endif newRingBfr(x); findEval(x); /* evaluate constant expression now */ evalConst(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; }