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; }
static void myvaluesetdump(pmValueSet *xvsp, int idx, int *flagsp) { int sts, flags = *flagsp; DescHash *hp; __pmHashNode *hnp; static __pmHashCtl hash = { 0, 0, NULL }; if ((hnp = __pmHashSearch((unsigned int)xvsp->pmid, &hash)) == NULL) { /* first time for this pmid */ hp = (DescHash *)malloc(sizeof(DescHash)); if (hp == NULL) { __pmNoMem("DescHash", sizeof(DescHash), PM_FATAL_ERR); /*NOTREACHED*/ } if ((sts = pmNameID(xvsp->pmid, &hp->name)) < 0) { printf(" %s: pmNameID: %s\n", pmIDStr(xvsp->pmid), pmErrStr(sts)); free(hp); return; } else { if (xvsp->pmid != pmid_flags && xvsp->pmid != pmid_missed && (sts = pmLookupDesc(xvsp->pmid, &hp->desc)) < 0) { printf(" %s: pmLookupDesc: %s\n", hp->name, pmErrStr(sts)); free(hp->name); free(hp); return; } if ((sts = __pmHashAdd((unsigned int)xvsp->pmid, (void *)hp, &hash)) < 0) { printf(" %s: __pmHashAdd: %s\n", hp->name, pmErrStr(sts)); free(hp->name); free(hp); return; } } } else hp = (DescHash *)hnp->data; if (idx == 0) { if (xvsp->pmid == pmid_flags) { flags = *flagsp = xvsp->vlist[0].value.lval; printf(" flags 0x%x", flags); printf(" (%s) ---\n", pmEventFlagsStr(flags)); return; } else printf(" ---\n"); } if ((flags & PM_EVENT_FLAG_MISSED) && (idx == 1) && (xvsp->pmid == pmid_missed)) { printf(" ==> %d missed event records\n", xvsp->vlist[0].value.lval); return; } mydump(hp->name, &hp->desc, xvsp); }
static void * func1(void *arg) { int sts; char *fn = "func1"; char **offspring; int *status; int i; int j; char *namelist[] = { "b", "a.three.foo", "d.f.fumble" }; pmID pmidlist[3]; pthread_barrier_wait(&barrier); __pmDumpNameSpace(stdout, 1); sts = pmGetChildrenStatus("", &offspring, &status); if (sts >= 0) { printf("%s: pmGetChildrenStatus -> %d\n", fn, sts); for (i = 0; i < sts; i++) { printf("[%d] %s %s\n", i, offspring[i], status[i] == PMNS_LEAF_STATUS ? "leaf" : "non-leaf"); } free(offspring); free(status); } else printf("%s: pmGetChildrenStatus -> %s\n", fn, pmErrStr(sts)); for (i = 0; i < 5; i++) { pthread_barrier_wait(&barrier); sts = pmLookupName(sizeof(namelist)/sizeof(namelist[0]), namelist, pmidlist); if (sts < 0) printf("%s: pmGetChildrenStatus[%d] -> %s\n", fn, i, pmErrStr(sts)); else { for (j = 0; j < sizeof(namelist)/sizeof(namelist[0]); j++) { printf("%s: [%d] %s -> %s", fn, i, namelist[j], pmIDStr(pmidlist[j])); if (pmidlist[j] == PM_ID_NULL) printf("\n"); else { char *name; sts = pmNameID(pmidlist[j], &name); if (sts < 0) printf(": pmNameID -> %s\n", pmErrStr(sts)); else { printf(" -> %s\n", name); free(name); } } } } pthread_barrier_wait(&barrier); } pthread_exit(NULL); }
static void foo(FILE *f, char *fn, int i, void *closure) { int sts; int numnames; int j; int leaf; pmID pmids[NMETRIC]; char **names; char *name; int *stsset; char strbuf[20]; if ((sts = pmLookupName(NMETRIC-i, &namelist[i], pmids)) < 0) { if (sts != PM_ERR_NONLEAF) { fprintf(f, "%s: %s ...: pmLookupName Error: %s\n", fn, namelist[i], pmErrStr(sts)); pthread_exit("botch"); } } for (j = i; j < NMETRIC; j++) { if (pmids[j-i] != pmidlist[j]) { fprintf(f, "%s: %s: Botch: expecting %s", fn, namelist[j], pmIDStr_r(pmidlist[j], strbuf, sizeof(strbuf))); fprintf(f, ", got %s\n", pmIDStr_r(pmids[j-i], strbuf, sizeof(strbuf))); pthread_exit("botch"); } } fprintf(f, "%s: %s ... pmLookupName OK\n", fn, namelist[i]); fprintf(f, "%s: %s", fn, namelist[i]); if (pmidlist[i] != PM_ID_NULL) { /* leaf node in PMNS */ if ((numnames = pmNameAll(pmidlist[i], &names)) < 0) { fprintf(f, "\n%s: %s ...: pmNameAll Error: %s\n", fn, namelist[i], pmErrStr(numnames)); pthread_exit("botch"); } for (j = 0; j < numnames; j++) { if (strcmp(names[j], namelist[i]) == 0) break; } if (j == numnames) { fprintf(f, "\n%s: %s: Botch: expecting %s, got {", fn, pmIDStr_r(pmidlist[i], strbuf, sizeof(strbuf)), namelist[i]); __pmPrintMetricNames(f, numnames, names, ","); fprintf(f, "}\n"); pthread_exit("botch"); } fprintf(f, " pmNameAll OK"); if ((sts = pmNameID(pmidlist[i], &name)) < 0) { fprintf(f, "\n%s: %s ...: pmNameID Error: %s\n", fn, namelist[i], pmErrStr(sts)); pthread_exit("botch"); } for (j = 0; j < numnames; j++) { if (strcmp(name, names[j]) == 0) break; } if (j == numnames) { fprintf(f, "\n%s: %s: Botch: expecting one of {", fn, pmIDStr_r(pmidlist[i], strbuf, sizeof(strbuf))); __pmPrintMetricNames(f, numnames, names, ","); fprintf(f, "}, got %s\n", name); pthread_exit("botch"); } free(names); free(name); fprintf(f, " pmNameID OK"); } else { /* non-leaf node in PMNS */ int keep = 0; if ((sts = pmGetChildrenStatus(namelist[i], &names, &stsset)) < 0) { fprintf(f, "\n%s: %s ...: pmGetChildrenStatus Error: %s\n", fn, namelist[i], pmErrStr(sts)); pthread_exit("botch"); } leaf = 0; for (j = 0; j < sts; j++) { if (stsset[j] == PMNS_LEAF_STATUS) leaf++; } PM_LOCK(chn_lock); if (leaf_chn[i] == -1) { leaf_chn[i] = leaf; nonleaf_chn[i] = sts - leaf; chn[i] = names; keep = 1; } else { if (leaf != leaf_chn[i] || sts - leaf != nonleaf_chn[i]) { fprintf(f, "\n%s: %s: Botch: expecting %d leaf & %d non-leaf, got %d leaf & %d non-leaf\n", fn, namelist[i], leaf_chn[i], nonleaf_chn[i], leaf, sts - leaf); pthread_exit("botch"); } for (j = 0; j < sts; j++) { if (strcmp(chn[i][j], names[j]) != 0) { fprintf(f, "\n%s: %s: Botch: child[%d] expecting %s, got %s\n", fn, namelist[i], j, chn[i][j], names[j]); PM_UNLOCK(chn_lock); pthread_exit("botch"); } } } if (keep == 0) { free(names); names = NULL; /* silence coverity */ } free(stsset); fprintf(f, " pmGetChildrenStatus OK"); if ((sts = pmGetChildren(namelist[i], &names)) < 0) { fprintf(f, "\n%s: %s ...: pmGetChildren Error: %s\n", fn, namelist[i], pmErrStr(sts)); PM_UNLOCK(chn_lock); pthread_exit("botch"); } if (sts != leaf_chn[i] + nonleaf_chn[i]) { fprintf(f, "\n%s: %s: Botch: expecting %d children, got %d\n", fn, namelist[i], leaf_chn[i] + nonleaf_chn[i], sts); PM_UNLOCK(chn_lock); pthread_exit("botch"); } for (j = 0; j < sts; j++) { if (strcmp(chn[i][j], names[j]) != 0) { fprintf(f, "\n%s: %s: Botch: child[%d] expecting %s, got %s\n", fn, namelist[i], j, chn[i][j], names[j]); PM_UNLOCK(chn_lock); pthread_exit("botch"); } } PM_UNLOCK(chn_lock); free(names); fprintf(f, " pmGetChildren OK"); *((int *)closure) = 0; if ((sts = pmTraversePMNS_r(namelist[i], dometric, closure)) < 0) { fprintf(f, "\n%s: %s ...: pmTraversePMNS_r Error: %s\n", fn, namelist[i], pmErrStr(sts)); pthread_exit("botch"); } if (sum_traverse[i] != *((int *)closure)) { fprintf(f, "\n%s: %s: Botch: sum strlen(descendent names) expecting %d, got %d\n", fn, namelist[i], sum_traverse[i], *((int *)closure)); pthread_exit("botch"); } fprintf(f, " pmTraversePMNS_r OK"); } fputc('\n', f); }
/* Update an existing metric (given a pmValueSet) adding it to the specified * task. Allocate and return a new task_t if the specified task pointer is nil. */ static int update_metric(pmValueSet *vsp, int reqstate, int mflags, task_t **result) { pmID pmid = vsp->pmid; task_t *ntp = *result; /* pointer to new task */ task_t *ctp; /* pointer to current task */ optreq_t *rqp; pmDesc *dp; int i, j, inst; int sts, need = 0; int addpmid = 0; int freedp; /* allocate a new task if null task pointer passed in */ if (ntp == NULL) { ntp = calloc(1, sizeof(task_t)); if (ntp == NULL) { __pmNoMem("update_metric: new task calloc", sizeof(task_t), PM_FATAL_ERR); } *result = ntp; } if ((mflags & MF_HAS_INDOM) == 0) { rqp = findoptreq(pmid, 0); ctp = (task_t *)(rqp->r_fetch->f_aux); if (!update_ok(ctp->t_state, reqstate)) return 1; /* if the new state is advisory off, just remove the metric */ if ((PMLC_GET_MAYBE(reqstate)) || (PMLC_GET_MAND(reqstate) == 0 && PMLC_GET_ON(reqstate) == 0)) del_optreq(rqp); else { /* update the optreq. For single valued metrics there are no * instances involved so the sole optreq can just be re-used. */ if ((sts = __pmOptFetchDel(&ctp->t_fetch, rqp)) < 0) die("update_metric: 1 metric __pmOptFetchDel", sts); __pmOptFetchAdd(&ntp->t_fetch, rqp); linkback(ntp); addpmid = 1; } } else { /* metric has an instance domain */ if (vsp->numval > 0) { /* tricky: since optFetch can't handle instance profiles of the * form "all except these specific instances", and managing it * manually is just too hard, reject requests for specific * metric instances if "all instances" of the metric are already * being logged. * Note: advisory off "all instances" is excepted since ANY request * overrides and advisory off. E.g. "advisory off all" followed by * "advisory on someinsts" turns on advisory logging for * "someinsts". mflags will be zero for "advisory off" metrics. */ if (mflags & MF_HAS_ALL) return 1; /* can't turn "all" into specific insts */ for (i = 0; i < vsp->numval; i++) { dp = NULL; freedp = 0; inst = vsp->vlist[i].inst; rqp = findoptreq(pmid, inst); if (rqp != NULL) { dp = rqp->r_desc; ctp = (task_t *)(rqp->r_fetch->f_aux); /* no work required if new task and current are the same */ if (ntp == ctp) continue; if (!update_ok(ctp->t_state, reqstate)) continue; /* remove inst's group from current task */ if ((sts = __pmOptFetchDel(&ctp->t_fetch, rqp)) < 0) die("update_metric: instance add __pmOptFetchDel", sts); /* put group back if there are any instances left */ if (rqp->r_numinst > 1) { /* remove inst from group */ for (j = 0; j < rqp->r_numinst; j++) if (inst == rqp->r_instlist[j]) break; /* don't call memmove to move zero bytes */ if (j < rqp->r_numinst - 1) memmove(&rqp->r_instlist[j], &rqp->r_instlist[j+1], (rqp->r_numinst - 1 - j) * sizeof(rqp->r_instlist[0])); rqp->r_numinst--; /* (don't bother realloc-ing the instlist to a smaller size) */ __pmOptFetchAdd(&ctp->t_fetch, rqp); linkback(ctp); /* no need to update hash list, rqp already there */ } /* if that was the last instance, free the group */ else { if (( sts = __pmHashDel(pmid, (void *)rqp, &pm_hash)) < 0) die("update_metric: instance __pmHashDel", sts); freedp = 1; free(rqp->r_instlist); free(rqp); } } /* advisory off (mandatory maybe) metrics don't get put into * the data structure */ if (PMLC_GET_MAYBE(reqstate) || (PMLC_GET_MAND(reqstate) == 0 && PMLC_GET_ON(reqstate) == 0)) { if (freedp) free(dp); continue; } addpmid = 1; /* try to find an existing optreq_t for the instance */ rqp = find_instoptreq(ntp, pmid); if (rqp != NULL) { if ((sts = __pmOptFetchDel(&ntp->t_fetch, rqp)) < 0) die("update_metric: instance add __pmOptFetchDel", sts); } /* no existing optreq_t found, allocate & populate a new one */ else { rqp = (optreq_t *)calloc(1, sizeof(optreq_t)); if (rqp == NULL) { __pmNoMem("update_metric: optreq calloc", sizeof(optreq_t), PM_FATAL_ERR); } /* if the metric existed but the instance didn't, we don't * have a valid pmDesc (dp), so find one. */ if (dp == NULL) { /* find metric and associated pmDesc */ __pmHashNode *hp; for (hp = __pmHashSearch(pmid, &pm_hash); hp != NULL; hp = hp->next) { if (pmid == (pmID)hp->key) break; } assert(hp != NULL); dp = ((optreq_t *)hp->data)->r_desc; } /* recycle pmDesc from the old group, if possible */ if (freedp) { rqp->r_desc = dp; freedp = 0; } /* otherwise allocate & copy a new pmDesc via dp */ else { need = sizeof(pmDesc); rqp->r_desc = (pmDesc *)malloc(need); if (rqp->r_desc == NULL) { __pmNoMem("update_metric: new inst pmDesc malloc", need, PM_FATAL_ERR); } memcpy(rqp->r_desc, dp, need); } if ((sts = __pmHashAdd(pmid, (void *)rqp, &pm_hash)) < 0) die("update_metric: __pmHashAdd", sts); } need = (rqp->r_numinst + 1) * sizeof(rqp->r_instlist[0]); rqp->r_instlist = (int *)realloc(rqp->r_instlist, need); if (rqp->r_instlist == NULL) { __pmNoMem("update_metric: inst list resize", need, PM_FATAL_ERR); } rqp->r_instlist[rqp->r_numinst++] = inst; __pmOptFetchAdd(&ntp->t_fetch, rqp); linkback(ntp); if (freedp) free(dp); } } /* the vset has numval == 0, a request for "all instances" */ else { /* if the metric is a singular instance that has mandatory logging * or has at least one instance with mandatory logging on, a * request for advisory logging cannot be honoured */ if ((mflags & MF_HAS_MAND) && PMLC_GET_MAND(reqstate) == 0 && PMLC_GET_MAYBE(reqstate) == 0) return 1; if (mflags & MF_HAS_ALL) { /* if there is an "all instances" for the metric, it will be * the only optreq_t for the metric */ rqp = findoptreq(pmid, 0); ctp = (task_t *)rqp->r_fetch->f_aux; /* if the metric is "advisory on, all instances" and the * request is for "mandatory maybe, all instances" the current * advisory logging state of the metric is retained */ if (PMLC_GET_MAND(ctp->t_state) == 0 && PMLC_GET_MAYBE(reqstate)) return 0; /* advisory off & mandatory maybe metrics don't get put into * the data structure */ if (PMLC_GET_MAYBE(reqstate) || (PMLC_GET_MAND(reqstate) == 0 && PMLC_GET_ON(reqstate) == 0)) { del_optreq(rqp); return 0; } addpmid = 1; if ((sts = __pmOptFetchDel(&ctp->t_fetch, rqp)) < 0) die("update_metric: all inst __pmOptFetchDel", sts); /* don't delete from hash list, rqp re-used */ __pmOptFetchAdd(&ntp->t_fetch, rqp); linkback(ntp); } else { /* there are one or more specific instances for the metric. * The metric cannot have an "all instances" at the same time. * * if the request is for "mandatory maybe, all instances" and * the only instances of the metric all have advisory logging * on, retain the current advisory semantics. */ if (PMLC_GET_MAYBE(reqstate) && (mflags & MF_HAS_INST) && !(mflags & MF_HAS_MAND)) return 0; dp = del_insts(pmid); /* advisory off (mandatory maybe) metrics don't get put into * the data structure */ if (PMLC_GET_MAYBE(reqstate) || (PMLC_GET_MAND(reqstate) == 0 && PMLC_GET_ON(reqstate) == 0)) { free(dp); return 0; } addpmid = 1; rqp = (optreq_t *)calloc(1, sizeof(optreq_t)); if (rqp == NULL) { __pmNoMem("update_metric: all inst calloc", sizeof(optreq_t), PM_FATAL_ERR); } rqp->r_desc = dp; __pmOptFetchAdd(&ntp->t_fetch, rqp); linkback(ntp); if ((sts = __pmHashAdd(pmid, (void *)rqp, &pm_hash)) < 0) die("update_metric: all inst __pmHashAdd", sts); } } } if (!addpmid) return 0; /* add pmid to new task if not already there */ for (i = 0; i < ntp->t_numpmid; i++) if (pmid == ntp->t_pmidlist[i]) break; if (i >= ntp->t_numpmid) { pmDesc desc; char *name; int need; if ((sts = pmLookupDesc(pmid, &desc)) < 0) die("update_metric: cannot lookup desc", sts); if ((sts = pmNameID(pmid, &name)) < 0) die("update_metric: cannot lookup name", sts); need = (ntp->t_numpmid + 1) * sizeof(pmID); if (!(ntp->t_pmidlist = (pmID *)realloc(ntp->t_pmidlist, need))) __pmNoMem("update_metric: grow task pmidlist", need, PM_FATAL_ERR); need = (ntp->t_numpmid + 1) * sizeof(char *); if (!(ntp->t_namelist = (char **)realloc(ntp->t_namelist, need))) __pmNoMem("update_metric: grow task namelist", need, PM_FATAL_ERR); need = (ntp->t_numpmid + 1) * sizeof(pmDesc); if (!(ntp->t_desclist = (pmDesc *)realloc(ntp->t_desclist, need))) __pmNoMem("update_metric: grow task desclist", need, PM_FATAL_ERR); i = ntp->t_numpmid; ntp->t_pmidlist[i] = pmid; ntp->t_namelist[i] = name; ntp->t_desclist[i] = desc; ntp->t_numpmid++; } return 0; }
/* Add a new metric (given a pmValueSet and a pmDesc) to the specified task. * Allocate and return a new task_t if the specified task pointer is nil. * * Note that this should only be called for metrics not currently in the * logging data structure. All instances in the pmValueSet are added! */ static int add_metric(pmValueSet *vsp, task_t **result) { pmID pmid = vsp->pmid; task_t *tp = *result; optreq_t *rqp; pmDesc *dp; char *name; int sts, i, need = 0; dp = (pmDesc *)malloc(sizeof(pmDesc)); if (dp == NULL) { __pmNoMem("add_metric: new pmDesc malloc", sizeof(pmDesc), PM_FATAL_ERR); } if ((sts = pmLookupDesc(pmid, dp)) < 0) die("add_metric: lookup desc", sts); if ((sts = pmNameID(pmid, &name)) < 0) die("add_metric: lookup name", sts); /* allocate a new task if null task pointer passed in */ if (tp == NULL) { tp = calloc(1, sizeof(task_t)); if (tp == NULL) { __pmNoMem("add_metric: new task calloc", sizeof(task_t), PM_FATAL_ERR); } *result = tp; } /* add metric (and any instances specified) to task */ i = tp->t_numpmid++; need = tp->t_numpmid * sizeof(pmID); if (!(tp->t_pmidlist = (pmID *)realloc(tp->t_pmidlist, need))) __pmNoMem("add_metric: new task pmidlist realloc", need, PM_FATAL_ERR); need = tp->t_numpmid * sizeof(char *); if (!(tp->t_namelist = (char **)realloc(tp->t_namelist, need))) __pmNoMem("add_metric: new task namelist realloc", need, PM_FATAL_ERR); need = tp->t_numpmid * sizeof(pmDesc); if (!(tp->t_desclist = (pmDesc *)realloc(tp->t_desclist, need))) __pmNoMem("add_metric: new task desclist realloc", need, PM_FATAL_ERR); tp->t_pmidlist[i] = pmid; tp->t_namelist[i] = name; tp->t_desclist[i] = *dp; /* struct assignment */ rqp = (optreq_t *)calloc(1, sizeof(optreq_t)); if (rqp == NULL) { __pmNoMem("add_metric: new task optreq calloc", need, PM_FATAL_ERR); } rqp->r_desc = dp; /* Now copy instances if required. Remember that metrics with singular * values actually have one instance specified to distinguish them from the * "all instances" case (which has no instances). Use the pmDesc to check * for this. */ if (dp->indom != PM_INDOM_NULL) need = rqp->r_numinst = vsp->numval; if (need) { need *= sizeof(rqp->r_instlist[0]); rqp->r_instlist = (int *)malloc(need); if (rqp->r_instlist == NULL) { __pmNoMem("add_metric: new task optreq instlist malloc", need, PM_FATAL_ERR); } for (i = 0; i < vsp->numval; i++) rqp->r_instlist[i] = vsp->vlist[i].inst; } /* Add new metric to task's fetchgroup(s) and global hash table */ __pmOptFetchAdd(&tp->t_fetch, rqp); linkback(tp); if ((sts = __pmHashAdd(pmid, (void *)rqp, &pm_hash)) < 0) die("add_metric: __pmHashAdd", sts); return 0; }