Пример #1
0
static int
__pmSetUserGroupAttributes(const char *username, __pmHashCtl *attrs)
{
    char name[32];
    char *namep;
    uid_t uid;
    gid_t gid;

    if (__pmGetUserIdentity(username, &uid, &gid, PM_RECOV_ERR) == 0) {
	pmsprintf(name, sizeof(name), "%u", uid);
	name[sizeof(name)-1] = '\0';
	if ((namep = strdup(name)) != NULL)
	    __pmHashAdd(PCP_ATTR_USERID, namep, attrs);
	else
	    return -ENOMEM;

	pmsprintf(name, sizeof(name), "%u", gid);
	name[sizeof(name)-1] = '\0';
	if ((namep = strdup(name)) != NULL)
	    __pmHashAdd(PCP_ATTR_GROUPID, namep, attrs);
	else
	    return -ENOMEM;
	return 0;
    }
    pmNotifyErr(LOG_ERR, "Authenticated user %s not found\n", username);
    return -ESRCH;
}
Пример #2
0
static int
SetCredentialAttrs(__pmHashCtl *attrs, unsigned int pid, unsigned int uid, unsigned int gid)
{
    char name[32], *namep;

    snprintf(name, sizeof(name), "%u", uid);
    name[sizeof(name)-1] = '\0';
    if ((namep = strdup(name)) != NULL)
        __pmHashAdd(PCP_ATTR_USERID, namep, attrs);

    snprintf(name, sizeof(name), "%u", gid);
    name[sizeof(name)-1] = '\0';
    if ((namep = strdup(name)) != NULL)
        __pmHashAdd(PCP_ATTR_GROUPID, namep, attrs);

    if (!pid)	/* not available on all platforms */
	return 0;

    snprintf(name, sizeof(name), "%u", pid);
    name[sizeof(name)-1] = '\0';
    if ((namep = strdup(name)) != NULL)
        __pmHashAdd(PCP_ATTR_PROCESSID, namep, attrs);

    return 0;
}
Пример #3
0
int
main(int argc, char **argv)
{
    __pmHashCtl hc = { 0 };

    printf("adding entries\n");
    __pmHashAdd(0, (void *)0L, &hc);
    __pmHashAdd(1, (void *)1L, &hc);
    __pmHashAdd(2, (void *)2L, &hc);
    __pmHashAdd(3, (void *)3L, &hc);

    if (argc >= 2) {
        if (strcmp(argv[1], "callback") == 0)
            __pmHashWalkCB(walker, (void *)PM_HASH_WALK_NEXT, &hc);
        else if (strcmp(argv[1], "linked") == 0)
            chained(&hc);
        exit(0);
    }

    printf("iterating WALK_STOP\n");
    __pmHashWalkCB(walker, (void *)PM_HASH_WALK_STOP, &hc);
    printf("iterating WALK_NEXT\n");
    __pmHashWalkCB(walker, (void *)PM_HASH_WALK_NEXT, &hc);
    printf("iterating WALK_DELETE_STOP\n");
    __pmHashWalkCB(walker, (void *)PM_HASH_WALK_DELETE_STOP, &hc);
    printf("iterating WALK_NEXT\n");
    __pmHashWalkCB(walker, (void *)PM_HASH_WALK_NEXT, &hc);
    printf("iterating WALK_DELETE_NEXT\n");
    __pmHashWalkCB(walker, (void *)PM_HASH_WALK_DELETE_NEXT, &hc);
    printf("iterating WALK_NEXT\n");
    __pmHashWalkCB(walker, (void *)PM_HASH_WALK_NEXT, &hc);

    exit(0);
}
Пример #4
0
/*
 * Parse the attributes component of a PCP connection string.
 * Optionally, an initial attribute:value pair can be passed
 * in as well to add to the parsed set.
 */
