diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2014-10-26 12:33:50 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2014-10-26 12:33:50 +0400 |
commit | 47e6e7c84f008a53061e661f31ae96629bc694ef (patch) | |
tree | 648a07f3b5b9d67ce19b0fd72e8caa1175c98f1a /src/pmdas/sample | |
download | pcp-47e6e7c84f008a53061e661f31ae96629bc694ef.tar.gz |
Debian 3.9.10debian/3.9.10debian
Diffstat (limited to 'src/pmdas/sample')
-rw-r--r-- | src/pmdas/sample/GNUmakefile | 40 | ||||
-rwxr-xr-x | src/pmdas/sample/Install | 74 | ||||
-rw-r--r-- | src/pmdas/sample/README | 63 | ||||
-rwxr-xr-x | src/pmdas/sample/Remove | 45 | ||||
-rw-r--r-- | src/pmdas/sample/Sample.pmchart | 10 | ||||
-rw-r--r-- | src/pmdas/sample/domain.h | 4 | ||||
-rwxr-xr-x | src/pmdas/sample/get_next_pmid | 48 | ||||
-rw-r--r-- | src/pmdas/sample/help | 602 | ||||
-rw-r--r-- | src/pmdas/sample/pmns | 260 | ||||
-rw-r--r-- | src/pmdas/sample/root | 20 | ||||
-rw-r--r-- | src/pmdas/sample/src/GNUmakefile | 62 | ||||
-rw-r--r-- | src/pmdas/sample/src/GNUmakefile.install | 53 | ||||
-rw-r--r-- | src/pmdas/sample/src/events.c | 477 | ||||
-rw-r--r-- | src/pmdas/sample/src/events.h | 33 | ||||
-rw-r--r-- | src/pmdas/sample/src/percontext.c | 256 | ||||
-rw-r--r-- | src/pmdas/sample/src/percontext.h | 31 | ||||
-rw-r--r-- | src/pmdas/sample/src/pmda.c | 126 | ||||
-rw-r--r-- | src/pmdas/sample/src/sample.c | 2748 |
18 files changed, 4952 insertions, 0 deletions
diff --git a/src/pmdas/sample/GNUmakefile b/src/pmdas/sample/GNUmakefile new file mode 100644 index 0000000..2c30757 --- /dev/null +++ b/src/pmdas/sample/GNUmakefile @@ -0,0 +1,40 @@ +# +# Copyright (c) 2014 Red Hat. All Rights Reserved. +# Copyright (c) 2000,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 + +DFILES = README help +LSRCFILES = root pmns $(DFILES) Install Remove Sample.pmchart get_next_pmid +LDIRT = *.dir *.pag + +SUBDIRS = src +PMDADIR = $(PCP_PMDAS_DIR)/sample + +default_pcp default :: $(SUBDIRS) + +default_pcp default :: $(SUBDIRS) + $(SUBDIRS_MAKERULE) + +install_pcp install :: $(SUBDIRS) + $(SUBDIRS_MAKERULE) + +install_pcp install :: default + $(INSTALL) -d $(PMDADIR) + $(INSTALL) -m 755 Install Remove $(PMDADIR) + $(INSTALL) -m 644 $(DFILES) pmns root $(PMDADIR) + $(INSTALL) -m 644 Sample.pmchart $(PCP_VAR_DIR)/config/pmchart/Sample + +include $(BUILDRULES) diff --git a/src/pmdas/sample/Install b/src/pmdas/sample/Install new file mode 100755 index 0000000..fd6bee6 --- /dev/null +++ b/src/pmdas/sample/Install @@ -0,0 +1,74 @@ +#! /bin/sh +# +# Copyright (c) 1997 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. +# +# Install the sample PMDA and/or PMNS +# + +. $PCP_DIR/etc/pcp.env +. $PCP_SHARE_DIR/lib/pmdaproc.sh + +iam=sample +forced_restart=false +pmda_interface=2 + +# Do it for sample +# +pmdaSetup + +echo "======================" +echo "= sample daemon PMDA =" +echo "======================" + +daemon_opt=true # can install as daemon +dso_opt=false +pipe_opt=true # supports pipe IPC +socket_opt=true # supports socket IPC +socket_inet_def=2077 # default TCP port for Internet socket IPC + +pmdaInstall + +# The name of the PMDA for sampledso +# +iam=sampledso + +# Do it for sampledso ... no pmdaSetup +# + +echo "======================" +echo "= sampledso DSO PMDA =" +echo "======================" + +domain=30 +SYMDOM=SAMPLEDSO +sed -e 's/sample/sampledso/' -e 's/SAMPLE/SAMPLEDSO/' <pmns >$tmp/pmns +pmns_source=$tmp/pmns +pmns_name=sampledso + +if $do_pmda +then + sed -e 's/sample/sampledso/' -e 's/SAMPLE/SAMPLEDSO/' <help >dsohelp + help_source=dsohelp +fi + +dso_opt=true +daemon_opt=false +dso_suffix=so +[ "$PCP_PLATFORM" = "mingw" ] && dso_suffix=dll +[ "$PCP_PLATFORM" = "darwin" ] && dso_suffix=dylib +dso_name=$PCP_PMDAS_DIR/sample/pmda_sample.$dso_suffix +dso_entry=sample_init + +pmdaInstall + +exit 0 diff --git a/src/pmdas/sample/README b/src/pmdas/sample/README new file mode 100644 index 0000000..6e15fcf --- /dev/null +++ b/src/pmdas/sample/README @@ -0,0 +1,63 @@ +Sample PMDA +=========== + +This PMDA supports a synthetic collection of metrics that are designed +to exercise various facilities of the Performance Co-Pilot. The most +common reasons for installing this PMDA are + a. for internal product QA, or + b. as part of one of the animated tutorials or demonstrations that + accompany the PCP + +Two variants of the PMDA are installed, namely "sample" as a daemon +with an IPC channel to PMCD, and "sampledso" that is attached as a +Dynamic Shared Object (DSO) by PMCD and called directly. + +Metrics +======= + +The file ./help contains descriptions for all of the metrics exported +by this PMDA. + +Once the PMDA has been installed, the following command will list all +the available metrics and their explanatory "help" text: + + $ pminfo -fT sample sampledso + +Installation +============ + + + # cd $PCP_PMDAS_DIR/sample + + + Check that there is no clash in the Performance Metrics Domain + defined in ./domain.h and the other PMDAs currently in use (see + $PCP_PMCDCONF_PATH). If there is, edit ./domain.h to choose another + domain number. + + Note that sampledso uses the next domain number after the one in + ./domain.h, so you must check for its uniqueness as well. + + + Then simply use + + # ./Install + + and choose both the "collector" and "monitor" installation + configuration options. + + You will be prompted to choose the IPC channel for the daemon + implementation of the sample PMDA -- everything else is automated + +De-installation +=============== + + + Simply use + + # cd $PCP_PMDAS_DIR/sample + # ./Remove + +Troubleshooting +=============== + + + After installing or restarting the agent, the PMCD log file + ($PCP_LOG_DIR/pmcd/pmcd.log) and the PMDA log file + ($PCP_LOG_DIR/pmcd/sample.log) should be checked for any warnings + or errors. diff --git a/src/pmdas/sample/Remove b/src/pmdas/sample/Remove new file mode 100755 index 0000000..5b547f9 --- /dev/null +++ b/src/pmdas/sample/Remove @@ -0,0 +1,45 @@ +#! /bin/sh +# +# Copyright (c) 1997 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 +# +# Remove the sample PMDA +# + +# source the PCP configuration environment variables +. $PCP_DIR/etc/pcp.env + +# Get the common procedures and variable assignments +# +. $PCP_SHARE_DIR/lib/pmdaproc.sh + +# The name of the PMDA +# +iam=sample + +# Do it +# +pmdaSetup +pmdaRemove + +# and again +# +iam=sampledso +pmns_name=sampledso +domain=30 +pmdaRemove + +exit 0 diff --git a/src/pmdas/sample/Sample.pmchart b/src/pmdas/sample/Sample.pmchart new file mode 100644 index 0000000..188ef1c --- /dev/null +++ b/src/pmdas/sample/Sample.pmchart @@ -0,0 +1,10 @@ +#pmchart +Version 1.2 host dynamic + +Chart Style plot + Plot Color #-cycle Host * Metric sample.drift +Chart Style plot + Plot Color #-cycle Host * Metric sample.step + +# +# Created by pmchart Mon Jul 15 08:52:18 1996 diff --git a/src/pmdas/sample/domain.h b/src/pmdas/sample/domain.h new file mode 100644 index 0000000..0aa641b --- /dev/null +++ b/src/pmdas/sample/domain.h @@ -0,0 +1,4 @@ +/* + * built from ../../pmns/stdpmid + */ +#define SAMPLE 29 diff --git a/src/pmdas/sample/get_next_pmid b/src/pmdas/sample/get_next_pmid new file mode 100755 index 0000000..5443a7d --- /dev/null +++ b/src/pmdas/sample/get_next_pmid @@ -0,0 +1,48 @@ +#!/bin/sh +# +# find next unallocated PMIDs for the sample PMDA +# + +if [ $# -gt 1 ] +then + echo "Usage: $0 [N]" + echo "N defaults to 1 (PMID to generate)" + exit 1 +fi +want=1 +[ $# -eq 1 ] && want="$1" + +root=root +if [ ! -f $root ] +then + root=../root +fi +if [ ! -f $root ] +then + echo "Error: cannot find PMNS in root nor ../root" + exit 1 +fi + +pminfo -m -n $root \ +| sed -n -e '/ 29/s/\(.*\): \(.*\)/\2 \1/p' \ +| sort -t . -n -k 1,1 -k 2,2 -k 3,3 \ +| sed -e 's/ .*//' -e 's/\./ /g' \ +| awk ' +BEGIN { lastidx = -1; found = 0 } +NF != 3 { next } +$2 != 0 { next } + { if (lastidx+1 != $3) { + for (i = lastidx+1; i < $3; i++) { + print "SAMPLE:0:" i + found++ + if (found == '"$want"') exit + } + } + lastidx = $3 + } +END { while (found < '"$want"') { + lastidx++ + print "SAMPLE:0:" lastidx + found++ + } + }' diff --git a/src/pmdas/sample/help b/src/pmdas/sample/help new file mode 100644 index 0000000..756c374 --- /dev/null +++ b/src/pmdas/sample/help @@ -0,0 +1,602 @@ +# +# Copyright (c) 2000-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 +# +# sample 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 +# + +@ SAMPLE.1 Instance domain "colour" for sample PMDA +Universally 3 instances, "red" (0), "green" (1) and "blue" (3). + +@ SAMPLE.2 Instance domain "bin" for sample PMDA +Universally 9 instances numbered 100 .. 900 in steps of 100, and named +"bin-100" .. "bin-900" + +@ SAMPLE.3 Instance domain "mirage" for sample PMDA +Random number of instances, that change with time. Instance "m-00" (0) +is always present, while the others are numbered 1 .. 49 and named "m-01" +.. "m-99" + +@ SAMPLE.4 Instance domain "family" for sample PMDA. +A fixed set of instances: + "colleen", "terry", "emma", "cathy" and "fat bald bastard" + +@ SAMPLE.7 Instance domain "many" for sample PMDA. +A varable size set of instances controlled by sample.many.count + +@ sample.control A control variable for the "sample" PMDA +This control variable may be modified using pmStore(). +The allowed values are + 0 disable debugging output in the PMDA + >0 set pmDebug to this value to enable debugging output + -1 force the PMDA to terminate + +@ sample.daemon_pid Process id of PMDA daemon +The process id of PMDA daemon, -1 if the daemon is a DSO. + +@ sample.seconds Elapsed time (seconds) +The elapsed time since the PMDA started, in seconds, i.e. as returned +by time(2). + +@ sample.milliseconds Elapsed time (milliseconds) +The elapsed time since the PMDA started, in milliseconds, i.e. as +returned by gettimeofday(2), and then adjusted from microseconds +to milliseconds. + +@ sample.load Hypothetical load +The hypothetical load is always 42! + +@ sample.colour Metrics with a "saw-tooth" trend over time +This metric has 3 instances, designated "red", "green" and "blue". + +The value of the metric is monotonic increasing in the range N to +N+100, then back to N. The different instances have different N values, +namely 100 (red), 200 (green) and 300 (blue). + +@ sample.darkness No values available +Defined over the same instance domain as sample.colour, but this metric +returns the "No values available" error for every fetch. + +@ sample.bin Several constant instances +9 instances labelled "bin-100" thru "bin-900", each with a constant +value of 100 thru 900. + +@ sample.bucket Several constant instances +9 instances labelled "bin-100" thru "bin-900", each with a constant +value of 100 thru 900. This is an alias for sample.bin, but with +a different PMID. + +@ sample.part_bin Several constant instances +5 instances labelled "bin-100" thru "bin-900", each with a constant +value of 100 thru 900. This is defined over the same domain as +sample.part, but half of the instances are missing. + +@ sample.bogus_bin Several constant instances +9 instances labelled "bin-100" thru "bin-900", each with a constant +value of 100 thru 900. This is defined over the same domain as +sample.part, half the values are for instances not in the instance +domain. + +@ sample.drift A random trended metric +This metric returns a random value (expected mean is approximately 200), +subject to a trending pattern such that the sequence is mainly monotonic, +with a change in direction after on average 4 consecutive samples. + +Use pmStore() to modifiy the instantaneous value, which becomes the new +expected mean. + +@ sample.step A step function (instantaneous) +This metric changes magnitude every 30 seconds, between a base value and +3 times the base value. + +The metric has "instantaneous" semantics. See also sample.step_counter. + +Use pmStore() to modify the base value. + +@ sample.step_counter A step function (counter) +This metric changes magnitude every 30 seconds, between a base value and +3 times the base value. + +The metric has "counter" semantics. See also sample.step. + +Use pmStore() to modify the base value. + +@ sample.needprofile Metrics that need an explicit profile +Simulate behaviour similar to the "proc" PMDA where metrics values are +only available if an explicit instance profile is provided. + +@ sample.lights Traffic lights. +A singular metric that has a discrete string value, namely "red", +"yellow" or "green". There is some persistance in the value, so +consecutive fetches are likely to return the same value, however over a +long period of time all values are equally probable. + +@ sample.magnitude Powers of two. +A singular metric that has a discrete integer value, namely 1, 2, 4, 8, +16, 32 or 64. There is some persistance in the value, so consecutive +fetches are likely to return the same value, however over a long period +of time all values are equally probable. + +@ sample.pdu Total PDU count +Count of PDUs received or transmitted. + +Use pmStore() to reset the counter to 0, independent of the value passed +to pmStore(). + +@ sample.recv_pdu Count of PDUs received +Count of PDUs received. + +Use pmStore() to reset the counter to 0, independent of the value passed +to pmStore(). + +@ sample.xmit_pdu Count of PDUs transmitted +Count of PDUs transmitted. + +Use pmStore() to reset the counter to 0, independent of the value passed +to pmStore(). + +@ sample.mirage Simple saw-tooth rate, but instances come and go +The metric is a rate (Kbytes/sec) that varies in a saw-tooth distribution +over time. Different instances of the metric have different baselines +for the saw-tooth, but all have an max-to-min range of 100. + +What makes this metric interesting is that instances come and go (not +more often than once every 10 seconds however). Instance 0 is always +present, but the other instances 1 thru 49 come and go in a cyclic +pattern with a large random component influencing when each instance +appears and disappears. + +@ sample.mirage_longlong Simple saw-tooth rate, but instances come and go +The metric is a rate (bytes/msec) that varies in a saw-tooth distribution +over time. Different instances of the metric have different baselines +for the saw-tooth, but all have an max-to-min range of 100,000,000. + +What makes this metric interesting is that instances come and go (not +more often than once every 10 seconds however). Instance 0 is always +present, but the other instances 1 thru 49 come and go in a cyclic +pattern with a large random component influencing when each instance +appears and disappears. + +@ sample.write_me Modifiable, but otherwise constant. +This metric has a 32-bit integer value of 2, unless changed via pmStore. +The metric has semantics of rate, and units of events per second. + +@ sample.sysinfo Aggregate containing system accounting structures +This metric has an aggregate value containing the following struct: + struct { + int len; + struct sysinfo sysinfo; + }; + +The len field contains the size of the structure enclosing it. +The sysinfo field contains various system accounting structures, summed over +all CPUs, as returned by + sysmp(MP_SAGET, MPSA_SINFO, ...); + +See /usr/include/sys/sysinfo.h for the definition of the sysinfo struct. + +@ sample.noinst No instance available +For testing, only. This metric is known, but no value is ever available + +@ sample.long.one 1 as a 32-bit integer +@ sample.long.ten 10 as a 32-bit integer +@ sample.long.hundred 100 as a 32-bit integer +@ sample.long.million 1000000 as a 32-bit integer +@ sample.long.write_me a 32-bit integer that can be modified +@ sample.long.bin like sample.bin but type 32 +@ sample.long.bin_ctr like sample.bin but type 32, SEM_COUNTER and SPACE_KBYTE + +@ sample.ulong.one 1 as a 32-bit unsigned integer +@ sample.ulong.ten 10 as a 32-bit unsigned integer +@ sample.ulong.hundred 100 as a 32-bit unsigned integer +@ sample.ulong.million 1000000 as a 32-bit unsigned integer +@ sample.ulong.write_me a 32-bit unsigned integer that can be modified +@ sample.ulong.bin like sample.bin but type U32 +@ sample.ulong.bin_ctr like sample.bin but type U32, SEM_COUNTER and SPACE_KBYTE + +@ sample.ulong.count.base count scale is 1, value is 42,000,000 +@ sample.ulong.count.deca count scale is 10, value is 4,200,000 +@ sample.ulong.count.hecto count scale is 10, value is 420,000 +@ sample.ulong.count.kilo count scale is 10, value is 42,000 +@ sample.ulong.count.mega count scale is 10, value is 42 + +@ sample.longlong.one 1 as a 64-bit integer +@ sample.longlong.ten 10 as a 64-bit integer +@ sample.longlong.hundred 100 as a 64-bit integer +@ sample.longlong.million 1000000 as a 64-bit integer +@ sample.longlong.write_me a 64-bit integer that can be modified +@ sample.longlong.bin like sample.bin but type 64 +@ sample.longlong.bin_ctr like sample.bin but type 64, SEM_COUNTER and SPACE_KBYTE + +@ sample.ulonglong.one 1 as a 64-bit unsigned integer +@ sample.ulonglong.ten 10 as a 64-bit unsigned integer +@ sample.ulonglong.hundred 100 as a 64-bit unsigned integer +@ sample.ulonglong.million 1000000 as a 64-bit unsigned integer +@ sample.ulonglong.write_me a 64-bit unsigned integer that can be modified +@ sample.ulonglong.bin like sample.bin but type U64 +@ sample.ulonglong.bin_ctr like sample.bin but type U64, SEM_COUNTER and SPACE_KBYTE + +@ sample.float.one 1 as a 32-bit floating point value +@ sample.float.ten 10 as a 32-bit floating point value +@ sample.float.hundred 100 as a 32-bit floating point value +@ sample.float.million 1000000 as a 32-bit floating point value +@ sample.float.write_me a 32-bit floating-point value that can be modified +@ sample.float.bin like sample.bin but type FLOAT +@ sample.float.bin_ctr like sample.bin but type FLOAT, SEM_COUNTER and SPACE_KBYTE + +@ sample.double.one 1 as a 64-bit floating point value +@ sample.double.ten 10 as a 64-bit floating point value +@ sample.double.hundred 100 as a 64-bit floating point value +@ sample.double.million 1000000 as a 64-bit floating point value +@ sample.double.write_me a 64-bit floating-point value that can be modified +@ sample.double.bin like sample.bin but type DOUBLE +@ sample.double.bin_ctr like sample.bin but type DOUBLE, SEM_COUNTER and SPACE_KBYTE + +@ sample.string.null a zero length string +@ sample.string.hullo K&R have a lot to answer for +@ sample.string.write_me a string value that can be modified + +@ sample.aggregate.null a zero length aggregate +@ sample.aggregate.hullo K&R have a lot to answer for +@ sample.aggregate.write_me a aggregate value that can be modified + +@ sample.hordes.one 500 instances +Value of the metric is the instance identifier. +@ sample.hordes.two 500 instances +Value of the metric is 500 - the instance identifier. + +@ sample.bad.unknown Not known to the PMDA +In the PMNS, but the sample agent pretends it does not know about this one. +@ sample.bad.nosupport Not supported in this version of the PMDA +Type is PM_NOSUPPORT, fetch returns PM_ERR_APPVERSION +@ sample.bad.novalues Scalar with no values, ever + +@ sample.not_ready interval (in seconds) during which PMDA does not respond to PDUs +Store a positive number of seconds as the value of this metric. The +following PDU received will result in the following sequence of events: + 1. return an error PDU with PM_ERR_PMDANOTREADY to pmcd + 2. sleep for the given number of seconds + 3. sends an error PDU with PM_ERR_PMDAREADY to pmcd +If everything went as planned, sample.not_ready returns to 0, otherwise it +has a negative error code as value. + +@ sample.wrap.long long counter that wraps +The metric value increments by INT_MAX / 2 - 1 (from <limits.h>) every +time it is fetched. + +@ sample.wrap.ulong unsigned long counter that wraps +The metric value increments by UINT_MAX / 2 - 1 (from <limits.h>) every +time it is fetched. + +@ sample.wrap.longlong long long counter that wraps +The metric value increments by LONGLONG_MAX / 2 - 1 (from <limits.h>) +every time it is fetched. + +@ sample.wrap.ulonglong unsigned long long counter that wraps +The metric value increments by ULONGLONG_MAX / 2 - 1 (from <limits.h>) +every time it is fetched. + +@ sample.dodgey.value 5 unreliable instances +The metric is a set of 5 instantaneous values, drawn at random from the +range 0 to 100. The number of instances "visible" is controlled by +sample.dodgey.control. + +@ sample.dodgey.control control values retured for sample.dodgey.value +If sample.dodgey.control is <= 0, then this is returned as the "numval" +component in the pmResult (0 => no values available, less than 0 => +various errors). + +If sample.dodgey.control is between 1 and 5 (inclusive), then this many +of the values will be "visible". The values will be selected in order +from the underlying 5 instances. + +If sample.dodgey.control is > 5, then at random times (between 1 and +sample.dodgey.control fetches of the metric), the number of instances +available is changed according to the following probabilities ... + 0.9 some number of instances in the range 0 to 5, selected at random + from the underlying 5 instances. + 0.1 error (PM_ERR_NOAGENT or PM_ERR_AGAIN or PM_ERR_APPVERSION) + +@ sample.rapid count very quickly +Base counter increments by 8*10^7 per fetch. Result is 10 x base counter. + +@ sample.scale_step.bytes_up count up by powers of 2, wrap back to one at 10 Tbytes + +@ sample.scale_step.bytes_down count down by powers of 2, wrap back to 10 Tbytes at 1 + +@ sample.scale_step.count_up count up by powers of 10, wrap back to 1 at 10e12 + +@ sample.scale_step.count_down count down by powers of 10, wrap back to 10e12 at 1 + +@ sample.scale_step.time_up_secs count up seconds by multiples of 10, wrap back to 1 second at 1 day + +@ sample.scale_step.time_up_nanosecs count up nanoseconds by multiples of 10, wrap back to 1 nanosecond at 1 day + +@ sample.scale_step.none_up count up dimensionless by multiples of 10, wrap back to 1 at 10 million + +@ sample.const_rate.value constant rate counter +A counter that changes with constant rate between fetches. + +The rate is set by storing the desired rate (counts per second) +into sample.const_rate.gradient + +@ sample.const_rate.gradient rate per second to set sample.const_rate.value, writable + +@ sample.error_code Arbitrary PMAPI error code for sample.error_check +The metrics sample.error_code and sample.error_check are used in tandem +as follows: + if sample.error_code is < 0, then any attempt to retrieve + information about sample.error_check will return a + sample.error_code as a PMAPI error from the PMDA. + +Use pmstore(1) to change sample.error_code. + +@ sample.error_check Return PMAPI error code from sample.error_code +The metrics sample.error_code and sample.error_check are used in tandem +as follows: + if sample.error_code is < 0, then any attempt to retrieve + information about sample.error_check will return a + sample.error_code as a PMAPI error from the PMDA. + +Otherwise sample.error_check is a boring metric that always has +the value 0. + +@ sample.dynamic.counter counter metric with dynamic indom +Instances come from $PCP_PMDAS_DIR/sample/dynamic.indom, if it exists. +Each line in this file is + internal_id external_id + +This metric increments each time this instance has been seen when scanning +the dynamic.indom file, and resets to zero each time the instance appears. + +@ sample.dynamic.discrete discrete metric with dynamic indom +Instances come from $PCP_PMDAS_DIR/sample/dynamic.indom, if it exists. +Each line in this file is + internal_id external_id + +This metric increments each time this instance has been seen when scanning +the dynamic.indom file, and resets to zero each time the instance appears. + +@ sample.dynamic.instant instant metric with dynamic indom +Instances come from $PCP_PMDAS_DIR/sample/dynamic.indom, if it exists. +Each line in this file is + internal_id external_id + +This metric increments each time this instance has been seen when scanning +the dynamic.indom file, and resets to zero each time the instance appears. + +@ sample.many.count number of instances in sample.many.int's domain +store a value in sample.many.count to change the number of instances +that appear in sample.many.int's instance domain + +@ sample.many.int variable sized instance domain +store a value in sample.many.count to change the number of instances +that appear in sample.many.int's instance domain + +@ sample.bigid a metric with item number bigger then 2^9 + +@ sample.byte_ctr counter byte counter +value increments randomly in the range (0,1023) bytes per fetch + +@ sample.byte_rate instantaneous bytes/second +random value in the range (0,1023), so avg value is 512 bytes/second + +@ sample.kbyte_ctr counter Kbytes/second +value increments randomly in the range (0,1023) Kbytes per fetch + +@ sample.kbyte_rate instantaneous Kbytes/second +random value in the range (0,1023), so avg value is 512 Kbytes/second + +@ sample.byte_rate_perhour instantaneous bytes/hour +random value in the range (0,1023), so avg value is 512 bytes/hour + +@ sample.dynamic.meta.metric metric with modifiable metadata +See sample.dynamic.meta.pmdesc for the metrics that can be modified to +change the metadata for this metric. +The value of this metric is always 42. + +@ sample.dynamic.meta.pmdesc.type pmDesc.type for sample.dynamic.meta.metric +One of these values: +PM_TYPE_NOSUPPORT -1 /* not implemented in this version */ +PM_TYPE_32 0 /* 32-bit signed integer */ +PM_TYPE_U32 1 /* 32-bit unsigned integer */ +PM_TYPE_64 2 /* 64-bit signed integer */ +PM_TYPE_U64 3 /* 64-bit unsigned integer */ +PM_TYPE_FLOAT 4 /* 32-bit floating point */ +PM_TYPE_DOUBLE 5 /* 64-bit floating point */ +PM_TYPE_STRING 6 /* array of char */ +PM_TYPE_AGGREGATE 7 /* arbitrary binary data (aggregate) */ +PM_TYPE_AGGREGATE_STATIC 8 /* static pointer to aggregate */ +PM_TYPE_UNKNOWN 255 /* used in pmValueBlock, not pmDesc */ + +Defaults to PM_TYPE_32. + +@ sample.dynamic.meta.pmdesc.indom pmDesc.indom for sample.dynamic.meta.metric +Defaults to PM_INDOM_NULL (0xffffffff). + +@ sample.dynamic.meta.pmdesc.sem pmDesc.sem for sample.dynamic.meta.metric +One of these values: +PM_SEM_COUNTER 1 /* cumulative counter (monotonic increasing) */ +PM_SEM_INSTANT 3 /* instantaneous value, continuous domain */ +PM_SEM_DISCRETE 4 /* instantaneous value, discrete domain */ + +Defaults to PM_SEM_DISCRETE. + +@ sample.dynamic.meta.pmdesc.units pmDesc.units for sample.dynamic.meta.metric +6 x 4-bit values, from least-significant bit to most-significant bit: +dimSpace: + -1, 0, 1 +dimTime: + -1, 0, 1 +dimCount: + 0, 1 +scaleSpace: + PM_SPACE_BYTE 0 /* bytes */ + PM_SPACE_KBYTE 1 /* Kilobytes (1024) */ + PM_SPACE_MBYTE 2 /* Megabytes (1024^2) */ + PM_SPACE_GBYTE 3 /* Gigabytes (1024^3) */ + PM_SPACE_TBYTE 4 /* Terabytes (1024^4) */ + PM_SPACE_PBYTE 5 /* Petabytes (1024^5) */ + PM_SPACE_EBYTE 6 /* Exabytes (1024^6) */ +scaleTime: + PM_TIME_NSEC 0 /* nanoseconds */ + PM_TIME_USEC 1 /* microseconds */ + PM_TIME_MSEC 2 /* milliseconds */ + PM_TIME_SEC 3 /* seconds */ + PM_TIME_MIN 4 /* minutes */ + PM_TIME_HOUR 5 /* hours */ +scaleCount: + PM_COUNT_ONE 0 /* 1 */ + +Defaults to { 1, -1, 0, PM_SPACE_BYTE, PM_TIME_SEC, 0 } + +@ sample.datasize Space allocated for PMDA's data segment +This metric returns the amount of memory in kilobytes allocated for the +data segment of the PMDA. + +This is handy for tracing memory utilization (and leaks) in libpcp_pmda. + +@ SAMPLE.0.1000 dynamic *.secret.bar metric +Value "foo". + +@ SAMPLE.0.1001 dynamic *.secret.foo.one metric +Value 1. + +@ SAMPLE.0.1002 dynamic *.secret.foo.two metric +Value 2. + +@ SAMPLE.0.1003 dynamic *.secret.foo.bar.three metric +Value 3. + +@ SAMPLE.0.1004 dynamic *.secret.foo.bar.four metric +Value 4. + +@ SAMPLE.0.1005 dynamic *.secret.foo.bar.grunt.five metric +Value 5. + +@ SAMPLE.0.1006 dynamic *.secret.foo.bar.grunt.snort.six metric +Value 6. + +@ SAMPLE.0.1007 dynamic *.secret.foo.bar.grunt.snort.huff.puff.seven metric +Value 7. + +@ sample.scramble.bin Several constant instances, instances scrambled +Like sample.bin, except +1. instances are missing with probability 0.33 +2. order of the instances from pmFetch is random + +Designed to help testing instance matching between pmFetch calls +for PCP clients. + +@ sample.scramble.version Current state version and reset for sample.scramble.bin +To make the order of instances seen from sample.scramble.bin +deterministic, use pmstore(1) to trigger a reset. + +@ sample.percontext.control.ctx Number of PMAPI contexts seen +One more than the highest PMAPI context number from PMCD. + +@ sample.percontext.control.active Number of active PMAPI contexts + +@ sample.percontext.control.start Number of new PMAPI contexts seen +Incremented each time a new PMAPI context is seen from PMCD. + +sample.percontext.control.start - sample.percontext.control.end +should equal sample.percontext.control.active. + +@ sample.percontext.control.end Number of PMAPI contexts closed +Incremented each time PMCD closes a PMAPI context. + +sample.percontext.control.start - sample.percontext.control.end +should equal sample.percontext.control.active. + +@ sample.percontext.pdu Total PDU count for the client context +Count of PDUs received from or transmitted to the current PMAPI client +context. + +Use pmStore() to reset the counter to 0, independent of the value passed +to pmStore(). + +@ sample.percontext.recv_pdu Count of PDUs received from the client context +Count of PDUs received from the current PMAPI client context. + +Use pmStore() to reset the counter to 0, independent of the value passed +to pmStore(). + +@ sample.percontext.xmit_pdu Count of PDUs transmitted +Count of PDUs transmitted to the current PMAPI client context. + +Use pmStore() to reset the counter to 0, independent of the value passed +to pmStore(). + +@ sample.event.records Dummy event records +Dummy event records are generated in a fixed pattern to help QA. + +Once all setups have been returned, the cycle is repeated. + +See event.reset to exert explicit control over the next batch of event +records to be returned. + +@ sample.event.no_indom_records More dummy event records +Like sample.event.records but without the instance domain. + +@ sample.event.reset reset event record state +Used for QA, should take one of the values 0, 1, 2 or 3 +to determine which of the dummy event record setups will +be returned for the next fetch of event.records. + +@ sample.event.highres_records Dummy highres timestamp event records +Dummy high resolution event records generated in a fixed pattern to help QA. + +Once all setups have been returned, the cycle is repeated. + +See event.reset_highres to exert explicit control over the next batch of event +records to be returned. + +@ sample.event.reset_highres reset highres event record state +Used for QA, should take one of the values 0, 1, 2 or 3 +to determine which of the dummy event record setups will +be returned for the next fetch of event.highres_records. + +@ sample.event.type event type parameter for event records + +@ sample.event.param_32 32 parameter for event records + +@ sample.event.param_u32 U32 parameter for event records + +@ sample.event.param_64 64 parameter for event records + +@ sample.event.param_u64 U64 parameter for event records + +@ sample.event.param_float FLOAT parameter for event records + +@ sample.event.param_double DOUBLE parameter for event records + +@ sample.event.param_string STRING parameter for event records + +@ sample.event.param_aggregate AGGREGATE parameter for event records diff --git a/src/pmdas/sample/pmns b/src/pmdas/sample/pmns new file mode 100644 index 0000000..87c7507 --- /dev/null +++ b/src/pmdas/sample/pmns @@ -0,0 +1,260 @@ +/* + * Metrics for sample PMDA + * + * Next pmid ... use get_next_pmid + * + * Copyright (c) 2000-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 + * + */ + +sample { + control SAMPLE:0:0 + daemon_pid SAMPLE:0:1 + seconds SAMPLE:0:2 + milliseconds SAMPLE:0:3 + load SAMPLE:0:4 + colour SAMPLE:0:5 + darkness SAMPLE:0:92 + bin SAMPLE:0:6 + bucket SAMPLE:0:48 + part_bin SAMPLE:0:50 + bogus_bin SAMPLE:0:51 + drift SAMPLE:0:7 + step SAMPLE:0:8 + step_counter SAMPLE:0:63 + mirage SAMPLE:0:37 + mirage_longlong SAMPLE:0:38 + write_me SAMPLE:0:36 + lights SAMPLE:0:46 + magnitude SAMPLE:0:47 + sysinfo SAMPLE:0:39 + pdu SAMPLE:0:40 + recv_pdu SAMPLE:0:41 + xmit_pdu SAMPLE:0:42 + noinst SAMPLE:0:9 + needprofile SAMPLE:0:49 + long + ulong + longlong + ulonglong + float + double + string + aggregate + hordes + bad + not_ready SAMPLE:0:56 + wrap + dodgey + dynamic + rapid SAMPLE:0:64 + scale_step + const_rate + error_code SAMPLE:0:74 + error_check SAMPLE:0:75 + bigid SAMPLE:0:1023 + many + byte_ctr SAMPLE:0:81 + byte_rate SAMPLE:0:82 + kbyte_ctr SAMPLE:0:83 + kbyte_rate SAMPLE:0:84 + byte_rate_perhour SAMPLE:0:85 + datasize SAMPLE:0:91 + secret SAMPLE:*:* + scramble + percontext + event +} + +sample.long { + one SAMPLE:0:10 + ten SAMPLE:0:11 + hundred SAMPLE:0:12 + million SAMPLE:0:13 + write_me SAMPLE:0:14 + bin SAMPLE:0:103 + bin_ctr SAMPLE:0:104 +} + +sample.ulong { + one SAMPLE:0:93 + ten SAMPLE:0:94 + hundred SAMPLE:0:95 + million SAMPLE:0:96 + write_me SAMPLE:0:97 + bin SAMPLE:0:105 + bin_ctr SAMPLE:0:106 + count +} + +sample.ulong.count { + base SAMPLE:0:115 + deca SAMPLE:0:116 + hecto SAMPLE:0:117 + kilo SAMPLE:0:118 + mega SAMPLE:0:119 +} + +sample.float { + one SAMPLE:0:15 + ten SAMPLE:0:16 + hundred SAMPLE:0:17 + million SAMPLE:0:18 + write_me SAMPLE:0:19 + bin SAMPLE:0:107 + bin_ctr SAMPLE:0:108 +} + +sample.longlong { + one SAMPLE:0:20 + ten SAMPLE:0:21 + hundred SAMPLE:0:22 + million SAMPLE:0:23 + write_me SAMPLE:0:24 + bin SAMPLE:0:109 + bin_ctr SAMPLE:0:110 +} + +sample.ulonglong { + one SAMPLE:0:98 + ten SAMPLE:0:99 + hundred SAMPLE:0:100 + million SAMPLE:0:101 + write_me SAMPLE:0:102 + bin SAMPLE:0:111 + bin_ctr SAMPLE:0:112 +} + +sample.double { + one SAMPLE:0:25 + ten SAMPLE:0:26 + hundred SAMPLE:0:27 + million SAMPLE:0:28 + write_me SAMPLE:0:29 + bin SAMPLE:0:113 + bin_ctr SAMPLE:0:114 +} + +sample.string { + null SAMPLE:0:30 + hullo SAMPLE:0:31 + write_me SAMPLE:0:32 +} + +sample.aggregate { + null SAMPLE:0:33 + hullo SAMPLE:0:34 + write_me SAMPLE:0:35 +} + +sample.hordes { + one SAMPLE:0:52 + two SAMPLE:0:53 +} + +sample.bad { + unknown SAMPLE:0:54 + nosupport SAMPLE:0:55 + novalues SAMPLE:0:138 +} + +sample.wrap { + long SAMPLE:0:57 + ulong SAMPLE:0:58 + longlong SAMPLE:0:59 + ulonglong SAMPLE:0:60 +} + +sample.dodgey { + control SAMPLE:0:61 + value SAMPLE:0:62 +} + +sample.scale_step { + bytes_up SAMPLE:0:65 + bytes_down SAMPLE:0:66 + count_up SAMPLE:0:67 + count_down SAMPLE:0:68 + time_up_secs SAMPLE:0:69 + time_up_nanosecs SAMPLE:0:70 + none_up SAMPLE:0:71 +} + +sample.const_rate { + value SAMPLE:0:72 + gradient SAMPLE:0:73 +} + +sample.dynamic { + counter SAMPLE:0:76 + discrete SAMPLE:0:77 + instant SAMPLE:0:78 + meta +} + +sample.dynamic.meta { + metric SAMPLE:0:86 + pmdesc +} + +sample.dynamic.meta.pmdesc { + type SAMPLE:0:87 + indom SAMPLE:0:88 + sem SAMPLE:0:89 + units SAMPLE:0:90 +} + +sample.many { + count SAMPLE:0:79 + int SAMPLE:0:80 +} + +sample.scramble { + version SAMPLE:0:120 + bin SAMPLE:0:121 +} + +sample.percontext { + control + pdu SAMPLE:0:43 + recv_pdu SAMPLE:0:44 + xmit_pdu SAMPLE:0:45 +} + +sample.percontext.control { + ctx SAMPLE:0:122 + active SAMPLE:0:123 + start SAMPLE:0:124 + end SAMPLE:0:125 +} + +sample.event { + records SAMPLE:0:136 + highres_records SAMPLE:0:139 + no_indom_records SAMPLE:0:137 + reset SAMPLE:0:126 + reset_highres SAMPLE:0:140 + type SAMPLE:0:127 + param_32 SAMPLE:0:128 + param_u32 SAMPLE:0:129 + param_64 SAMPLE:0:130 + param_u64 SAMPLE:0:131 + param_float SAMPLE:0:132 + param_double SAMPLE:0:133 + param_string SAMPLE:0:134 + param_aggregate SAMPLE:0:135 +} diff --git a/src/pmdas/sample/root b/src/pmdas/sample/root new file mode 100644 index 0000000..4f87c8e --- /dev/null +++ b/src/pmdas/sample/root @@ -0,0 +1,20 @@ +/* + * fake "root" for validating the local PMNS subtree + */ + +#include <stdpmid> + +root { + sample + sampledso +} + +#include "pmns" + +#define sample sampledso +#ifdef SAMPLE +#undef SAMPLE +#endif +#define SAMPLE 30 +#include "pmns" + diff --git a/src/pmdas/sample/src/GNUmakefile b/src/pmdas/sample/src/GNUmakefile new file mode 100644 index 0000000..78ed5ad --- /dev/null +++ b/src/pmdas/sample/src/GNUmakefile @@ -0,0 +1,62 @@ +# +# Copyright (c) 2014 Red Hat. +# Copyright (c) 2000,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 + +# +# The TARGETS macro must be set to the name of the executable we +# are building. +# +IAM = sample +DOMAIN = SAMPLE +CMDTARGET = pmda$(IAM)$(EXECSUFFIX) +LIBTARGET = pmda_$(IAM).$(DSOSUFFIX) +TARGETS = $(CMDTARGET) $(LIBTARGET) + +PMDAINIT = $(IAM)_init +PMDADIR = $(PCP_PMDAS_DIR)/sample + +CFILES = pmda.c sample.c percontext.c events.c +HFILES = percontext.h events.h +VERSION_SCRIPT = exports + +LDIRT = domain.h sample.log $(TARGETS) $(VERSION_SCRIPT) +LCFLAGS += $(INVISIBILITY) +LLDLIBS = $(PCP_PMDALIB) $(LIB_FOR_RT) +LSRCFILES = GNUmakefile.install + +default: domain.h $(TARGETS) + +pmda.o sample.o percontext.o: percontext.h +sample.o events.o: events.h +pmda.o: $(VERSION_SCRIPT) + +domain.h: ../../../pmns/stdpmid + $(DOMAIN_MAKERULE) + +$(VERSION_SCRIPT): + $(VERSION_SCRIPT_MAKERULE) + +install: default + $(INSTALL) -m 755 -d $(PMDADIR) + $(INSTALL) -m 644 domain.h $(CFILES) $(HFILES) $(PMDADIR) + $(INSTALL) -m 644 GNUmakefile.install $(PMDADIR)/Makefile + +include $(BUILDRULES) + +default_pcp: default + +install_pcp: install diff --git a/src/pmdas/sample/src/GNUmakefile.install b/src/pmdas/sample/src/GNUmakefile.install new file mode 100644 index 0000000..37191d0 --- /dev/null +++ b/src/pmdas/sample/src/GNUmakefile.install @@ -0,0 +1,53 @@ +# +# Copyright (c) 2014 Red Hat. +# 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. +# + +SHELL = sh + +ifdef PCP_CONF +include $(PCP_CONF) +else +include $(PCP_DIR)/etc/pcp.conf +endif +include $(PCP_INC_DIR)/builddefs + +# remove -Lpath and -Ipath options from builddefs CFLAGS value +# +PCP_LIBS = +TMP := $(CFLAGS:-I%=) +ifdef PCP_DIR +# put -Ipath and -Lpath back but use paths for run-time environment +# +CFLAGS = $(TMP) -I$(PCP_INC_DIR)/.. +LDFLAGS = -L$(PCP_LIB_DIR) +else +CFLAGS = $(TMP) +endif + +IAM = sample +CFILES = pmda.c sample.c percontext.c events.c +HFILES = percontext.h events.h + +LIBTARGET = pmda_$(IAM).$(DSOSUFFIX) +CMDTARGET = pmda$(IAM) +TARGETS = $(LIBTARGET) $(CMDTARGET) + +LLDLIBS = -lpcp_pmda -lpcp $(LIB_FOR_MATH) $(LIB_FOR_PTHREADS) $(LIB_FOR_RT) +LDIRT = *.log help.dir help.pag + +default: $(TARGETS) + +install: default + +include $(PCP_INC_DIR)/buildrules diff --git a/src/pmdas/sample/src/events.c b/src/pmdas/sample/src/events.c new file mode 100644 index 0000000..cc1cf62 --- /dev/null +++ b/src/pmdas/sample/src/events.c @@ -0,0 +1,477 @@ +/* + * The "event" records here are all fake. But the logic does show how + * a real PMDA could deliver values for metrics of type PM_TYPE_EVENT + * and PM_TYPE_HIGHRES_EVENT. + * + * Copyright (c) 2014 Red Hat. + * Copyright (c) 2010 Ken McDonell. 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 <pcp/pmapi.h> +#include <pcp/impl.h> +#include <pcp/pmda.h> +#include "events.h" + +static int nfetch; +static int xnfetch; +static int myarray[2]; + +static int nhrfetch; +static int xnhrfetch; +static int hrarray[2]; + +/* event parameters */ +static pmValueBlock *aggr; +static char aggrval[] = { '\01', '\03', '\07', '\017', '\037', '\077', '\177', '\377' }; +static pmID pmid_type = PMDA_PMID(0,127); /* event.type */ +static pmID pmid_32 = PMDA_PMID(0,128); /* event.param_32 */ +static pmID pmid_u32 = PMDA_PMID(0,129); /* event.param_u32 */ +static pmID pmid_64 = PMDA_PMID(0,130); /* event.param_64 */ +static pmID pmid_u64 = PMDA_PMID(0,131); /* event.param_u64 */ +static pmID pmid_float = PMDA_PMID(0,132); /* event.param_float */ +static pmID pmid_double = PMDA_PMID(0,133); /* event.param_double */ +static pmID pmid_string = PMDA_PMID(0,134); /* event.param_string */ +static pmID pmid_aggregate = PMDA_PMID(0,135); /* event.param_aggregate */ + +void +init_events(int domain) +{ + int i, sts; + + /* + * fix the domain field in the event parameter PMIDs ... + * note these PMIDs must match the corresponding metrics in + * desctab[] and this cannot easily be done automatically + */ + ((__pmID_int *)&pmid_type)->domain = domain; + ((__pmID_int *)&pmid_32)->domain = domain; + ((__pmID_int *)&pmid_u32)->domain = domain; + ((__pmID_int *)&pmid_64)->domain = domain; + ((__pmID_int *)&pmid_u64)->domain = domain; + ((__pmID_int *)&pmid_float)->domain = domain; + ((__pmID_int *)&pmid_double)->domain = domain; + ((__pmID_int *)&pmid_string)->domain = domain; + ((__pmID_int *)&pmid_aggregate)->domain = domain; + + /* build pmValueBlock for aggregate value */ + aggr = (pmValueBlock *)malloc(PM_VAL_HDR_SIZE + sizeof(aggrval)); + aggr->vtype = PM_TYPE_AGGREGATE; + aggr->vlen = PM_VAL_HDR_SIZE + sizeof(aggrval); + memcpy(aggr->vbuf, (void *)aggrval, sizeof(aggrval)); + + /* setup event arrays for 2 instances */ + for (i = 0; i < 2; i++) { + if ((sts = myarray[i] = pmdaEventNewArray()) < 0) + fprintf(stderr, "pmdaEventNewArray: %s\n", pmErrStr(sts)); + if ((sts = hrarray[i] = pmdaEventNewHighResArray()) < 0) + fprintf(stderr, "pmdaEventNewHighResArray: %s\n", pmErrStr(sts)); + } +} + +int +event_get_fetch_count(void) +{ + return nfetch % 4; +} + +void +event_set_fetch_count(int c) +{ + xnfetch = nfetch = c; +} + +int +sample_fetch_events(pmValueBlock **vbpp, int inst) +{ + int c; + int sts; + int flags; + struct timeval stamp; + pmAtomValue atom; + + if (nfetch >= 0) + c = nfetch % 4; + else /* one of the error injection cases */ + c = nfetch; + + if (inst == PM_IN_NULL || inst > 1 || inst < 0) + inst = 1; + + pmdaEventResetArray(myarray[inst]); + gettimeofday(&stamp, NULL); + + if (inst == 0) { + /* original instance ... */ + /* rebase event records 10 secs in past, add 1 sec for each new record */ + stamp.tv_sec -= 10; + + switch (c) { + case 0: + /* + * 1st fetch + * No events + */ + break; + case 1: + /* + * 2nd fetch + * 1 event with NO parameters + */ + flags = PM_EVENT_FLAG_POINT; + if ((sts = pmdaEventAddRecord(myarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + break; + case 2: + /* + * 3rd fetch + * 1 event with one U32 parameter + * 1 event with 2 parameters(U32 and 64 types) + */ + flags = PM_EVENT_FLAG_POINT; + if ((sts = pmdaEventAddRecord(myarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = 1; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + if ((sts = pmdaEventAddRecord(myarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = 2; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + atom.ll = -3; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_64, PM_TYPE_64, &atom)) < 0) + return sts; + break; + case 3: + /* + * 4th fetch + * 1 event start with 3 parameters (U32, U64 and STRING types) + * 1 event with 3 parameters (U32 and 2 DOUBLE types) + * 1 event end with 6 (U32, U64, STRING, STRING, 32 and U32 types) + * 7 "missed" events + * 1 event with 3 parameters (U32, FLOAT and AGGREGATE types) + */ + flags = PM_EVENT_FLAG_START|PM_EVENT_FLAG_ID|PM_EVENT_FLAG_PARENT; + if ((sts = pmdaEventAddRecord(myarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = 4; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + atom.ull = 5; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_u64, PM_TYPE_U64, &atom)) < 0) + return sts; + atom.cp = "6"; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_string, PM_TYPE_STRING, &atom)) < 0) + return sts; + flags = PM_EVENT_FLAG_POINT; + if ((sts = pmdaEventAddRecord(myarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = 7; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + atom.d = 8; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_double, PM_TYPE_DOUBLE, &atom)) < 0) + return sts; + atom.d = -9; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_double, PM_TYPE_DOUBLE, &atom)) < 0) + return sts; + flags = PM_EVENT_FLAG_END; + if ((sts = pmdaEventAddRecord(myarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = 10; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + atom.ull = 11; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_u64, PM_TYPE_U64, &atom)) < 0) + return sts; + atom.cp = "twelve"; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_string, PM_TYPE_STRING, &atom)) < 0) + return sts; + atom.cp = "thirteen"; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_string, PM_TYPE_STRING, &atom)) < 0) + return sts; + atom.l = -14; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_32, PM_TYPE_32, &atom)) < 0) + return sts; + atom.ul = 15; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_u32, PM_TYPE_U32, &atom)) < 0) + return sts; + /* "missed" 7 records */ + if ((sts = pmdaEventAddMissedRecord(myarray[inst], &stamp, 7)) < 0) + return sts; + stamp.tv_sec++; + flags = PM_EVENT_FLAG_POINT; + if ((sts = pmdaEventAddRecord(myarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = 16; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + atom.f = -17; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_float, PM_TYPE_FLOAT, &atom)) < 0) + return sts; + atom.vbp = aggr; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_aggregate, PM_TYPE_AGGREGATE, &atom)) < 0) + return sts; + break; + case -1: + /* error injection */ + flags = PM_EVENT_FLAG_POINT; + if ((sts = pmdaEventAddRecord(myarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = c; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + /* pmid that is not in PMNS and not known to the PMDA */ + if ((sts = pmdaEventAddParam(myarray[inst], PMDA_PMID(100,200), PM_TYPE_U32, &atom)) < 0) + return sts; + break; + } + nfetch++; + } + else { + /* + * new, boring instance ..., either instance ["bogus"] for + * sample.events.rrecord or singular instance for + * sample.events.no_indom_records + */ + static char hrecord1[20]; + static char hrecord2[] = "bingo!"; + + flags = PM_EVENT_FLAG_POINT; + if ((sts = pmdaEventAddRecord(myarray[inst], &stamp, flags)) < 0) + return sts; + snprintf(hrecord1, sizeof(hrecord1), "fetch #%d", xnfetch); + atom.cp = hrecord1; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_string, PM_TYPE_STRING, &atom)) < 0) + return sts; + if ((xnfetch % 3) == 0) { + if ((sts = pmdaEventAddRecord(myarray[inst], &stamp, flags)) < 0) + return sts; + atom.cp = hrecord2; + if ((sts = pmdaEventAddParam(myarray[inst], pmid_string, PM_TYPE_STRING, &atom)) < 0) + return sts; + } + xnfetch++; + } + + *vbpp = (pmValueBlock *)pmdaEventGetAddr(myarray[inst]); + + return 0; +} + +int +event_get_highres_fetch_count(void) +{ + return nhrfetch % 4; +} + +void +event_set_highres_fetch_count(int c) +{ + xnhrfetch = nhrfetch = c; +} + +int +sample_fetch_highres_events(pmValueBlock **vbpp, int inst) +{ + int c; + int sts; + int flags; + struct timespec stamp; + pmAtomValue atom; + + if (nhrfetch >= 0) + c = nhrfetch % 4; + else /* one of the error injection cases */ + c = nhrfetch; + + if (inst == PM_IN_NULL || inst > 1 || inst < 0) + inst = 1; + + pmdaEventResetHighResArray(hrarray[inst]); + __pmGetTimespec(&stamp); + + if (inst == 0) { + /* original instance ... */ + /* rebase event records 10 secs in past, add 1 sec for each new record */ + stamp.tv_sec -= 10; + + switch (c) { + case 0: + /* + * 1st fetch + * No events + */ + break; + case 1: + /* + * 2nd fetch + * 1 event with NO parameters + */ + flags = PM_EVENT_FLAG_POINT; + if ((sts = pmdaEventAddHighResRecord(hrarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + break; + case 2: + /* + * 3rd fetch + * 1 event with one U32 parameter + * 1 event with 2 parameters(U32 and 64 types) + */ + flags = PM_EVENT_FLAG_POINT; + if ((sts = pmdaEventAddHighResRecord(hrarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = 1; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + if ((sts = pmdaEventAddHighResRecord(hrarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = 2; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + atom.ll = -3; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_64, PM_TYPE_64, &atom)) < 0) + return sts; + break; + case 3: + /* + * 4th fetch + * 1 event start with 3 parameters (U32, U64 and STRING types) + * 1 event with 3 parameters (U32 and 2 DOUBLE types) + * 1 event end with 6 (U32, U64, STRING, STRING, 32 and U32 types) + * 7 "missed" events + * 1 event with 3 parameters (U32, FLOAT and AGGREGATE types) + */ + flags = PM_EVENT_FLAG_START|PM_EVENT_FLAG_ID|PM_EVENT_FLAG_PARENT; + if ((sts = pmdaEventAddHighResRecord(hrarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = 4; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + atom.ull = 5; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_u64, PM_TYPE_U64, &atom)) < 0) + return sts; + atom.cp = "6"; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_string, PM_TYPE_STRING, &atom)) < 0) + return sts; + flags = PM_EVENT_FLAG_POINT; + if ((sts = pmdaEventAddHighResRecord(hrarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = 7; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + atom.d = 8; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_double, PM_TYPE_DOUBLE, &atom)) < 0) + return sts; + atom.d = -9; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_double, PM_TYPE_DOUBLE, &atom)) < 0) + return sts; + flags = PM_EVENT_FLAG_END; + if ((sts = pmdaEventAddHighResRecord(hrarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = 10; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + atom.ull = 11; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_u64, PM_TYPE_U64, &atom)) < 0) + return sts; + atom.cp = "twelve"; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_string, PM_TYPE_STRING, &atom)) < 0) + return sts; + atom.cp = "thirteen"; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_string, PM_TYPE_STRING, &atom)) < 0) + return sts; + atom.l = -14; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_32, PM_TYPE_32, &atom)) < 0) + return sts; + atom.ul = 15; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_u32, PM_TYPE_U32, &atom)) < 0) + return sts; + /* "missed" 7000 records */ + if ((sts = pmdaEventAddHighResMissedRecord(hrarray[inst], &stamp, 7000)) < 0) + return sts; + stamp.tv_sec++; + flags = PM_EVENT_FLAG_POINT; + if ((sts = pmdaEventAddHighResRecord(hrarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = 16; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + atom.f = -17; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_float, PM_TYPE_FLOAT, &atom)) < 0) + return sts; + atom.vbp = aggr; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_aggregate, PM_TYPE_AGGREGATE, &atom)) < 0) + return sts; + break; + case -1: + /* error injection */ + flags = PM_EVENT_FLAG_POINT; + if ((sts = pmdaEventAddHighResRecord(hrarray[inst], &stamp, flags)) < 0) + return sts; + stamp.tv_sec++; + atom.ul = c; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_type, PM_TYPE_U32, &atom)) < 0) + return sts; + /* pmid that is not in PMNS and not known to the PMDA */ + if ((sts = pmdaEventHighResAddParam(hrarray[inst], PMDA_PMID(100,200), PM_TYPE_U32, &atom)) < 0) + return sts; + break; + } + nhrfetch++; + } + else { + /* + * new, boring instance ..., either instance ["bogus"] for + * sample.events.rrecord or singular instance for + * sample.events.no_indom_records + */ + static char record1[20]; + static char record2[] = "bingo!"; + + flags = PM_EVENT_FLAG_POINT; + if ((sts = pmdaEventAddHighResRecord(hrarray[inst], &stamp, flags)) < 0) + return sts; + snprintf(record1, sizeof(record1), "fetch #%d", xnhrfetch); + atom.cp = record1; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_string, PM_TYPE_STRING, &atom)) < 0) + return sts; + if ((xnhrfetch % 3) == 0) { + if ((sts = pmdaEventAddHighResRecord(hrarray[inst], &stamp, flags)) < 0) + return sts; + atom.cp = record2; + if ((sts = pmdaEventHighResAddParam(hrarray[inst], pmid_string, PM_TYPE_STRING, &atom)) < 0) + return sts; + } + xnhrfetch++; + } + + *vbpp = (pmValueBlock *)pmdaEventHighResGetAddr(hrarray[inst]); + + return 0; +} diff --git a/src/pmdas/sample/src/events.h b/src/pmdas/sample/src/events.h new file mode 100644 index 0000000..d7dd1b5 --- /dev/null +++ b/src/pmdas/sample/src/events.h @@ -0,0 +1,33 @@ +/* + * The "event" records here are all fake. But the logic does show how + * a real PMDA could deliver values for metrics of type PM_TYPE_EVENT. + * and PM_TYPE_HIGHRES_EVENT. + * + * Copyright (c) 2014 Red Hat. + * Copyright (c) 2010 Ken McDonell. 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. + */ + +#ifndef _EVENTS_H +#define _EVENTS_H + +extern void init_events(int); + +extern int sample_fetch_events(pmValueBlock **, int); +extern void event_set_fetch_count(int); +extern int event_get_fetch_count(void); + +extern int sample_fetch_highres_events(pmValueBlock **, int); +extern void event_set_highres_fetch_count(int); +extern int event_get_highres_fetch_count(void); + +#endif /* _EVENTS_H */ diff --git a/src/pmdas/sample/src/percontext.c b/src/pmdas/sample/src/percontext.c new file mode 100644 index 0000000..0c549df --- /dev/null +++ b/src/pmdas/sample/src/percontext.c @@ -0,0 +1,256 @@ +/* + * Some functions become per-client (of pmcd) with the introduction + * of PMDA_INTERFACE_5. + * + * Copyright (c) 2010 Ken McDonell. 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 <pcp/pmapi.h> +#include <pcp/impl.h> +#include <pcp/pmda.h> +#include "percontext.h" + +typedef struct { + int state; /* active or inactive context */ + int recv_pdu; /* count of PDUs received from this context */ + int xmit_pdu; /* count of PDUs sent to this context */ +} perctx_t; + +/* values for state */ +#define CTX_INACTIVE 0 +#define CTX_ACTIVE 1 + +static perctx_t *ctxtab; +static int num_ctx; +static int num_start; /* count of new contexts noted */ +static int num_end; /* count of end context events */ +static int num_recv_pdu; /* recv count from closed contexts */ +static int num_xmit_pdu; /* xmit count from closed contexts */ + +void +sample_clr_recv(int ctx) +{ + if (ctx == CTX_ALL) { + int i; + for (i = 0; i < num_ctx; i++) { + if (ctxtab[i].state == CTX_ACTIVE) + ctxtab[i].recv_pdu = 0; + } + num_recv_pdu = 0; + } + else if (ctx < 0 || ctx >= num_ctx || ctxtab[ctx].state == CTX_INACTIVE) { + fprintf(stderr, "Botch: sample_clr_recv(%d) num_ctx=%d", ctx, num_ctx); + if (ctx >= 0 && ctx < num_ctx) + fprintf(stderr, " ctxtab[] is inactive"); + fputc('\n', stderr); + } + else + ctxtab[ctx].recv_pdu = 0; +} + +void +sample_clr_xmit(int ctx) +{ + if (ctx == CTX_ALL) { + int i; + for (i = 0; i < num_ctx; i++) { + if (ctxtab[i].state == CTX_ACTIVE) + ctxtab[i].xmit_pdu = 0; + } + num_xmit_pdu = 0; + } + else if (ctx < 0 || ctx >= num_ctx || ctxtab[ctx].state == CTX_INACTIVE) { + fprintf(stderr, "Botch: sample_clr_xmit(%d) num_ctx=%d", ctx, num_ctx); + if (ctx >= 0 && ctx < num_ctx) + fprintf(stderr, " ctxtab[] is inactive"); + fputc('\n', stderr); + } + else + ctxtab[ctx].xmit_pdu = 0; +} + +int +sample_get_recv(int ctx) +{ + if (ctx == CTX_ALL) { + int i; + int ans = num_recv_pdu; + for (i = 0; i < num_ctx; i++) { + if (ctxtab[i].state == CTX_ACTIVE) + ans += ctxtab[i].recv_pdu; + } + return ans; + } + else if (ctx < 0 || ctx >= num_ctx || ctxtab[ctx].state == CTX_INACTIVE) { + return PM_ERR_NOCONTEXT; + } + else + return ctxtab[ctx].recv_pdu; +} + +int +sample_get_xmit(int ctx) +{ + if (ctx == CTX_ALL) { + int i; + int ans = num_xmit_pdu; + for (i = 0; i < num_ctx; i++) { + if (ctxtab[i].state == CTX_ACTIVE) + ans += ctxtab[i].xmit_pdu; + } + return ans; + } + else if (ctx < 0 || ctx >= num_ctx || ctxtab[ctx].state == CTX_INACTIVE) { + return PM_ERR_NOCONTEXT; + } + else + return ctxtab[ctx].xmit_pdu; +} + +static void +growtab(int ctx) +{ + ctxtab = (perctx_t *)realloc(ctxtab, (ctx+1)*sizeof(ctxtab[0])); + if (ctxtab == NULL) { + __pmNoMem("growtab", (ctx+1)*sizeof(ctxtab[0]), PM_FATAL_ERR); + /*NOTREACHED*/ + } + while (num_ctx <= ctx) { + ctxtab[num_ctx].state = CTX_INACTIVE; + ctxtab[num_ctx].recv_pdu = 0; + ctxtab[num_ctx].xmit_pdu = 0; + num_ctx++; + } + ctxtab[ctx].state = CTX_INACTIVE; +} + +void +sample_inc_recv(int ctx) +{ + if (ctx < 0) { + fprintf(stderr, "Botch: sample_inc_recv(%d)!\n", ctx); + return; + } + if (ctx >= num_ctx) growtab(ctx); + if (ctxtab[ctx].state == CTX_INACTIVE) { + num_start++; + ctxtab[ctx].state = CTX_ACTIVE; + ctxtab[ctx].recv_pdu = 0; + ctxtab[ctx].xmit_pdu = 0; +#ifdef PCP_DEBUG + if (pmDebug & DBG_TRACE_APPL1) { + fprintf(stderr, "sample_inc_recv(%d) [new context, num_ctx=%d]\n", ctx, num_ctx); + } +#endif + } + ctxtab[ctx].recv_pdu++; +} + +void +sample_inc_xmit(int ctx) +{ + if (ctx < 0 || ctx >= num_ctx || ctxtab[ctx].state == CTX_INACTIVE) { + fprintf(stderr, "Botch: sample_inc_xmit(%d) num_ctx=%d", ctx, num_ctx); + if (ctx >= 0 && ctx < num_ctx) + fprintf(stderr, " ctxtab[] is inactive"); + fputc('\n', stderr); + return; + } + if (ctx >= num_ctx) + growtab(ctx); + ctxtab[ctx].xmit_pdu++; +} + +int +sample_ctx_fetch(int ctx, int item) +{ + if (ctx < 0 || ctx >= num_ctx || ctxtab[ctx].state == CTX_INACTIVE) { + fprintf(stderr, "Botch: sample_ctx_fetch(%d, %d) num_ctx=%d", ctx, item, num_ctx); + if (ctx >= 0 && ctx < num_ctx) + fprintf(stderr, " ctxtab[] is inactive"); + fputc('\n', stderr); + return PM_ERR_NOCONTEXT; + } + + if (item == 43) { + /* percontext.pdu */ + return ctxtab[ctx].recv_pdu + ctxtab[ctx].xmit_pdu; + } + else if (item == 44) { + /* percontext.recv-pdu */ + return ctxtab[ctx].recv_pdu; + } + else if (item == 45) { + /* percontext.xmit-pdu */ + return ctxtab[ctx].xmit_pdu; + } + else if (item == 122) { + /* percontext.control.ctx */ + return num_ctx; + } + else if (item == 123) { + /* percontext.control.active */ + int i; + int ans = 0; + for (i = 0; i < num_ctx; i++) { + if (ctxtab[i].state == CTX_ACTIVE) + ans++; + } + return ans; + } + else if (item == 124) { + /* percontext.control.start */ + return num_start; + } + else if (item == 125) { + /* percontext.control.end */ + return num_end; + } + + fprintf(stderr, "Botch: sample_ctx_fetch(%d, %d): item bad!\n", ctx, item); + return PM_ERR_PMID; +} + +void +sample_ctx_end(int ctx) +{ +#ifdef PCP_DEBUG + if (pmDebug & DBG_TRACE_APPL1) { + fprintf(stderr, "sample_ctx_end(%d) [context is ", ctx); + if (ctx < 0 || ctx >= num_ctx) + fprintf(stderr, "unknown, num_ctx=%d", num_ctx); + else if (ctxtab[ctx].state == CTX_ACTIVE) + fprintf(stderr, "active"); + else if (ctxtab[ctx].state == CTX_INACTIVE) + fprintf(stderr, "inactive"); + else + fprintf(stderr, "botched state, %d", ctxtab[ctx].state); + fprintf(stderr, "]\n"); + } +#endif + if (ctx < 0 || ctx >= num_ctx || ctxtab[ctx].state == CTX_INACTIVE) { + /* + * This is expected ... when a context is closed in pmcd + * (or for a local context or for dbpmda or ...) all the + * PMDAs with a registered pmdaEndContextCallBack will be + * called end some of the PMDAs may not have not serviced + * any previous requests for that context. + */ + return; + } + num_end++; + num_recv_pdu += ctxtab[ctx].recv_pdu; + num_xmit_pdu += ctxtab[ctx].xmit_pdu; + ctxtab[ctx].state = CTX_INACTIVE; +} + diff --git a/src/pmdas/sample/src/percontext.h b/src/pmdas/sample/src/percontext.h new file mode 100644 index 0000000..151fba6 --- /dev/null +++ b/src/pmdas/sample/src/percontext.h @@ -0,0 +1,31 @@ +/* + * Some functions become per-client (of pmcd) with the introduction + * of PMDA_INTERFACE_5. + * + * Copyright (c) 2010 Ken McDonell. 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. + */ +#ifndef _PERCONTEXT_H +#define _PERCONTEXT_H + +extern int sample_get_recv(int); +extern int sample_get_xmit(int); +extern void sample_clr_recv(int); +extern void sample_clr_xmit(int); +extern void sample_inc_recv(int); +extern void sample_inc_xmit(int); +extern int sample_ctx_fetch(int, int); +extern void sample_ctx_end(int); + +#define CTX_ALL -1 + +#endif /* _PERCONTEXT_H */ diff --git a/src/pmdas/sample/src/pmda.c b/src/pmdas/sample/src/pmda.c new file mode 100644 index 0000000..c1449fb --- /dev/null +++ b/src/pmdas/sample/src/pmda.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014 Red Hat. + * Copyright (c) 1997-2002 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. + */ + +/* + * Generic driver for a daemon-based PMDA + */ + +#include <pcp/pmapi.h> +#include <pcp/impl.h> +#include <pcp/pmda.h> +#include "domain.h" +#include "percontext.h" + +extern void sample_init(pmdaInterface *); +extern int sample_done; +extern int not_ready; +extern int _isDSO; + +static pmdaInterface dispatch; +static pmLongOptions longopts[] = { + PMDA_OPTIONS_HEADER("Options"), + PMOPT_DEBUG, + PMDAOPT_DOMAIN, + PMDAOPT_LOGFILE, + PMDAOPT_USERNAME, + PMOPT_HELP, + PMDA_OPTIONS_TEXT("\nExactly one of the following options may appear:"), + PMDAOPT_INET, + PMDAOPT_PIPE, + PMDAOPT_UNIX, + PMDAOPT_IPV6, + PMDA_OPTIONS_END +}; +static pmdaOptions opts = { + .short_options = "D:d:i:l:pu:U:6:?", + .long_options = longopts, +}; + +/* + * simulate PMDA busy (not responding to PDUs) + */ +int +limbo(void) +{ + __pmSendError(dispatch.version.two.ext->e_outfd, FROM_ANON, PM_ERR_PMDANOTREADY); + while (not_ready > 0) + not_ready = sleep(not_ready); + return PM_ERR_PMDAREADY; +} + +/* + * callback from pmdaMain + */ +static int +check(void) +{ + if (access("/tmp/sample.unavail", F_OK) == 0) + return PM_ERR_AGAIN; + return 0; +} + +/* + * callback from pmdaMain + */ +static void +done(void) +{ + if (sample_done) + exit(0); +} + +int +main(int argc, char **argv) +{ + int sep = __pmPathSeparator(); + char helppath[MAXPATHLEN]; + char *username; + + _isDSO = 0; + __pmSetProgname(argv[0]); + __pmGetUsername(&username); + + snprintf(helppath, sizeof(helppath), "%s%c" "sample" "%c" "help", + pmGetConfig("PCP_PMDAS_DIR"), sep, sep); + pmdaDaemon(&dispatch, PMDA_INTERFACE_LATEST, pmProgname, SAMPLE, + "sample.log", helppath); + + pmdaGetOptions(argc, argv, &opts, &dispatch); + if (opts.errors) { + pmdaUsageMessage(&opts); + exit(1); + } + pmdaOpenLog(&dispatch); + if (opts.username) + username = opts.username; + __pmSetProcessIdentity(username); + + sample_init(&dispatch); + pmdaSetCheckCallBack(&dispatch, check); + pmdaSetDoneCallBack(&dispatch, done); + pmdaConnect(&dispatch); + +#ifdef HAVE_SIGHUP + /* + * Non-DSO agents should ignore gratuitous SIGHUPs, e.g. from a + * terminal when launched by the PCP Tutorial! + */ + signal(SIGHUP, SIG_IGN); +#endif + + pmdaMain(&dispatch); + + exit(0); +} diff --git a/src/pmdas/sample/src/sample.c b/src/pmdas/sample/src/sample.c new file mode 100644 index 0000000..13a1328 --- /dev/null +++ b/src/pmdas/sample/src/sample.c @@ -0,0 +1,2748 @@ +/* + * Copyright (c) 2014 Red Hat. + * 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 <limits.h> +#include <sys/stat.h> +#include <pcp/pmapi.h> +#include <pcp/impl.h> +#include <pcp/pmda.h> +#include "percontext.h" +#include "events.h" +#include "domain.h" +#ifdef HAVE_SYSINFO +/* + * On Solaris, need <sys/systeminfo.h> and sysinfo() is different. + * Other platforms need <sys/sysinfo.h> + */ +#ifdef IS_SOLARIS +#include <sys/systeminfo.h> +#define MAX_SYSNAME 257 +#else +#include <sys/sysinfo.h> +#endif +#else +static struct sysinfo { + char dummy[64]; +} si = { { +'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', +'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', +'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', +'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '9', '[', ']', '.' +} }; +#endif + +static int need_mirage; /* only do mirage glop is someone asks for it */ +static int need_dynamic;/* only do dynamic glop is someone asks for it */ + +/* from pmda.c: simulate PMDA busy */ +extern int limbo(void); + +/* + * all metrics supported in this PMD - one table entry for each + */ + +static pmDesc desctab[] = { +/* control */ + { PMDA_PMID(0,0), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* daemon-pid */ + { PMDA_PMID(0,1), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* seconds */ + { PMDA_PMID(0,2), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_SEC,0) }, +/* milliseconds */ + { PMDA_PMID(0,3), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, +/* load */ + { PMDA_PMID(0,4), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* colour */ + { PMDA_PMID(0,5), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* bin */ + { PMDA_PMID(0,6), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* drift */ + { PMDA_PMID(0,7), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* step */ + { PMDA_PMID(0,8), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* noinst */ + { PMDA_PMID(0,9), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* long.one */ + { PMDA_PMID(0,10), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* long.ten */ + { PMDA_PMID(0,11), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* long.hundred */ + { PMDA_PMID(0,12), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* long.million */ + { PMDA_PMID(0,13), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* long.write_me */ + { PMDA_PMID(0,14), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* float.one */ + { PMDA_PMID(0,15), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* float.ten */ + { PMDA_PMID(0,16), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* float.hundred */ + { PMDA_PMID(0,17), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* float.million */ + { PMDA_PMID(0,18), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* float.write_me */ + { PMDA_PMID(0,19), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* longlong.one */ + { PMDA_PMID(0,20), PM_TYPE_64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* longlong.ten */ + { PMDA_PMID(0,21), PM_TYPE_64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* longlong.hundred */ + { PMDA_PMID(0,22), PM_TYPE_64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* longlong.million */ + { PMDA_PMID(0,23), PM_TYPE_64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* longlong.write_me */ + { PMDA_PMID(0,24), PM_TYPE_64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* double.one */ + { PMDA_PMID(0,25), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* double.ten */ + { PMDA_PMID(0,26), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* double.hundred */ + { PMDA_PMID(0,27), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* double.million */ + { PMDA_PMID(0,28), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* double.write_me */ + { PMDA_PMID(0,29), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* string.null */ + { PMDA_PMID(0,30), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* string.hullo */ + { PMDA_PMID(0,31), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* string.write_me */ + { PMDA_PMID(0,32), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* aggregate.null */ + { PMDA_PMID(0,33), PM_TYPE_AGGREGATE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* aggregate.hullo */ + { PMDA_PMID(0,34), PM_TYPE_AGGREGATE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* aggregate.write_me */ + { PMDA_PMID(0,35), PM_TYPE_AGGREGATE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* write_me */ + { PMDA_PMID(0,36), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,-1,1,0,PM_TIME_SEC,PM_COUNT_ONE) }, +/* mirage */ + { PMDA_PMID(0,37), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(1,-1,0,PM_SPACE_KBYTE,PM_TIME_SEC,0) }, +/* mirage-longlong */ + { PMDA_PMID(0,38), PM_TYPE_64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(1,-1,0,PM_SPACE_BYTE,PM_TIME_MSEC,0) }, +/* sysinfo */ + { PMDA_PMID(0,39), PM_TYPE_AGGREGATE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* pdu */ + { PMDA_PMID(0,40), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* recv-pdu */ + { PMDA_PMID(0,41), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* xmit-pdu */ + { PMDA_PMID(0,42), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* percontext.pdu */ + { PMDA_PMID(0,43), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* percontext.recv-pdu */ + { PMDA_PMID(0,44), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* percontext.xmit-pdu */ + { PMDA_PMID(0,45), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* lights */ + { PMDA_PMID(0,46), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* magnitude */ + { PMDA_PMID(0,47), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* bucket - alias for bin, but different PMID */ + { PMDA_PMID(0,48), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* needprofile - need explicit instance profile */ + { PMDA_PMID(0,49), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* part_bin - bin, minus an instance or two */ + { PMDA_PMID(0,50), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* bogus_bin - bin, plus an instance or two */ + { PMDA_PMID(0,51), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* hordes.one */ + { PMDA_PMID(0,52), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* hordes.two */ + { PMDA_PMID(0,53), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* bad.unknown */ + { PMDA_PMID(0,54), 0, 0, 0, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* bad.nosupport */ + { PMDA_PMID(0,55), PM_TYPE_NOSUPPORT, PM_INDOM_NULL, 0, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* not_ready */ + { PMDA_PMID(0,56), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* wrap.long */ + { PMDA_PMID(0,57), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* wrap.ulong */ + { PMDA_PMID(0,58), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* wrap.longlong */ + { PMDA_PMID(0,59), PM_TYPE_64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* wrap.ulonglong */ + { PMDA_PMID(0,60), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* dodgey.control */ + { PMDA_PMID(0,61), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* dodgey.value */ + { PMDA_PMID(0,62), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* step_counter */ + { PMDA_PMID(0,63), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* rapid */ + { PMDA_PMID(0,64), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* scale_step.bytes_up */ + { PMDA_PMID(0,65), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(1,-1,0,PM_SPACE_BYTE,PM_TIME_SEC,0) }, +/* scale_step.bytes_down */ + { PMDA_PMID(0,66), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, +/* scale_step.count_up */ + { PMDA_PMID(0,67), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,-1,1,0,PM_TIME_SEC,PM_COUNT_ONE) }, +/* scale_step.count_down */ + { PMDA_PMID(0,68), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* scale_step.time_up_secs */ + { PMDA_PMID(0,69), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,1,0,0,PM_TIME_SEC,0) }, +/* scale_step.time_up_nanosecs */ + { PMDA_PMID(0,70), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,1,0,0,PM_TIME_NSEC,0) }, +/* scale_step.none_up */ + { PMDA_PMID(0,71), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* const_rate.value */ + { PMDA_PMID(0,72), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* const_rate.gradient */ + { PMDA_PMID(0,73), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* error_code */ + { PMDA_PMID(0,74), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* error_check */ + { PMDA_PMID(0,75), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* dynamic.counter */ + { PMDA_PMID(0,76), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* dynamic.discrete */ + { PMDA_PMID(0,77), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* dynamic.instant */ + { PMDA_PMID(0,78), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* many.count */ + { PMDA_PMID(0,79), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,0) }, +/* many.int */ + { PMDA_PMID(0,80), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,0) }, +/* byte_ctr */ + { PMDA_PMID(0,81), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, +/* byte_rate */ + { PMDA_PMID(0,82), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(1,-1,0,PM_SPACE_BYTE,PM_TIME_SEC,0) }, +/* kbyte_ctr */ + { PMDA_PMID(0,83), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, +/* kbyte_rate */ + { PMDA_PMID(0,84), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(1,-1,0,PM_SPACE_KBYTE,PM_TIME_SEC,0) }, +/* byte_rate_per_hour */ + { PMDA_PMID(0,85), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(1,-1,0,PM_SPACE_BYTE,PM_TIME_HOUR,0) }, +/* dynamic.meta.metric - pmDesc here is a fake, use magic */ + { PMDA_PMID(0,86), 0, 0, 0, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* dynamic.meta.pmdesc.type */ + { PMDA_PMID(0,87), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* dynamic.meta.pmdesc.indom */ + { PMDA_PMID(0,88), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* dynamic.meta.pmdesc.sem */ + { PMDA_PMID(0,89), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* dynamic.meta.pmdesc.units */ + { PMDA_PMID(0,90), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* datasize */ + { PMDA_PMID(0,91), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, +/* darkness */ + { PMDA_PMID(0,92), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* ulong.one */ + { PMDA_PMID(0,93), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* ulong.ten */ + { PMDA_PMID(0,94), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* ulong.hundred */ + { PMDA_PMID(0,95), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* ulong.million */ + { PMDA_PMID(0,96), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* ulong.write_me */ + { PMDA_PMID(0,97), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* ulonglong.one */ + { PMDA_PMID(0,98), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* ulonglong.ten */ + { PMDA_PMID(0,99), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* ulonglong.hundred */ + { PMDA_PMID(0,100), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* ulonglong.million */ + { PMDA_PMID(0,101), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* ulonglong.write_me */ + { PMDA_PMID(0,102), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* long.bin */ + { PMDA_PMID(0,103), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* long.bin_ctr */ + { PMDA_PMID(0,104), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, +/* ulong.bin */ + { PMDA_PMID(0,105), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* ulong.bin_ctr */ + { PMDA_PMID(0,106), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, +/* float.bin */ + { PMDA_PMID(0,107), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* float.bin_ctr */ + { PMDA_PMID(0,108), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, +/* longlong.bin */ + { PMDA_PMID(0,109), PM_TYPE_64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* longlong.bin_ctr */ + { PMDA_PMID(0,110), PM_TYPE_64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, +/* ulonglong.bin */ + { PMDA_PMID(0,111), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* ulonglong.bin_ctr */ + { PMDA_PMID(0,112), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, +/* double.bin */ + { PMDA_PMID(0,113), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* double.bin_ctr */ + { PMDA_PMID(0,114), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_COUNTER, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, +/* sample.ulong.count.base */ + { PMDA_PMID(0,115), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(-1,0,1,PM_SPACE_MBYTE,0,PM_COUNT_ONE) }, +/* sample.ulong.count.deca */ + { PMDA_PMID(0,116), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(-1,0,1,PM_SPACE_MBYTE,0,PM_COUNT_ONE+1) }, +/* sample.ulong.count.hecto */ + { PMDA_PMID(0,117), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(-1,0,1,PM_SPACE_MBYTE,0,PM_COUNT_ONE+2) }, +/* sample.ulong.count.kilo */ + { PMDA_PMID(0,118), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(-1,0,1,PM_SPACE_MBYTE,0,PM_COUNT_ONE+3) }, +/* sample.ulong.count.mega */ + { PMDA_PMID(0,119), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(-1,0,1,PM_SPACE_MBYTE,0,PM_COUNT_ONE+6) }, +/* scramble.version */ + { PMDA_PMID(0,120), PM_TYPE_64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* scramble.bin */ + { PMDA_PMID(0,121), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* percontext.control.ctx */ + { PMDA_PMID(0,122), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* percontext.control.active */ + { PMDA_PMID(0,123), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* percontext.control.start */ + { PMDA_PMID(0,124), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* percontext.control.end */ + { PMDA_PMID(0,125), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* event.reset */ + { PMDA_PMID(0,126), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* event.type */ + { PMDA_PMID(0,127), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* event.param_32 */ + { PMDA_PMID(0,128), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* event.param_u32 */ + { PMDA_PMID(0,129), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* event.param_64 */ + { PMDA_PMID(0,130), PM_TYPE_64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* event.param_u64 */ + { PMDA_PMID(0,131), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* event.param_float */ + { PMDA_PMID(0,132), PM_TYPE_FLOAT, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* event.param_double */ + { PMDA_PMID(0,133), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* event.param_string */ + { PMDA_PMID(0,134), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* event.param_aggregate */ + { PMDA_PMID(0,135), PM_TYPE_AGGREGATE, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* event.records */ + { PMDA_PMID(0,136), PM_TYPE_EVENT, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* event.no_indom_records */ + { PMDA_PMID(0,137), PM_TYPE_EVENT, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* bad.novalues */ + { PMDA_PMID(0,138), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* event.highres_records */ + { PMDA_PMID(0,139), PM_TYPE_HIGHRES_EVENT, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* event.reset */ + { PMDA_PMID(0,140), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, + +/* + * dynamic PMNS ones + * secret.bar + */ + { PMDA_PMID(0,1000), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, +/* secret.foo.one */ + { PMDA_PMID(0,1001), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* secret.foo.two */ + { PMDA_PMID(0,1002), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* secret.foo.bar.three */ + { PMDA_PMID(0,1003), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* secret.foo.bar.four */ + { PMDA_PMID(0,1004), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* secret.foo.bar.grunt.five */ + { PMDA_PMID(0,1005), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* secret.foo.bar.grunt.snort.six */ + { PMDA_PMID(0,1006), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, +/* secret.foo.bar.grunt.snort.seven */ + { PMDA_PMID(0,1007), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, + +/* bigid */ + { PMDA_PMID(0,1023), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, + +/* End-of-List */ + { PM_ID_NULL, 0, 0, 0, { 0, 0, 0, 0, 0, 0 } } +}; +static int direct_map = 1; +static int ndesc = sizeof(desctab)/sizeof(desctab[0]); + +static pmDesc magic = + { PMDA_PMID(0,86), PM_TYPE_32, PM_INDOM_NULL, PM_SEM_DISCRETE, PMDA_PMUNITS(1,-1,0,PM_SPACE_BYTE,PM_TIME_SEC,0) }; + +static pmdaInstid _colour[] = { + { 0, "red" }, { 1, "green" }, { 2, "blue" } +}; + +static pmdaInstid _bin[] = { + { 100, "bin-100" }, { 200, "bin-200" }, { 300, "bin-300" }, + { 400, "bin-400" }, { 500, "bin-500" }, { 600, "bin-600" }, + { 700, "bin-700" }, { 800, "bin-800" }, { 900, "bin-900" } +}; + +static pmdaInstid _scramble[] = { + { 100, "bin-100" }, { 200, "bin-200" }, { 300, "bin-300" }, + { 400, "bin-400" }, { 500, "bin-500" }, { 600, "bin-600" }, + { 700, "bin-700" }, { 800, "bin-800" }, { 900, "bin-900" } +}; + +static long scramble_ver = 0; + +static pmdaInstid _family[] = { + { 0, "colleen" }, { 1, "terry" }, { 2, "emma" }, { 3, "cathy" }, { 4, "fat bald bastard" } +}; + +static pmdaInstid _dodgey[] = { + { 1, NULL}, { 2, NULL }, { 3, NULL }, { 4, NULL }, { 5, NULL } +}; + +static pmdaInstid _hordes[] = { + { 0, "0" }, { 1, "1" }, { 2, "2" }, { 3, "3" }, { 4, "4" }, + { 5, "5" }, { 6, "6" }, { 7, "7" }, { 8, "8" }, { 9, "9" }, + { 10, "10" }, { 11, "11" }, { 12, "12" }, { 13, "13" }, { 14, "14" }, + { 15, "15" }, { 16, "16" }, { 17, "17" }, { 18, "18" }, { 19, "19" }, + { 20, "20" }, { 21, "21" }, { 22, "22" }, { 23, "23" }, { 24, "24" }, + { 25, "25" }, { 26, "26" }, { 27, "27" }, { 28, "28" }, { 29, "29" }, + { 30, "30" }, { 31, "31" }, { 32, "32" }, { 33, "33" }, { 34, "34" }, + { 35, "35" }, { 36, "36" }, { 37, "37" }, { 38, "38" }, { 39, "39" }, + { 40, "40" }, { 41, "41" }, { 42, "42" }, { 43, "43" }, { 44, "44" }, + { 45, "45" }, { 46, "46" }, { 47, "47" }, { 48, "48" }, { 49, "49" }, + { 50, "50" }, { 51, "51" }, { 52, "52" }, { 53, "53" }, { 54, "54" }, + { 55, "55" }, { 56, "56" }, { 57, "57" }, { 58, "58" }, { 59, "59" }, + { 60, "60" }, { 61, "61" }, { 62, "62" }, { 63, "63" }, { 64, "64" }, + { 65, "65" }, { 66, "66" }, { 67, "67" }, { 68, "68" }, { 69, "69" }, + { 70, "70" }, { 71, "71" }, { 72, "72" }, { 73, "73" }, { 74, "74" }, + { 75, "75" }, { 76, "76" }, { 77, "77" }, { 78, "78" }, { 79, "79" }, + { 80, "80" }, { 81, "81" }, { 82, "82" }, { 83, "83" }, { 84, "84" }, + { 85, "85" }, { 86, "86" }, { 87, "87" }, { 88, "88" }, { 89, "89" }, + { 90, "90" }, { 91, "91" }, { 92, "92" }, { 93, "93" }, { 94, "94" }, + { 95, "95" }, { 96, "96" }, { 97, "97" }, { 98, "98" }, { 99, "99" }, + {100, "100" }, {101, "101" }, {102, "102" }, {103, "103" }, {104, "104" }, + {105, "105" }, {106, "106" }, {107, "107" }, {108, "108" }, {109, "109" }, + {110, "110" }, {111, "111" }, {112, "112" }, {113, "113" }, {114, "114" }, + {115, "115" }, {116, "116" }, {117, "117" }, {118, "118" }, {119, "119" }, + {120, "120" }, {121, "121" }, {122, "122" }, {123, "123" }, {124, "124" }, + {125, "125" }, {126, "126" }, {127, "127" }, {128, "128" }, {129, "129" }, + {130, "130" }, {131, "131" }, {132, "132" }, {133, "133" }, {134, "134" }, + {135, "135" }, {136, "136" }, {137, "137" }, {138, "138" }, {139, "139" }, + {140, "140" }, {141, "141" }, {142, "142" }, {143, "143" }, {144, "144" }, + {145, "145" }, {146, "146" }, {147, "147" }, {148, "148" }, {149, "149" }, + {150, "150" }, {151, "151" }, {152, "152" }, {153, "153" }, {154, "154" }, + {155, "155" }, {156, "156" }, {157, "157" }, {158, "158" }, {159, "159" }, + {160, "160" }, {161, "161" }, {162, "162" }, {163, "163" }, {164, "164" }, + {165, "165" }, {166, "166" }, {167, "167" }, {168, "168" }, {169, "169" }, + {170, "170" }, {171, "171" }, {172, "172" }, {173, "173" }, {174, "174" }, + {175, "175" }, {176, "176" }, {177, "177" }, {178, "178" }, {179, "179" }, + {180, "180" }, {181, "181" }, {182, "182" }, {183, "183" }, {184, "184" }, + {185, "185" }, {186, "186" }, {187, "187" }, {188, "188" }, {189, "189" }, + {190, "190" }, {191, "191" }, {192, "192" }, {193, "193" }, {194, "194" }, + {195, "195" }, {196, "196" }, {197, "197" }, {198, "198" }, {199, "199" }, + {200, "200" }, {201, "201" }, {202, "202" }, {203, "203" }, {204, "204" }, + {205, "205" }, {206, "206" }, {207, "207" }, {208, "208" }, {209, "209" }, + {210, "210" }, {211, "211" }, {212, "212" }, {213, "213" }, {214, "214" }, + {215, "215" }, {216, "216" }, {217, "217" }, {218, "218" }, {219, "219" }, + {220, "220" }, {221, "221" }, {222, "222" }, {223, "223" }, {224, "224" }, + {225, "225" }, {226, "226" }, {227, "227" }, {228, "228" }, {229, "229" }, + {230, "230" }, {231, "231" }, {232, "232" }, {233, "233" }, {234, "234" }, + {235, "235" }, {236, "236" }, {237, "237" }, {238, "238" }, {239, "239" }, + {240, "240" }, {241, "241" }, {242, "242" }, {243, "243" }, {244, "244" }, + {245, "245" }, {246, "246" }, {247, "247" }, {248, "248" }, {249, "249" }, + {250, "250" }, {251, "251" }, {252, "252" }, {253, "253" }, {254, "254" }, + {255, "255" }, {256, "256" }, {257, "257" }, {258, "258" }, {259, "259" }, + {260, "260" }, {261, "261" }, {262, "262" }, {263, "263" }, {264, "264" }, + {265, "265" }, {266, "266" }, {267, "267" }, {268, "268" }, {269, "269" }, + {270, "270" }, {271, "271" }, {272, "272" }, {273, "273" }, {274, "274" }, + {275, "275" }, {276, "276" }, {277, "277" }, {278, "278" }, {279, "279" }, + {280, "280" }, {281, "281" }, {282, "282" }, {283, "283" }, {284, "284" }, + {285, "285" }, {286, "286" }, {287, "287" }, {288, "288" }, {289, "289" }, + {290, "290" }, {291, "291" }, {292, "292" }, {293, "293" }, {294, "294" }, + {295, "295" }, {296, "296" }, {297, "297" }, {298, "298" }, {299, "299" }, + {300, "300" }, {301, "301" }, {302, "302" }, {303, "303" }, {304, "304" }, + {305, "305" }, {306, "306" }, {307, "307" }, {308, "308" }, {309, "309" }, + {310, "310" }, {311, "311" }, {312, "312" }, {313, "313" }, {314, "314" }, + {315, "315" }, {316, "316" }, {317, "317" }, {318, "318" }, {319, "319" }, + {320, "320" }, {321, "321" }, {322, "322" }, {323, "323" }, {324, "324" }, + {325, "325" }, {326, "326" }, {327, "327" }, {328, "328" }, {329, "329" }, + {330, "330" }, {331, "331" }, {332, "332" }, {333, "333" }, {334, "334" }, + {335, "335" }, {336, "336" }, {337, "337" }, {338, "338" }, {339, "339" }, + {340, "340" }, {341, "341" }, {342, "342" }, {343, "343" }, {344, "344" }, + {345, "345" }, {346, "346" }, {347, "347" }, {348, "348" }, {349, "349" }, + {350, "350" }, {351, "351" }, {352, "352" }, {353, "353" }, {354, "354" }, + {355, "355" }, {356, "356" }, {357, "357" }, {358, "358" }, {359, "359" }, + {360, "360" }, {361, "361" }, {362, "362" }, {363, "363" }, {364, "364" }, + {365, "365" }, {366, "366" }, {367, "367" }, {368, "368" }, {369, "369" }, + {370, "370" }, {371, "371" }, {372, "372" }, {373, "373" }, {374, "374" }, + {375, "375" }, {376, "376" }, {377, "377" }, {378, "378" }, {379, "379" }, + {380, "380" }, {381, "381" }, {382, "382" }, {383, "383" }, {384, "384" }, + {385, "385" }, {386, "386" }, {387, "387" }, {388, "388" }, {389, "389" }, + {390, "390" }, {391, "391" }, {392, "392" }, {393, "393" }, {394, "394" }, + {395, "395" }, {396, "396" }, {397, "397" }, {398, "398" }, {399, "399" }, + {400, "400" }, {401, "401" }, {402, "402" }, {403, "403" }, {404, "404" }, + {405, "405" }, {406, "406" }, {407, "407" }, {408, "408" }, {409, "409" }, + {410, "410" }, {411, "411" }, {412, "412" }, {413, "413" }, {414, "414" }, + {415, "415" }, {416, "416" }, {417, "417" }, {418, "418" }, {419, "419" }, + {420, "420" }, {421, "421" }, {422, "422" }, {423, "423" }, {424, "424" }, + {425, "425" }, {426, "426" }, {427, "427" }, {428, "428" }, {429, "429" }, + {430, "430" }, {431, "431" }, {432, "432" }, {433, "433" }, {434, "434" }, + {435, "435" }, {436, "436" }, {437, "437" }, {438, "438" }, {439, "439" }, + {440, "440" }, {441, "441" }, {442, "442" }, {443, "443" }, {444, "444" }, + {445, "445" }, {446, "446" }, {447, "447" }, {448, "448" }, {449, "449" }, + {450, "450" }, {451, "451" }, {452, "452" }, {453, "453" }, {454, "454" }, + {455, "455" }, {456, "456" }, {457, "457" }, {458, "458" }, {459, "459" }, + {460, "460" }, {461, "461" }, {462, "462" }, {463, "463" }, {464, "464" }, + {465, "465" }, {466, "466" }, {467, "467" }, {468, "468" }, {469, "469" }, + {470, "470" }, {471, "471" }, {472, "472" }, {473, "473" }, {474, "474" }, + {475, "475" }, {476, "476" }, {477, "477" }, {478, "478" }, {479, "479" }, + {480, "480" }, {481, "481" }, {482, "482" }, {483, "483" }, {484, "484" }, + {485, "485" }, {486, "486" }, {487, "487" }, {488, "488" }, {489, "489" }, + {490, "490" }, {491, "491" }, {492, "492" }, {493, "493" }, {494, "494" }, + {495, "495" }, {496, "496" }, {497, "497" }, {498, "498" }, {499, "499" } +}; + +static pmdaInstid _events[] = { + { 0, "fungus" }, { 1, "bogus" } +}; + +/* all domains supported in this PMDA - one entry each */ +static pmdaIndom indomtab[] = { +#define COLOUR_INDOM 0 + { 0, 3, _colour }, +#define BIN_INDOM 1 + { 0, 9, _bin }, +#define MIRAGE_INDOM 2 + { 0, 0, NULL }, +#define FAMILY_INDOM 3 + { 0, 5, _family }, +#define HORDES_INDOM 4 + { 0, 500, _hordes }, +#define DODGEY_INDOM 5 + { 0, 5, _dodgey }, +#define DYNAMIC_INDOM 6 + { 0, 0, NULL }, +#define MANY_INDOM 7 + { 0, 5, NULL }, +#define SCRAMBLE_INDOM 8 + { 0, 9, _scramble }, +#define EVENT_INDOM 9 + { 0, 2, _events }, + + { PM_INDOM_NULL, 0, 0 } +}; + +static struct timeval _then; /* time we started */ +static time_t _start; /* ditto */ +static __pmProfile *_profile; /* last received profile */ +static int _x; +static pmdaIndom *_idp; +static int _singular = -1; /* =0 for singular values */ +static int _ordinal = -1; /* >=0 for non-singular values */ +static int _control; /* the control variable */ +static int _mypid; +static int _drift = 200; /* starting value for drift */ +static int _sign = -1; /* up/down for drift */ +static int _step = 20; /* magnitude of step */ +static int _write_me = 2; /* constant, but modifiable */ +static __int32_t _long = 13; /* long.write_me */ +static __uint32_t _ulong = 13; /* ulong.write_me */ +static __int64_t _longlong = 13; /* longlong.write_me */ +static __uint64_t _ulonglong = 13;/* ulonglong.write_me */ +static float _float = 13; /* float.write_me */ +static double _double = 13; /* double.write_me */ +static char *_string; /* string.write_me */ +static pmValueBlock *_aggr33; /* aggregate.null */ +static pmValueBlock *_aggr34; /* aggregate.hullo */ +static pmValueBlock *_aggr35; /* aggregate.write_me */ +static long _col46; /* lights */ +static int _n46; /* sample count for lights */ +static long _mag47; /* magnitude */ +static int _n47; /* sample count for magnitude */ +static __uint32_t _rapid; /* counts @ 8x10^8 per fetch */ +static int _dyn_max = -1; +static int *_dyn_ctr; +static int many_count = 5; + +static pmValueBlock *sivb=NULL; + +static __int32_t _wrap = 0; /* wrap.long */ +static __uint32_t _u_wrap = 0; /* wrap.ulong */ +static __int64_t _ll_wrap = 0; /* wrap.longlong */ +static __uint64_t _ull_wrap = 0; /* wrap.ulonglong */ + +static int _error_code = 0;/* return this! */ + +static int dodgey = 5; /* dodgey.control */ +static int tmp_dodgey = 5; +static int new_dodgey = 0; + +static double scale_step_bytes_up = 1; +static double scale_step_bytes_down = 1; +static double scale_step_count_up = 1; +static double scale_step_count_down = 1; +static double scale_step_time_up_secs = 1; +static double scale_step_time_up_nanosecs = 1; +static double scale_step_none_up = 1; +static int scale_step_number[7] = {0,0,0,0,0,0,0}; + +static __uint32_t const_rate_gradient = 0; +static __uint32_t const_rate_value = 10485760; +static struct timeval const_rate_timestamp = {0,0}; + +/* this needs to be visible in pmda.c */ +int not_ready = 0; /* sleep interval in seconds */ +int sample_done = 0;/* pending request to terminate, see sample_store() */ + +int _isDSO = 1; /* =0 I am a daemon */ + +/* + * dynamic PMNS metrics ... nothing to do with redo_dynamic() and dynamic + * InDoms + */ +static struct { + char *name; + pmID pmid; + int mark; +} dynamic_ones[] = { + { "secret.foo.bar.max.redirect", PMDA_PMID(0,0) }, + { "secret.bar", PMDA_PMID(0,1000) }, + { "secret.foo.one", PMDA_PMID(0,1001) }, + { "secret.foo.two", PMDA_PMID(0,1002) }, + { "secret.foo.bar.three", PMDA_PMID(0,1003) }, + { "secret.foo.bar.four", PMDA_PMID(0,1004) }, + { "secret.foo.bar.grunt.five", PMDA_PMID(0,1005) }, + { "secret.foo.bar.grunt.snort.six", PMDA_PMID(0,1006) }, + { "secret.foo.bar.grunt.snort.huff.puff.seven", PMDA_PMID(0,1007) } +}; +static int numdyn = sizeof(dynamic_ones)/sizeof(dynamic_ones[0]); + +static int +redo_dynamic(void) +{ + int err; + int i; + int sep = __pmPathSeparator(); + static struct stat lastsbuf; + struct stat statbuf; + pmdaIndom *idp = &indomtab[DYNAMIC_INDOM]; + char mypath[MAXPATHLEN]; + + snprintf(mypath, sizeof(mypath), "%s%c" "sample" "%c" "dynamic.indom", + pmGetConfig("PCP_PMDAS_DIR"), sep, sep); + + if (stat(mypath, &statbuf) == 0) { +#if defined(HAVE_ST_MTIME_WITH_E) && defined(HAVE_STAT_TIME_T) + if (statbuf.st_mtime != lastsbuf.st_mtime) +#elif defined(HAVE_ST_MTIME_WITH_SPEC) + if ((statbuf.st_mtimespec.tv_sec != lastsbuf.st_mtimespec.tv_sec) || + (statbuf.st_mtimespec.tv_nsec != lastsbuf.st_mtimespec.tv_nsec)) +#elif defined(HAVE_STAT_TIMESTRUC) || defined(HAVE_STAT_TIMESPEC) || defined(HAVE_STAT_TIMESPEC_T) + if ((statbuf.st_mtim.tv_sec != lastsbuf.st_mtim.tv_sec) || + (statbuf.st_mtim.tv_nsec != lastsbuf.st_mtim.tv_nsec)) +#else +!bozo! +#endif + { + FILE *fspec; + int newinst; + char newname[100]; /* hack, secret max */ + int numinst; + + lastsbuf = statbuf; + if ((fspec = fopen(mypath, "r")) != NULL) { + for (i = 0; i < idp->it_numinst; i++) { + free(idp->it_set[i].i_name); + } + for (i = 0; i <= _dyn_max; i++) { + _dyn_ctr[i] = -_dyn_ctr[i]; + } + free(idp->it_set); + idp->it_numinst = 0; + idp->it_set = NULL; + numinst = 0; + for ( ; ; ) { + if (fscanf(fspec, "%d %s", &newinst, newname) != 2) + break; + numinst++; + if ((idp->it_set = (pmdaInstid *)realloc(idp->it_set, numinst * sizeof(pmdaInstid))) == NULL) { + err = -oserror(); + fclose(fspec); + return err; + } + idp->it_set[numinst-1].i_inst = newinst; + if ((idp->it_set[numinst-1].i_name = strdup(newname)) == NULL) { + err = -oserror(); + free(idp->it_set); + idp->it_set = NULL; + fclose(fspec); + return err; + } + if (newinst > _dyn_max) { + if ((_dyn_ctr = (int *)realloc(_dyn_ctr, (newinst+1)*sizeof(_dyn_ctr[0]))) == NULL) { + err = -oserror(); + free(idp->it_set); + idp->it_set = NULL; + fclose(fspec); + return err; + } + for (i = _dyn_max+1; i <= newinst; i++) + _dyn_ctr[i] = 0; + _dyn_max = newinst; + } + _dyn_ctr[newinst] = -_dyn_ctr[newinst]; + } + fclose(fspec); + idp->it_numinst = numinst; + + for (i = 0; i <= _dyn_max; i++) { + if (_dyn_ctr[i] < 0) + _dyn_ctr[i] = 0; + } + +#ifdef PCP_DEBUG + if (pmDebug & DBG_TRACE_APPL0) { + fprintf(stderr, "redo instance domain for dynamic: numinst: %d\n", idp->it_numinst); + for (i = 0; i < idp->it_numinst; i++) { + fprintf(stderr, " %d \"%s\"", idp->it_set[i].i_inst, idp->it_set[i].i_name); + } + fputc('\n', stderr); + } +#endif + } + } + } + else { + /* control file is not present, empty indom if not already so */ + if (idp->it_set != NULL) { + for (i = 0; i < idp->it_numinst; i++) { + free(idp->it_set[i].i_name); + } + free(idp->it_set); + idp->it_set = NULL; + idp->it_numinst = 0; + for (i = 0; i <= _dyn_max; i++) { + _dyn_ctr[i] = 0; + } +#ifdef PCP_DEBUG + if (pmDebug & DBG_TRACE_APPL0) + fprintf(stderr, "redo instance domain for dynamic: numinst: 0 (no control file)\n"); +#endif + } + } + + for (i = 0; i < idp->it_numinst; i++) { + _dyn_ctr[idp->it_set[i].i_inst]++; + } + + return 0; +} + +#define MANY_MAX_LEN 10 + +static int +redo_many(void) +{ + pmdaIndom *idp; + int a; + static char *tags=NULL; + char *tag; + + /* sanity check, range clip */ + + if (many_count<0) many_count=0; + if (many_count>999999) many_count=999999; + + idp = &indomtab[MANY_INDOM]; + + /* realloc instances buffer */ + + idp->it_set = realloc(idp->it_set, many_count*sizeof(pmdaInstid)); + if (!idp->it_set) { + idp->it_numinst=0; + many_count=0; + return -oserror(); + } + + /* realloc string buffer */ + + tags = realloc(tags, many_count*MANY_MAX_LEN); + if (!idp->it_set) { + idp->it_numinst=0; + many_count=0; + return -oserror(); + } + + /* set number of instances */ + + idp->it_numinst=many_count; + + /* generate instances */ + + tag=tags; + for (a=0;a<many_count;a++) { + idp->it_set[a].i_inst=a; + idp->it_set[a].i_name=tag; + tag+=sprintf(tag,"i-%d",a)+1; + } + + return 0; +} + +static int +redo_mirage(void) +{ + static time_t doit = 0; + time_t now; + int i; + int j; + static int newinst = 0; + pmdaIndom *idp; + + now = time(NULL); + if (now < doit) + return 0; + + idp = &indomtab[MIRAGE_INDOM]; + if (idp->it_set == NULL) { + /* first time */ + if ((idp->it_set = (pmdaInstid *)malloc(sizeof(pmdaInstid))) == NULL) + return -oserror(); + if ((idp->it_set[0].i_name = (char *)malloc(5)) == NULL) { + idp->it_set = NULL; + return -oserror(); + } + idp->it_numinst = 1; + idp->it_set[0].i_inst = 0; + sprintf(idp->it_set[0].i_name, "m-%02d", 0); + } + else { + int numinst; + int cull; + + numinst = 1; + cull = idp->it_numinst > 12 ? idp->it_numinst/2 : idp->it_numinst; + for (i = 1; i < idp->it_numinst; i++) { + if (lrand48() % 1000 < 1000 / cull) { + /* delete this one */ + free(idp->it_set[i].i_name); + continue; + } + idp->it_set[numinst++] = idp->it_set[i]; + } + if (numinst != idp->it_numinst) { + if ((idp->it_set = (pmdaInstid *)realloc(idp->it_set, numinst * sizeof(pmdaInstid))) == NULL) { + idp->it_set = NULL; + idp->it_numinst = 0; + return -oserror(); + } + idp->it_numinst = numinst; + } + for (i = 0; i < 2; i++) { + if (lrand48() % 1000 < 500) { + /* add a new one */ + numinst++; + if ((idp->it_set = (pmdaInstid *)realloc(idp->it_set, numinst * sizeof(pmdaInstid))) == NULL) { + idp->it_set = NULL; + idp->it_numinst = 0; + return -oserror(); + } + if ((idp->it_set[numinst-1].i_name = (char *)malloc(5)) == NULL) { + idp->it_set = NULL; + return -oserror(); + } + for ( ; ; ) { + newinst = (newinst + 1) % 50; + for (j = 0; j < idp->it_numinst; j++) { + if (idp->it_set[j].i_inst == newinst) + break; + } + if (j == idp->it_numinst) + break; + } + idp->it_numinst = numinst; + idp->it_set[numinst-1].i_inst = newinst; + sprintf(idp->it_set[numinst-1].i_name, "m-%02d", newinst); + } + } + } +#ifdef PCP_DEBUG + if (pmDebug & DBG_TRACE_APPL0) { + fprintf(stderr, "redo instance domain for mirage: numinst: %d\n", idp->it_numinst); + for (i = 0; i < idp->it_numinst; i++) { + fprintf(stderr, " %d \"%s\"", idp->it_set[i].i_inst, idp->it_set[i].i_name); + } + fputc('\n', stderr); + } +#endif + + doit = now + 10; /* no more than once every 10 seconds */ + return 0; +} + +static void +redo_dodgey(void) +{ + int j; + int k; + + if (dodgey <= 5) { + tmp_dodgey = dodgey; + new_dodgey = 0; + /* re-build full instance table */ + for (j = 0; j < 5; j++) { + _dodgey[j].i_inst = j+1; + _dodgey[j].i_name[1] = '0' + j+1; + } + indomtab[DODGEY_INDOM].it_numinst = 5; + } + else { + j = (int)(lrand48() % 1000); + if (j < 33) + tmp_dodgey = PM_ERR_NOAGENT; + else if (j < 66) + tmp_dodgey = PM_ERR_AGAIN; + else if (j < 99) + tmp_dodgey = PM_ERR_APPVERSION; + else { + /* + * create partial instance table, instances appear + * at random with prob = 0.5 + */ + k = 0; + for (j = 0; j < 5; j++) { + if (lrand48() % 100 < 49) { + _dodgey[k].i_inst = j+1; + _dodgey[k].i_name[1] = '0' + j+1; + k++; + } + } + tmp_dodgey = indomtab[DODGEY_INDOM].it_numinst = k; + } + /* fetches before re-setting */ + new_dodgey = (int)(lrand48() % dodgey); + } +} + +/* + * count the number of instances in an instance domain + */ +static int +cntinst(pmInDom indom) +{ + pmdaIndom *idp; + + if (indom == PM_INDOM_NULL) + return 1; + for (idp = indomtab; idp->it_indom != PM_INDOM_NULL; idp++) { + if (idp->it_indom == indom) + return idp->it_numinst; + } + __pmNotifyErr(LOG_WARNING, "cntinst: unknown pmInDom 0x%x", indom); + return 0; +} + +/* + * commence a new round of instance selection + * flag == 1 for prefetch instance counting + * flag == 0 for iteration over instances to retrieve values + */ +static void +startinst(pmInDom indom, int flag) +{ + _ordinal = _singular = -1; + if (indom == PM_INDOM_NULL) { + /* singular value */ + _singular = 0; + return; + } + for (_idp = indomtab; _idp->it_indom != PM_INDOM_NULL; _idp++) { + if (_idp->it_indom == indom) { + /* multiple values are possible */ + _ordinal = 0; + if (flag == 1 && _idp == &indomtab[SCRAMBLE_INDOM]) { + /* + * indomtab[BIN_INDOM].it_set[] is the same size as + * indomtab[SCRAMBLE_INDOM].it_set[] (maxnuminst + * entries) + */ + int i; + int k = 0; + int maxnuminst = indomtab[BIN_INDOM].it_numinst; + srand48((scramble_ver << 10) + 13); + scramble_ver++; + for (i = 0; i < maxnuminst; i++) + indomtab[SCRAMBLE_INDOM].it_set[i].i_inst = PM_IN_NULL; + for (i = 0; i < maxnuminst; i++) { + /* skip 1/3 of instances */ + if ((lrand48() % 100) < 33) continue; + /* order of instances is random */ + for ( ; ; ) { + k = lrand48() % maxnuminst; + if (indomtab[SCRAMBLE_INDOM].it_set[k].i_inst != PM_IN_NULL) + continue; + indomtab[SCRAMBLE_INDOM].it_set[k].i_inst = indomtab[BIN_INDOM].it_set[i].i_inst; + indomtab[SCRAMBLE_INDOM].it_set[k].i_name = indomtab[BIN_INDOM].it_set[i].i_name; + break; + } + } + /* pack to remove skipped instances */ + k = 0; + for (i = 0; i < maxnuminst; i++) { + if (indomtab[SCRAMBLE_INDOM].it_set[i].i_inst == PM_IN_NULL) + continue; + if (k < i) { + indomtab[SCRAMBLE_INDOM].it_set[k].i_inst = indomtab[SCRAMBLE_INDOM].it_set[i].i_inst; + indomtab[SCRAMBLE_INDOM].it_set[k].i_name = indomtab[SCRAMBLE_INDOM].it_set[i].i_name; + } + k++; + } + indomtab[SCRAMBLE_INDOM].it_numinst = k; + } + break; + } + } +} + +/* + * find next selected instance, if any + * + * EXCEPTION PCP 2.1.1: make use of __pmProfile much smarter, particularly when state for + * this indom is PM_PROFILE_EXCLUDE, then only need to consider inst + * values in the profile - this is a performance enhancement, and + * the simple method is functionally complete, particularly for + * stable (non-varying) instance domains + */ +static int +nextinst(int *inst) +{ + int j; + + if (_singular == 0) { + /* PM_INDOM_NULL ... just the one value */ + *inst = 0; + _singular = -1; + return 1; + } + if (_ordinal >= 0) { + /* scan for next value in the profile */ + for (j = _ordinal; j < _idp->it_numinst; j++) { + if (__pmInProfile(_idp->it_indom, _profile, _idp->it_set[j].i_inst)) { + *inst = _idp->it_set[j].i_inst; + _ordinal = j+1; + return 1; + } + } + _ordinal = -1; + } + return 0; +} + +/* + * this routine is called at initialization to patch up any parts of the + * desctab that cannot be statically initialized, and to optionally + * modify our Performance Metrics Domain Id (dom) + */ +static void +init_tables(int dom) +{ + int i; + __pmInDom_int b_indom; + __pmInDom_int *indomp; + __pmID_int *pmidp; + pmDesc *dp; + + /* serial numbering is arbitrary, but must be unique in this PMD */ + b_indom.flag = 0; + b_indom.domain = dom; + b_indom.serial = 1; + indomp = (__pmInDom_int *)&indomtab[COLOUR_INDOM].it_indom; + *indomp = b_indom; + b_indom.serial++; + indomp = (__pmInDom_int *)&indomtab[BIN_INDOM].it_indom; + *indomp = b_indom; + b_indom.serial++; + indomp = (__pmInDom_int *)&indomtab[MIRAGE_INDOM].it_indom; + *indomp = b_indom; + b_indom.serial++; + indomp = (__pmInDom_int *)&indomtab[FAMILY_INDOM].it_indom; + *indomp = b_indom; + b_indom.serial++; + indomp = (__pmInDom_int *)&indomtab[HORDES_INDOM].it_indom; + *indomp = b_indom; + b_indom.serial++; + indomp = (__pmInDom_int *)&indomtab[DODGEY_INDOM].it_indom; + *indomp = b_indom; + b_indom.serial++; + indomp = (__pmInDom_int *)&indomtab[DYNAMIC_INDOM].it_indom; + *indomp = b_indom; + b_indom.serial++; + indomp = (__pmInDom_int *)&indomtab[MANY_INDOM].it_indom; + *indomp = b_indom; + b_indom.serial++; + indomp = (__pmInDom_int *)&indomtab[SCRAMBLE_INDOM].it_indom; + *indomp = b_indom; + b_indom.serial++; + indomp = (__pmInDom_int *)&indomtab[EVENT_INDOM].it_indom; + *indomp = b_indom; + + /* rewrite indom in desctab[] */ + for (dp = desctab; dp->pmid != PM_ID_NULL; dp++) { + switch (dp->pmid) { + case PMDA_PMID(0,5): /* colour */ + case PMDA_PMID(0,92): /* darkness */ + dp->indom = indomtab[COLOUR_INDOM].it_indom; + break; + case PMDA_PMID(0,6): /* bin */ + case PMDA_PMID(0,48): /* bucket */ + case PMDA_PMID(0,50): /* part_bin */ + case PMDA_PMID(0,51): /* bogus_bin */ + case PMDA_PMID(0,103): /* long.bin */ + case PMDA_PMID(0,104): /* long.bin_ctr */ + case PMDA_PMID(0,105): /* ulong.bin */ + case PMDA_PMID(0,106): /* ulong.bin_ctr */ + case PMDA_PMID(0,107): /* float.bin */ + case PMDA_PMID(0,108): /* float.bin_ctr */ + case PMDA_PMID(0,109): /* longlong.bin */ + case PMDA_PMID(0,110): /* longlong.bin_ctr */ + case PMDA_PMID(0,111): /* ulonglong.bin */ + case PMDA_PMID(0,112): /* ulonglong.bin_ctr */ + case PMDA_PMID(0,113): /* double.bin */ + case PMDA_PMID(0,114): /* double.bin_ctr */ + dp->indom = indomtab[BIN_INDOM].it_indom; + break; + case PMDA_PMID(0,37): /* mirage */ + dp->indom = indomtab[MIRAGE_INDOM].it_indom; + break; + case PMDA_PMID(0,38): /* mirage-longlong */ + dp->indom = indomtab[MIRAGE_INDOM].it_indom; + break; + case PMDA_PMID(0,49): /* needprofile */ + dp->indom = indomtab[FAMILY_INDOM].it_indom; + break; + case PMDA_PMID(0,52): /* hordes.one */ + case PMDA_PMID(0,53): /* hordes.two */ + dp->indom = indomtab[HORDES_INDOM].it_indom; + break; + case PMDA_PMID(0,62): /* dodgey.value */ + dp->indom = indomtab[DODGEY_INDOM].it_indom; + break; + case PMDA_PMID(0,76): /* dynamic.counter */ + case PMDA_PMID(0,77): /* dynamic.discrete */ + case PMDA_PMID(0,78): /* dynamic.instant */ + dp->indom = indomtab[DYNAMIC_INDOM].it_indom; + break; + case PMDA_PMID(0,80): /* many.int */ + dp->indom = indomtab[MANY_INDOM].it_indom; + break; + case PMDA_PMID(0,121): /* scramble.bin */ + dp->indom = indomtab[SCRAMBLE_INDOM].it_indom; + break; + case PMDA_PMID(0,136): /* event.records */ + case PMDA_PMID(0,139): /* event.highres_records */ + dp->indom = indomtab[EVENT_INDOM].it_indom; + break; + } + } + + /* merge performance domain id part into PMIDs in pmDesc table */ + for (i = 0; desctab[i].pmid != PM_ID_NULL; i++) { + pmidp = (__pmID_int *)&desctab[i].pmid; + pmidp->domain = dom; + if (direct_map && pmidp->item != i) { + direct_map = 0; +#ifdef PCP_DEBUG + if (pmDebug & DBG_TRACE_APPL0) { + __pmNotifyErr(LOG_WARNING, "sample_init: direct map disabled @ desctab[%d]", i); + } +#endif + } + } + ndesc--; + pmidp = (__pmID_int *)&magic.pmid; + pmidp->domain = dom; + + /* local hacks */ + _string = (char *)calloc(1, 8); + strncpy(_string, "13", sizeof("13")); + _aggr33 = (pmValueBlock *)malloc(PM_VAL_HDR_SIZE); + _aggr33->vlen = PM_VAL_HDR_SIZE + 0; + _aggr33->vtype = PM_TYPE_AGGREGATE; + _aggr34 = (pmValueBlock *)malloc(PM_VAL_HDR_SIZE+strlen("hullo world!")); + _aggr34->vlen = PM_VAL_HDR_SIZE + strlen("hullo world!"); + _aggr34->vtype = PM_TYPE_AGGREGATE; + memcpy(_aggr34->vbuf, "hullo world!", strlen("hullo world!")); + _aggr35 = (pmValueBlock *)malloc(PM_VAL_HDR_SIZE+strlen("13")); + _aggr35->vlen = PM_VAL_HDR_SIZE + strlen("13"); + _aggr35->vtype = PM_TYPE_AGGREGATE; + memcpy(_aggr35->vbuf, "13", strlen("13")); + + (void)redo_many(); +} + +static int +sample_profile(__pmProfile *prof, pmdaExt *ep) +{ + sample_inc_recv(ep->e_context); + _profile = prof; + return 0; +} + +static int +sample_instance(pmInDom indom, int inst, char *name, __pmInResult **result, pmdaExt *ep) +{ + int i; + __pmInResult *res; + pmdaIndom *idp; + int err = 0; + + sample_inc_recv(ep->e_context); + sample_inc_xmit(ep->e_context); + + if (not_ready > 0) { + return limbo(); + } + + if (need_mirage && (i = redo_mirage()) < 0) + return i; + if (need_dynamic && (i = redo_dynamic()) < 0) + return i; + + /* + * check this is an instance domain we know about -- code below + * assumes this test is complete + */ + for (idp = indomtab; idp->it_indom != PM_INDOM_NULL; idp++) { + if (idp->it_indom == indom) + break; + } + if (idp->it_indom == PM_INDOM_NULL) + return PM_ERR_INDOM; + + if ((res = (__pmInResult *)malloc(sizeof(*res))) == NULL) + return -oserror(); + res->indom = indom; + + if (name == NULL && inst == PM_IN_NULL) + res->numinst = cntinst(indom); + else + res->numinst = 1; + + if (inst == PM_IN_NULL) { + if ((res->instlist = (int *)malloc(res->numinst * sizeof(res->instlist[0]))) == NULL) { + free(res); + return -oserror(); + } + } + else + res->instlist = NULL; + + if (name == NULL) { + if ((res->namelist = (char **)malloc(res->numinst * sizeof(res->namelist[0]))) == NULL) { + __pmFreeInResult(res); + return -oserror(); + } + for (i = 0; i < res->numinst; i++) + res->namelist[0] = NULL; + } + else + res->namelist = NULL; + + if (name == NULL && inst == PM_IN_NULL) { + /* return inst and name for everything */ + for (i = 0; i < res->numinst; i++) { + res->instlist[i] = idp->it_set[i].i_inst; + if ((res->namelist[i] = strdup(idp->it_set[i].i_name)) == NULL) { + __pmFreeInResult(res); + return -oserror(); + } + } + } + else if (name == NULL) { + /* given an inst, return the name */ + for (i = 0; i < idp->it_numinst; i++) { + char *p; + if (inst == idp->it_set[i].i_inst) { + if ((res->namelist[0] = strdup(idp->it_set[i].i_name)) == NULL) { + __pmFreeInResult(res); + return -oserror(); + } + for (p = res->namelist[0]; *p; p++) { + if (*p == ' ') { + *p = '\0'; + break; + } + } + break; + } + } + if (i == idp->it_numinst) + err = 1; + } + else if (inst == PM_IN_NULL) { + /* given a name, return an inst */ + char *p; + long len; + for (p = name; *p; p++) { + if (*p == ' ') + break; + } + len = p - name; + for (i = 0; i < idp->it_numinst; i++) { + if (strncmp(name, idp->it_set[i].i_name, len) == 0 && + strlen(idp->it_set[i].i_name) >= len && + (idp->it_set[i].i_name[len] == '\0' || idp->it_set[i].i_name[len] == ' ')) { + res->instlist[0] = idp->it_set[i].i_inst; + break; + } + } + if (i == idp->it_numinst) + err = 1; + } + else + err = 1; + if (err == 1) { + /* bogus arguments or instance id/name */ + __pmFreeInResult(res); + return PM_ERR_INST; + } + + *result = res; + return 0; +} + +static int +sample_pmid(const char *name, pmID *pmid, pmdaExt *pmda) +{ + int i; + const char *p; + + /* skip the sample. or sampledso. part */ + for (p = name; *p != '.' && *p; p++) + ; + if (*p == '.') p++; + + for (i = 0; i < numdyn; i++) { + if (strcmp(p, dynamic_ones[i].name) == 0) { + *pmid = dynamic_ones[i].pmid; + return 0; + } + } + + return PM_ERR_NAME; +} + +static int +sample_name(pmID pmid, char ***nameset, pmdaExt *pmda) +{ + size_t len = 0; + int nmatch = 0; + int i; + char *pfx; + char *p; + char **list; + + if (_isDSO) + pfx = "sampledso."; + else + pfx = "sample."; + + for (i = 0; i < numdyn; i++) { + if (dynamic_ones[i].pmid == pmid) { + nmatch++; + len += strlen(pfx)+strlen(dynamic_ones[i].name)+1; + } + } + + if (nmatch == 0) + return PM_ERR_PMID; + + len += nmatch*sizeof(char *); /* pointers to names */ + + if ((list = (char **)malloc(len)) == NULL) + return -oserror(); + + p = (char *)&list[nmatch]; + nmatch = 0; + for (i = 0; i < numdyn; i++) { + if (dynamic_ones[i].pmid == pmid) { + list[nmatch++] = p; + strcpy(p, pfx); + p += strlen(pfx); + strcpy(p, dynamic_ones[i].name); + p += strlen(dynamic_ones[i].name); + *p++ = '\0'; + } + } + *nameset = list; + + return nmatch; +} + +static int +sample_children(const char *name, int traverse, char ***offspring, int **status, pmdaExt *pmda) +{ + int i; + int j; + int nmatch; + int pfxlen; + int namelen; + const char *p; + char *q; + char *qend = NULL; + char **chn = NULL; + int *sts = NULL; + size_t len = 0; + size_t tlen = 0; + + /* skip the sample. or sampledso. part */ + for (p = name; *p != '.' && *p; p++) + ; + pfxlen = p - name; + if (*p == '.') p++; + namelen = strlen(p); + + nmatch = 0; + for (i = 0; i < numdyn; i++) { + q = dynamic_ones[i].name; + if (strncmp(p, q, namelen) != 0) { + /* no prefix match */ + dynamic_ones[i].mark = 0; + continue; + } + if (traverse == 0 && q[namelen] != '.') { + /* cannot be a child of name */ + dynamic_ones[i].mark = 0; + continue; + } + if (traverse == 1 && q[namelen] != '.' && q[namelen] != '\0') { + /* cannot be name itself, not a child of name */ + dynamic_ones[i].mark = 0; + continue; + } + if (traverse == 0) { + qend = &q[namelen+1]; + while (*qend && *qend != '.') + qend++; + tlen = qend - &q[namelen+1]; + for (j = 0; j < nmatch; j++) { + if (strncmp(&q[namelen+1], chn[j], tlen) == 0) { + /* already seen this child ... skip it */ + break; + } + } + } + else { + /* traversal ... need this one */ + j = nmatch; + } + if (j == nmatch) { + nmatch++; + if ((chn = (char **)realloc(chn, nmatch*sizeof(chn[0]))) == NULL) { + j = -oserror(); + goto fail; + } + if ((sts = (int *)realloc(sts, nmatch*sizeof(sts[0]))) == NULL) { + j = -oserror(); + goto fail; + } + if (traverse == 0) { + /* + * descendents only ... just want the next component of + * PMNS name + */ + if ((chn[nmatch-1] = (char *)malloc(tlen+1)) == NULL) { + j = -oserror(); + goto fail; + } + strncpy(chn[nmatch-1], &q[namelen+1], tlen); + chn[nmatch-1][tlen] = '\0'; + if (*qend == '.') + sts[nmatch-1] = PMNS_NONLEAF_STATUS; + else + sts[nmatch-1] = PMNS_LEAF_STATUS; + } + else { + /* + * traversal ... want the whole name including the prefix + * part + */ + tlen = pfxlen + strlen(dynamic_ones[i].name) + 2; + if ((chn[nmatch-1] = malloc(tlen)) == NULL) { + j = -oserror(); + goto fail; + } + strncpy(chn[nmatch-1], name, pfxlen); + chn[nmatch-1][pfxlen] = '.'; + chn[nmatch-1][pfxlen+1] = '\0'; + strcat(chn[nmatch-1], dynamic_ones[i].name); + sts[nmatch-1] = PMNS_LEAF_STATUS; + } + len += tlen + 1; + } + } + if (nmatch == 0) { + *offspring = NULL; + *status = NULL; + } + else { + if ((chn = (char **)realloc(chn, nmatch*sizeof(chn[0])+len)) == NULL) { + j = -oserror(); + goto fail; + } + q = (char *)&chn[nmatch]; + for (j = 0; j < nmatch; j++) { + strcpy(q, chn[j]); + free(chn[j]); + chn[j] = q; + q += strlen(chn[j])+1; + } + *offspring = chn; + *status = sts; + } + return nmatch; + +fail: + /* + * come here with j as negative error code, and some allocation failure for + * sts[] or chn[] or chn[nmatch-1][] + */ + if (sts != NULL) free(sts); + if (chn != NULL) { + for (i = 0; i < nmatch-1; i++) { + if (chn[i] != NULL) free(chn[i]); + } + free(chn); + } + return j; +} + +static int +sample_attribute(int ctx, int attr, const char *value, int length, pmdaExt *pmda) +{ + /* + * We have no special security or other requirements, so we're just + * going to log any connection attribute messages we happen to get + * from pmcd (handy for demo and testing purposes). + */ + if (pmDebug & DBG_TRACE_AUTH) { + char buffer[256]; + + if (!__pmAttrStr_r(attr, value, buffer, sizeof(buffer))) { + __pmNotifyErr(LOG_ERR, "Bad Attribute: ctx=%d, attr=%d\n", ctx, attr); + } else { + buffer[sizeof(buffer)-1] = '\0'; + __pmNotifyErr(LOG_INFO, "Attribute: ctx=%d %s", ctx, buffer); + } + } + return 0; +} + +/* + * high precision counter + */ +typedef union { + __uint32_t half[2]; + __uint64_t full; +} pmHPC_t; + +#ifdef HAVE_NETWORK_BYTEORDER +#define PM_HPC_TOP 0 +#define PM_HPC_BOTTOM 1 +#else +#define PM_HPC_TOP 1 +#define PM_HPC_BOTTOM 0 +#endif + +void +_pmHPCincr(pmHPC_t *ctr, __uint32_t val) +{ + if (val < ctr->half[PM_HPC_BOTTOM]) + /* assume single overflow */ + ctr->half[PM_HPC_TOP]++; + ctr->half[PM_HPC_BOTTOM] = val; +} + +static pmHPC_t rapid_ctr; + +static int +sample_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *ep) +{ + int i; /* over pmidlist[] */ + int j; /* over vset->vlist[] */ + int sts; + int need; + int inst; + int numval; + static pmResult *res; + static int maxnpmids; + static int nbyte; + __uint32_t *ulp; + unsigned long ul; + struct timeval now; + pmValueSet *vset; + pmDesc *dp; + __pmID_int *pmidp; + pmAtomValue atom; + int type; + + sample_inc_recv(ep->e_context); + sample_inc_xmit(ep->e_context); + + if (not_ready > 0) { + return limbo(); + } + + if (numpmid > maxnpmids) { + if (res != NULL) + free(res); + /* (numpmid - 1) because there's room for one valueSet in a pmResult */ + need = (int)sizeof(pmResult) + (numpmid - 1) * (int)sizeof(pmValueSet *); + if ((res = (pmResult *)malloc(need)) == NULL) + return -oserror(); + maxnpmids = numpmid; + } + res->timestamp.tv_sec = 0; + res->timestamp.tv_usec = 0; + res->numpmid = numpmid; + + if (need_mirage && (j = redo_mirage()) < 0) + return j; + if (need_dynamic && (j = redo_dynamic()) < 0) + return j; + + if (new_dodgey < 0) + redo_dodgey(); + + for (i = 0; i < numpmid; i++) { + pmidp = (__pmID_int *)&pmidlist[i]; + + if (direct_map) { + j = pmidp->item; + if (j < ndesc && desctab[j].pmid == pmidlist[i]) { + dp = &desctab[j]; + goto doit; + } + } + for (dp = desctab; dp->pmid != PM_ID_NULL; dp++) { + if (dp->pmid == pmidlist[i]) + break; + } +doit: + + if (dp->pmid != PM_ID_NULL) { + /* the special cases */ + if (pmidp->cluster == 0 && pmidp->item == 86) { + dp = &magic; + numval = 1; + } + else if (pmidp->cluster == 0 && pmidp->item == 54) + numval = PM_ERR_PMID; + else if (pmidp->cluster == 0 && pmidp->item == 92) /* darkness */ + numval = 0; + else if (pmidp->cluster == 0 && pmidp->item == 138) /* bad.novalues */ + numval = 0; + else if (pmidp->cluster == 0 && + (pmidp->item == 127 || /* event.type */ + pmidp->item == 128 || /* event.param_32 */ + pmidp->item == 129 || /* event.param_u32 */ + pmidp->item == 130 || /* event.param_64 */ + pmidp->item == 131 || /* event.param_u64 */ + pmidp->item == 132 || /* event.param_float */ + pmidp->item == 133 || /* event.param_double */ + pmidp->item == 134 || /* event.param_string */ + pmidp->item == 135)) /* event.param_aggregate */ + numval = 0; + else if (dp->type == PM_TYPE_NOSUPPORT) + numval = PM_ERR_APPVERSION; + else if (dp->indom != PM_INDOM_NULL) { + /* count instances in the profile */ + numval = 0; + /* special case(s) */ + if (pmidp->cluster == 0 && pmidp->item == 49) { + int kp; + /* needprofile - explict instances required */ + + numval = PM_ERR_PROFILE; + for (kp = 0; kp < _profile->profile_len; kp++) { + if (_profile->profile[kp].indom != dp->indom) + continue; + if (_profile->profile[kp].state == PM_PROFILE_EXCLUDE && + _profile->profile[kp].instances_len != 0) + numval = 0; + break; + } + } + else if (pmidp->cluster == 0 && (pmidp->item == 76 || pmidp->item == 77 || pmidp->item == 78)) { + /* + * if $(PCP_VAR_DIR)/pmdas/sample/dynamic.indom is not present, + * then numinst will be zero after the redo_dynamic() call + * in sample_init(), which makes zero loops through the + * fetch loop, so cannot set need_dynamic there ... + * do it here if not already turned on + */ + if (need_dynamic == 0) { + need_dynamic = 1; + if ((j = redo_dynamic()) < 0) + return j; + } + } + if (numval == 0) { + /* count instances in indom */ + startinst(dp->indom, 1); + while (nextinst(&inst)) { + /* special case ... not all here for part_bin */ + if (pmidp->cluster == 0 && pmidp->item == 50 && (inst % 200) == 0) + continue; + numval++; + } + } + } + else { + /* special case(s) for singular instance domains */ + if (pmidp->cluster == 0 && pmidp->item == 9) { + /* surprise! no value available */ + numval = 0; + } + else + numval = 1; + } + } + else + numval = 0; + + /* Must use individual malloc()s because of pmFreeResult() */ + if (numval >= 1) + res->vset[i] = vset = (pmValueSet *)malloc(sizeof(pmValueSet) + + (numval - 1)*sizeof(pmValue)); + else + res->vset[i] = vset = (pmValueSet *)malloc(sizeof(pmValueSet) - + sizeof(pmValue)); + if (vset == NULL) { + if (i) { + res->numpmid = i; + __pmFreeResultValues(res); + } + return -oserror(); + } + vset->pmid = pmidlist[i]; + vset->numval = numval; + vset->valfmt = PM_VAL_INSITU; + if (vset->numval <= 0) + continue; + + if (dp->indom == PM_INDOM_NULL) + inst = PM_IN_NULL; + else { + startinst(dp->indom, 0); + nextinst(&inst); + } + type = dp->type; + j = 0; + do { + if (pmidp->cluster == 0 && pmidp->item == 50 && inst % 200 == 0) + goto skip; + if (pmidp->cluster == 0 && pmidp->item == 51 && inst % 200 == 0) + inst += 50; + if (j == numval) { + /* more instances than expected! */ + numval++; + res->vset[i] = vset = (pmValueSet *)realloc(vset, + sizeof(pmValueSet) + (numval - 1)*sizeof(pmValue)); + if (vset == NULL) { + if (i) { + res->numpmid = i; + __pmFreeResultValues(res); + } + return -oserror(); + } + } + vset->vlist[j].inst = inst; + /* + * we mostly have cluster 0, metric already found in desctab[] + * so no checking needed + */ + if (pmidp->cluster == 0) { + switch (pmidp->item) { + case 0: + atom.l = _control; + break; + case 1: + if (_mypid == 0) _mypid = (int)getpid(); + atom.ul = _mypid; + break; + case 2: + atom.ul = time(NULL) - _start; + break; + case 3: + __pmtimevalNow(&now); + atom.d = 1000 * __pmtimevalSub(&now, &_then); + break; + case 4: + atom.l = 42; + break; + case 5: + switch (inst) { + case 0: /* "red" */ + _x = (_x + 1) % 100; + atom.l = _x + 100; + break; + case 1: /* "green" */ + _x = (_x + 1) % 100; + atom.l = _x + 200; + break; + case 2: /* "blue" */ + _x = (_x + 1) % 100; + atom.l = _x + 300; + break; + } + break; + case 6: + case 48: + case 50: + case 51: + case 103: /* long.bin & long.bin_ctr */ + case 104: + case 121: /* scramble.bin */ + /* the value is the instance identifier (sic) */ + atom.l = inst; + break; + /* and ditto for all the other type variants of "bin" */ + case 105: /* ulong.bin & ulong.bin_ctr */ + case 106: + atom.ul = inst; + break; + case 107: /* float.bin & float.bin_ctr */ + case 108: + atom.f = inst; + break; + case 109: /* longlong.bin & longlong.bin_ctr */ + case 110: + atom.ll = inst; + break; + case 111: /* ulonglong.bin & ulonglong.bin_ctr */ + case 112: + atom.ull = inst; + break; + case 113: /* double.bin & double.bin_ctr */ + case 114: + atom.d = inst; + break; + case 7: + /* drift */ + _drift = _drift + _sign * (int)(lrand48() % 50); + if (_drift < 0) _drift = 0; + atom.l = _drift; + if ((lrand48() % 100) < 20) { + if (_sign == 1) + _sign = -1; + else + _sign = 1; + } + break; + case 63: /* step_counter */ + case 8: /* step every 30 seconds */ + atom.l = (1 + (time(NULL) - _start) / 30) * _step; + break; + case 40: + /* total pdu count for all contexts */ + atom.ll = (__int64_t)sample_get_recv(CTX_ALL) + (__int64_t)sample_get_xmit(CTX_ALL); + break; + case 41: + /* recv pdu count for all contexts */ + atom.l = sample_get_recv(CTX_ALL); + break; + case 42: + /* xmit pdu count for all contexts */ + atom.l = sample_get_xmit(CTX_ALL); + break; + case 43: + case 44: + case 45: + case 122: + case 123: + case 124: + case 125: + /* percontext.pdu */ + /* percontext.recv-pdu */ + /* percontext.xmit-pdu */ + /* percontext.control.ctx */ + /* percontext.control.active */ + /* percontext.control.start */ + /* percontext.control.end */ + atom.l = sample_ctx_fetch(ep->e_context, pmidp->item); + break; + case 37: + /* mirage */ + _x = (_x + 1) % 100; + atom.l = (inst + 1) * 100 - _x; + need_mirage = 1; + break; + case 36: + /* write_me */ + atom.l = _write_me; + break; + case 39: + /* sysinfo */ + if (!sivb) { + /* malloc and init the pmValueBlock for + * sysinfo first type around */ + + int size = sizeof(pmValueBlock) - sizeof(int); + +#ifdef IS_SOLARIS + size += MAX_SYSNAME; +#else + size += sizeof (struct sysinfo); +#endif + + if ((sivb = calloc(1, size)) == NULL ) + return PM_ERR_GENERIC; + + sivb->vlen = size; + sivb->vtype = PM_TYPE_AGGREGATE; + } + +#ifdef HAVE_SYSINFO +#ifdef IS_SOLARIS + sysinfo(SI_SYSNAME, sivb->vbuf, MAX_SYSNAME); +#else + sysinfo((struct sysinfo *)sivb->vbuf); +#endif +#else + strncpy((char *)sivb->vbuf, si.dummy, sizeof(struct sysinfo)); +#endif + atom.vbp = sivb; + + /* + * pv:782029 The actual type must be PM_TYPE_AGGREGATE, + * but we have to tell pmStuffValue it's a + * PM_TYPE_AGGREGATE_STATIC + */ + type = PM_TYPE_AGGREGATE_STATIC; + break; + case 46: + if (_n46 == 0) { + _col46 = lrand48() % 3; + _n46 = 1 + (int)(lrand48() % 10); + } + _n46--; + switch (_col46) { + case 0: + atom.cp = "red"; + break; + case 1: + atom.cp = "yellow"; + break; + case 2: + atom.cp = "green"; + break; + } + break; + case 47: + if (_n47 == 0) { + _mag47 = 1 << (1 + (int)(lrand48() % 6)); + _n47 = 1 + (int)(lrand48() % 5); + } + _n47--; + atom.l = (__int32_t)_mag47; + break; + case 38: + /* mirage-longlong */ + _x = (_x + 1) % 100; + atom.ll = (inst + 1) * 100 - _x; + atom.ll *= 1000000; + need_mirage = 1; + break; + case 49: + /* need profile */ + switch (inst) { + case 0: /* "colleen" */ + atom.f = 3.05; + break; + case 1: /* "terry" */ + atom.f = 12.05; + break; + case 2: /* "emma" */ + case 3: /* "cathy" */ + atom.f = 11.09; + break; + case 4: /* "alexi" */ + atom.f = 5.26; + break; + } + break; + case 10: /* long.* group */ + atom.l = 1; + break; + case 11: + atom.l = 10; + break; + case 12: + atom.l = 100; + break; + case 13: + atom.l = 1000000; + break; + case 14: + atom.l = (__int32_t)_long; + break; + case 20: /* longlong.* group */ +#if !defined(HAVE_CONST_LONGLONG) + atom.ll = 1; +#else + atom.ll = 1LL; +#endif + break; + case 21: +#if !defined(HAVE_CONST_LONGLONG) + atom.ll = 10; +#else + atom.ll = 10LL; +#endif + break; + case 22: +#if !defined(HAVE_CONST_LONGLONG) + atom.ll = 100; +#else + atom.ll = 100LL; +#endif + break; + case 23: +#if !defined(HAVE_CONST_LONGLONG) + atom.ll = 1000000; +#else + atom.ll = 1000000LL; +#endif + break; + case 24: + atom.ll = _longlong; + break; + case 15: /* float.* group */ + atom.f = 1; + break; + case 16: + atom.f = 10; + break; + case 17: + atom.f = 100; + break; + case 18: + atom.f = 1000000; + break; + case 19: + atom.f = _float; + break; + case 25: /* double.* group */ + atom.d = 1; + break; + case 26: + atom.d = 10; + break; + case 27: + atom.d = 100; + break; + case 28: + atom.d = 1000000; + break; + case 29: + atom.d = _double; + break; + case 30: + atom.cp = ""; + break; + case 31: + atom.cp = "hullo world!"; + break; + case 32: + atom.cp = _string; + break; + case 33: + atom.vbp = _aggr33; + break; + case 34: + atom.vbp = _aggr34; + break; + case 35: + atom.vbp = _aggr35; + break; + case 52: + atom.l = inst; + break; + case 53: + atom.l = 499 - inst; + break; + case 56: + atom.l = not_ready; + break; + case 57: + _wrap += INT_MAX / 2 - 1; + atom.l = _wrap; + break; + case 58: + _u_wrap += UINT_MAX / 2 - 1; + atom.ul = _u_wrap; + break; + case 59: + _ll_wrap += LONGLONG_MAX / 2 - 1; + atom.ll = _ll_wrap; + break; + case 60: + _ull_wrap += ULONGLONG_MAX / 2 - 1; + atom.ull = _ull_wrap; + break; + case 61: + atom.l = dodgey; + break; + case 62: + if (dodgey > 5 && j == 0) + new_dodgey--; + if (tmp_dodgey <= 0) { + j = tmp_dodgey; + goto done; + } + else if (tmp_dodgey <= 5) { + if (inst > tmp_dodgey) + goto skip; + } + atom.l = (int)(lrand48() % 101); + break; + case 64: + _rapid += 80000000; + _pmHPCincr(&rapid_ctr, _rapid); + atom.ul = (__uint32_t)(rapid_ctr.full * 10); + break; + case 65: /* scale_step.bytes_up */ + atom.d = scale_step_bytes_up; + if (++scale_step_number[0] % 5 == 0) { + if (scale_step_bytes_up < 1024.0*1024.0*1024.0*1024.0) + scale_step_bytes_up *= 2; + else + scale_step_bytes_up = 1; + } + break; + case 66: /* scale_step.bytes_down */ + atom.d = scale_step_bytes_down; + if (++scale_step_number[1] % 5 == 0) { + if (scale_step_bytes_down > 1) + scale_step_bytes_down /= 2; + else + scale_step_bytes_down = 1024.0*1024.0*1024.0*1024.0; + } + break; + case 67: /* scale_step.count_up */ + atom.d = scale_step_count_up; + if (++scale_step_number[2] % 5 == 0) { + if (scale_step_count_up < 1.0e12) + scale_step_count_up *= 10; + else + scale_step_count_up = 1; + } + break; + case 68: /* scale_step.count_down */ + atom.d = scale_step_count_down; + if (++scale_step_number[3] % 5 == 0) { + if (scale_step_count_down > 1) + scale_step_count_down /= 10; + else + scale_step_count_down = 1.0e12; + } + break; + case 69: /* scale_step.time_up_secs */ + atom.d = scale_step_time_up_secs; + if (++scale_step_number[4] % 5 == 0) { + if (scale_step_time_up_secs < 60*60*24) + scale_step_time_up_secs *= 10; + else + scale_step_time_up_secs = 1; + } + break; + case 70: /* scale_step.time_up_nanosecs */ + atom.d = scale_step_time_up_nanosecs; + if (++scale_step_number[5] % 5 == 0) { + if (scale_step_time_up_nanosecs < 1e9*60*60*24) + scale_step_time_up_nanosecs *= 10; + else + scale_step_time_up_nanosecs = 1; + } + break; + case 71: /* scale_step.none_up */ + atom.d = scale_step_none_up; + if (++scale_step_number[6] % 5 == 0) { + if (scale_step_none_up < 10000000) + scale_step_none_up *= 10; + else + scale_step_none_up = 1; + } + break; + case 72: /* const_rate.value */ + __pmtimevalNow(&now); + atom.ul = const_rate_value + const_rate_gradient * __pmtimevalSub(&now, &const_rate_timestamp); + const_rate_timestamp = now; + const_rate_value = atom.ul; + break; + case 73: /* const_rate.gradient */ + atom.ul = const_rate_gradient; + break; + case 74: /* error_code */ + atom.l = _error_code; + break; + case 75: /* error_check */ + if (_error_code < 0) + return _error_code; + atom.l = 0; + break; + case 76: /* dynamic.counter */ + case 77: /* dynamic.discrete */ + case 78: /* dynamic.instant */ + if (inst > _dyn_max) { + /* bad instance! */ + goto done; + } + atom.l = _dyn_ctr[inst]; + break; + case 79: /* many.count */ + atom.l=many_count; + break; + case 80: /* many.int */ + atom.l = inst; + break; + case 81: /* byte_ctr */ + nbyte += lrand48() % 1024; + atom.l = nbyte; + break; + case 82: /* byte_rate */ + atom.l = (int)(lrand48() % 1024); + break; + case 83: /* kbyte_ctr */ + nbyte += lrand48() % 1024; + atom.l = nbyte; + break; + case 84: /* kbyte_rate */ + atom.l = (int)(lrand48() % 1024); + break; + case 85: /* byte_rate_per_hour */ + atom.l = (int)(lrand48() % 1024); + break; + case 86: /* dynamic.meta.metric */ + switch (magic.type) { + case PM_TYPE_32: + atom.l = 42; + break; + case PM_TYPE_U32: + atom.ul = 42; + break; + case PM_TYPE_64: + atom.ll = 42; + break; + case PM_TYPE_U64: + atom.ull = 42; + break; + case PM_TYPE_FLOAT: + atom.f = 42; + break; + case PM_TYPE_DOUBLE: + atom.d = 42; + break; + default: + /* do nothing in other cases ... return garbage */ + break; + } + break; + case 87: /* dynamic.meta.pmdesc.type */ + atom.ul = magic.type; + break; + case 88: /* dynamic.meta.pmdesc.indom */ + atom.ul = magic.indom; + break; + case 89: /* dynamic.meta.pmdesc.sem */ + atom.ul = magic.sem; + break; + case 90: /* dynamic.meta.pmdesc.units */ + ulp = (__uint32_t *)&magic.units; + atom.ul = *ulp; + break; + case 91: /* datasize */ + __pmProcessDataSize(&ul); + atom.ul = ul; + break; + /* no case 92 for darkeness, handled above */ + case 93: /* ulong.* group */ + atom.ul = 1; + break; + case 94: + atom.ul = 10; + break; + case 95: + atom.ul = 100; + break; + case 96: + atom.ul = 1000000; + break; + case 97: + atom.ul = (__int32_t)_ulong; + break; + case 98: /* ulonglong.* group */ +#if !defined(HAVE_CONST_LONGLONG) + atom.ull = 1; +#else + atom.ull = 1ULL; +#endif + break; + case 99: +#if !defined(HAVE_CONST_LONGLONG) + atom.ull = 10; +#else + atom.ull = 10ULL; +#endif + break; + case 100: +#if !defined(HAVE_CONST_LONGLONG) + atom.ull = 100; +#else + atom.ull = 100ULL; +#endif + break; + case 101: +#if !defined(HAVE_CONST_LONGLONG) + atom.ull = 1000000; +#else + atom.ull = 1000000ULL; +#endif + break; + case 102: + atom.ull = _ulonglong; + break; + case 115: /* ulong.count.base */ + atom.ul = 42000000; + break; + case 116: /* ulong.count.deca */ + atom.ul = 4200000; + break; + case 117: /* ulong.count.hecto */ + atom.ul = 420000; + break; + case 118: /* ulong.count.kilo */ + atom.ul = 42000; + break; + case 119: /* ulong.count.mega */ + atom.ul = 42; + break; + case 120: /* scramble.version */ + atom.ll = scramble_ver; + break; + case 126: /* event.reset */ + atom.l = event_get_fetch_count(); + break; + case 136: /* event.records */ + case 137: /* event.no_indom_records */ + if ((sts = sample_fetch_events(&atom.vbp, inst)) < 0) + return sts; + break; + case 139: /* event.highres_records */ + if ((sts = sample_fetch_highres_events(&atom.vbp, inst)) < 0) + return sts; + break; + case 140: /* event.reset_highres */ + atom.l = event_get_highres_fetch_count(); + break; + case 1000: /* secret.bar */ + atom.cp = "foo"; + break; + case 1001: /* secret.foo.one */ + atom.l = 1; + break; + case 1002: /* secret.foo.two */ + atom.l = 2; + break; + case 1003: /* secret.foo.bar.three */ + atom.l = 3; + break; + case 1004: /* secret.foo.bar.four */ + atom.l = 4; + break; + case 1005: /* secret.foo.bar.grunt.five */ + atom.l = 5; + break; + case 1006: /* secret.foo.bar.grunt.snort.six */ + atom.l = 6; + break; + case 1007: /* secret.foo.bar.grunt.snort.seven */ + atom.l = 7; + break; + case 1023: /* bigid */ + atom.l = 4194303; + break; + } + } + if ((sts = __pmStuffValue(&atom, &vset->vlist[j], type)) < 0) { + __pmFreeResultValues(res); + return sts; + } + vset->valfmt = sts; + j++; /* next element in vlist[] for next instance */ + +skip: + ; + } while (dp->indom != PM_INDOM_NULL && nextinst(&inst)); +done: + vset->numval = j; + } + *resp = res; + return PMDA_FETCH_STATIC; +} + +static int +sample_desc(pmID pmid, pmDesc *desc, pmdaExt *ep) +{ + int i; + __pmID_int *pmidp = (__pmID_int *)&pmid; + + sample_inc_recv(ep->e_context); + sample_inc_xmit(ep->e_context); + + if (not_ready > 0) { + return limbo(); + } + + if (direct_map) { + i = pmidp->item; + if (i < ndesc && desctab[i].pmid == pmid) + goto doit; + } + for (i = 0; desctab[i].pmid != PM_ID_NULL; i++) { + if (desctab[i].pmid == pmid) { +doit: + /* the special cases */ + if (pmidp->item == 54) + return PM_ERR_PMID; + else if (pmidp->item == 75 && _error_code < 0) + /* error_check and error_code armed */ + return _error_code; + else if (pmidp->item == 86) + *desc = magic; + else + *desc = desctab[i]; + return 0; + } + } + return PM_ERR_PMID; +} + +static int +sample_text(int ident, int type, char **buffer, pmdaExt *ep) +{ + int sts; + + sample_inc_recv(ep->e_context); + sample_inc_xmit(ep->e_context); + + if (not_ready > 0) { + return limbo(); + } + + if (ident & PM_TEXT_PMID) { + __pmID_int *pmidp = (__pmID_int *)&ident; + int i; + + if (direct_map) { + i = pmidp->item; + if (i < ndesc && desctab[i].pmid == (pmID)ident) + goto doit; + } + for (i = 0; desctab[i].pmid != PM_ID_NULL; i++) { + if (desctab[i].pmid == (pmID)ident) { +doit: + /* the special cases */ + if (pmidp->item == 75 && _error_code < 0) + /* error_check and error_code armed */ + return _error_code; + break; + } + } + } + + sts = pmdaText(ident, type, buffer, ep); + + return sts; +} + +static int +sample_store(pmResult *result, pmdaExt *ep) +{ + int i; + pmValueSet *vsp; + pmDesc *dp; + __pmID_int *pmidp; + int sts = 0; + __int32_t *lp; + pmAtomValue av; + + sample_inc_recv(ep->e_context); + sample_inc_xmit(ep->e_context); + + if (not_ready > 0) { + return limbo(); + } + + for (i = 0; i < result->numpmid; i++) { + vsp = result->vset[i]; + for (dp = desctab; dp->pmid != PM_ID_NULL; dp++) { + if (dp->pmid == vsp->pmid) + break; + } + if (dp->pmid == PM_ID_NULL) { + /* not one of our metrics */ + sts = PM_ERR_PMID; + break; + } + pmidp = (__pmID_int *)&vsp->pmid; + + if (pmidp->cluster != 0) { + sts = PM_ERR_PMID; + break; + } + + /* + * for this PMD, the metrics that support modification + * via pmStore() mostly demand a single value, encoded in + * the result structure as PM_VAL_INSITU format + */ + switch (pmidp->item) { + case 24: /* longlong.write_me */ + case 29: /* double.write_me */ + case 32: /* string.write_me */ + case 35: /* aggregate.write_me */ + case 102: /* ulonglong.write_me */ + case 120: /* scramble.ver */ + if (vsp->numval != 1 || vsp->valfmt == PM_VAL_INSITU) + sts = PM_ERR_CONV; + break; + + case 74: /* error_code */ + case 73: /* const_rate.gradient */ + case 61: /* dodgey.control */ + case 56: /* not_ready */ + case 36: + case 42: + case 41: + case 14: /* long.write_me */ + case 8: /* step */ + case 7: /* drift */ + case 0: /* control */ + case 79: /* many.count */ + case 87: /* dynamic.meta.pmdesc.type */ + case 88: /* dynamic.meta.pmdesc.indom */ + case 89: /* dynamic.meta.pmdesc.sem */ + case 90: /* dynamic.meta.pmdesc.units */ + case 97: /* ulong.write_me */ + case 126: /* event.reset */ + case 140: /* event.reset_highres */ + if (vsp->numval != 1 || vsp->valfmt != PM_VAL_INSITU) + sts = PM_ERR_CONV; + break; + + case 19: /* float.write_me */ + if (vsp->numval != 1) + sts = PM_ERR_CONV; + /* accommodate both old and new encoding styles for floats */ + break; + + case 40: /* pdu */ + /* value is ignored, so valfmt does not matter */ + if (vsp->numval != 1) + sts = PM_ERR_CONV; + break; + + default: + sts = PM_ERR_PERMISSION; + break; + + } + if (sts != 0) + break; + + if ((sts = pmExtractValue(vsp->valfmt, &vsp->vlist[0], dp->type, &av, dp->type)) < 0) + break; + + /* + * we only have cluster 0, metric already found in desctab[], + * so no checking needed nor outer case on pmidp->cluster + */ + switch (pmidp->item) { + case 0: /* control */ + _control = av.l; + switch (_control) { + case -1: + /* terminate, if we are not a DSO implementation */ + sample_done = 1; + break; + default: + pmDebug = _control; + break; + } + break; + case 7: /* drift */ + _drift = av.l; + break; + case 8: /* step */ + _step = av.l; + break; + case 14: /* long.write_me */ + _long = av.l; + break; + case 24: /* longlong.write_me */ + _longlong = av.ll; + break; + case 19: /* float.write_me */ + _float = av.f; + break; + case 40: /* pdu */ + /* + * for the pdu group, the value is ignored, and the only + * operation is to reset the counter(s) + */ + sample_clr_recv(CTX_ALL); + sample_clr_xmit(CTX_ALL); + break; + case 41: + sample_clr_recv(CTX_ALL); + break; + case 42: + sample_clr_xmit(CTX_ALL); + break; + case 36: + _write_me = av.l; + break; + case 29: /* double.write_me */ + _double = av.d; + break; + case 32: /* string.write_me */ + free(_string); + _string = av.cp; + break; + case 35: /* aggregate.write_me */ + free(_aggr35); + _aggr35 = av.vbp; + break; + case 56: /* not_ready */ + not_ready = av.l; + break; + case 61: /* dodgey.control */ + dodgey = av.l; + redo_dodgey(); + break; + case 73: /* const_rate.gradient */ + const_rate_gradient = av.ul; + break; + case 74: /* error_code */ + _error_code = av.l; + break; + case 79: /* many.count */ + many_count = av.l; + /* change the size of the many instance domain */ + _error_code = redo_many(); + break; + case 87: /* dynamic.meta.pmdesc.type */ + magic.type = av.l; + break; + case 88: /* dynamic.meta.pmdesc.indom */ + magic.indom = av.l; + break; + case 89: /* dynamic.meta.pmdesc.sem */ + magic.sem = av.l; + break; + case 90: /* dynamic.meta.pmdesc.units */ + lp = (__int32_t *)&magic.units; + *lp = av.l; + break; + case 97: /* ulong.write_me */ + _ulong = av.ul; + break; + case 102: /* ulonglong.write_me */ + _ulonglong = av.ull; + break; + case 120: /* scramble.version */ + scramble_ver = 0; + for (i = 0; i < indomtab[BIN_INDOM].it_numinst; i++) { + indomtab[SCRAMBLE_INDOM].it_set[i].i_inst = indomtab[BIN_INDOM].it_set[i].i_inst; + indomtab[SCRAMBLE_INDOM].it_set[i].i_name = indomtab[BIN_INDOM].it_set[i].i_name; + } + indomtab[SCRAMBLE_INDOM].it_numinst = indomtab[BIN_INDOM].it_numinst; + break; + case 126: /* event.reset */ + event_set_fetch_count(av.l); + break; + case 140: /* event.reset_highres */ + event_set_highres_fetch_count(av.l); + break; + default: + sts = PM_ERR_PERMISSION; + break; + } + } + + return sts; +} + +void +__PMDA_INIT_CALL +sample_init(pmdaInterface *dp) +{ + char helppath[MAXPATHLEN]; + int i; + + if (_isDSO) { + int sep = __pmPathSeparator(); + snprintf(helppath, sizeof(helppath), "%s%c" "sample" "%c" "dsohelp", + pmGetConfig("PCP_PMDAS_DIR"), sep, sep); + pmdaDSO(dp, PMDA_INTERFACE_LATEST, "sample DSO", helppath); + } + else { + __pmProcessDataSize(NULL); + } + + if (dp->status != 0) + return; + dp->comm.flags |= PDU_FLAG_AUTH; + + dp->version.any.fetch = sample_fetch; + dp->version.any.desc = sample_desc; + dp->version.any.instance = sample_instance; + dp->version.any.text = sample_text; + dp->version.any.store = sample_store; + dp->version.any.profile = sample_profile; + dp->version.four.pmid = sample_pmid; + dp->version.four.name = sample_name; + dp->version.four.children = sample_children; + dp->version.six.attribute = sample_attribute; + pmdaSetEndContextCallBack(dp, sample_ctx_end); + + pmdaInit(dp, NULL, 0, NULL, 0); /* don't use indomtab or metrictab */ + + __pmtimevalNow(&_then); + _start = time(NULL); + init_tables(dp->domain); + init_events(dp->domain); + redo_mirage(); + redo_dynamic(); + + /* initialization of domain in PMIDs for dynamic PMNS entries */ + for (i = 0; i < numdyn; i++) { + ((__pmID_int *)&dynamic_ones[i].pmid)->domain = dp->domain; + } + /* + * Max Matveev wanted this sort of redirection, so first entry is + * actually a redirect to PMID 2.4.1 (pmcd.agent.status) + */ + ((__pmID_int *)&dynamic_ones[0].pmid)->domain = 2; + ((__pmID_int *)&dynamic_ones[0].pmid)->cluster = 4; + ((__pmID_int *)&dynamic_ones[0].pmid)->item = 1; + + /* + * for gcc/egcs, statically initializing these cased the strings + * to be read-only, causing SEGV in redo_dynamic ... so do the + * initialization dynamically here. + */ + _dodgey[0].i_name = strdup("d1"); + _dodgey[1].i_name = strdup("d2"); + _dodgey[2].i_name = strdup("d3"); + _dodgey[3].i_name = strdup("d4"); + _dodgey[4].i_name = strdup("d5"); +} |