diff options
Diffstat (limited to 'src/pmprobe')
-rw-r--r-- | src/pmprobe/GNUmakefile | 32 | ||||
-rw-r--r-- | src/pmprobe/pmprobe.c | 361 |
2 files changed, 393 insertions, 0 deletions
diff --git a/src/pmprobe/GNUmakefile b/src/pmprobe/GNUmakefile new file mode 100644 index 0000000..475a11d --- /dev/null +++ b/src/pmprobe/GNUmakefile @@ -0,0 +1,32 @@ +# +# 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. +# + +TOPDIR = ../.. +include $(TOPDIR)/src/include/builddefs + +CFILES = pmprobe.c +LLDLIBS = $(PCPLIB) +CMDTARGET = pmprobe$(EXECSUFFIX) + +default: $(CMDTARGET) + +include $(BUILDRULES) + +install: default + $(INSTALL) -m 755 $(CMDTARGET) $(PCP_BIN_DIR)/$(CMDTARGET) + +default_pcp: default + +install_pcp: install + diff --git a/src/pmprobe/pmprobe.c b/src/pmprobe/pmprobe.c new file mode 100644 index 0000000..c9b2a22 --- /dev/null +++ b/src/pmprobe/pmprobe.c @@ -0,0 +1,361 @@ +/* + * pmprobe - light-weight pminfo for configuring monitor apps + * + * Copyright (c) 2013-2014 Red Hat. + * Copyright (c) 2000-2001 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 <unistd.h> +#include "pmapi.h" +#include "impl.h" + +static char **namelist; +static pmID *pmidlist; +static int listsize; +static int numpmid; +static int *instlist; +static char **instnamelist; + +static pmLongOptions longopts[] = { + PMAPI_OPTIONS_HEADER("General options"), + PMOPT_ARCHIVE, + PMOPT_DEBUG, + PMOPT_HOST, + PMOPT_LOCALPMDA, + PMOPT_SPECLOCAL, + PMOPT_NAMESPACE, + PMOPT_ORIGIN, + PMOPT_HELP, + PMAPI_OPTIONS_HEADER("Reporting options"), + { "force", 0, 'f', 0, "report all pmGetIndom or pmGetInDomArchive instances" }, + { "external", 0, 'I', 0, "list external instance names" }, + { "internal", 0, 'i', 0, "list internal instance numbers" }, + { "verbose", 0, 'V', 0, "report PDU operations (verbose)" }, + { "values", 0, 'v', 0, "list metric values" }, + PMAPI_OPTIONS_END +}; + +static pmOptions opts = { + .flags = PM_OPTFLAG_STDOUT_TZ, + .short_options = "a:D:fh:IiK:Ln:O:VvZ:z?", + .long_options = longopts, + .short_usage = "[options] [metricname ...]", +}; + +static void +dometric(const char *name) +{ + if (numpmid >= listsize) { + size_t size; + + listsize = listsize == 0 ? 16 : listsize * 2; + size = listsize * sizeof(pmidlist[0]); + if ((pmidlist = (pmID *)realloc(pmidlist, size)) == NULL) + __pmNoMem("realloc pmidlist", size, PM_FATAL_ERR); + size = listsize * sizeof(namelist[0]); + if ((namelist = (char **)realloc(namelist, size)) == NULL) + __pmNoMem("realloc namelist", size, PM_FATAL_ERR); + } + + namelist[numpmid]= strdup(name); + if (namelist[numpmid] == NULL) + __pmNoMem("strdup name", strlen(name), PM_FATAL_ERR); + + numpmid++; +} + +static int +lookup(pmInDom indom) +{ + static pmInDom last = PM_INDOM_NULL; + static int numinst; + + if (indom != last) { + if (numinst > 0) { + free(instlist); + free(instnamelist); + } + if (opts.context == PM_CONTEXT_ARCHIVE) + numinst = pmGetInDomArchive(indom, &instlist, &instnamelist); + else + numinst = pmGetInDom(indom, &instlist, &instnamelist); + last = indom; + } + return numinst; +} + +int +main(int argc, char **argv) +{ + int c, i, j, sts; + int fetch_sts; + int numinst; + int fflag = 0; /* -f pmGetIndom or pmGetIndomArchive for instances */ + int iflag = 0; /* -i for instance numbers */ + int Iflag = 0; /* -I for instance names */ + int vflag = 0; /* -v for values */ + int Vflag = 0; /* -V for verbose */ + char *source; + pmResult *result; + pmValueSet *vsp; + pmDesc desc; + + while ((c = pmGetOptions(argc, argv, &opts)) != EOF) { + switch (c) { + + case 'f': /* pmGetIndom or pmGetInDomArchive for instances with -i or -I */ + fflag++; + break; + + case 'i': /* report internal instance numbers */ + if (vflag) { + pmprintf("%s: at most one of -i and -v allowed\n", pmProgname); + opts.errors++; + } + iflag++; + break; + + case 'I': /* report external instance names */ + if (vflag) { + pmprintf("%s: at most one of -I and -v allowed\n", pmProgname); + opts.errors++; + } + Iflag++; + break; + + case 'V': /* verbose */ + Vflag++; + break; + + case 'v': /* cheap values */ + if (iflag || Iflag) { + pmprintf("%s: at most one of -v and (-i or -I) allowed\n", pmProgname); + opts.errors++; + } + vflag++; + break; + + default: + opts.errors++; + break; + } + } + + if (opts.errors) { + pmUsageMessage(&opts); + exit(1); + } + + if (opts.context == PM_CONTEXT_ARCHIVE) + source = opts.archives[0]; + else if (opts.context == PM_CONTEXT_HOST) + source = opts.hosts[0]; + else if (opts.context == PM_CONTEXT_LOCAL) + source = NULL; + else { + opts.context = PM_CONTEXT_HOST; + source = "local:"; + } + + if ((sts = c = pmNewContext(opts.context, source)) < 0) { + if (opts.context == PM_CONTEXT_HOST) + fprintf(stderr, "%s: Cannot connect to PMCD on host \"%s\": %s\n", + pmProgname, source, pmErrStr(sts)); + else if (opts.context == PM_CONTEXT_LOCAL) + fprintf(stderr, "%s: Cannot make standalone connection on localhost: %s\n", + pmProgname, pmErrStr(sts)); + else + fprintf(stderr, "%s: Cannot open archive \"%s\": %s\n", + pmProgname, source, pmErrStr(sts)); + exit(1); + } + + /* complete TZ and time window option (origin) setup */ + if (opts.context == PM_CONTEXT_ARCHIVE) { + if (pmGetContextOptions(c, &opts)) { + pmflush(); + exit(1); + } + } + + if (opts.optind >= argc) + pmTraversePMNS("", dometric); + else { + for (i = opts.optind; i < argc; i++) { + sts = pmTraversePMNS(argv[i], dometric); + if (sts < 0) + printf("%s %d %s\n", argv[i], sts, pmErrStr(sts)); + } + } + + /* Lookup names. + * Cull out names that were unsuccessfully looked up. + * However, it is unlikely to fail because names come from a traverse PMNS. + */ + if ((sts = pmLookupName(numpmid, namelist, pmidlist)) < 0) { + for (i = j = 0; i < numpmid; i++) { + if (pmidlist[i] == PM_ID_NULL) { + printf("%s %d %s\n", namelist[i], sts, pmErrStr(sts)); + free(namelist[i]); + } + else { + /* assert(j <= i); */ + pmidlist[j] = pmidlist[i]; + namelist[j] = namelist[i]; + j++; + } + } + numpmid = j; + } + + fetch_sts = 0; + for (i = 0; i < numpmid; i++) { + printf("%s ", namelist[i]); + + if (iflag || Iflag || vflag) { + if ((sts = pmLookupDesc(pmidlist[i], &desc)) < 0) { + printf("%d %s (pmLookupDesc)\n", sts, pmErrStr(sts)); + continue; + } + } + + if (fflag && (iflag || Iflag)) { + /* + * must be -i or -I with -f ... don't even fetch a result + * with pmFetch, just go straight to the instance domain with + * pmGetInDom or pmGetInDomArchive + */ + if (desc.indom == PM_INDOM_NULL) { + printf("1 PM_IN_NULL"); + if ( iflag && Iflag ) + printf(" PM_IN_NULL"); + } + else { + if ((numinst = lookup(desc.indom)) < 0) { + printf("%d %s (pmGetInDom)", numinst, pmErrStr(numinst)); + } + else { + int j; + printf("%d", numinst); + for (j = 0; j < numinst; j++) { + if (iflag) + printf(" ?%d", instlist[j]); + if (Iflag) + printf(" \"%s\"", instnamelist[j]); + } + } + } + putchar('\n'); + continue; + } + + if (opts.context == PM_CONTEXT_ARCHIVE) { + /* + * merics from archives are fetched one at a time, otherwise + * get them all at once + */ + if ((sts = pmSetMode(PM_MODE_FORW, &opts.start, 0)) < 0) { + printf("%d %s (pmSetMode)\n", sts, pmErrStr(sts)); + continue; + } + fetch_sts = pmFetch(1, &pmidlist[i], &result); + } + else { + if (i == 0) + fetch_sts = pmFetch(numpmid, pmidlist, &result); + } + + if (fetch_sts < 0) { + printf("%d %s (pmFetch)", fetch_sts, pmErrStr(fetch_sts)); + } + else { + if (opts.context == PM_CONTEXT_ARCHIVE) + vsp = result->vset[0]; + else + vsp = result->vset[i]; + + if (vsp->numval < 0) { + printf("%d %s", vsp->numval, pmErrStr(vsp->numval)); + } + else if (vsp->numval == 0) { + printf("0"); + ; + } + else if (vsp->numval > 0) { + printf("%d", vsp->numval); + if (vflag) { + for (j = 0; j < vsp->numval; j++) { + pmValue *vp = &vsp->vlist[j]; + putchar(' '); + pmPrintValue(stdout, vsp->valfmt, desc.type, vp, 1); + } + } + if (iflag || Iflag) { + /* + * must be without -f + * get instance domain for reporting to minimize PDU + * round trips ... state should be the same as of the + * pmResult, so each instance in the pmResult should be + * found by pmGetInDom or pmGetInDomArchive + */ + if (desc.indom == PM_INDOM_NULL) { + printf(" PM_IN_NULL"); + if ( iflag && Iflag ) + printf(" PM_IN_NULL"); + putchar ('\n'); + continue; + } + if ((numinst = lookup(desc.indom)) < 0) { + printf("%d %s (pmGetInDom)\n", numinst, pmErrStr(numinst)); + continue; + } + for (j = 0; j < vsp->numval; j++) { + pmValue *vp = &vsp->vlist[j]; + if (iflag) + printf(" ?%d", vp->inst); + if (Iflag) { + int k; + for (k = 0; k < numinst; k++) { + if (instlist[k] == vp->inst) + break; + } + if (k < numinst) + printf(" \"%s\"", instnamelist[k]); + else + printf(" ?%d", vp->inst); + } + } + } + } + } + putchar('\n'); + } + + if (Vflag) { + printf("PDUs send"); + for (i = j = 0; i < PDU_MAX; i++) { + printf(" %3d", __pmPDUCntOut[i]); + j += __pmPDUCntOut[i]; + } + printf("\nTotal: %d\n", j); + + printf("PDUs recv"); + for (i = j = 0; i < PDU_MAX; i++) { + printf(" %3d",__pmPDUCntIn[i]); + j += __pmPDUCntIn[i]; + } + printf("\nTotal: %d\n", j); + } + + exit(0); +} |