static int
parseAttributeSpec(
    const char *spec,           /* the original, complete string to parse */
    char **position,            /* parse from here onward and update at end */
    int attribute,
    char *value,
    __pmHashCtl *attributes,
    char **errmsg)
{
    char *s, *start, *v = NULL;
    char buffer[32];	/* must be large enough to hold largest attr name */
    int buflen, attr, len, sts;

    if (attribute != PCP_ATTR_NONE)
	if ((sts = __pmHashAdd(attribute, (void *)value, attributes)) < 0)
	    return sts;

    for (s = start = *position; s != NULL; s++) {
	/* parse: foo=bar&moo&goo=blah ... go! */
	if (*s == '\0' || *s == '/' || *s == '&') {
	    if ((*s == '\0' || *s == '/') && s == start)
		break;
	    len = v ? (v - start - 1) : (s - start);
	    buflen = (len < sizeof(buffer)-1) ? len : sizeof(buffer)-1;
	    strncpy(buffer, start, buflen);
	    buffer[buflen] = '\0';
	    attr = __pmLookupAttrKey(buffer, buflen+1);
	    if (attr != PCP_ATTR_NONE) {
		char *val = NULL;

		if (v && (val = strndup(v, s - v)) == NULL) {
		    sts = -ENOMEM;
		    goto fail;
		}
		if ((sts = __pmHashAdd(attr, (void *)val, attributes)) < 0) {
		    free(val);
		    goto fail;
		}
	    }
	    v = NULL;
	    if (*s == '\0' || *s == '/')
		break;
	    start = s + 1;	/* start of attribute name */
	    continue;
	}
	if (*s == '=') {
	   v = s + 1;	/* start of attribute value */
	}
    }

    *position = s;
    return 0;

fail:
    if (attribute != PCP_ATTR_NONE)	/* avoid double free in caller */
	__pmHashDel(attribute, (void *)value, attributes);
    __pmFreeAttrsSpec(attributes);
    return sts;
}
Пример #5
0
static int
__pmAuthServerSetAttributes(sasl_conn_t *conn, __pmHashCtl *attrs)
{
    const void *property = NULL;
    char *username;
    int sts;

    sts = sasl_getprop(conn, SASL_USERNAME, &property);
    username = (char *)property;
    if (sts == SASL_OK && username) {
	int len = strlen(username);

	pmNotifyErr(LOG_INFO,
			"Successful authentication for user \"%s\"\n",
			username);
	if ((username = strdup(username)) == NULL) {
	    pmNoMem("__pmAuthServerSetAttributes",
			len, PM_RECOV_ERR);
	    return -ENOMEM;
	}
    } else {
	pmNotifyErr(LOG_ERR,
			"Authentication complete, but no username\n");
	return -ESRCH;
    }

    if ((sts = __pmHashAdd(PCP_ATTR_USERNAME, username, attrs)) < 0)
	return sts;
    return __pmSetUserGroupAttributes(username, attrs);
}
Пример #6
0
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;
}
Пример #7
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);
}
Пример #8
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;
}
Пример #9
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);
    }
}
Пример #10
0
static int
build_dsoattrs(pmdaInterface *dispatch, __pmHashCtl *attrs)
{
    __pmHashNode *node;
    char name[32];
    char *namep;
    int sts = 0;

#ifdef HAVE_GETUID
    snprintf(name, sizeof(name), "%u", getuid());
    name[sizeof(name)-1] = '\0';
    if ((namep = strdup(name)) != NULL)
	__pmHashAdd(PCP_ATTR_USERID, namep, attrs);
#endif

#ifdef HAVE_GETGID
    snprintf(name, sizeof(name), "%u", getgid());
    name[sizeof(name)-1] = '\0';
    if ((namep = strdup(name)) != NULL)
	__pmHashAdd(PCP_ATTR_GROUPID, namep, attrs);
#endif

    snprintf(name, sizeof(name), "%u", getpid());
    name[sizeof(name)-1] = '\0';
    if ((namep = strdup(name)) != NULL)
	__pmHashAdd(PCP_ATTR_PROCESSID, namep, attrs);

    if (dispatch->version.six.attribute != NULL) {
	for (node = __pmHashWalk(attrs, PM_HASH_WALK_START);
	     node != NULL;
	     node = __pmHashWalk(attrs, PM_HASH_WALK_NEXT)) {
	    if ((sts = dispatch->version.six.attribute(
				0, node->key, node->data,
				node->data ? strlen(node->data)+1 : 0,
				dispatch->version.six.ext)) < 0)
		break;
	}
    }
    return sts;
}
Пример #11
0
static int
ctxlocal(__pmHashCtl *attrs)
{
    int sts;
    char *name = NULL;
    char *container = NULL;

    if ((container = getenv("PCP_CONTAINER")) != NULL) {
	if ((name = strdup(container)) == NULL)
	    return -ENOMEM;
	if ((sts = __pmHashAdd(PCP_ATTR_CONTAINER, (void *)name, attrs)) < 0) {
	    free(name);
	    return sts;
	}
    }
    return 0;
}
Пример #12
0
/*
 * load _all_ of the hashed pmDesc and __pmLogInDom structures from the metadata
 * log file -- used at the initialization (NewContext) of an archive
 * If version 2 then
 * load all the names from the meta data and create l_pmns.
 */
