예제 #1
0
파일: p_label.c 프로젝트: goodwinos/pcp
char *
__pmLabelIdentString(int ident, int type, char *buf, size_t buflen)
{
    char	*p, id[32];

    switch (type) {
    case PM_LABEL_DOMAIN:
	pmsprintf(buf, buflen, "Domain %u", ident);
	break;
    case PM_LABEL_INDOM:
    case PM_LABEL_INSTANCES:
	pmsprintf(buf, buflen, "InDom %s", pmInDomStr_r(ident, id, sizeof(id)));
	break;
    case PM_LABEL_CLUSTER:
	pmIDStr_r(ident, id, sizeof(id));
	p = rindex(id, '.');
	*p = '\0';
	pmsprintf(buf, buflen, "Cluster %s", id);
	break;
    case PM_LABEL_ITEM:
	pmsprintf(buf, buflen, "PMID %s", pmIDStr_r(ident, id, sizeof(id)));
	break;
    case PM_LABEL_CONTEXT:
	pmsprintf(buf, buflen, "Context");
	break;
    default:
	buf[0] = '\0';
	break;
    }
    return buf;
}
예제 #2
0
파일: multithread5.c 프로젝트: Aconex/pcp
static void
foo(FILE *f, char *fn, int i)
{
    pmDesc	desc;
    char	strbuf[60];
    int		sts;

    sts = pmLookupDesc(pmidlist[i], &desc);
    if (sts < 0) {
	fprintf(f, "%s: pmLookupDesc[%s] -> %s\n", fn, pmIDStr_r(pmidlist[i], strbuf, sizeof(strbuf)), pmErrStr(sts));
	pthread_exit("botch");
    }
    else if (pmidlist[i] != desc.pmid) {
	fprintf(f, "%s: pmLookupDesc: Expecting PMID: %s", fn, pmIDStr_r(pmidlist[i], strbuf, sizeof(strbuf)));
	fprintf(f, " got: %s\n", pmIDStr_r(desc.pmid, strbuf, sizeof(strbuf)));
	pthread_exit("botch");
    }
    else {
	fprintf(f, "%s: %s (%s) ->", fn, namelist[i], pmIDStr_r(pmidlist[i], strbuf, sizeof(strbuf)));
	fprintf(f, " %s", pmTypeStr_r(desc.type, strbuf, sizeof(strbuf)));
	fprintf(f, " %s", pmInDomStr_r(desc.indom, strbuf, sizeof(strbuf)));
	if (desc.sem == PM_SEM_COUNTER) fprintf(f, " counter");
	else if (desc.sem == PM_SEM_INSTANT) fprintf(f, " instant");
	else if (desc.sem == PM_SEM_DISCRETE) fprintf(f, " discrete");
	else fprintf(f, " sem-%d", desc.sem);
	fprintf(f, " %s\n", pmUnitsStr_r(&desc.units, strbuf, sizeof(strbuf)));
    }
}
예제 #3
0
파일: callback.c 프로젝트: ColeJackes/pcp
int
pmdaDesc(pmID pmid, pmDesc *desc, pmdaExt *pmda)
{
    e_ext_t		*extp = (e_ext_t *)pmda->e_ext;
    pmdaMetric		*metric;
    char		strbuf[32];

    if (extp->dispatch->comm.pmda_interface >= PMDA_INTERFACE_5)
	__pmdaSetContext(pmda->e_context);

    if (pmda->e_flags & PMDA_EXT_FLAG_HASHED)
	metric = __pmdaHashedSearch(pmid, &extp->hashpmids);
    else if (pmda->e_direct)
	metric = __pmdaDirectSearch(pmid, pmda);
    else
	metric = __pmdaLinearSearch(pmid, pmda);

    if (metric) {
	*desc = metric->m_desc;
	return 0;
    }

    __pmNotifyErr(LOG_ERR, "pmdaDesc: Requested metric %s is not defined",
			pmIDStr_r(pmid, strbuf, sizeof(strbuf)));
    return PM_ERR_PMID;
}
예제 #4
0
파일: util.c 프로젝트: scotte/pcp
char *
strcluster(pmID pmid)
{
    static char buffer[32];
    char *p;

    pmIDStr_r(pmid, buffer, sizeof(buffer));
    p = rindex(buffer, '.');
    *p = '\0';
    return buffer;
}
예제 #5
0
파일: p_desc.c 프로젝트: goodwinos/pcp
int
__pmSendDescReq(int fd, int from, pmID pmid)
{
    desc_req_t	*pp;
    int		sts;

    if ((pp = (desc_req_t *)__pmFindPDUBuf(sizeof(desc_req_t))) == NULL)
	return -oserror();
    pp->hdr.len = sizeof(desc_req_t);
    pp->hdr.type = PDU_DESC_REQ;
    pp->hdr.from = from;
    pp->pmid = __htonpmID(pmid);

#ifdef DESPERATE
    {
	char	strbuf[20];
	fprintf(stderr, "__pmSendDescReq: converted 0x%08x (%s) to 0x%08x\n", pmid, pmIDStr_r(pmid, strbuf, sizeof(strbuf)), pp->pmid);
    }
#endif

    sts = __pmXmitPDU(fd, (__pmPDU *)pp);
    __pmUnpinPDUBuf(pp);
    return sts;
}
예제 #6
0
파일: import.c 프로젝트: Aconex/pcp
void
pmiDump(void)
{
    FILE	*f = stderr;

    fprintf(f, "pmiDump: context %ld of %d",
	(long)(current - context_tab), ncontext);
    if (current == NULL) {
	fprintf(f, " Error: current context is not defined.\n");
	return;
    }
    else {
	fprintf(f, " archive: %s\n", 
	    current->archive == NULL ? "<undefined>" : current->archive);
    }
    fprintf(f, "  state: %d ", current->state);
    switch (current->state) {
	case CONTEXT_START:
	    fprintf(f, "(start)");
	    break;
	case CONTEXT_ACTIVE:
	    fprintf(f, "(active)");
	    break;
	case CONTEXT_END:
	    fprintf(f, "(end)");
	    break;
	default:
	    fprintf(f, "(BAD)");
	    break;
    }
    fprintf(f, " hostname: %s timezone: %s\n", 
	current->hostname == NULL ? "<undefined>" : current->hostname,
	current->timezone == NULL ? "<undefined>" : current->timezone);
    if (current->nmetric == 0)
	fprintf(f, "  No metrics.\n");
    else {
	int	m;
	char	strbuf[20];
	for (m = 0; m < current->nmetric; m++) {
	    fprintf(f, "  metric[%d] name=%s pmid=%s\n",
		m, current->metric[m].name,
		pmIDStr_r(current->metric[m].pmid, strbuf, sizeof(strbuf)));
	    __pmPrintDesc(f, &current->metric[m].desc);
	}
    }
    if (current->nindom == 0)
	fprintf(f, "  No indoms.\n");
    else {
	int	i;
	char	strbuf[20];
	for (i = 0; i < current->nindom; i++) {
	    fprintf(f, "  indom[%d] indom=%s",
		i, pmInDomStr_r(current->indom[i].indom, strbuf, sizeof(strbuf)));
	    if (current->indom[i].ninstance == 0) {
		fprintf(f, "   No instances.\n");
	    }
	    else {
		int	j;
		fputc('\n', f);
		for (j = 0; j < current->indom[i].ninstance; j++) {
		    fprintf(f, "   instance[%d] %s (%d)\n",
			j, current->indom[i].name[j],
			current->indom[i].inst[j]);
		}
	    }
	}
    }
    if (current->nhandle == 0)
	fprintf(f, "  No handles.\n");
    else {
	int	h;
	char	strbuf[20];
	for (h = 0; h < current->nhandle; h++) {
	    fprintf(f, "  handle[%d] metric=%s (%s) instance=%d\n",
		h, current->metric[current->handle[h].midx].name,
		pmIDStr_r(current->metric[current->handle[h].midx].pmid, strbuf, sizeof(strbuf)),
		current->handle[h].inst);
	}
    }
    if (current->result == NULL)
	fprintf(f, "  No pmResult.\n");
    else
	__pmDumpResult(f, current->result);
}
예제 #7
0
파일: callback.c 프로젝트: ColeJackes/pcp
int
pmdaFetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda)
{
    int			i;		/* over pmidlist[] */
    int			j;		/* over metatab and vset->vlist[] */
    int			sts;
    int			need;
    int			inst;
    int			numval;
    pmValueSet		*vset;
    pmDesc		*dp;
    pmdaMetric          metaBuf;
    pmdaMetric		*metap;
    pmAtomValue		atom;
    int			type;
    e_ext_t		*extp = (e_ext_t *)pmda->e_ext;

    if (extp->dispatch->version.any.ext != pmda)
	fprintf(stderr, "Botch: pmdaFetch: PMDA domain=%d pmda=%p extp=%p backpointer=%p pmda-via-backpointer %p NOT EQUAL to pmda\n",
	    pmda->e_domain, pmda, extp, extp->dispatch, extp->dispatch->version.any.ext);

    if (extp->dispatch->comm.pmda_interface >= PMDA_INTERFACE_5)
	__pmdaSetContext(pmda->e_context);

    if (numpmid > extp->maxnpmids) {
	if (extp->res != NULL)
	    free(extp->res);
	/* (numpmid - 1) because there's room for one valueSet in a pmResult */
	need = (int)sizeof(pmResult) + (numpmid - 1) * (int)sizeof(pmValueSet *);
	if ((extp->res = (pmResult *) malloc(need)) == NULL)
	    return -oserror();
	extp->maxnpmids = numpmid;
    }

    extp->res->timestamp.tv_sec = 0;
    extp->res->timestamp.tv_usec = 0;
    extp->res->numpmid = numpmid;

    /* Look up the pmDesc for the incoming pmids in our pmdaMetrics tables,
       if present.  Fall back to .desc callback if not found (for highly
       dynamic pmdas). */
    for (i = 0; i < numpmid; i++) {
        dp = NULL;

	if (pmda->e_flags & PMDA_EXT_FLAG_HASHED)
	    metap = __pmdaHashedSearch(pmidlist[i], &extp->hashpmids);
	else if (pmda->e_direct)
	    metap = __pmdaDirectSearch(pmidlist[i], pmda);
	else
	    metap = __pmdaLinearSearch(pmidlist[i], pmda);

	if (metap != NULL)
	    dp = &(metap->m_desc);
        else {
            /* possibly a highly dynamic metric with null metrictab[] */
            if (extp->dispatch->version.any.desc != NULL) {
                /* may need a temporary pmdaMetric for passing to e_fetchCallBack */
                sts = (*(extp->dispatch->version.any.desc))(pmidlist[i], &metaBuf.m_desc, pmda);
                if (sts >= 0) {
                    metaBuf.m_user = NULL;
                    metap = &metaBuf;
                    dp = &metaBuf.m_desc;
                }
            }
        }

	if (dp != NULL) {
	    if (dp->indom != PM_INDOM_NULL) {
		/* count instances in the profile */
		numval = 0;
		/* count instances in indom */
		__pmdaStartInst(dp->indom, pmda);
		while (__pmdaNextInst(&inst, pmda)) {
		    numval++;
		}
	    }
	    else {
		/* singular instance domains */
		numval = 1;
	    }
	}
	else {
	    /* dynamic name metrics may often vanish, avoid log spam */
	    if (extp->dispatch->comm.pmda_interface < PMDA_INTERFACE_4) {
		char	strbuf[20];
		__pmNotifyErr(LOG_ERR,
			"pmdaFetch: Requested metric %s is not defined",
			 pmIDStr_r(pmidlist[i], strbuf, sizeof(strbuf)));
	    }
	    numval = PM_ERR_PMID;
	}


	/* Must use individual malloc()s because of pmFreeResult() */
	if (numval >= 1)
	    extp->res->vset[i] = vset = (pmValueSet *)malloc(sizeof(pmValueSet) +
					    (numval - 1)*sizeof(pmValue));
	else
	    extp->res->vset[i] = vset = (pmValueSet *)malloc(sizeof(pmValueSet) -
					    sizeof(pmValue));
	if (vset == NULL) {
	    sts = -oserror();
	    goto error;
	}
	vset->pmid = pmidlist[i];
	vset->numval = numval;
	vset->valfmt = PM_VAL_INSITU;
	if (vset->numval <= 0)
	    continue;

	if (dp->indom == PM_INDOM_NULL)
	    inst = PM_IN_NULL;
	else {
	    __pmdaStartInst(dp->indom, pmda);
	    __pmdaNextInst(&inst, pmda);
	}
	type = dp->type;
	j = 0;
	do {
	    if (j == numval) {
		/* more instances than expected! */
		numval++;
		extp->res->vset[i] = vset = (pmValueSet *)realloc(vset,
			    sizeof(pmValueSet) + (numval - 1)*sizeof(pmValue));
		if (vset == NULL) {
		    sts = -oserror();
		    goto error;
		}
	    }
	    vset->vlist[j].inst = inst;

	    if ((sts = (*(pmda->e_fetchCallBack))(metap, inst, &atom)) < 0) {
		char	strbuf[20];

		pmIDStr_r(dp->pmid, strbuf, sizeof(strbuf));
		if (sts == PM_ERR_PMID) {
		    __pmNotifyErr(LOG_ERR, 
		        "pmdaFetch: PMID %s not handled by fetch callback\n",
				strbuf);
		}
		else if (sts == PM_ERR_INST) {
#ifdef PCP_DEBUG
		    if (pmDebug & DBG_TRACE_LIBPMDA) {
			__pmNotifyErr(LOG_ERR,
			    "pmdaFetch: Instance %d of PMID %s not handled by fetch callback\n",
				    inst, strbuf);
		    }
#endif
		}
		else if (sts == PM_ERR_APPVERSION ||
			 sts == PM_ERR_PERMISSION ||
			 sts == PM_ERR_AGAIN ||
			 sts == PM_ERR_NYI) {
#ifdef PCP_DEBUG
		    if (pmDebug & DBG_TRACE_LIBPMDA) {
			__pmNotifyErr(LOG_ERR,
			     "pmdaFetch: Unavailable metric PMID %s[%d]\n",
				    strbuf, inst);
		    }
#endif
		}
		else {
		    __pmNotifyErr(LOG_ERR,
			"pmdaFetch: Fetch callback error from metric PMID %s[%d]: %s\n",
				strbuf, inst, pmErrStr(sts));
		}
	    }
	    else {
		/*
		 * PMDA_INTERFACE_2
		 *	>= 0 => OK
		 * PMDA_INTERFACE_3 or PMDA_INTERFACE_4
		 *	== 0 => no values
		 *	> 0  => OK
		 * PMDA_INTERFACE_5 or later
		 *	== 0 (PMDA_FETCH_NOVALUES) => no values
		 *	== 1 (PMDA_FETCH_STATIC) or > 2 => OK
		 *	== 2 (PMDA_FETCH_DYNAMIC) => OK and free(atom.vp)
		 *	     after __pmStuffValue() called
		 */
		if (extp->dispatch->comm.pmda_interface == PMDA_INTERFACE_2 ||
		    (extp->dispatch->comm.pmda_interface >= PMDA_INTERFACE_3 && sts > 0)) {
		    int		lsts;

		    if ((lsts = __pmStuffValue(&atom, &vset->vlist[j], type)) == PM_ERR_TYPE) {
			char	strbuf[20];
			char	st2buf[20];
			__pmNotifyErr(LOG_ERR, 
				     "pmdaFetch: Descriptor type (%s) for metric %s is bad",
				     pmTypeStr_r(type, strbuf, sizeof(strbuf)),
				     pmIDStr_r(dp->pmid, st2buf, sizeof(st2buf)));
		    }
		    else if (lsts >= 0) {
			vset->valfmt = lsts;
			j++;
		    }
		    if (extp->dispatch->comm.pmda_interface >= PMDA_INTERFACE_5 && sts == PMDA_FETCH_DYNAMIC) {
			if (type == PM_TYPE_STRING)
			    free(atom.cp);
			else if (type == PM_TYPE_AGGREGATE)
			    free(atom.vbp);
			else {
			    char	strbuf[20];
			    char	st2buf[20];
			    __pmNotifyErr(LOG_WARNING,
					  "pmdaFetch: Attempt to free value for metric %s of wrong type %s\n",
					  pmIDStr_r(dp->pmid, strbuf, sizeof(strbuf)),
					  pmTypeStr_r(type, st2buf, sizeof(st2buf)));
			}
		    }
		    if (lsts < 0)
			sts = lsts;
		}
	    }
	} while (dp->indom != PM_INDOM_NULL && __pmdaNextInst(&inst, pmda));

	if (j == 0)
	    vset->numval = sts;
	else
	    vset->numval = j;

    }
    *resp = extp->res;
    return 0;

error:

    if (i) {
	extp->res->numpmid = i;
	__pmFreeResultValues(extp->res);
    }
    return sts;
}
예제 #8
0
파일: multithread9.c 프로젝트: scotte/pcp
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);

}
예제 #9
0
파일: check.c 프로젝트: jujis008/pcp
/*
 * Called when an error PDU containing PMCD_ADD_AGENT is received.
 * This function checks all of the configured metrics to make sure that
 * they have not changed. For example due to a PMDA being replaced by an
 * updated version 
 */
