Exemplo n.º 1
0
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)));
    }
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
Arquivo: check.c Projeto: 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);
    }
}