Example #1
0
static void
__pmInitContextLock(pthread_mutex_t *lock)
{
    pthread_mutexattr_t	attr;
    int			sts;
    char		errmsg[PM_MAXERRMSGLEN];

    /*
     * Need context lock to be recursive as we sometimes call
     * __pmHandleToPtr() while the current context is already
     * locked
     */
    if ((sts = pthread_mutexattr_init(&attr)) != 0) {
	pmErrStr_r(-sts, errmsg, sizeof(errmsg));
	fprintf(stderr, "pmNewContext: "
		"context=%d lock pthread_mutexattr_init failed: %s",
		contexts_len-1, errmsg);
	exit(4);
    }
    if ((sts = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) != 0) {
	pmErrStr_r(-sts, errmsg, sizeof(errmsg));
	fprintf(stderr, "pmNewContext: "
		"context=%d lock pthread_mutexattr_settype failed: %s",
		contexts_len-1, errmsg);
	exit(4);
    }
    if ((sts = pthread_mutex_init(lock, &attr)) != 0) {
	pmErrStr_r(-sts, errmsg, sizeof(errmsg));
	fprintf(stderr, "pmNewContext: "
		"context=%d lock pthread_mutex_init failed: %s",
		contexts_len-1, errmsg);
	exit(4);
    }
}
Example #2
0
File: connect.c Project: tongfw/pcp
static int
negotiate_proxy(int fd, const char *hostname, int port)
{
    char	buf[MY_BUFLEN];
    char	*bp;
    int		ok = 0;

    /*
     * version negotiation (converse to pmproxy logic)
     *   __pmSend my client version message
     *   __pmRecv server version message
     *   __pmSend hostname and port
     */

    if (__pmSend(fd, MY_VERSION, strlen(MY_VERSION), 0) != strlen(MY_VERSION)) {
	char	errmsg[PM_MAXERRMSGLEN];
	__pmNotifyErr(LOG_WARNING,
	     "__pmConnectPMCD: send version string to pmproxy failed: %s\n",
	    pmErrStr_r(-neterror(), errmsg, sizeof(errmsg)));
	return PM_ERR_IPC;
    }
    for (bp = buf; bp < &buf[MY_BUFLEN]; bp++) {
	if (__pmRecv(fd, bp, 1, 0) != 1) {
	    *bp = '\0';
	    bp = &buf[MY_BUFLEN];
	    break;
	}
	if (*bp == '\n' || *bp == '\r') {
	    *bp = '\0';
	    break;
	}
    }
    if (bp < &buf[MY_BUFLEN]) {
	if (strcmp(buf, "pmproxy-server 1") == 0)
	    ok = 1;
    }

    if (!ok) {
	__pmNotifyErr(LOG_WARNING,
	     "__pmConnectPMCD: bad version string from pmproxy: \"%s\"\n",
	    buf);
	return PM_ERR_IPC;
    }

    snprintf(buf, sizeof(buf), "%s %d\n", hostname, port);
    if (__pmSend(fd, buf, strlen(buf), 0) != strlen(buf)) {
	char	errmsg[PM_MAXERRMSGLEN];
	__pmNotifyErr(LOG_WARNING,
	     "__pmConnectPMCD: send hostname+port string to pmproxy failed: %s'\n",
	     pmErrStr_r(-neterror(), errmsg, sizeof(errmsg)));
	return PM_ERR_IPC;
    }

    return ok;
}
Example #3
0
static void *
func1(void *arg)
{
    int		sts;
    int		i;
    char	msgbuf[PM_MAXERRMSGLEN];

    for (i = 0; i < ITER; i++) {
	nmetric = 0;
	sts = pmTraversePMNS("", dometric);
	if (sts >= 0)
	    printf("traverse: found %d metrics, sts %d\n", nmetric, sts);
	else {
	    /*
	     * expect 0 metrics and PM_ERR_NOPMNS if the pmTraversePMNS
	     * gets in between the pmUnloadPMNS and the pmLoadPMNS in the
	     * other thread
	     */
	    if (nmetric > 0 || sts != PM_ERR_NOPMNS)
		printf("traverse: found %d metrics, sts %s\n", nmetric, pmErrStr_r(sts, msgbuf, PM_MAXERRMSGLEN));
	    else {
		/* 
		 * nmetric == 0 && sts == PM_ERR_NOPMNS, so try again ...
		 * won't loop forever because eventually func2() will
		 * finish
		 */
		i--;
	    }
	}
    }

    pthread_exit(NULL);
}
Example #4
0
File: err.c Project: scotte/pcp
char *
pmErrStr(int code)
{
    static char	errmsg[PM_MAXERRMSGLEN];
    pmErrStr_r(code, errmsg, sizeof(errmsg));
    return errmsg;
}
Example #5
0
File: root.c Project: rwongone/pcp
/*
 * Connect to the pmdaroot socket as a client, perform version exchange
 */