int
__pmLogLoadMeta(__pmLogCtl *lcp)
{
    int		rlen;
    int		check;
    pmDesc	*dp;
    int		sts = 0;
    __pmLogHdr	h;
    FILE	*f = lcp->l_mdfp;
    int         version2 = ((lcp->l_label.ill_magic & 0xff) == PM_LOG_VERS02);
    int		numpmid = 0;
    int		n;
    
    if (version2) {
       if ((sts = __pmNewPMNS(&(lcp->l_pmns))) < 0) {
          goto end;
       }
    }

    fseek(f, (long)(sizeof(__pmLogLabel) + 2*sizeof(int)), SEEK_SET);
    for ( ; ; ) {
	n = (int)fread(&h, 1, sizeof(__pmLogHdr), f);

	/* swab hdr */
	h.len = ntohl(h.len);
	h.type = ntohl(h.type);

	if (n != sizeof(__pmLogHdr) || h.len <= 0) {
            if (feof(f)) {
		clearerr(f);
                sts = 0;
		goto end;
            }
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_LOGMETA) {
		fprintf(stderr, "__pmLogLoadMeta: header read -> %d: expected: %d\n",
			n, (int)sizeof(__pmLogHdr));
	    }
#endif
	    if (ferror(f)) {
		clearerr(f);
		sts = -errno;
	    }
	    else
		sts = PM_ERR_LOGREC;
	    goto end;
	}
#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_LOGMETA) {
	    fprintf(stderr, "__pmLogLoadMeta: record len=%d, type=%d @ offset=%d\n",
		h.len, h.type, (int)(ftell(f) - sizeof(__pmLogHdr)));
	}
