diff options
Diffstat (limited to 'src/pmdas/aix')
-rw-r--r-- | src/pmdas/aix/GNUmakefile | 69 | ||||
-rw-r--r-- | src/pmdas/aix/aix.c | 127 | ||||
-rw-r--r-- | src/pmdas/aix/common.h | 104 | ||||
-rw-r--r-- | src/pmdas/aix/cpu.c | 186 | ||||
-rw-r--r-- | src/pmdas/aix/cpu_total.c | 133 | ||||
-rw-r--r-- | src/pmdas/aix/data.c | 435 | ||||
-rw-r--r-- | src/pmdas/aix/disk.c | 189 | ||||
-rw-r--r-- | src/pmdas/aix/disk_total.c | 127 | ||||
-rw-r--r-- | src/pmdas/aix/help | 61 | ||||
-rw-r--r-- | src/pmdas/aix/netif.c | 190 | ||||
-rw-r--r-- | src/pmdas/aix/pmns.disk | 22 | ||||
-rw-r--r-- | src/pmdas/aix/pmns.hinv | 6 | ||||
-rw-r--r-- | src/pmdas/aix/pmns.kernel | 77 | ||||
-rw-r--r-- | src/pmdas/aix/pmns.mem | 2 | ||||
-rw-r--r-- | src/pmdas/aix/pmns.network | 26 | ||||
-rw-r--r-- | src/pmdas/aix/root | 20 |
16 files changed, 1774 insertions, 0 deletions
diff --git a/src/pmdas/aix/GNUmakefile b/src/pmdas/aix/GNUmakefile new file mode 100644 index 0000000..9282d76 --- /dev/null +++ b/src/pmdas/aix/GNUmakefile @@ -0,0 +1,69 @@ +# +# Copyright (c) 2000,2003,2004 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. +# + +TOPDIR = ../../.. +include $(TOPDIR)/src/include/builddefs + +IAM = aix +DOMAIN = AIX +CMDTARGET = pmdaaix +LIBTARGET = pmda_aix.so +PMDADIR = $(PCP_PMDAS_DIR)/$(IAM) +CONF_LINE = "aix 80 dso aix_init $(PMDADIR)/$(LIBTARGET)" + +CFILES = aix.c data.c disk_total.c disk.c cpu_total.c cpu.c netif.c + +LLDLIBS = $(PCP_PMDALIB) -lperfstat +PMNS = pmns.disk pmns.kernel pmns.mem pmns.network pmns.hinv +LSRCFILES = $(PMNS) help root common.h + +LDIRT = *.log *.dir *.pag root_aix domain.h + +default: build-me + +ifeq "$(TARGET_OS)" "aix" +build-me: common.h root_aix domain.h $(CMDTARGET) $(LIBTARGET) help.dir help.pag + @if [ `grep -c $(CONF_LINE) ../pmcd.conf` -eq 0 ]; then \ + echo $(CONF_LINE) >> ../pmcd.conf ; \ + fi + +install: build-me + $(INSTALL) -m 755 -d $(PMDADIR) + $(INSTALL) -m 644 domain.h help.dir help.pag $(PMDADIR) + $(INSTALL) -m 755 $(LIBTARGET) $(CMDTARGET) $(PMDADIR) + $(INSTALL) -m 644 root_aix $(PCP_VAR_DIR)/pmns/root_aix +else +build-me: +install: +endif + +$(OBJECTS): common.h + +include $(BUILDRULES) + +default_pcp : default + +install_pcp : install + +help.dir help.pag: help root_aix + $(RUN_IN_BUILD_ENV) $(TOPDIR)/src/newhelp/newhelp -n root_aix -v 2 -o help < help + +root_aix: ../../pmns/stdpmid + rm -f root_aix + sed -e 's;<stdpmid>;"../../pmns/stdpmid";' <root \ + | $(RUN_IN_BUILD_ENV) $(TOPDIR)/src/pmcpp/pmcpp \ + | sed -e '/^#/d' -e '/^$$/d' >root_aix + +domain.h: ../../pmns/stdpmid + $(DOMAIN_MAKERULE) diff --git a/src/pmdas/aix/aix.c b/src/pmdas/aix/aix.c new file mode 100644 index 0000000..335aacd --- /dev/null +++ b/src/pmdas/aix/aix.c @@ -0,0 +1,127 @@ +/* + * AIX PMDA + * + * Collect performance data from the AIX kernel using libperfstat for + * the most part. + * + * Copyright (c) 2012,2014 Red Hat. + * Copyright (c) 2004 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 <time.h> +#include "common.h" + +static int _isDSO = 1; +static char mypath[MAXPATHLEN]; +static char *username; + +/* + * wrapper for pmdaFetch which primes the methods ready for + * the next fetch + * ... real callback is fetch_callback() + */ +static int +aix_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda) +{ + int i; + + // TODO: this should only fetch metrics from "pmidlist" + for (i = 0; i < methodtab_sz; i++) { + methodtab[i].m_prefetch(); + } + + return pmdaFetch(numpmid, pmidlist, resp, pmda); +} + +/* + * callback provided to pmdaFetch + */ +static int +aix_fetch_callback(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom) +{ + metricdesc_t *mdp; + + mdp = (metricdesc_t *)mdesc->m_user; + return methodtab[mdp->md_method].m_fetch(mdesc, inst, atom); +} + +/* + * Initialise the agent (both daemon and DSO). + */ +void +aix_init(pmdaInterface *dp) +{ + if (_isDSO) { + int sep = __pmPathSeparator(); + snprintf(mypath, sizeof(mypath), "%s%c" "aix" "%c" "help", + pmGetConfig("PCP_PMDAS_DIR"), sep, sep); + pmdaDSO(dp, PMDA_INTERFACE_3, "AIX DSO", mypath); + } else { + __pmSetProcessIdentity(username); + } + + if (dp->status != 0) + return; + + dp->version.two.fetch = aix_fetch; + pmdaSetFetchCallBack(dp, aix_fetch_callback); + init_data(dp->domain); + pmdaInit(dp, indomtab, indomtab_sz, metrictab, metrictab_sz); +} + +pmLongOptions longopts[] = { + PMDA_OPTIONS_HEADER("Options"), + PMOPT_DEBUG, + PMDAOPT_DOMAIN, + PMDAOPT_LOGFILE, + PMDAOPT_USERNAME, + PMOPT_HELP, + PMDA_OPTIONS_END +}; + +pmdaOptions opts = { + .short_options = "D:d:l:U:?", + .long_options = longopts, +}; + +/* + * Set up the agent if running as a daemon. + */ +int +main(int argc, char **argv) +{ + int sep = __pmPathSeparator(); + pmdaInterface desc; + + _isDSO = 0; + __pmSetProgname(argv[0]); + __pmGetUsername(&username); + + snprintf(mypath, sizeof(mypath), "%s%c" "aix" "%c" "help", + pmGetConfig("PCP_PMDAS_DIR"), sep, sep); + pmdaDaemon(&desc, PMDA_INTERFACE_3, pmProgname, AIX, "aix.log", mypath); + + pmdaGetOptions(argc, argv, &opts, &desc); + if (opts.errors) { + pmdaUsageMessage(&opts); + exit(1); + } + if (opts.username) + username = opts.username; + + pmdaOpenLog(&desc); + aix_init(&desc); + pmdaConnect(&desc); + pmdaMain(&desc); + exit(0); +} diff --git a/src/pmdas/aix/common.h b/src/pmdas/aix/common.h new file mode 100644 index 0000000..604ff73 --- /dev/null +++ b/src/pmdas/aix/common.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2004 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "pmapi.h" +#include "impl.h" +#include "pmda.h" +#include "./domain.h" + +typedef long long longlong_t; // TODO nuke for AIX +typedef unsigned long long u_longlong_t; // TODO nuke for AIX build +typedef unsigned char uchar; // TODO nuke for AIX build + +#include <libperfstat.h> + +/* + * libperfstat method controls + * + * md_method choices (see below) ... must be contiguous integers so + * we can index directly into method[] + */ +#define M_CPU_TOTAL 0 +#define M_CPU 1 +#define M_DISK_TOTAL 2 +#define M_DISK 3 +#define M_NETIF 4 +#define M_NETBUF 5 // TODO +#define M_PROTO 6 // TODO +#define M_MEM_TOTAL 7 // TODO + +/* + * special values for offset + */ +#define OFF_NOVALUES -2 +#define OFF_DERIVED -1 + +typedef struct { + void (*m_init)(int); + void (*m_prefetch)(void); + int (*m_fetch)(pmdaMetric *, int, pmAtomValue *); +} method_t; + +extern method_t methodtab[]; +extern int methodtab_sz; + +extern void init_data(int); + +extern void cpu_total_init(int); +extern void cpu_total_prefetch(void); +extern int cpu_total_fetch(pmdaMetric *, int, pmAtomValue *); + +extern void cpu_init(int); +extern void cpu_prefetch(void); +extern int cpu_fetch(pmdaMetric *, int, pmAtomValue *); + +extern void disk_total_init(int); +extern void disk_total_prefetch(void); +extern int disk_total_fetch(pmdaMetric *, int, pmAtomValue *); + +extern void disk_init(int); +extern void disk_prefetch(void); +extern int disk_fetch(pmdaMetric *, int, pmAtomValue *); + +extern void netif_init(int); +extern void netif_prefetch(void); +extern int netif_fetch(pmdaMetric *, int, pmAtomValue *); + +/* + * metric descriptions + */ +typedef struct { + pmDesc md_desc; // PMDA's idea of the semantics + int md_method; // specific stats method + int md_offset; // offset into stats structure +} metricdesc_t; + +extern metricdesc_t metricdesc[]; +extern pmdaMetric *metrictab; +extern int metrictab_sz; + +#define DISK_INDOM 0 +#define CPU_INDOM 1 +#define NETIF_INDOM 2 + +extern pmdaIndom indomtab[]; +extern int indomtab_sz; diff --git a/src/pmdas/aix/cpu.c b/src/pmdas/aix/cpu.c new file mode 100644 index 0000000..98d3348 --- /dev/null +++ b/src/pmdas/aix/cpu.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2004 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 "common.h" + +static int ncpu; +static int ncpu_alloc; +static int *fetched; +static perfstat_cpu_t *cpustat; + +void +cpu_init(int first) +{ + perfstat_id_t id; + int i; + + if (!first) + /* TODO ... not sure if/when we'll use this re-init hook */ + return; + + ncpu = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0); + if ((fetched = (int *)malloc(ncpu * sizeof(int))) == NULL) { + fprintf(stderr, "cpu_init: fetched malloc[%d] failed: %s\n", + ncpu * sizeof(int), osstrerror()); + exit(1); + } + if ((cpustat = (perfstat_cpu_t *)malloc(ncpu * sizeof(perfstat_cpu_t))) == NULL) { + fprintf(stderr, "cpu_init: cpustat malloc[%d] failed: %s\n", + ncpu * sizeof(perfstat_cpu_t), osstrerror()); + exit(1); + } + ncpu_alloc = ncpu; + + /* + * set up instance domain + */ + strcpy(id.name, ""); + ncpu = perfstat_cpu(&id, cpustat, sizeof(perfstat_cpu_t), ncpu_alloc); + + indomtab[CPU_INDOM].it_numinst = ncpu; + indomtab[CPU_INDOM].it_set = (pmdaInstid *)malloc(ncpu * sizeof(pmdaInstid)); + if (indomtab[CPU_INDOM].it_set == NULL) { + fprintf(stderr, "cpu_init: indomtab malloc[%d] failed: %s\n", + ncpu * sizeof(pmdaInstid), osstrerror()); + exit(1); + } + for (i = 0; i < ncpu; i++) { + indomtab[CPU_INDOM].it_set[i].i_inst = i; + indomtab[CPU_INDOM].it_set[i].i_name = strdup(cpustat[i].name); + } + +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "cpu_init: ncpu=%d\n", ncpu); + } +#endif +} + +void +cpu_prefetch(void) +{ + int i; + + for (i = 0; i < ncpu_alloc; i++) + fetched[i] = 0; +} + +static __uint64_t +cpu_derived(pmdaMetric *mdesc, int inst) +{ + pmID pmid; + __pmID_int *ip = (__pmID_int *)&pmid; + __uint64_t val; + + pmid = mdesc->m_desc.pmid; + ip->domain = 0; + + switch (pmid) { + + default: + fprintf(stderr, "cpu_derived: Botch: no method for pmid %s\n", + pmIDStr(mdesc->m_desc.pmid)); + val = 0; + break; + } + +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "cpu_derived: pmid %s inst %d val %llu\n", + pmIDStr(mdesc->m_desc.pmid), inst, val); + } +#endif + + return val; +} + +int +cpu_fetch(pmdaMetric *mdesc, int inst, pmAtomValue *atom) +{ + int offset; + + if (fetched[inst] == 0) { + int sts; + int i; + perfstat_id_t id; + + strcpy(id.name, ""); + sts = perfstat_cpu(&id, cpustat, sizeof(perfstat_cpu_t), ncpu_alloc); + + /* TODO ... + * - if sts != ncpu, the number of CPUs has changed, need to set + * fetched[i] to -1 for the missing ones + * - is sts > ncpu possible? worse, if the number of cpus is > + * ncpu_alloc what should we do? + * - possibly reshape the instance domain? + * - error handling? + */ + + for (i = 0; i < ncpu; i++) { + fetched[i] = 1; + } + } + + if (fetched[inst] != 1) + return 0; + + offset = ((metricdesc_t *)mdesc->m_user)->md_offset; + if (offset == OFF_NOVALUES) + return 0; + + if (mdesc->m_desc.type == PM_TYPE_U64) { + if (offset == OFF_DERIVED) + atom->ull = cpu_derived(mdesc, inst); + else { + __uint64_t *ullp; + ullp = (__uint64_t *)&((char *)&cpustat[inst])[offset]; + atom->ull = *ullp; + } + if (mdesc->m_desc.units.scaleTime == PM_TIME_MSEC) { + /* assumed to be CPU time */ + atom->ull *= 1000 / HZ; + } +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "cpu_fetch: pmid %s inst %d val %llu\n", + pmIDStr(mdesc->m_desc.pmid), inst, atom->ull); + } +#endif + } + else { + if (offset == OFF_DERIVED) + atom->ul = (__uint32_t)cpu_derived(mdesc, inst); + else { + __uint32_t *ulp; + ulp = (__uint32_t *)&((char *)&cpustat[inst])[offset]; + atom->ul = *ulp; + } + if (mdesc->m_desc.units.scaleTime == PM_TIME_MSEC) { + /* assumed to be CPU time */ + atom->ul *= 1000 / HZ; + } +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "cpu_fetch: pmid %s inst %d val %lu\n", + pmIDStr(mdesc->m_desc.pmid), inst, atom->ul); + } +#endif + } + + return 1; +} diff --git a/src/pmdas/aix/cpu_total.c b/src/pmdas/aix/cpu_total.c new file mode 100644 index 0000000..bf3d118 --- /dev/null +++ b/src/pmdas/aix/cpu_total.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2004 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 "common.h" +#include <sys/m_param.h> + +static perfstat_cpu_total_t cpustat; +static int fetched; + +void +cpu_total_init(int first) +{ + if (!first) + /* TODO ... not sure if/when we'll use this re-init hook */ + return; +} + +void +cpu_total_prefetch(void) +{ + int i; + + fetched = 0; +} + +static __uint64_t +cpu_total_derived(pmdaMetric *mdesc, int inst) +{ + pmID pmid; + __pmID_int *ip = (__pmID_int *)&pmid; + __uint64_t val; + + pmid = mdesc->m_desc.pmid; + ip->domain = 0; + + switch (pmid) { + + default: + fprintf(stderr, "cpu_total_derived: Botch: no method for pmid %s\n", + pmIDStr(mdesc->m_desc.pmid)); + val = 0; + break; + } + +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "cpu_total_derived: pmid %s inst %d val %llu\n", + pmIDStr(mdesc->m_desc.pmid), inst, val); + } +#endif + + return val; +} + +int +cpu_total_fetch(pmdaMetric *mdesc, int inst, pmAtomValue *atom) +{ + int offset; + + if (fetched == 0) { + int sts; + sts = perfstat_cpu_total(NULL, &cpustat, sizeof(perfstat_cpu_total_t), 1); + if (sts != 1) { + /* TODO - how to find/decode errors? */ + fprintf(stderr, "perfstat_cpu_total: failed %s\n", osstrerror()); + fetched = -1; + } + else + fetched = 1; + } + + if (fetched != 1) + return 0; + + offset = ((metricdesc_t *)mdesc->m_user)->md_offset; + if (offset == OFF_NOVALUES) + return 0; + + if (mdesc->m_desc.type == PM_TYPE_U64) { + if (offset == OFF_DERIVED) + atom->ull = cpu_total_derived(mdesc, inst); + else { + __uint64_t *ullp; + ullp = (__uint64_t *)&((char *)&cpustat)[offset]; + atom->ull = *ullp; + } + if (mdesc->m_desc.units.scaleTime == PM_TIME_MSEC) { + /* assumed to be CPU time */ + atom->ull *= 1000 / HZ; + } +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "cpu_total_fetch: pmid %s inst %d val %llu\n", + pmIDStr(mdesc->m_desc.pmid), inst, atom->ull); + } +#endif + } + else { + if (offset == OFF_DERIVED) + atom->ul = (__uint32_t)cpu_total_derived(mdesc, inst); + else { + __uint32_t *ulp; + ulp = (__uint32_t *)&((char *)&cpustat)[offset]; + atom->ul = *ulp; + } + if (mdesc->m_desc.units.scaleTime == PM_TIME_MSEC) { + /* assumed to be CPU time */ + atom->ul *= 1000 / HZ; + } +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "cpu_total_fetch: pmid %s inst %d val %lu\n", + pmIDStr(mdesc->m_desc.pmid), inst, atom->ul); + } +#endif + } + + return 1; +} diff --git a/src/pmdas/aix/data.c b/src/pmdas/aix/data.c new file mode 100644 index 0000000..6198e78 --- /dev/null +++ b/src/pmdas/aix/data.c @@ -0,0 +1,435 @@ +/* + * Data structures that define metrics and control the AIX PMDA + * + * Copyright (c) 2004 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 "common.h" +#include <ctype.h> + +/* + * List of instance domains ... we expect the *_INDOM macros + * to index into this table. + */ +pmdaIndom indomtab[] = { + { DISK_INDOM, 0, NULL }, + { CPU_INDOM, 0, NULL }, + { NETIF_INDOM, 0, NULL } +}; +int indomtab_sz = sizeof(indomtab) / sizeof(indomtab[0]); + +pmdaMetric *metrictab; + +method_t methodtab[] = { + { cpu_total_init, cpu_total_prefetch, cpu_total_fetch }, // M_CPU_TOTAL + { cpu_init, cpu_prefetch, cpu_fetch }, // M_CPU + { disk_total_init, disk_total_prefetch, disk_total_fetch }, // M_DISK_TOTAL + { disk_init, disk_prefetch, disk_fetch }, // M_DISK + { netif_init, netif_prefetch, netif_fetch } // M_NETIF + // M_NETBUF - TODO + // M_PROTO - TODO + // M_MEM_TOTAL - TODO +}; +int methodtab_sz = sizeof(methodtab) / sizeof(methodtab[0]); + +#define CPU_OFF(field) ((int)&((perfstat_cpu_t *)0)->field) +#define CPU_TOTAL_OFF(field) ((int)&((perfstat_cpu_total_t *)0)->field) +#define DISK_OFF(field) ((int)&((perfstat_disk_t *)0)->field) +#define DISK_TOTAL_OFF(field) ((int)&((perfstat_disk_total_t *)0)->field) +#define NETIF_OFF(field) ((int)&((perfstat_netinterface_t *)0)->field) + +/* + * all metrics supported in this PMDA - one table entry for each metric + */ +metricdesc_t metricdesc[] = { + +/* kernel.all.cpu.idle */ + { { PMDA_PMID(0,0), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(idle) }, + +/* kernel.all.cpu.user */ + { { PMDA_PMID(0,1), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(user) }, + +/* kernel.all.cpu.sys */ + { { PMDA_PMID(0,2), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(sys) }, + +/* kernel.all.cpu.wait.total */ + { { PMDA_PMID(0,3), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(wait) }, + +/* kernel.percpu.cpu.idle */ + { { PMDA_PMID(0,4), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU, CPU_OFF(idle) }, + +/* kernel.percpu.cpu.user */ + { { PMDA_PMID(0,5), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU, CPU_OFF(user) }, + +/* kernel.percpu.cpu.sys */ + { { PMDA_PMID(0,6), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU, CPU_OFF(sys) }, + +/* kernel.percpu.cpu.wait.total */ + { { PMDA_PMID(0,7), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU, CPU_OFF(wait) }, + +/* kernel.all.readch */ + { { PMDA_PMID(0,8), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(readch) }, + +/* kernel.all.writech */ + { { PMDA_PMID(0,9), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(readch) }, + +/* kernel.all.io.softintrs */ + { { PMDA_PMID(0,10), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(softintrs) }, + +/* kernel.percpu.readch */ + { { PMDA_PMID(0,11), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU, CPU_OFF(readch) }, + +/* kernel.percpu.writech */ + { { PMDA_PMID(0,12), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU, CPU_OFF(writech) }, + +/* kernel.percpu.cpu.intr */ + { { PMDA_PMID(0,13), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU, OFF_NOVALUES }, + +/* kernel.all.io.bread */ + { { PMDA_PMID(0,14), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(bread) }, + +/* kernel.all.io.bwrite */ + { { PMDA_PMID(0,15), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(bwrite) }, + +/* kernel.all.io.lread */ + { { PMDA_PMID(0,16), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(lread) }, + +/* kernel.all.io.lwrite */ + { { PMDA_PMID(0,17), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(lwrite) }, + +/* kernel.percpu.io.bread */ + { { PMDA_PMID(0,18), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU, CPU_OFF(bread) }, + +/* kernel.percpu.io.bwrite */ + { { PMDA_PMID(0,19), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU, CPU_OFF(bwrite) }, + +/* kernel.percpu.io.lread */ + { { PMDA_PMID(0,20), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU, CPU_OFF(lread) }, + +/* kernel.percpu.io.lwrite */ + { { PMDA_PMID(0,21), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU, CPU_OFF(lwrite) }, + +/* kernel.all.syscall */ + { { PMDA_PMID(0,22), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(syscall) }, + +/* kernel.all.pswitch */ + { { PMDA_PMID(0,23), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(pswitch) }, + +/* kernel.percpu.syscall */ + { { PMDA_PMID(0,24), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU, CPU_OFF(syscall) }, + +/* kernel.percpu.pswitch */ + { { PMDA_PMID(0,25), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU, CPU_OFF(pswitch) }, + +/* kernel.all.io.phread */ + { { PMDA_PMID(0,26), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(phread) }, + +/* kernel.all.io.phwrite */ + { { PMDA_PMID(0,27), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(phwrite) }, + +/* kernel.all.io.devintrs */ + { { PMDA_PMID(0,28), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(devintrs) }, + +/* kernel.percpu.io.phread */ + { { PMDA_PMID(0,29), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU, CPU_OFF(phread) }, + +/* kernel.percpu.io.phwrite */ + { { PMDA_PMID(0,30), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU, CPU_OFF(phwrite) }, + +/* kernel.all.cpu.intr */ + { { PMDA_PMID(0,31), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_MSEC, 0) + }, M_CPU_TOTAL, OFF_NOVALUES }, + +/* kernel.all.trap */ + { { PMDA_PMID(0,32), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(traps) }, + +/* kernel.all.sysexec */ + { { PMDA_PMID(0,33), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(sysexec) }, + +/* kernel.all.sysfork */ + { { PMDA_PMID(0,34), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(sysfork) }, + +/* kernel.all.io.namei */ + { { PMDA_PMID(0,35), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(namei) }, + +/* kernel.all.sysread */ + { { PMDA_PMID(0,36), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(sysread) }, + +/* kernel.all.syswrite */ + { { PMDA_PMID(0,37), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(syswrite) }, + +/* hinv.ncpu_cfg */ + { { PMDA_PMID(0,38), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(ncpus_cfg) }, + +/* kernel.percpu.sysexec */ + { { PMDA_PMID(0,39), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU, CPU_OFF(sysexec) }, + +/* kernel.percpu.sysfork */ + { { PMDA_PMID(0,40), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU, CPU_OFF(sysfork) }, + +/* kernel.percpu.io.namei */ + { { PMDA_PMID(0,41), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU, CPU_OFF(namei) }, + +/* kernel.percpu.sysread */ + { { PMDA_PMID(0,42), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU, CPU_OFF(sysread) }, + +/* kernel.percpu.syswrite */ + { { PMDA_PMID(0,43), PM_TYPE_U64, CPU_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU, CPU_OFF(syswrite) }, + +/* disk.all.read -- not available */ + { { PMDA_PMID(0,44), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_DISK_TOTAL, OFF_NOVALUES }, + +/* disk.all.write -- not available */ + { { PMDA_PMID(0,45), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_DISK_TOTAL, OFF_NOVALUES }, + +/* disk.all.total */ + { { PMDA_PMID(0,46), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_DISK_TOTAL, DISK_TOTAL_OFF(xfers) }, + +/* disk.all.read_bytes */ + { { PMDA_PMID(0,47), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0) + }, M_DISK_TOTAL, DISK_TOTAL_OFF(rblks) }, + +/* disk.all.write_bytes */ + { { PMDA_PMID(0,48), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0) + }, M_DISK_TOTAL, DISK_TOTAL_OFF(wblks) }, + +/* disk.all.total_bytes */ + { { PMDA_PMID(0,49), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0) + }, M_DISK_TOTAL, OFF_DERIVED }, + +/* disk.dev.read -- not available */ + { { PMDA_PMID(0,50), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_DISK, OFF_NOVALUES }, + +/* disk.dev.write -- not available */ + { { PMDA_PMID(0,51), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_DISK, OFF_NOVALUES }, + +/* disk.dev.total */ + { { PMDA_PMID(0,52), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_DISK, DISK_OFF(xfers) }, + +/* disk.dev.read_bytes */ + { { PMDA_PMID(0,53), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0) + }, M_DISK, DISK_OFF(rblks) }, + +/* disk.dev.write_bytes */ + { { PMDA_PMID(0,54), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0) + }, M_DISK, DISK_OFF(wblks) }, + +/* disk.dev.total_bytes */ + { { PMDA_PMID(0,55), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_MBYTE, 0, 0) + }, M_DISK, OFF_DERIVED }, + +/* hinv.ncpu */ + { { PMDA_PMID(0,56), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_CPU_TOTAL, CPU_TOTAL_OFF(ncpus) }, + +/* hinv.ndisk */ + { { PMDA_PMID(0,57), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_DISK_TOTAL, DISK_TOTAL_OFF(number) }, + +/* hinv.nnetif */ + { { PMDA_PMID(0,58), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_NETIF, OFF_DERIVED }, + +/* network.interface.in.packets */ + { { PMDA_PMID(0,59), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_NETIF, NETIF_OFF(ipackets) }, + +/* network.interface.in.bytes */ + { { PMDA_PMID(0,60), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) + }, M_NETIF, NETIF_OFF(ibytes) }, + +/* network.interface.in.errors */ + { { PMDA_PMID(0,61), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_NETIF, NETIF_OFF(ierrors) }, + +/* network.interface.out.packets */ + { { PMDA_PMID(0,62), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_NETIF, NETIF_OFF(opackets) }, + +/* network.interface.out.bytes */ + { { PMDA_PMID(0,63), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) + }, M_NETIF, NETIF_OFF(obytes) }, + +/* network.interface.out.errors */ + { { PMDA_PMID(0,64), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_NETIF, NETIF_OFF(oerrors) }, + +/* network.interface.total.packets */ + { { PMDA_PMID(0,65), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE, + PMDA_PMUNITS(0, 0, 1, 0, 0, PM_COUNT_ONE) + }, M_NETIF, OFF_DERIVED }, + +/* network.interface.total.bytes */ + { { PMDA_PMID(0,66), PM_TYPE_U64, NETIF_INDOM, PM_SEM_DISCRETE, + PMDA_PMUNITS(1, 0, 0, PM_SPACE_BYTE, 0, 0) + }, M_NETIF, OFF_DERIVED } + +/* remember to add trailing comma before adding more entries ... */ +}; +int metrictab_sz = sizeof(metricdesc) / sizeof(metricdesc[0]); + +void +init_data(int domain) +{ + int i; + int serial; + __pmID_int *ip; + __pmInDom_int *iip; + + /* + * Create the PMDA's metrictab[] version of the per-metric table. + * + * Also do domain initialization for each pmid and indom element of + * the metricdesc[] table ... the PMDA table is fixed up in + * libpcp_pmda + */ + if ((metrictab = (pmdaMetric *)malloc(metrictab_sz * sizeof(pmdaMetric))) == NULL) { + fprintf(stderr, "init_data: Error: malloc metrictab [%d] failed: %s\n", + metrictab_sz * sizeof(pmdaMetric), osstrerror()); + exit(1); + } + for (i = 0; i < metrictab_sz; i++) { + metrictab[i].m_user = &metricdesc[i]; + metrictab[i].m_desc = metricdesc[i].md_desc; + ip = (__pmID_int *)&metricdesc[i].md_desc.pmid; + ip->domain = domain; + if (metricdesc[i].md_desc.indom != PM_INDOM_NULL) { + serial = metricdesc[i].md_desc.indom; + iip = (__pmInDom_int *)&metricdesc[i].md_desc.indom; + iip->serial = serial; + iip->pad = 0; + iip->domain = domain; + } + } + + /* + * initialize each of the methods + */ + for (i = 0; i < methodtab_sz; i++) { + methodtab[i].m_init(1); + } +} diff --git a/src/pmdas/aix/disk.c b/src/pmdas/aix/disk.c new file mode 100644 index 0000000..5ab52d6 --- /dev/null +++ b/src/pmdas/aix/disk.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2004 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 "common.h" + +static int ndisk; +static int ndisk_alloc; +static int *fetched; +static perfstat_disk_t *diskstat; + +void +disk_init(int first) +{ + perfstat_id_t id; + int i; + + if (!first) + /* TODO ... not sure if/when we'll use this re-init hook */ + return; + + ndisk = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0); + if ((fetched = (int *)malloc(ndisk * sizeof(int))) == NULL) { + fprintf(stderr, "disk_init: fetched malloc[%d] failed: %s\n", + ndisk * sizeof(int), osstrerror()); + exit(1); + } + if ((diskstat = (perfstat_disk_t *)malloc(ndisk * sizeof(perfstat_disk_t))) == NULL) { + fprintf(stderr, "disk_init: diskstat malloc[%d] failed: %s\n", + ndisk * sizeof(perfstat_disk_t), osstrerror()); + exit(1); + } + ndisk_alloc = ndisk; + + /* + * set up instance domain + */ + strcpy(id.name, ""); + ndisk = perfstat_disk(&id, diskstat, sizeof(perfstat_disk_t), ndisk_alloc); + + indomtab[DISK_INDOM].it_numinst = ndisk; + indomtab[DISK_INDOM].it_set = (pmdaInstid *)malloc(ndisk * sizeof(pmdaInstid)); + if (indomtab[DISK_INDOM].it_set == NULL) { + fprintf(stderr, "disk_init: indomtab malloc[%d] failed: %s\n", + ndisk * sizeof(pmdaInstid), osstrerror()); + exit(1); + } + for (i = 0; i < ndisk; i++) { + indomtab[DISK_INDOM].it_set[i].i_inst = i; + indomtab[DISK_INDOM].it_set[i].i_name = strdup(diskstat[i].name); + } + +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "disk_init: ndisk=%d\n", ndisk); + } +#endif +} + +void +disk_prefetch(void) +{ + int i; + + for (i = 0; i < ndisk_alloc; i++) + fetched[i] = 0; +} + +static __uint64_t +disk_derived(pmdaMetric *mdesc, int inst) +{ + pmID pmid; + __pmID_int *ip = (__pmID_int *)&pmid; + __uint64_t val; + + pmid = mdesc->m_desc.pmid; + ip->domain = 0; + + switch (pmid) { + case PMDA_PMID(0,55): /* disk.dev.total_bytes */ + val = diskstat[inst].rblks + diskstat[inst].wblks; + break; + + default: + fprintf(stderr, "disk_derived: Botch: no method for pmid %s\n", + pmIDStr(mdesc->m_desc.pmid)); + val = 0; + break; + } + +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "disk_derived: pmid %s inst %d val %llu\n", + pmIDStr(mdesc->m_desc.pmid), inst, val); + } +#endif + + return val; +} + +int +disk_fetch(pmdaMetric *mdesc, int inst, pmAtomValue *atom) +{ + int offset; + + if (fetched[inst] == 0) { + int sts; + int i; + perfstat_id_t id; + + strcpy(id.name, ""); + sts = perfstat_disk(&id, diskstat, sizeof(perfstat_disk_t), ndisk_alloc); + + /* TODO ... + * - if sts != ndisk, the number of disks has changed, need to set + * fetched[i] to -1 for the missing ones + * - is sts > ndisk possible? worse, if the number of disks is > + * ndisk_alloc what should we do? + * - possibly reshape the instance domain? + * - error handling? + */ + + for (i = 0; i < ndisk; i++) { + fetched[i] = 1; + } + } + + if (fetched[inst] != 1) + return 0; + + offset = ((metricdesc_t *)mdesc->m_user)->md_offset; + if (offset == OFF_NOVALUES) + return 0; + + if (mdesc->m_desc.type == PM_TYPE_U64) { + if (offset == OFF_DERIVED) + atom->ull = disk_derived(mdesc, inst); + else { + __uint64_t *ullp; + ullp = (__uint64_t *)&((char *)&diskstat[inst])[offset]; + atom->ull = *ullp; + } + if (mdesc->m_desc.units.scaleTime == PM_TIME_MSEC) { + /* assumed to be CPU time */ + atom->ull *= 1000 / HZ; + } +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "disk_fetch: pmid %s inst %d val %llu\n", + pmIDStr(mdesc->m_desc.pmid), inst, atom->ull); + } +#endif + } + else { + if (offset == OFF_DERIVED) + atom->ul = (__uint32_t)disk_derived(mdesc, inst); + else { + __uint32_t *ulp; + ulp = (__uint32_t *)&((char *)&diskstat[inst])[offset]; + atom->ul = *ulp; + } + if (mdesc->m_desc.units.scaleTime == PM_TIME_MSEC) { + /* assumed to be CPU time */ + atom->ul *= 1000 / HZ; + } +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "disk_fetch: pmid %s inst %d val %lu\n", + pmIDStr(mdesc->m_desc.pmid), inst, atom->ul); + } +#endif + } + + return 1; +} diff --git a/src/pmdas/aix/disk_total.c b/src/pmdas/aix/disk_total.c new file mode 100644 index 0000000..1087d74 --- /dev/null +++ b/src/pmdas/aix/disk_total.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2004 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 "common.h" + +static perfstat_disk_total_t diskstat; +static int fetched; + +void +disk_total_init(int first) +{ + if (!first) + /* TODO ... not sure if/when we'll use this re-init hook */ + return; +} + +void +disk_total_prefetch(void) +{ + int i; + + fetched = 0; +} + +static __uint64_t +disk_total_derived(pmdaMetric *mdesc, int inst) +{ + pmID pmid; + __pmID_int *ip = (__pmID_int *)&pmid; + __uint64_t val; + + pmid = mdesc->m_desc.pmid; + ip->domain = 0; + + switch (pmid) { + case PMDA_PMID(0,49): /* disk.all.total_bytes */ + val = diskstat.rblks + diskstat.wblks; + break; + + default: + fprintf(stderr, "disk_total_derived: Botch: no method for pmid %s\n", + pmIDStr(mdesc->m_desc.pmid)); + val = 0; + break; + } + +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "disk_total_derived: pmid %s inst %d val %llu\n", + pmIDStr(mdesc->m_desc.pmid), inst, val); + } +#endif + + return val; +} + +int +disk_total_fetch(pmdaMetric *mdesc, int inst, pmAtomValue *atom) +{ + int offset; + + if (fetched == 0) { + int sts; + sts = perfstat_disk_total(NULL, &diskstat, sizeof(perfstat_disk_total_t), 1); + if (sts != 1) { + /* TODO - how to find/decode errors? */ + fprintf(stderr, "perfstat_disk_total: failed %s\n", osstrerror()); + fetched = -1; + } + else + fetched = 1; + } + + if (fetched != 1) + return 0; + + offset = ((metricdesc_t *)mdesc->m_user)->md_offset; + if (offset == OFF_NOVALUES) + return 0; + + if (mdesc->m_desc.type == PM_TYPE_U64) { + if (offset == OFF_DERIVED) + atom->ull = disk_total_derived(mdesc, inst); + else { + __uint64_t *ullp; + ullp = (__uint64_t *)&((char *)&diskstat)[offset]; + atom->ull = *ullp; + } +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "disk_total_fetch: pmid %s inst %d val %llu\n", + pmIDStr(mdesc->m_desc.pmid), inst, atom->ull); + } +#endif + } + else { + if (offset == OFF_DERIVED) + atom->ul = (__uint32_t)disk_total_derived(mdesc, inst); + else { + __uint32_t *ulp; + ulp = (__uint32_t *)&((char *)&diskstat)[offset]; + atom->ul = *ulp; + } +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "disk_total_fetch: pmid %s inst %d val %lu\n", + pmIDStr(mdesc->m_desc.pmid), inst, atom->ul); + } +#endif + } + + return 1; +} diff --git a/src/pmdas/aix/help b/src/pmdas/aix/help new file mode 100644 index 0000000..afce5d8 --- /dev/null +++ b/src/pmdas/aix/help @@ -0,0 +1,61 @@ +# +# Copyright (c) 2004 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. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# AIX PMDA help file in the ASCII format +# +# lines beginning with a # are ignored +# lines beginning @ introduce a new entry of the form +# @ metric_name oneline-text +# help test goes +# here over multiple lines +# ... +# +# the metric_name is decoded against the default PMNS -- as a special case, +# a name of the form NNN.MM (for numeric NNN and MM) is interpreted as an +# instance domain identification, and the text describes the instance domain +# +# blank lines before the @ line are ignored +# + +@ kernel.all.cpu.idle TODO +@ kernel.all.cpu.user TODO +@ kernel.all.cpu.sys TODO +@ kernel.all.cpu.wait.total TODO +@ kernel.percpu.cpu.user TODO +@ kernel.percpu.cpu.idle TODO +@ kernel.percpu.cpu.sys TODO +@ kernel.percpu.cpu.wait.total TODO +@ disk.all.read TODO +@ disk.all.write TODO +@ disk.all.total TODO +@ disk.all.read_bytes TODO +@ disk.all.write_bytes TODO +@ disk.all.total_bytes TODO +@ disk.dev.read TODO +@ disk.dev.write TODO +@ disk.dev.total TODO +@ disk.dev.read_bytes TODO +@ disk.dev.write_bytes TODO +@ disk.dev.total_bytes TODO +@ network.interface.in.packets TODO +@ network.interface.in.bytes TODO +@ network.interface.in.errors TODO +@ network.interface.out.packets TODO +@ network.interface.out.bytes TODO +@ network.interface.out.errors TODO +@ network.interface.total.packets TODO +@ network.interface.total.bytes TODO diff --git a/src/pmdas/aix/netif.c b/src/pmdas/aix/netif.c new file mode 100644 index 0000000..01e0ac6 --- /dev/null +++ b/src/pmdas/aix/netif.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2004 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 "common.h" + +static int nnetif; +static int nnetif_alloc; +static int *fetched; +static perfstat_netinterface_t *netifstat; + +void +netif_init(int first) +{ + perfstat_id_t id; + int i; + + if (!first) + /* TODO ... not sure if/when we'll use this re-init hook */ + return; + + nnetif = perfstat_netinterface(NULL, NULL, sizeof(perfstat_netinterface_t), 0); + if ((fetched = (int *)malloc(nnetif * sizeof(int))) == NULL) { + fprintf(stderr, "netif_init: fetched malloc[%d] failed: %s\n", + nnetif * sizeof(int), osstrerror()); + exit(1); + } + if ((netifstat = (perfstat_netinterface_t *)malloc(nnetif * sizeof(perfstat_netinterface_t))) == NULL) { + fprintf(stderr, "netif_init: netifstat malloc[%d] failed: %s\n", + nnetif * sizeof(perfstat_netinterface_t), osstrerror()); + exit(1); + } + nnetif_alloc = nnetif; + + /* + * set up instance domain + */ + strcpy(id.name, ""); + nnetif = perfstat_netinterface(&id, netifstat, sizeof(perfstat_netinterface_t), nnetif_alloc); + + indomtab[NETIF_INDOM].it_numinst = nnetif; + indomtab[NETIF_INDOM].it_set = (pmdaInstid *)malloc(nnetif * sizeof(pmdaInstid)); + if (indomtab[NETIF_INDOM].it_set == NULL) { + fprintf(stderr, "netif_init: indomtab malloc[%d] failed: %s\n", + nnetif * sizeof(pmdaInstid), osstrerror()); + exit(1); + } + for (i = 0; i < nnetif; i++) { + indomtab[NETIF_INDOM].it_set[i].i_inst = i; + indomtab[NETIF_INDOM].it_set[i].i_name = strdup(netifstat[i].name); + } + +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "netif_init: nnetif=%d\n", nnetif); + } +#endif +} + +void +netif_prefetch(void) +{ + int i; + + for (i = 0; i < nnetif_alloc; i++) + fetched[i] = 0; +} + +static __uint64_t +netif_derived(pmdaMetric *mdesc, int inst) +{ + pmID pmid; + __pmID_int *ip = (__pmID_int *)&pmid; + __uint64_t val; + + pmid = mdesc->m_desc.pmid; + ip->domain = 0; + + switch (pmid) { + case PMDA_PMID(0,58): /* hinv.nnetif */ + val = nnetif; + break; + + case PMDA_PMID(0,65): /* network.interface.total.packets */ + val = netifstat[inst].ipackets + netifstat[inst].opackets; + break; + + case PMDA_PMID(0,66): /* network.interface.total.bytes */ + val = netifstat[inst].ibytes + netifstat[inst].obytes; + break; + + default: + fprintf(stderr, "netif_derived: Botch: no method for pmid %s\n", + pmIDStr(mdesc->m_desc.pmid)); + val = 0; + break; + } + +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "netif_derived: pmid %s inst %d val %llu\n", + pmIDStr(mdesc->m_desc.pmid), inst, val); + } +#endif + + return val; +} + +int +netif_fetch(pmdaMetric *mdesc, int inst, pmAtomValue *atom) +{ + int offset; + + if (fetched[inst] == 0) { + int sts; + int i; + perfstat_id_t id; + + strcpy(id.name, ""); + sts = perfstat_netinterface(&id, netifstat, sizeof(perfstat_netinterface_t), nnetif_alloc); + + /* TODO ... + * - if sts != nnetif, the number of network interfaces has changed, + * need to set fetched[i] to -1 for the missing ones + * - is sts > nnetif possible? worse, if the number of network + * interfaces is > nnetif_alloc what should we do? + * - possibly reshape the instance domain? + * - error handling? + */ + + for (i = 0; i < nnetif; i++) { + fetched[i] = 1; + } + } + + /* hinv.nnetif is a singular metric ... so no "instance" for this one */ + if (inst != PM_IN_NULL && fetched[inst] != 1) + return 0; + + offset = ((metricdesc_t *)mdesc->m_user)->md_offset; + if (offset == OFF_NOVALUES) + return 0; + + if (mdesc->m_desc.type == PM_TYPE_U64) { + if (offset == OFF_DERIVED) + atom->ull = netif_derived(mdesc, inst); + else { + __uint64_t *ullp; + ullp = (__uint64_t *)&((char *)&netifstat[inst])[offset]; + atom->ull = *ullp; + } +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "netif_fetch: pmid %s inst %d val %llu\n", + pmIDStr(mdesc->m_desc.pmid), inst, atom->ull); + } +#endif + } + else { + if (offset == OFF_DERIVED) + atom->ul = (__uint32_t)netif_derived(mdesc, inst); + else { + __uint32_t *ulp; + ulp = (__uint32_t *)&((char *)&netifstat[inst])[offset]; + atom->ul = *ulp; + } +#ifdef PCP_DEBUG + if ((pmDebug & (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) == (DBG_TRACE_APPL0|DBG_TRACE_APPL2)) { + /* desperate */ + fprintf(stderr, "netif_fetch: pmid %s inst %d val %lu\n", + pmIDStr(mdesc->m_desc.pmid), inst, atom->ul); + } +#endif + } + + return 1; +} diff --git a/src/pmdas/aix/pmns.disk b/src/pmdas/aix/pmns.disk new file mode 100644 index 0000000..d9ed093 --- /dev/null +++ b/src/pmdas/aix/pmns.disk @@ -0,0 +1,22 @@ +disk { + all + dev +} + +disk.all { + read AIX:0:44 + write AIX:0:45 + total AIX:0:46 + read_bytes AIX:0:47 + write_bytes AIX:0:48 + total_bytes AIX:0:49 +} + +disk.dev { + read AIX:0:50 + write AIX:0:51 + total AIX:0:52 + read_bytes AIX:0:53 + write_bytes AIX:0:54 + total_bytes AIX:0:55 +} diff --git a/src/pmdas/aix/pmns.hinv b/src/pmdas/aix/pmns.hinv new file mode 100644 index 0000000..ba148e2 --- /dev/null +++ b/src/pmdas/aix/pmns.hinv @@ -0,0 +1,6 @@ +hinv { + ncpu AIX:0:56 + ncpu_cfg AIX:0:38 + ndisk AIX:0:57 + nnetif AIX:0:58 +} diff --git a/src/pmdas/aix/pmns.kernel b/src/pmdas/aix/pmns.kernel new file mode 100644 index 0000000..fcafd54 --- /dev/null +++ b/src/pmdas/aix/pmns.kernel @@ -0,0 +1,77 @@ +kernel { + all + percpu +} + +kernel.all { + cpu + io + trap AIX:0:32 + pswitch AIX:0:23 + syscall AIX:0:22 + sysexec AIX:0:33 + sysfork AIX:0:34 + sysread AIX:0:36 + syswrite AIX:0:37 + readch AIX:0:8 + writech AIX:0:9 +} + +kernel.all.cpu { + idle AIX:0:0 + user AIX:0:1 + sys AIX:0:2 + intr AIX:0:31 + wait +} + +kernel.all.cpu.wait { + total AIX:0:3 +} + +kernel.all.io { + bread AIX:0:14 + bwrite AIX:0:15 + lread AIX:0:16 + lwrite AIX:0:17 + phread AIX:0:26 + phwrite AIX:0:27 + devintrs AIX:0:28 + softintrs AIX:0:10 + namei AIX:0:35 +} + +kernel.percpu { + cpu + io + pswitch AIX:0:25 + syscall AIX:0:24 + sysexec AIX:0:39 + sysfork AIX:0:40 + sysread AIX:0:42 + syswrite AIX:0:43 + readch AIX:0:11 + writech AIX:0:12 +} + +kernel.percpu.cpu { + idle AIX:0:4 + user AIX:0:5 + sys AIX:0:6 + intr AIX:0:13 + wait +} + +kernel.percpu.cpu.wait { + total AIX:0:7 +} + +kernel.percpu.io { + bread AIX:0:18 + bwrite AIX:0:19 + lread AIX:0:20 + lwrite AIX:0:21 + phread AIX:0:29 + phwrite AIX:0:30 + namei AIX:0:41 +} diff --git a/src/pmdas/aix/pmns.mem b/src/pmdas/aix/pmns.mem new file mode 100644 index 0000000..bfe42d2 --- /dev/null +++ b/src/pmdas/aix/pmns.mem @@ -0,0 +1,2 @@ +mem { +} diff --git a/src/pmdas/aix/pmns.network b/src/pmdas/aix/pmns.network new file mode 100644 index 0000000..a469296 --- /dev/null +++ b/src/pmdas/aix/pmns.network @@ -0,0 +1,26 @@ +network { + interface +} + +network.interface { + in + out + total +} + +network.interface.in { + packets AIX:0:59 + bytes AIX:0:60 + errors AIX:0:61 +} + +network.interface.out { + packets AIX:0:62 + bytes AIX:0:63 + errors AIX:0:64 +} + +network.interface.total { + packets AIX:0:65 + bytes AIX:0:66 +} diff --git a/src/pmdas/aix/root b/src/pmdas/aix/root new file mode 100644 index 0000000..ec99587 --- /dev/null +++ b/src/pmdas/aix/root @@ -0,0 +1,20 @@ +/* + * fake "root" for validating the local PMNS subtree + */ + +#include <stdpmid> + +root { + kernel + disk + mem + network + hinv +} + +#include "pmns.kernel" +#include "pmns.disk" +#include "pmns.mem" +#include "pmns.network" +#include "pmns.hinv" + |