summaryrefslogtreecommitdiff
path: root/src/genpmda
diff options
context:
space:
mode:
Diffstat (limited to 'src/genpmda')
-rw-r--r--src/genpmda/GNUmakefile34
-rwxr-xr-xsrc/genpmda/genpmda1026
2 files changed, 1060 insertions, 0 deletions
diff --git a/src/genpmda/GNUmakefile b/src/genpmda/GNUmakefile
new file mode 100644
index 0000000..7526a7c
--- /dev/null
+++ b/src/genpmda/GNUmakefile
@@ -0,0 +1,34 @@
+#!gmake
+#
+# Copyright (c) 2005 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
+#
+TOPDIR = ../..
+include $(TOPDIR)/src/include/builddefs
+
+TARGETS = genpmda
+LSRCFILES = genpmda
+
+default: $(TARGETS)
+
+install: default
+ $(INSTALL) -m 755 genpmda $(PCP_BIN_DIR)/genpmda
+
+default_pcp: default
+
+install_pcp: install
+
+include $(BUILDRULES)
diff --git a/src/genpmda/genpmda b/src/genpmda/genpmda
new file mode 100755
index 0000000..4650315
--- /dev/null
+++ b/src/genpmda/genpmda
@@ -0,0 +1,1026 @@
+#! /bin/sh
+#
+# Copyright (c) 2005 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.
+#
+
+prog=`basename $0`
+
+usage()
+{
+ cat <<EOFEOF
+Usage: $prog [-d] [-s stdpmid] [-D domain] [-t topdir] [-n pmns] [-o dir] [-v] -i IAM -c config
+Required options:
+ -c config required: input config file, see example below
+ -i IAM required: pmda name "IAM", must appear in stdpmid
+ or -D domain number may be given.
+
+Other options:
+ -D domain domain number to use (if -s is not given)
+ -d generate an Install script for a daemon PMDA (default is DSO)
+ -t topdir use "topdir" in generated GNUmakefile (default "../../..")
+ -n pmns use "pmns" as root of pmns (default matches -i flag)
+ -s stdpmid path to stdpmid (default "../../pmns/stdpmid")
+ -o dir directory for generated source (default "./generated")
+ -v verbose
+
+Example config file (for the required -c option):
+Notes:
+ EXAMPLE must appear in src/pmns/stdpmid
+ Generate the "example" pmda: genpmda -D 99 -v -i EXAMPLE -c example.conf
+
+example {
+ metric
+}
+
+example.metric {
+ ## metric string
+ ## pmid EXAMPLE:SOME_CLUSTER_NAME:0
+ ## indom PM_INDOM_NULL
+ ## type PM_TYPE_STRING
+ ## units PMDA_PMUNITS(0,0,0,0,0,0)
+ ## semantics PM_SEM_DISCRETE
+ ## briefhelptext one line help text for example.metric.string
+ ## helptext long help text for example.metric.string
+ ## helptext This is the second line of the long help text
+ ## helptext and this is the third line.
+ ## fetch function example_string_fetch_callback
+ ## code /* optional code for this metric */
+ ## code atom->cp = "hello world";
+ ## endmetric
+}
+EOFEOF
+
+ exit 1
+}
+
+dflag=false
+Dflag=""
+iflag=""
+sflag="../../pmns/stdpmid"
+tflag="../../.."
+oflag="generated"
+nflag=""
+verbose=false
+
+while getopts "c:vdD:s:t:i:n:o:" c
+do
+ case $c
+ in
+
+ D) Dflag="$OPTARG"
+ ;;
+
+ d) dflag=true
+ ;;
+
+ c) cflag="$OPTARG"
+ ;;
+
+ i) iflag="$OPTARG"
+ ;;
+
+ s) sflag="$OPTARG"
+ ;;
+
+ t) tflag="$OPTARG"
+ ;;
+
+ n) nflag="$OPTARG"
+ ;;
+
+ o) oflag="$OPTARG"
+ ;;
+
+ v) verbose=true
+ ;;
+
+ \?) usage
+ ;;
+ esac
+done
+
+[ -z "$iflag" ] && usage
+[ ! -f "$cflag" ] && echo "Error: config \"$cflag\" not found" && usage
+
+IAM=`echo $iflag | tr a-z A-Z`
+iam=`echo $IAM | tr A-Z a-z`
+[ -z "$nflag" ] && nflag="$iam"
+config="$cflag"
+
+for stdpmid in $sflag $tflag/src/pmns/stdpmid ../pmns/stdpmid ../../pmns/stdpmid
+do
+ [ -f "$stdpmid" ] && break
+done
+$verbose && [ -f "$stdpmid" ] && echo Found stdpmid in \"$stdpmid\"
+[ ! -f "$stdpmid" ] && echo Error: could not find \"stdpmid\" && usage
+domain=`awk '/^#define[ \t]*'$IAM'/ {print $3}' $stdpmid`
+if [ -z "$Dflag" ]
+then
+ [ -z "$domain" ] && echo "Error: domain for \"$IAM\" not found in ../../pmns/stdpmid, please use -D" && usage
+else
+ domain="$Dflag"
+fi
+
+[ ! -d $oflag ] && mkdir $oflag && $verbose && echo "created output directory \"$oflag\""
+
+#
+# Generate domain.h
+#
+cat <<EOFEOF >$oflag/domain.h
+/*
+ * Generated code, do not edit!
+ */
+#define $IAM $domain
+EOFEOF
+$verbose && echo Wrote $oflag/domain.h
+
+#
+# Generate (the beginning of) pmda.c
+#
+cat <<EOFEOF >$oflag/pmda.c
+/*
+ * Generated code, do not edit!
+ */
+#include <stdio.h>
+#include <limits.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "pmapi.h"
+#include "impl.h"
+#include "pmda.h"
+#include "domain.h"
+#include "metrictab.h"
+#include "clusters.h"
+
+static int _isDSO = 1; /* =0 I am a daemon */
+
+EOFEOF
+$verbose && echo Wrote $oflag/pmda.c
+
+gnumakefile=GNUmakefile.new
+gnumakefile_g=GNUmakefile.generic.new
+install_g=install-generic.new
+
+#
+# Generate Install, Remove and Makefile.install
+#
+cat <<EOFEOF >$oflag/Install
+#! /bin/sh
+. \$PCP_DIR/etc/pcp.env
+. \$PCP_SHARE_DIR/lib/pmdaproc.sh
+
+iam=$iam
+pmda_interface=3
+EOFEOF
+
+if $dflag
+then
+ cat <<EOFEOF >>$oflag/Install
+# controls for daemon PMDA installation procedures
+#
+daemon_opt=true
+dso_opt=false
+pipe_opt=true
+socket_opt=false
+
+EOFEOF
+else
+ cat <<EOFEOF >>$oflag/Install
+# controls for DSO installation procedures
+#
+daemon_opt=false
+dso_opt=true
+pipe_opt=false
+socket_opt=false
+
+EOFEOF
+fi
+
+cat <<EOFEOF >>$oflag/Install
+#
+# override "choose mode"
+__choose_mode()
+{
+ do_pmda=true
+}
+
+#
+# override "choose IPC method"
+__choose_ipc()
+{
+ ipc_type=pipe
+ type="pipe binary \$PCP_PMDAS_DIR/\$iam/pmda\$iam"
+}
+
+# Do it
+#
+pmdaSetup
+cat domain.h clusters.h pmns | \$PCP_BINADM_DIR/pmgcc -DPCP_PMNS >\$tmp/pmns
+pmns_source=\$tmp/pmns
+pmns_name=\$iam
+
+pmdaInstall
+
+exit 0
+EOFEOF
+$verbose && echo Wrote $oflag/Install
+
+cat <<EOFEOF >$oflag/Remove
+#! /bin/sh
+. \$PCP_DIR/etc/pcp.env
+. \$PCP_SHARE_DIR/lib/pmdaproc.sh
+
+iam=$iam
+pmdaSetup
+pmdaRemove
+
+exit 0
+EOFEOF
+$verbose && echo Wrote $oflag/Remove
+
+cat <<"EOFEOF" >$oflag/Makefile.install
+SHELL = sh
+TARGETS =
+LDIRT = *.log *.pag *.dir
+
+default: $(TARGETS)
+
+install: default
+
+clobber:
+ rm -f $(LDIRT) $(TARGETS)
+EOFEOF
+$verbose && echo Wrote $oflag/Makefile.install
+
+#
+# Generate metrictab.[ch]
+#
+awk '
+BEGIN {
+ mt_h="'$oflag'/metrictab.h"
+ mt_c="'$oflag'/metrictab.c"
+ pmda_c="'$oflag'/pmda.c"
+ clusters_h="'$oflag'/clusters.h"
+ pmns="'$oflag'/pmns"
+ cfiles="CFILES"
+ init_c="init.c.new"
+
+ printf "/* Generated code, do not edit! */\n\n" >mt_c
+ printf "/* Generated code, do not edit! */\n\n" >mt_h
+ printf "#include \"pmapi.h\"\n" >>mt_c
+ printf "#include \"impl.h\"\n" >>mt_c
+ printf "#include \"pmda.h\"\n" >>mt_c
+ printf "#include \"metrictab.h\"\n\n" >>mt_c
+ printf "#include \"clusters.h\"\n\n" >>mt_c
+ printf "/*\n * Metric Table\n */\npmdaMetric metrictab[] = {\n" >>mt_c
+
+ printf "init.c" >cfiles
+ printf "/*\n" >init_c
+ printf " * local initialization for the %s PMDA\n", "'$IAM'" >>init_c
+ printf " * ADD CODE HERE\n" >>init_c
+ printf " */\n" >>init_c
+
+ printf "#include <stdio.h>\n" >>init_c
+ printf "#include <limits.h>\n" >>init_c
+ printf "#include <ctype.h>\n" >>init_c
+ printf "#include <sys/types.h>\n" >>init_c
+ printf "#include <sys/stat.h>\n" >>init_c
+ printf "#include <fcntl.h>\n" >>init_c
+ printf "#include \"pmapi.h\"\n" >>init_c
+ printf "#include \"impl.h\"\n" >>init_c
+ printf "#include \"pmda.h\"\n" >>init_c
+ printf "#include \"'$oflag'/domain.h\"\n" >>init_c
+ printf "#include \"'$oflag'/metrictab.h\"\n" >>init_c
+ printf "#include \"'$oflag'/clusters.h\"\n" >>init_c
+ printf "\n" >>init_c
+ printf "void\n%s_local_init(pmdaInterface *dispatch)\n", "'$iam'" >>init_c
+ printf "{\n" >>init_c
+ printf "\t/* add code for local initialization here, if required */\n" >>init_c
+ printf "}\n" >>init_c
+}
+
+/.*{$/ {
+ nonleaf = $1
+}
+
+$1 == "##" && $2 == "metric" {
+ metric = nonleaf"."$3
+ metriclist[metric] = metric
+ leafmetric[metric] = $3
+ nmetrics++
+}
+
+$1 == "##" && $2 == "pmid" {
+ pmid[metric] = $3
+ n = split(pmid[metric], id, ":")
+ current_cluster = id[2]
+ cluster[metric] = current_cluster
+ item[metric] = id[3]
+ s = metric
+ gsub("\\.", "_", s)
+ m = "METRIC_"s
+ if (seen_metric_macro[m]) {
+ printf "FATAL ERROR: cluster_metric \"%s\" is not unique,\n", m
+ printf "Conflicts with metric \"%s\"\n", seen_metric_macro[m]
+ exit 1
+ }
+ seen_metric_macro[m] = metric
+ metric_macro[metric] = m
+}
+
+$1 == "##" && $2 == "code" {
+ thiscode=$3
+ for (i=4; i <= NF; i++)
+ thiscode = thiscode " " $i
+ if (!code[metric])
+ code[metric] = "\t\t"thiscode;
+ else
+ code[metric] = code[metric]"\n\t\t"thiscode
+}
+
+$1 == "##" && $2 == "type" {
+ type[metric] = $3
+}
+
+$1 == "##" && $2 == "units" {
+ units[metric] = $3
+}
+
+$1 == "##" && $2 == "semantics" {
+ semantics[metric] = $3
+}
+
+$1 == "##" && $2 == "indom" {
+ indom[metric] = $3
+ if (indom[metric] != "PM_INDOM_NULL" && !seen_indom[indom[metric]]) {
+ printf "#define %s %d\n", indom[metric], nindoms >>mt_h
+ seen_indom[indom[metric]]++
+ nindoms++
+ indoms[nindoms] = indom[metric]
+ indom_cluster[$3] = current_cluster
+ }
+}
+
+$1 == "##" && $2 == "endmetric" {
+ printf "\t/* %s */\n", metric >>mt_c
+ printf "\t{ (void *)fetch_%s,\n", cluster[metric] >>mt_c
+ printf "\t{PMDA_PMID(%s,%s),\n", cluster[metric], metric_macro[metric] >>mt_c
+ printf "\t %s, %s, %s, %s }, },\n\n",
+ type[metric], indom[metric], semantics[metric], units[metric] >>mt_c
+}
+
+END {
+ printf "};\n" >>mt_c
+
+ if (nindoms > 0) {
+ printf "\npmdaIndom indomtab[] = {\n" >>mt_c
+ for (i=1; i <= nindoms; i++)
+ printf " { %s, 0, NULL },\n", indoms[i] >>mt_c
+ printf "};\n" >>mt_c
+ }
+
+ printf "\n#define NMETRICS %d\n", nmetrics >>mt_h
+ printf "extern pmdaMetric metrictab[NMETRICS];\n" >>mt_h
+
+ printf "\n#define NINDOMS %d\n", nindoms >>mt_h
+ if (nindoms > 0) {
+ printf "extern pmdaIndom indomtab[NINDOMS];\n" >>mt_h
+ }
+
+ #
+ # Generate clusters.h and first part of pmns
+ #
+ printf "/* Generated code, do not edit! */\n\n" >pmns
+ printf "/* Generated code, do not edit! */\n\n" >clusters_h
+ printf "#ifndef _CLUSTER_H\n" >>clusters_h
+ printf "#define _CLUSTER_H\n" >>clusters_h
+ clustercnt = 0
+ for (m in cluster) {
+ c = cluster[m]
+ if (seencluster[c])
+ continue;
+ seencluster[c] = 1
+ printf "\n/*\n" >>clusters_h
+ printf " * Metrics in the \"%s\" cluster\n", c >>clusters_h
+ printf " */\n" >>clusters_h
+ printf "#define %s\t\t\t%d\n", c, clustercnt >>clusters_h
+ for (metric in metriclist) {
+ if (cluster[metric] == c) {
+ printf "#define %s\t%s /* %s */\n", metric_macro[metric], item[metric], metric >>clusters_h
+ }
+ }
+
+ clustercnt++
+ }
+ printf "\n\n#ifndef PCP_PMNS\n" >>clusters_h
+ printf "#define NCLUSTERS\t\t\t%d\n\n", clustercnt >>clusters_h
+
+ #
+ # Generate the refresh method in pmda.c
+ #
+ for (m in cluster) {
+ c = cluster[m]
+ seencluster[c] = 0;
+ }
+ printf "\nstatic void\n%s_refresh(int *need_refresh)\n{\n", "'$iam'" >>pmda_c
+ for (m in cluster) {
+ c = cluster[m]
+ if (seencluster[c])
+ continue;
+ seencluster[c] = 1
+ printf "extern void refresh_%s(void);\n", c >>mt_h
+ printf " if (need_refresh[%s])\n\trefresh_%s();\n", c, c >>pmda_c
+ }
+ printf "}\n\n" >>pmda_c
+
+ #
+ # Generate the instance method in pmda.c
+ #
+ for (m in cluster) {
+ c = cluster[m]
+ seencluster[c] = 0;
+ }
+ printf "static int\n" >>pmda_c
+ printf "%s_instance(pmInDom indom, int inst, char *name, __pmInResult **result, pmdaExt *pmda)\n", "'$iam'" >>pmda_c
+ printf "{\n" >>pmda_c
+ printf " __pmInDom_int *indomp = (__pmInDom_int *)&indom;\n" >>pmda_c
+ printf " int need_refresh[NCLUSTERS];\n" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " memset(need_refresh, 1, sizeof(need_refresh));\n" >>pmda_c
+ printf " /* TODO: only refresh some clusters */\n" >>pmda_c
+ printf " %s_refresh(need_refresh);\n", "'$iam'" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " return pmdaInstance(indom, inst, name, result, pmda);\n" >>pmda_c
+ printf "}\n\n" >>pmda_c
+
+ #
+ # Generate the fetch method in pmda.c
+ #
+ printf "int\n" >>pmda_c
+ printf "%s_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda)\n", "'$iam'" >>pmda_c
+ printf "{\n" >>pmda_c
+ printf " int i;\n" >>pmda_c
+ printf " int need_refresh[NCLUSTERS];\n" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " memset(need_refresh, 0, sizeof(need_refresh));\n" >>pmda_c
+ printf " for (i=0; i < numpmid; i++) {\n" >>pmda_c
+ printf " __pmID_int *idp = (__pmID_int *)&(pmidlist[i]);\n" >>pmda_c
+ printf " if (idp->cluster >= 0 && idp->cluster < NCLUSTERS) {\n" >>pmda_c
+ printf " need_refresh[idp->cluster]++;\n" >>pmda_c
+ printf " }\n" >>pmda_c
+ printf " }\n" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " %s_refresh(need_refresh);\n", "'$iam'" >>pmda_c
+ printf " return pmdaFetch(numpmid, pmidlist, resp, pmda);\n" >>pmda_c
+ printf "}\n\n" >>pmda_c
+
+ #
+ # Generate the generic fetch callback in pmda.c
+ #
+ printf "static int\n" >>pmda_c
+ printf "%s_fetchCallBack(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom)\n", "'$iam'" >>pmda_c
+ printf "{\n" >>pmda_c
+
+ printf "\tint (*fetchfunction)(pmdaMetric *, unsigned int, pmAtomValue *) =\n">>pmda_c
+ printf "\t\t(int (*)(pmdaMetric *, unsigned int, pmAtomValue *)) mdesc->m_user;\n">>pmda_c
+ printf "\treturn (*fetchfunction)(mdesc, inst, atom);\n" >>pmda_c
+ printf "}\n\n", pmda_c >>pmda_c
+
+ #
+ # Generate the init method in pmda.c
+ #
+ printf "void\n" >>pmda_c
+ printf "%s_init(pmdaInterface *dp)\n", "'$iam'" >>pmda_c
+ printf "{\n" >>pmda_c
+ printf " int\tneed_refresh[NCLUSTERS];\n" >>pmda_c
+ printf " extern void\t%s_local_init(pmdaInterface *);\n", "'$iam'" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " if (_isDSO) {\n" >>pmda_c
+ printf " char helppath[MAXPATHLEN];\n" >>pmda_c
+ printf " snprintf(helppath, sizeof(helppath), \"%%s/pmdas/'$iam'/help\",\n" >>pmda_c
+ printf " pmGetConfig(\"PCP_VAR_DIR\"));\n" >>pmda_c
+ printf " pmdaDSO(dp, PMDA_INTERFACE_4, \"%s DSO\", helppath);\n", "'$iam'" >>pmda_c
+ printf " }\n" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " if (dp->status != 0)\n" >>pmda_c
+ printf " return;\n" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " dp->version.two.instance = %s_instance;\n", "'$iam'" >>pmda_c
+ printf " dp->version.two.fetch = %s_fetch;\n", "'$iam'" >>pmda_c
+ printf " pmdaSetFetchCallBack(dp, %s_fetchCallBack);\n", "'$iam'" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " /* local initialization, see init.c */\n" >>pmda_c
+ printf " %s_local_init(dp);\n", "'$iam'" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " /* initially refresh all clusters */\n" >>pmda_c
+ printf " memset(need_refresh, 1, sizeof(need_refresh));\n" >>pmda_c
+ printf " %s_refresh(need_refresh);\n", "'$iam'" >>pmda_c
+ printf "\n" >>pmda_c
+ if (nindoms > 0) {
+ printf " pmdaInit(dp, indomtab, sizeof(indomtab)/sizeof(indomtab[0]), metrictab,\n" >>pmda_c
+ printf " sizeof(metrictab)/sizeof(metrictab[0]));\n" >>pmda_c
+ }
+ else {
+ printf " pmdaInit(dp, NULL, 0, metrictab,\n" >>pmda_c
+ printf " sizeof(metrictab)/sizeof(metrictab[0]));\n" >>pmda_c
+ }
+ printf "}\n" >>pmda_c
+
+ #
+ # Generate usage() and main() for the daemon PMDA
+ #
+ printf "\nstatic void\n" >>pmda_c
+ printf "usage(void)\n" >>pmda_c
+ printf "{\n" >>pmda_c
+ printf " fprintf(stderr, \"Usage: %%s [options]\\n\\n\", pmProgname);\n" >>pmda_c
+ printf " fputs(\"Options:\\n\"\n" >>pmda_c
+ printf " \" -d domain use domain (numeric) for metrics domain of PMDA\\n\"\n" >>pmda_c
+ printf " \" -l logfile write log into logfile rather than using default log name\\n\",\n" >>pmda_c
+ printf " stderr);\n" >>pmda_c
+ printf " exit(1);\n" >>pmda_c
+ printf "}\n" >>pmda_c
+ printf "\n" >>pmda_c
+ printf "int\n" >>pmda_c
+ printf "main(int argc, char **argv)\n" >>pmda_c
+ printf "{\n" >>pmda_c
+ printf " int err = 0;\n" >>pmda_c
+ printf " int c = 0;\n" >>pmda_c
+ printf " pmdaInterface dispatch;\n" >>pmda_c
+ printf " char helppath[MAXPATHLEN];\n" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " __pmSetProgname(argv[0]);\n" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " _isDSO = 0;\n" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " snprintf(helppath, sizeof(helppath), \"%%s/pmdas/'$iam'/help\", pmGetConfig(\"PCP_VAR_DIR\"));\n" >>pmda_c
+ printf " pmdaDaemon(&dispatch, PMDA_INTERFACE_4, pmProgname, '$IAM', \"'$iam'.log\", helppath);\n" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " if ((c = pmdaGetOpt(argc, argv, \"D:d:l:?\", &dispatch, &err)) != EOF)\n" >>pmda_c
+ printf " err++;\n" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " if (err)\n" >>pmda_c
+ printf " usage();\n" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " pmdaOpenLog(&dispatch);\n" >>pmda_c
+ printf " '$iam'_init(&dispatch);\n" >>pmda_c
+ printf " pmdaConnect(&dispatch);\n" >>pmda_c
+ printf " pmdaMain(&dispatch);\n" >>pmda_c
+ printf "\n" >>pmda_c
+ printf " exit(0);\n" >>pmda_c
+ printf "}\n" >>pmda_c
+
+ #
+ # Generate the refresh and fetch methods for each cluster
+ #
+ for (m in cluster) {
+ c = cluster[m]
+ seencluster[c] = 0;
+ }
+ for (m in cluster) {
+ c = cluster[m]
+ if (seencluster[c])
+ continue;
+ seencluster[c] = 1
+
+ fetch_c = c".c.new"
+ printf " %s.c", c >>cfiles
+
+ printf "/*\n" >>fetch_c
+ printf " * Originally generated from \"%s\" using genpmda(1).\n","'$config'" >>fetch_c
+ printf " *\n" >>fetch_c
+ printf " * Refresh and fetch methods for the \"%s\" cluster.\n", c >>fetch_c
+ printf " */\n" >>fetch_c
+ printf "#include <stdio.h>\n" >>fetch_c
+ printf "#include <limits.h>\n" >>fetch_c
+ printf "#include <ctype.h>\n" >>fetch_c
+ printf "#include <sys/types.h>\n" >>fetch_c
+ printf "#include <sys/stat.h>\n" >>fetch_c
+ printf "#include <fcntl.h>\n" >>fetch_c
+ printf "#include \"pmapi.h\"\n" >>fetch_c
+ printf "#include \"impl.h\"\n" >>fetch_c
+ printf "#include \"pmda.h\"\n" >>fetch_c
+ printf "#include \"'$oflag'/domain.h\"\n" >>fetch_c
+ printf "#include \"'$oflag'/metrictab.h\"\n" >>fetch_c
+ printf "#include \"'$oflag'/clusters.h\"\n" >>fetch_c
+
+ printf "\nvoid\nrefresh_%s(void)\n", c >>fetch_c
+ printf "{\n" >>fetch_c
+
+ z = 0
+ if (nindoms > 0) {
+ for (i in indoms) {
+ this = indoms[i];
+ if (indom_cluster[this] == c) {
+ printf "\tpmInDom indom_%s = indomtab[%s].it_indom;\n", this, this >>fetch_c
+ z++
+ }
+ }
+ if (z > 0)
+ printf "\tstatic int first = 1;\n" >>fetch_c
+ }
+ printf "\n" >>fetch_c
+ if (z > 0) {
+ printf "\t/* initialize the instance domain cache(s) */\n" >>fetch_c
+ printf "\tif (first) {\n" >>fetch_c
+ for (i in indoms) {
+ this = indoms[i];
+ if (indom_cluster[this] == c) {
+ printf "\t\tpmdaCacheOp(indom_%s, PMDA_CACHE_LOAD);\n", this >>fetch_c
+ }
+ }
+ printf "\t\tfirst = 0;\n" >>fetch_c
+ printf "\t}\n" >>fetch_c
+ }
+
+ printf "\n" >>fetch_c
+ if (z > 0) {
+ for (i in indoms) {
+ this = indoms[i];
+ if (indom_cluster[this] == c) {
+ printf "\t/* inactivate all instances in the %s instance domain */\n", this >>fetch_c
+ printf "\tpmdaCacheOp(indom_%s, PMDA_CACHE_INACTIVE);\n", this >>fetch_c
+ printf "\n" >>fetch_c
+ printf "\t/*\n" >>fetch_c
+ printf "\t * Add code here to refresh the %s instance domain.\n", this >>fetch_c
+ printf "\t * Basically, walk your data and activate each instance, e.g.\n" >>fetch_c
+ printf "\t * inst = pmdaCacheStore(indom_%s, PMDA_CACHE_ADD, name, p);\n", this >>fetch_c
+ printf "\t * where \"name\" is a char buffer naming each instance\n" >>fetch_c
+ printf "\t * and \"p\" points to private anonymous data.\n" >>fetch_c
+ printf "\t */\n" >>fetch_c
+ printf "\t/* ADD CODE HERE */\n\n\n" >>fetch_c
+
+ printf "\n" >>fetch_c
+ printf "\t/*\n" >>fetch_c
+ printf "\t * Flush the cache for the indom_%s indom. This is\n", this >>fetch_c
+ printf "\t * only strictly needed if there are any _new_ instances.\n" >>fetch_c
+ printf "\t */\n", this >>fetch_c
+ printf "\tpmdaCacheOp(indom_%s, PMDA_CACHE_SAVE);\n", this >>fetch_c
+ }
+ }
+ }
+ else {
+ printf "\t/*\n" >>fetch_c
+ printf "\t * Add code here to refresh your data for this cluster\n" >>fetch_c
+ printf "\t * (no instance domains are defined for this cluster)\n" >>fetch_c
+ printf "\t */\n\n" >>fetch_c
+ printf "\t/* ADD CODE HERE */\n\n\n" >>fetch_c
+ }
+
+ printf "}\n" >>fetch_c
+
+ #
+ # Generate the skeletal fetch callback function for each cluster
+ # and the commented skeletal fetch code for each metric.
+ #
+ printf "extern int fetch_%s(pmdaMetric *, unsigned int, pmAtomValue *);\n", c >>clusters_h
+ printf "\nint\nfetch_%s(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom)\n", c >>fetch_c
+ printf "{\n" >>fetch_c
+ printf "\t__pmID_int\t*idp = (__pmID_int *)&(mdesc->m_desc.pmid);\n" >>fetch_c
+ printf "\tvoid\t\t*p = NULL;\n" >>fetch_c
+ printf "\tint\t\tsts = 1; /* return value, success is the default */\n" >>fetch_c
+
+ printf "\n\tif (inst != PM_INDOM_NULL) {\n" >>fetch_c
+ printf "\t\tif (pmdaCacheLookup(mdesc->m_desc.indom, inst, NULL, (void **)&p) != PMDA_CACHE_ACTIVE || !p)\n" >>fetch_c
+ printf "\t\t\treturn PM_ERR_INST;\n" >>fetch_c
+ printf "\t}\n\n" >>fetch_c
+ printf "\t/*\n" >>fetch_c
+ printf "\t * p now points to the private data for this instance that was\n" >>fetch_c
+ printf "\t * previously stored in refresh_%s(), or will be NULL\n", c >>fetch_c
+ printf "\t * if this is a singular instance domain.\n" >>fetch_c
+ printf "\t */\n" >>fetch_c
+
+ printf "\n\tswitch(idp->item) {\n" >>fetch_c
+ for (metric in metriclist) {
+ if (cluster[metric] != c)
+ continue
+ printf "\tcase %s:\n", metric_macro[metric] >>fetch_c
+ printf "\t\t/*\n" >>fetch_c
+ printf "\t\t * Fetch code for metric \"" metric "\"\n" >>fetch_c
+ printf "\t\t * PMID : " pmid[metric] "\n" >>fetch_c
+ printf "\t\t * Type : " type[metric] "\n" >>fetch_c
+ printf "\t\t * Indom : " indom[metric] "\n" >>fetch_c
+ printf "\t\t * Units : " units[metric] "\n" >>fetch_c
+ printf "\t\t * Semantics: " semantics[metric] "\n" >>fetch_c
+ printf "\t\t */\n" >>fetch_c
+ if (code[metric])
+ printf "%s\n", code[metric] >>fetch_c
+ else if (type[metric] == "PM_TYPE_32")
+ printf "\t\tatom->l = 0; /* ADD CODE HERE */\n" >>fetch_c
+ else if (type[metric] == "PM_TYPE_U32")
+ printf "\t\tatom->ul = 0; /* ADD CODE HERE */\n" >>fetch_c
+ else if (type[metric] == "PM_TYPE_64")
+ printf "\t\tatom->ll = 0; /* ADD CODE HERE */\n" >>fetch_c
+ else if (type[metric] == "PM_TYPE_U64")
+ printf "\t\tatom->ull = 0; /* ADD CODE HERE */\n" >>fetch_c
+ else if (type[metric] == "PM_TYPE_FLOAT")
+ printf "\t\tatom->f = 0; /* ADD CODE HERE */\n" >>fetch_c
+ else if (type[metric] == "PM_TYPE_DOUBLE")
+ printf "\t\tatom->d = 0; /* ADD CODE HERE */\n" >>fetch_c
+ else if (type[metric] == "PM_TYPE_STRING")
+ printf "\t\tatom->cp = \"string value\"; /* ADD CODE HERE */\n" >>fetch_c
+ else if (type[metric] == "PM_TYPE_AGGREGATE")
+ printf "\t\tatom->vp = NULL; /* ADD CODE HERE */\n" >>fetch_c
+ else if (type[metric] == "PM_TYPE_AGGREGATE_STATIC")
+ printf "\t\tatom->vp = NULL; /* ADD CODE HERE */\n" >>fetch_c
+ else if (type[metric] == "PM_TYPE_EVENT")
+ printf "\t\tatom->vp = NULL; /* ADD CODE HERE */\n" >>fetch_c
+
+ printf "\t\tbreak;\n\n" >>fetch_c
+ }
+ printf "\tdefault:\n" >>fetch_c
+ printf "\t\tsts = PM_ERR_PMID;\n" >>fetch_c
+ printf "\t\tbreak;\n" >>fetch_c
+ printf "\t}\n", c >>fetch_c
+ printf "\n", c >>fetch_c
+ printf "\t/*\n", c >>fetch_c
+ printf "\t * Return value:\n", c >>fetch_c
+ printf "\t * < 0 error\n", c >>fetch_c
+ printf "\t * = 0 no values available\n", c >>fetch_c
+ printf "\t * > 0 success\n", c >>fetch_c
+ printf "\t */\n", c >>fetch_c
+ printf "\treturn sts;\n" >>fetch_c
+ printf "}\n" >>fetch_c
+ }
+
+ printf "#endif /* PCP_PMNS */\n" >>clusters_h
+ printf "\n#endif /* _CLUSTER_H */\n" >>clusters_h
+ printf "\n" >>cfiles
+
+}' $config
+$verbose && echo Wrote $oflag/clusters.h
+$verbose && echo Wrote $oflag/metrictab.h
+$verbose && echo Wrote $oflag/metrictab.c
+
+#
+# Generate remainder of pmns
+#
+awk '
+$1 == "##" {
+ if ($2 == "metric")
+ metric = $3
+ else if ($2 == "pmid")
+ printf "\t%s\t\t%s\n", metric, $3
+ next
+}
+{
+ print
+}' <$config >>$oflag/pmns
+$verbose && echo Wrote $oflag/pmns
+
+#
+# Generate dummy root pmns
+#
+cat <<EOFEOF >$oflag/root
+/*
+ * Generated code, do not edit!
+ */
+#define PCP_PMNS
+#include "domain.h"
+#include "clusters.h"
+
+root { $nflag }
+
+#include "pmns"
+EOFEOF
+$verbose && echo Wrote $oflag/root
+
+#
+# Generate help text
+#
+awk '
+/.*{$/ {
+ nonleaf = $1
+}
+$1 == "##" {
+ if ($2 == "metric")
+ metric = $3
+ else if ($2 == "briefhelptext") {
+ printf "@ %s.%s", nonleaf, metric
+ for (i=3; i <= NF; i++)
+ printf " %s", $i
+ printf "\n"
+ }
+ else if ($2 == "helptext") {
+ for (i=3; i <= NF; i++)
+ if (i == 3)
+ printf "%s", $i
+ else
+ printf " %s", $i
+ printf "\n"
+ }
+}' <$config >$oflag/help
+$verbose && echo Wrote $oflag/help
+
+#
+# Generate generic install script
+#
+cat << EOFEOF >$install_g
+#! /bin/sh
+
+usage()
+{
+ echo "Usage: \$0 [-m mode] [-d dir] [-f srcfile -t destfile]"
+ echo "Required options: both -f and -t, or just -d"
+ exit 1
+}
+
+mdflag="755"
+mflag="644"
+
+while getopts "m:d:f:t:v" c
+do
+ case \$c
+ in
+
+ m) mflag="\$OPTARG"
+ mdflag=\$mflag
+ ;;
+
+ d) dflag="\$OPTARG"
+ ;;
+
+ f) fflag="\$OPTARG"
+ ;;
+
+ t) tflag="\$OPTARG"
+ ;;
+
+ \?) usage
+ ;;
+ esac
+done
+
+[ -z "\$fflag" -a -z "\$dflag" ] && usage
+[ -z "\$fflag" -a ! -z "\$tflag" ] && usage
+[ ! -z "\$fflag" -a -z "\$tflag" ] && usage
+[ ! -z "\$dflag" ] && mkdir \$dflag && chmod \$mdflag \$dflag
+[ ! -z "\$fflag" ] && cp \$fflag \$tflag && chmod \$mflag \$tflag
+
+exit 0
+EOFEOF
+chmod 755 $install_g
+
+#
+# Generate GNUmakefile
+#
+cat << EOFEOF >$gnumakefile
+TOPDIR = $tflag
+include \$(TOPDIR)/src/include/builddefs
+
+IAM = $iam
+CMDTARGET= pmda\$(IAM)
+LIBTARGET= pmda_\$(IAM).so
+TARGETS = \$(CMDTARGET) \$(LIBTARGET)
+
+CFILES = `cat CFILES`
+HFILES =
+
+GCFILES = $oflag/metrictab.c $oflag/pmda.c
+GHFILES = $oflag/domain.h $oflag/metrictab.h
+GSRCFILES = $oflag/help $oflag/root $oflag/pmns \
+ $oflag/Makefile.install $oflag/Install \
+ $oflag/Remove $oflag/clusters.h
+
+OBJECTS += \$(GCFILES:.c=.o)
+LCFLAGS =
+LLDLIBS = \$(PCP_PMDALIB)
+
+PMDADIR = \$(PCP_PMDAS_DIR)/\$(IAM)
+LDIRT = generated *.o \$(TARGETS) *.log *.dir *.pag pcp
+
+default: pcp help.pag help.dir \$(TARGETS)
+
+include \$(BUILDRULES)
+
+install: default
+ \$(INSTALL) -m 755 -d \$(PCP_VAR_DIR)
+ \$(INSTALL) -m 755 -d \$(PCP_VAR_DIR)/pmdas
+ \$(INSTALL) -m 755 -d \$(PMDADIR)
+ \$(INSTALL) -m 755 \$(CMDTARGET) \$(PMDADIR)/\$(CMDTARGET)
+ \$(INSTALL) -m 755 \$(LIBTARGET) \$(PMDADIR)/\$(LIBTARGET)
+ \$(INSTALL) -m 755 $oflag/Install \$(PMDADIR)/Install
+ \$(INSTALL) -m 755 $oflag/Remove \$(PMDADIR)/Remove
+ \$(INSTALL) -m 644 $oflag/Makefile.install \$(PMDADIR)/Makefile
+ \$(INSTALL) -m 644 $oflag/pmns \$(PMDADIR)/pmns
+ \$(INSTALL) -m 644 $oflag/root \$(PMDADIR)/root
+ \$(INSTALL) -m 644 $oflag/domain.h \$(PMDADIR)/domain.h
+ \$(INSTALL) -m 644 $oflag/clusters.h \$(PMDADIR)/clusters.h
+ \$(INSTALL) -m 644 $oflag/help \$(PMDADIR)/help
+ \$(INSTALL) -m 644 help.pag \$(PMDADIR)/help.pag
+ \$(INSTALL) -m 644 help.dir \$(PMDADIR)/help.dir
+
+pcp:
+ ln -s \$(TOPDIR)/src/include pcp
+
+help.dir help.pag : $oflag/help
+ \$(RUN_IN_BUILD_ENV) \$(TOPDIR)/src/newhelp/newhelp -n $oflag/root -v 2 -o help < $oflag/help
+
+\$(GCFILES) \$(GHFILES) \$(GSRCFILES) : $config
+ \$(GENPMDA) -v -i $IAM -c $config
+
+default_pro: default
+
+install_pro: install
+EOFEOF
+
+#
+# Generate GNUmakefile.generic
+#
+cat << EOFEOF >$gnumakefile_g
+IAM = $iam
+CONFIG = $config
+DOMAIN = $domain
+
+include /etc/pcp.conf
+INSTALL ?= ./install-generic
+GENPMDA ?= /usr/bin/genpmda
+CMDTARGET= pmda\$(IAM)
+LIBTARGET= pmda_\$(IAM).so
+TARGETS = \$(CMDTARGET) \$(LIBTARGET)
+
+CFILES = `cat CFILES`
+
+GCFILES = $oflag/metrictab.c $oflag/pmda.c
+GHFILES = $oflag/domain.h $oflag/metrictab.h
+GSRCFILES = $oflag/help $oflag/root $oflag/pmns \
+ $oflag/Makefile.install $oflag/Install \
+ $oflag/Remove $oflag/clusters.h
+
+OBJECTS = \$(CFILES:.c=.o) \$(GCFILES:.c=.o)
+CFLAGS = -I/usr/include/pcp
+LLDLIBS = -lpcp_pmda -lpcp
+
+PMDADIR = \$(PCP_PMDAS_DIR)/\$(IAM)
+LDIRT = generated *.o \$(TARGETS) *.log *.dir *.pag *.o
+
+default: help.pag help.dir \$(TARGETS)
+
+install: default
+ \$(INSTALL) -m 755 -d \$(PCP_VAR_DIR)
+ \$(INSTALL) -m 755 -d \$(PCP_VAR_DIR)/pmdas
+ \$(INSTALL) -m 755 -d \$(PMDADIR)
+ \$(INSTALL) -m 755 -f \$(CMDTARGET) \$(PMDADIR)/\$(CMDTARGET)
+ \$(INSTALL) -m 755 -f \$(LIBTARGET) \$(PMDADIR)/\$(LIBTARGET)
+ \$(INSTALL) -m 755 -f $oflag/Install \$(PMDADIR)/Install
+ \$(INSTALL) -m 755 -f $oflag/Remove \$(PMDADIR)/Remove
+ \$(INSTALL) -m 644 -f $oflag/Makefile.install \$(PMDADIR)/Makefile
+ \$(INSTALL) -m 644 -f $oflag/pmns \$(PMDADIR)/pmns
+ \$(INSTALL) -m 644 -f $oflag/root \$(PMDADIR)/root
+ \$(INSTALL) -m 644 -f $oflag/domain.h \$(PMDADIR)/domain.h
+ \$(INSTALL) -m 644 -f $oflag/clusters.h \$(PMDADIR)/clusters.h
+ \$(INSTALL) -m 644 -f $oflag/help \$(PMDADIR)/help
+ \$(INSTALL) -m 644 -f help.pag \$(PMDADIR)/help.pag
+ \$(INSTALL) -m 644 -f help.dir \$(PMDADIR)/help.dir
+
+help.dir help.pag : $oflag/help
+ \$(PCP_BINADM_DIR)/newhelp -n $oflag/root -v 2 -o help < $oflag/help
+
+\$(GCFILES) \$(GHFILES) \$(GSRCFILES) : \$(CONFIG)
+ \$(GENPMDA) -s \$(PCP_VAR_DIR)/pmns/stdpmid -D \$(DOMAIN) -d -v -i \$(IAM) -c \$(CONFIG)
+
+\$(CMDTARGET): \$(OBJECTS)
+ cc -o \$(CMDTARGET) \$(OBJECTS) \$(LLDLIBS)
+
+\$(LIBTARGET): \$(OBJECTS)
+ cc -shared -Wl,-soname,\$(LIBTARGET) -o \$(LIBTARGET) \$(OBJECTS) \$(LLDLIBS) -ldl
+
+clean clobber:
+ rm -rf \$(LDIRT)
+EOFEOF
+
+
+#
+# What needs to be merged?
+#
+for f in *.new
+do
+ b=`basename $f .new`
+ if [ -f "$b" ]
+ then
+ if diff "$b" "$f" >/dev/null 2>&1
+ then
+ rm -f $f
+ $verbose && echo "Unchanged $b"
+ else
+ echo "MERGE required, gdiff $b $f"
+ fi
+ else
+ mv $f $b
+ $verbose && echo "Wrote $b"
+ fi
+done
+
+rm -f CFILES
+exit 0