int
pmdaRootConnect(const char *path)
{
    __pmSockAddr	*addr;
    char		*tmpdir;
    char		socketpath[MAXPATHLEN];
    char		errmsg[PM_MAXERRMSGLEN];
    int			fd, sts, version, features;

    /* Initialize the socket address. */
    if ((addr = __pmSockAddrAlloc()) == NULL)
	return -ENOMEM;

    if (path == NULL) {
	if ((tmpdir = pmGetOptionalConfig("PCP_TMP_DIR")) == NULL) {
	    __pmSockAddrFree(addr);
	    return PM_ERR_GENERIC;
	}
	snprintf(socketpath, sizeof(socketpath), "%s/pmcd/root.socket", tmpdir);
    } else
	strncpy(socketpath, path, sizeof(socketpath));
    socketpath[sizeof(socketpath)-1] = '\0';

    __pmSockAddrSetFamily(addr, AF_UNIX);
    __pmSockAddrSetPath(addr, socketpath);

    /* Create client socket connection */
    if ((fd = __pmCreateUnixSocket()) < 0) {
	__pmNotifyErr(LOG_ERR, "pmdaRootConnect: cannot create socket %s: %s\n",
			socketpath, osstrerror_r(errmsg, sizeof(errmsg)));
	__pmSockAddrFree(addr);
	return fd;
    }

    sts = __pmConnect(fd, addr, -1);
    __pmSockAddrFree(addr);
    if (sts < 0) {
	if (sts != -EPERM || (pmDebug & DBG_TRACE_LIBPMDA))
	    __pmNotifyErr(LOG_INFO,
			"pmdaRootConnect: cannot connect to %s: %s\n",
			socketpath, osstrerror_r(errmsg, sizeof(errmsg)));
	__pmCloseSocket(fd);
	return sts;
    }

    /* Check server connection information */
    if ((sts = __pmdaRecvRootPDUInfo(fd, &version, &features)) < 0) {
	__pmNotifyErr(LOG_ERR,
			"pmdaRootConnect: cannot verify %s server: %s\n",
			socketpath, pmErrStr_r(sts, errmsg, sizeof(errmsg)));
	__pmCloseSocket(fd);
	return sts;
    }

    if (pmDebug & DBG_TRACE_LIBPMDA)
	__pmNotifyErr(LOG_INFO,
		"pmdaRootConnect: %s server fd=%d version=%d features=0x%x\n",
			socketpath, fd, version, features);
    return fd;
}
Example #6
0
File: spec.c Project: goodwinos/pcp
static int
unparseHostSpec(pmHostSpec *hostp, int count, char *string, size_t size, int prefix)
{
    int off = 0, len = size;	/* offset in string and space remaining */
    int i, j, sts;

    for (i = 0; i < count; i++) {
	if (i > 0) {
	    if ((sts = pmsprintf(string + off, len, "@")) >= size) {
		off = -E2BIG;
		goto done;
	    }
	    len -= sts; off += sts;
	}

	if (prefix && hostp[i].nports == PM_HOST_SPEC_NPORTS_LOCAL) {
	    if ((sts = pmsprintf(string + off, len, "local:/%s", hostp[i].name + 1)) >= size) {
		off = -E2BIG;
		goto done;
	    }
	}
	else if (prefix && hostp[i].nports == PM_HOST_SPEC_NPORTS_UNIX) {
	    if ((sts = pmsprintf(string + off, len, "unix:/%s", hostp[i].name + 1)) >= size) {
		off = -E2BIG;
		goto done;
	    }
	}
	else {
	    if ((sts = pmsprintf(string + off, len, "%s", hostp[i].name)) >= size) {
		off = -E2BIG;
		goto done;
	    }
	}
	len -= sts; off += sts;

	for (j = 0; j < hostp[i].nports; j++) {
	    if ((sts = pmsprintf(string + off, len,
			    "%c%u", (j == 0) ? ':' : ',',
			    hostp[i].ports[j])) >= size) {
		off = -E2BIG;
		goto done;
	    }
	    len -= sts; off += sts;
	}
    }

done:
    if (pmDebugOptions.context) {
	fprintf(stderr, "__pmUnparseHostSpec([name=%s ports=%p nport=%d], count=%d, ...) -> ", hostp->name, hostp->ports, hostp->nports, count);
	if (off < 0) {
	    char	errmsg[PM_MAXERRMSGLEN];
	    pmErrStr_r(off, errmsg, sizeof(errmsg));
	    fprintf(stderr, "%s\n", errmsg);
	}
	else
	    fprintf(stderr, "%d \"%s\"\n", off, string);
    }
    return off;
}
Example #7
0
int
main(int argc, char **argv)
{
    pthread_t		tid1;
    pthread_t		tid2;
    int			sts;
    char		*msg;
    unsigned int	in[PDU_MAX+1];
    unsigned int	out[PDU_MAX+1];
    int			i;
    char		msgbuf[PM_MAXERRMSGLEN];

    setvbuf(stdout, NULL, _IONBF, 0);

    if (argc != 1) {
	printf("Usage: multithread4\n");
	exit(1);
    }

    for (i = 0; i <= PDU_MAX; i++) {
	in[i] = out[i] = 0;
    }
    __pmSetPDUCntBuf(in, out);

    if ((sts = pmLoadNameSpace(PM_NS_DEFAULT)) < 0) {
	printf("%s: pmLoadNameSpace: %s\n", argv[0], pmErrStr_r(sts, msgbuf, PM_MAXERRMSGLEN));
	exit(1);
    }

    sts = pthread_create(&tid1, NULL, func1, NULL);
    if (sts != 0) {
	printf("thread_create: tid1: sts=%d\n", sts);
	exit(1);
    }
    sts = pthread_create(&tid2, NULL, func2, NULL);
    if (sts != 0) {
	printf("thread_create: tid2: sts=%d\n", sts);
	exit(1);
    }

    pthread_join(tid1, (void *)&msg);
    if (msg != NULL) printf("tid1: %s\n", msg);
    pthread_join(tid2, (void *)&msg); 
    if (msg != NULL) printf("tid2: %s\n", msg);

    printf("Total PDU counts\n");
    printf("in:");
    for (i = 0; i <= PDU_MAX; i++)
	printf(" %d", in[i]);
    putchar('\n');
    printf("out:");
    for (i = 0; i <= PDU_MAX; i++)
	printf(" %d", out[i]);
    putchar('\n');

    exit(0);
}
Example #8
0
File: import.c Project: Aconex/pcp
char *
pmiErrStr_r(int code, char *buf, int buflen)
{
    const char *msg;

    if (code == -1 && current != NULL) code = current->last_sts;
    switch (code) {
	case PMI_ERR_DUPMETRICNAME:
	    msg = "Metric name already defined";
	    break;
	case PMI_ERR_DUPMETRICID:
	    msg = "Metric pmID already defined";
	    break;
	case PMI_ERR_DUPINSTNAME:
	    msg = "External instance name already defined";
	    break;
	case PMI_ERR_DUPINSTID:
	    msg = "Internal instance identifer already defined";
	    break;
	case PMI_ERR_INSTNOTNULL:
	    msg = "Null instance expected for a singular metric";
	    break;
	case PMI_ERR_INSTNULL:
	    msg = "Null instance not allowed for a non-singular metric";
	    break;
	case PMI_ERR_BADHANDLE:
	    msg = "Illegal handle";
	    break;
	case PMI_ERR_DUPVALUE:
	    msg = "Value already assigned for this metric-instance";
	    break;
	case PMI_ERR_BADTYPE:
	    msg = "Illegal metric type";
	    break;
	case PMI_ERR_BADSEM:
	    msg = "Illegal metric semantics";
	    break;
	case PMI_ERR_NODATA:
	    msg = "No data to output";
	    break;
	case PMI_ERR_BADMETRICNAME:
	    msg = "Illegal metric name";
	    break;
	case PMI_ERR_BADTIMESTAMP:
	    msg = "Illegal result timestamp";
	    break;
	default:
	    return pmErrStr_r(code, buf, buflen);
    }
    strncpy(buf, msg, buflen);
    buf[buflen-1] = '\0';
    return buf;
}
Example #9
0
File: context.c Project: hc000/pcp
static void
destroylock(pthread_mutex_t *lock, char *which)
{
    int		psts;
    char	errmsg[PM_MAXERRMSGLEN];

    if ((psts = pthread_mutex_destroy(lock)) != 0) {
	pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	fprintf(stderr, "pmDestroyContext: pthread_mutex_destroy(%s) failed: %s\n", which, errmsg);
	/*
	 * Most likely cause is the mutex still being locked ... this is a
	 * a library bug, but potentially recoverable ...
	 */
	while (PM_UNLOCK(lock) >= 0) {
	    fprintf(stderr, "pmDestroyContext: extra %s unlock?\n", which);
	}
	if ((psts = pthread_mutex_destroy(lock)) != 0) {
	    pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	    fprintf(stderr, "pmDestroyContext: pthread_mutex_destroy(%s) failed second try: %s\n", which, errmsg);
	}
    }
}
Example #10
0
static void
__pmInitChannelLock(pthread_mutex_t *lock)
{
    int		sts;
    char	errmsg[PM_MAXERRMSGLEN];

    if ((sts = pthread_mutex_init(lock, NULL)) != 0) {
	pmErrStr_r(-sts, errmsg, sizeof(errmsg));
	fprintf(stderr, "pmNewContext: "
		"context=%d pmcd channel lock pthread_mutex_init failed: %s",
		contexts_len, errmsg);
	exit(4);
    }
}
Example #11
0
    /**
     * @brief Constructor.
     *
     * If the optional \a message is not provided (or is empty), then either
     * pmErrStr_r (if available) or pmErrStr will be used to fetch PCP's message
     * for \a pm_error_code.
     *
     * @param pm_error_code PCP error code.
     * @param message       Error message.
     *
     * @see pmErrStr
     * @see pmErrStr_r
     */
    exception(const int pm_error_code,
              const std::string &message = std::string())
        : pm_error_code(pm_error_code),
          message(message)
    {
        if (message.empty()) {
#ifdef PM_MAXERRMSGLEN // pmErrStr_r and PM_MAXERRMSGLEN added in PCP 3.6.0.
            char buffer[PM_MAXERRMSGLEN];
            pmErrStr_r(pm_error_code, buffer, sizeof(buffer));
            this->message.assign(buffer);
#else
            this->message.assign(pmErrStr(pm_error_code));
#endif
        }
    }