#endif
	rlen = h.len - (int)sizeof(__pmLogHdr) - (int)sizeof(int);
	if (h.type == TYPE_DESC) {
            numpmid++;
	    if ((dp = (pmDesc *)malloc(sizeof(pmDesc))) == NULL) {
		sts = -errno;
		goto end;
	    }
	    if ((n = (int)fread(dp, 1, sizeof(pmDesc), f)) != sizeof(pmDesc)) {
#ifdef PCP_DEBUG
		if (pmDebug & DBG_TRACE_LOGMETA) {
		    fprintf(stderr, "__pmLogLoadMeta: pmDesc read -> %d: expected: %d\n",
			    n, (int)sizeof(pmDesc));
		}
#endif
		if (ferror(f)) {
		    clearerr(f);
		    sts = -errno;
		}
		else
		    sts = PM_ERR_LOGREC;
		goto end;
	    }
	    else {
		/* swab desc */
		dp->type = ntohl(dp->type);
		dp->sem = ntohl(dp->sem);
		dp->indom = __ntohpmInDom(dp->indom);
		dp->units = __ntohpmUnits(dp->units);
		dp->pmid = __ntohpmID(dp->pmid);
	    }

	    if ((sts = __pmHashAdd((int)dp->pmid, (void *)dp, &lcp->l_hashpmid)) < 0)
		goto end;

            if (version2) {
                char name[MAXPATHLEN];
                int numnames;
		int i;
		int len;

                /* read in the names & store in PMNS tree ... */
		if ((n = (int)fread(&numnames, 1, sizeof(numnames), f)) != 
                     sizeof(numnames)) {
#ifdef PCP_DEBUG
		    if (pmDebug & DBG_TRACE_LOGMETA) {
			fprintf(stderr, "__pmLogLoadMeta: numnames read -> %d: expected: %d\n",
				n, (int)sizeof(numnames));
		    }
#endif
		    if (ferror(f)) {
			clearerr(f);
			sts = -errno;
		    }
		    else
			sts = PM_ERR_LOGREC;
		    goto end;
		}
		else {
		    /* swab numnames */
		    numnames = ntohl(numnames);
		}

 		for (i = 0; i < numnames; i++) {
		    if ((n = (int)fread(&len, 1, sizeof(len), f)) != 
			 sizeof(len)) {
#ifdef PCP_DEBUG
			if (pmDebug & DBG_TRACE_LOGMETA) {
			    fprintf(stderr, "__pmLogLoadMeta: len name[%d] read -> %d: expected: %d\n",
				    i, n, (int)sizeof(len));
			}
#endif
			if (ferror(f)) {
			    clearerr(f);
			    sts = -errno;
			}
			else
			    sts = PM_ERR_LOGREC;
			goto end;
		    }
		    else {
			/* swab len */
			len = ntohl(len);
		    }

		    if ((n = (int)fread(name, 1, len, f)) != len) {
#ifdef PCP_DEBUG
			if (pmDebug & DBG_TRACE_LOGMETA) {
			    fprintf(stderr, "__pmLogLoadMeta: name[%d] read -> %d: expected: %d\n",
				    i, n, len);
			}
#endif
			if (ferror(f)) {
			    clearerr(f);
			    sts = -errno;
			}
			else
			    sts = PM_ERR_LOGREC;
			goto end;
		    }
                    name[len] = '\0';
#ifdef PCP_DEBUG
		    if (pmDebug & DBG_TRACE_LOGMETA) {
			fprintf(stderr, "__pmLogLoadMeta: PMID: %s name: %s\n",
				pmIDStr(dp->pmid), name);
		    }
#endif

                    if ((sts = __pmAddPMNSNode(lcp->l_pmns, dp->pmid, name)) < 0) {
			/*
			 * If we see a duplicate PMID, its a recoverable error.
			 * We wont be able to see all of the data in the log, but
			 * its better to provide access to some rather than none,
			 * esp. when only one or two metric IDs may be corrupted
			 * in this way (which we may not be interested in anyway).
			 */
			if (sts != PM_ERR_PMID)
			    goto end;
			sts = 0;
		    } 
		}/*for*/
            }/*version2*/
	}
	else if (h.type == TYPE_INDOM) {
	    int			*tbuf;
	    pmInDom		indom;
	    __pmTimeval		*when;
	    int			numinst;
	    int			*instlist;
	    char		**namelist;
	    char		*namebase;
	    int			*stridx;
	    int			i;
	    int			k;
	    int			allinbuf;

	    if ((tbuf = (int *)malloc(rlen)) == NULL) {
		sts = -errno;
		goto end;
	    }
	    if ((n = (int)fread(tbuf, 1, rlen, f)) != rlen) {
#ifdef PCP_DEBUG
		if (pmDebug & DBG_TRACE_LOGMETA) {
		    fprintf(stderr, "__pmLogLoadMeta: indom read -> %d: expected: %d\n",
			    n, rlen);
		}
#endif
		if (ferror(f)) {
		    clearerr(f);
		    sts = -errno;
		}
		else
		    sts = PM_ERR_LOGREC;
		goto end;
	    }

	    k = 0;
	    when = (__pmTimeval *)&tbuf[k];
	    when->tv_sec = ntohl(when->tv_sec);
	    when->tv_usec = ntohl(when->tv_usec);
	    k += sizeof(*when)/sizeof(int);
	    indom = __ntohpmInDom((unsigned int)tbuf[k++]);
	    numinst = ntohl(tbuf[k++]);
	    if (numinst > 0) {
		instlist = &tbuf[k];
		k += numinst;
		stridx = &tbuf[k];
#if defined(HAVE_32BIT_PTR)
		namelist = (char **)stridx;
		allinbuf = 1; /* allocation is all in tbuf */
#else
		allinbuf = 0; /* allocation for namelist + tbuf */
		/* need to allocate to hold the pointers */
		namelist = (char **)malloc(numinst*sizeof(char*));
		if (namelist == NULL) {
		    sts = -errno;
		    goto end;
		}
#endif
		k += numinst;
		namebase = (char *)&tbuf[k];
	        for (i = 0; i < numinst; i++) {
		    instlist[i] = ntohl(instlist[i]);
	            namelist[i] = &namebase[ntohl(stridx[i])];
		}
	    }
	    else {
		/* no instances, or an error */
		instlist = NULL;
		namelist = NULL;
	    }
	    if ((sts = addindom(lcp, indom, when, numinst, instlist, namelist, tbuf, allinbuf)) < 0)
		goto end;
	}
	else
	    fseek(f, (long)rlen, SEEK_CUR);
	n = (int)fread(&check, 1, sizeof(check), f);
	check = ntohl(check);
	if (n != sizeof(check) || h.len != check) {
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_LOGMETA) {
		fprintf(stderr, "__pmLogLoadMeta: trailer read -> %d or len=%d: expected %d @ offset=%d\n",
		    n, check, h.len, (int)(ftell(f) - sizeof(check)));
	    }
