static int __pmSetUserGroupAttributes(const char *username, __pmHashCtl *attrs) { char name[32]; char *namep; uid_t uid; gid_t gid; if (__pmGetUserIdentity(username, &uid, &gid, PM_RECOV_ERR) == 0) { pmsprintf(name, sizeof(name), "%u", uid); name[sizeof(name)-1] = '\0'; if ((namep = strdup(name)) != NULL) __pmHashAdd(PCP_ATTR_USERID, namep, attrs); else return -ENOMEM; pmsprintf(name, sizeof(name), "%u", gid); name[sizeof(name)-1] = '\0'; if ((namep = strdup(name)) != NULL) __pmHashAdd(PCP_ATTR_GROUPID, namep, attrs); else return -ENOMEM; return 0; } pmNotifyErr(LOG_ERR, "Authenticated user %s not found\n", username); return -ESRCH; }
static int SetCredentialAttrs(__pmHashCtl *attrs, unsigned int pid, unsigned int uid, unsigned int gid) { char name[32], *namep; snprintf(name, sizeof(name), "%u", uid); name[sizeof(name)-1] = '\0'; if ((namep = strdup(name)) != NULL) __pmHashAdd(PCP_ATTR_USERID, namep, attrs); snprintf(name, sizeof(name), "%u", gid); name[sizeof(name)-1] = '\0'; if ((namep = strdup(name)) != NULL) __pmHashAdd(PCP_ATTR_GROUPID, namep, attrs); if (!pid) /* not available on all platforms */ return 0; snprintf(name, sizeof(name), "%u", pid); name[sizeof(name)-1] = '\0'; if ((namep = strdup(name)) != NULL) __pmHashAdd(PCP_ATTR_PROCESSID, namep, attrs); return 0; }
int main(int argc, char **argv) { __pmHashCtl hc = { 0 }; printf("adding entries\n"); __pmHashAdd(0, (void *)0L, &hc); __pmHashAdd(1, (void *)1L, &hc); __pmHashAdd(2, (void *)2L, &hc); __pmHashAdd(3, (void *)3L, &hc); if (argc >= 2) { if (strcmp(argv[1], "callback") == 0) __pmHashWalkCB(walker, (void *)PM_HASH_WALK_NEXT, &hc); else if (strcmp(argv[1], "linked") == 0) chained(&hc); exit(0); } printf("iterating WALK_STOP\n"); __pmHashWalkCB(walker, (void *)PM_HASH_WALK_STOP, &hc); printf("iterating WALK_NEXT\n"); __pmHashWalkCB(walker, (void *)PM_HASH_WALK_NEXT, &hc); printf("iterating WALK_DELETE_STOP\n"); __pmHashWalkCB(walker, (void *)PM_HASH_WALK_DELETE_STOP, &hc); printf("iterating WALK_NEXT\n"); __pmHashWalkCB(walker, (void *)PM_HASH_WALK_NEXT, &hc); printf("iterating WALK_DELETE_NEXT\n"); __pmHashWalkCB(walker, (void *)PM_HASH_WALK_DELETE_NEXT, &hc); printf("iterating WALK_NEXT\n"); __pmHashWalkCB(walker, (void *)PM_HASH_WALK_NEXT, &hc); exit(0); }
/* * Parse the attributes component of a PCP connection string. * Optionally, an initial attribute:value pair can be passed * in as well to add to the parsed set. */ static int parseAttributeSpec( const char *spec, /* the original, complete string to parse */ char **position, /* parse from here onward and update at end */ int attribute, char *value, __pmHashCtl *attributes, char **errmsg) { char *s, *start, *v = NULL; char buffer[32]; /* must be large enough to hold largest attr name */ int buflen, attr, len, sts; if (attribute != PCP_ATTR_NONE) if ((sts = __pmHashAdd(attribute, (void *)value, attributes)) < 0) return sts; for (s = start = *position; s != NULL; s++) { /* parse: foo=bar&moo&goo=blah ... go! */ if (*s == '\0' || *s == '/' || *s == '&') { if ((*s == '\0' || *s == '/') && s == start) break; len = v ? (v - start - 1) : (s - start); buflen = (len < sizeof(buffer)-1) ? len : sizeof(buffer)-1; strncpy(buffer, start, buflen); buffer[buflen] = '\0'; attr = __pmLookupAttrKey(buffer, buflen+1); if (attr != PCP_ATTR_NONE) { char *val = NULL; if (v && (val = strndup(v, s - v)) == NULL) { sts = -ENOMEM; goto fail; } if ((sts = __pmHashAdd(attr, (void *)val, attributes)) < 0) { free(val); goto fail; } } v = NULL; if (*s == '\0' || *s == '/') break; start = s + 1; /* start of attribute name */ continue; } if (*s == '=') { v = s + 1; /* start of attribute value */ } } *position = s; return 0; fail: if (attribute != PCP_ATTR_NONE) /* avoid double free in caller */ __pmHashDel(attribute, (void *)value, attributes); __pmFreeAttrsSpec(attributes); return sts; }
static int __pmAuthServerSetAttributes(sasl_conn_t *conn, __pmHashCtl *attrs) { const void *property = NULL; char *username; int sts; sts = sasl_getprop(conn, SASL_USERNAME, &property); username = (char *)property; if (sts == SASL_OK && username) { int len = strlen(username); pmNotifyErr(LOG_INFO, "Successful authentication for user \"%s\"\n", username); if ((username = strdup(username)) == NULL) { pmNoMem("__pmAuthServerSetAttributes", len, PM_RECOV_ERR); return -ENOMEM; } } else { pmNotifyErr(LOG_ERR, "Authentication complete, but no username\n"); return -ESRCH; } if ((sts = __pmHashAdd(PCP_ATTR_USERNAME, username, attrs)) < 0) return sts; return __pmSetUserGroupAttributes(username, attrs); }
static int addindom(__pmLogCtl *lcp, pmInDom indom, const __pmTimeval *tp, int numinst, int *instlist, char **namelist, int *indom_buf, int allinbuf) { __pmLogInDom *idp; __pmHashNode *hp; int sts; if ((idp = (__pmLogInDom *)malloc(sizeof(__pmLogInDom))) == NULL) return -errno; idp->stamp = *tp; /* struct assignment */ idp->numinst = numinst; idp->instlist = instlist; idp->namelist = namelist; idp->buf = indom_buf; idp->allinbuf = allinbuf; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) fprintf(stderr, "addindom( ..., %s, %s, numinst=%d)\n", pmInDomStr(indom), StrTimeval((__pmTimeval *)tp), numinst); #endif if ((hp = __pmHashSearch((unsigned int)indom, &lcp->l_hashindom)) == NULL) { idp->next = NULL; sts = __pmHashAdd((unsigned int)indom, (void *)idp, &lcp->l_hashindom); } else { idp->next = (__pmLogInDom *)hp->data; hp->data = (void *)idp; sts = 0; } 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 int ctxflags(__pmHashCtl *attrs, int *flags) { int sts; char *name = NULL; char *secure = NULL; char *container = NULL; __pmHashNode *node; if ((node = __pmHashSearch(PCP_ATTR_PROTOCOL, attrs)) != NULL) { if (strcmp((char *)node->data, "pcps") == 0) { if ((node = __pmHashSearch(PCP_ATTR_SECURE, attrs)) != NULL) secure = (char *)node->data; else secure = "enforce"; } } if (!secure) secure = getenv("PCP_SECURE_SOCKETS"); if (secure) { if (secure[0] == '\0' || (strcmp(secure, "1")) == 0 || (strcmp(secure, "enforce")) == 0) { *flags |= PM_CTXFLAG_SECURE; } else if (strcmp(secure, "relaxed") == 0) { *flags |= PM_CTXFLAG_RELAXED; } } if (__pmHashSearch(PCP_ATTR_COMPRESS, attrs) != NULL) *flags |= PM_CTXFLAG_COMPRESS; if (__pmHashSearch(PCP_ATTR_USERAUTH, attrs) != NULL || __pmHashSearch(PCP_ATTR_USERNAME, attrs) != NULL || __pmHashSearch(PCP_ATTR_PASSWORD, attrs) != NULL || __pmHashSearch(PCP_ATTR_METHOD, attrs) != NULL || __pmHashSearch(PCP_ATTR_REALM, attrs) != NULL) *flags |= PM_CTXFLAG_AUTH; if (__pmHashSearch(PCP_ATTR_CONTAINER, attrs) != NULL) *flags |= PM_CTXFLAG_CONTAINER; else if ((container = getenv("PCP_CONTAINER")) != NULL) { if ((name = strdup(container)) == NULL) return -ENOMEM; if ((sts = __pmHashAdd(PCP_ATTR_CONTAINER, (void *)name, attrs)) < 0) { free(name); return sts; } *flags |= PM_CTXFLAG_CONTAINER; } if (__pmHashSearch(PCP_ATTR_EXCLUSIVE, attrs) != NULL) *flags |= PM_CTXFLAG_EXCLUSIVE; return 0; }
/* Print event performance metric values */ void printevents(Context *x, pmValueSet *vset, int cols) { int i, sts, highres = (x->desc.type != PM_TYPE_EVENT); unsigned inst; for (i = 0; i < vset->numval; i++) { inst = (unsigned int)vset->vlist[i].inst; if (inst == PM_IN_NULL) printf("%s:", x->metric); else { int k; char *iname = NULL; if (x->inum > 0) { for (k = 0; k < x->inum; k++) { if (x->iids[k] == inst) { iname = x->inames[k]; break; } } } else { /* all instances selected */ __pmHashNode *hnp; hnp = __pmHashSearch(inst, &x->ihash); if (hnp == NULL) { if (archive) sts = pmNameInDomArchive(x->desc.indom, inst, &iname); else sts = pmNameInDom(x->desc.indom, inst, &iname); if (sts < 0) { fprintf(stderr, "%s: pmNameInDom: %s[%u]: %s\n", pmProgname, x->metric, inst, pmErrStr(sts)); exit(EXIT_FAILURE); } if ((sts = __pmHashAdd(inst, (void *)iname, &x->ihash)) < 0) { fprintf(stderr, "%s: __pmHashAdd: %s[%s (%u)]: %s\n", pmProgname, x->metric, iname, inst, pmErrStr(sts)); exit(EXIT_FAILURE); } } else iname = (char *)hnp->data; } if (iname == NULL) continue; printf("%s[%s]:", x->metric, iname); } myeventdump(vset, i, highres); } }
static int build_dsoattrs(pmdaInterface *dispatch, __pmHashCtl *attrs) { __pmHashNode *node; char name[32]; char *namep; int sts = 0; #ifdef HAVE_GETUID snprintf(name, sizeof(name), "%u", getuid()); name[sizeof(name)-1] = '\0'; if ((namep = strdup(name)) != NULL) __pmHashAdd(PCP_ATTR_USERID, namep, attrs); #endif #ifdef HAVE_GETGID snprintf(name, sizeof(name), "%u", getgid()); name[sizeof(name)-1] = '\0'; if ((namep = strdup(name)) != NULL) __pmHashAdd(PCP_ATTR_GROUPID, namep, attrs); #endif snprintf(name, sizeof(name), "%u", getpid()); name[sizeof(name)-1] = '\0'; if ((namep = strdup(name)) != NULL) __pmHashAdd(PCP_ATTR_PROCESSID, namep, attrs); if (dispatch->version.six.attribute != NULL) { for (node = __pmHashWalk(attrs, PM_HASH_WALK_START); node != NULL; node = __pmHashWalk(attrs, PM_HASH_WALK_NEXT)) { if ((sts = dispatch->version.six.attribute( 0, node->key, node->data, node->data ? strlen(node->data)+1 : 0, dispatch->version.six.ext)) < 0) break; } } return sts; }
static int ctxlocal(__pmHashCtl *attrs) { int sts; char *name = NULL; char *container = NULL; if ((container = getenv("PCP_CONTAINER")) != NULL) { if ((name = strdup(container)) == NULL) return -ENOMEM; if ((sts = __pmHashAdd(PCP_ATTR_CONTAINER, (void *)name, attrs)) < 0) { free(name); return sts; } } return 0; }
/* * load _all_ of the hashed pmDesc and __pmLogInDom structures from the metadata * log file -- used at the initialization (NewContext) of an archive * If version 2 then * load all the names from the meta data and create l_pmns. */ int __pmLogLoadMeta(__pmLogCtl *lcp) { int rlen; int check; pmDesc *dp; int sts = 0; __pmLogHdr h; FILE *f = lcp->l_mdfp; int version2 = ((lcp->l_label.ill_magic & 0xff) == PM_LOG_VERS02); int numpmid = 0; int n; if (version2) { if ((sts = __pmNewPMNS(&(lcp->l_pmns))) < 0) { goto end; } } fseek(f, (long)(sizeof(__pmLogLabel) + 2*sizeof(int)), SEEK_SET); for ( ; ; ) { n = (int)fread(&h, 1, sizeof(__pmLogHdr), f); /* swab hdr */ h.len = ntohl(h.len); h.type = ntohl(h.type); if (n != sizeof(__pmLogHdr) || h.len <= 0) { if (feof(f)) { clearerr(f); sts = 0; goto end; } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: header read -> %d: expected: %d\n", n, (int)sizeof(__pmLogHdr)); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: record len=%d, type=%d @ offset=%d\n", h.len, h.type, (int)(ftell(f) - sizeof(__pmLogHdr))); } #endif rlen = h.len - (int)sizeof(__pmLogHdr) - (int)sizeof(int); if (h.type == TYPE_DESC) { numpmid++; if ((dp = (pmDesc *)malloc(sizeof(pmDesc))) == NULL) { sts = -errno; goto end; } if ((n = (int)fread(dp, 1, sizeof(pmDesc), f)) != sizeof(pmDesc)) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: pmDesc read -> %d: expected: %d\n", n, (int)sizeof(pmDesc)); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } else { /* swab desc */ dp->type = ntohl(dp->type); dp->sem = ntohl(dp->sem); dp->indom = __ntohpmInDom(dp->indom); dp->units = __ntohpmUnits(dp->units); dp->pmid = __ntohpmID(dp->pmid); } if ((sts = __pmHashAdd((int)dp->pmid, (void *)dp, &lcp->l_hashpmid)) < 0) goto end; if (version2) { char name[MAXPATHLEN]; int numnames; int i; int len; /* read in the names & store in PMNS tree ... */ if ((n = (int)fread(&numnames, 1, sizeof(numnames), f)) != sizeof(numnames)) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: numnames read -> %d: expected: %d\n", n, (int)sizeof(numnames)); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } else { /* swab numnames */ numnames = ntohl(numnames); } for (i = 0; i < numnames; i++) { if ((n = (int)fread(&len, 1, sizeof(len), f)) != sizeof(len)) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: len name[%d] read -> %d: expected: %d\n", i, n, (int)sizeof(len)); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } else { /* swab len */ len = ntohl(len); } if ((n = (int)fread(name, 1, len, f)) != len) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: name[%d] read -> %d: expected: %d\n", i, n, len); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } name[len] = '\0'; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: PMID: %s name: %s\n", pmIDStr(dp->pmid), name); } #endif if ((sts = __pmAddPMNSNode(lcp->l_pmns, dp->pmid, name)) < 0) { /* * If we see a duplicate PMID, its a recoverable error. * We wont be able to see all of the data in the log, but * its better to provide access to some rather than none, * esp. when only one or two metric IDs may be corrupted * in this way (which we may not be interested in anyway). */ if (sts != PM_ERR_PMID) goto end; sts = 0; } }/*for*/ }/*version2*/ } else if (h.type == TYPE_INDOM) { int *tbuf; pmInDom indom; __pmTimeval *when; int numinst; int *instlist; char **namelist; char *namebase; int *stridx; int i; int k; int allinbuf; if ((tbuf = (int *)malloc(rlen)) == NULL) { sts = -errno; goto end; } if ((n = (int)fread(tbuf, 1, rlen, f)) != rlen) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: indom read -> %d: expected: %d\n", n, rlen); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } k = 0; when = (__pmTimeval *)&tbuf[k]; when->tv_sec = ntohl(when->tv_sec); when->tv_usec = ntohl(when->tv_usec); k += sizeof(*when)/sizeof(int); indom = __ntohpmInDom((unsigned int)tbuf[k++]); numinst = ntohl(tbuf[k++]); if (numinst > 0) { instlist = &tbuf[k]; k += numinst; stridx = &tbuf[k]; #if defined(HAVE_32BIT_PTR) namelist = (char **)stridx; allinbuf = 1; /* allocation is all in tbuf */ #else allinbuf = 0; /* allocation for namelist + tbuf */ /* need to allocate to hold the pointers */ namelist = (char **)malloc(numinst*sizeof(char*)); if (namelist == NULL) { sts = -errno; goto end; } #endif k += numinst; namebase = (char *)&tbuf[k]; for (i = 0; i < numinst; i++) { instlist[i] = ntohl(instlist[i]); namelist[i] = &namebase[ntohl(stridx[i])]; } } else { /* no instances, or an error */ instlist = NULL; namelist = NULL; } if ((sts = addindom(lcp, indom, when, numinst, instlist, namelist, tbuf, allinbuf)) < 0) goto end; } else fseek(f, (long)rlen, SEEK_CUR); n = (int)fread(&check, 1, sizeof(check), f); check = ntohl(check); if (n != sizeof(check) || h.len != check) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: trailer read -> %d or len=%d: expected %d @ offset=%d\n", n, check, h.len, (int)(ftell(f) - sizeof(check))); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } }/*for*/ end: fseek(f, (long)(sizeof(__pmLogLabel) + 2*sizeof(int)), SEEK_SET); if (version2 && sts == 0) { __pmFixPMNSHashTab(lcp->l_pmns, numpmid, 1); } return sts; }
/* 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; }
static void docheck(pmResult *result) { int i, j, k; int sts; pmDesc desc; pmAtomValue av; pmValue *vp; pmValueSet *vsp; __pmHashNode *hptr = NULL; checkData *checkdata = NULL; double diff; struct timeval timediff; for (i = 0; i < result->numpmid; i++) { vsp = result->vset[i]; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL1) { if (vsp->numval == 0) { fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); fprintf(stderr, "] "); print_metric(stderr, vsp->pmid); fprintf(stderr, ": no values returned\n"); continue; } else if (vsp->numval < 0) { fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); fprintf(stderr, "] "); print_metric(stderr, vsp->pmid); fprintf(stderr, ": error from numval: %s\n", pmErrStr(vsp->numval)); continue; } } #endif if (vsp->numval <= 0) continue; /* check if pmid already in hash list */ if ((hptr = __pmHashSearch(vsp->pmid, &hashlist)) == NULL) { if ((sts = pmLookupDesc(vsp->pmid, &desc)) < 0) { fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); fprintf(stderr, "] "); print_metric(stderr, vsp->pmid); fprintf(stderr, ": pmLookupDesc failed: %s\n", pmErrStr(sts)); continue; } if (desc.type != PM_TYPE_32 && desc.type != PM_TYPE_U32 && desc.type != PM_TYPE_64 && desc.type != PM_TYPE_U64 && desc.type != PM_TYPE_FLOAT && desc.type != PM_TYPE_DOUBLE) { continue; /* no checks for non-numeric metrics */ } /* create a new one & add to list */ checkdata = (checkData*) malloc(sizeof(checkData)); newHashItem(vsp, &desc, checkdata, &result->timestamp); if (__pmHashAdd(checkdata->desc.pmid, (void*)checkdata, &hashlist) < 0) { fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); fprintf(stderr, "] "); print_metric(stderr, vsp->pmid); fprintf(stderr, ": __pmHashAdd failed (internal pmlogcheck error)\n"); /* free memory allocated above on insert failure */ for (j = 0; j < vsp->numval; j++) { if (checkdata->instlist[j] != NULL) free(checkdata->instlist[j]); } if (checkdata->instlist != NULL) free(checkdata->instlist); continue; } } else { /* pmid exists - update statistics */ checkdata = (checkData *)hptr->data; for (j = 0; j < vsp->numval; j++) { /* iterate thro result values */ vp = &vsp->vlist[j]; k = j; /* index into stored inst list, result may differ */ if ((vsp->numval > 1) || (checkdata->desc.indom != PM_INDOM_NULL)) { /* must store values using correct inst - probably in correct order already */ if ((k < checkdata->listsize) && (checkdata->instlist[k]->inst != vp->inst)) { for (k = 0; k < checkdata->listsize; k++) { if (vp->inst == checkdata->instlist[k]->inst) { break; /* k now correct */ } } if (k == checkdata->listsize) { /* no matching inst was found */ newHashInst(vp, checkdata, vsp->valfmt, &result->timestamp, k); continue; } } else if (k >= checkdata->listsize) { k = checkdata->listsize; newHashInst(vp, checkdata, vsp->valfmt, &result->timestamp, k); continue; } } if (k >= checkdata->listsize) { /* only error values observed so far */ k = checkdata->listsize; newHashInst(vp, checkdata, vsp->valfmt, &result->timestamp, k); continue; } timediff = result->timestamp; tsub(&timediff, &(checkdata->instlist[k]->lasttime)); if (timediff.tv_sec < 0) { /* clip negative values at zero */ timediff.tv_sec = 0; timediff.tv_usec = 0; } diff = __pmtimevalToReal(&timediff); if ((sts = pmExtractValue(vsp->valfmt, vp, checkdata->desc.type, &av, PM_TYPE_DOUBLE)) < 0) { fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); fprintf(stderr, "] "); print_metric(stderr, vsp->pmid); fprintf(stderr, ": pmExtractValue failed: %s\n", pmErrStr(sts)); continue; } if (checkdata->desc.sem == PM_SEM_COUNTER) { if (diff == 0.0) continue; diff *= checkdata->scale; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_APPL2) { fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol); print_stamp(stderr, &result->timestamp); fprintf(stderr, "] "); print_metric(stderr, checkdata->desc.pmid); fprintf(stderr, ": current counter value is %.0f\n", av.d); } #endif unwrap(av.d, &(result->timestamp), checkdata, k); } checkdata->instlist[k]->lastval = av.d; checkdata->instlist[k]->lasttime = result->timestamp; } } } }