summaryrefslogtreecommitdiff
path: root/src/pmdas/txmon
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdas/txmon')
-rw-r--r--src/pmdas/txmon/GNUmakefile68
-rw-r--r--src/pmdas/txmon/GNUmakefile.install57
-rwxr-xr-xsrc/pmdas/txmon/Install56
-rw-r--r--src/pmdas/txmon/README77
-rw-r--r--src/pmdas/txmon/Remove38
-rwxr-xr-xsrc/pmdas/txmon/genload120
-rw-r--r--src/pmdas/txmon/help62
-rw-r--r--src/pmdas/txmon/pmns32
-rw-r--r--src/pmdas/txmon/root10
-rw-r--r--src/pmdas/txmon/txmon.c383
-rw-r--r--src/pmdas/txmon/txmon.h53
-rw-r--r--src/pmdas/txmon/txrecord.c108
12 files changed, 1064 insertions, 0 deletions
diff --git a/src/pmdas/txmon/GNUmakefile b/src/pmdas/txmon/GNUmakefile
new file mode 100644
index 0000000..7c423ba
--- /dev/null
+++ b/src/pmdas/txmon/GNUmakefile
@@ -0,0 +1,68 @@
+#
+# Copyright (c) 2012 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.
+#
+
+TOPDIR = ../../..
+include $(TOPDIR)/src/include/builddefs
+
+DFILES = README
+CFILES = txmon.c txrecord.c
+HFILES = txmon.h
+TARGETS = txmon$(EXECSUFFIX) txrecord$(EXECSUFFIX)
+
+LCFLAGS = -I.
+LLDLIBS = $(PCP_PMDALIB)
+
+SCRIPTS = Install Remove genload
+OTHERS = pmns help root
+LSRCFILES= $(SCRIPTS) $(OTHERS) GNUmakefile.install $(DFILES)
+
+IAM = txmon
+DOMAIN = TXMON
+PMDADIR = $(PCP_PMDAS_DIR)/$(IAM)
+
+LDIRT = *.o *.log *.dir *.pag domain.h $(TARGETS)
+
+default: build-me
+
+include $(BUILDRULES)
+
+ifneq "$(TARGET_OS)" "mingw"
+build-me: $(TARGETS)
+
+install: build-me
+ $(INSTALL) -m 755 -d $(PMDADIR)
+ $(INSTALL) -m 755 $(SCRIPTS) $(PMDADIR)
+ $(INSTALL) -m 644 $(DFILES) root $(HFILES) $(PMDADIR)
+ $(INSTALL) -m 644 help pmns domain.h $(CFILES) $(PMDADIR)
+ $(INSTALL) -m 644 GNUmakefile.install $(PMDADIR)/Makefile
+else
+build-me:
+install:
+endif
+
+domain.h: ../../pmns/stdpmid
+ $(DOMAIN_MAKERULE)
+
+$(OBJECTS): domain.h
+
+txmon$(EXECSUFFIX): txmon.o
+ $(CCF) -o $@ $(LDFLAGS) txmon.o $(LDLIBS)
+
+txrecord$(EXECSUFFIX): txrecord.o
+ $(CCF) -o $@ $(LDFLAGS) txrecord.o $(LDLIBS)
+
+default_pcp: default
+
+install_pcp: install
diff --git a/src/pmdas/txmon/GNUmakefile.install b/src/pmdas/txmon/GNUmakefile.install
new file mode 100644
index 0000000..1f264c0
--- /dev/null
+++ b/src/pmdas/txmon/GNUmakefile.install
@@ -0,0 +1,57 @@
+#
+# Copyright (c) 2012 Red Hat.
+# Copyright (c) 2000,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.
+#
+
+SHELL = sh
+
+ifdef PCP_CONF
+include $(PCP_CONF)
+else
+PCP_DIR = $(shell echo $$PCP_DIR)
+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 = txmon
+CFILES = $(IAM).c
+CMDTARGET = pmda$(IAM)
+TARGETS = txrecord $(CMDTARGET)
+LLDLIBS = -lpcp_pmda -lpcp $(LIB_FOR_MATH) $(LIB_FOR_PTHREADS)
+LDIRT = *.log help.dir help.pag txrecord
+
+default: $(TARGETS)
+
+install: default
+
+pmda$(IAM): txmon.h domain.h $(CFILES)
+
+txrecord.o: txmon.h txrecord.c
+
+txrecord: txrecord.o
+ $(CC) $(CFLAGS) -o $@ txrecord.o $(LDFLAGS) $(LDLIBS)
+
+include $(PCP_INC_DIR)/buildrules
diff --git a/src/pmdas/txmon/Install b/src/pmdas/txmon/Install
new file mode 100755
index 0000000..b8e1fcf
--- /dev/null
+++ b/src/pmdas/txmon/Install
@@ -0,0 +1,56 @@
+#! /bin/sh
+#
+# Copyright (c) 1997,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.
+#
+# Install the txmon PMDA and/or PMNS
+#
+
+. $PCP_DIR/etc/pcp.env
+. $PCP_SHARE_DIR/lib/pmdaproc.sh
+
+iam=txmon
+pmda_interface=2
+forced_restart=false
+
+pmdaSetup
+
+if $do_pmda
+then
+ # special txmon PMDA args
+ #
+ echo 'Welcome to the Install script for the demonstration "txmon" PMDA.
+This PMDA will establish a shared memory segment with one statistics
+structure per transaction type.
+
+You must define the names of the transaction types (the names are
+arbitrary strings with no embedded white space, e.g. mytx#1).
+'
+
+ args=""
+ while true
+ do
+ $PCP_ECHO_PROG $PCP_ECHO_N "Name for transaction type? [return if no more] ""$PCP_ECHO_C"
+ read ans
+ [ -z "$ans" ] && break
+ args="$args $ans"
+ done
+ if [ -z "$args" ]
+ then
+ echo "You need to specify at least one transaction type name!"
+ exit 1
+ fi
+fi
+
+pmdaInstall
+
+exit 0
diff --git a/src/pmdas/txmon/README b/src/pmdas/txmon/README
new file mode 100644
index 0000000..97fea32
--- /dev/null
+++ b/src/pmdas/txmon/README
@@ -0,0 +1,77 @@
+txmon PMDA
+===========
+
+This PMDA is a sample that illustrates how a simple transaction monitor
+PMDA might be constructed, using a shared memory segment to transfer
+information about transaction activity from the applications that
+submit (or process) transactions and the txmon PMDA.
+
+Although the metrics supported are simple, the framework is quite
+general and could be extended to implement a much more complex PMDA.
+
+Note:
+ This PMDA may be remade from source and hence requires IDO (or
+ more specifically a C compiler) to be installed.
+
+ Uses of make(1) may fail (without removing or clobbering files)
+ if the C compiler cannot be found. This is most likely to
+ happen when running the PMDA ./Install script.
+
+ The only remedial action is to install the C compiler, or
+ hand-craft changes to the Makefile.
+
+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 txmon
+
+Installation
+============
+
+ + # cd $PCP_PMDAS_DIR/txmon
+
+ + 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.
+
+ + Then simply use
+
+ # ./Install
+
+ and choose both the "collector" and "monitor" installation
+ configuration options.
+
+ You will be prompted to define the names of the transaction types
+ to be monitored -- everything else is automated.
+
+De-installation
+===============
+
+ + Simply use
+
+ # cd $PCP_PMDAS_DIR/txmon
+ # ./Remove
+
+Making something happen
+=======================
+
+The application ./txrecord updates the shared memory segment to add
+new information about transactions and their service times. Usually
+this would be run from the ./genload script that will continue to
+update the shared memory segment with data drawn from some synthetic
+distributions.
+
+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/txmon.log) should be checked for any warnings
+ or errors.
diff --git a/src/pmdas/txmon/Remove b/src/pmdas/txmon/Remove
new file mode 100644
index 0000000..5b71f70
--- /dev/null
+++ b/src/pmdas/txmon/Remove
@@ -0,0 +1,38 @@
+#! /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 txmon PMDA
+#
+
+# Get standard environment
+. $PCP_DIR/etc/pcp.env
+
+# Get the common procedures and variable assignments
+#
+. $PCP_SHARE_DIR/lib/pmdaproc.sh
+
+# The name of the PMDA
+#
+iam=txmon
+
+# Do it
+#
+pmdaSetup
+pmdaRemove
+
+exit 0
diff --git a/src/pmdas/txmon/genload b/src/pmdas/txmon/genload
new file mode 100755
index 0000000..d906eaa
--- /dev/null
+++ b/src/pmdas/txmon/genload
@@ -0,0 +1,120 @@
+#! /bin/sh
+#
+# Copyright (c) 1997,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.
+#
+# 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
+#
+# micky mouse transaction load generator ...
+#
+
+# Get standard environment
+. $PCP_DIR/etc/pcp.env
+
+
+NUMTX=-1
+while getopts n:\? c
+do
+ case $c
+ in
+ n) NUMTX=$OPTARG;;
+ \?) echo "Usage: genload [-n numtx] [tps [avg_serv]]"
+ exit 1
+ ;;
+ esac
+done
+shift `expr $OPTIND - 1`
+
+# target TPS [default 10]
+#
+TPS=${1-10}
+
+# mean of the mean service times [default 10 seconds]
+#
+AVG=${2-10}
+
+if [ ! -x ./txrecord ]
+then
+ echo 'Error: no txrecord binary here ... try "make txrecord"?'
+ exit 1
+fi
+
+# get tx types from txmon PMDA via pmcd on the localhost, then choose tx
+# type with Zipfian distribution, and artifically chosen service times
+# ... pipe them to a record-then-sleep droid in the while loop at the
+# end ... rate throttling relies on O/S pipe-full synchronization
+# (crude, but simple and effective)
+#
+pminfo -f txmon.count \
+| tr -d '"\]\[' \
+| $PCP_AWK_PROG '
+BEGIN { i = 0; w = 2; s = 0; numtx='$NUMTX' }
+/value/ { name[i] = $4; zipf[i] = s + 1 / w; s = zipf[i]
+ i++; w *= 2
+ }
+END { if (i == 0) {
+ print "e Cannot determine transaction type names ... is the txmon PMDA running locally?"
+ exit
+ }
+ # compute mean, drawn from normal distn with mean and std dev AVG
+ for (j=0; j<i; j++) {
+ while (1) { # the csw method
+ y = rand()
+ d = 1 - y
+ h = 0.14 / d
+ x = 1.22 * y * (1.0 + h)
+ t = log(rand() / (1.0 + h/d)) + 0.5 * x*x + 0.1576
+ if (t <= 0) {
+ if (t >= -0.69314706) x = -x
+ m[j] = '$AVG' + '$AVG' * x
+ if (m[j] >= 0)
+ break
+ }
+ }
+ print "i Mean service time for " name[j] " tx: " m[j]
+ }
+ zipf[i-1] = 1 # force upper bound of last interval
+ while (numtx != 0) {
+ printf "w "
+ for (k=0; k < '$TPS' && numtx != 0; k++) {
+ r = rand()
+ for (j=0; j<i; j++) {
+ if (r <= zipf[j])
+ break
+ }
+ printf " %s %f",name[j],rand() * m[j]
+ if (numtx > 0)
+ numtx--
+ }
+ print ""
+ print "s"
+ }
+ }' \
+| while read action arg
+do
+ case $action
+ in
+ i) echo "$arg"
+ ;;
+ e) echo "Error: $arg"
+ exit 1
+ ;;
+ s) sleep 1
+ ;;
+ w) ./txrecord $arg
+ ;;
+ esac
+done
+
+
diff --git a/src/pmdas/txmon/help b/src/pmdas/txmon/help
new file mode 100644
index 0000000..83e2300
--- /dev/null
+++ b/src/pmdas/txmon/help
@@ -0,0 +1,62 @@
+#
+# 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
+#
+# txmon 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
+#
+
+@ TXMON.0 Instance domain "transaction type name" for txmon PMDA
+There is one instance for each transaction type.
+
+@ txmon.count count by transaction type
+Count by transaction type of transactions serviced since the txmon PMDA
+started.
+
+@ txmon.reset_count reset count by transaction type
+Count by transaction type of transactions serviced since the last time
+the average and maximum summaries were reset.
+
+@ txmon.ave_time average time per transaction type
+Average recorded service time per transaction type since the last time
+the statistics were reset.
+
+@ txmon.max_time maximum time per transaction type
+Maximum recorded service time per transaction type since the last time
+the statistics were reset.
+
+@ txmon.control.level statistics control levels
+0 => no statistics are collected
+1 => transaction counts are enabled
+2 => transaction counts and service times are enabled
+
+@ txmon.control.reset reset statistics
+This metric is a toggle-switch ... any pmStore() operation for this
+metric will reset all statistics except txmon.count.
+
+The value for this metric is always 1.
diff --git a/src/pmdas/txmon/pmns b/src/pmdas/txmon/pmns
new file mode 100644
index 0000000..9535a4d
--- /dev/null
+++ b/src/pmdas/txmon/pmns
@@ -0,0 +1,32 @@
+/*
+ * Metrics for txmon PMDA
+ *
+ * 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
+ */
+
+txmon {
+ count TXMON:0:0
+ ave_time TXMON:0:1
+ max_time TXMON:0:2
+ reset_count TXMON:0:3
+ control
+}
+
+txmon.control {
+ level TXMON:0:4
+ reset TXMON:0:5
+}
diff --git a/src/pmdas/txmon/root b/src/pmdas/txmon/root
new file mode 100644
index 0000000..3d85304
--- /dev/null
+++ b/src/pmdas/txmon/root
@@ -0,0 +1,10 @@
+/*
+ * fake "root" for validating the local PMNS subtree
+ */
+
+#include <stdpmid>
+
+root { txmon }
+
+#include "pmns"
+
diff --git a/src/pmdas/txmon/txmon.c b/src/pmdas/txmon/txmon.c
new file mode 100644
index 0000000..bdfbf7a
--- /dev/null
+++ b/src/pmdas/txmon/txmon.c
@@ -0,0 +1,383 @@
+/*
+ * txmon PMDA
+ *
+ * Copyright (c) 2012 Red Hat.
+ * Copyright (c) 1995-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.
+ */
+
+#include <pcp/pmapi.h>
+#include <pcp/impl.h>
+#include <pcp/pmda.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include "domain.h"
+
+#define CACHELINE 32
+#define RND_TO_CACHE_LINE(x) (((x + CACHELINE - 1) / CACHELINE) * CACHELINE)
+
+/*
+ * txmon PMDA
+ *
+ * This PMDA is a sample that illustrates how a PMDA might be
+ * constructed with libpcp_pmda to use a System V shared memory (shm)
+ * segment to transfer performance data between the collectors on the
+ * application side (see ./txrecord and ./genload for a simple example)
+ * and this PCP PMDA
+ */
+
+/*
+ * list of instances ... created dynamically, after parsing cmd line options
+ */
+static pmdaInstid *tx_indom;
+
+/*
+ * list of instance domains ... initialized after parsing cmd line options
+ */
+static pmdaIndom indomtab[] = {
+#define TX_INDOM 0
+ { TX_INDOM, 0, NULL },
+};
+
+/*
+ * all metrics supported in this PMDA - one table entry for each
+ */
+static pmdaMetric metrictab[] = {
+/* count */
+ { NULL,
+ { PMDA_PMID(0,0), PM_TYPE_U32, TX_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } },
+/* ave_time */
+ { NULL,
+ { PMDA_PMID(0,1), PM_TYPE_FLOAT, TX_INDOM, PM_SEM_INSTANT,
+ PMDA_PMUNITS(0,1,-1,0,PM_TIME_SEC,PM_COUNT_ONE) } },
+/* max_time */
+ { NULL,
+ { PMDA_PMID(0,2), PM_TYPE_FLOAT, TX_INDOM, PM_SEM_INSTANT,
+ PMDA_PMUNITS(0, 1, 0, 0, PM_TIME_SEC, 0 ) } },
+/* reset_count */
+ { NULL,
+ { PMDA_PMID(0,3), PM_TYPE_U32, TX_INDOM, PM_SEM_INSTANT,
+ PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } },
+/* control.level */
+ { NULL,
+ { PMDA_PMID(0,4), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT,
+ PMDA_PMUNITS(0,0,0,0,0,0) } },
+/* control.reset */
+ { NULL,
+ { PMDA_PMID(0,5), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT,
+ PMDA_PMUNITS(0,0,0,0,0,0) } },
+};
+
+#include "./txmon.h"
+
+static int shmid = -1;
+
+static char mypath[MAXPATHLEN];
+static char *username;
+
+/*
+ * callback provided to pmdaFetch
+ */
+static int
+txmon_fetchCallBack(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom)
+{
+ stat_t *sp;
+ __pmID_int *idp = (__pmID_int *)&(mdesc->m_desc.pmid);
+ unsigned int real_count;
+
+ if (inst != PM_IN_NULL && mdesc->m_desc.indom == PM_INDOM_NULL)
+ return PM_ERR_INST;
+
+ if (idp->cluster != 0)
+ return PM_ERR_PMID;
+
+ if (idp->item <= 3) {
+ if (inst >= control->n_tx)
+ return PM_ERR_INST;
+
+ sp = (stat_t *)((__psint_t)control + control->index[inst]);
+
+ switch (idp->item) {
+ case 0: /* txmon.count */
+ if (control->level < 1)
+ return PM_ERR_AGAIN;
+ atom->ul = sp->count;
+ break;
+ case 1: /* txmon.ave_time */
+ if (control->level < 2)
+ return PM_ERR_AGAIN;
+ real_count = sp->count - sp->reset_count;
+ atom->f = real_count > 0 ? sp->sum_time / real_count : -1;
+ break;
+ case 2: /* txmon.max_time */
+ if (control->level < 2)
+ return PM_ERR_AGAIN;
+ atom->f = sp->max_time;
+ break;
+ case 3: /* txmon.reset_count */
+ if (control->level < 1)
+ return PM_ERR_AGAIN;
+ atom->ul = sp->count - sp->reset_count;
+ break;
+ }
+ }
+ else {
+ switch (idp->item) {
+
+ case 4: /* txmon.control.level */
+ atom->ul = control->level;
+ break;
+ case 5: /* txmon.control.reset */
+ atom->ul = 1;
+ break;
+ default:
+ return PM_ERR_PMID;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * support the storage of a value into the control metrics
+ */
+static int
+txmon_store(pmResult *result, pmdaExt *pmda)
+{
+ int i;
+ int n;
+ int val;
+ int sts = 0;
+ pmValueSet *vsp = NULL;
+ __pmID_int *pmidp = NULL;
+ stat_t *sp;
+
+ for (i = 0; i < result->numpmid; i++) {
+ vsp = result->vset[i];
+ pmidp = (__pmID_int *)&vsp->pmid;
+
+ if (pmidp->cluster == 0) { /* all storable metrics are cluster 0 */
+
+ switch (pmidp->item) {
+ case 0: /* no store for these ones */
+ case 1:
+ case 2:
+ case 3:
+ sts = PM_ERR_PERMISSION;
+ break;
+
+ case 4: /* txmon.control.level */
+ val = vsp->vlist[0].value.lval;
+ if (val < 0) {
+ sts = PM_ERR_SIGN;
+ val = 0;
+ }
+ control->level = val;
+ break;
+
+ case 5: /* txmon.control.reset */
+ for (n = 0; n < control->n_tx; n++) {
+ sp = (stat_t *)((__psint_t)control + control->index[n]);
+ sp->reset_count = sp->count;
+ sp->sum_time = 0;
+ sp->max_time = -1;
+ }
+ break;
+
+ default:
+ sts = PM_ERR_PMID;
+ break;
+ }
+ }
+ else
+ sts = PM_ERR_PMID;
+ }
+ return sts;
+}
+
+
+/*
+ * Initialise the agent
+ */
+void
+txmon_init(pmdaInterface *dp)
+{
+ if (dp->status != 0)
+ return;
+
+ __pmSetProcessIdentity(username);
+
+ dp->version.two.store = txmon_store;
+
+ pmdaSetFetchCallBack(dp, txmon_fetchCallBack);
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0) {
+ fprintf(stderr, "after pmdaSetFetchCallBack() control @ %p\n", control);
+ }
+#endif
+
+ pmdaInit(dp, indomtab, 1, metrictab,
+ sizeof(metrictab)/sizeof(metrictab[0]));
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0) {
+ fprintf(stderr, "after pmdaInit() control @ %p\n", control);
+ }
+#endif
+}
+
+/*
+ * come here on exit()
+ */
+static void
+done(void)
+{
+ if (shmid != -1)
+ /* remove the shm segment */
+ shmctl(shmid, IPC_RMID, NULL);
+}
+
+pmLongOptions longopts[] = {
+ PMDA_OPTIONS_HEADER("Options"),
+ PMOPT_DEBUG,
+ PMDAOPT_DOMAIN,
+ PMDAOPT_LOGFILE,
+ PMDAOPT_USERNAME,
+ PMOPT_HELP,
+ PMDA_OPTIONS_END
+};
+
+pmdaOptions opts = {
+ .short_options = "D:d:l:U:?",
+ .long_options = longopts,
+ .short_usage = "[options] tx_type [...]",
+};
+
+/*
+ * Set up the agent.
+ */
+int
+main(int argc, char **argv)
+{
+ int n, sep = __pmPathSeparator();
+ char *p;
+ pmdaInterface dispatch;
+ size_t index_size;
+ size_t shm_size;
+ stat_t *sp;
+
+ __pmSetProgname(argv[0]);
+ __pmGetUsername(&username);
+
+ snprintf(mypath, sizeof(mypath), "%s%c" "txmon" "%c" "help",
+ pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
+ pmdaDaemon(&dispatch, PMDA_INTERFACE_2, pmProgname, TXMON,
+ "txmon.log", mypath);
+
+ pmdaGetOptions(argc, argv, &opts, &dispatch);
+ if (opts.errors) {
+ pmdaUsageMessage(&opts);
+ exit(1);
+ }
+ n = argc - opts.optind;
+ if (n < 1) {
+ pmprintf("No transaction types specified\n\n");
+ pmdaUsageMessage(&opts);
+ exit(1);
+ }
+ if (opts.username)
+ username = opts.username;
+
+ pmdaOpenLog(&dispatch);
+
+ /*
+ * create the instance domain table ... one entry per transaction type
+ */
+ if ((tx_indom = (pmdaInstid *)malloc(n * sizeof(pmdaInstid))) == NULL) {
+ fprintf(stderr, "malloc(%d): %s\n",
+ n * (int)sizeof(pmdaInstid), osstrerror());
+ exit(1);
+ }
+ indomtab[0].it_numinst = n;
+ indomtab[0].it_set = tx_indom;
+
+ /*
+ * size shm segment so each stat_t starts on a cache line boundary
+ */
+ index_size =
+ RND_TO_CACHE_LINE(sizeof(control->level) +
+ sizeof(control->n_tx) +
+ n * sizeof(control->index[0]));
+ shm_size = index_size + n * RND_TO_CACHE_LINE(sizeof(stat_t));
+
+ /*
+ * create the shm segment, and install exit() handler to remove it
+ */
+ if ((shmid = shmget(KEY, shm_size, IPC_CREAT|0666)) < 0) {
+ fprintf(stderr, "shmid: %s\n", osstrerror());
+ exit(1);
+ }
+ atexit(done);
+ if ((control = (control_t *)shmat(shmid, NULL, 0)) == (control_t *)-1) {
+ fprintf(stderr, "shmat: %s\n", osstrerror());
+ exit(1);
+ }
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0) {
+ fprintf(stderr, "shmat -> control @ %p\n", control);
+ }
+#endif
+
+ /*
+ * set up the shm control info and directory
+ */
+ control->n_tx = n;
+ control->level = 2; /* arbitrary default stats level */
+ p = (char *)control;
+ p = &p[index_size];
+ for (n = 0; n < control->n_tx; n++) {
+ /*
+ * Note: it is important that the index[] entries are byte
+ * offsets from the start of the shm segment ... using
+ * pointers may cause problems for 32-bit and 64-bit apps
+ * attaching to the shm segment
+ */
+ control->index[n] = p - (char *)control;
+ sp = (stat_t *)p;
+ strncpy(sp->type, argv[opts.optind++], MAXNAMESIZE);
+ sp->type[MAXNAMESIZE-1] = '\0'; /* ensure null terminated */
+ sp->reset_count = 0;
+ sp->count = 0;
+ sp->max_time = -1.0;
+ sp->sum_time = 0.0;
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0) {
+ fprintf(stderr, "index[%d]=%d @ %p name=\"%s\"\n", n, control->index[n], p, sp->type);
+ }
+#endif
+ p += RND_TO_CACHE_LINE(sizeof(stat_t));
+
+ /*
+ * and set up the corresponding indom table entries
+ */
+ tx_indom[n].i_inst = n;
+ tx_indom[n].i_name = sp->type;
+ }
+
+ /*
+ * the real work is done below here ...
+ */
+ txmon_init(&dispatch);
+ pmdaConnect(&dispatch);
+ pmdaMain(&dispatch);
+ exit(0);
+}
diff --git a/src/pmdas/txmon/txmon.h b/src/pmdas/txmon/txmon.h
new file mode 100644
index 0000000..d7a74e8
--- /dev/null
+++ b/src/pmdas/txmon/txmon.h
@@ -0,0 +1,53 @@
+/*
+ * 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
+ */
+
+/*
+ * the txmon shm segment
+ *
+ * control comes at the beginning, with index[] expanded to match the
+ * number of transaction types (control->n_tx)
+ *
+ * then follows one stat_t per transaction type, subject to the
+ * constraint that each stat_t is hardware cache aligned to avoid
+ * anti-social bus traffic
+ */
+
+typedef struct {
+ int level; /* controls stats collection levels */
+ int n_tx; /* # of tx types */
+ int index[1]; /* will be expanded when allocated */
+} control_t;
+
+static control_t *control;
+
+#define MAXNAMESIZE 20
+
+typedef struct {
+
+ /* managed by txmon PMDA ... do not fiddle with these! */
+ char type[MAXNAMESIZE]; /* tx type name */
+ unsigned int reset_count; /* tx count @ last reset */
+
+ /* initialized and then read by txmon PMDA, updated by txrecord */
+ unsigned int count; /* tx count since epoch */
+ float max_time; /* maximum elapsed time */
+ double sum_time; /* aggregate elapsed time */
+} stat_t;
+
+/* arbitrary shm key */
+#define KEY (key_t)0xdeadbeef
diff --git a/src/pmdas/txmon/txrecord.c b/src/pmdas/txmon/txrecord.c
new file mode 100644
index 0000000..0289a9d
--- /dev/null
+++ b/src/pmdas/txmon/txrecord.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 1995-2000 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 <pcp/pmapi.h>
+#include <pcp/impl.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include "txmon.h"
+
+/*
+ * Update the shm segment the is used to export metrics via the txmon PMDA
+ */
+int
+main(int argc, char **argv)
+{
+ int shmid;
+ int n;
+ char *p;
+ stat_t *sp = NULL; /* initialize to pander to gcc */
+
+ if (argc == 1 || (argc == 2 && strcmp(argv[1], "-?") == 0)) {
+ fprintf(stderr, "Usage: txrecord tx_type servtime [tx_type servtime ...]\n"
+ " txrecord -l\n");
+ exit(1);
+ }
+
+ /*
+ * attach to the txmon PMDA shm segment ...
+ */
+ if ((shmid = shmget(KEY, 0, 0)) < 0) {
+ fprintf(stderr, "Cannot attach to shm segment, shmid: %s\n", osstrerror());
+ fprintf(stderr, "Is the txmon PMDA configured and running?\n");
+ exit(1);
+ }
+ if ((control = (control_t *)shmat(shmid, NULL, 0)) == (control_t *)-1) {
+ fprintf(stderr, "Cannot attach to shm segment, shmat: %s\n", osstrerror());
+ fprintf(stderr, "Is the txmon PMDA configured and running?\n");
+ exit(1);
+ }
+
+ if (control->level == 0) {
+ fprintf(stderr, "Stats collection disabled\n");
+ exit(1);
+ }
+ else if (control->level == 1)
+ fprintf(stderr, "Warning: stats time collection disabled\n");
+
+ if (argc == 2 && strcmp(argv[1], "-l") == 0) {
+ printf("txmon shared memory segment summary\n");
+ printf(" tx reset total maximum\n");
+ printf("index offset count count time time name\n");
+ for (n = 0; n < control->n_tx; n++) {
+ sp = (stat_t *)((__psint_t)control + control->index[n]);
+ printf("%5d %6d %6d %6d %9.3f %7.3f %s\n",
+ n, control->index[n], sp->count, sp->reset_count,
+ (float)sp->sum_time, sp->max_time, sp->type);
+ }
+ exit(0);
+ }
+
+ while (argc > 1) {
+
+ for (n = 0; n < control->n_tx; n++) {
+ sp = (stat_t *)((__psint_t)control + control->index[n]);
+ if (strcmp(argv[1], sp->type) == 0)
+ break;
+ }
+ argc--;
+ argv++;
+ if (argc == 1) {
+ fprintf(stderr, "Missing time for tx type \"%s\"?\n", argv[0]);
+ exit(1);
+ }
+
+ if (n == control->n_tx)
+ fprintf(stderr, "Unknown tx type \"%s\" ... skipped\n", argv[0]);
+
+ else {
+ double e;
+ e = strtod(argv[1], &p);
+ if (*p != '\0')
+ fprintf(stderr, "Time value (%s) for tx type \"%s\" is bogus ... skipped\n", argv[1], argv[0]);
+ else {
+ sp->count++;
+ if (control->level == 2) {
+ sp->sum_time += (float)e;
+ if ((float)e > sp->max_time)
+ sp->max_time = e;
+ }
+ }
+ }
+ argc--;
+ argv++;
+ }
+
+ exit(0);
+}