Ejemplo n.º 1
0
Archivo: AF.c Proyecto: tongfw/pcp
int
__pmAFregister(const struct timeval *delta, void *data, void (*func)(int, void *))
{
    qelt		*qp;
    struct timeval	now;
    struct timeval	interval;

    if (PM_MULTIPLE_THREADS(PM_SCOPE_AF))
	return PM_ERR_THREAD;

    if (!block)
	AFhold();
    if (afid == 0x8000 && !block)	/* first time */
	AFrearm();
    if ((qp = (qelt *)malloc(sizeof(qelt))) == NULL) {
	return -oserror();
    }
    qp->q_afid = ++afid;
    qp->q_data = data;
    qp->q_delta = *delta;
    qp->q_func = func;
    __pmtimevalNow(&qp->q_when);
    tadd(&qp->q_when, &qp->q_delta);

    enqueue(qp);
    if (root == qp) {
	/* we ended up at the head of the list, set itimer */
	interval = qp->q_when;
	__pmtimevalNow(&now);
	tsub(&interval, &now);

	if (interval.tv_sec == 0 && interval.tv_usec < MIN_ITIMER_USEC)
	    /* use minimal delay (platform dependent) */
	    interval.tv_usec = MIN_ITIMER_USEC;

#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_AF) {
	    __pmPrintStamp(stderr, &now);
	    fprintf(stderr, " AFsetitimer for delta ");
	    printdelta(stderr, &interval);
	    fputc('\n', stderr);
	}
#endif
	AFsetitimer(&interval);
    }

    if (!block)
	AFrelse();
    return qp->q_afid;
}
Ejemplo n.º 2
0
Archivo: AF.c Proyecto: tongfw/pcp
static void
enqueue(qelt *qp)
{
    qelt		*tqp;
    qelt		*priorp;

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_AF) {
	struct timeval	now;

	__pmtimevalNow(&now);
	__pmPrintStamp(stderr, &now);
	fprintf(stderr, " AFenqueue " PRINTF_P_PFX "%p(%d, " PRINTF_P_PFX "%p) for ",
		qp->q_func, qp->q_afid, qp->q_data);
	__pmPrintStamp(stderr, &qp->q_when);
	fputc('\n', stderr);
    }
#endif

    for (tqp = root, priorp = NULL;
	 tqp != NULL && tcmp(&qp->q_when, &tqp->q_when) >= 0;
	 tqp = tqp->q_next)
	    priorp = tqp;

    if (priorp == NULL) {
	qp->q_next = root;
	root = qp;
    }
    else {
	qp->q_next = priorp->q_next;
	priorp->q_next = qp;
    }
}
Ejemplo n.º 3
0
/* return real time */
RealTime
getReal(void)
{
    struct timeval t;

    __pmtimevalNow(&t);
    return __pmtimevalToReal(&t);
}
Ejemplo n.º 4
0
/* Establish a new socket connection to a client */
ClientInfo *
AcceptNewClient(int reqfd)
{
    static unsigned int	seq = 0;
    int			i, fd;
    __pmSockLen		addrlen;
    struct timeval	now;

    i = NewClient();
    addrlen = __pmSockAddrSize();
    fd = __pmAccept(reqfd, client[i].addr, &addrlen);
    if (fd == -1) {
        if (neterror() == EPERM) {
            __pmNotifyErr(LOG_NOTICE, "AcceptNewClient(%d): "
                          "Permission Denied\n", reqfd);
            client[i].fd = -1;
            DeleteClient(&client[i]);
            return NULL;
        }
        else {
            __pmNotifyErr(LOG_ERR, "AcceptNewClient(%d) __pmAccept: %s\n",
                          reqfd, netstrerror());
            Shutdown();
            exit(1);
        }
    }
    if (fd > maxClientFd)
        maxClientFd = fd;

    pmcd_openfds_sethi(fd);

    __pmFD_SET(fd, &clientFds);
    __pmSetVersionIPC(fd, UNKNOWN_VERSION);	/* before negotiation */
    __pmSetSocketIPC(fd);

    client[i].fd = fd;
    client[i].status.connected = 1;
    client[i].status.changes = 0;
    memset(&client[i].attrs, 0, sizeof(__pmHashCtl));

    /*
     * Note seq needs to be unique, but we're using a free running counter
     * and not bothering to check here ... unless we churn through
     * 4,294,967,296 (2^32) clients while one client remains connected
     * we won't have a problem
     */
    client[i].seq = seq++;
    __pmtimevalNow(&now);
    client[i].start = now.tv_sec;

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_APPL0)
        fprintf(stderr, "AcceptNewClient(%d): client[%d] (fd %d)\n", reqfd, i, fd);
