Example #1
0
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;
}
Example #2
0
File: spec.c Project: goodwinos/pcp
int
__pmUnparseHostAttrsSpec(
    pmHostSpec *hosts,
    int count,
    __pmHashCtl *attrs,
    char *string,
    size_t size)
{
    __pmHashNode *node;
    int off = 0, len = size;	/* offset in string and space remaining */
    int sts, first;

    if ((node = __pmHashSearch(PCP_ATTR_PROTOCOL, attrs)) != NULL) {
	if ((sts = pmsprintf(string, len, "%s://", (char *)node->data)) >= len)
	    return -E2BIG;
	len -= sts; off += sts;
    }
    else if (__pmHashSearch(PCP_ATTR_UNIXSOCK, attrs) != NULL) {
	if ((sts = pmsprintf(string, len, "unix:/")) >= len)
	    return -E2BIG;
	len -= sts; off += sts;
    }
    else if (__pmHashSearch(PCP_ATTR_LOCAL, attrs) != NULL) {
	if ((sts = pmsprintf(string, len, "local:/")) >= len)
	    return -E2BIG;
	len -= sts; off += sts;
    }

    if ((sts = unparseHostSpec(hosts, count, string + off, len, 0)) >= len)
	return sts;
    len -= sts; off += sts;

    first = 1;
    for (node = __pmHashWalk(attrs, PM_HASH_WALK_START);
	 node != NULL;
	 node = __pmHashWalk(attrs, PM_HASH_WALK_NEXT)) {
	if (node->key == PCP_ATTR_PROTOCOL ||
	    node->key == PCP_ATTR_UNIXSOCK || node->key == PCP_ATTR_LOCAL)
	    continue;
	if ((sts = pmsprintf(string + off, len, "%c", first ? '?' : '&')) >= len)
	    return -E2BIG;
	len -= sts; off += sts;
	first = 0;

	if ((sts = unparseAttribute(node, string + off, len)) >= len)
	    return -E2BIG;
	len -= sts; off += sts;
    }

    return off;
}
Example #3
0
File: dopdu.c Project: aeppert/pcp
					/* logging (or is mandatory if no indom) */
static int
find_metric(pmID pmid)
{
    __pmHashNode	*hp;
    optreq_t	*rqp;
    int		result = 0;
    int		found = 0;

    for (hp = __pmHashSearch(pmid, &pm_hash); hp != NULL; hp = hp->next) {
	if (pmid != (pmID)hp->key)
	    continue;
	rqp = (optreq_t *)hp->data;
	if (found++ == 0)
	    if (rqp->r_desc->indom != PM_INDOM_NULL) {
		result |= MF_HAS_INDOM;
		if (rqp->r_numinst == 0)
		    result |= MF_HAS_ALL;
		else
		    result |= MF_HAS_INST;
	    }
	if (PMLC_GET_MAND(((task_t *)(rqp->r_fetch->f_aux))->t_state))
	    result |= MF_HAS_MAND;
    }
    return found ? result : -1;
}
Example #4
0
File: libpcp.c Project: Aconex/pcp
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;
}
Example #5
0
File: client.c Project: Aconex/pcp
int
CheckAccountAccess(ClientInfo *cp)
{
    __pmHashNode *node;
    const char *userid;
    const char *groupid;

    userid = ((node = __pmHashSearch(PCP_ATTR_USERID, &cp->attrs)) ?
		(const char *)node->data : NULL);
    groupid = ((node = __pmHashSearch(PCP_ATTR_GROUPID, &cp->attrs)) ?
		(const char *)node->data : NULL);
    if (!userid || !groupid)
	if (__pmServerHasFeature(PM_SERVER_FEATURE_CREDS_REQD))
	    return PM_ERR_PERMISSION;
    return __pmAccAddAccount(userid, groupid, &cp->denyOps);
}
Example #6
0
File: dopdu.c Project: aeppert/pcp
/* Return a mask containing the history flags for a given metric/instance.
 * the history flags indicate whether the metric/instance is in the log at all
 * and whether the last fetch of the metric/instance was successful.
 *
 * The result is suitable for ORing into the result returned by a control log
 * request.
 */