void
validate_metrics(void)
{
    const task_t	*tp;
    pmID		*new_pmids;
    const pmDesc	*old_desc;
    pmDesc		new_desc;
    int			index;
    int			error;
    int			sts;
    time_t		now;
    char		buf1[20], buf2[20];

    time(&now);
    fprintf(stderr, "%s: Validating metrics after PMCD state changed at %s",
		    pmProgname, ctime(&now));

    /*
     * Check each metric in each element of the task list, whether it is
     * active or not.
     */
    error = 0;
    for (tp = tasklist; tp != NULL; tp = tp->t_next) {
	/* We need at least one metric to look up. */
	if (tp->t_numpmid < 1)
	    continue;

	/*
	 * Perform a bulk lookup and then check for consistency.
	 * Lookup the metrics by name, since that's the way they are
	 * specified in the pmlogger config file.
	 * We need a temporary array for the new pmIDs
	 */

	new_pmids = malloc(tp->t_numpmid * sizeof(*tp->t_pmidlist));
	if (new_pmids == NULL) {
	    __pmNoMem("allocating pmID array for validating metrice",
		      tp->t_numpmid * sizeof(*tp->t_pmidlist), PM_FATAL_ERR);
	}
	if ((sts = pmLookupName(tp->t_numpmid, tp->t_namelist, new_pmids)) < 0) {
	    fprintf(stderr, "Error looking up metrics: Reason: %s\n",
		    pmErrStr(sts));
	    exit(1);
	}

	/* Now check the individual metrics for problems. */
	for (index = 0; index < tp->t_numpmid; ++index) {
	    /* If there was an error looking up this metric, try again in order
	     * to obtain the reason. If there is no error the second time
	     * (possible), then the needed pmID will be fetched.
	     */
	    if (new_pmids[index] == PM_ID_NULL) {
		if ((sts = pmLookupName(1, &tp->t_namelist[index],
					&new_pmids[index])) < 0) {
		    /* The lookup of the metric is still in error. */
		    fprintf(stderr, "Error looking up %s: Reason: %s\n",
			    tp->t_namelist[index], pmErrStr(sts));
		    ++error;
		    continue;
		}
		/* No error the second time. Fall through */
	    }

	    /*
	     * Check that the pmid, type, semantics, instance domain and units
	     * of the metric have not changed.
	     */
	    if (new_pmids[index] != tp->t_pmidlist[index]) {
		fprintf(stderr, "PMID of metric \"%s\" has changed from %s to %s\n",
			tp->t_namelist[index],
			pmIDStr_r(tp->t_pmidlist[index], buf1, sizeof(buf1)),
			pmIDStr_r(new_pmids[index], buf2, sizeof(buf2)));
		++error;
	    }
	    if ((sts = pmLookupDesc(new_pmids[index], &new_desc)) < 0) {
		fprintf(stderr, "Description unavailable for metric \"%s\": %s\n",
			tp->t_namelist[index], pmErrStr(sts));
		++error;
		continue;
	    }
	    old_desc = &tp->t_desclist[index];
	    if (new_desc.type != old_desc->type) {
		fprintf(stderr, "Type of metric \"%s\" has changed from %s to %s\n",
			tp->t_namelist[index],
			pmTypeStr_r(old_desc->type, buf1, sizeof(buf1)),
			pmTypeStr_r(new_desc.type, buf2, sizeof(buf2)));
		++error;
	    }
	    if (new_desc.sem != old_desc->sem) {
		fprintf(stderr, "Semantics of metric \"%s\" have changed from %s to %s\n",
			tp->t_namelist[index],
			pmSemStr_r(old_desc->sem, buf1, sizeof(buf1)),
			pmSemStr_r(new_desc.sem, buf2, sizeof(buf2)));
		++error;
	    }
	    if (new_desc.indom != old_desc->indom) {
		fprintf(stderr, "Instance domain of metric \"%s\" has changed from %s to %s\n",
			tp->t_namelist[index],
			pmInDomStr_r(old_desc->indom, buf1, sizeof(buf1)),
			pmInDomStr_r(new_desc.indom, buf2, sizeof(buf2)));
		++error;
	    }
	    if (new_desc.units.dimSpace != old_desc->units.dimSpace ||
		new_desc.units.dimTime != old_desc->units.dimTime ||
		new_desc.units.dimCount != old_desc->units.dimCount ||
		new_desc.units.scaleSpace != old_desc->units.scaleSpace ||
		new_desc.units.scaleTime != old_desc->units.scaleTime ||
		new_desc.units.scaleCount != old_desc->units.scaleCount) {
		++error;
		fprintf(stderr, "Units of metric \"%s\" has changed from %s to %s\n",
			tp->t_namelist[index],
			pmUnitsStr_r(&old_desc->units, buf1, sizeof(buf1)),
			pmUnitsStr_r(&new_desc.units, buf2, sizeof(buf2)));
	    }
	} /* loop over metrics */

	free(new_pmids);
    } /* Loop over task list */

    /* We cannot continue, if any of the metrics have changed. */
    if (error) {
	fprintf(stderr, "One or more configured metrics have changed after pmcd state change. Exiting\n");
	exit(1);
    }
}
예제 #10
0
파일: fetchlocal.c 프로젝트: Aconex/pcp
/*
 * Called with valid context locked ...
 */