#endif
    pmcd_trace(TR_ADD_CLIENT, i, 0, 0);

    return &client[i];
}
Ejemplo n.º 5
0
Archivo: AF.c Proyecto: tongfw/pcp
int
__pmAFunregister(int afid)
{
    qelt		*qp;
    qelt		*priorp;
    struct timeval	now;
    struct timeval	interval;

    if (PM_MULTIPLE_THREADS(PM_SCOPE_AF))
	return PM_ERR_THREAD;

    if (!block)
	AFhold();
    for (qp = root, priorp = NULL; qp != NULL && qp->q_afid != afid; qp = qp->q_next)
	    priorp = qp;

    if (qp == NULL) {
	if (!block)
	    AFrelse();
	return -1;
    }

    if (priorp == NULL) {
	root = qp->q_next;
	if (root != NULL) {
	    /*
	     * we removed the head of the queue, set itimer for the
	     * new head of queue
	     */
	    interval = root->q_when;
	    __pmtimevalNow(&now);
	    tsub(&interval, &now);
	    if (interval.tv_sec == 0 && interval.tv_usec < MIN_ITIMER_USEC)
		/* use minimal delay (platform dependent) */
		interval.tv_usec = MIN_ITIMER_USEC;
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_AF) {
		__pmPrintStamp(stderr, &now);
		fprintf(stderr, " AFsetitimer for delta ");
		printdelta(stderr, &interval);
		fputc('\n', stderr);
	    }
#endif
	    AFsetitimer(&interval);
	}
    }
    else
	priorp->q_next = qp->q_next;

    free(qp);

    if (!block)
	AFrelse();
    return 0;
}
Ejemplo n.º 6
0
static void
sleeptill(struct timeval sched)
{
    int sts;
    struct timeval curr;	/* current time */
    struct timespec delay;	/* interval to sleep */
    struct timespec left;	/* remaining sleep time */

    __pmtimevalNow(&curr);
    tospec(tsub(sched, curr), &delay);
    for (;;) {		/* loop to catch early wakeup by nanosleep */
	sts = nanosleep(&delay, &left);
	if (sts == 0 || (sts < 0 && errno != EINTR))
	    break;
	delay = left;
    }
}
Ejemplo n.º 7
0
Archivo: tv.c Proyecto: Aconex/pcp
/* sleep until given timeval */
void
__pmtimevalPause(struct timeval sched)
{
    int sts;
    struct timeval curr;	/* current time */
    struct timespec delay;	/* interval to sleep */
    struct timespec left;	/* remaining sleep time */

    __pmtimevalNow(&curr);
    __pmtimevalDec(&sched, &curr);
    tospec(&sched, &delay);
    for (;;) {		/* loop to catch early wakeup by nanosleep */
	sts = nanosleep(&delay, &left);
	if (sts == 0 || (sts < 0 && oserror() != EINTR))
	    break;
	delay = left;
    }
}
Ejemplo n.º 8
0
Archivo: import.c Proyecto: Aconex/pcp
int
pmiWrite(int sec, int usec)
{
    int		sts;

    if (current == NULL)
	return PM_ERR_NOCONTEXT;
    if (current->result == NULL)
	return current->last_sts = PMI_ERR_NODATA;

    if (sec < 0) {
	__pmtimevalNow(&current->result->timestamp);
    }
    else {
	current->result->timestamp.tv_sec = sec;
	current->result->timestamp.tv_usec = usec;
    }
    if (current->result->timestamp.tv_sec < current->last_stamp.tv_sec ||
        (current->result->timestamp.tv_sec == current->last_stamp.tv_sec &&
	 current->result->timestamp.tv_usec < current->last_stamp.tv_usec)) {
	fprintf(stderr, "Fatal Error: timestamp ");
	printstamp(stderr, &current->result->timestamp);
	fprintf(stderr, " not greater than previous valid timestamp ");
	printstamp(stderr, &current->last_stamp);
	fputc('\n', stderr);
	sts = PMI_ERR_BADTIMESTAMP;
    }
    else {
	sts = _pmi_put_result(current, current->result);
	current->last_stamp = current->result->timestamp;
    }

    pmFreeResult(current->result);
    current->result = NULL;

    return current->last_sts = sts;
}
Ejemplo n.º 9
0
Archivo: dso.c Proyecto: linwukang/pcp
void
dodso(int pdu)
{
    int			sts = 0;		/* initialize to pander to gcc */
    int			length;
    pmDesc		desc;
    pmDesc		*desc_list = NULL;
    pmResult		*result;
    __pmInResult	*inresult;
    int			i;
    int			j;
    char		*buffer;
    struct timeval	start;
    struct timeval	end;
    char		name[32];
    char		**namelist;
    int			*statuslist;
    pmID		pmid;

    if (timer != 0)
        __pmtimevalNow(&start);

    switch (pdu) {

    case PDU_DESC_REQ:
        printf("PMID: %s\n", pmIDStr(param.pmid));
        if ((sts = dodso_desc(param.pmid, &desc)) >= 0)
            __pmPrintDesc(stdout, &desc);
        else
            printf("Error: DSO desc() failed: %s\n", pmErrStr(sts));
        break;

    case PDU_FETCH:
        printf("PMID(s):");
        for (i = 0; i < param.numpmid; i++)
            printf(" %s", pmIDStr(param.pmidlist[i]));
        putchar('\n');

        if (get_desc) {
            desc_list = (pmDesc *)malloc(param.numpmid * sizeof(pmDesc));
            if (desc_list == NULL) {
                printf("Error: DSO fetch() failed: %s\n", pmErrStr(ENOMEM));
                return;
            }
            for (i = 0; i < param.numpmid; i++) {
                if ((sts = dodso_desc(param.pmidlist[i], &desc_list[i])) < 0) {
                    printf("Error: DSO desc() failed: %s\n", pmErrStr(sts));
                    free(desc_list);
                    return;
                }
            }
        }
        sts = 0;
        if (profile_changed) {
#ifdef PCP_DEBUG
            if (pmDebug & DBG_TRACE_PDU)
                fprintf(stderr, "DSO profile()\n");
#endif
            sts = dispatch.version.any.profile(profile, dispatch.version.any.ext);
            if (sts < 0)
                printf("Error: DSO profile() failed: %s\n", pmErrStr(sts));
            else
                profile_changed = 0;
        }
        if (sts >= 0) {
#ifdef PCP_DEBUG
            if (pmDebug & DBG_TRACE_PDU)
                fprintf(stderr, "DSO fetch()\n");
#endif
            sts = dispatch.version.any.fetch(param.numpmid, param.pmidlist,
                                             &result, dispatch.version.any.ext);
            if (sts >= 0) {
                if (desc_list)
                    _dbDumpResult(stdout, result, desc_list);
                else
                    __pmDumpResult(stdout, result);
                /*
                 * DSO PMDA will manage the pmResult skelton, but
                 * we need to free the pmValueSets and values here
                 */
                __pmFreeResultValues(result);
            }
            else {
                printf("Error: DSO fetch() failed: %s\n", pmErrStr(sts));
            }
        }
        if (desc_list)
            free(desc_list);
        break;

    case PDU_INSTANCE_REQ:
        printf("pmInDom: %s\n", pmInDomStr(param.indom));
#ifdef PCP_DEBUG
        if (pmDebug & DBG_TRACE_PDU)
            fprintf(stderr, "DSO instance()\n");
#endif

        sts = dispatch.version.any.instance(param.indom, param.number,
                                            param.name, &inresult,
                                            dispatch.version.any.ext);
        if (sts >= 0)
            printindom(stdout, inresult);
        else
            printf("Error: DSO instance() failed: %s\n", pmErrStr(sts));
        break;

    case PDU_RESULT:

        printf("PMID: %s\n", pmIDStr(param.pmid));
        printf("Getting description...\n");
        desc_list = &desc;
        if ((sts = dodso_desc(param.pmid, desc_list)) < 0) {
            printf("Error: DSO desc() failed: %s\n", pmErrStr(sts));
            return;
        }

        if (profile_changed) {
            printf("Sending Profile...\n");
            sts = dispatch.version.any.profile(profile, dispatch.version.any.ext);
            if (sts < 0) {
                printf("Error: DSO profile() failed: %s\n", pmErrStr(sts));
                return;
            }
            else
                profile_changed = 0;
        }

        printf("Getting Result Structure...\n");
        sts = dispatch.version.any.fetch(1, &(desc.pmid), &result,
                                         dispatch.version.any.ext);
        if (sts < 0) {
            printf("Error: DSO fetch() failed: %s\n", pmErrStr(sts));
            return;
        }

#ifdef PCP_DEBUG
        else if (pmDebug & DBG_TRACE_FETCH)
            _dbDumpResult(stdout, result, desc_list);
#endif

        sts = fillResult(result, desc.type);
        if (sts < 0) {
            pmFreeResult(result);
            return;
        }

        sts = dispatch.version.any.store(result, dispatch.version.any.ext);
        if (sts < 0)
            printf("Error: DSO store() failed: %s\n", pmErrStr(sts));

        break;

    case PDU_TEXT_REQ:
        if (param.number == PM_TEXT_PMID) {
            printf("PMID: %s\n", pmIDStr(param.pmid));
            i = param.pmid;
        }
        else {
            printf("pmInDom: %s\n", pmInDomStr(param.indom));
            i = param.indom;
        }

        for (j = 0; j < 2; j++) {

            if (j == 0)
                param.number |= PM_TEXT_ONELINE;
            else {
                param.number &= ~PM_TEXT_ONELINE;
                param.number |= PM_TEXT_HELP;
            }

            sts = dispatch.version.any.text(i, param.number, &buffer, dispatch.version.any.ext);
            if (sts >= 0) {
                if (j == 0) {
                    if (*buffer != '\0')
                        printf("[%s]\n", buffer);
                    else
                        printf("[<no one line help text specified>]\n");
                }
                else if (*buffer != '\0')
                    printf("%s\n", buffer);
                else
                    printf("<no help text specified>\n");
            }
            else
                printf("Error: DSO text() failed: %s\n", pmErrStr(sts));
        }
        break;

    case PDU_PMNS_IDS:
        if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) {
            printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface);
            break;
        }
        printf("PMID: %s\n", pmIDStr(param.pmid));
        sts = dispatch.version.four.name(param.pmid, &namelist, dispatch.version.four.ext);
        if (sts > 0) {
            for (i = 0; i < sts; i++) {
                printf("   %s\n", namelist[i]);
            }
            free(namelist);
        }
        else if (sts == 0)
            printf("Warning: DSO name() returns 0\n");
        else
            printf("Error: DSO name() failed: %s\n", pmErrStr(sts));
        break;

    case PDU_PMNS_NAMES:
        if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) {
            printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface);
            break;
        }
        printf("Metric: %s\n", param.name);
        sts = dispatch.version.four.pmid(param.name, &pmid, dispatch.version.four.ext);
        if (sts >= 0)
            printf("   %s\n", pmIDStr(pmid));
        else
            printf("Error: DSO pmid() failed: %s\n", pmErrStr(sts));
        break;

    case PDU_PMNS_CHILD:
        if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) {
            printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface);
            break;
        }
        printf("Metric: %s\n", param.name);
        sts = dispatch.version.four.children(param.name, 0, &namelist, &statuslist, dispatch.version.four.ext);
        if (sts > 0) {
            for (i = 0; i < sts; i++) {
                printf("   %8.8s %s\n", statuslist[i] == 1 ? "non-leaf" : "leaf", namelist[i]);
            }
            free(namelist);
            free(statuslist);
        }
        else if (sts == 0)
            printf("Warning: DSO children() returns 0\n");
        else
            printf("Error: DSO children() failed: %s\n", pmErrStr(sts));
        break;

    case PDU_PMNS_TRAVERSE:
        if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) {
            printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface);
            break;
        }
        printf("Metric: %s\n", param.name);
        sts = dispatch.version.four.children(param.name, 1, &namelist, &statuslist, dispatch.version.four.ext);
        if (sts > 0) {
            for (i = 0; i < sts; i++) {
                printf("   %8.8s %s\n", statuslist[i] == 1 ? "non-leaf" : "leaf", namelist[i]);
            }
            free(namelist);
            free(statuslist);
        }
        else if (sts == 0)
            printf("Warning: DSO children() returns 0\n");
        else
            printf("Error: DSO children() failed: %s\n", pmErrStr(sts));
        break;

    case PDU_AUTH:
        if (dispatch.comm.pmda_interface < PMDA_INTERFACE_6) {
            printf("Error: PMDA Interface %d does not support authentication\n", dispatch.comm.pmda_interface);
            break;
        }
        j = param.number;			/* attribute key */
        buffer = param.name;		/* attribute value */
        if (buffer)
            length = strlen(buffer) + 1;	/* length of value */
        else
            length = 0;
        i = 0;				/* client ID */

        __pmAttrKeyStr_r(j, name, sizeof(name)-1);
        name[sizeof(name)-1] = '\0';

        printf("Attribute: %s=%s\n", name, buffer ? buffer : "''");
        sts = dispatch.version.six.attribute(i, j, buffer, length, dispatch.version.six.ext);
        if (sts >= 0)
            printf("Success\n");
        else
            printf("Error: DSO attribute() failed: %s\n", pmErrStr(sts));
        break;

    default:
        printf("Error: DSO PDU (%s) botch!\n", __pmPDUTypeStr(pdu));
        break;
    }

    if (sts >= 0 && timer != 0) {
        __pmtimevalNow(&end);
        printf("Timer: %f seconds\n", __pmtimevalSub(&end, &start));
    }
}
Ejemplo n.º 10
0
int
DoFetch(ClientInfo *cip, __pmPDU* pb)
{
    int			i, j;
    int 		sts;
    int			ctxnum;
    __pmTimeval		when;
    int			nPmids;
    pmID		*pmidList;
    static pmResult	*endResult = NULL;
    static int		maxnpmids = 0;	/* sizes endResult */
    DomPmidList		*dList;		/* NOTE: NOT indexed by agent index */
    static int		nDoms = 0;
    static pmResult	**results = NULL;
    static int		*resIndex = NULL;
    __pmFdSet		waitFds;
    __pmFdSet		readyFds;
    int			nWait;
    int			maxFd;
    struct timeval	timeout;

    if (nAgents > nDoms) {
	if (results != NULL)
	    free(results);
	if (resIndex != NULL)
	    free(resIndex);
	results = (pmResult **)malloc((nAgents + 1) * sizeof (pmResult *));
	resIndex = (int *)malloc((nAgents + 1) * sizeof(int));
	if (results == NULL || resIndex == NULL) {
	    __pmNoMem("DoFetch.results", (nAgents + 1) * sizeof (pmResult *) + (nAgents + 1) * sizeof(int), PM_FATAL_ERR);
	}
	nDoms = nAgents;
    }
    memset(results, 0, (nAgents + 1) * sizeof(results[0]));

    sts = __pmDecodeFetch(pb, &ctxnum, &when, &nPmids, &pmidList);
    if (sts < 0)
	return sts;

    /* Check that a profile has been received from the specified context */
    if (ctxnum < 0 || ctxnum >= cip->szProfile ||
	cip->profile[ctxnum] == NULL) {
	__pmUnpinPDUBuf(pb);
	if (ctxnum < 0 || ctxnum >= cip->szProfile)
	    __pmNotifyErr(LOG_ERR, "DoFetch: bad ctxnum=%d\n", ctxnum);
	else
	    __pmNotifyErr(LOG_ERR, "DoFetch: no profile for ctxnum=%d\n", ctxnum);
	return PM_ERR_NOPROFILE;
    }

    if (nPmids > maxnpmids) {
	int		need;
	if (endResult != NULL)
	    free(endResult);
	need = (int)sizeof(pmResult) + (nPmids - 1) * (int)sizeof(pmValueSet *);
	if ((endResult = (pmResult *)malloc(need)) == NULL) {
	    __pmNoMem("DoFetch.endResult", need, PM_FATAL_ERR);
	}
	maxnpmids = nPmids;
    }

    dList = SplitPmidList(nPmids, pmidList);

    /* For each domain in the split pmidList, dispatch the per-domain subset
     * of pmIDs to the appropriate agent.  For DSO agents, the pmResult will
     * come back immediately.  If a request cannot be sent to an agent, a
     * suitable pmResult (containing metric not available values) will be
     * returned.
     */
    __pmFD_ZERO(&waitFds);
    nWait = 0;
    maxFd = -1;
    for (i = 0; dList[i].domain != -1; i++) {
	j = mapdom[dList[i].domain];
	results[j] = SendFetch(&dList[i], &agent[j], cip, ctxnum);
	if (results[j] == NULL) { /* Wait for agent's response */
	    int fd = agent[j].outFd;
	    agent[j].status.busy = 1;
	    __pmFD_SET(fd, &waitFds);
	    if (fd > maxFd)
		maxFd = fd;
	    nWait++;
	}
    }
    /* Construct pmResult for bad-pmID list */
    if (dList[i].listSize != 0)
	results[nAgents] = MakeBadResult(dList[i].listSize, dList[i].list, PM_ERR_NOAGENT);

    /* Wait for results to roll in from agents */
    while (nWait > 0) {
        __pmFD_COPY(&readyFds, &waitFds);
	if (nWait > 1) {
	    timeout.tv_sec = _pmcd_timeout;
	    timeout.tv_usec = 0;

            retry:
	    setoserror(0);
	    sts = __pmSelectRead(maxFd+1, &readyFds, &timeout);

	    if (sts == 0) {
		__pmNotifyErr(LOG_INFO, "DoFetch: select timeout");

		/* Timeout, terminate agents with undelivered results */
		for (i = 0; i < nAgents; i++) {
		    if (agent[i].status.busy) {
			/* Find entry in dList for this agent */
			for (j = 0; dList[j].domain != -1; j++)
			    if (dList[j].domain == agent[i].pmDomainId)
				break;
			results[i] = MakeBadResult(dList[j].listSize,
						   dList[j].list,
						   PM_ERR_NOAGENT);
			pmcd_trace(TR_RECV_TIMEOUT, agent[i].outFd, PDU_RESULT, 0);
			CleanupAgent(&agent[i], AT_COMM, agent[i].inFd);
		    }
		}
		break;
	    }
	    else if (sts < 0) {
		if (neterror() == EINTR)
		    goto retry;
		/* this is not expected to happen! */
		__pmNotifyErr(LOG_ERR, "DoFetch: fatal select failure: %s\n",
			netstrerror());
		Shutdown();
		exit(1);
	    }
	}

	/* Read results from agents that have them ready */
	for (i = 0; i < nAgents; i++) {
	    AgentInfo	*ap = &agent[i];
	    int		pinpdu;
	    if (!ap->status.busy || !__pmFD_ISSET(ap->outFd, &readyFds))
		continue;
	    ap->status.busy = 0;
	    __pmFD_CLR(ap->outFd, &waitFds);
	    nWait--;
	    pinpdu = sts = __pmGetPDU(ap->outFd, ANY_SIZE, _pmcd_timeout, &pb);
	    if (sts > 0)
		pmcd_trace(TR_RECV_PDU, ap->outFd, sts, (int)((__psint_t)pb & 0xffffffff));
	    if (sts == PDU_RESULT) {
		if ((sts = __pmDecodeResult(pb, &results[i])) >= 0)
		    if (results[i]->numpmid != aFreq[i]) {
			pmFreeResult(results[i]);
			sts = PM_ERR_IPC;
#ifdef PCP_DEBUG
			if (pmDebug & DBG_TRACE_APPL0)
			    __pmNotifyErr(LOG_ERR, "DoFetch: \"%s\" agent given %d pmIDs, returned %d\n",
					 ap->pmDomainLabel, aFreq[i], results[i]->numpmid);
#endif
		    }
	    }
	    else {
		if (sts == PDU_ERROR) {
		    int s;
		    if ((s = __pmDecodeError(pb, &sts)) < 0)
			sts = s;
		    else if (sts >= 0)
			sts = PM_ERR_GENERIC;
		    pmcd_trace(TR_RECV_ERR, ap->outFd, PDU_RESULT, sts);
		}
		else if (sts >= 0) {
		    pmcd_trace(TR_WRONG_PDU, ap->outFd, PDU_RESULT, sts);
		    sts = PM_ERR_IPC;
		}
	    }
	    if (pinpdu > 0)
		__pmUnpinPDUBuf(pb);

	    if (sts < 0) {
		/* Find entry in dList for this agent */
		for (j = 0; dList[j].domain != -1; j++)
		    if (dList[j].domain == agent[i].pmDomainId)
			break;
		results[i] = MakeBadResult(dList[j].listSize,
					   dList[j].list, sts);

		if (sts == PM_ERR_PMDANOTREADY) {
		    /* the agent is indicating it can't handle PDUs for now */
		    int k;
		    extern int CheckError(AgentInfo *ap, int sts);

		    for (k = 0; k < dList[j].listSize; k++)
			results[i]->vset[k]->numval = PM_ERR_AGAIN;
		    sts = CheckError(&agent[i], sts);
		}

#ifdef PCP_DEBUG
		if (pmDebug & DBG_TRACE_APPL0) {
		    fprintf(stderr, "RESULT error from \"%s\" agent : %s\n",
			    ap->pmDomainLabel, pmErrStr(sts));
		}
#endif
		if (sts == PM_ERR_IPC || sts == PM_ERR_TIMEOUT)
		    CleanupAgent(ap, AT_COMM, ap->outFd);
	    }
	}
    }

    endResult->numpmid = nPmids;
    __pmtimevalNow(&endResult->timestamp);
    /* The order of the pmIDs in the per-domain results is the same as in the
     * original request, but on a per-domain basis.  resIndex is an array of
     * indices (one per agent) of the next metric to be retrieved from each
     * per-domain result's vset.
     */
    memset(resIndex, 0, (nAgents + 1) * sizeof(resIndex[0]));

    for (i = 0; i < nPmids; i++) {
	j = mapdom[((__pmID_int *)&pmidList[i])->domain];
	endResult->vset[i] = results[j]->vset[resIndex[j]++];
    }
    pmcd_trace(TR_XMIT_PDU, cip->fd, PDU_RESULT, endResult->numpmid);

    sts = 0;
    if (cip->status.changes) {
	/* notify client of PMCD state change */
	sts = __pmSendError(cip->fd, FROM_ANON, (int)cip->status.changes);
	if (sts > 0)
	    sts = 0;
	cip->status.changes = 0;
    }
    if (sts == 0)
	sts = __pmSendResult(cip->fd, FROM_ANON, endResult);

    if (sts < 0) {
	pmcd_trace(TR_XMIT_ERR, cip->fd, PDU_RESULT, sts);
	CleanupClient(cip, sts);
    }

    /*
     * pmFreeResult() all the accumulated results.
     */
    for (i = 0; dList[i].domain != -1; i++) {
	j = mapdom[dList[i].domain];
	if (agent[j].ipcType == AGENT_DSO && agent[j].status.connected &&
	    !agent[j].status.madeDsoResult)
	    /* Living DSO's manage their own pmResult skeleton unless
	     * MakeBadResult was called to create the result.  The value sets
	     * within the skeleton need to be freed though!
	     */
	    __pmFreeResultValues(results[j]);
	else
	    /* For others it is dynamically allocated in __pmDecodeResult or
	     * MakeBadResult
	     */
	    pmFreeResult(results[j]);
    }
    if (results[nAgents] != NULL)
	pmFreeResult(results[nAgents]);
    __pmUnpinPDUBuf(pmidList);
    return 0;
}
Ejemplo n.º 11
0
int
main(int argc, char **argv)
{
    int			c;
    int			sts;
    int			sep = __pmPathSeparator();
    int			use_localtime = 0;
    int			isdaemon = 0;
    char		*pmnsfile = PM_NS_DEFAULT;
    char		*username;
    char		*logfile = "pmlogger.log";
				    /* default log (not archive) file name */
    char		*endnum;
    int			i;
    task_t		*tp;
    optcost_t		ocp;
    __pmFdSet		readyfds;
    char		*p;
    char		*runtime = NULL;
    int	    		ctx;		/* handle corresponding to ctxp below */
    __pmContext  	*ctxp;		/* pmlogger has just this one context */
    int			niter;
    pid_t               target_pid = 0;

    __pmGetUsername(&username);

    /*
     * Warning:
     *		If any of the pmlogger options change, make sure the
     *		corresponding changes are made to pmnewlog when pmlogger
     *		options are passed through from the control file
     */
    while ((c = pmgetopt_r(argc, argv, &opts)) != EOF) {
	switch (c) {

	case 'c':		/* config file */
	    if (access(opts.optarg, F_OK) == 0)
		configfile = opts.optarg;
	    else {
		/* does not exist as given, try the standard place */
		char *sysconf = pmGetConfig("PCP_VAR_DIR");
		int sz = strlen(sysconf)+strlen("/config/pmlogger/")+strlen(opts.optarg)+1;
		if ((configfile = (char *)malloc(sz)) == NULL)
		    __pmNoMem("config file name", sz, PM_FATAL_ERR);
		snprintf(configfile, sz,
			"%s%c" "config%c" "pmlogger%c" "%s",
			sysconf, sep, sep, sep, opts.optarg);
		if (access(configfile, F_OK) != 0) {
		    /* still no good, error handling happens below */
		    free(configfile);
		    configfile = opts.optarg;
		}
	    }
	    break;

	case 'D':	/* debug flag */
	    sts = __pmParseDebug(opts.optarg);
	    if (sts < 0) {
		pmprintf("%s: unrecognized debug flag specification (%s)\n",
			pmProgname, opts.optarg);
		opts.errors++;
	    }
	    else
		pmDebug |= sts;
	    break;

	case 'h':		/* hostname for PMCD to contact */
	    pmcd_host_conn = opts.optarg;
	    break;

	case 'l':		/* log file name */
	    logfile = opts.optarg;
	    break;

	case 'L':		/* linger if not primary logger */
	    linger = 1;
	    break;

	case 'm':		/* note for port map file */
	    note = opts.optarg;
	    isdaemon = ((strcmp(note, "pmlogger_check") == 0) ||
			(strcmp(note, "pmlogger_daily") == 0));
	    break;

	case 'n':		/* alternative name space file */
	    pmnsfile = opts.optarg;
	    break;

	case 'p':
	    target_pid = (int)strtol(opts.optarg, &endnum, 10);
	    if (*endnum != '\0') {
		pmprintf("%s: invalid process identifier (%s)\n",
			 pmProgname, opts.optarg);
		opts.errors++;
	    } else if (!__pmProcessExists(target_pid)) {
		pmprintf("%s: PID error - no such process (%d)\n",
			 pmProgname, target_pid);
		opts.errors++;
	    }
	    break;

	case 'P':		/* this is the primary pmlogger */
	    primary = 1;
	    isdaemon = 1;
	    break;

	case 'r':		/* report sizes of pmResult records */
	    rflag = 1;
	    break;

	case 's':		/* exit size */
	    sts = ParseSize(opts.optarg, &exit_samples, &exit_bytes, &exit_time);
	    if (sts < 0) {
		pmprintf("%s: illegal size argument '%s' for exit size\n",
			pmProgname, opts.optarg);
		opts.errors++;
	    }
	    else if (exit_time.tv_sec > 0) {
		__pmAFregister(&exit_time, NULL, run_done_callback);
	    }
	    break;

	case 'T':		/* end time */
	    runtime = opts.optarg;
            break;

	case 't':		/* change default logging interval */
	    if (pmParseInterval(opts.optarg, &delta, &p) < 0) {
		pmprintf("%s: illegal -t argument\n%s", pmProgname, p);
		free(p);
		opts.errors++;
	    }
	    break;

	case 'U':		/* run as named user */
	    username = opts.optarg;
	    isdaemon = 1;
	    break;

	case 'u':		/* flush output buffers after each fetch */
	    /*
	     * all archive write I/O is unbuffered now, so maintain -u
	     * for backwards compatibility only
	     */
	    break;

	case 'v':		/* volume switch after given size */
	    sts = ParseSize(opts.optarg, &vol_switch_samples, &vol_switch_bytes,
			    &vol_switch_time);
	    if (sts < 0) {
		pmprintf("%s: illegal size argument '%s' for volume size\n", 
			pmProgname, opts.optarg);
		opts.errors++;
	    }
	    else if (vol_switch_time.tv_sec > 0) {
		vol_switch_afid = __pmAFregister(&vol_switch_time, NULL, 
						 vol_switch_callback);
            }
	    break;

        case 'V': 
	    archive_version = (int)strtol(opts.optarg, &endnum, 10);
	    if (*endnum != '\0' || archive_version != PM_LOG_VERS02) {
		pmprintf("%s: -V requires a version number of %d\n",
			 pmProgname, PM_LOG_VERS02); 
		opts.errors++;
	    }
	    break;

	case 'x':		/* recording session control fd */
	    rsc_fd = (int)strtol(opts.optarg, &endnum, 10);
	    if (*endnum != '\0' || rsc_fd < 0) {
		pmprintf("%s: -x requires a non-negative numeric argument\n", pmProgname);
		opts.errors++;
	    }
	    else {
		time(&rsc_start);
	    }
	    break;

	case 'y':
	    use_localtime = 1;
	    break;

	case '?':
	default:
	    opts.errors++;
	    break;
	}
    }

    if (primary && pmcd_host != NULL) {
	pmprintf(
	    "%s: -P and -h are mutually exclusive; use -P only when running\n"
	    "%s on the same (local) host as the PMCD to which it connects.\n",
		pmProgname, pmProgname);
	opts.errors++;
    }

    if (!opts.errors && opts.optind != argc - 1) {
	pmprintf("%s: insufficient arguments\n", pmProgname);
	opts.errors++;
    }

    if (opts.errors) {
	pmUsageMessage(&opts);
	exit(1);
    }

    if (rsc_fd != -1 && note == NULL) {
	/* add default note to indicate running with -x */
	static char	xnote[10];
	snprintf(xnote, sizeof(xnote), "-x %d", rsc_fd);
	note = xnote;
    }

    /* if we are running as a daemon, change user early */
    if (isdaemon)
	__pmSetProcessIdentity(username);

    __pmOpenLog("pmlogger", logfile, stderr, &sts);
    if (sts != 1) {
	fprintf(stderr, "%s: Warning: log file (%s) creation failed\n", pmProgname, logfile);
	/* continue on ... writing to stderr */
    }

    /* base name for archive is here ... */
    archBase = argv[opts.optind];

    if (pmcd_host_conn == NULL)
	pmcd_host_conn = "local:";

    /* initialise access control */
    if (__pmAccAddOp(PM_OP_LOG_ADV) < 0 ||
	__pmAccAddOp(PM_OP_LOG_MAND) < 0 ||
	__pmAccAddOp(PM_OP_LOG_ENQ) < 0) {
	fprintf(stderr, "%s: access control initialisation failed\n", pmProgname);
	exit(1);
    }

    if (pmnsfile != PM_NS_DEFAULT) {
	if ((sts = pmLoadASCIINameSpace(pmnsfile, 1)) < 0) {
	    fprintf(stderr, "%s: Cannot load namespace from \"%s\": %s\n", pmProgname, pmnsfile, pmErrStr(sts));
	    exit(1);
	}
    }

    if ((ctx = pmNewContext(PM_CONTEXT_HOST, pmcd_host_conn)) < 0) {
	fprintf(stderr, "%s: Cannot connect to PMCD on host \"%s\": %s\n", pmProgname, pmcd_host_conn, pmErrStr(ctx));
	exit(1);
    }
    pmcd_host = (char *)pmGetContextHostName(ctx);
    if (strlen(pmcd_host) == 0) {
	fprintf(stderr, "%s: pmGetContextHostName(%d) failed\n",
	    pmProgname, ctx);
	exit(1);
    }

    if (rsc_fd == -1) {
	/* no -x, so register client id with pmcd */
	__pmSetClientIdArgv(argc, argv);
    }

    /*
     * discover fd for comms channel to PMCD ... 
     */
    if ((ctxp = __pmHandleToPtr(ctx)) == NULL) {
	fprintf(stderr, "%s: botch: __pmHandleToPtr(%d) returns NULL!\n", pmProgname, ctx);
	exit(1);
    }
    pmcdfd = ctxp->c_pmcd->pc_fd;
    PM_UNLOCK(ctxp->c_lock);

    if (configfile != NULL) {
	if ((yyin = fopen(configfile, "r")) == NULL) {
	    fprintf(stderr, "%s: Cannot open config file \"%s\": %s\n",
		pmProgname, configfile, osstrerror());
	    exit(1);
	}
    }
    else {
	/* **ANY** Lex would read from stdin automagically */
	configfile = "<stdin>";
    }

    __pmOptFetchGetParams(&ocp);
    ocp.c_scope = 1;
    __pmOptFetchPutParams(&ocp);

    /* prevent early timer events ... */
    __pmAFblock();

    if (yyparse() != 0)
	exit(1);
    if (configfile != NULL)
	fclose(yyin);
    yyend();

#ifdef PCP_DEBUG
    fprintf(stderr, "Config parsed\n");
#endif

    fprintf(stderr, "Starting %slogger for host \"%s\" via \"%s\"\n",
            primary ? "primary " : "", pmcd_host, pmcd_host_conn);

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_LOG) {
	fprintf(stderr, "optFetch Cost Parameters: pmid=%d indom=%d fetch=%d scope=%d\n",
		ocp.c_pmid, ocp.c_indom, ocp.c_fetch, ocp.c_scope);

	fprintf(stderr, "\nAfter loading config ...\n");
	for (tp = tasklist; tp != NULL; tp = tp->t_next) {
	    if (tp->t_numvalid == 0)
		continue;
	    fprintf(stderr, " state: %sin log, %savail, %s, %s",
		PMLC_GET_INLOG(tp->t_state) ? "" : "not ",
		PMLC_GET_AVAIL(tp->t_state) ? "" : "un",
		PMLC_GET_MAND(tp->t_state) ? "mand" : "adv",
		PMLC_GET_ON(tp->t_state) ? "on" : "off");
	    fprintf(stderr, " delta: %ld usec", 
			(long)1000 * tp->t_delta.tv_sec + tp->t_delta.tv_usec);
	    fprintf(stderr, " numpmid: %d\n", tp->t_numpmid);
	    for (i = 0; i < tp->t_numpmid; i++) {
		fprintf(stderr, "  %s (%s):\n", pmIDStr(tp->t_pmidlist[i]), tp->t_namelist[i]);
	    }
	    __pmOptFetchDump(stderr, tp->t_fetch);
	}
    }