#endif
	    if (ferror(f)) {
		clearerr(f);
		sts = -errno;
	    }
	    else
		sts = PM_ERR_LOGREC;
	    goto end;
	}
    }/*for*/
end:
    
    fseek(f, (long)(sizeof(__pmLogLabel) + 2*sizeof(int)), SEEK_SET);

    if (version2 && sts == 0) {
        __pmFixPMNSHashTab(lcp->l_pmns, numpmid, 1);
    }
    return sts;
}
Пример #13
0
/* 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;
}
Пример #14
0
/* Add a new metric (given a pmValueSet and a pmDesc) to the specified task.
 * Allocate and return a new task_t if the specified task pointer is nil.
 *
 * Note that this should only be called for metrics not currently in the
 * logging data structure.  All instances in the pmValueSet are added!
 */
static int
add_metric(pmValueSet *vsp, task_t **result)
{
    pmID	pmid = vsp->pmid;
    task_t	*tp = *result;
    optreq_t	*rqp;
    pmDesc	*dp;
    char	*name;
    int		sts, i, need = 0;

    dp = (pmDesc *)malloc(sizeof(pmDesc));
    if (dp == NULL) {
	__pmNoMem("add_metric: new pmDesc malloc", sizeof(pmDesc), PM_FATAL_ERR);
    }
    if ((sts = pmLookupDesc(pmid, dp)) < 0)
	die("add_metric: lookup desc", sts);
    if ((sts = pmNameID(pmid, &name)) < 0)
	die("add_metric: lookup name", sts);

    /* allocate a new task if null task pointer passed in */
    if (tp == NULL) {
	tp = calloc(1, sizeof(task_t));
	if (tp == NULL) {
	    __pmNoMem("add_metric: new task calloc", sizeof(task_t), PM_FATAL_ERR);
	}
	*result = tp;
    }

    /* add metric (and any instances specified) to task */
    i = tp->t_numpmid++;
    need = tp->t_numpmid * sizeof(pmID);
    if (!(tp->t_pmidlist = (pmID *)realloc(tp->t_pmidlist, need)))
	__pmNoMem("add_metric: new task pmidlist realloc", need, PM_FATAL_ERR);
    need = tp->t_numpmid * sizeof(char *);
    if (!(tp->t_namelist = (char **)realloc(tp->t_namelist, need)))
	__pmNoMem("add_metric: new task namelist realloc", need, PM_FATAL_ERR);
    need = tp->t_numpmid * sizeof(pmDesc);
    if (!(tp->t_desclist = (pmDesc *)realloc(tp->t_desclist, need)))
	__pmNoMem("add_metric: new task desclist realloc", need, PM_FATAL_ERR);
    tp->t_pmidlist[i] = pmid;
    tp->t_namelist[i] = name;
    tp->t_desclist[i] = *dp;	/* struct assignment */

    rqp = (optreq_t *)calloc(1, sizeof(optreq_t));
    if (rqp == NULL) {
	__pmNoMem("add_metric: new task optreq calloc", need, PM_FATAL_ERR);
    }
    rqp->r_desc = dp;

    /* Now copy instances if required.  Remember that metrics with singular
     * values actually have one instance specified to distinguish them from the
     * "all instances" case (which has no instances).  Use the pmDesc to check
     * for this.
     */
    if (dp->indom != PM_INDOM_NULL)
	need = rqp->r_numinst = vsp->numval;
    if (need) {
	need *= sizeof(rqp->r_instlist[0]);
	rqp->r_instlist = (int *)malloc(need);
	if (rqp->r_instlist == NULL) {
	    __pmNoMem("add_metric: new task optreq instlist malloc", need,
		     PM_FATAL_ERR);
	}
	for (i = 0; i < vsp->numval; i++)
	    rqp->r_instlist[i] = vsp->vlist[i].inst;
    }

    /* Add new metric to task's fetchgroup(s) and global hash table */
    __pmOptFetchAdd(&tp->t_fetch, rqp);
    linkback(tp);
    if ((sts = __pmHashAdd(pmid, (void *)rqp, &pm_hash)) < 0)
	die("add_metric: __pmHashAdd", sts);
    return 0;
}
Пример #15
0
static void
docheck(pmResult *result)
{
    int			i, j, k;
    int			sts;
    pmDesc		desc;
    pmAtomValue 	av;
    pmValue		*vp;
    pmValueSet		*vsp;
    __pmHashNode	*hptr = NULL;
    checkData		*checkdata = NULL;
    double		diff;
    struct timeval	timediff;

    for (i = 0; i < result->numpmid; i++) {
	vsp = result->vset[i];

#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_APPL1) {
	    if (vsp->numval == 0) {
		fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol);
		print_stamp(stderr, &result->timestamp);
		fprintf(stderr, "] ");
		print_metric(stderr, vsp->pmid);
		fprintf(stderr, ": no values returned\n");
		continue;
	    }
	    else if (vsp->numval < 0) {
		fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol);
		print_stamp(stderr, &result->timestamp);
		fprintf(stderr, "] ");
		print_metric(stderr, vsp->pmid);
		fprintf(stderr, ": error from numval: %s\n", pmErrStr(vsp->numval));
		continue;
	    }
	}
