summaryrefslogtreecommitdiff
path: root/src/pmdas/sample
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2014-10-26 12:33:50 +0400
committerIgor Pashev <pashev.igor@gmail.com>2014-10-26 12:33:50 +0400
commit47e6e7c84f008a53061e661f31ae96629bc694ef (patch)
tree648a07f3b5b9d67ce19b0fd72e8caa1175c98f1a /src/pmdas/sample
downloadpcp-47e6e7c84f008a53061e661f31ae96629bc694ef.tar.gz
Debian 3.9.10debian/3.9.10debian
Diffstat (limited to 'src/pmdas/sample')
-rw-r--r--src/pmdas/sample/GNUmakefile40
-rwxr-xr-xsrc/pmdas/sample/Install74
-rw-r--r--src/pmdas/sample/README63
-rwxr-xr-xsrc/pmdas/sample/Remove45
-rw-r--r--src/pmdas/sample/Sample.pmchart10
-rw-r--r--src/pmdas/sample/domain.h4
-rwxr-xr-xsrc/pmdas/sample/get_next_pmid48
-rw-r--r--src/pmdas/sample/help602
-rw-r--r--src/pmdas/sample/pmns260
-rw-r--r--src/pmdas/sample/root20
-rw-r--r--src/pmdas/sample/src/GNUmakefile62
-rw-r--r--src/pmdas/sample/src/GNUmakefile.install53
-rw-r--r--src/pmdas/sample/src/events.c477
-rw-r--r--src/pmdas/sample/src/events.h33
-rw-r--r--src/pmdas/sample/src/percontext.c256
-rw-r--r--src/pmdas/sample/src/percontext.h31
-rw-r--r--src/pmdas/sample/src/pmda.c126
-rw-r--r--src/pmdas/sample/src/sample.c2748
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");
+}