#endif

    if (!primary && tasklist == NULL && !linger) {
	fprintf(stderr, "Nothing to log, and not the primary logger instance ... good-bye\n");
	exit(1);
    }

    if ((sts = __pmLogCreate(pmcd_host, archBase, archive_version, &logctl)) < 0) {
	fprintf(stderr, "__pmLogCreate: %s\n", pmErrStr(sts));
	exit(1);
    }
    else {
	/*
	 * try and establish $TZ from the remote PMCD ...
	 * Note the label record has been set up, but not written yet
	 */
	char		*name = "pmcd.timezone";
	pmID		pmid;
	pmResult	*resp;

	__pmtimevalNow(&epoch);
	sts = pmUseContext(ctx);

	if (sts >= 0)
	    sts = pmLookupName(1, &name, &pmid);
	if (sts >= 0)
	    sts = pmFetch(1, &pmid, &resp);
	if (sts >= 0) {
	    if (resp->vset[0]->numval > 0) { /* pmcd.timezone present */
		strcpy(logctl.l_label.ill_tz, resp->vset[0]->vlist[0].value.pval->vbuf);
		/* prefer to use remote time to avoid clock drift problems */
		epoch = resp->timestamp;		/* struct assignment */
		if (! use_localtime)
		    pmNewZone(logctl.l_label.ill_tz);
	    }
#ifdef PCP_DEBUG
	    else if (pmDebug & DBG_TRACE_LOG) {
		fprintf(stderr,
			"main: Could not get timezone from host %s\n",
			pmcd_host);
	    }
#endif
	    pmFreeResult(resp);
	}
    }

    /* do ParseTimeWindow stuff for -T */
    if (runtime) {
        struct timeval res_end;    /* time window end */
        struct timeval start;
        struct timeval end;
        struct timeval last_delta;
        char *err_msg;             /* parsing error message */
        time_t now;
        struct timeval now_tv;

        time(&now);
        now_tv.tv_sec = now;
        now_tv.tv_usec = 0; 

        start = now_tv;
        end.tv_sec = INT_MAX;
        end.tv_usec = INT_MAX;
        sts = __pmParseTime(runtime, &start, &end, &res_end, &err_msg);
        if (sts < 0) {
	    fprintf(stderr, "%s: illegal -T argument\n%s", pmProgname, err_msg);
            exit(1);
        }

        last_delta = res_end;
        tsub(&last_delta, &now_tv);
	__pmAFregister(&last_delta, NULL, run_done_callback);

        last_stamp = res_end;
    }

    fprintf(stderr, "Archive basename: %s\n", archBase);