Example #12
0
static void *
func2(void *arg)
{
    int		sts;
    char	*fn = "func2";
    int		i;
    char	msgbuf[PM_MAXERRMSGLEN];

    for (i = 0; i < ITER; i++) {
	pmUnloadNameSpace();
	if ((sts = pmLoadNameSpace(PM_NS_DEFAULT)) < 0) {
	    printf("%s: pmLoadNameSpace[%d]: %s\n", fn, i, pmErrStr_r(sts, msgbuf, PM_MAXERRMSGLEN));
	    exit(1);
	}
    }

    pthread_exit(NULL);
}
Example #13
0
File: connect.c Project: tongfw/pcp
static void
load_proxy_hostspec(pmHostSpec *proxy)
{
    char	errmsg[PM_MAXERRMSGLEN];
    char	*envstr;

    if ((envstr = getenv("PMPROXY_HOST")) != NULL) {
	proxy->name = strdup(envstr);
	if (proxy->name == NULL) {
	    __pmNotifyErr(LOG_WARNING,
			  "__pmConnectPMCD: cannot save PMPROXY_HOST: %s\n",
			  pmErrStr_r(-oserror(), errmsg, sizeof(errmsg)));
	}
	else {
	    /*
	     *__pmProxyAddPorts discovers at least one valid port, if it
	     * returns.
	     */
	    proxy->nports = __pmProxyAddPorts(&proxy->ports, proxy->nports);
	}
    }
}
Example #14
0
File: derive.c Project: Aconex/pcp
static void
init(void)
{
    if (need_init) {
	char	*configpath;

	if ((configpath = getenv("PCP_DERIVED_CONFIG")) != NULL) {
	    int	sts;
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_DERIVE) {
		fprintf(stderr, "Derived metric initialization from $PCP_DERIVED_CONFIG\n");
	    }
#endif
	    sts = pmLoadDerivedConfig(configpath);
#ifdef PCP_DEBUG
	    if (sts < 0 && (pmDebug & DBG_TRACE_DERIVE)) {
		char	errmsg[PM_MAXERRMSGLEN];
		fprintf(stderr, "pmLoadDerivedConfig -> %s\n", pmErrStr_r(sts, errmsg, sizeof(errmsg)));
	    }
#endif
	}
	need_init = 0;
    }
}
Example #15
0
File: pdu.c Project: rwongone/pcp
/* result is pinned on successful return */
int
__pmGetPDU(int fd, int mode, int timeout, __pmPDU **result)
{
    int			need;
    int			len;
    static int		maxsize = PDU_CHUNK;
    char		*handle;
    __pmPDU		*pdubuf;
    __pmPDU		*pdubuf_prev;
    __pmPDUHdr		*php;

    if ((pdubuf = __pmFindPDUBuf(maxsize)) == NULL)
	return -oserror();

    /* First read - try to read the header */
    len = pduread(fd, (void *)pdubuf, sizeof(__pmPDUHdr), HEADER, timeout);
    php = (__pmPDUHdr *)pdubuf;

    if (len < (int)sizeof(__pmPDUHdr)) {
	if (len == -1) {
	    if (__pmSocketClosed()) {
		len = 0;
	    } else {
		char	errmsg[PM_MAXERRMSGLEN];
		__pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d hdr read: len=%d: %s", fd, len, pmErrStr_r(-oserror(), errmsg, sizeof(errmsg)));
	    }
	}
	else if (len >= (int)sizeof(php->len)) {
	    /*
	     * Have part of a PDU header.  Enough for the "len"
	     * field to be valid, but not yet all of it - save
	     * what we have received and try to read some more.
	     * Note this can only happen once per PDU, so the
	     * ntohl() below will _only_ be done once per PDU.
	     */
	    goto check_read_len;	/* continue, do not return */
	}
	else if (len == PM_ERR_TIMEOUT) {
	    __pmUnpinPDUBuf(pdubuf);
	    return PM_ERR_TIMEOUT;
	}
	else if (len < 0) {
	    char	errmsg[PM_MAXERRMSGLEN];
	    __pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d hdr read: len=%d: %s", fd, len, pmErrStr_r(len, errmsg, sizeof(errmsg)));
	    __pmUnpinPDUBuf(pdubuf);
	    return PM_ERR_IPC;
	}
	else if (len > 0) {
	    __pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d hdr read: bad len=%d", fd, len);
	    __pmUnpinPDUBuf(pdubuf);
	    return PM_ERR_IPC;
	}

	/*
	 * end-of-file with no data
	 */
	__pmUnpinPDUBuf(pdubuf);
	return 0;
    }

check_read_len:
    php->len = ntohl(php->len);
    if (php->len < (int)sizeof(__pmPDUHdr)) {
	/*
	 * PDU length indicates insufficient bytes for a PDU header
	 * ... looks like DOS attack like PV 935490
	 */
	__pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d illegal PDU len=%d in hdr", fd, php->len);
	__pmUnpinPDUBuf(pdubuf);
	return PM_ERR_IPC;
    }
    else if (mode == LIMIT_SIZE && php->len > ceiling) {
	/*
	 * Guard against denial of service attack ... don't accept PDUs
	 * from clients that are larger than 64 Kbytes (ceiling)
	 * (note, pmcd and pmdas have to be able to _send_ large PDUs,
	 * e.g. for a pmResult or instance domain enquiry)
	 */
	__pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d bad PDU len=%d in hdr exceeds maximum client PDU size (%d)",
		      fd, php->len, ceiling);

	__pmUnpinPDUBuf(pdubuf);
	return PM_ERR_TOOBIG;
    }

    if (len < php->len) {
	/*
	 * need to read more ...
	 */
	int		tmpsize;
	int		have = len;

	PM_INIT_LOCKS();
	PM_LOCK(__pmLock_libpcp);
	if (php->len > maxsize) {
	    tmpsize = PDU_CHUNK * ( 1 + php->len / PDU_CHUNK);
	    maxsize = tmpsize;
	}
	else
	    tmpsize = maxsize;
	PM_UNLOCK(__pmLock_libpcp);

	pdubuf_prev = pdubuf;
	if ((pdubuf = __pmFindPDUBuf(tmpsize)) == NULL) {
	    __pmUnpinPDUBuf(pdubuf_prev);
	    return -oserror();
	}

	memmove((void *)pdubuf, (void *)php, len);
	__pmUnpinPDUBuf(pdubuf_prev);

	php = (__pmPDUHdr *)pdubuf;
	need = php->len - have;
	handle = (char *)pdubuf;
	/* block until all of the PDU is received this time */
	len = pduread(fd, (void *)&handle[len], need, BODY, timeout);
	if (len != need) {
	    if (len == PM_ERR_TIMEOUT) {
		__pmUnpinPDUBuf(pdubuf);
		return PM_ERR_TIMEOUT;
	    }
	    else if (len < 0) {
		char	errmsg[PM_MAXERRMSGLEN];
		__pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d data read: len=%d: %s", fd, len, pmErrStr_r(-oserror(), errmsg, sizeof(errmsg)));
	    }
	    else
		__pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d data read: have %d, want %d, got %d", fd, have, need, len);
	    /*
	     * only report header fields if you've read enough bytes
	     */
	    if (len > 0)
		have += len;
	    if (have >= (int)(sizeof(php->len)+sizeof(php->type)+sizeof(php->from)))
		__pmNotifyErr(LOG_ERR, "__pmGetPDU: PDU hdr: len=0x%x type=0x%x from=0x%x", php->len, (unsigned)ntohl(php->type), (unsigned)ntohl(php->from));
	    else if (have >= (int)(sizeof(php->len)+sizeof(php->type)))
		__pmNotifyErr(LOG_ERR, "__pmGetPDU: PDU hdr: len=0x%x type=0x%x", php->len, (unsigned)ntohl(php->type));
	    __pmUnpinPDUBuf(pdubuf);
	    return PM_ERR_IPC;
	}
    }

    *result = (__pmPDU *)php;
    php->type = ntohl((unsigned int)php->type);
    if (php->type < 0) {
	/*
	 * PDU type is bad ... could be a possible mem leak attack like
	 * https://bugzilla.redhat.com/show_bug.cgi?id=841319
	 */
	__pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d illegal PDU type=%d in hdr", fd, php->type);
	__pmUnpinPDUBuf(pdubuf);
	return PM_ERR_IPC;
    }
    php->from = ntohl((unsigned int)php->from);
