diff options
Diffstat (limited to 'src/pmdas/txmon')
-rw-r--r-- | src/pmdas/txmon/GNUmakefile | 68 | ||||
-rw-r--r-- | src/pmdas/txmon/GNUmakefile.install | 57 | ||||
-rwxr-xr-x | src/pmdas/txmon/Install | 56 | ||||
-rw-r--r-- | src/pmdas/txmon/README | 77 | ||||
-rw-r--r-- | src/pmdas/txmon/Remove | 38 | ||||
-rwxr-xr-x | src/pmdas/txmon/genload | 120 | ||||
-rw-r--r-- | src/pmdas/txmon/help | 62 | ||||
-rw-r--r-- | src/pmdas/txmon/pmns | 32 | ||||
-rw-r--r-- | src/pmdas/txmon/root | 10 | ||||
-rw-r--r-- | src/pmdas/txmon/txmon.c | 383 | ||||
-rw-r--r-- | src/pmdas/txmon/txmon.h | 53 | ||||
-rw-r--r-- | src/pmdas/txmon/txrecord.c | 108 |
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); +} |