#ifndef IS_MINGW
    /* detach yourself from the launching process */
    if (isdaemon)
        setpgid(getpid(), 0);
#endif

    /* set up control port */
    init_ports();
    __pmFD_ZERO(&fds);
    for (i = 0; i < CFD_NUM; ++i) {
	if (ctlfds[i] >= 0)
	    __pmFD_SET(ctlfds[i], &fds);
    }
#ifndef IS_MINGW
    __pmFD_SET(pmcdfd, &fds);
#endif
    if (rsc_fd != -1)
	__pmFD_SET(rsc_fd, &fds);
    numfds = maxfd() + 1;

    if ((sts = do_preamble()) < 0)
	fprintf(stderr, "Warning: problem writing archive preamble: %s\n",
	    pmErrStr(sts));

    sts = 0;		/* default exit status */

    parse_done = 1;	/* enable callback processing */
    __pmAFunblock();

    for ( ; ; ) {
	int		nready;

#ifdef PCP_DEBUG
	if ((pmDebug & DBG_TRACE_APPL2) && (pmDebug & DBG_TRACE_DESPERATE)) {
	    fprintf(stderr, "before __pmSelectRead(%d,...): run_done_alarm=%d vol_switch_alarm=%d log_alarm=%d\n", numfds, run_done_alarm, vol_switch_alarm, log_alarm);
	}
#endif

	niter = 0;
	while (log_alarm && niter++ < 10) {
	    __pmAFblock();
	    log_alarm = 0;
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_APPL2)
		fprintf(stderr, "delayed callback: log_alarm\n");
#endif
	    for (tp = tasklist; tp != NULL; tp = tp->t_next) {
		if (tp->t_alarm) {
		    tp->t_alarm = 0;
		    do_work(tp);
		}
	    }
	    __pmAFunblock();
	}

	if (vol_switch_alarm) {
	    __pmAFblock();
	    vol_switch_alarm = 0;
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_APPL2)
		fprintf(stderr, "delayed callback: vol_switch_alarm\n");
