summaryrefslogtreecommitdiff
path: root/src/pmdas/summary/summary.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdas/summary/summary.c')
-rw-r--r--src/pmdas/summary/summary.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/src/pmdas/summary/summary.c b/src/pmdas/summary/summary.c
new file mode 100644
index 0000000..a3da84a
--- /dev/null
+++ b/src/pmdas/summary/summary.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 1995,2003 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.
+ */
+
+#include <ctype.h>
+#include <signal.h>
+#include "pmapi.h"
+#include "impl.h"
+#include "pmda.h"
+#include "summary.h"
+#include "domain.h"
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+int nmeta;
+meta_t *meta;
+pmResult *cachedResult;
+static int *freeList;
+
+static int
+summary_desc(pmID pmid, pmDesc *desc, pmdaExt * ex)
+{
+ static int i=0;
+
+ if ( i < nmeta && pmid == meta[i].desc.pmid) {
+found:
+ if (meta[i].desc.type == PM_TYPE_NOSUPPORT)
+ return PM_ERR_AGAIN; /* p76 rules ok */
+ *desc = meta[i].desc; /* struct assignment */
+ return 0; /* success */
+ }
+
+ for (i = 0; i < nmeta; i++) {
+ if (pmid == meta[i].desc.pmid)
+ goto found;
+ }
+ return PM_ERR_PMID;
+}
+
+void
+service_client(__pmPDU *pb)
+{
+ int n;
+ int i;
+ int j;
+ pmDesc desc;
+ pmDesc foundDesc;
+ pmResult *resp;
+ pmValueSet *vsp;
+ __pmPDUHdr *ph = (__pmPDUHdr *)pb;
+
+ switch (ph->type) {
+
+ case PDU_DESC:
+ if ((n = __pmDecodeDesc(pb, &desc)) < 0) {
+ fprintf(stderr, "service_client: __pmDecodeDesc failed: %s\n",
+ pmErrStr(n));
+ exit(1);
+ }
+
+ if (desc.indom != PM_INDOM_NULL) {
+ fprintf(stderr, "service_client: Warning: ignored desc for pmid=%s: indom is not singular\n", pmIDStr(desc.pmid));
+ return;
+ }
+
+ if (summary_desc(desc.pmid, &foundDesc, NULL) == 0) {
+ /* already in table */
+ fprintf(stderr,
+ "service_client: Warning: duplicate desc for pmid=%s\n",
+ pmIDStr(desc.pmid));
+ return;
+ }
+
+ nmeta++;
+ if ((meta = (meta_t *)realloc(meta, nmeta * sizeof(meta_t))) == NULL) {
+ __pmNoMem("service_client: meta realloc", nmeta * sizeof(meta_t), PM_FATAL_ERR);
+ }
+ memcpy(&meta[nmeta-1].desc, &desc, sizeof(pmDesc));
+
+ break;
+
+ case PDU_RESULT:
+ if ((n = __pmDecodeResult(pb, &resp)) < 0) {
+ fprintf(stderr, "service_client: __pmDecodeResult failed: %s\n", pmErrStr(n));
+ exit(1);
+ }
+
+ if (cachedResult == NULL) {
+ int need;
+ need = (int)sizeof(pmResult) - (int)sizeof(pmValueSet *);
+ if ((cachedResult = (pmResult *)malloc(need)) == NULL) {
+ __pmNoMem("service_client: result malloc", need, PM_FATAL_ERR);
+ }
+ cachedResult->numpmid = 0;
+ }
+
+ /*
+ * swap values from resp with those in cachedResult, expanding
+ * cachedResult if there are metrics we've not seen before
+ */
+ for (i = 0; i < resp->numpmid; i++) {
+ for (j = 0; j < cachedResult->numpmid; j++) {
+ if (resp->vset[i]->pmid == cachedResult->vset[j]->pmid) {
+ /* found matching PMID, update this value */
+ break;
+ }
+ }
+
+ if (j == cachedResult->numpmid) {
+ /* new PMID, expand cachedResult and initialize vset */
+ int need;
+ cachedResult->numpmid++;
+ need = (int)sizeof(pmResult) +
+ (cachedResult->numpmid-1) * (int)sizeof(pmValueSet *);
+ if ((cachedResult = (pmResult *)realloc(cachedResult, need)) == NULL) {
+ __pmNoMem("service_client: result realloc", need, PM_FATAL_ERR);
+ }
+ if ((cachedResult->vset[j] = (pmValueSet *)malloc(sizeof(pmValueSet))) == NULL) {
+ __pmNoMem("service_client: vset[]", sizeof(pmValueSet), PM_FATAL_ERR);
+ }
+ cachedResult->vset[j]->pmid = resp->vset[i]->pmid;
+ cachedResult->vset[j]->numval = 0;
+ }
+
+ /*
+ * swap vsets
+ */
+ vsp = cachedResult->vset[j];
+ cachedResult->vset[j] = resp->vset[i];
+ resp->vset[i] = vsp;
+
+ }
+
+ pmFreeResult(resp);
+ break;
+
+ case PDU_ERROR:
+ if ((n = __pmDecodeError(pb, &i)) < 0) {
+ fprintf(stderr, "service_client: __pmDecodeError failed: %s\n", pmErrStr(n));
+ exit(1);
+ }
+ fprintf(stderr, "service_client: Error PDU! %s\n", pmErrStr(i));
+ break;
+
+ default:
+ fprintf(stderr, "service_client: Bogus PDU type %d\n", ph->type);
+ exit(1);
+ }
+}
+
+static int
+summary_profile(__pmProfile *prof, pmdaExt * ex)
+{
+ /*
+ * doesn't make sense since summary metrics
+ * always have a singular instance domain.
+ */
+ return 0;
+}
+
+static int
+summary_instance(pmInDom indom, int inst, char *name, __pmInResult **result,
+ pmdaExt * ex)
+{
+ return PM_ERR_INDOM;
+}
+
+static void
+freeResultCallback(pmResult *res)
+{
+ int i;
+
+ /*
+ * pmResult has now been sent to pmcd. Only free the
+ * value sets that had no values available because
+ * the valid ones were reused from the cachedResult.
+ */
+ for (i=0; i < res->numpmid; i++) {
+ if (freeList[i])
+ free(res->vset[i]);
+ }
+ return;
+}
+
+
+static int
+summary_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt * ex)
+{
+ int i; /* over pmidlist[] */
+ int j; /* over vset->vlist[] */
+ int sts;
+ int need;
+ int validpmid;
+ pmID pmid;
+ pmDesc desc;
+ static pmResult *res = NULL;
+ static int maxnpmids = 0;
+
+ if (numpmid > maxnpmids) {
+ maxnpmids = numpmid;
+ if (res != NULL)
+ free(res);
+ /* (numpmid - 1) because there's room for one valueSet in a pmResult */
+ need = sizeof(pmResult) + (numpmid - 1) * sizeof(pmValueSet *);
+ if ((res = (pmResult *)malloc(need)) == NULL)
+ return -oserror();
+
+ if (freeList != NULL)
+ free(freeList);
+ if ((freeList = (int *)malloc(numpmid * sizeof(int))) == NULL)
+ return -oserror();
+ }
+ res->timestamp.tv_sec = 0;
+ res->timestamp.tv_usec = 0;
+ res->numpmid = numpmid;
+
+ for (i = 0; i < numpmid; i++) {
+ pmid = pmidlist[i];
+
+ /*
+ * do we know about the descriptor for this pmid?
+ * If not, then the error is PM_ERR_PMID
+ * regardless of whether there is an entry in
+ * the cached result.
+ */
+ sts = summary_desc(pmid, &desc, NULL);
+ validpmid = (sts == 0);
+
+ res->vset[i] = NULL;
+ freeList[i] = 1;
+
+ if (validpmid && cachedResult != NULL) {
+ for (j=0; j < cachedResult->numpmid; j++) {
+ if (pmid == cachedResult->vset[j]->pmid) {
+ res->vset[i] = cachedResult->vset[j];
+ freeList[i] = 0;
+ break;
+ }
+ }
+ }
+
+ if (!validpmid || res->vset[i] == NULL) {
+ /* no values available or the metric has no descriptor */
+ if ((res->vset[i] = (pmValueSet *)malloc(sizeof(pmValueSet))) == NULL)
+ return -oserror();
+ res->vset[i]->pmid = pmid;
+ res->vset[i]->valfmt = PM_VAL_INSITU;
+ res->vset[i]->numval = validpmid ? PM_ERR_VALUE : sts;
+ }
+ }
+ *resp = res;
+
+ return numpmid;
+}
+
+static int
+summary_store(pmResult *result, pmdaExt * ex)
+{
+ return PM_ERR_PERMISSION;
+}
+
+void
+summary_init(pmdaInterface *dp)
+{
+ void (*callback)() = freeResultCallback;
+
+ dp->version.two.profile = summary_profile;
+ dp->version.two.fetch = summary_fetch;
+ dp->version.two.desc = summary_desc;
+ dp->version.two.instance = summary_instance;
+ dp->version.two.store = summary_store;
+
+ mainLoopFreeResultCallback(callback);
+
+ pmdaInit(dp, NULL, 0, NULL, 0);
+}
+
+void
+summary_done(void)
+{
+ int st;
+
+ fprintf(stderr, "summary agent pid=%" FMT_PID " done\n", getpid());
+ kill(clientPID, SIGINT);
+ waitpid(clientPID, &st, 0);
+}