#endif
	if (vsp->numval <= 0)
	    continue;

	/* check if pmid already in hash list */
	if ((hptr = __pmHashSearch(vsp->pmid, &hashlist)) == NULL) {
	    if ((sts = pmLookupDesc(vsp->pmid, &desc)) < 0) {
		fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol);
		print_stamp(stderr, &result->timestamp);
		fprintf(stderr, "] ");
		print_metric(stderr, vsp->pmid);
		fprintf(stderr, ": pmLookupDesc failed: %s\n", pmErrStr(sts));
		continue;
	    }

	    if (desc.type != PM_TYPE_32 && desc.type != PM_TYPE_U32 &&
		desc.type != PM_TYPE_64 && desc.type != PM_TYPE_U64 &&
		desc.type != PM_TYPE_FLOAT && desc.type != PM_TYPE_DOUBLE) {
		continue;	/* no checks for non-numeric metrics */
	    }

	    /* create a new one & add to list */
	    checkdata = (checkData*) malloc(sizeof(checkData));
	    newHashItem(vsp, &desc, checkdata, &result->timestamp);
	    if (__pmHashAdd(checkdata->desc.pmid, (void*)checkdata, &hashlist) < 0) {
		fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol);
		print_stamp(stderr, &result->timestamp);
		fprintf(stderr, "] ");
		print_metric(stderr, vsp->pmid);
		fprintf(stderr, ": __pmHashAdd failed (internal pmlogcheck error)\n");
		/* free memory allocated above on insert failure */
		for (j = 0; j < vsp->numval; j++) {
		    if (checkdata->instlist[j] != NULL)
			free(checkdata->instlist[j]);
		}
		if (checkdata->instlist != NULL)
		    free(checkdata->instlist);
		continue;
	    }
	}
	else {	/* pmid exists - update statistics */
	    checkdata = (checkData *)hptr->data;
	    for (j = 0; j < vsp->numval; j++) {	/* iterate thro result values */
		vp = &vsp->vlist[j];
		k = j;	/* index into stored inst list, result may differ */
		if ((vsp->numval > 1) || (checkdata->desc.indom != PM_INDOM_NULL)) {
		    /* must store values using correct inst - probably in correct order already */
		    if ((k < checkdata->listsize) && (checkdata->instlist[k]->inst != vp->inst)) {
			for (k = 0; k < checkdata->listsize; k++) {
			    if (vp->inst == checkdata->instlist[k]->inst) {
				break;	/* k now correct */
			    }
			}
			if (k == checkdata->listsize) {	/* no matching inst was found */
			    newHashInst(vp, checkdata, vsp->valfmt, &result->timestamp, k);
			    continue;
			}
		    }
		    else if (k >= checkdata->listsize) {
			k = checkdata->listsize;
			newHashInst(vp, checkdata, vsp->valfmt, &result->timestamp, k);
			continue;
		    }
		}
		if (k >= checkdata->listsize) {	/* only error values observed so far */
		    k = checkdata->listsize;
		    newHashInst(vp, checkdata, vsp->valfmt, &result->timestamp, k);
		    continue;
		}

		timediff = result->timestamp;
		tsub(&timediff, &(checkdata->instlist[k]->lasttime));
		if (timediff.tv_sec < 0) {
		    /* clip negative values at zero */
		    timediff.tv_sec = 0;
		    timediff.tv_usec = 0;
		}
		diff = __pmtimevalToReal(&timediff);
		if ((sts = pmExtractValue(vsp->valfmt, vp, checkdata->desc.type, &av, PM_TYPE_DOUBLE)) < 0) {
		    fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol);
		    print_stamp(stderr, &result->timestamp);
		    fprintf(stderr, "] ");
		    print_metric(stderr, vsp->pmid);
		    fprintf(stderr, ": pmExtractValue failed: %s\n", pmErrStr(sts));
		    continue;
		}
		if (checkdata->desc.sem == PM_SEM_COUNTER) {
		    if (diff == 0.0) continue;
		    diff *= checkdata->scale;
#ifdef PCP_DEBUG
		    if (pmDebug & DBG_TRACE_APPL2) {
			fprintf(stderr, "%s.%d:[", l_archname, l_ctxp->c_archctl->ac_vol);
			print_stamp(stderr, &result->timestamp);
			fprintf(stderr, "] ");
			print_metric(stderr, checkdata->desc.pmid);
			fprintf(stderr, ": current counter value is %.0f\n", av.d);
		    }
#endif
		    unwrap(av.d, &(result->timestamp), checkdata, k);
		}
		checkdata->instlist[k]->lastval = av.d;
		checkdata->instlist[k]->lasttime = result->timestamp;
	    }
	}
    }
}