#endif
	    newvolume(VOL_SW_TIME);
	    __pmAFunblock();
	}

	if (run_done_alarm) {
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_APPL2)
		fprintf(stderr, "delayed callback: run_done_alarm\n");
#endif
	    run_done(0, NULL);
	    /*NOTREACHED*/
	}

	__pmFD_COPY(&readyfds, &fds);
	nready = __pmSelectRead(numfds, &readyfds, NULL);

#ifdef PCP_DEBUG
	if ((pmDebug & DBG_TRACE_APPL2) && (pmDebug & DBG_TRACE_DESPERATE)) {
	    fprintf(stderr, "__pmSelectRead(%d,...) done: nready=%d run_done_alarm=%d vol_switch_alarm=%d log_alarm=%d\n", numfds, nready, run_done_alarm, vol_switch_alarm, log_alarm);
	}
#endif

	__pmAFblock();
	if (nready > 0) {

	    /* handle request on control port */
	    for (i = 0; i < CFD_NUM; ++i) {
		if (ctlfds[i] >= 0 && __pmFD_ISSET(ctlfds[i], &readyfds)) {
		    if (control_req(ctlfds[i])) {
			/* new client has connected */
			__pmFD_SET(clientfd, &fds);
			if (clientfd >= numfds)
			    numfds = clientfd + 1;
		    }
		}
	    }
	    if (clientfd >= 0 && __pmFD_ISSET(clientfd, &readyfds)) {
		/* process request from client, save clientfd in case client
		 * closes connection, resetting clientfd to -1
		 */
		int	fd = clientfd;

		if (client_req()) {
		    /* client closed connection */
		    __pmFD_CLR(fd, &fds);
		    __pmCloseSocket(clientfd);
		    clientfd = -1;
		    numfds = maxfd() + 1;
		    qa_case = 0;
		}
	    }
#ifndef IS_MINGW
	    if (pmcdfd >= 0 && __pmFD_ISSET(pmcdfd, &readyfds)) {
		/*
		 * do not expect this, given synchronous commumication with the
		 * pmcd ... either pmcd has terminated, or bogus PDU ... or its
		 * Win32 and we are operating under the different conditions of
		 * our AF.c implementation there, which has to deal with a lack
		 * of signal support on Windows - race condition exists between
		 * this check and the async event timer callback.
		 */
		__pmPDU		*pb;
		__pmPDUHdr	*php;
		sts = __pmGetPDU(pmcdfd, ANY_SIZE, TIMEOUT_NEVER, &pb);
		if (sts <= 0) {
		    if (sts < 0)
			fprintf(stderr, "Error: __pmGetPDU: %s\n", pmErrStr(sts));
		    disconnect(sts);
		}
		else {
		    php = (__pmPDUHdr *)pb;
		    fprintf(stderr, "Error: Unsolicited %s PDU from PMCD\n",
			__pmPDUTypeStr(php->type));
		    disconnect(PM_ERR_IPC);
		}
		if (sts > 0)
		    __pmUnpinPDUBuf(pb);
	    }
#endif
	    if (rsc_fd >= 0 && __pmFD_ISSET(rsc_fd, &readyfds)) {
		/*
		 * some action on the recording session control fd
		 * end-of-file means launcher has quit, otherwise we
		 * expect one of these commands
		 *	V<number>\n	- version
		 *	F<folio>\n	- folio name
		 *	P<name>\n	- launcher's name
		 *	R\n		- launcher can replay
		 *	D\n		- detach from launcher
		 *	Q\n		- quit pmlogger
		 */
		char	rsc_buf[MAXPATHLEN];
		char	*rp = rsc_buf;
		char	myc;
		int	fake_x = 0;

		for (rp = rsc_buf; ; rp++) {
		    if (read(rsc_fd, &myc, 1) <= 0) {
#ifdef PCP_DEBUG
			if (pmDebug & DBG_TRACE_APPL2)
			    fprintf(stderr, "recording session control: eof\n");
#endif
			if (rp != rsc_buf) {
			    *rp = '\0';
			    fprintf(stderr, "Error: incomplete recording session control message: \"%s\"\n", rsc_buf);
			}
			fake_x = 1;
			break;
		    }
		    if (rp >= &rsc_buf[MAXPATHLEN]) {
			fprintf(stderr, "Error: absurd recording session control message: \"%100.100s ...\"\n", rsc_buf);
			fake_x = 1;
			break;
		    }
		    if (myc == '\n') {
			*rp = '\0';
			break;
		    }
		    *rp = myc;
		}

#ifdef PCP_DEBUG
		if (pmDebug & DBG_TRACE_APPL2) {
		    if (fake_x == 0)
			fprintf(stderr, "recording session control: \"%s\"\n", rsc_buf);
		}
#endif

		if (fake_x)
		    do_dialog('X');
		else if (strcmp(rsc_buf, "Q") == 0 ||
		         strcmp(rsc_buf, "D") == 0 ||
			 strcmp(rsc_buf, "?") == 0)
		    do_dialog(rsc_buf[0]);
		else if (rsc_buf[0] == 'F')
		    folio_name = strdup(&rsc_buf[1]);
		else if (rsc_buf[0] == 'P')
		    rsc_prog = strdup(&rsc_buf[1]);
		else if (strcmp(rsc_buf, "R") == 0)
		    rsc_replay = 1;
		else if (rsc_buf[0] == 'V' && rsc_buf[1] == '0') {
		    /*
		     * version 0 of the recording session control ...
		     * this is all we grok at the moment
		     */
		    ;
		}
		else {
		    fprintf(stderr, "Error: illegal recording session control message: \"%s\"\n", rsc_buf);
		    do_dialog('X');
		}
	    }
	}
	else if (vol_switch_flag) {
	    newvolume(VOL_SW_SIGHUP);
	    vol_switch_flag = 0;
	}
	else if (nready < 0 && neterror() != EINTR)
	    fprintf(stderr, "Error: select: %s\n", netstrerror());

	__pmAFunblock();

	if (target_pid && !__pmProcessExists(target_pid))
	    exit(EXIT_SUCCESS);

	if (exit_code)
	    break;
    }
    exit(exit_code);
}
Ejemplo n.º 12
0
int
newvolume(int vol_switch_type)
{
    FILE	*newfp;
    int		nextvol = logctl.l_curvol + 1;
    time_t	now;
    static char *vol_sw_strs[] = {
       "SIGHUP", "pmlc request", "sample counter",
       "sample byte size", "sample time", "max data volume size"
    };

    vol_samples_counter = 0;
    vol_bytes += ftell(logctl.l_mfp);
    if (exit_bytes != -1) {
        if (vol_bytes >= exit_bytes) 
	    run_done(0, "Byte limit reached");
    }

    /* 
     * If we are not part of a callback but instead a 
     * volume switch from "pmlc" or a "SIGHUP" then
     * get rid of pending volume switch in event queue
     * as it will now be wrong, and schedule a new
     * volume switch event.
     */
    if (vol_switch_afid >= 0 && vol_switch_type != VOL_SW_TIME) {
      __pmAFunregister(vol_switch_afid);
      vol_switch_afid = __pmAFregister(&vol_switch_time, NULL,
                                   vol_switch_callback);
    }

    if ((newfp = __pmLogNewFile(archBase, nextvol)) != NULL) {
	if (logctl.l_state == PM_LOG_STATE_NEW) {
	    /*
	     * nothing has been logged as yet, force out the label records
	     */
	    __pmtimevalNow(&last_stamp);
	    logctl.l_label.ill_start.tv_sec = (__int32_t)last_stamp.tv_sec;
	    logctl.l_label.ill_start.tv_usec = (__int32_t)last_stamp.tv_usec;
	    logctl.l_label.ill_vol = PM_LOG_VOL_TI;
	    __pmLogWriteLabel(logctl.l_tifp, &logctl.l_label);
	    logctl.l_label.ill_vol = PM_LOG_VOL_META;
	    __pmLogWriteLabel(logctl.l_mdfp, &logctl.l_label);
	    logctl.l_label.ill_vol = 0;
	    __pmLogWriteLabel(logctl.l_mfp, &logctl.l_label);
	    logctl.l_state = PM_LOG_STATE_INIT;
	}
#if 0
	if (last_stamp.tv_sec != 0) {
	    __pmTimeval	tmp;
	    tmp.tv_sec = (__int32_t)last_stamp.tv_sec;
	    tmp.tv_usec = (__int32_t)last_stamp.tv_usec;
	    __pmLogPutIndex(&logctl, &tmp);
	}
#endif
	fclose(logctl.l_mfp);
	logctl.l_mfp = newfp;
	logctl.l_label.ill_vol = logctl.l_curvol = nextvol;
	__pmLogWriteLabel(logctl.l_mfp, &logctl.l_label);
	time(&now);
	fprintf(stderr, "New log volume %d, via %s at %s",
		nextvol, vol_sw_strs[vol_switch_type], ctime(&now));
	return nextvol;
    }
    else
	return -oserror();
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
0
Archivo: AF.c Proyecto: tongfw/pcp
static void
onalarm(int dummy)
{
    struct timeval	now;
    struct timeval	tmp;
    struct timeval	interval;
    qelt		*qp;

    if (!block)
	AFhold();

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_AF) {
	__pmtimevalNow(&now);
	__pmPrintStamp(stderr, &now);
	fprintf(stderr, " AFonalarm(%d)\n", dummy);
    }
#endif
    if (root != NULL) {
	/* something to do ... */
	while (root != NULL) {
	    /* compute difference between scheduled time and now */
	    __pmtimevalNow(&now);
	    tmp = root->q_when;
	    tsub(&tmp, &now);
	    if (tmp.tv_sec == 0 && tmp.tv_usec <= 10000) {
		/*
		 * within one 10msec tick, the time has passed for this one,
		 * execute the callback and reschedule
		 */

		qp = root;
		root = root->q_next;
#ifdef PCP_DEBUG
		if (pmDebug & DBG_TRACE_AF) {
		    __pmPrintStamp(stderr, &now);
		    fprintf(stderr, " AFcallback " PRINTF_P_PFX "%p(%d, " PRINTF_P_PFX "%p)\n",
			    qp->q_func, qp->q_afid, qp->q_data);
		}
#endif
		qp->q_func(qp->q_afid, qp->q_data);
             
		if (qp->q_delta.tv_sec == 0 && qp->q_delta.tv_usec == 0) {
		    /*
		     * if delta is zero, this is a single-shot event,
		     * so do not reschedule it
		     */
		    free(qp);
		}
		else {
		    /*
		     * avoid falling too far behind
		     * if the scheduled time is more than q_delta in the
		     * past we will never catch up ... better to skip some
		     * events to catch up ...
		     *
		     * <------------ next q_when range ----------------->
		     *
		     *      cannot catchup | may catchup   | on schedule
		     *                     |               |
		     * --------------------|---------------|------------> time
		     *                     |               |
		     *      		   |               +-- now
		     *      		   +-- now - q_delta
		     */
		    __pmtimevalNow(&now);
		    for ( ; ; ) {
			tadd(&qp->q_when, &qp->q_delta);
			tmp = qp->q_when;
			tsub_real(&tmp, &now);
			tadd(&tmp, &qp->q_delta);
			if (tmp.tv_sec >= 0)
			    break;
#ifdef PCP_DEBUG
			if (pmDebug & DBG_TRACE_AF) {
			    __pmPrintStamp(stderr, &now);
			    fprintf(stderr, " AFcallback event %d too slow, skip callback for ", qp->q_afid);
			    __pmPrintStamp(stderr, &qp->q_when);
			    fputc('\n', stderr);
			}
#endif
		    }
		    enqueue(qp);
		}
	    }
	    else
		/*
		 * head of the queue (and hence all others) are too far in
		 * the future ... done for this time
		 */
		break;
	}

	if (root == NULL) {
	    pmprintf("Warning: AF event queue is empty, nothing more will be scheduled\n");
	    pmflush();
	}
	else {
	    /* set itimer for head of queue */
	    interval = root->q_when;
	    __pmtimevalNow(&now);
	    tsub(&interval, &now);
	    if (interval.tv_sec == 0 && interval.tv_usec < MIN_ITIMER_USEC)
		/* use minimal delay (platform dependent) */
		interval.tv_usec = MIN_ITIMER_USEC;
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_AF) {
		__pmPrintStamp(stderr, &now);
		fprintf(stderr, " AFsetitimer for delta ");
		printdelta(stderr, &interval);
		fputc('\n', stderr);
	    }
#endif
	    AFsetitimer(&interval);
	}
    }
    if (!block) {
	AFrearm();
	AFrelse();
    }
}
Ejemplo n.º 15
0
Archivo: trace.c Proyecto: tongfw/pcp
int
pmtracebegin(const char *tag)
{
    static int		first = 1;
    _pmTraceLibdata	*hptr;
    _pmTraceLibdata	hash;
    int			len, a_sts = 0, b_sts = 0, protocol;

    if (tag == NULL || *tag == '\0')
	return PMTRACE_ERR_TAGNAME;
    if ((len = strlen(tag)+1) >= MAXTAGNAMELEN)
	return PMTRACE_ERR_TAGLENGTH;

    hash.tag = (char *)tag;
    hash.taglength = len;
    hash.id = _pmtraceid();
    hash.tracetype = TRACE_TYPE_TRANSACT;

    /*
     * We need to do both the connect and hash table manipulation,
     * otherwise the reconnect isn't reliable and the hash table 
     * (potentially) becomes completely wrong, and we reject some
     * transact calls which actually were in a valid call sequence.
     */

    protocol = __pmtraceprotocol(TRACE_PROTOCOL_QUERY);

    if (_pmtimedout && (a_sts = _pmtraceconnect(1)) < 0) {
	if (first || protocol == TRACE_PROTOCOL_ASYNC)
	    return a_sts;	/* exception to the rule */
	a_sts = _pmtraceremaperr(a_sts);
	if (a_sts == PMTRACE_ERR_IPC && protocol == TRACE_PROTOCOL_SYNC) {
	    _pmtimedout = 1;	/* try reconnect */
	    a_sts = 0;
	}
    }
    if (a_sts >= 0)
	first = 0;

    /* lock hash table for search and subsequent insert/update */
    TRACE_LOCK;

    if ((hptr = __pmhashlookup(&_pmtable, tag, &hash)) == NULL) {
#ifdef PMTRACE_DEBUG
	if (__pmstate & PMTRACE_STATE_API)
	    fprintf(stderr, "pmtracebegin: new transaction '%s' "
			    "(id=0x%" PRIx64 ")\n", tag, hash.id);
#endif
	hash.pad = 0;
	if ((hash.tag = strdup(tag)) == NULL)
	    b_sts = -oserror();
	__pmtimevalNow(&hash.start);
	if (b_sts >= 0) {
	    hash.inprogress = 1;
	    b_sts = __pmhashinsert(&_pmtable, tag, &hash);
	}
	if (b_sts < 0 && hash.tag != NULL)
	    free(hash.tag);
    }
    else if (hptr->inprogress == 1)
	b_sts = PMTRACE_ERR_INPROGRESS;
    else if (hptr->tracetype != TRACE_TYPE_TRANSACT)
	b_sts = PMTRACE_ERR_TAGTYPE;
    else {
#ifdef PMTRACE_DEBUG
    if (__pmstate & PMTRACE_STATE_API)
	fprintf(stderr, "pmtracebegin: updating transaction '%s' "
			"(id=0x%" PRIx64 ")\n", tag, hash.id);
#endif
	__pmtimevalNow(&hptr->start);
	hptr->inprogress = 1;
    }

    /* unlock hash table */
    if (TRACE_UNLOCK != 0)
	b_sts = -oserror();

    if (a_sts < 0)
	return a_sts;
    return b_sts;
}
Ejemplo n.º 16
0
Archivo: dopdu.c Proyecto: aeppert/pcp
/*
 * sendstatus
 */