int
__pmFetchLocal(__pmContext *ctxp, int numpmid, pmID pmidlist[], pmResult **result)
{
    int		sts;
    int		ctx;
    int		j;
    int		k;
    int		n;
    pmResult	*ans;
    pmResult	*tmp_ans;
    __pmDSO	*dp;
    int		need;

    static pmID * splitlist=NULL;
    static int	splitmax=0;

    if (PM_MULTIPLE_THREADS(PM_SCOPE_DSO_PMDA))
	/* Local context requires single-threaded applications */
	return PM_ERR_THREAD;
    if (numpmid < 1)
	return PM_ERR_TOOSMALL;

    ctx = __pmPtrToHandle(ctxp);

    /*
     * this is very ugly ... the DSOs have a high-water mark
     * allocation algorithm for the result skeleton, but the
     * code that calls us assumes it has freedom to retain
     * this result structure for as long as it wishes, and
     * then to call pmFreeResult
     *
     * we make another skeleton, selectively copy and return that
     *
     * (numpmid - 1) because there's room for one valueSet
     * in a pmResult
     */
    need = (int)sizeof(pmResult) + (numpmid - 1) * (int)sizeof(pmValueSet *);
    if ((ans = (pmResult *)malloc(need)) == NULL)
	return -oserror();

    /*
     * Check if we have enough space to accomodate "best" case scenario -
     * all pmids are from the same domain
     */
    if (splitmax < numpmid) {
	splitmax = numpmid;
	pmID *tmp_list = (pmID *)realloc(splitlist, sizeof(pmID)*splitmax);
	if (tmp_list == NULL) {
	    free(splitlist);
	    splitmax = 0;
	    free(ans);
	    return -oserror();
	}
	splitlist = tmp_list;
    }

    ans->numpmid = numpmid;
    __pmtimevalNow(&ans->timestamp);
    for (j = 0; j < numpmid; j++)
	ans->vset[j] = NULL;

    for (j = 0; j < numpmid; j++) {
	int cnt;

	if (ans->vset[j] != NULL)
	    /* picked up in a previous fetch */
	    continue;

	sts = 0;
	if ((dp = __pmLookupDSO(((__pmID_int *)&pmidlist[j])->domain)) == NULL)
	    /* based on domain, unknown PMDA */
	    sts = PM_ERR_NOAGENT;
	else {
	    if (ctxp->c_sent != dp->domain) {
		/*
		 * current profile is _not_ already cached at other end of
		 * IPC, so send get current profile ...
		 * Note: trickier than the non-local case, as no per-PMDA
		 *	 caching at the PMCD end, so need to remember the
		 *	 last domain to receive a profile
		 */
#ifdef PCP_DEBUG
		if (pmDebug & DBG_TRACE_FETCH)
		    fprintf(stderr, 
			    "__pmFetchLocal: calling ???_profile(domain: %d), "
			    "context: %d\n", dp->domain, ctx);
#endif
		if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_5)
		    dp->dispatch.version.four.ext->e_context = ctx;
		sts = dp->dispatch.version.any.profile(ctxp->c_instprof,
						dp->dispatch.version.any.ext);
		if (sts >= 0)
		    ctxp->c_sent = dp->domain;
	    }
	}

	/* Copy all pmID for the current domain into the temp. list */
	for (cnt=0, k=j; k < numpmid; k++ ) {
	    if (((__pmID_int*)(pmidlist+k))->domain ==
		((__pmID_int*)(pmidlist+j))->domain)
		splitlist[cnt++] = pmidlist[k];
	}

	if (sts >= 0) {
	    if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_5)
		dp->dispatch.version.four.ext->e_context = ctx;
	    sts = dp->dispatch.version.any.fetch(cnt, splitlist, &tmp_ans,
						dp->dispatch.version.any.ext);
	}

	/* Copy results back
	 *
	 * Note: We DO NOT have to free tmp_ans since DSO PMDA would
	 *		ALWAYS return a pointer to the static area.
	 */
	for (n = 0, k = j; k < numpmid && n < cnt; k++) {
	    if (pmidlist[k] == splitlist[n]) {
		if (sts < 0) {
		    ans->vset[k] = (pmValueSet *)malloc(sizeof(pmValueSet));
		    if (ans->vset[k] == NULL) {
			/* cleanup all partial allocations for ans->vset[] */
			for (k--; k >=0; k--)
			    free(ans->vset[k]);
			free(ans);
			return -oserror();
		    }
		    ans->vset[k]->numval = sts;
		    ans->vset[k]->pmid = pmidlist[k];
		}
		else {
		    ans->vset[k] = tmp_ans->vset[n];
		}
#ifdef PCP_DEBUG
		if (pmDebug & DBG_TRACE_FETCH) {
		    char	strbuf[20];
		    char	errmsg[PM_MAXERRMSGLEN];
		    fprintf(stderr, "__pmFetchLocal: [%d] PMID=%s nval=",
			    k, pmIDStr_r(pmidlist[k], strbuf, sizeof(strbuf)));
		    if (ans->vset[k]->numval < 0)
			fprintf(stderr, "%s\n",
				pmErrStr_r(ans->vset[k]->numval, errmsg, sizeof(errmsg)));
		    else
			fprintf(stderr, "%d\n", ans->vset[k]->numval);
		}
#endif
		n++;
	    }
	}
    }
    *result = ans;

    return 0;
}
예제 #11
0
/*
 * Walk the pmidlist[] from pmFetch.
 * For each derived metric found in the list add all the operand metrics,
 * and build a combined pmID list (newlist).
 *
 * Return 0 if no derived metrics in the list, else the number of pmIDs
 * in the combined list.
 *
 * The derived metric pmIDs are left in the combined list (they will
 * return PM_ERR_NOAGENT from the fetch) to simplify the post-processing
 * of the pmResult in __dmpostfetch()
 */