static int
gethistflags(pmID pmid, int inst)
{
    __pmHashNode	*hp;
    pmidhist_t		*php;
    insthist_t		*ihp;
    int			i, found;
    int			val;

    for (hp = __pmHashSearch(pmid, &hist_hash); hp != NULL; hp = hp->next)
	if ((pmID)hp->key == pmid)
	    break;
    if (hp == NULL)
	return 0;
    php = (pmidhist_t *)hp->data;
    ihp = &php->ph_instlist[0];
    val = 0;
    if (php->ph_indom != PM_INDOM_NULL) {
	for (i = 0; i < php->ph_numinst; i++, ihp++)
	    if (ihp->ih_inst == inst)
		break;
	found = i < php->ph_numinst;
    }
    else
	found = php->ph_numinst > 0;
    if (found) {
	PMLC_SET_INLOG(val, 1);
	val |= ihp->ih_flags;		/* only "available flag" is ever set */
    }
    return val;
}
Example #7
0
int
__pmSecureServerHandshake(int fd, int flags, __pmHashCtl *attrs)
{
    int sts, ssf = DEFAULT_SECURITY_STRENGTH;

    /* protect from unsupported requests from future/oddball clients */
    if (flags & ~(PDU_FLAG_SECURE | PDU_FLAG_SECURE_ACK | PDU_FLAG_COMPRESS |
		  PDU_FLAG_AUTH | PDU_FLAG_CREDS_REQD | PDU_FLAG_CONTAINER |
		  PDU_FLAG_CERT_REQD))
	return PM_ERR_IPC;

    if (flags & PDU_FLAG_CREDS_REQD) {
	if (__pmHashSearch(PCP_ATTR_USERID, attrs) != NULL)
	    return 0;	/* unix domain socket */
	else
	    flags |= PDU_FLAG_AUTH;	/* force authentication */
    }

    if ((sts = __pmSecureServerIPCFlags(fd, flags)) < 0)
	return sts;
    if (((flags & PDU_FLAG_SECURE) != 0) &&
	((sts = __pmSecureServerNegotiation(fd, &ssf)) < 0))
	return sts;
    if (((flags & PDU_FLAG_AUTH) != 0) &&
	((sts = __pmAuthServerNegotiation(fd, ssf, attrs)) < 0))
	return sts;
    return 0;
}
Example #8
0
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);
}
Example #9
0
static pmdaMetric *
__pmdaHashedSearch(pmID pmid, __pmHashCtl *hash)
{
    __pmHashNode *node;

    if ((node = __pmHashSearch(pmid, hash)) == NULL)
	return NULL;
    return (pmdaMetric *)node->data;
}
Example #10
0
File: dopdu.c Project: aeppert/pcp
/* Delete every instance of a given metric from the data structure.
 * The pmid is deleted from the pmidlist of every task containing an instance.
 * Return a pointer to the first pmDesc found (the only thing salvaged from the
 * smoking ruins), or nil if no instances were found.
 */
