summaryrefslogtreecommitdiff
path: root/src/pmtrace/pmtrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmtrace/pmtrace.c')
-rw-r--r--src/pmtrace/pmtrace.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/src/pmtrace/pmtrace.c b/src/pmtrace/pmtrace.c
new file mode 100644
index 0000000..745da3e
--- /dev/null
+++ b/src/pmtrace/pmtrace.c
@@ -0,0 +1,211 @@
+/*
+ * 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 "pmapi.h"
+#include "impl.h"
+#include "trace.h"
+
+typedef enum { UNKNOWN, COUNTER, OBSERVE, TRANSACT } trace_t;
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ char *p;
+ char *me;
+ int err = 0;
+ int verbose = 1;
+ /* anything directly influencing the trace API is in this struct */
+ struct {
+ int state;
+ char *tag;
+ char *host;
+ trace_t type; /* COUNTER, OBSERVE, or TRANSACT */
+ union {
+ double value; /* OBSERVE/COUNTER types */
+ char *command; /* TRANSACT type */
+ } arg;
+ } api;
+
+ __pmSetProgname(argv[0]);
+ me = pmProgname;
+
+ memset(&api, 0, sizeof(api));
+
+ while ((c = getopt(argc, argv, "S:c:e:h:qv:?")) != EOF) {
+ switch (c) {
+ case 'S':
+ /* allow base 8 or 16 or 10 based on supplied value */
+ c = (int)strtol(optarg, &p, 0);
+ if (p == optarg || *p != '\0') {
+ fprintf(stderr, "%s: -S requires a numeric argument\n", me);
+ err++;
+ }
+ else
+ api.state |= c;
+ break;
+
+ case 'h':
+ api.host = optarg;
+ break;
+
+ case 'q':
+ verbose = 0;
+ break;
+
+ case 'c':
+ if (api.type != UNKNOWN) {
+ fprintf(stderr, "%s: only one of -c, -v or -e allowed\n", me);
+ err++;
+ }
+ api.type = COUNTER;
+ api.arg.value = strtod(optarg, &p);
+ if (*p != '\0') {
+ fprintf(stderr, "%s: -v requires a numeric argument\n", me);
+ err++;
+ }
+ break;
+
+ case 'e':
+ if (api.type != UNKNOWN) {
+ fprintf(stderr, "%s: only one of -c, -v or -e allowed\n", me);
+ err++;
+ }
+ api.type = TRANSACT;
+ api.arg.command = optarg;
+ break;
+
+ case 'v':
+ if (api.type != UNKNOWN) {
+ fprintf(stderr, "%s: only one of -c, -v or -e allowed\n", me);
+ err++;
+ }
+ api.type = OBSERVE;
+ api.arg.value = strtod(optarg, &p);
+ if (*p != '\0') {
+ fprintf(stderr, "%s: -v requires a numeric argument\n", me);
+ err++;
+ }
+ break;
+
+ default:
+ err++;
+ }
+ }
+
+ if (optind == argc-1) {
+ api.tag = argv[optind];
+ optind++;
+ }
+
+ if (err || optind != argc || api.tag == NULL) {
+ fprintf(stderr,
+"Usage: %s [-q] [-c value|-e command|-v value] [-h host] [-S state] tag\n\n\
+Options:\n\
+ -c value export a counter value through the trace PMDA\n\
+ -e command run command and export transaction data\n\
+ -h host send trace data to trace PMDA on given host\n\
+ -q quiet mode - suppress message from successful trace\n\
+ -S state set debug state using pmtracestate(3) as bit-wise\n\
+ combination of these flags:\n\
+ 1 Shows processing just below the API\n\
+ 2 Shows network-related activity\n\
+ 4 Shows app<->PMDA IPC traffic\n\
+ 8 Shows internal IPC buffer management\n\
+ 16 No PMDA communications at all\n\
+ -v value export an observation value through the trace PMDA\n\
+\n\
+%s always uses the asynchronous PDU protocol mode.\n", me, me);
+ exit(0);
+ }
+
+ pmtracestate(api.state | PMTRACE_STATE_ASYNC);
+ c = 0; /* reuse as the exit status */
+
+ if (api.host != NULL) {
+ if ((p = (char *)malloc(strlen(api.host) + 20)) == NULL) {
+ fprintf(stderr, "%s: malloc failed: %s\n",
+ me, pmtraceerrstr(-oserror()));
+ exit(0);
+ }
+ sprintf(p, "PCP_TRACE_HOST=%s", api.host);
+ if (putenv(p) < 0) {
+ fprintf(stderr, "%s: putenv failed: %s\n",
+ me, pmtraceerrstr(-oserror()));
+ exit(0);
+ }
+ }
+
+ switch (api.type) {
+ case COUNTER:
+ if ((err = pmtracecounter(api.tag, api.arg.value)) < 0) {
+ fprintf(stderr, "%s: counter error: %s\n",
+ me, pmtraceerrstr(err));
+ exit(0);
+ }
+ else if (verbose) {
+ printf("%s: counter complete (tag=\"%s\", value=%f)\n",
+ me, api.tag, api.arg.value);
+ }
+ break;
+
+ case OBSERVE:
+ if ((err = pmtraceobs(api.tag, api.arg.value)) < 0) {
+ fprintf(stderr, "%s: observation error: %s\n",
+ me, pmtraceerrstr(err));
+ exit(0);
+ }
+ else if (verbose) {
+ printf("%s: observation complete (tag=\"%s\", value=%f)\n",
+ me, api.tag, api.arg.value);
+ }
+ break;
+
+ case TRANSACT:
+ if ((err = pmtracebegin(api.tag)) < 0) {
+ fprintf(stderr, "%s: transaction begin error: %s\n",
+ me, pmtraceerrstr(err));
+ /* don't exit yet - execute cmd anyway, just no tracing */
+ }
+
+ if ((c = system(api.arg.command)) < 0) {
+ fprintf(stderr, "%s: system error running '%s': %s\n",
+ me, api.arg.command, pmtraceerrstr(-oserror()));
+ exit(0);
+ }
+ if (err < 0)
+ exit(c);
+
+ if ((err = pmtraceend(api.tag)) < 0) {
+ fprintf(stderr, "%s: transaction end error: %s\n",
+ me, pmtraceerrstr(err));
+ exit(c);
+ }
+ else if (verbose) {
+ printf("%s: transaction complete (tag=\"%s\")\n", me, api.tag);
+ }
+ break;
+
+ default:
+ if ((err = pmtracepoint(api.tag)) < 0) {
+ fprintf(stderr, "%s: point error: %s\n",
+ me, pmtraceerrstr(err));
+ exit(0);
+ }
+ else if (verbose) {
+ printf("%s: point complete (tag=\"%s\")\n", me, api.tag);
+ }
+ }
+ exit(c);
+}