summaryrefslogtreecommitdiff
path: root/src/pmdas/solaris/solaris.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2014-10-26 12:33:50 +0400
committerIgor Pashev <pashev.igor@gmail.com>2014-10-26 12:33:50 +0400
commit47e6e7c84f008a53061e661f31ae96629bc694ef (patch)
tree648a07f3b5b9d67ce19b0fd72e8caa1175c98f1a /src/pmdas/solaris/solaris.c
downloadpcp-debian/3.9.10.tar.gz
Debian 3.9.10debian/3.9.10debian
Diffstat (limited to 'src/pmdas/solaris/solaris.c')
-rw-r--r--src/pmdas/solaris/solaris.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/src/pmdas/solaris/solaris.c b/src/pmdas/solaris/solaris.c
new file mode 100644
index 0000000..2deb6fd
--- /dev/null
+++ b/src/pmdas/solaris/solaris.c
@@ -0,0 +1,216 @@
+/*
+ * Solaris PMDA
+ *
+ * Collect performance data from the Solaris kernel using kstat() for
+ * the most part.
+ *
+ * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2010 Max Matveev. 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 <time.h>
+#include <sys/time.h>
+#include "common.h"
+
+static int _isDSO = 1;
+static char mypath[MAXPATHLEN];
+
+/*
+ * wrapper for pmdaFetch which primes the methods ready for
+ * the next fetch
+ * ... real callback is fetch_callback()
+ */
+static int
+solaris_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda)
+{
+ int i;
+
+ kstat_ctl_needs_update();
+
+ for (i = 0; i < methodtab_sz; i++) {
+ methodtab[i].m_fetched = 0;
+ }
+
+ return pmdaFetch(numpmid, pmidlist, resp, pmda);
+}
+
+/*
+ * callback provided to pmdaFetch
+ */
+static int
+solaris_fetch_callback(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom)
+{
+ metricdesc_t *mdp = (metricdesc_t *)mdesc->m_user;
+ int cluster = pmid_cluster(mdesc->m_desc.pmid);
+ method_t *m = methodtab + cluster;
+ hrtime_t start;
+ int rv;
+ __pmID_int *id = __pmid_int(&mdesc->m_desc.pmid);
+
+ if (cluster == 4095) {
+ switch (id->item) {
+ case 0: /* pmda.prefetch.time */
+ if ((inst <= 0) || (inst > methodtab_sz+1))
+ return PM_ERR_INST;
+ atom->ull = methodtab[inst-1].m_elapsed;
+ return 1;
+ case 1: /* pmda.prefetch.count */
+ if ((inst <= 0) || (inst > methodtab_sz+1))
+ return PM_ERR_INST;
+ atom->ull = methodtab[inst-1].m_hits;
+ return 1;
+ case 2: /* pmda.metric.time */
+ if ((inst <= 0) || (inst > metrictab_sz+1))
+ return PM_ERR_INST;
+ atom->ull = metricdesc[inst-1].md_elapsed;
+ return 1;
+ case 3: /* pmda.metric.count */
+ if ((inst <= 0) || (inst > metrictab_sz+1))
+ return PM_ERR_INST;
+ atom->ull = metricdesc[inst-1].md_hits;
+ return 1;
+ default:
+ return PM_ERR_PMID;
+ }
+ } else if (cluster >= methodtab_sz) {
+ return PM_ERR_PMID;
+ }
+
+ if (!m->m_fetched && m->m_prefetch) {
+ start = gethrtime();
+ m->m_prefetch();
+ m->m_elapsed = gethrtime() - start;
+ m->m_hits++;
+ m->m_fetched = 1;
+ }
+ start = gethrtime();
+ rv = m->m_fetch(mdesc, inst, atom);
+ mdp->md_elapsed = gethrtime() - start;
+ mdp->md_hits++;
+ return rv;
+}
+
+/*
+ * Initialise the agent (both daemon and DSO).
+ */
+void
+__PMDA_INIT_CALL
+solaris_init(pmdaInterface *dp)
+{
+ if (_isDSO) {
+ int sep = __pmPathSeparator();
+ snprintf(mypath, sizeof(mypath), "%s%c" "solaris" "%c" "help",
+ pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
+ pmdaDSO(dp, PMDA_INTERFACE_3, "Solaris DSO", mypath);
+ }
+
+ if (dp->status != 0)
+ return;
+
+ dp->version.two.fetch = solaris_fetch;
+ pmdaSetFetchCallBack(dp, solaris_fetch_callback);
+ init_data(dp->domain);
+ pmdaInit(dp, indomtab, indomtab_sz, metrictab, metrictab_sz);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage: %s [options]\n\n", pmProgname);
+ fputs("Options:\n"
+ " -d domain use domain (numeric) for metrics domain of PMDA\n"
+ " -l logfile write log into logfile rather than using default log name\n"
+ " -N namespace verify consistency of internal metrics with the namespace\n",
+ stderr);
+ exit(1);
+}
+
+static void
+checkname(const char *mname)
+{
+ int i;
+ for (i = 0; i < metrictab_sz; i++) {
+ if (strcmp(mname, metricdesc[i].md_name) == 0)
+ return;
+ }
+ printf ("Cannot find %s in the code\n", mname);
+}
+
+/*
+ * Set up the agent if running as a daemon.
+ */
+int
+main(int argc, char **argv)
+{
+ int err = 0;
+ int sep = __pmPathSeparator();
+ pmdaInterface desc;
+ int c;
+ char *namespace = NULL;
+
+ _isDSO = 0;
+ __pmSetProgname(argv[0]);
+
+ snprintf(mypath, sizeof(mypath), "%s%c" "solaris" "%c" "help",
+ pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
+ pmdaDaemon(&desc, PMDA_INTERFACE_3, pmProgname, SOLARIS,
+ "solaris.log", mypath);
+
+ while ((c = pmdaGetOpt(argc, argv, "N:D:d:l:?", &desc, &err)) != EOF) {
+ switch (c) {
+ case 'N':
+ namespace = optarg;
+ break;
+ default:
+ err++;
+ break;
+ }
+ }
+ if (err)
+ usage();
+
+ if (namespace) {
+ if (pmLoadNameSpace(namespace))
+ exit(1);
+
+ for (c = 0; c < metrictab_sz; c++) {
+ char *name;
+ int e;
+ __pmID_int *id = __pmid_int(&metricdesc[c].md_desc.pmid);
+ id->domain = desc.domain;
+
+ if ((e = pmNameID(metricdesc[c].md_desc.pmid, &name)) != 0) {
+ printf ("Cannot find %s(%s) in %s: %s\n",
+ metricdesc[c].md_name,
+ pmIDStr(metricdesc[c].md_desc.pmid),
+ namespace, pmErrStr(e));
+ } else {
+ if (strcmp(name, metricdesc[c].md_name)) {
+ printf ("%s is %s in the %s but %s in code\n",
+ pmIDStr(metricdesc[c].md_desc.pmid),
+ name, namespace,metricdesc[c].md_name);
+ }
+ }
+ }
+
+ pmTraversePMNS("", checkname);
+ exit (0);
+ }
+
+ pmdaOpenLog(&desc);
+ solaris_init(&desc);
+ pmdaConnect(&desc);
+ pmdaMain(&desc);
+
+ exit(0);
+}