int
__dmprefetch(__pmContext *ctxp, int numpmid, const pmID *pmidlist, pmID **newlist)
{
    int		i;
    int		j;
    int		m;
    int		xtracnt = 0;
    pmID	*xtralist = NULL;
    pmID	*list;
    ctl_t	*cp = (ctl_t *)ctxp->c_dm;

    /* if needed, init() called in __dmopencontext beforehand */

    if (cp == NULL) return 0;

    /*
     * save numpmid to be used in __dmpostfetch() ... works because calls
     * to pmFetch cannot be nested (at all, but certainly for the same
     * context).
     * Ditto for the fast path flag (fetch_has_dm).
     */
    cp->numpmid = numpmid;
    cp->fetch_has_dm = 0;

    for (m = 0; m < numpmid; m++) {
	if (!IS_DERIVED(pmidlist[m]))
	    continue;
	for (i = 0; i < cp->nmetric; i++) {
	    if (pmidlist[m] == cp->mlist[i].pmid) {
		if (cp->mlist[i].expr != NULL) {
		    get_pmids(cp->mlist[i].expr, &xtracnt, &xtralist);
		    cp->fetch_has_dm = 1;
		}
		break;
	    }
	}
    }
    if (xtracnt == 0) {
	if (cp->fetch_has_dm)
	    return numpmid;
	else
	    return 0;
    }

    /*
     * Some of the "extra" ones, may already be in the caller's pmFetch 
     * list, or repeated in xtralist[] (if the same metric operand appears
     * more than once as a leaf node in the expression tree.
     * Remove these duplicates
     */
    j = 0;
    for (i = 0; i < xtracnt; i++) {
	for (m = 0; m < numpmid; m++) {
	    if (xtralist[i] == pmidlist[m])
		/* already in pmFetch list */
		break;
	}
	if (m < numpmid) continue;
	for (m = 0; m < j; m++) {
	    if (xtralist[i] == xtralist[m])
	    	/* already in xtralist[] */
		break;
	}
	if (m == j)
	    xtralist[j++] = xtralist[i];
    }
    xtracnt = j;
    if (xtracnt == 0) {
	free(xtralist);
	return numpmid;
    }

#ifdef PCP_DEBUG
    if ((pmDebug & DBG_TRACE_DERIVE) && (pmDebug & DBG_TRACE_APPL2)) {
	char	strbuf[20];
	fprintf(stderr, "derived metrics prefetch added %d metrics:", xtracnt);
	for (i = 0; i < xtracnt; i++)
	    fprintf(stderr, " %s", pmIDStr_r(xtralist[i], strbuf, sizeof(strbuf)));
	fputc('\n', stderr);
    }
#endif
    if ((list = (pmID *)malloc((numpmid+xtracnt)*sizeof(pmID))) == NULL) {
	__pmNoMem("__dmprefetch: alloc list", (numpmid+xtracnt)*sizeof(pmID), PM_FATAL_ERR);
	/*NOTREACHED*/
    }
    for (m = 0; m < numpmid; m++) {
	list[m] = pmidlist[m];
    }
    for (i = 0; i < xtracnt; i++) {
	list[m++] = xtralist[i];
    }
    free(xtralist);
    *newlist = list;

    return m;
}
예제 #12
0
/*
 * Walk an expression tree, filling in operand values from the
 * pmResult at the leaf nodes and propagating the computed values
 * towards the root node of the tree.
 */
