summaryrefslogtreecommitdiff
path: root/src/pmlogger/src/fetch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmlogger/src/fetch.c')
-rw-r--r--src/pmlogger/src/fetch.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/pmlogger/src/fetch.c b/src/pmlogger/src/fetch.c
new file mode 100644
index 0000000..05e0378
--- /dev/null
+++ b/src/pmlogger/src/fetch.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2013 Red Hat.
+ * Copyright (c) 1995 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * Thread-safe note
+ *
+ * myFetch() returns a PDU buffer that is pinned from _pmGetPDU() or
+ * __pmEncodeResult() and this needs to be unpinned by the myFetch()
+ * caller when safe to do so.
+ */
+
+#include "logger.h"
+
+int
+myFetch(int numpmid, pmID pmidlist[], __pmPDU **pdup)
+{
+ int n = 0;
+ int ctx;
+ __pmPDU *pb;
+ __pmContext *ctxp;
+
+ if (numpmid < 1)
+ return PM_ERR_TOOSMALL;
+
+ if ((ctx = pmWhichContext()) >= 0) {
+ ctxp = __pmHandleToPtr(ctx);
+ if (ctxp == NULL)
+ return PM_ERR_NOCONTEXT;
+ if (ctxp->c_type != PM_CONTEXT_HOST) {
+ PM_UNLOCK(ctxp->c_lock);
+ return PM_ERR_NOTHOST;
+ }
+ }
+ else
+ return PM_ERR_NOCONTEXT;
+
+#if CAN_RECONNECT
+ if (ctxp->c_pmcd->pc_fd == -1) {
+ /* lost connection, try to get it back */
+ n = reconnect();
+ if (n < 0) {
+ PM_UNLOCK(ctxp->c_lock);
+ return n;
+ }
+ }
+#endif
+
+ if (ctxp->c_sent == 0) {
+ /*
+ * current profile is _not_ already cached at other end of
+ * IPC, so send current profile
+ */
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_PROFILE)
+ fprintf(stderr, "myFetch: calling __pmSendProfile, context: %d\n", ctx);
+#endif
+ if ((n = __pmSendProfile(ctxp->c_pmcd->pc_fd, FROM_ANON, ctx, ctxp->c_instprof)) >= 0)
+ ctxp->c_sent = 1;
+ }
+
+ if (n >= 0) {
+ int newcnt;
+ pmID *newlist = NULL;
+ int have_dm;
+
+ /* for derived metrics, may need to rewrite the pmidlist */
+ have_dm = newcnt = __pmPrepareFetch(ctxp, numpmid, pmidlist, &newlist);
+ if (newcnt > numpmid) {
+ /* replace args passed into myFetch */
+ numpmid = newcnt;
+ pmidlist = newlist;
+ }
+
+ n = __pmSendFetch(ctxp->c_pmcd->pc_fd, FROM_ANON, ctx, &ctxp->c_origin, numpmid, pmidlist);
+ if (n >= 0){
+ int changed = 0;
+ do {
+ n = __pmGetPDU(ctxp->c_pmcd->pc_fd, ANY_SIZE, TIMEOUT_DEFAULT, &pb);
+ /*
+ * expect PDU_RESULT or
+ * PDU_ERROR(changed > 0)+PDU_RESULT or
+ * PDU_ERROR(real error < 0 from PMCD) or
+ * 0 (end of file)
+ * < 0 (local error or IPC problem)
+ * other (bogus PDU)
+ */
+ if (n == PDU_RESULT) {
+ /*
+ * Success with a pmResult in a pdubuf.
+ *
+ * Need to process derived metrics, if any.
+ * This is ugly, we need to decode the pdubuf, rebuild
+ * the pmResult and encode back into a pdubuf ... the
+ * fastpath of not doing all of this needs to be
+ * preserved in the common case where derived metrics
+ * are not being logged.
+ */
+ if (have_dm) {
+ pmResult *result;
+ __pmPDU *npb;
+ int sts;
+ if ((sts = __pmDecodeResult(pb, &result)) < 0) {
+ n = sts;
+ }
+ else {
+ __pmFinishResult(ctxp, sts, &result);
+ if ((sts = __pmEncodeResult(ctxp->c_pmcd->pc_fd, result, &npb)) < 0)
+ n = sts;
+ else {
+ /* using PDU with derived metrics */
+ __pmUnpinPDUBuf(pb);
+ *pdup = npb;
+ }
+ }
+ }
+ else
+ *pdup = pb;
+ }
+ else if (n == PDU_ERROR) {
+ __pmDecodeError(pb, &n);
+ if (n > 0) {
+ /* PMCD state change protocol */
+ changed = n;
+ n = 0;
+ }
+ else {
+ fprintf(stderr, "myFetch: ERROR PDU: %s\n", pmErrStr(n));
+ disconnect(PM_ERR_IPC);
+ }
+ __pmUnpinPDUBuf(pb);
+ }
+ else if (n == 0) {
+ fprintf(stderr, "myFetch: End of File: PMCD exited?\n");
+ disconnect(PM_ERR_IPC);
+ }
+ else if (n < 0) {
+ fprintf(stderr, "myFetch: __pmGetPDU: Error: %s\n", pmErrStr(n));
+ disconnect(PM_ERR_IPC);
+ }
+ else {
+ fprintf(stderr, "myFetch: Unexpected %s PDU from PMCD\n", __pmPDUTypeStr(n));
+ disconnect(PM_ERR_IPC);
+ __pmUnpinPDUBuf(pb);
+ }
+ } while (n == 0);
+
+ if (changed & PMCD_ADD_AGENT) {
+ /*
+ * PMCD_DROP_AGENT does not matter, no values are returned.
+ * Trying to restart (PMCD_RESTART_AGENT) is less interesting
+ * than when we actually start (PMCD_ADD_AGENT) ... the latter
+ * is also set when a successful restart occurs, but more
+ * to the point the sequence Install-Remove-Install does
+ * not involve a restart ... it is the second Install that
+ * generates the second PMCD_ADD_AGENT that we need to be
+ * particularly sensitive to, as this may reset counter
+ * metrics ...
+ */
+ int sts;
+ if ((sts = putmark()) < 0) {
+ fprintf(stderr, "putmark: %s\n", pmErrStr(sts));
+ exit(1);
+ }
+ }
+ }
+ if (newlist != NULL)
+ free(newlist);
+ }
+
+ if (n < 0 && ctxp->c_pmcd->pc_fd != -1) {
+ disconnect(n);
+ }
+
+ PM_UNLOCK(ctxp->c_lock);
+ return n;
+}