static pmDesc *
del_insts(pmID pmid)
{
    optreq_t	*rqp;
    __pmHashNode	*hp;
    task_t	*tp;
    pmDesc	*dp = NULL;
    int		i, sts, keep;

    for (hp = __pmHashSearch(pmid, &pm_hash); hp != NULL; ) {
	/* Do that BEFORE we nuke the node */
    	__pmHashNode * nextnode = hp->next;

	if (pmid == (pmID)hp->key) {
	    rqp = (optreq_t *)hp->data;
	    tp = (task_t *)rqp->r_fetch->f_aux;
	    if ((sts = __pmOptFetchDel(&tp->t_fetch, rqp)) < 0)
		die("del_insts: __pmOptFetchDel", sts);
	    if ((sts = __pmHashDel(pmid, (void *)rqp, &pm_hash)) < 0)
		die("del_insts: __pmHashDel", sts);

	    /* save the first pmDesc pointer for return and subsequent
	     *  re-use, but free all the others
	     */
	    if (dp != NULL)
		free(rqp->r_desc);
	    else
		dp = rqp->r_desc;

	    if (rqp->r_numinst)
		free(rqp->r_instlist);
	    free(rqp);

	    /* remove pmid from the task's pmid list */
	    for (i = 0; i < tp->t_numpmid; i++)
		if (tp->t_pmidlist[i] == pmid)
		    break;
	    keep = (tp->t_numpmid - 1 - i) * sizeof(tp->t_pmidlist[0]);
	    if (keep) {
		memmove(&tp->t_pmidlist[i], &tp->t_pmidlist[i+1], keep);
		memmove(&tp->t_desclist[i], &tp->t_desclist[i+1], keep);
		memmove(&tp->t_namelist[i], &tp->t_namelist[i+1], keep);
	    }

	    /* don't bother shrinking the pmidlist */
	    tp->t_numpmid--;
	    if (tp->t_numpmid == 0) {
		/* TODO: nuke the task if that was the last pmID */
	    }
	}
	hp = nextnode;
    }

    return dp;
}
Example #11
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);
    }
}
Example #12
0
int
CheckAccountAccess(ClientInfo *cp)
{
    __pmHashNode *node;
    const char *userid;
    const char *groupid;

    userid = ((node = __pmHashSearch(PCP_ATTR_USERID, &cp->attrs)) ?
              (const char *)node->data : NULL);
    groupid = ((node = __pmHashSearch(PCP_ATTR_GROUPID, &cp->attrs)) ?
               (const char *)node->data : NULL);
#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_AUTH)
        fprintf(stderr, "CheckAccountAccess: client fd=%d userid=%s groupid=%s\n", cp->fd, userid, groupid);
#endif
    if (!userid || !groupid)
        if (__pmServerHasFeature(PM_SERVER_FEATURE_CREDS_REQD))
            return PM_ERR_PERMISSION;
    return __pmAccAddAccount(userid, groupid, &cp->denyOps);
}
Example #13
0
File: dopdu.c Project: aeppert/pcp
/* This crawls over the data structure looking for weirdness */
void
reality_check(void)
{
    __pmHashNode		*hp;
    task_t		*tp;
    task_t		*tp2;
    fetchctl_t		*fp;
    optreq_t		*rqp;
    pmID		pmid;
    int			i = 0, j, k;

    /* check that all fetch_t's f_aux point back to their parent task */
    for (tp = tasklist; tp != NULL; tp = tp->t_next, i++) {
	if (tp->t_fetch == NULL)
	    fprintf(stderr, "task[%d] @" PRINTF_P_PFX "%p has no fetch group\n", i, tp);
	j = 0;
	for (fp = tp->t_fetch; fp != NULL; fp = fp->f_next) {
	    if (fp->f_aux != (void *)tp)
		fprintf(stderr, "task[%d] fetch group[%d] has invalid task pointer\n",
			i, j);
	    j++;
	}

	/* check that all optreq_t's in hash list have valid r_fetch->f_aux
	 * pointing to a task in the task list.
	 */
	for (j = 0; j < tp->t_numpmid; j++) {
	    pmid = tp->t_pmidlist[j];
	    for (hp = __pmHashSearch(pmid, &pm_hash); hp != NULL; hp = hp->next) {
		if (pmid != (pmID)hp->key)
		continue;
		rqp = (optreq_t *)hp->data;
		for (tp2 = tasklist; tp2 != NULL; tp2 = tp2->t_next)
		    if (rqp->r_fetch->f_aux == (void *)tp2)
			break;
		if (tp2 == NULL) {
		    fprintf(stderr, "task[%d] pmid %s optreq " PRINTF_P_PFX "%p for [",
			    i, pmIDStr(pmid), rqp);
		    if (rqp->r_numinst == 0)
			fputs("`all instances' ", stderr);
		    else
			for (k = 0; k < rqp->r_numinst; k++)
			    fprintf(stderr, "%d ", rqp->r_instlist[k]);
		    fputs("] bad task pointer\n", stderr);
		}
	    }
	}
    }
}
Example #14
0
int
__pmSecureServerHandshake(int fd, int flags, __pmHashCtl *attrs)
{
    (void)fd;

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_AUTH)
	fprintf(stderr, "%s:__pmSecureServerHandshake: flags=%d: ", __FILE__, flags);