static int
eval_expr(node_t *np, pmResult *rp, int level)
{
    int		sts;
    int		i;
    int		j;
    int		k;
    size_t	need;

    assert(np != NULL);
    if (np->left != NULL) {
	sts = eval_expr(np->left, rp, level+1);
	if (sts < 0) return sts;
    }
    if (np->right != NULL) {
	sts = eval_expr(np->right, rp, level+1);
	if (sts < 0) return sts;
    }

    /* mostly, np->left is not NULL ... */
    assert (np->type == L_NUMBER || np->type == L_NAME || np->left != NULL);

    switch (np->type) {

	case L_NUMBER:
	    if (np->info->numval == 0) {
		/* initialize ivlist[] for singular instance first time through */
		np->info->numval = 1;
		if ((np->info->ivlist = (val_t *)malloc(sizeof(val_t))) == NULL) {
		    __pmNoMem("eval_expr: number ivlist", sizeof(val_t), PM_FATAL_ERR);
		    /*NOTREACHED*/
		}
		np->info->ivlist[0].inst = PM_INDOM_NULL;
		/* don't need error checking, done in the lexical scanner */
		np->info->ivlist[0].value.l = atoi(np->value);
	    }
	    return 1;
	    break;

	case L_DELTA:
	case L_RATE:
	    /*
	     * this and the last values are in the left expr
	     */
	    np->info->last_stamp = np->info->stamp;
	    np->info->stamp = rp->timestamp;
	    free_ivlist(np);
	    np->info->numval = np->left->info->numval <= np->left->info->last_numval ? np->left->info->numval : np->left->info->last_numval;
	    if (np->info->numval <= 0)
		return np->info->numval;
	    if ((np->info->ivlist = (val_t *)malloc(np->info->numval*sizeof(val_t))) == NULL) {
		__pmNoMem("eval_expr: delta()/rate() ivlist", np->info->numval*sizeof(val_t), PM_FATAL_ERR);
		/*NOTREACHED*/
	    }
	    /*
	     * delta()
	     * ivlist[k] = left->ivlist[i] - left->last_ivlist[j]
	     * rate()
	     * ivlist[k] = (left->ivlist[i] - left->last_ivlist[j]) /
	     *             (timestamp - left->last_stamp)
	     */
	    for (i = k = 0; i < np->left->info->numval; i++) {
		j = i;
		if (j >= np->left->info->last_numval)
		    j = 0;
		if (np->left->info->ivlist[i].inst != np->left->info->last_ivlist[j].inst) {
		    /* current ith inst != last jth inst ... search in last */
#ifdef PCP_DEBUG
		    if ((pmDebug & DBG_TRACE_DERIVE) && (pmDebug & DBG_TRACE_APPL2)) {
			fprintf(stderr, "eval_expr: inst[%d] mismatch left [%d]=%d last [%d]=%d\n", k, i, np->left->info->ivlist[i].inst, j, np->left->info->last_ivlist[j].inst);
		    }
#endif
		    for (j = 0; j < np->left->info->last_numval; j++) {
			if (np->left->info->ivlist[i].inst == np->left->info->last_ivlist[j].inst)
			    break;
		    }
		    if (j == np->left->info->last_numval) {
			/* no match, skip this instance from this result */
			continue;
		    }
#ifdef PCP_DEBUG
		    else {
			if ((pmDebug & DBG_TRACE_DERIVE) && (pmDebug & DBG_TRACE_APPL2)) {
			    fprintf(stderr, "eval_expr: recover @ last [%d]=%d\n", j, np->left->info->last_ivlist[j].inst);
			}
		    }
#endif
		}
		np->info->ivlist[k].inst = np->left->info->ivlist[i].inst;
		if (np->type == L_DELTA) {
		    /* for delta() result type == operand type */
		    switch (np->left->desc.type) {
			case PM_TYPE_32:
			    np->info->ivlist[k].value.l = np->left->info->ivlist[i].value.l - np->left->info->last_ivlist[j].value.l;
			    break;
			case PM_TYPE_U32:
			    np->info->ivlist[k].value.ul = np->left->info->ivlist[i].value.ul - np->left->info->last_ivlist[j].value.ul;
			    break;
			case PM_TYPE_64:
			    np->info->ivlist[k].value.ll = np->left->info->ivlist[i].value.ll - np->left->info->last_ivlist[j].value.ll;
			    break;
			case PM_TYPE_U64:
			    np->info->ivlist[k].value.ull = np->left->info->ivlist[i].value.ull - np->left->info->last_ivlist[j].value.ull;
			    break;
			case PM_TYPE_FLOAT:
			    np->info->ivlist[k].value.f = np->left->info->ivlist[i].value.f - np->left->info->last_ivlist[j].value.f;
			    break;
			case PM_TYPE_DOUBLE:
			    np->info->ivlist[k].value.d = np->left->info->ivlist[i].value.d - np->left->info->last_ivlist[j].value.d;
			    break;
			default:
			    /*
			     * Nothing should end up here as check_expr() checks
			     * for numeric data type at bind time
			     */
			    return PM_ERR_CONV;
		    }
		}
		else {
		    /* rate() conversion, type will be DOUBLE */
		    struct timeval	stampdiff;
		    stampdiff = np->info->stamp;
		    __pmtimevalDec(&stampdiff, &np->info->last_stamp);
		    switch (np->left->desc.type) {
			case PM_TYPE_32:
			    np->info->ivlist[k].value.d = (double)(np->left->info->ivlist[i].value.l - np->left->info->last_ivlist[j].value.l);
			    break;
			case PM_TYPE_U32:
			    np->info->ivlist[k].value.d = (double)(np->left->info->ivlist[i].value.ul - np->left->info->last_ivlist[j].value.ul);
			    break;
			case PM_TYPE_64:
			    np->info->ivlist[k].value.d = (double)(np->left->info->ivlist[i].value.ll - np->left->info->last_ivlist[j].value.ll);
			    break;
			case PM_TYPE_U64:
			    np->info->ivlist[k].value.d = (double)(np->left->info->ivlist[i].value.ull - np->left->info->last_ivlist[j].value.ull);
			    break;
			case PM_TYPE_FLOAT:
			    np->info->ivlist[k].value.d = (double)(np->left->info->ivlist[i].value.f - np->left->info->last_ivlist[j].value.f);
			    break;
			case PM_TYPE_DOUBLE:
			    np->info->ivlist[k].value.d = np->left->info->ivlist[i].value.d - np->left->info->last_ivlist[j].value.d;
			    break;
			default:
			    /*
			     * Nothing should end up here as check_expr() checks
			     * for numeric data type at bind time
			     */
			    return PM_ERR_CONV;
		    }
		    np->info->ivlist[k].value.d /= __pmtimevalToReal(&stampdiff);
		    /*
		     * check_expr() ensures dimTime is 0 or 1 at bind time
		     */
		    if (np->left->desc.units.dimTime == 1) {
			/* scale rate(time counter) -> time utilization */
			if (np->info->time_scale < 0) {
			    /*
			     * one trip initialization for time utilization
			     * scaling factor (to scale metric from counter
			     * units into seconds)
			     */
			    int		i;
			    np->info->time_scale = 1;
			    if (np->left->desc.units.scaleTime > PM_TIME_SEC) {

				for (i = PM_TIME_SEC; i < np->left->desc.units.scaleTime; i++)

				    np->info->time_scale *= 60;
			    }
			    else {
				for (i = np->left->desc.units.scaleTime; i < PM_TIME_SEC; i++)
				    np->info->time_scale /= 1000;
			    }
			}
			np->info->ivlist[k].value.d *= np->info->time_scale;
		    }
		}
		k++;
	    }
	    np->info->numval = k;
	    return np->info->numval;
	    break;

	case L_INSTANT:
	    /*
	     * values are in the left expr
	     */
	    np->info->last_stamp = np->info->stamp;
	    np->info->stamp = rp->timestamp;
	    np->info->numval = np->left->info->numval;
	    if (np->info->numval > 0)
		np->info->ivlist = np->left->info->ivlist;
	    return np->info->numval;
	    break;

	case L_AVG:
	case L_COUNT:
	case L_SUM:
	case L_MAX:
	case L_MIN:
	    if (np->info->ivlist == NULL) {
		/* initialize ivlist[] for singular instance first time through */
		if ((np->info->ivlist = (val_t *)malloc(sizeof(val_t))) == NULL) {
		    __pmNoMem("eval_expr: aggr ivlist", sizeof(val_t), PM_FATAL_ERR);
		    /*NOTREACHED*/
		}
		np->info->ivlist[0].inst = PM_IN_NULL;
	    }
	    /*
	     * values are in the left expr
	     */
	    if (np->type == L_COUNT) {
		np->info->numval = 1;
		np->info->ivlist[0].value.l = np->left->info->numval;
	    }
	    else {
		np->info->numval = 1;
		if (np->type == L_AVG)
		    np->info->ivlist[0].value.f = 0;
		else if (np->type == L_SUM) {
		    switch (np->desc.type) {
			case PM_TYPE_32:
			    np->info->ivlist[0].value.l = 0;
			    break;
			case PM_TYPE_U32:
			    np->info->ivlist[0].value.ul = 0;
			    break;
			case PM_TYPE_64:
			    np->info->ivlist[0].value.ll = 0;
			    break;
			case PM_TYPE_U64:
			    np->info->ivlist[0].value.ull = 0;
			    break;
			case PM_TYPE_FLOAT:
			    np->info->ivlist[0].value.f = 0;
			    break;
			case PM_TYPE_DOUBLE:
			    np->info->ivlist[0].value.d = 0;
			    break;
		    }
		}
		for (i = 0; i < np->left->info->numval; i++) {
		    switch (np->type) {

			case L_AVG:
			    switch (np->left->desc.type) {
				case PM_TYPE_32:
				    np->info->ivlist[0].value.f += (float)np->left->info->ivlist[i].value.l / np->left->info->numval;
				    break;
				case PM_TYPE_U32:
				    np->info->ivlist[0].value.f += (float)np->left->info->ivlist[i].value.ul / np->left->info->numval;
				    break;
				case PM_TYPE_64:
				    np->info->ivlist[0].value.f += (float)np->left->info->ivlist[i].value.ll / np->left->info->numval;
				    break;
				case PM_TYPE_U64:
				    np->info->ivlist[0].value.f += (float)np->left->info->ivlist[i].value.ull / np->left->info->numval;
				    break;
				case PM_TYPE_FLOAT:
				    np->info->ivlist[0].value.f += (float)np->left->info->ivlist[i].value.f / np->left->info->numval;
				    break;
				case PM_TYPE_DOUBLE:
				    np->info->ivlist[0].value.f += (float)np->left->info->ivlist[i].value.d / np->left->info->numval;
				    break;
				default:
				    /*
				     * check_expr() checks for numeric data
				     * type at bind time ... if here, botch!
				     */
				    return PM_ERR_CONV;
			    }
			    break;

			case L_MAX:
			    switch (np->desc.type) {
				case PM_TYPE_32:
				    if (i == 0 ||
				        np->info->ivlist[0].value.l < np->left->info->ivlist[i].value.l)
					np->info->ivlist[0].value.l = np->left->info->ivlist[i].value.l;
				    break;
				case PM_TYPE_U32:
				    if (i == 0 ||
				        np->info->ivlist[0].value.ul < np->left->info->ivlist[i].value.ul)
					np->info->ivlist[0].value.ul = np->left->info->ivlist[i].value.ul;
				    break;
				case PM_TYPE_64:
				    if (i == 0 ||
				        np->info->ivlist[0].value.ll < np->left->info->ivlist[i].value.ll)
					np->info->ivlist[0].value.ll = np->left->info->ivlist[i].value.ll;
				    break;
				case PM_TYPE_U64:
				    if (i == 0 ||
				        np->info->ivlist[0].value.ull < np->left->info->ivlist[i].value.ull)
					np->info->ivlist[0].value.ull = np->left->info->ivlist[i].value.ull;
				    break;
				case PM_TYPE_FLOAT:
				    if (i == 0 ||
				        np->info->ivlist[0].value.f < np->left->info->ivlist[i].value.f)
					np->info->ivlist[0].value.f = np->left->info->ivlist[i].value.f;
				    break;
				case PM_TYPE_DOUBLE:
				    if (i == 0 ||
				        np->info->ivlist[0].value.d < np->left->info->ivlist[i].value.d)
					np->info->ivlist[0].value.d = np->left->info->ivlist[i].value.d;
				    break;
				default:
				    /*
				     * check_expr() checks for numeric data
				     * type at bind time ... if here, botch!
				     */
				    return PM_ERR_CONV;
			    }
			    break;

			case L_MIN:
			    switch (np->desc.type) {
				case PM_TYPE_32:
				    if (i == 0 ||
				        np->info->ivlist[0].value.l > np->left->info->ivlist[i].value.l)
					np->info->ivlist[0].value.l = np->left->info->ivlist[i].value.l;
				    break;
				case PM_TYPE_U32:
				    if (i == 0 ||
				        np->info->ivlist[0].value.ul > np->left->info->ivlist[i].value.ul)
					np->info->ivlist[0].value.ul = np->left->info->ivlist[i].value.ul;
				    break;
				case PM_TYPE_64:
				    if (i == 0 ||
				        np->info->ivlist[0].value.ll > np->left->info->ivlist[i].value.ll)
					np->info->ivlist[0].value.ll = np->left->info->ivlist[i].value.ll;
				    break;
				case PM_TYPE_U64:
				    if (i == 0 ||
				        np->info->ivlist[0].value.ull > np->left->info->ivlist[i].value.ull)
					np->info->ivlist[0].value.ull = np->left->info->ivlist[i].value.ull;
				    break;
				case PM_TYPE_FLOAT:
				    if (i == 0 ||
				        np->info->ivlist[0].value.f > np->left->info->ivlist[i].value.f)
					np->info->ivlist[0].value.f = np->left->info->ivlist[i].value.f;
				    break;
				case PM_TYPE_DOUBLE:
				    if (i == 0 ||
				        np->info->ivlist[0].value.d > np->left->info->ivlist[i].value.d)
					np->info->ivlist[0].value.d = np->left->info->ivlist[i].value.d;
				    break;
				default:
				    /*
				     * check_expr() checks for numeric data
				     * type at bind time ... if here, botch!
				     */
				    return PM_ERR_CONV;
			    }
			    break;

			case L_SUM:
			    switch (np->desc.type) {
				case PM_TYPE_32:
				    np->info->ivlist[0].value.l += np->left->info->ivlist[i].value.l;
				    break;
				case PM_TYPE_U32:
				    np->info->ivlist[0].value.ul += np->left->info->ivlist[i].value.ul;
				    break;
				case PM_TYPE_64:
				    np->info->ivlist[0].value.ll += np->left->info->ivlist[i].value.ll;
				    break;
				case PM_TYPE_U64:
				    np->info->ivlist[0].value.ull += np->left->info->ivlist[i].value.ull;
				    break;
				case PM_TYPE_FLOAT:
				    np->info->ivlist[0].value.f += np->left->info->ivlist[i].value.f;
				    break;
				case PM_TYPE_DOUBLE:
				    np->info->ivlist[0].value.d += np->left->info->ivlist[i].value.d;
				    break;
				default:
				    /*
				     * check_expr() checks for numeric data
				     * type at bind time ... if here, botch!
				     */
				    return PM_ERR_CONV;
			    }
			    break;

		    }
		}
	    }
	    return np->info->numval;
	    break;

	case L_NAME:
	    /*
	     * Extract instance-values from pmResult and store them in
	     * ivlist[] as <int, pmAtomValue> pairs
	     */
	    for (j = 0; j < rp->numpmid; j++) {
		if (np->info->pmid == rp->vset[j]->pmid) {
		    free_ivlist(np);
		    np->info->numval = rp->vset[j]->numval;
		    if (np->info->numval <= 0)
			return np->info->numval;
		    if ((np->info->ivlist = (val_t *)malloc(np->info->numval*sizeof(val_t))) == NULL) {
			__pmNoMem("eval_expr: metric ivlist", np->info->numval*sizeof(val_t), PM_FATAL_ERR);
			/*NOTREACHED*/
		    }
		    for (i = 0; i < np->info->numval; i++) {
			np->info->ivlist[i].inst = rp->vset[j]->vlist[i].inst;
			switch (np->desc.type) {
			    case PM_TYPE_32:
			    case PM_TYPE_U32:
				np->info->ivlist[i].value.l = rp->vset[j]->vlist[i].value.lval;
				break;

			    case PM_TYPE_64:
			    case PM_TYPE_U64:
				memcpy((void *)&np->info->ivlist[i].value.ll, (void *)rp->vset[j]->vlist[i].value.pval->vbuf, sizeof(__int64_t));
				break;

			    case PM_TYPE_FLOAT:
				if (rp->vset[j]->valfmt == PM_VAL_INSITU) {
				    /* old style insitu float */
				    np->info->ivlist[i].value.l = rp->vset[j]->vlist[i].value.lval;
				}
				else {
				    assert(rp->vset[j]->vlist[i].value.pval->vtype == PM_TYPE_FLOAT);
				    memcpy((void *)&np->info->ivlist[i].value.f, (void *)rp->vset[j]->vlist[i].value.pval->vbuf, sizeof(float));
				}
				break;

			    case PM_TYPE_DOUBLE:
				memcpy((void *)&np->info->ivlist[i].value.d, (void *)rp->vset[j]->vlist[i].value.pval->vbuf, sizeof(double));
				break;

			    case PM_TYPE_STRING:
				need = rp->vset[j]->vlist[i].value.pval->vlen-PM_VAL_HDR_SIZE;
				if ((np->info->ivlist[i].value.cp = (char *)malloc(need)) == NULL) {
				    __pmNoMem("eval_expr: string value", rp->vset[j]->vlist[i].value.pval->vlen, PM_FATAL_ERR);
				    /*NOTREACHED*/
				}
				memcpy((void *)np->info->ivlist[i].value.cp, (void *)rp->vset[j]->vlist[i].value.pval->vbuf, need);
				np->info->ivlist[i].vlen = need;
				break;

			    case PM_TYPE_AGGREGATE:
			    case PM_TYPE_AGGREGATE_STATIC:
			    case PM_TYPE_EVENT:
			    case PM_TYPE_HIGHRES_EVENT:
				if ((np->info->ivlist[i].value.vbp = (pmValueBlock *)malloc(rp->vset[j]->vlist[i].value.pval->vlen)) == NULL) {
				    __pmNoMem("eval_expr: aggregate value", rp->vset[j]->vlist[i].value.pval->vlen, PM_FATAL_ERR);
				    /*NOTREACHED*/
				}
				memcpy(np->info->ivlist[i].value.vbp, (void *)rp->vset[j]->vlist[i].value.pval, rp->vset[j]->vlist[i].value.pval->vlen);
				np->info->ivlist[i].vlen = rp->vset[j]->vlist[i].value.pval->vlen;
				break;

			    default:
				/*
				 * really only PM_TYPE_NOSUPPORT should
				 * end up here
				 */
				return PM_ERR_TYPE;
			}
		    }
		    return np->info->numval;
		}
	    }
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_DERIVE) {
		char	strbuf[20];
		fprintf(stderr, "eval_expr: botch: operand %s not in the extended pmResult\n", pmIDStr_r(np->info->pmid, strbuf, sizeof(strbuf)));
		__pmDumpResult(stderr, rp);
	    }
#endif
	    return PM_ERR_PMID;

	case L_ANON:
	    /* no values available for anonymous metrics */
	    return 0;

	default:
	    /*
	     * binary operator cases ... always have a left and right
	     * operand and no errors (these are caught earlier when the
	     * recursive call on each of the operands would may have
	     * returned an error
	     */
	    assert(np->left != NULL);
	    assert(np->right != NULL);

	    free_ivlist(np);
	    /*
	     * empty result cases first
	     */
	    if (np->left->info->numval == 0) {
		np->info->numval = 0;
		return np->info->numval;
	    }
	    if (np->right->info->numval == 0) {
		np->info->numval = 0;
		return np->info->numval;
	    }
	    /*
	     * really got some work to do ...
	     */
	    if (np->left->desc.indom == PM_INDOM_NULL)
		np->info->numval = np->right->info->numval;
	    else if (np->right->desc.indom == PM_INDOM_NULL)
		np->info->numval = np->left->info->numval;
	    else {
		/*
		 * Generally have the same number of instances because
		 * both operands are over the same instance domain,
		 * fetched with the same profile.  When not the case,
		 * the result can contain no more instances than in
		 * the smaller of the operands.
		 */
		if (np->left->info->numval <= np->right->info->numval)
		    np->info->numval = np->left->info->numval;
		else
		    np->info->numval = np->right->info->numval;
	    }
	    if ((np->info->ivlist = (val_t *)malloc(np->info->numval*sizeof(val_t))) == NULL) {
		__pmNoMem("eval_expr: expr ivlist", np->info->numval*sizeof(val_t), PM_FATAL_ERR);
		/*NOTREACHED*/
	    }
	    /*
	     * ivlist[k] = left-ivlist[i] <op> right-ivlist[j]
	     */
	    for (i = j = k = 0; k < np->info->numval; ) {
		if (i >= np->left->info->numval || j >= np->right->info->numval) {
		    /* run out of operand instances, quit */
		    np->info->numval = k;
		    break;
		}
		if (np->left->desc.indom != PM_INDOM_NULL &&
		    np->right->desc.indom != PM_INDOM_NULL) {
		    if (np->left->info->ivlist[i].inst != np->right->info->ivlist[j].inst) {
			/* left ith inst != right jth inst ... search in right */
#ifdef PCP_DEBUG
			if ((pmDebug & DBG_TRACE_DERIVE) && (pmDebug & DBG_TRACE_APPL2)) {
			    fprintf(stderr, "eval_expr: inst[%d] mismatch left [%d]=%d right [%d]=%d\n", k, i, np->left->info->ivlist[i].inst, j, np->right->info->ivlist[j].inst);
			}
#endif
			for (j = 0; j < np->right->info->numval; j++) {
			    if (np->left->info->ivlist[i].inst == np->right->info->ivlist[j].inst)
				break;
			}
			if (j == np->right->info->numval) {
			    /*
			     * no match, so next instance on left operand,
			     * and reset to start from first instance of
			     * right operand
			     */
			    i++;
			    j = 0;
			    continue;
			}
#ifdef PCP_DEBUG
			else {
			    if ((pmDebug & DBG_TRACE_DERIVE) && (pmDebug & DBG_TRACE_APPL2)) {
				fprintf(stderr, "eval_expr: recover @ right [%d]=%d\n", j, np->right->info->ivlist[j].inst);
			    }
			}
#endif
		    }
		}
		np->info->ivlist[k].value =
		    bin_op(np->desc.type, np->type,
			   np->left->info->ivlist[i].value, np->left->desc.type, np->left->info->mul_scale, np->left->info->div_scale,
			   np->right->info->ivlist[j].value, np->right->desc.type, np->right->info->mul_scale, np->right->info->div_scale);
		if (np->left->desc.indom != PM_INDOM_NULL)
		    np->info->ivlist[k].inst = np->left->info->ivlist[i].inst;
		else
		    np->info->ivlist[k].inst = np->right->info->ivlist[j].inst;
		k++;
		if (np->left->desc.indom != PM_INDOM_NULL) {
		    i++;
		    if (np->right->desc.indom != PM_INDOM_NULL) {
			j++;
			if (j >= np->right->info->numval) {
			    /* rescan if need be */
			    j = 0;
			}
		    }
		}
		else if (np->right->desc.indom != PM_INDOM_NULL) {
		    j++;
		}
	    }
	    return np->info->numval;
    }
    /*NOTREACHED*/
}
예제 #13
0
/*
 * Algorithm here is complicated by trying to re-write the pmResult.
 *
 * On entry the pmResult is likely to be built over a pinned PDU buffer,
 * which means individual pmValueSets cannot be selectively replaced
 * (this would come to tears badly in pmFreeResult() where as soon as
 * one pmValueSet is found to be in a pinned PDU buffer it is assumed
 * they are all so ... leaving a memory leak for any ones we'd modified
 * here).
 *
 * So the only option is to COPY the pmResult, selectively replacing
 * the pmValueSets for the derived metrics, and then calling
 * pmFreeResult() to free the input structure and return the new one.
 *
 * In making the COPY it is critical that we reverse the algorithm
 * used in pmFreeResult() so that a later call to pmFreeResult() will
 * not cause a memory leak.
 * This means ...
 * - malloc() the pmResult (padded out to the right number of vset[]
 *   entries)
 * - if valfmt is not PM_VAL_INSITU use PM_VAL_DPTR (not PM_VAL_SPTR),
 *   so anything we point to is going to be released when our caller
 *   calls pmFreeResult()
 * - use one malloc() for each pmValueSet with vlist[] sized to be 0
 *   if numval < 0 else numval
 * - pmValueBlocks are from malloc()
 *
 * For reference, the same logic appears in __pmLogFetchInterp() to
 * sythesize a pmResult there.
 */