#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_PDU) {
	int	j;
	char	*p;
	int	jend = PM_PDU_SIZE(php->len);
	char	strbuf[20];

        /* clear the padding bytes, lest they contain garbage */
	p = (char *)*result + php->len;
	while (p < (char *)*result + jend*sizeof(__pmPDU))
	    *p++ = '~';	/* buffer end */

	if (mypid == -1)
	    mypid = (int)getpid();
	fprintf(stderr, "[%d]pmGetPDU: %s fd=%d len=%d from=%d",
		mypid, __pmPDUTypeStr_r(php->type, strbuf, sizeof(strbuf)), fd, php->len, php->from);
	for (j = 0; j < jend; j++) {
	    if ((j % 8) == 0)
		fprintf(stderr, "\n%03d: ", j);
	    fprintf(stderr, "%8x ", (*result)[j]);
	}
	putc('\n', stderr);
    }
#endif
    if (php->type >= PDU_START && php->type <= PDU_FINISH)
	__pmPDUCntIn[php->type-PDU_START]++;

    /*
     * Note php points into the PDU buffer pdubuf that remains pinned
     * and php is returned via the result parameter ... see the
     * thread-safe comments above
     */
    return php->type;
}
Example #16
0
int
__pmConnectLocal(__pmHashCtl *attrs)
{
    int			i;
    __pmDSO		*dp;
    char		pathbuf[MAXPATHLEN];
    const char		*path;
#if defined(HAVE_DLOPEN)
    unsigned int	challenge;
    void		(*initp)(pmdaInterface *);
#ifdef HAVE_ATEXIT
    static int		atexit_installed = 0;
#endif
#endif

    if (numdso == -1) {
	int	sts;
	sts = build_dsotab();
	if (sts < 0) return sts;
    }

    for (i = 0; i < numdso; i++) {
	dp = &dsotab[i];
	if (dp->domain == -1 || dp->handle != NULL)
	    continue;
	/*
	 * __pmLocalPMDA() means the path to the DSO may be something
	 * other than relative to $PCP_PMDAS_DIR ... need to try both
	 * options and also with and without DSO_SUFFIX (so, dll, etc)
	 */
	snprintf(pathbuf, sizeof(pathbuf), "%s%c%s",
		 pmGetConfig("PCP_PMDAS_DIR"), __pmPathSeparator(), dp->name);
	if ((path = __pmFindPMDA(pathbuf)) == NULL) {
	    snprintf(pathbuf, sizeof(pathbuf), "%s%c%s.%s",
		 pmGetConfig("PCP_PMDAS_DIR"), __pmPathSeparator(), dp->name, DSO_SUFFIX);
	    if ((path = __pmFindPMDA(pathbuf)) == NULL) {
		if ((path = __pmFindPMDA(dp->name)) == NULL) {
		    snprintf(pathbuf, sizeof(pathbuf), "%s.%s", dp->name, DSO_SUFFIX);
		    if ((path = __pmFindPMDA(pathbuf)) == NULL) {
			pmprintf("__pmConnectLocal: Warning: cannot find DSO at \"%s\" or \"%s\"\n", 
			     pathbuf, dp->name);
			pmflush();
			dp->domain = -1;
			dp->handle = NULL;
			continue;
		    }
		}
	    }
	}
#if defined(HAVE_DLOPEN)
	dp->handle = dlopen(path, RTLD_NOW);
	if (dp->handle == NULL) {
	    pmprintf("__pmConnectLocal: Warning: error attaching DSO "
		     "\"%s\"\n%s\n\n", path, dlerror());
	    pmflush();
	    dp->domain = -1;
	}
#else	/* ! HAVE_DLOPEN */
	dp->handle = NULL;
	pmprintf("__pmConnectLocal: Warning: error attaching DSO \"%s\"\n",
		 path);
	pmprintf("No dynamic DSO/DLL support on this platform\n\n");
	pmflush();
	dp->domain = -1;
#endif

	if (dp->handle == NULL)
	    continue;

#if defined(HAVE_DLOPEN)
	/*
	 * rest of this only makes sense if the dlopen() worked
	 */
	if (dp->init == NULL)
	    initp = NULL;
	else
	    initp = (void (*)(pmdaInterface *))dlsym(dp->handle, dp->init);
	if (initp == NULL) {
	    pmprintf("__pmConnectLocal: Warning: couldn't find init function "
		     "\"%s\" in DSO \"%s\"\n", dp->init, path);
	    pmflush();
	    dlclose(dp->handle);
	    dp->domain = -1;
	    continue;
	}

	/*
	 * Pass in the expected domain id.
	 * The PMDA initialization routine can (a) ignore it, (b) check it
	 * is the expected value, or (c) self-adapt.
	 */
	dp->dispatch.domain = dp->domain;

	/*
	 * the PMDA interface / PMAPI version discovery as a "challenge" ...
	 * for pmda_interface it is all the bits being set,
	 * for pmapi_version it is the complement of the one you are using now
	 */
	challenge = 0xff;
	dp->dispatch.comm.pmda_interface = challenge;
	dp->dispatch.comm.pmapi_version = ~PMAPI_VERSION;
	dp->dispatch.comm.flags = 0;
	dp->dispatch.status = 0;

	(*initp)(&dp->dispatch);

	if (dp->dispatch.status != 0) {
	    /* initialization failed for some reason */
	    char	errmsg[PM_MAXERRMSGLEN];
	    pmprintf("__pmConnectLocal: Warning: initialization "
		     "routine \"%s\" failed in DSO \"%s\": %s\n", 
		     dp->init, path, pmErrStr_r(dp->dispatch.status, errmsg, sizeof(errmsg)));
	    pmflush();
	    dlclose(dp->handle);
	    dp->domain = -1;
	}
	else {
	    if (dp->dispatch.comm.pmda_interface < PMDA_INTERFACE_2 ||
		dp->dispatch.comm.pmda_interface > PMDA_INTERFACE_LATEST) {
		pmprintf("__pmConnectLocal: Error: Unknown PMDA interface "
			 "version %d in \"%s\" DSO\n", 
			 dp->dispatch.comm.pmda_interface, path);
		pmflush();
		dlclose(dp->handle);
		dp->domain = -1;
	    }
	    else if (dp->dispatch.comm.pmapi_version != PMAPI_VERSION_2) {
		pmprintf("__pmConnectLocal: Error: Unknown PMAPI version %d "
			 "in \"%s\" DSO\n",
			 dp->dispatch.comm.pmapi_version, path);
		pmflush();
		dlclose(dp->handle);
		dp->domain = -1;
	    }
	    else if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_6 &&
		    (dp->dispatch.comm.flags & PDU_FLAG_AUTH) != 0) {
		/* Agent wants to know about connection attributes */
		build_dsoattrs(&dp->dispatch, attrs);
	    }
	}
#ifdef HAVE_ATEXIT
	PM_INIT_LOCKS();
	PM_LOCK(__pmLock_libpcp);
	if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_5 &&
	    atexit_installed == 0) {
	    /* install end of local context handler */
	    atexit(EndLocalContext);
	    atexit_installed = 1;
	}
	PM_UNLOCK(__pmLock_libpcp);