#endif

    /* for things that require a secure server, return -EOPNOTSUPP */
    if ((flags & (PDU_FLAG_SECURE | PDU_FLAG_SECURE_ACK | PDU_FLAG_COMPRESS
		   | PDU_FLAG_AUTH)) != 0) {
#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_AUTH)
	    fprintf(stderr, "not allowed\n");
#endif
	return -EOPNOTSUPP;
    }

    /*
     * CREDS_REQD is a special case that does not need a secure server
     * provided we've connected on a unix domain socket
     */
    if ((flags & PDU_FLAG_CREDS_REQD) != 0 && __pmHashSearch(PCP_ATTR_USERID, attrs) != NULL) {
#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_AUTH)
	    fprintf(stderr, "ok\n");
#endif
	return 0;
    }
    /* remove all of the known good flags */
    flags &= ~(PDU_FLAG_SECURE | PDU_FLAG_SECURE_ACK | PDU_FLAG_COMPRESS |
	       PDU_FLAG_AUTH | PDU_FLAG_CREDS_REQD | PDU_FLAG_CONTAINER);
    if (!flags)
	return 0;

    /* any remaining flags are unexpected */
#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_AUTH)
	fprintf(stderr, "bad\n");
#endif
    return PM_ERR_IPC;
}
Example #15
0
File: dopdu.c Project: aeppert/pcp
optreq_t *
findoptreq(pmID pmid, int inst)
{
    __pmHashNode	*hp;
    optreq_t	*rqp;
    optreq_t	*all_rqp = NULL;
    int		j;

    /*
     * Note:
     * The logic here assumes that for each metric-inst pair, there is
     * at most one optreq_t structure, corresponding to the logging
     * state of ON (mandatory or advisory) else OFF (mandatory).  Other
     * requests change the data structures, but do not leave optreq_t
     * structures lying about, i.e. MAYBE (mandatory) is the default,
     * and does not have to be explicitly stored, while OFF (advisory)
     * reverts to MAYBE (mandatory).
     * There is one exception to the above assumption, namely for
     * cases where the initial specification includes "all" instances,
     * then some later concurrent specification may refer to specific
     * instances ... in this case, the specific optreq_t structure is
     * the one that applies.
     */
    
    for (hp = __pmHashSearch(pmid, &pm_hash); hp != NULL; hp = hp->next) {
	if (pmid != (pmID)hp->key)
	    continue;
	rqp = (optreq_t *)hp->data;
	if (rqp->r_numinst == 0) {
	    all_rqp = rqp;
	    continue;
	}
	for (j = 0; j < rqp->r_numinst; j++)
	    if (inst == rqp->r_instlist[j])
		return rqp;
    }

    if (all_rqp != NULL)
	return all_rqp;
    else
	return NULL;
}
Example #16
0
File: dopdu.c Project: aeppert/pcp
/* Given a task and a pmID, find an optreq_t associated with the task suitable
 * for inserting a new instance into.
 * The one with the smallest number of instances is chosen.  We could also
 * have just used the first, but smallest-first gives a more even distribution.
 */
static optreq_t *
find_instoptreq(task_t *tp, pmID pmid)
{
    optreq_t	*result = NULL;
    optreq_t	*rqp;
    int		ni = 0;
    __pmHashNode	*hp;

    for (hp = __pmHashSearch(pmid, &pm_hash); hp != NULL;
	 hp = hp->next) {
	if (pmid != (pmID)hp->key)
	    continue;
	rqp = (optreq_t *)hp->data;
	if ((task_t *)rqp->r_fetch->f_aux != tp)
	    continue;
	if (rqp->r_numinst == 0)
	    continue;			/* don't want "all instances" cases */
	if (ni == 0 || rqp->r_numinst < ni) {
	    result = rqp;
	    ni = rqp->r_numinst;
	}
    }
    return result;
}
Example #17
0
File: pass3.c Project: aeppert/pcp
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;
	    }
	}
    }
}
Example #18
0
File: dopdu.c Project: aeppert/pcp
/* create a pmValueSet large enough to contain the union of the current
 * instance domain of the specified metric and any previous instances from
 * the history list.
 */
