File: //bin/genpmda
#! /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 "libpcp.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 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 \"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 \"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 " pmsprintf(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\", pmGetProgname());\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 " pmsprintf(helppath, sizeof(helppath), \"%%s/pmdas/'$iam'/help\", pmGetConfig(\"PCP_VAR_DIR\"));\n" >>pmda_c
printf " pmdaDaemon(&dispatch, PMDA_INTERFACE_4, pmGetProgname(), '$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 \"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
\$(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