#endif
#endif	/* HAVE_DLOPEN */
    }

    return 0;
}
Example #17
0
File: fetch.c Project: Aconex/pcp
int
pmFetch(int numpmid, pmID pmidlist[], pmResult **result)
{
    int		n;

    if (numpmid < 1) {
	n = PM_ERR_TOOSMALL;
	goto done;
    }

    if ((n = pmWhichContext()) >= 0) {
	__pmContext	*ctxp = __pmHandleToPtr(n);
	int		newcnt;
	pmID		*newlist = NULL;
	int		have_dm;

	if (ctxp == NULL) {
	    n = PM_ERR_NOCONTEXT;
	    goto done;
	}
	if (ctxp->c_type == PM_CONTEXT_LOCAL && PM_MULTIPLE_THREADS(PM_SCOPE_DSO_PMDA)) {
	    /* Local context requires single-threaded applications */
	    n = PM_ERR_THREAD;
	    PM_UNLOCK(ctxp->c_lock);
	    goto done;
	}

	/* for derived metrics, may need to rewrite the pmidlist */
	have_dm = newcnt = __pmPrepareFetch(ctxp, numpmid, pmidlist, &newlist);
	if (newcnt > numpmid) {
	    /* replace args passed into pmFetch */
	    numpmid = newcnt;
	    pmidlist = newlist;
	}

	if (ctxp->c_type == PM_CONTEXT_HOST) {
	    /*
	     * Thread-safe note
	     *
	     * Need to be careful here, because the PMCD changed protocol
	     * may mean several PDUs are returned, but __pmDecodeResult()
	     * may request more info from PMCD if pmDebug is set.
	     *
	     * So unlock ctxp->c_pmcd->pc_lock as soon as possible.
	     */
	    PM_LOCK(ctxp->c_pmcd->pc_lock);
	    if ((n = request_fetch(n, ctxp, numpmid, pmidlist)) >= 0) {
		int changed = 0;
		do {
		    __pmPDU	*pb;
		    int		pinpdu;

		    pinpdu = n = __pmGetPDU(ctxp->c_pmcd->pc_fd, ANY_SIZE,
					    ctxp->c_pmcd->pc_tout_sec, &pb);
		    if (n == PDU_RESULT) {
			PM_UNLOCK(ctxp->c_pmcd->pc_lock);
			n = __pmDecodeResult(pb, result);
		    }
		    else if (n == PDU_ERROR) {
			__pmDecodeError(pb, &n);
			if (n > 0)
			    /* PMCD state change protocol */
			    changed = n;
			else
			    PM_UNLOCK(ctxp->c_pmcd->pc_lock);
		    }
		    else {
			PM_UNLOCK(ctxp->c_pmcd->pc_lock);
			if (n != PM_ERR_TIMEOUT)
			    n = PM_ERR_IPC;
		    }
		    if (pinpdu > 0)
			__pmUnpinPDUBuf(pb);
		} while (n > 0);

		if (n == 0)
		    n |= changed;
	    }
	    else
		PM_UNLOCK(ctxp->c_pmcd->pc_lock);
	}
	else if (ctxp->c_type == PM_CONTEXT_LOCAL) {
	    n = __pmFetchLocal(ctxp, numpmid, pmidlist, result);
	}
	else {
	    /* assume PM_CONTEXT_ARCHIVE */
	    n = __pmLogFetch(ctxp, numpmid, pmidlist, result);
	    if (n >= 0 && (ctxp->c_mode & __PM_MODE_MASK) != PM_MODE_INTERP) {
		ctxp->c_origin.tv_sec = (__int32_t)(*result)->timestamp.tv_sec;
		ctxp->c_origin.tv_usec = (__int32_t)(*result)->timestamp.tv_usec;
	    }
	}

	/* process derived metrics, if any */
	if (have_dm) {
	    __pmFinishResult(ctxp, n, result);
	    if (newlist != NULL)
		free(newlist);
	}
	PM_UNLOCK(ctxp->c_lock);
    }

done:
#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_FETCH) {
	fprintf(stderr, "pmFetch returns ...\n");
	if (n > 0) {
	    fprintf(stderr, "PMCD state changes: agent(s)");
	    if (n & PMCD_ADD_AGENT) fprintf(stderr, " added");
	    if (n & PMCD_RESTART_AGENT) fprintf(stderr, " restarted");
	    if (n & PMCD_DROP_AGENT) fprintf(stderr, " dropped");
	    fputc('\n', stderr);
	}
	if (n >= 0)
	    __pmDumpResult(stderr, *result);
	else {
	    char	errmsg[PM_MAXERRMSGLEN];
	    fprintf(stderr, "Error: %s\n", pmErrStr_r(n, errmsg, sizeof(errmsg)));
	}
    }