static int
sendstatus(void)
{
    int				rv;
    int				end;
    int				version;
    static int			firsttime = 1;
    static char			*tzlogger;
    struct timeval		now;

    if (firsttime) {
        tzlogger = __pmTimezone();
	firsttime = 0;
    }

    if ((version = __pmVersionIPC(clientfd)) < 0)
	return version;

    if (version >= LOG_PDU_VERSION2) {
	__pmLoggerStatus		ls;

	if ((ls.ls_state = logctl.l_state) == PM_LOG_STATE_NEW)
	    ls.ls_start.tv_sec = ls.ls_start.tv_usec = 0;
	else
	    memcpy(&ls.ls_start, &logctl.l_label.ill_start, sizeof(ls.ls_start));
	memcpy(&ls.ls_last, &last_stamp, sizeof(ls.ls_last));
	__pmtimevalNow(&now);
	ls.ls_timenow.tv_sec = (__int32_t)now.tv_sec;
	ls.ls_timenow.tv_usec = (__int32_t)now.tv_usec;
	ls.ls_vol = logctl.l_curvol;
	ls.ls_size = ftell(logctl.l_mfp);
	assert(ls.ls_size >= 0);

	/* be careful of buffer size mismatches when copying strings */
	end = sizeof(ls.ls_hostname) - 1;
	strncpy(ls.ls_hostname, logctl.l_label.ill_hostname, end);
	ls.ls_hostname[end] = '\0';
        /* BTW, that string should equal pmcd_host[]. */

        /* NB: FQDN cleanup: there is no such thing as 'the fully
           qualified domain name' of a server: it may have several or
           none; the set may have changed since the time the log
           archive was collected.  Now that we store the then-current
           pmcd.hostname in the ill_hostname (and thus get it reported
           in ls_hostname), we could pass something else informative
           in the ls_fqdn slot.  Namely, pmcd_host_conn[], which is the
           access path pmlogger's using to get to the pmcd. */
	end = sizeof(ls.ls_fqdn) - 1;
        strncpy(ls.ls_fqdn, pmcd_host_conn, end);
	ls.ls_fqdn[end] = '\0';

	end = sizeof(ls.ls_tz) - 1;
	strncpy(ls.ls_tz, logctl.l_label.ill_tz, end);
	ls.ls_tz[end] = '\0';
	end = sizeof(ls.ls_tzlogger) - 1;
	if (tzlogger != NULL)
	    strncpy(ls.ls_tzlogger, tzlogger, end);
	else
	    end = 0;
	ls.ls_tzlogger[end] = '\0';

	rv = __pmSendLogStatus(clientfd, &ls);
    }
    else
	rv = PM_ERR_IPC;
    return rv;
}
Ejemplo n.º 17
0
Archivo: trace.c Proyecto: tongfw/pcp
int
pmtraceend(const char *tag)
{
    _pmTraceLibdata	hash;
    _pmTraceLibdata	*hptr;
    struct timeval	now;
    int			len, protocol, sts = 0;

    if (tag == NULL || *tag == '\0')
	return PMTRACE_ERR_TAGNAME;
    if ((len = strlen(tag)+1) >= MAXTAGNAMELEN)
	return PMTRACE_ERR_TAGLENGTH;

    __pmtimevalNow(&now);

    /* give just enough info for comparison routine */
    hash.tag = (char *)tag;
    hash.taglength = len;
    hash.id = _pmtraceid();
    hash.tracetype = TRACE_TYPE_TRANSACT;

    /* lock hash table for search and update then send data */
    TRACE_LOCK;

    if ((hptr = __pmhashlookup(&_pmtable, tag, &hash)) == NULL)
	sts = PMTRACE_ERR_NOSUCHTAG;
    else if (hptr->inprogress != 1)
	sts = PMTRACE_ERR_NOPROGRESS;
    else if (hptr->tracetype != TRACE_TYPE_TRANSACT)
	sts = PMTRACE_ERR_TAGTYPE;
    else {
#ifdef PMTRACE_DEBUG
    if (__pmstate & PMTRACE_STATE_API)
	fprintf(stderr, "pmtraceend: sending transaction data '%s' "
			"(id=0x%" PRIx64 ")\n", tag, hash.id);
#endif
	hptr->inprogress = 0;
	hptr->data = __pmtracetvsub(&now, &hptr->start);

	if (sts >= 0 && _pmtimedout) {
	    sts = _pmtracereconnect();
	    sts = _pmtraceremaperr(sts);
	}

	if (sts >= 0) {
	    sts = __pmtracesenddata(__pmfd, hptr->tag, hptr->taglength,
					TRACE_TYPE_TRANSACT, hptr->data);
	    sts = _pmtraceremaperr(sts);
	}

	protocol = __pmtraceprotocol(TRACE_PROTOCOL_QUERY);

	if (sts >= 0 && protocol == TRACE_PROTOCOL_SYNC)
	    sts = _pmtracegetack(sts, TRACE_TYPE_TRANSACT);

	if (sts == PMTRACE_ERR_IPC && protocol == TRACE_PROTOCOL_SYNC) {
	    _pmtimedout = 1;	/* try reconnect */
	    sts = 0;
	}
    }

    if (TRACE_UNLOCK != 0)
	return -oserror();

    return sts;
}