int __pmSendInstanceReq(int fd, int from, const __pmTimeval *when, pmInDom indom, int inst, const char *name) { instance_req_t *pp; int need; int sts; need = sizeof(instance_req_t) - sizeof(int); if (name != NULL) need += PM_PDU_SIZE_BYTES(strlen(name)); if ((pp = (instance_req_t *)__pmFindPDUBuf(need)) == NULL) return -oserror(); pp->hdr.len = need; pp->hdr.type = PDU_INSTANCE_REQ; pp->hdr.from = from; pp->when.tv_sec = htonl((__int32_t)when->tv_sec); pp->when.tv_usec = htonl((__int32_t)when->tv_usec); pp->indom = __htonpmInDom(indom); pp->inst = htonl(inst); if (name == NULL) pp->namelen = 0; else { pp->namelen = (int)strlen(name); memcpy((void *)pp->name, (void *)name, pp->namelen); if ((pp->namelen % sizeof(__pmPDU)) != 0) { /* clear the padding bytes, lest they contain garbage */ int pad; char *padp = pp->name + pp->namelen; for (pad = sizeof(__pmPDU) - 1; pad >= (pp->namelen % sizeof(__pmPDU)); pad--) *padp++ = '~'; /* buffer end */ } pp->namelen = htonl(pp->namelen); } sts = __pmXmitPDU(fd, (__pmPDU *)pp); __pmUnpinPDUBuf(pp); return sts; }
int __pmSendText(int fd, int ctx, int ident, const char *buffer) { text_t *pp; size_t need; size_t len = strlen(buffer); int sts; need = sizeof(text_t) - sizeof(pp->buffer) + PM_PDU_SIZE_BYTES(len); if ((pp = (text_t *)__pmFindPDUBuf((int)need)) == NULL) return -oserror(); pp->hdr.len = (int)need; pp->hdr.type = PDU_TEXT; pp->hdr.from = ctx; /* * Note: ident argument must already be in network byte order. * The caller has to do this because the type of ident is not * part of the transmitted PDU_TEXT pdu; ident may be either * a pmID or pmInDom, and so the caller must use either * __htonpmID or __htonpmInDom (respectively). */ pp->ident = ident; pp->buflen = htonl(len); memcpy((void *)pp->buffer, (void *)buffer, len); if (len % sizeof(__pmPDU) != 0) { /* clear the padding bytes, lest they contain garbage */ int pad; char *padp = pp->buffer + len; for (pad = sizeof(__pmPDU) - 1; pad >= (len % sizeof(__pmPDU)); pad--) *padp++ = '~'; /* buffer end */ } sts = __pmXmitPDU(fd, (__pmPDU *)pp); __pmUnpinPDUBuf(pp); return sts; }
static int do_size(pmResult *rp) { int nbyte = 0; int i; int j; /* * Externally the log record looks like this ... * :----------:-----------:..........:---------: * | int len | timestamp | pmResult | int len | * :----------:-----------:..........:---------: * * start with sizes of the header len, timestamp, numpmid, and * trailer len */ nbyte = sizeof(int) + sizeof(__pmTimeval) + sizeof(int); /* len + timestamp + len */ nbyte += sizeof(int); /* numpmid */ for (i = 0; i < rp->numpmid; i++) { pmValueSet *vsp = rp->vset[i]; nbyte += sizeof(pmID) + sizeof(int); /* + pmid[i], numval */ if (vsp->numval > 0) { nbyte += sizeof(int); /* + valfmt */ for (j = 0; j < vsp->numval; j++) { nbyte += sizeof(__pmValue_PDU); /* + pmValue[j] */ if (vsp->valfmt != PM_VAL_INSITU) /* + pmValueBlock */ /* rounded up */ nbyte += PM_PDU_SIZE_BYTES(vsp->vlist[j].value.pval->vlen); } } } return nbyte; }
/* * Handle event records. * * Walk the packed array of events using similar logic to * pmUnpackEventRecords() but we don't need any allocations. * * For each embedded event parameter, make sure the metadata for * the associated metric is added to the archive. */ int do_events(pmValueSet *vsp) { pmEventArray *eap; char *base; pmEventRecord *erp; pmEventParameter *epp; int r; /* records */ int p; /* parameters in a record ... */ int i; /* instances ... */ int sts; pmDesc desc; for (i = 0; i < vsp->numval; i++) { if ((sts = __pmCheckEventRecords(vsp, i)) < 0) { __pmDumpEventRecords(stderr, vsp, i); return sts; } eap = (pmEventArray *)vsp->vlist[i].value.pval; if (eap->ea_nrecords == 0) return 0; base = (char *)&eap->ea_record[0]; for (r = 0; r < eap->ea_nrecords; r++) { erp = (pmEventRecord *)base; base += sizeof(erp->er_timestamp) + sizeof(erp->er_flags) + sizeof(erp->er_nparams); if (erp->er_flags & PM_EVENT_FLAG_MISSED) { /* * no event "parameters" here, just a missed records count * in er_nparams */ continue; } for (p = 0; p < erp->er_nparams; p++) { epp = (pmEventParameter *)base; base += sizeof(epp->ep_pmid) + PM_PDU_SIZE_BYTES(epp->ep_len); sts = __pmLogLookupDesc(&logctl, epp->ep_pmid, &desc); if (sts < 0) { int numnames; char **names; numnames = pmNameAll(epp->ep_pmid, &names); if (numnames < 0) { /* * Event parameter metric not defined in the PMNS. * This should not happen, but is probably not fatal, so * issue a warning and make up a name based on the pmid * event_param.<domain>.<cluster>.<item> */ char *name; size_t name_size = strlen("event_param")+3+1+4+1+4+1; names = (char **)malloc(sizeof(char*) + name_size); if (names == NULL) return -oserror(); name = (char *)&names[1]; names[0] = name; snprintf(name, name_size, "event_param.%s", pmIDStr(epp->ep_pmid)); fprintf(stderr, "Warning: metric %s has no name, using %s\n", pmIDStr(epp->ep_pmid), name); } sts = pmLookupDesc(epp->ep_pmid, &desc); if (sts < 0) { /* Event parameter metric does not have a pmDesc. * This should not happen, but is probably not entirely * fatal (although more serious than not having a metric * name), issue a warning and construct a minimalist * pmDesc */ desc.pmid = epp->ep_pmid; desc.type = PM_TYPE_AGGREGATE; desc.indom = PM_INDOM_NULL; desc.sem = PM_SEM_DISCRETE; memset(&desc.units, '\0', sizeof(desc.units)); fprintf(stderr, "Warning: metric %s (%s) has no descriptor, using a default one\n", names[0], pmIDStr(epp->ep_pmid)); } if ((sts = __pmLogPutDesc(&logctl, &desc, numnames, names)) < 0) { fprintf(stderr, "__pmLogPutDesc: %s\n", pmErrStr(sts)); exit(1); } free(names); } } } } return 0; }
int __pmDecodeInstance(__pmPDU *pdubuf, __pmInResult **result) { int i; int j; instance_t *rp; instlist_t *ip; __pmInResult *res; int sts; char *p; char *pdu_end; int keep_instlist; int keep_namelist; rp = (instance_t *)pdubuf; pdu_end = (char *)pdubuf + rp->hdr.len; if (pdu_end - (char *)pdubuf < sizeof(instance_t) - sizeof(__pmPDU)) return PM_ERR_IPC; if ((res = (__pmInResult *)malloc(sizeof(*res))) == NULL) return -oserror(); res->instlist = NULL; res->namelist = NULL; res->indom = __ntohpmInDom(rp->indom); res->numinst = ntohl(rp->numinst); if (res->numinst >= (INT_MAX / sizeof(res->instlist[0])) || res->numinst >= (INT_MAX / sizeof(res->namelist[0])) || res->numinst >= rp->hdr.len) { sts = PM_ERR_IPC; goto badsts; } if ((res->instlist = (int *)malloc(res->numinst * sizeof(res->instlist[0]))) == NULL) { sts = -oserror(); goto badsts; } if ((res->namelist = (char **)malloc(res->numinst * sizeof(res->namelist[0]))) == NULL) { sts = -oserror(); goto badsts; } /* required for __pmFreeInResult() in the event of a later error */ memset(res->namelist, 0, res->numinst * sizeof(res->namelist[0])); if (res->numinst == 1) keep_instlist = keep_namelist = 0; else keep_instlist = keep_namelist = 1; for (i = j = 0; i < res->numinst; i++) { ip = (instlist_t *)&rp->rest[j/sizeof(__pmPDU)]; if (sizeof(instlist_t) - sizeof(ip->name) > (size_t)(pdu_end - (char *)ip)) { sts = PM_ERR_IPC; goto badsts; } res->instlist[i] = ntohl(ip->inst); if (res->instlist[i] != PM_IN_NULL) keep_instlist = 1; ip->namelen = ntohl(ip->namelen); if (ip->namelen > 0) keep_namelist = 1; if (ip->namelen < 0) { sts = PM_ERR_IPC; goto badsts; } if (sizeof(instlist_t) - sizeof(int) + ip->namelen > (size_t)(pdu_end - (char *)ip)) { sts = PM_ERR_IPC; goto badsts; } if ((p = (char *)malloc(ip->namelen + 1)) == NULL) { sts = -oserror(); goto badsts; } memcpy((void *)p, (void *)ip->name, ip->namelen); p[ip->namelen] = '\0'; res->namelist[i] = p; j += sizeof(*ip) - sizeof(ip->name) + PM_PDU_SIZE_BYTES(ip->namelen); } if (keep_instlist == 0) { free(res->instlist); res->instlist = NULL; } if (keep_namelist == 0) { free(res->namelist[0]); free(res->namelist); res->namelist = NULL; } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_INDOM) __pmDumpInResult(stderr, res); #endif *result = res; return 0; badsts: __pmFreeInResult(res); return sts; }
int __pmSendInstance(int fd, int from, __pmInResult *result) { instance_t *rp; instlist_t *ip; int need; int i; int j; int sts; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_INDOM) __pmDumpInResult(stderr, result); #endif need = sizeof(*rp) - sizeof(rp->rest); /* instlist_t + name rounded up to a __pmPDU boundary */ for (i = 0; i < result->numinst; i++) { need += sizeof(*ip) - sizeof(ip->name); if (result->namelist != NULL) need += PM_PDU_SIZE_BYTES(strlen(result->namelist[i])); } if ((rp = (instance_t *)__pmFindPDUBuf(need)) == NULL) return -oserror(); rp->hdr.len = need; rp->hdr.type = PDU_INSTANCE; rp->hdr.from = from; rp->indom = __htonpmInDom(result->indom); rp->numinst = htonl(result->numinst); for (i = j = 0; i < result->numinst; i++) { ip = (instlist_t *)&rp->rest[j/sizeof(__pmPDU)]; if (result->instlist != NULL) ip->inst = htonl(result->instlist[i]); else /* weird, but this is going to be ignored at the other end */ ip->inst = htonl(PM_IN_NULL); if (result->namelist != NULL) { ip->namelen = (int)strlen(result->namelist[i]); memcpy((void *)ip->name, (void *)result->namelist[i], ip->namelen); if ((ip->namelen % sizeof(__pmPDU)) != 0) { /* clear the padding bytes, lest they contain garbage */ int pad; char *padp = ip->name + ip->namelen; for (pad = sizeof(__pmPDU) - 1; pad >= (ip->namelen % sizeof(__pmPDU)); pad--) *padp++ = '~'; /* buffer end */ } j += sizeof(*ip) - sizeof(ip->name) + PM_PDU_SIZE_BYTES(ip->namelen); ip->namelen = htonl(ip->namelen); } else { ip->namelen = 0; j += sizeof(*ip) - sizeof(ip->name); } } sts = __pmXmitPDU(fd, (__pmPDU *)rp); __pmUnpinPDUBuf(rp); return sts; }