#endif

    return n;
}
Example #18
0
int
__pmLocalPMDA(int op, int domain, const char *name, const char *init)
{
    int		sts = 0;
    int		i;

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_CONTEXT) {
	fprintf(stderr, "__pmLocalPMDA(op=");
	if (op == PM_LOCAL_ADD) fprintf(stderr, "ADD");
	else if (op == PM_LOCAL_DEL) fprintf(stderr, "DEL");
	else if (op == PM_LOCAL_CLEAR) fprintf(stderr, "CLEAR");
	else fprintf(stderr, "%d ???", op);
	fprintf(stderr, ", domain=%d, name=%s, init=%s)\n", domain, name, init);
    }
#endif

    if (numdso == -1) {
	if (op != PM_LOCAL_CLEAR)
	    if ((sts = build_dsotab()) < 0)
		return sts;
    }

    switch (op) {
	case PM_LOCAL_ADD:
	    if ((dsotab = (__pmDSO *)realloc(dsotab, (numdso+1)*sizeof(__pmDSO))) == NULL) {
		__pmNoMem("__pmLocalPMDA realloc", (numdso+1)*sizeof(__pmDSO), PM_FATAL_ERR);
		/*NOTREACHED*/
	    }
	    dsotab[numdso].domain = domain;
	    if (name == NULL) {
		/* odd, will fail later at dlopen */
		dsotab[numdso].name = NULL;
	    }
	    else {
		if ((dsotab[numdso].name = strdup(name)) == NULL) {
		    sts = -oserror();
		    __pmNoMem("__pmLocalPMDA name", strlen(name)+1, PM_RECOV_ERR);
		    return sts;
		}
	    }
	    if (init == NULL) {
		/* odd, will fail later at initialization call */
		dsotab[numdso].init = NULL;
	    }
	    else {
		if ((dsotab[numdso].init = strdup(init)) == NULL) {
		    sts = -oserror();
		    __pmNoMem("__pmLocalPMDA init", strlen(init)+1, PM_RECOV_ERR);
		    return sts;
		}
	    }
	    dsotab[numdso].handle = NULL;
	    numdso++;
	    break;

	case PM_LOCAL_DEL:
	    sts = PM_ERR_INDOM;
	    for (i = 0; i < numdso; i++) {
		if ((domain != -1 && dsotab[i].domain == domain) ||
		    (name != NULL && strcmp(dsotab[i].name, name) == 0)) {
		    if (dsotab[i].handle) {
			dlclose(dsotab[i].handle);
			dsotab[i].handle = NULL;
		    }
		    dsotab[i].domain = -1;
		    sts = 0;
		}
	    }
	    break;

	case PM_LOCAL_CLEAR:
	    for (i = 0; i < numdso; i++) {
		free(dsotab[i].name);
	    	free(dsotab[i].init);
		if (dsotab[i].handle)
		    dlclose(dsotab[i].handle);
	    }
	    free(dsotab);
	    dsotab = NULL;
	    numdso = 0;
	    break;

	default:
	    sts = PM_ERR_CONV;
	    break;
    }

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_CONTEXT) {
	if (sts != 0) {
	    char	errmsg[PM_MAXERRMSGLEN];
	    fprintf(stderr, "__pmLocalPMDA -> %s\n", pmErrStr_r(sts, errmsg, sizeof(errmsg)));
	}
	fprintf(stderr, "Local Context PMDA Table");
	if (numdso == 0)
	    fprintf(stderr, " ... empty");
	fputc('\n', stderr);
	for (i = 0; i < numdso; i++) {
	    fprintf(stderr, PRINTF_P_PFX "%p [%d] domain=%d name=%s init=%s handle=" PRINTF_P_PFX "%p\n",
		&dsotab[i], i, dsotab[i].domain, dsotab[i].name, dsotab[i].init, dsotab[i].handle);
	}
    }