static pmValueSet *
build_vset(pmID pmid, int usehist)
{
    __pmHashNode		*hp;
    pmidhist_t		*php = NULL;
    insthist_t		*ihp;
    int			need = 0;
    int			i, numindom = 0;
    pmDesc		desc;
    int			have_desc;
    int			*instlist = NULL;
    char		**namelist = NULL;
    pmValueSet		*vsp;

   if (usehist) {
	/* find the number of instances of the metric in the history (1 if
	 * single-valued metric)
	 */
	for (hp = __pmHashSearch(pmid, &hist_hash); hp != NULL; hp = hp->next)
	    if ((pmID)hp->key == pmid)
		break;
	if (hp != NULL) {
	    php = (pmidhist_t *)hp->data;
	    need = php->ph_numinst;
	}
    }
    /*
     * get the current instance domain, so that if the metric hasn't been
     * logged yet a sensible result is returned.
     */
    if ((have_desc = pmLookupDesc(pmid, &desc)) < 0)
	goto no_info;
    if (desc.indom == PM_INDOM_NULL)
	need = 1;			/* will be same in history */
    else {
	int	j;
	    
	if ((numindom = pmGetInDom(desc.indom, &instlist, &namelist)) < 0) {
	    have_desc = numindom;
	    goto no_info;
	}
	/* php will be null if usehist is false or there is no history yet */
	if (php == NULL)
	    need = numindom;		/* no history => use indom */
	else
	    for (i = 0; i < numindom; i++) {
		int	inst = instlist[i];
		
		for (j = 0; j < php->ph_numinst; j++)
		    if (inst == php->ph_instlist[j].ih_inst)
			break;
		/*
		 * if instance is in history but not instance domain, leave
		 * extra space for it in vset, otherwise use the USEINDOM
		 * flag to avoid another NxM comparison when building the vset
		 * instances later.
		 */
		if (j >= php->ph_numinst)
		    need++;
		else
		    PMLC_SET_USEINDOM(php->ph_instlist[j].ih_flags, 1);
	    }
    }

no_info:

    need = sizeof(pmValueSet) + (need - 1) * sizeof(pmValue);
    vsp = (pmValueSet *)malloc(need);
    if (vsp == NULL) {
	__pmNoMem("build_vset for control/enquire", need, PM_FATAL_ERR);
    }
    vsp->pmid = pmid;
    if (have_desc < 0) {
	vsp->numval = have_desc;
    }
    else if (desc.indom == PM_INDOM_NULL) {
	vsp->vlist[0].inst = PM_IN_NULL;
	vsp->numval = 1;
    }
    else {
	int	j;
	
	i = 0;
	/* get instances out of instance domain first */
	if (numindom > 0)
	    for (j = 0; j < numindom; j++)
		vsp->vlist[i++].inst = instlist[j];

	/* then any not in instance domain from history */
	if (php != NULL) {
	    ihp = &php->ph_instlist[0];
	    for (j = 0; j < php->ph_numinst; j++, ihp++)
		if (PMLC_GET_USEINDOM(ihp->ih_flags))
		    /* it's already in the indom */
		    PMLC_SET_USEINDOM(ihp->ih_flags, 0);
		else
		    vsp->vlist[i++].inst = ihp->ih_inst;
	}
	vsp->numval = i;
    }
    if (instlist)
	free(instlist);
    if (namelist)
	free(namelist);
    
    return vsp;
}
Example #19
0
File: dopdu.c Project: aeppert/pcp
/* 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;
}