diff options
Diffstat (limited to 'src/pmdas/trace/src/pmda.c')
-rw-r--r-- | src/pmdas/trace/src/pmda.c | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/src/pmdas/trace/src/pmda.c b/src/pmdas/trace/src/pmda.c new file mode 100644 index 0000000..36560aa --- /dev/null +++ b/src/pmdas/trace/src/pmda.c @@ -0,0 +1,228 @@ +/* + * Trace PMDA - process level transaction monitoring for libpcp_trace processes + * + * Copyright (c) 2012 Red Hat. + * Copyright (c) 1997-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 <ctype.h> +#include "pmapi.h" +#include "impl.h" +#include "pmda.h" +#include "domain.h" +#include "trace.h" +#include "trace_dev.h" +#include "comms.h" + +#define DEFAULT_TIMESPAN 60 /* one minute */ +#define DEFAULT_BUFSIZE 5 /* twelve second update */ + +struct timeval timespan = { DEFAULT_TIMESPAN, 0 }; +struct timeval interval; +unsigned int rbufsize = DEFAULT_BUFSIZE; +int ctlport = -1; +char *ctlsock; + +static char mypath[MAXPATHLEN]; +static char *username; + +extern void traceInit(pmdaInterface *dispatch); +extern void traceMain(pmdaInterface *dispatch); +extern int updateObserveValue(const char *); +extern int updateCounterValue(const char *); +extern void debuglibrary(int); + +static void +usage(void) +{ + fprintf(stderr, +"Usage: %s [options]\n\ +\n\ +Options:\n\ + -d domain use domain (numeric) for metrics domain of PMDA\n\ + -l logfile write log into logfile rather than using default file\n\ + -A access host based access control\n\ + -I port expect programs to connect on given inet port (number/name)\n\ + -M username user account to run under (default \"pcp\")\n\ + -N buckets number of historical data buffers maintained\n\ + -T period time over which samples are considered (default 60 seconds)\n\ + -U units export observation values using the given units\n\ + -V units export counter values using the given units\n", + pmProgname); + exit(1); +} + +static char * +squash(char *str, int *offset) +{ + char *hspec = NULL; + char *p = str; + int i = 0; + + hspec = strdup(str); /* make sure we have space */ + *offset = 0; + while (isspace((int)*p)) { p++; (*offset)++; } + while (p && *p != ':' && *p != '\0') { + hspec[i++] = *p; + p++; + } + hspec[i] = '\0'; + *offset += i; + return hspec; +} + +static int +parseAuth(char *spec) +{ + static int first = 1; + int offset, maxconn, specops = TR_OP_ALL, denyops; + char *p, *endnum; + + if (first) { + if (__pmAccAddOp(TR_OP_SEND) < 0) { + __pmNotifyErr(LOG_ERR, "failed to add send auth operation"); + return -1; + } + first = 0; + } + + if (strncasecmp(spec, "disallow:", 9) == 0) { + p = squash(&spec[9], &offset); + if (p == NULL || p[0] == '\0') { + fprintf(stderr, "%s: invalid disallow (%s)\n", pmProgname, spec); + if (p) + free(p); + return -1; + } +#ifdef PCP_DEBUG + if (pmDebug & DBG_TRACE_APPL0) + fprintf(stderr, "deny: host '%s'\n", p); +#endif + denyops = TR_OP_SEND; + if (__pmAccAddHost(p, specops, denyops, 0) < 0) + __pmNotifyErr(LOG_ERR, "failed to add authorisation (%s)", p); + free(p); + } + else if (strncasecmp(spec, "allow:", 6) == 0) { + p = squash(&spec[6], &offset); + if (p == NULL || p[0] == '\0') { + fprintf(stderr, "%s: invalid allow (%s)\n", pmProgname, spec); + if (p) + free(p); + return -1; + } + offset += 7; + maxconn = (int)strtol(&spec[offset], &endnum, 10); + if (*endnum != '\0' || maxconn < 0) { + fprintf(stderr, "%s: bogus max connection in '%s'\n", pmProgname, + &spec[offset]); + free(p); + return -1; + } +#ifdef PCP_DEBUG + if (pmDebug & DBG_TRACE_APPL0) + fprintf(stderr, "allow: host '%s', maxconn=%d\n", p, maxconn); +#endif + denyops = TR_OP_NONE; + if (__pmAccAddHost(p, specops, denyops, maxconn) < 0) + __pmNotifyErr(LOG_ERR, "failed to add authorisation (%s)", p); + free(p); + } + else { + fprintf(stderr, "%s: access spec is invalid (%s)\n", pmProgname, spec); + return -1; + } + return 0; +} + +int +main(int argc, char **argv) +{ + pmdaInterface dispatch; + char *endnum; + int err = 0; + int sep = __pmPathSeparator(); + int c = 0; + + __pmSetProgname(argv[0]); + __pmGetUsername(&username); + + snprintf(mypath, sizeof(mypath), "%s%c" "trace" "%c" "help", + pmGetConfig("PCP_PMDAS_DIR"), sep, sep); + pmdaDaemon(&dispatch, PMDA_INTERFACE_2, pmProgname, TRACE, + "trace.log", mypath); + + /* need - port, as well as time interval and time span for averaging */ + while ((c = pmdaGetOpt(argc, argv, "A:D:d:I:l:T:M:N:U:V:?", + &dispatch, &err)) != EOF) { + switch(c) { + case 'A': + if (parseAuth(optarg) < 0) + err++; + /* add optarg to access control list */ + break; + case 'I': + ctlport = (int)strtol(optarg, &endnum, 10); + if (*endnum != '\0' || ctlport < 0) + ctlsock = optarg; + break; + case 'M': + username = optarg; + break; + case 'N': + rbufsize = (int)strtol(optarg, &endnum, 10); + if (*endnum != '\0' || rbufsize < 1) { + fprintf(stderr, "%s: -N requires a positive number.\n", pmProgname); + err++; + } + break; + case 'T': + if (pmParseInterval(optarg, ×pan, &endnum) < 0) { + fprintf(stderr, "%s: -T requires a time interval: %s\n", + pmProgname, endnum); + free(endnum); + err++; + } + break; + case 'U': + if (updateObserveValue(optarg) < 0) + err++; + break; + case 'V': + if (updateCounterValue(optarg) < 0) + err++; + break; + default: + err++; + } + } + + if (err) + usage(); + + interval.tv_sec = (int)(timespan.tv_sec / rbufsize); + interval.tv_usec = (long)((timespan.tv_sec % rbufsize) * 1000000); + rbufsize++; /* reserve space for the `working' buffer */ + +#ifdef PCP_DEBUG + debuglibrary(pmDebug); +#endif + + pmdaOpenLog(&dispatch); + __pmSetProcessIdentity(username); + traceInit(&dispatch); + pmdaConnect(&dispatch); + traceMain(&dispatch); + + exit(0); +} |