void
__dmpostfetch(__pmContext *ctxp, pmResult **result)
{
    int		i;
    int		j;
    int		m;
    int		numval;
    int		valfmt;
    size_t	need;
    int		rewrite;
    ctl_t	*cp = (ctl_t *)ctxp->c_dm;
    pmResult	*rp = *result;
    pmResult	*newrp;

    /* if needed, init() called in __dmopencontext beforehand */

    if (cp == NULL || cp->fetch_has_dm == 0) return;

    newrp = (pmResult *)malloc(sizeof(pmResult)+(cp->numpmid-1)*sizeof(pmValueSet *));
    if (newrp == NULL) {
	__pmNoMem("__dmpostfetch: newrp", sizeof(pmResult)+(cp->numpmid-1)*sizeof(pmValueSet *), PM_FATAL_ERR);
	/*NOTREACHED*/
    }
    newrp->timestamp = rp->timestamp;
    newrp->numpmid = cp->numpmid;

    for (j = 0; j < newrp->numpmid; j++) {
	numval = rp->vset[j]->numval;
	valfmt = rp->vset[j]->valfmt;
	rewrite = 0;
	/*
	 * pandering to gcc ... m is not used unless rewrite == 1 in
	 * which case m is well-defined
	 */
	m = 0;
	if (IS_DERIVED(rp->vset[j]->pmid)) {
	    for (m = 0; m < cp->nmetric; m++) {
		if (rp->vset[j]->pmid == cp->mlist[m].pmid) {
		    if (cp->mlist[m].expr == NULL) {
			numval = PM_ERR_PMID;
		    }
		    else {
			rewrite = 1;
			if (cp->mlist[m].expr->desc.type == PM_TYPE_32 ||
			    cp->mlist[m].expr->desc.type == PM_TYPE_U32)
			    valfmt = PM_VAL_INSITU;
			else
			    valfmt = PM_VAL_DPTR;
			numval = eval_expr(cp->mlist[m].expr, rp, 1);
#ifdef PCP_DEBUG
    if ((pmDebug & DBG_TRACE_DERIVE) && (pmDebug & DBG_TRACE_APPL2)) {
	int	k;
	char	strbuf[20];

	fprintf(stderr, "__dmpostfetch: [%d] root node %s: numval=%d", j, pmIDStr_r(rp->vset[j]->pmid, strbuf, sizeof(strbuf)), numval);
	for (k = 0; k < numval; k++) {
	    fprintf(stderr, " vset[%d]: inst=%d", k, cp->mlist[m].expr->info->ivlist[k].inst);
	    if (cp->mlist[m].expr->desc.type == PM_TYPE_32)
		fprintf(stderr, " l=%d", cp->mlist[m].expr->info->ivlist[k].value.l);
	    else if (cp->mlist[m].expr->desc.type == PM_TYPE_U32)
		fprintf(stderr, " u=%u", cp->mlist[m].expr->info->ivlist[k].value.ul);
	    else if (cp->mlist[m].expr->desc.type == PM_TYPE_64)
		fprintf(stderr, " ll=%"PRIi64, cp->mlist[m].expr->info->ivlist[k].value.ll);
	    else if (cp->mlist[m].expr->desc.type == PM_TYPE_U64)
		fprintf(stderr, " ul=%"PRIu64, cp->mlist[m].expr->info->ivlist[k].value.ull);
	    else if (cp->mlist[m].expr->desc.type == PM_TYPE_FLOAT)
		fprintf(stderr, " f=%f", (double)cp->mlist[m].expr->info->ivlist[k].value.f);
	    else if (cp->mlist[m].expr->desc.type == PM_TYPE_DOUBLE)
		fprintf(stderr, " d=%f", cp->mlist[m].expr->info->ivlist[k].value.d);
	    else if (cp->mlist[m].expr->desc.type == PM_TYPE_STRING) {
		fprintf(stderr, " cp=%s (len=%d)", cp->mlist[m].expr->info->ivlist[k].value.cp, cp->mlist[m].expr->info->ivlist[k].vlen);
	    }
	    else {
		fprintf(stderr, " vbp=" PRINTF_P_PFX "%p (len=%d)", cp->mlist[m].expr->info->ivlist[k].value.vbp, cp->mlist[m].expr->info->ivlist[k].vlen);
	    }
	}
	fputc('\n', stderr);
	if (cp->mlist[m].expr->info != NULL)
	    __dmdumpexpr(cp->mlist[m].expr, 1);
    }
#endif
		    }
		    break;
		}
	    }
	}

	if (numval <= 0) {
	    /* only need pmid and numval */
	    need = sizeof(pmValueSet) - sizeof(pmValue);
	}
	else {
	    /* already one pmValue in a pmValueSet */
	    need = sizeof(pmValueSet) + (numval - 1)*sizeof(pmValue);
	}
	if (need > 0) {
	    if ((newrp->vset[j] = (pmValueSet *)malloc(need)) == NULL) {
		__pmNoMem("__dmpostfetch: vset", need, PM_FATAL_ERR);
		/*NOTREACHED*/
	    }
	}
	newrp->vset[j]->pmid = rp->vset[j]->pmid;
	newrp->vset[j]->numval = numval;
	newrp->vset[j]->valfmt = valfmt;
	if (numval < 0)
	    continue;

	for (i = 0; i < numval; i++) {
	    pmValueBlock	*vp;

	    if (!rewrite) {
		newrp->vset[j]->vlist[i].inst = rp->vset[j]->vlist[i].inst;
		if (newrp->vset[j]->valfmt == PM_VAL_INSITU) {
		    newrp->vset[j]->vlist[i].value.lval = rp->vset[j]->vlist[i].value.lval;
		}
		else {
		    need = rp->vset[j]->vlist[i].value.pval->vlen;
		    vp = (pmValueBlock *)malloc(need);
		    if (vp == NULL) {
			__pmNoMem("__dmpostfetch: copy value", need, PM_FATAL_ERR);
			/*NOTREACHED*/
		    }
		    memcpy((void *)vp, (void *)rp->vset[j]->vlist[i].value.pval, need);
		    newrp->vset[j]->vlist[i].value.pval = vp;
		}
		continue;
	    }

	    /*
	     * the rewrite case ...
	     */
	    newrp->vset[j]->vlist[i].inst = cp->mlist[m].expr->info->ivlist[i].inst;
	    switch (cp->mlist[m].expr->desc.type) {
		case PM_TYPE_32:
		case PM_TYPE_U32:
		    newrp->vset[j]->vlist[i].value.lval = cp->mlist[m].expr->info->ivlist[i].value.l;
		    break;

		case PM_TYPE_64:
		case PM_TYPE_U64:
		    need = PM_VAL_HDR_SIZE + sizeof(__int64_t);
		    if ((vp = (pmValueBlock *)malloc(need)) == NULL) {
			__pmNoMem("__dmpostfetch: 64-bit int value", need, PM_FATAL_ERR);
			/*NOTREACHED*/
		    }
		    vp->vlen = need;
		    vp->vtype = cp->mlist[m].expr->desc.type;
		    memcpy((void *)vp->vbuf, (void *)&cp->mlist[m].expr->info->ivlist[i].value.ll, sizeof(__int64_t));
		    newrp->vset[j]->vlist[i].value.pval = vp;
		    break;

		case PM_TYPE_FLOAT:
		    need = PM_VAL_HDR_SIZE + sizeof(float);
		    if ((vp = (pmValueBlock *)malloc(need)) == NULL) {
			__pmNoMem("__dmpostfetch: float value", need, PM_FATAL_ERR);
			/*NOTREACHED*/
		    }
		    vp->vlen = need;
		    vp->vtype = PM_TYPE_FLOAT;
		    memcpy((void *)vp->vbuf, (void *)&cp->mlist[m].expr->info->ivlist[i].value.f, sizeof(float));
		    newrp->vset[j]->vlist[i].value.pval = vp;
		    break;

		case PM_TYPE_DOUBLE:
		    need = PM_VAL_HDR_SIZE + sizeof(double);
		    if ((vp = (pmValueBlock *)malloc(need)) == NULL) {
			__pmNoMem("__dmpostfetch: double value", need, PM_FATAL_ERR);
			/*NOTREACHED*/
		    }
		    vp->vlen = need;
		    vp->vtype = PM_TYPE_DOUBLE;
		    memcpy((void *)vp->vbuf, (void *)&cp->mlist[m].expr->info->ivlist[i].value.f, sizeof(double));
		    newrp->vset[j]->vlist[i].value.pval = vp;
		    break;

		case PM_TYPE_STRING:
		    need = PM_VAL_HDR_SIZE + cp->mlist[m].expr->info->ivlist[i].vlen;
		    vp = (pmValueBlock *)malloc(need);
		    if (vp == NULL) {
			__pmNoMem("__dmpostfetch: string value", need, PM_FATAL_ERR);
			/*NOTREACHED*/
		    }
		    vp->vlen = need;
		    vp->vtype = cp->mlist[m].expr->desc.type;
		    memcpy((void *)vp->vbuf, cp->mlist[m].expr->info->ivlist[i].value.cp, cp->mlist[m].expr->info->ivlist[i].vlen);
		    newrp->vset[j]->vlist[i].value.pval = vp;
		    break;

		case PM_TYPE_AGGREGATE:
		case PM_TYPE_AGGREGATE_STATIC:
		case PM_TYPE_EVENT:
		case PM_TYPE_HIGHRES_EVENT:
		    need = cp->mlist[m].expr->info->ivlist[i].vlen;
		    vp = (pmValueBlock *)malloc(need);
		    if (vp == NULL) {
			__pmNoMem("__dmpostfetch: aggregate or event value", need, PM_FATAL_ERR);
			/*NOTREACHED*/
		    }
		    memcpy((void *)vp, cp->mlist[m].expr->info->ivlist[i].value.vbp, cp->mlist[m].expr->info->ivlist[i].vlen);
		    newrp->vset[j]->vlist[i].value.pval = vp;
		    break;

		default:
		    /*
		     * really nothing should end up here ...
		     * do nothing as numval should have been < 0
		     */
#ifdef PCP_DEBUG
		    if (pmDebug & DBG_TRACE_DERIVE) {
			char	strbuf[20];
			fprintf(stderr, "__dmpostfetch: botch: drived metric[%d]: operand %s has odd type (%d)\n", m, pmIDStr_r(rp->vset[j]->pmid, strbuf, sizeof(strbuf)), cp->mlist[m].expr->desc.type);
		    }
#endif
		    break;
	    }
	}
    }

    /*
     * cull the original pmResult and return the rewritten one
     */
    pmFreeResult(rp);
    *result = newrp;

    return;
}