#endif

    return sts;
}
Example #19
0
File: connect.c Project: tongfw/pcp
int
__pmConnectPMCD(pmHostSpec *hosts, int nhosts, int ctxflags, __pmHashCtl *attrs)
{
    int		sts = -1;
    int		fd = -1;	/* Fd for socket connection to pmcd */
    int		*ports;
    int		nports;
    int		portIx;
    int		version = -1;
    int		proxyport;
    pmHostSpec	*proxyhost;

    static int first_time = 1;
    static pmHostSpec proxy;

    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);
    if (first_time) {
	/*
	 * One-trip check for use of pmproxy(1) in lieu of pmcd(1),
	 * and to extract the optional environment variables ...
	 * PMCD_PORT, PMPROXY_HOST and PMPROXY_PORT.
	 * We also check for the presense of a certificate database
	 * and load it up if either a user or system (global) DB is
	 * found.
	 */
	first_time = 0;
	load_pmcd_ports();
	load_proxy_hostspec(&proxy);
    }

    if (hosts[0].nports == 0) {
	nports = global_nports;
	ports = global_portlist;
    }
    else {
	nports = hosts[0].nports;
	ports = hosts[0].ports;
    }

    if (proxy.name == NULL && nhosts == 1) {
	const char *name = (const char *)hosts[0].name;

	/*
	 * no proxy, connecting directly to pmcd
	 */
	PM_UNLOCK(__pmLock_libpcp);

	sts = -1;
	/* Try connecting via the local unix domain socket, if requested and supported. */
	if (nports == PM_HOST_SPEC_NPORTS_LOCAL || nports == PM_HOST_SPEC_NPORTS_UNIX) {
#if defined(HAVE_STRUCT_SOCKADDR_UN)
	    if ((fd = __pmAuxConnectPMCDUnixSocket(name)) >= 0) {
		if ((sts = __pmConnectHandshake(fd, name, ctxflags, attrs)) < 0) {
		    __pmCloseSocket(fd);
		}
		else
		    sts = fd;
		portIx = -1; /* no port */
	    }
#endif
	    /*
	     * If the connection failed, or is not supported, and the protocol was 'local:',
	     * then try connecting to localhost via the default port(s).
	     */
	    if (sts < 0) {
		if (nports == PM_HOST_SPEC_NPORTS_LOCAL) {
		    name = "localhost";
		    nports = global_nports;
		    ports = global_portlist;
		    sts = -1; /* keep trying */
		}
		else
		    sts = -2; /* no more connection attempts. */
	    }
	}

	/* If still not connected, try via the given host name and ports, if requested. */
	if (sts == -1) {
	    for (portIx = 0; portIx < nports; portIx++) {
		if ((fd = __pmAuxConnectPMCDPort(name, ports[portIx])) >= 0) {
		    if ((sts = __pmConnectHandshake(fd, name, ctxflags, attrs)) < 0) {
			__pmCloseSocket(fd);
		    }
		    else
			/* success */
			break;
		}
		else
		    sts = fd;
	    }
	}

	if (sts < 0) {
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_CONTEXT) {
		char	errmsg[PM_MAXERRMSGLEN];
		fprintf(stderr, "__pmConnectPMCD(%s): pmcd connection port=",
		   hosts[0].name);
		for (portIx = 0; portIx < nports; portIx++) {
		    if (portIx == 0) fprintf(stderr, "%d", ports[portIx]);
		    else fprintf(stderr, ",%d", ports[portIx]);
		}
		fprintf(stderr, " failed: %s\n", pmErrStr_r(sts, errmsg, sizeof(errmsg)));
	    }
#endif
	    return sts;
	}

#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_CONTEXT) {
	    if (portIx >= 0) {
		fprintf(stderr, "__pmConnectPMCD(%s): pmcd connection port=%d fd=%d PDU version=%u\n",
			hosts[0].name, ports[portIx], fd, __pmVersionIPC(fd));
	    }
	    else {
		fprintf(stderr, "__pmConnectPMCD(%s): pmcd connection path=%s fd=%d PDU version=%u\n",
			hosts[0].name, name, fd, __pmVersionIPC(fd));
	    }
	    __pmPrintIPC();
	}
#endif

	return fd;
    }

    /*
     * connecting to pmproxy, and then to pmcd ... not a direct
     * connection to pmcd
     */
    proxyhost = (nhosts > 1) ? &hosts[1] : &proxy;
    proxyport = (proxyhost->nports > 0) ? proxyhost->ports[0] : PROXY_PORT;

    for (portIx = 0; portIx < nports; portIx++) {
	fd = __pmAuxConnectPMCDPort(proxyhost->name, proxyport);
	if (fd < 0) {
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_CONTEXT) {
		char	errmsg[PM_MAXERRMSGLEN];
		fprintf(stderr, "__pmConnectPMCD(%s): proxy to %s port=%d failed: %s \n",
			hosts[0].name, proxyhost->name, proxyport, pmErrStr_r(-neterror(), errmsg, sizeof(errmsg)));
	    }
#endif
	    PM_UNLOCK(__pmLock_libpcp);
	    return fd;
	}
	if ((sts = version = negotiate_proxy(fd, hosts[0].name, ports[portIx])) < 0)
	    __pmCloseSocket(fd);
	else if ((sts = __pmConnectHandshake(fd, proxyhost->name, ctxflags, attrs)) < 0)
	    __pmCloseSocket(fd);
	else
	    /* success */
	    break;
    }

    if (sts < 0) {
#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_CONTEXT) {
	    char	errmsg[PM_MAXERRMSGLEN];
	    fprintf(stderr, "__pmConnectPMCD(%s): proxy connection to %s port=",
			hosts[0].name, proxyhost->name);
	    for (portIx = 0; portIx < nports; portIx++) {
		if (portIx == 0) fprintf(stderr, "%d", ports[portIx]);
		else fprintf(stderr, ",%d", ports[portIx]);
	    }
	    fprintf(stderr, " failed: %s\n", pmErrStr_r(sts, errmsg, sizeof(errmsg)));
	}
#endif
	PM_UNLOCK(__pmLock_libpcp);
	return sts;
    }

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_CONTEXT) {
	fprintf(stderr, "__pmConnectPMCD(%s): proxy connection host=%s port=%d fd=%d version=%d\n",
	    hosts[0].name, proxyhost->name, ports[portIx], fd, version);
    }
#endif

    PM_UNLOCK(__pmLock_libpcp);
    return fd;
}
Example #20
0
/*
 * Parse a command line string that encodes arguments to __pmLocalPMDA(),
 * then call __pmLocalPMDA().
 *
 * The syntax for the string is 1 to 4 fields separated by colons:
 * 	- op ("add" for add, "del" for delete, "clear" for clear)
 *	- domain (PMDA's PMD)
 *	- path (path to DSO PMDA)
 *	- init (name of DSO's initialization routine)
 */
char *
__pmSpecLocalPMDA(const char *spec)
{
    int		op;
    int		domain = -1;
    char	*name = NULL;
    char	*init = NULL;
    int		sts;
    char	*arg;
    char	*sbuf;
    char	*ap;

    if ((arg = sbuf = strdup(spec)) == NULL) {
	sts = -oserror();
	__pmNoMem("__pmSpecLocalPMDA dup spec", strlen(spec)+1, PM_RECOV_ERR);
	return "strdup failed";
    }
    if (strncmp(arg, "add", 3) == 0) {
	op = PM_LOCAL_ADD;
	ap = &arg[3];
    }
    else if (strncmp(arg, "del", 3) == 0) {
	op = PM_LOCAL_DEL;
	ap = &arg[3];
    }
    else if (strncmp(arg, "clear", 5) == 0) {
	op = PM_LOCAL_CLEAR;
	ap = &arg[5];
	if (*ap == '\0')
	    goto doit;
	else {
	    free(sbuf);
	    return "unexpected text after clear op in spec";
	}
    }
    else {
	free(sbuf);
	return "bad op in spec";
    }

    if (*ap != ',') {
	free(sbuf);
	return "expected , after op in spec";
    }
    /* ap-> , after add or del */
    arg = ++ap;
    if (*ap == '\0') {
	free(sbuf);
	return "missing domain in spec";
    }
    else if (*ap != ',') {
	/* ap-> domain */
	domain = (int)strtol(arg, &ap, 10);
	if ((*ap != ',' && *ap != '\0') || domain < 0 || domain > 510) {
	    free(sbuf);
	    return "bad domain in spec";
	}
	if (*ap != '\0')
	    /* skip , after domain */
	    ap++;
    }
    else {
	if (op != PM_LOCAL_DEL) {
	    /* found ,, where ,domain, expected */
	    free(sbuf);
	    return "missing domain in spec";
	}
	ap++;
    }
    /* ap -> char after , following domain */
    if (*ap == ',') {
	/* no path, could have init (not useful but possible!) */
	ap++;
	if (*ap != '\0')
	    init = ap;
    }
    else if (*ap != '\0') {
	/* have path and possibly init */
	name = ap;
	while (*ap != ',' && *ap != '\0')
	    ap++;
	if (*ap == ',') {
	    *ap++ = '\0';
	    if (*ap != '\0')
		init = ap;
	    else {
		if (op != PM_LOCAL_DEL) {
		    /* found end of string where init-routine expected */
		    free(sbuf);
		    return "missing init-routine in spec";
		}
	    }
	}
	else {
	    if (op != PM_LOCAL_DEL) {
		/* found end of string where init-routine expected */
		free(sbuf);
		return "missing init-routine in spec";
	    }
	}
    }
    else {
	if (op != PM_LOCAL_DEL) {
	    /* found end of string where path expected */
	    free(sbuf);
	    return "missing dso-path in spec";
	}
    }

    if (domain == -1 && name == NULL) {
	free(sbuf);
	return "missing domain and dso-path in spec";
    }

doit:
    sts = __pmLocalPMDA(op, domain, name, init);
    if (sts < 0) {
	/* see thread-safe note at the head of this file */
	static char buffer[256];
	char	errmsg[PM_MAXERRMSGLEN];
	snprintf(buffer, sizeof(buffer), "__pmLocalPMDA: %s", pmErrStr_r(sts, errmsg, sizeof(errmsg)));
	free(sbuf);
	return buffer;
    }

    free(sbuf);
    return NULL;
}
Example #21
0
/*
 * 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;
}