summaryrefslogtreecommitdiff
path: root/src/dbpmda
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2014-10-26 12:33:50 +0400
committerIgor Pashev <pashev.igor@gmail.com>2014-10-26 12:33:50 +0400
commit47e6e7c84f008a53061e661f31ae96629bc694ef (patch)
tree648a07f3b5b9d67ce19b0fd72e8caa1175c98f1a /src/dbpmda
downloadpcp-debian/3.9.10.tar.gz
Debian 3.9.10debian/3.9.10debian
Diffstat (limited to 'src/dbpmda')
-rw-r--r--src/dbpmda/GNUmakefile32
-rw-r--r--src/dbpmda/src/GNUmakefile47
-rw-r--r--src/dbpmda/src/dbpmda.c437
-rw-r--r--src/dbpmda/src/dbpmda.h98
-rw-r--r--src/dbpmda/src/dso.c479
-rw-r--r--src/dbpmda/src/gram.y634
-rw-r--r--src/dbpmda/src/lex.h32
-rw-r--r--src/dbpmda/src/lex.l611
-rw-r--r--src/dbpmda/src/pmda.c840
-rw-r--r--src/dbpmda/src/util.c587
10 files changed, 3797 insertions, 0 deletions
diff --git a/src/dbpmda/GNUmakefile b/src/dbpmda/GNUmakefile
new file mode 100644
index 0000000..4c4ed0e
--- /dev/null
+++ b/src/dbpmda/GNUmakefile
@@ -0,0 +1,32 @@
+#!gmake
+#
+# 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.
+#
+# 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
+
+SUBDIRS = src
+
+default install: $(SUBDIRS)
+ $(SUBDIRS_MAKERULE)
+
+include $(BUILDRULES)
+
+default_pcp : default
+
+install_pcp : install
diff --git a/src/dbpmda/src/GNUmakefile b/src/dbpmda/src/GNUmakefile
new file mode 100644
index 0000000..e74eb80
--- /dev/null
+++ b/src/dbpmda/src/GNUmakefile
@@ -0,0 +1,47 @@
+#
+# 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
+
+CMDTARGET = dbpmda$(EXECSUFFIX)
+CFILES = dbpmda.c dso.c util.c pmda.c
+HFILES = lex.h dbpmda.h
+LFILES = lex.l
+YFILES = gram.y
+
+LDIRT = *.log foo.* gram.h $(YFILES:%.y=%.tab.?) $(LFILES:%.l=%.c)
+LLDLIBS = $(PCPLIB) $(LIB_FOR_DLOPEN) $(LIB_FOR_READLINE) $(LIB_FOR_CURSES)
+
+default: $(CMDTARGET)
+
+include $(BUILDRULES)
+
+$(CMDTARGET): $(OBJECTS)
+
+install: $(CMDTARGET)
+ $(INSTALL) -m 755 $(CMDTARGET) $(PCP_BIN_DIR)/$(CMDTARGET)
+
+dbpmda.o: gram.h
+lex.o: gram.tab.h
+
+.NOTPARALLEL:
+gram.tab.h gram.tab.c: gram.y
+
+gram.h: gram.tab.h
+ rm -f $@ && $(LN_S) $< $@
+
+default_pcp: default
+
+install_pcp: install
diff --git a/src/dbpmda/src/dbpmda.c b/src/dbpmda/src/dbpmda.c
new file mode 100644
index 0000000..9af6e23
--- /dev/null
+++ b/src/dbpmda/src/dbpmda.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2012-2014 Red Hat.
+ * Copyright (c) 1995-2002 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 "dbpmda.h"
+#include "lex.h"
+#include "gram.h"
+#include <ctype.h>
+
+char *configfile;
+__pmLogCtl logctl;
+int parse_done;
+int primary; /* Non-zero for primary pmlc */
+pid_t pid = (pid_t) -1;
+char *pmnsfile = PM_NS_DEFAULT;
+char *cmd_namespace = NULL; /* namespace given from command */
+int _creds_timeout = 3; /* Timeout for agents credential PDU */
+
+int connmode = NO_CONN;
+int stmt_type;
+int eflag;
+int iflag;
+
+extern int yyparse(void);
+
+static pmLongOptions longopts[] = {
+ PMAPI_OPTIONS_HEADER("General options"),
+ PMOPT_DEBUG,
+ PMOPT_NAMESPACE,
+ { "creds-timeout", 1, 'q', "N", "initial negotiation timeout (seconds)" },
+ { "username", 1, 'U', "USER", "run under named user account" },
+ PMOPT_HELP,
+ PMAPI_OPTIONS_HEADER("Input options"),
+ { "echo-input", 0, 'e', 0, "echo input" },
+ { "interactive", 0, 'i', 0, "be interactive and prompt" },
+ PMAPI_OPTIONS_END
+};
+
+static pmOptions opts = {
+ .flags = PM_OPTFLAG_POSIX,
+ .short_options = "q:D:ein:U:?",
+ .long_options = longopts,
+};
+
+/*
+ * called before regular exit() or as atexit() handler
+ */
+static void
+cleanup()
+{
+ if (connmode == CONN_DSO)
+ closedso();
+ else if (connmode == CONN_DAEMON)
+ closepmda();
+ connmode = NO_CONN;
+}
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ int sts;
+ char *endnum;
+
+ iflag = isatty(0);
+
+ while ((c = pmgetopt_r(argc, argv, &opts)) != EOF) {
+ switch (c) {
+
+ case 'D': /* debug flag */
+ sts = __pmParseDebug(opts.optarg);
+ if (sts < 0) {
+ fprintf(stderr, "%s: unrecognized debug flag specification (%s)\n",
+ pmProgname, opts.optarg);
+ opts.errors++;
+ }
+ else
+ pmDebug |= sts;
+ break;
+
+ case 'e': /* echo input */
+ eflag++;
+ break;
+
+ case 'i': /* be interactive */
+ iflag = 1;
+ break;
+
+ case 'n': /* alternative name space file */
+ pmnsfile = opts.optarg;
+ break;
+
+ case 'q':
+ sts = (int)strtol(opts.optarg, &endnum, 10);
+ if (*endnum != '\0' || sts <= 0.0) {
+ pmprintf("%s: -q requires a positive numeric argument\n",
+ pmProgname);
+ opts.errors++;
+ } else {
+ _creds_timeout = sts;
+ }
+ break;
+
+ case 'U': /* run under alternate user account */
+ __pmSetProcessIdentity(opts.optarg);
+ break;
+
+ default:
+ case '?':
+ opts.errors++;
+ break;
+ }
+ }
+
+ if ((c = argc - opts.optind) > 0) {
+ if (c > 1)
+ opts.errors++;
+ else {
+ /* pid was specified */
+ if (primary) {
+ pmprintf("%s: you may not specify both -P and a pid\n",
+ pmProgname);
+ opts.errors++;
+ }
+ else {
+ pid = (int)strtol(argv[opts.optind], &endnum, 10);
+ if (*endnum != '\0') {
+ pmprintf("%s: pid must be a numeric process id\n",
+ pmProgname);
+ opts.errors++;
+ }
+ }
+ }
+ }
+
+ if (opts.errors) {
+ pmUsageMessage(&opts);
+ exit(1);
+ }
+
+ if ((sts = pmLoadNameSpace(pmnsfile)) < 0) {
+ if (pmnsfile == PM_NS_DEFAULT) {
+ fprintf(stderr, "%s: Cannot load default namespace: %s\n",
+ pmProgname, pmErrStr(sts));
+ } else {
+ fprintf(stderr, "%s: Cannot load namespace from \"%s\": %s\n",
+ pmProgname, pmnsfile, pmErrStr(sts));
+ }
+ exit(1);
+ }
+
+ /* initialize the "fake context" ... */
+ setup_context();
+
+ setlinebuf(stdout);
+ setlinebuf(stderr);
+
+#ifdef HAVE_ATEXIT
+ atexit(cleanup);
+#endif
+
+ for ( ; ; ) {
+ initmetriclist();
+ yyparse();
+ if (yywrap()) {
+ if (iflag)
+ putchar('\n');
+ break;
+ }
+
+ __pmSetInternalState(PM_STATE_PMCS);
+
+ switch (stmt_type) {
+
+ case OPEN:
+ profile_changed = 1;
+ break;
+
+ case CLOSE:
+ switch (connmode) {
+ case CONN_DSO:
+ closedso();
+ break;
+
+ case CONN_DAEMON:
+ closepmda();
+ break;
+
+ case NO_CONN:
+ yywarn("No PMDA currently opened");
+ break;
+ }
+ connmode = NO_CONN;
+ break;
+
+ case DESC:
+ switch (connmode) {
+ case CONN_DSO:
+ dodso(PDU_DESC_REQ);
+ break;
+
+ case CONN_DAEMON:
+ dopmda(PDU_DESC_REQ);
+ break;
+
+ case NO_CONN:
+ yywarn("No PMDA currently opened");
+ break;
+ }
+ break;
+
+ case FETCH:
+ switch (connmode) {
+ case CONN_DSO:
+ dodso(PDU_FETCH);
+ break;
+
+ case CONN_DAEMON:
+ dopmda(PDU_FETCH);
+ break;
+
+ case NO_CONN:
+ yywarn("No PMDA currently opened");
+ break;
+ }
+ break;
+
+ case INSTANCE:
+ switch (connmode) {
+ case CONN_DSO:
+ dodso(PDU_INSTANCE_REQ);
+ break;
+
+ case CONN_DAEMON:
+ dopmda(PDU_INSTANCE_REQ);
+ break;
+
+ case NO_CONN:
+ yywarn("No PMDA currently opened");
+ break;
+ }
+ break;
+
+ case STORE:
+ switch (connmode) {
+ case CONN_DSO:
+ dodso(PDU_RESULT);
+ break;
+
+ case CONN_DAEMON:
+ dopmda(PDU_RESULT);
+ break;
+
+ case NO_CONN:
+ yywarn("No PMDA currently opened");
+ break;
+ }
+ break;
+
+ case HELP:
+ dohelp(param.number, param.pmid);
+ break;
+
+ case WATCH:
+ break;
+
+ case DBG:
+ pmDebug = param.number;
+ break;
+
+ case QUIT:
+ goto done;
+
+ case STATUS:
+ dostatus();
+ break;
+
+ case INFO:
+ switch (connmode) {
+ case CONN_DSO:
+ dodso(PDU_TEXT_REQ);
+ break;
+
+ case CONN_DAEMON:
+ dopmda(PDU_TEXT_REQ);
+ break;
+
+ case NO_CONN:
+ yywarn("No PMDA currently opened");
+ break;
+ }
+ break;
+ case NAMESPACE:
+ if (cmd_namespace != NULL)
+ free(cmd_namespace);
+ cmd_namespace = strdup(param.name);
+ if (cmd_namespace == NULL) {
+ fprintf(stderr, "%s: No memory for new namespace\n",
+ pmProgname);
+ exit(1);
+ }
+ pmUnloadNameSpace();
+ strcpy(cmd_namespace, param.name);
+ if ((sts = pmLoadNameSpace(cmd_namespace)) < 0) {
+ fprintf(stderr, "%s: Cannot load namespace from \"%s\": %s\n",
+ pmProgname, cmd_namespace, pmErrStr(sts));
+
+ pmUnloadNameSpace();
+ if (pmnsfile == PM_NS_DEFAULT) {
+ fprintf(stderr, "%s: Reload default namespace\n",
+ pmProgname);
+ } else {
+ fprintf(stderr, "%s: Reload namespace from \"%s\"\n",
+ pmProgname, pmnsfile);
+ }
+ if ((sts = pmLoadNameSpace(pmnsfile)) < 0) {
+ if (pmnsfile == PM_NS_DEFAULT) {
+ fprintf(stderr,
+ "%s: Cannot load default namespace: %s\n",
+ pmProgname, pmErrStr(sts));
+ } else {
+ fprintf(stderr,
+ "%s: Cannot load namespace from \"%s\""
+ ": %s\n",
+ pmProgname, pmnsfile, pmErrStr(sts));
+ }
+ exit(1);
+ }
+ }
+ break;
+
+ case EOL:
+ break;
+
+ case PMNS_NAME:
+ switch (connmode) {
+ case CONN_DSO:
+ dodso(PDU_PMNS_IDS);
+ break;
+
+ case CONN_DAEMON:
+ dopmda(PDU_PMNS_IDS);
+ break;
+
+ case NO_CONN:
+ yywarn("No PMDA currently opened");
+ break;
+ }
+ break;
+
+ case PMNS_PMID:
+ switch (connmode) {
+ case CONN_DSO:
+ dodso(PDU_PMNS_NAMES);
+ break;
+
+ case CONN_DAEMON:
+ dopmda(PDU_PMNS_NAMES);
+ break;
+
+ case NO_CONN:
+ yywarn("No PMDA currently opened");
+ break;
+ }
+ break;
+
+ case PMNS_CHILDREN:
+ switch (connmode) {
+ case CONN_DSO:
+ dodso(PDU_PMNS_CHILD);
+ break;
+
+ case CONN_DAEMON:
+ dopmda(PDU_PMNS_CHILD);
+ break;
+
+ case NO_CONN:
+ yywarn("No PMDA currently opened");
+ break;
+ }
+ break;
+
+ case PMNS_TRAVERSE:
+ switch (connmode) {
+ case CONN_DSO:
+ dodso(PDU_PMNS_TRAVERSE);
+ break;
+
+ case CONN_DAEMON:
+ dopmda(PDU_PMNS_TRAVERSE);
+ break;
+
+ case NO_CONN:
+ yywarn("No PMDA currently opened");
+ break;
+ }
+ break;
+
+ case ATTR:
+ switch (connmode) {
+ case CONN_DSO:
+ dodso(PDU_AUTH);
+ break;
+
+ case CONN_DAEMON:
+ dopmda(PDU_AUTH);
+ break;
+
+ case NO_CONN:
+ yywarn("No PMDA currently opened");
+ break;
+ }
+ break;
+
+ default:
+ printf("Unexpected result (%d) from parser?\n", stmt_type);
+ break;
+ }
+ __pmSetInternalState(PM_STATE_APPL);
+ }
+
+done:
+ cleanup();
+
+ exit(0);
+}
diff --git a/src/dbpmda/src/dbpmda.h b/src/dbpmda/src/dbpmda.h
new file mode 100644
index 0000000..6e35cdf
--- /dev/null
+++ b/src/dbpmda/src/dbpmda.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2013 Red Hat.
+ * Copyright (c) 1997 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 "pmda.h"
+
+/* yacc/lex routines */
+extern char lastinput(void);
+extern void yyerror(const char *);
+extern void yywarn(char *);
+extern int yywrap(void);
+extern int yylex(void);
+extern int markpos(void);
+extern void locateError(void);
+
+/* utiltity routines */
+extern void setup_context(void);
+extern void reset_profile(void);
+extern char *strcons(char *, char *);
+extern char *strnum(int);
+extern void initmetriclist(void);
+extern void addmetriclist(pmID);
+extern void initarglist(void);
+extern void addarglist(char *);
+extern void doargs(void);
+extern void printindom(FILE *, __pmInResult *);
+extern void dohelp(int, int);
+extern void dostatus(void);
+extern int fillResult(pmResult *, int);
+extern void _dbDumpResult(FILE *, pmResult *, pmDesc *);
+
+/* pmda exerciser routines */
+extern void opendso(char *, char *, int);
+extern void closedso(void);
+extern void dodso(int);
+extern void openpmda(char *);
+extern void closepmda(void);
+extern void dopmda(int);
+extern void watch(char *);
+extern void open_unix_socket(char *);
+extern void open_inet_socket(int);
+extern void open_ipv6_socket(int);
+
+/*
+ * connection states
+ */
+#define NO_CONN -1
+#define CONN_DSO 0
+#define CONN_DAEMON 1
+extern int connmode;
+
+/* parameters for action routines ... */
+typedef struct {
+ int number;
+ char *name;
+ pmID pmid;
+ pmInDom indom;
+ int numpmid;
+ pmID *pmidlist;
+ int argc;
+ char **argv;
+} param_t;
+
+extern param_t param;
+
+/* the single profile */
+extern __pmProfile *profile;
+extern int profile_changed;
+
+/* status info */
+extern char *myPmdaName;
+
+/* help text formats */
+#define HELP_USAGE 0
+#define HELP_FULL 1
+
+/* timing information */
+extern int timer;
+
+/* get descriptor for fetch or not */
+extern int get_desc;
+
+/* namespace pathnames */
+extern char *pmnsfile;
+extern char *cmd_namespace;
diff --git a/src/dbpmda/src/dso.c b/src/dbpmda/src/dso.c
new file mode 100644
index 0000000..5dc7c16
--- /dev/null
+++ b/src/dbpmda/src/dso.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 2013 Red Hat.
+ * Copyright (c) 1995,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.
+ */
+
+#include <sys/stat.h>
+#include "./dbpmda.h"
+#include "pmapi.h"
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+static char *dsoname;
+static void *handle;
+pmdaInterface dispatch;
+
+void
+opendso(char *dso, char *init, int domain)
+{
+#ifdef HAVE_DLOPEN
+ struct stat buf;
+ unsigned int challenge;
+
+ dispatch.status = -1;
+
+ if (stat(dso, &buf) < 0) {
+ fprintf(stderr, "opendso: %s: %s\n", dso, osstrerror());
+ return;
+ }
+
+ closedso();
+ /*
+ * RTLD_NOW would be better in terms of detecting unresolved symbols
+ * now, rather than taking a SEGV later ... but various combinations
+ * of dynamic and static libraries used to create the DSO PMDA,
+ * combined with hiding symbols in the DSO PMDA may result in benign
+ * unresolved symbols remaining and the dlopen() would fail under
+ * these circumstances.
+ */
+ handle = dlopen(dso, RTLD_LAZY);
+ if (handle == NULL) {
+ printf("Error attaching DSO \"%s\"\n", dso);
+ printf("%s\n\n", dlerror());
+ }
+ else {
+ void (*initp)(pmdaInterface *);
+ initp = (void (*)(pmdaInterface *))dlsym(handle, init);
+ if (initp == NULL) {
+ printf("Error: couldn't find init function \"%s\" in DSO \"%s\"\n",
+ init, dso);
+ dlclose(handle);
+ }
+ else {
+ /*
+ * the PMDA interface / PMAPI version discovery as a "challenge" ...
+ * for pmda_interface it is all the bits being set,
+ * for pmapi_version it is the complement of the one you are
+ * using now
+ */
+ challenge = 0xff;
+ dispatch.comm.pmda_interface = challenge;
+ dispatch.comm.pmapi_version = ~PMAPI_VERSION;
+ dispatch.comm.flags = 0;
+ dispatch.status = 0;
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_PDU)
+ fprintf(stderr, "DSO init %s->"PRINTF_P_PFX"%p() domain=%d challenge: pmda_interface=0x%x pmapi_version=%d\n",
+ init, initp, dispatch.domain,
+ dispatch.comm.pmda_interface,
+ (~dispatch.comm.pmapi_version) & 0xff);
+#endif
+ dispatch.domain = domain;
+
+ (*initp)(&dispatch);
+
+ if (dispatch.status != 0) {
+ printf("Error: initialization routine \"%s\" failed in DSO \"%s\": %s\n",
+ init, dso, pmErrStr(dispatch.status));
+ dispatch.status = -1;
+ dlclose(handle);
+ }
+ else {
+ if (dispatch.comm.pmda_interface < PMDA_INTERFACE_2 ||
+ dispatch.comm.pmda_interface > PMDA_INTERFACE_LATEST) {
+
+ printf("Error: Unsupported PMDA interface version %d returned by DSO \"%s\"\n",
+ dispatch.comm.pmda_interface, dso);
+ dispatch.status = -1;
+ dlclose(handle);
+ }
+ if (dispatch.comm.pmapi_version != PMAPI_VERSION_2) {
+ printf("Error: Unsupported PMAPI version %d returned by DSO \"%s\"\n",
+ dispatch.comm.pmapi_version, dso);
+ dispatch.status = -1;
+ dlclose(handle);
+ }
+ }
+
+ if (dispatch.status == 0) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_PDU) {
+ fprintf(stderr, "DSO has domain=%d", dispatch.domain);
+ fprintf(stderr, " pmda_interface=%d pmapi_version=%d\n",
+ dispatch.comm.pmda_interface,
+ dispatch.comm.pmapi_version);
+ }
+#endif
+ dsoname = strdup(dso);
+ connmode = CONN_DSO;
+ reset_profile();
+
+ if (myPmdaName != NULL)
+ free(myPmdaName);
+ myPmdaName = strdup(dso);
+
+ /*
+ * set here once and used by all subsequent calls into the
+ * PMDA
+ */
+ if (dispatch.comm.pmda_interface >= PMDA_INTERFACE_5)
+ dispatch.version.four.ext->e_context = 0;
+ }
+ }
+ }
+#else /* ! HAVE_DLOPEN */
+ dispatch.status = -1;
+
+ fprintf(stderr, "opendso: %s: No dynamic DSO/DLL support on this platform\n", dso);
+#endif
+}
+
+void
+closedso(void)
+{
+ if (dsoname != NULL) {
+ if (dispatch.comm.pmda_interface >= PMDA_INTERFACE_5) {
+ if (dispatch.version.four.ext->e_endCallBack != NULL) {
+ (*(dispatch.version.four.ext->e_endCallBack))(0);
+ }
+ }
+#ifdef HAVE_DLOPEN
+ dlclose(handle);
+#endif
+ free(dsoname);
+ dsoname = NULL;
+ connmode = NO_CONN;
+ }
+}
+
+/*
+ * Do a descriptor pdu.
+ * Abstracted here for several calls.
+ */
+int
+dodso_desc(pmID pmid, pmDesc *desc)
+{
+ int sts;
+
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_PDU)
+ fprintf(stderr, "DSO desc()\n");
+#endif
+ sts = dispatch.version.any.desc(pmid, desc, dispatch.version.four.ext);
+
+#ifdef PCP_DEBUG
+ if (sts >= 0 && (pmDebug & DBG_TRACE_PDU))
+ __pmPrintDesc(stdout, desc);
+#endif
+
+ return sts;
+}/*dodso_desc*/
+
+
+void
+dodso(int pdu)
+{
+ int sts = 0; /* initialize to pander to gcc */
+ int length;
+ pmDesc desc;
+ pmDesc *desc_list = NULL;
+ pmResult *result;
+ __pmInResult *inresult;
+ int i;
+ int j;
+ char *buffer;
+ struct timeval start;
+ struct timeval end;
+ char name[32];
+ char **namelist;
+ int *statuslist;
+ pmID pmid;
+
+ if (timer != 0)
+ __pmtimevalNow(&start);
+
+ switch (pdu) {
+
+ case PDU_DESC_REQ:
+ printf("PMID: %s\n", pmIDStr(param.pmid));
+ if ((sts = dodso_desc(param.pmid, &desc)) >= 0)
+ __pmPrintDesc(stdout, &desc);
+ else
+ printf("Error: DSO desc() failed: %s\n", pmErrStr(sts));
+ break;
+
+ case PDU_FETCH:
+ printf("PMID(s):");
+ for (i = 0; i < param.numpmid; i++)
+ printf(" %s", pmIDStr(param.pmidlist[i]));
+ putchar('\n');
+
+ if (get_desc) {
+ desc_list = (pmDesc *)malloc(param.numpmid * sizeof(pmDesc));
+ if (desc_list == NULL) {
+ printf("Error: DSO fetch() failed: %s\n", pmErrStr(ENOMEM));
+ return;
+ }
+ for (i = 0; i < param.numpmid; i++) {
+ if ((sts = dodso_desc(param.pmidlist[i], &desc_list[i])) < 0) {
+ printf("Error: DSO desc() failed: %s\n", pmErrStr(sts));
+ free(desc_list);
+ return;
+ }
+ }
+ }
+ sts = 0;
+ if (profile_changed) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_PDU)
+ fprintf(stderr, "DSO profile()\n");
+#endif
+ sts = dispatch.version.any.profile(profile, dispatch.version.any.ext);
+ if (sts < 0)
+ printf("Error: DSO profile() failed: %s\n", pmErrStr(sts));
+ else
+ profile_changed = 0;
+ }
+ if (sts >= 0) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_PDU)
+ fprintf(stderr, "DSO fetch()\n");
+#endif
+ sts = dispatch.version.any.fetch(param.numpmid, param.pmidlist,
+ &result, dispatch.version.any.ext);
+ if (sts >= 0) {
+ if (desc_list)
+ _dbDumpResult(stdout, result, desc_list);
+ else
+ __pmDumpResult(stdout, result);
+ /*
+ * DSO PMDA will manage the pmResult skelton, but
+ * we need to free the pmValueSets and values here
+ */
+ __pmFreeResultValues(result);
+ }
+ else {
+ printf("Error: DSO fetch() failed: %s\n", pmErrStr(sts));
+ }
+ }
+ if (desc_list)
+ free(desc_list);
+ break;
+
+ case PDU_INSTANCE_REQ:
+ printf("pmInDom: %s\n", pmInDomStr(param.indom));
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_PDU)
+ fprintf(stderr, "DSO instance()\n");
+#endif
+
+ sts = dispatch.version.any.instance(param.indom, param.number,
+ param.name, &inresult,
+ dispatch.version.any.ext);
+ if (sts >= 0)
+ printindom(stdout, inresult);
+ else
+ printf("Error: DSO instance() failed: %s\n", pmErrStr(sts));
+ break;
+
+ case PDU_RESULT:
+
+ printf("PMID: %s\n", pmIDStr(param.pmid));
+ printf("Getting description...\n");
+ desc_list = &desc;
+ if ((sts = dodso_desc(param.pmid, desc_list)) < 0) {
+ printf("Error: DSO desc() failed: %s\n", pmErrStr(sts));
+ return;
+ }
+
+ if (profile_changed) {
+ printf("Sending Profile...\n");
+ sts = dispatch.version.any.profile(profile, dispatch.version.any.ext);
+ if (sts < 0) {
+ printf("Error: DSO profile() failed: %s\n", pmErrStr(sts));
+ return;
+ }
+ else
+ profile_changed = 0;
+ }
+
+ printf("Getting Result Structure...\n");
+ sts = dispatch.version.any.fetch(1, &(desc.pmid), &result,
+ dispatch.version.any.ext);
+ if (sts < 0) {
+ printf("Error: DSO fetch() failed: %s\n", pmErrStr(sts));
+ return;
+ }
+
+#ifdef PCP_DEBUG
+ else if (pmDebug & DBG_TRACE_FETCH)
+ _dbDumpResult(stdout, result, desc_list);
+#endif
+
+ sts = fillResult(result, desc.type);
+ if (sts < 0) {
+ pmFreeResult(result);
+ return;
+ }
+
+ sts = dispatch.version.any.store(result, dispatch.version.any.ext);
+ if (sts < 0)
+ printf("Error: DSO store() failed: %s\n", pmErrStr(sts));
+
+ break;
+
+ case PDU_TEXT_REQ:
+ if (param.number == PM_TEXT_PMID) {
+ printf("PMID: %s\n", pmIDStr(param.pmid));
+ i = param.pmid;
+ }
+ else {
+ printf("pmInDom: %s\n", pmInDomStr(param.indom));
+ i = param.indom;
+ }
+
+ for (j = 0; j < 2; j++) {
+
+ if (j == 0)
+ param.number |= PM_TEXT_ONELINE;
+ else {
+ param.number &= ~PM_TEXT_ONELINE;
+ param.number |= PM_TEXT_HELP;
+ }
+
+ sts = dispatch.version.any.text(i, param.number, &buffer, dispatch.version.any.ext);
+ if (sts >= 0) {
+ if (j == 0) {
+ if (*buffer != '\0')
+ printf("[%s]\n", buffer);
+ else
+ printf("[<no one line help text specified>]\n");
+ }
+ else if (*buffer != '\0')
+ printf("%s\n", buffer);
+ else
+ printf("<no help text specified>\n");
+ }
+ else
+ printf("Error: DSO text() failed: %s\n", pmErrStr(sts));
+ }
+ break;
+
+ case PDU_PMNS_IDS:
+ if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) {
+ printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface);
+ break;
+ }
+ printf("PMID: %s\n", pmIDStr(param.pmid));
+ sts = dispatch.version.four.name(param.pmid, &namelist, dispatch.version.four.ext);
+ if (sts > 0) {
+ for (i = 0; i < sts; i++) {
+ printf(" %s\n", namelist[i]);
+ }
+ free(namelist);
+ }
+ else if (sts == 0)
+ printf("Warning: DSO name() returns 0\n");
+ else
+ printf("Error: DSO name() failed: %s\n", pmErrStr(sts));
+ break;
+
+ case PDU_PMNS_NAMES:
+ if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) {
+ printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface);
+ break;
+ }
+ printf("Metric: %s\n", param.name);
+ sts = dispatch.version.four.pmid(param.name, &pmid, dispatch.version.four.ext);
+ if (sts >= 0)
+ printf(" %s\n", pmIDStr(pmid));
+ else
+ printf("Error: DSO pmid() failed: %s\n", pmErrStr(sts));
+ break;
+
+ case PDU_PMNS_CHILD:
+ if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) {
+ printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface);
+ break;
+ }
+ printf("Metric: %s\n", param.name);
+ sts = dispatch.version.four.children(param.name, 0, &namelist, &statuslist, dispatch.version.four.ext);
+ if (sts > 0) {
+ for (i = 0; i < sts; i++) {
+ printf(" %8.8s %s\n", statuslist[i] == 1 ? "non-leaf" : "leaf", namelist[i]);
+ }
+ free(namelist);
+ free(statuslist);
+ }
+ else if (sts == 0)
+ printf("Warning: DSO children() returns 0\n");
+ else
+ printf("Error: DSO children() failed: %s\n", pmErrStr(sts));
+ break;
+
+ case PDU_PMNS_TRAVERSE:
+ if (dispatch.comm.pmda_interface < PMDA_INTERFACE_4) {
+ printf("Error: PMDA Interface %d does not support dynamic metric names\n", dispatch.comm.pmda_interface);
+ break;
+ }
+ printf("Metric: %s\n", param.name);
+ sts = dispatch.version.four.children(param.name, 1, &namelist, &statuslist, dispatch.version.four.ext);
+ if (sts > 0) {
+ for (i = 0; i < sts; i++) {
+ printf(" %8.8s %s\n", statuslist[i] == 1 ? "non-leaf" : "leaf", namelist[i]);
+ }
+ free(namelist);
+ free(statuslist);
+ }
+ else if (sts == 0)
+ printf("Warning: DSO children() returns 0\n");
+ else
+ printf("Error: DSO children() failed: %s\n", pmErrStr(sts));
+ break;
+
+ case PDU_AUTH:
+ if (dispatch.comm.pmda_interface < PMDA_INTERFACE_6) {
+ printf("Error: PMDA Interface %d does not support authentication\n", dispatch.comm.pmda_interface);
+ break;
+ }
+ j = param.number; /* attribute key */
+ buffer = param.name; /* attribute value */
+ if (buffer)
+ length = strlen(buffer) + 1; /* length of value */
+ else
+ length = 0;
+ i = 0; /* client ID */
+
+ __pmAttrKeyStr_r(j, name, sizeof(name)-1);
+ name[sizeof(name)-1] = '\0';
+
+ printf("Attribute: %s=%s\n", name, buffer ? buffer : "''");
+ sts = dispatch.version.six.attribute(i, j, buffer, length, dispatch.version.six.ext);
+ if (sts >= 0)
+ printf("Success\n");
+ else
+ printf("Error: DSO attribute() failed: %s\n", pmErrStr(sts));
+ break;
+
+ default:
+ printf("Error: DSO PDU (%s) botch!\n", __pmPDUTypeStr(pdu));
+ break;
+ }
+
+ if (sts >= 0 && timer != 0) {
+ __pmtimevalNow(&end);
+ printf("Timer: %f seconds\n", __pmtimevalSub(&end, &start));
+ }
+}
diff --git a/src/dbpmda/src/gram.y b/src/dbpmda/src/gram.y
new file mode 100644
index 0000000..b9a83a6
--- /dev/null
+++ b/src/dbpmda/src/gram.y
@@ -0,0 +1,634 @@
+/*
+ * Copyright (c) 2013 Red Hat.
+ * Copyright (c) 1995 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 "./dbpmda.h"
+#include "./lex.h"
+
+extern int stmt_type;
+
+static union {
+ pmID whole;
+ __pmID_int part;
+} pmid;
+
+static union {
+ pmInDom whole;
+ __pmInDom_int part;
+} indom;
+
+
+static int sts;
+static int inst;
+static char *str;
+static char warnStr[80];
+
+param_t param;
+
+/*
+ * pmidp may contain a dynamic PMID ... if so, ask the PMDA to
+ * translate name if possible
+ */
+static int
+fix_dynamic_pmid(char *name, pmID *pmidp)
+{
+ int sts;
+ __pmPDU *pb;
+ extern int outfd;
+ extern int infd;
+ extern pmdaInterface dispatch;
+
+ if (pmid_domain(*pmidp) == DYNAMIC_PMID && pmid_item(*pmidp) == 0) {
+ if (connmode == CONN_DSO) {
+ if (dispatch.comm.pmda_interface >= PMDA_INTERFACE_4) {
+ sts = dispatch.version.four.pmid(name, pmidp, dispatch.version.four.ext);
+ if (sts < 0) return sts;
+ }
+ }
+ else if (connmode == CONN_DAEMON) {
+ sts = __pmSendNameList(outfd, FROM_ANON, 1, &name, NULL);
+ if (sts < 0) return sts;
+ sts = __pmGetPDU(infd, ANY_SIZE, TIMEOUT_NEVER, &pb);
+ if (sts < 0) return sts;
+ if (sts == PDU_PMNS_IDS) {
+ int xsts;
+ sts = __pmDecodeIDList(pb, 1, pmidp, &xsts);
+ __pmUnpinPDUBuf(pb);
+ if (sts < 0) return sts;
+ return xsts;
+ }
+ else if (sts == PDU_ERROR) {
+ __pmDecodeError(pb, &sts);
+ __pmUnpinPDUBuf(pb);
+ return sts;
+ }
+ }
+ }
+ return 0;
+}
+
+
+%}
+
+%union {
+ char *y_str;
+ int y_num;
+ twodot_num y_2num;
+ threedot_num y_3num;
+ }
+
+%token <y_2num>
+ NUMBER2D
+
+%token <y_3num>
+ NUMBER3D
+
+%token <y_num>
+ NUMBER
+ NEGNUMBER
+ FLAG
+
+%token <y_str>
+ NAME
+ PATHNAME
+ MACRO
+ STRING
+
+%term COMMA EQUAL
+ OPEN CLOSE DESC GETDESC FETCH INSTANCE PROFILE HELP
+ WATCH DBG QUIT STATUS STORE INFO TIMER NAMESPACE WAIT
+ PMNS_NAME PMNS_PMID PMNS_CHILDREN PMNS_TRAVERSE ATTR
+ DSO PIPE SOCK UNIX INET IPV6
+ ADD DEL ALL NONE INDOM ON OFF
+ PLUS EOL
+
+%type <y_num>
+ metric
+ indom
+ optdomain
+ debug
+ raw_pmid
+ attribute
+ servport
+
+%type <y_str>
+ fname
+ arglist
+ inst
+
+%%
+
+stmt : OPEN EOL {
+ param.number = OPEN; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | OPEN DSO fname NAME optdomain EOL {
+ opendso($3, $4, $5);
+ stmt_type = OPEN; YYACCEPT;
+ }
+ | OPEN PIPE fname arglist {
+ openpmda($3);
+ stmt_type = OPEN; YYACCEPT;
+ }
+ | OPEN SOCK fname {
+ open_unix_socket($3);
+ stmt_type = OPEN; YYACCEPT;
+ }
+ | OPEN SOCK UNIX fname {
+ open_unix_socket($4);
+ stmt_type = OPEN; YYACCEPT;
+ }
+ | OPEN SOCK INET servport {
+ open_inet_socket($4);
+ stmt_type = OPEN; YYACCEPT;
+ }
+ | OPEN SOCK IPV6 servport {
+ open_ipv6_socket($4);
+ stmt_type = OPEN; YYACCEPT;
+ }
+ | CLOSE EOL {
+ stmt_type = CLOSE; YYACCEPT;
+ }
+ | DESC EOL {
+ param.number = DESC; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | DESC metric EOL {
+ param.pmid = $2;
+ stmt_type = DESC; YYACCEPT;
+ }
+ | FETCH EOL {
+ param.number = FETCH; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | FETCH metriclist EOL {
+ stmt_type = FETCH; YYACCEPT;
+ }
+ | STORE EOL {
+ param.number = STORE; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | STORE metric STRING EOL {
+ param.name = $3;
+ param.pmid = (pmID)$2;
+ stmt_type = STORE; YYACCEPT;
+ }
+ | INFO EOL {
+ param.number = INFO; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | INFO metric EOL {
+ param.number = PM_TEXT_PMID;
+ param.pmid = (pmID)$2;
+ stmt_type = INFO; YYACCEPT;
+ }
+ | INFO INDOM indom EOL {
+ param.number = PM_TEXT_INDOM;
+ param.indom = indom.whole;
+ stmt_type = INFO; YYACCEPT;
+ }
+ | INSTANCE EOL {
+ param.number = INSTANCE; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | INSTANCE indom EOL {
+ param.indom = indom.whole;
+ param.number = PM_IN_NULL;
+ param.name = NULL;
+ stmt_type = INSTANCE; YYACCEPT;
+ }
+ | INSTANCE indom NUMBER EOL {
+ param.indom = indom.whole;
+ param.number = $3;
+ param.name = NULL;
+ stmt_type = INSTANCE; YYACCEPT;
+ }
+ | INSTANCE indom inst EOL {
+ param.indom = indom.whole;
+ param.number = PM_IN_NULL;
+ param.name = $3;
+ stmt_type = INSTANCE; YYACCEPT;
+ }
+ | PROFILE EOL {
+ param.number = PROFILE; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | PROFILE indom ALL EOL {
+ sts = pmAddProfile($2, 0, NULL);
+ if (sts < 0) {
+ yyerror(pmErrStr(sts));
+ YYERROR;
+ }
+ profile_changed = 1;
+ stmt_type = EOL;
+ YYACCEPT;
+ }
+ | PROFILE indom NONE EOL {
+ sts = pmDelProfile($2, 0, NULL);
+ if (sts < 0) {
+ yyerror(pmErrStr(sts));
+ YYERROR;
+ }
+ profile_changed = 1;
+ stmt_type = EOL;
+ YYACCEPT;
+ }
+ | PROFILE indom ADD NUMBER EOL {
+ inst = $4;
+ sts = pmAddProfile($2, 1, &inst);
+ if (sts < 0) {
+ yyerror(pmErrStr(sts));
+ YYERROR;
+ }
+ profile_changed = 1;
+ stmt_type = EOL;
+ YYACCEPT;
+ }
+ | PROFILE indom DEL NUMBER EOL {
+ inst = $4;
+ sts = pmDelProfile($2, 1, &inst);
+ if (sts < 0) {
+ yyerror(pmErrStr(sts));
+ YYERROR;
+ }
+ profile_changed = 1;
+ stmt_type = EOL;
+ YYACCEPT;
+ }
+ | WATCH EOL {
+ param.number = WATCH; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | WATCH fname EOL {
+ watch($2);
+ stmt_type = WATCH; YYACCEPT;
+ }
+ | PMNS_NAME EOL {
+ param.number = PMNS_NAME; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | PMNS_NAME raw_pmid EOL {
+ param.pmid = $2;
+ stmt_type = PMNS_NAME; YYACCEPT;
+ }
+ | PMNS_PMID EOL {
+ param.number = PMNS_PMID; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | PMNS_PMID NAME EOL {
+ param.name = $2;
+ stmt_type = PMNS_PMID; YYACCEPT;
+ }
+ | PMNS_CHILDREN EOL {
+ param.number = PMNS_CHILDREN; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | PMNS_CHILDREN NAME EOL {
+ param.name = $2;
+ stmt_type = PMNS_CHILDREN; YYACCEPT;
+ }
+ | PMNS_TRAVERSE EOL {
+ param.number = PMNS_TRAVERSE; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | PMNS_TRAVERSE NAME EOL {
+ param.name = $2;
+ stmt_type = PMNS_TRAVERSE; YYACCEPT;
+ }
+ | NAMESPACE fname EOL {
+ param.name = $2;
+ stmt_type = NAMESPACE; YYACCEPT;
+ }
+ | ATTR EOL {
+ param.number = ATTR; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | ATTR attribute EOL {
+ param.number = $2;
+ param.name = NULL;
+ stmt_type = ATTR; YYACCEPT;
+ }
+ | ATTR attribute STRING EOL {
+ param.number = $2;
+ param.name = $3;
+ stmt_type = ATTR; YYACCEPT;
+ }
+
+ | HELP EOL {
+ param.number = -1; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP CLOSE EOL {
+ param.number = CLOSE; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP DBG EOL {
+ param.number = DBG; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP DESC EOL {
+ param.number = DESC; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP FETCH EOL {
+ param.number = FETCH; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP GETDESC EOL {
+ param.number = GETDESC; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP INFO EOL {
+ param.number = INFO; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP INSTANCE EOL {
+ param.number = INSTANCE; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP NAMESPACE EOL {
+ param.number = NAMESPACE; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP OPEN EOL {
+ param.number = OPEN; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP PMNS_CHILDREN EOL {
+ param.number = PMNS_CHILDREN; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP PMNS_NAME EOL {
+ param.number = PMNS_NAME; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP PMNS_PMID EOL {
+ param.number = PMNS_PMID; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP PMNS_TRAVERSE EOL {
+ param.number = PMNS_TRAVERSE; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP ATTR EOL {
+ param.number = ATTR; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP PROFILE EOL {
+ param.number = PROFILE; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP QUIT EOL {
+ param.number = QUIT; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP STATUS EOL {
+ param.number = STATUS; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP STORE EOL {
+ param.number = STORE; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP TIMER EOL {
+ param.number = TIMER; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP WAIT EOL {
+ param.number = WAIT; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | HELP WATCH EOL {
+ param.number = WATCH; param.pmid = HELP_FULL;
+ stmt_type = HELP; YYACCEPT;
+ }
+
+ | QUIT EOL { stmt_type = QUIT; YYACCEPT; }
+ | DBG EOL {
+ param.number = DBG; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | DBG ALL EOL {
+ param.number = -1;
+ stmt_type = DBG; YYACCEPT;
+ }
+ | DBG NONE EOL {
+ param.number = 0;
+ stmt_type = DBG; YYACCEPT;
+ }
+ | DBG debug EOL {
+ param.number = $2;
+ stmt_type = DBG; YYACCEPT;
+ }
+ | STATUS EOL {
+ stmt_type = STATUS; YYACCEPT;
+ }
+ | TIMER EOL {
+ param.number = TIMER; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | TIMER ON EOL {
+ timer = 1; stmt_type = EOL; YYACCEPT;
+ }
+ | TIMER OFF EOL {
+ timer = 0; stmt_type = EOL; YYACCEPT;
+ }
+ | GETDESC EOL {
+ param.number = GETDESC; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | GETDESC ON EOL {
+ get_desc = 1; stmt_type = EOL; YYACCEPT;
+ }
+ | GETDESC OFF EOL {
+ get_desc = 0; stmt_type = EOL; YYACCEPT;
+ }
+ | WAIT EOL {
+ param.number = WAIT; param.pmid = HELP_USAGE;
+ stmt_type = HELP; YYACCEPT;
+ }
+ | WAIT NUMBER EOL {
+ stmt_type = EOL; sleep($2); YYACCEPT;
+ }
+ | EOL { stmt_type = EOL; YYACCEPT; }
+ | {
+ if (yywrap())
+ YYACCEPT;
+ else {
+ yyerror("Unrecognized command");
+ YYERROR;
+ }
+ }
+ ;
+
+fname : NAME { $$ = strcons("./", $1); }
+ | PATHNAME { $$ = $1; }
+ ;
+
+optdomain : NUMBER { $$ = $1; }
+ | /* nothing */ { $$ = 0; }
+ ;
+
+attribute : NUMBER {
+ sts = __pmAttrKeyStr_r($1, warnStr, sizeof(warnStr));
+ if (sts <= 0) {
+ sprintf(warnStr, "Attribute (%d) is not recognised", $1);
+ yyerror(warnStr);
+ YYERROR;
+ }
+ $$ = $1;
+ }
+ | STRING {
+ sts = __pmLookupAttrKey($1, strlen($1)+1);
+ if (sts <= 0) {
+ sprintf(warnStr, "Attribute (%s) is not recognised", $1);
+ yyerror(warnStr);
+ YYERROR;
+ }
+ $$ = sts;
+ }
+ ;
+
+servport : NUMBER { $$ = $1; }
+ | STRING {
+ struct servent *srv = getservbyname($1, NULL);
+ if (srv == NULL) {
+ sprintf(warnStr, "Failed to map (%s) to a port number", $1);
+ yyerror(warnStr);
+ YYERROR;
+ }
+ sprintf(warnStr, "Mapped %s to port number %d", $1, srv->s_port);
+ yywarn(warnStr);
+ $$ = srv->s_port;
+ }
+ ;
+
+metric : NUMBER {
+ pmid.whole = $1;
+ sts = pmNameID(pmid.whole, &str);
+ if (sts < 0) {
+ sprintf(warnStr, "PMID (%s) is not defined in the PMNS",
+ pmIDStr(pmid.whole));
+ yywarn(warnStr);
+ }
+ else
+ free(str);
+ $$ = (int)pmid.whole;
+ }
+ | NUMBER2D {
+ pmid.whole = 0;
+ pmid.part.cluster = $1.num1;
+ pmid.part.item = $1.num2;
+ sts = pmNameID(pmid.whole, &str);
+ if (sts < 0) {
+ sprintf(warnStr, "PMID (%s) is not defined in the PMNS",
+ pmIDStr(pmid.whole));
+ yywarn(warnStr);
+ }
+ else
+ free(str);
+ $$ = (int)pmid.whole;
+ }
+ | NUMBER3D {
+ pmid.whole = 0;
+ pmid.part.domain = $1.num1;
+ pmid.part.cluster = $1.num2;
+ pmid.part.item = $1.num3;
+ sts = pmNameID(pmid.whole, &str);
+ if (sts < 0) {
+ sprintf(warnStr, "PMID (%s) is not defined in the PMNS",
+ pmIDStr(pmid.whole));
+ yywarn(warnStr);
+ }
+ else
+ free(str);
+ $$ = (int)pmid.whole;
+ }
+ | NAME {
+ sts = pmLookupName(1, &$1, &pmid.whole);
+ if (sts < 0) {
+ yyerror(pmErrStr(sts));
+ YYERROR;
+ }
+ sts = fix_dynamic_pmid($1, &pmid.whole);
+ if (sts < 0) {
+ yyerror(pmErrStr(sts));
+ YYERROR;
+ }
+ $$ = (int)pmid.whole;
+ }
+ ;
+
+indom : NUMBER {
+ indom.whole = $1;
+ $$ = (int)indom.whole;
+ }
+ | NEGNUMBER {
+ indom.whole = $1;
+ $$ = (int)indom.whole;
+ }
+ | NUMBER2D {
+ indom.whole = 0;
+ indom.part.domain = $1.num1;
+ indom.part.serial = $1.num2;
+ $$ = (int)indom.whole;
+ }
+ ;
+
+raw_pmid: NUMBER3D {
+ pmid.whole = 0;
+ pmid.part.domain = $1.num1;
+ pmid.part.cluster = $1.num2;
+ pmid.part.item = $1.num3;
+ $$ = (int)pmid.whole;
+ }
+ ;
+
+metriclist : metric { addmetriclist((pmID)$1); }
+ | metriclist metric { addmetriclist((pmID)$2); }
+ | metriclist COMMA metric { addmetriclist((pmID)$3); }
+ ;
+
+
+arglist : /* nothing, a trick */ { doargs(); }
+ ;
+
+inst : STRING { $$ = $1; }
+ | NAME { $$ = $1; }
+ ;
+
+debug : NUMBER { $$ = $1; }
+ | NAME {
+ sts = __pmParseDebug($1);
+ if (sts < 0) {
+ sprintf(warnStr, "Bad debug flag (%s)", $1);
+ yywarn(warnStr);
+ YYERROR;
+ }
+ $$ = sts;
+ }
+ | NUMBER debug { $$ = $1 | $2; }
+ | NAME debug {
+ sts = __pmParseDebug($1);
+ if (sts < 0) {
+ sprintf(warnStr, "Bad debug flag (%s)", $1);
+ yywarn(warnStr);
+ YYERROR;
+ }
+ $$ = sts | $2;
+ }
+ ;
+
+%%
diff --git a/src/dbpmda/src/lex.h b/src/dbpmda/src/lex.h
new file mode 100644
index 0000000..7426571
--- /dev/null
+++ b/src/dbpmda/src/lex.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1995 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
+ */
+#ifndef _LEX_H
+#define _LEX_H
+
+typedef struct {
+ int num1;
+ int num2;
+}twodot_num;
+
+typedef struct {
+ int num1;
+ int num2;
+ int num3;
+}threedot_num;
+
+#endif
diff --git a/src/dbpmda/src/lex.l b/src/dbpmda/src/lex.l
new file mode 100644
index 0000000..2a9cebf
--- /dev/null
+++ b/src/dbpmda/src/lex.l
@@ -0,0 +1,611 @@
+/*
+ * Copyright (c) 2013 Red Hat.
+ * Copyright (c) 1995-2003 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"
+
+static int lineno = 0;
+static int using_readline = 0;
+
+#include "./lex.h"
+
+#ifdef HAVE_READLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+
+#ifdef FLEX_SCANNER
+#include "./gram.tab.h"
+static int dbpmdaFlexInput (char *, int);
+#else
+#include "./gram.h"
+#endif
+
+#include "./dbpmda.h"
+
+%}
+
+%s FNAME
+%a 2200
+
+%option noinput
+%option nounput
+
+%{
+#ifdef FLEX_SCANNER
+#ifndef YY_NO_UNPUT
+#define YY_NO_UNPUT
+#endif
+#undef YY_INPUT
+#define YY_INPUT(b,r,ms) (r=dbpmdaFlexInput(b, ms))
+#else
+#undef input
+#undef unput
+#undef yywrap
+#undef yyinput
+#endif
+%}
+
+%%
+
+add { return ADD; }
+all { return ALL; }
+attr { return ATTR; }
+attribute { return ATTR; }
+children { return PMNS_CHILDREN; }
+close { return CLOSE; }
+debug { return DBG; }
+delete { return DEL; }
+desc { return DESC; }
+dso { BEGIN FNAME; return DSO; }
+exit { return QUIT; }
+fetch { return FETCH; }
+getdesc { return GETDESC; }
+help { return HELP; }
+indom { return INDOM; }
+inet { return INET; }
+instance { return INSTANCE; }
+ipv6 { return IPV6; }
+name { return PMNS_NAME; }
+namespace { BEGIN FNAME; return NAMESPACE; }
+none { return NONE; }
+off { return OFF; }
+on { return ON; }
+open { return OPEN; }
+pipe { BEGIN FNAME; return PIPE; }
+pmid { return PMNS_PMID; }
+profile { return PROFILE; }
+q { return QUIT; }
+quit { return QUIT; }
+socket { BEGIN FNAME; return SOCK; }
+status { return STATUS; }
+store { return STORE; }
+text { return INFO; }
+timer { return TIMER; }
+traverse { return PMNS_TRAVERSE; }
+unix { return UNIX; }
+wait { return WAIT; }
+watch { BEGIN FNAME; return WATCH; }
+\? { return HELP; }
+\= { return EQUAL; }
+\, { return COMMA; }
+\+ { return PLUS; }
+
+[A-Za-z][A-Za-z0-9_\./:-]* {
+ yylval.y_str = (char *)malloc(yyleng+1);
+ strcpy(yylval.y_str, yytext);
+ return NAME;
+ }
+
+\$[A-Za-z][A-Za-z0-9_-]* {
+ yylval.y_str = (char *)malloc(yyleng+1);
+ strcpy(yylval.y_str, yytext);
+ return MACRO;
+ }
+
+0[xX][0-9]+ {
+ yylval.y_num = (int)strtol(&yytext[2], NULL, 16);
+ return NUMBER;
+ }
+
+[0-9]+ {
+ yylval.y_num = atoi(yytext);
+ return NUMBER;
+ }
+
+-[0-9]+ {
+ yylval.y_num = atoi(yytext);
+ return NEGNUMBER;
+ }
+
+[0-9]+\.[0-9]+ {
+ sscanf(yytext, "%d.%d", &yylval.y_2num.num1,
+ &yylval.y_2num.num2);
+ return NUMBER2D;
+ }
+
+[0-9]+\.[0-9]+\.[0-9]+ {
+ sscanf(yytext, "%d.%d.%d", &yylval.y_3num.num1,
+ &yylval.y_3num.num2, &yylval.y_3num.num3);
+ return NUMBER3D;
+ }
+
+
+\"[^\"\n][^\"\n]*\" {
+ yylval.y_str = (char *)malloc(yyleng-1);
+ strncpy(yylval.y_str, &yytext[1], yyleng-2);
+ yylval.y_str[yyleng-2] = '\0';
+ return STRING;
+ }
+
+\"[^\"\n][^\"\n]*\n {
+ yyerror("Expected \"");
+ }
+
+\#.*\n { return EOL; }
+
+[\r\t ]+ { }
+
+\n { return EOL; }
+
+<FNAME>[^\t \n]+ {
+ yylval.y_str = (char *)malloc(yyleng+1);
+ strcpy(yylval.y_str, yytext);
+ BEGIN 0;
+ return PATHNAME;
+ }
+
+
+. {
+ yyerror("Illegal character");
+ }
+%%
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+static char *prompt = "dbpmda";
+static char *line = NULL;
+static int lastc = '\n';
+static int linepos = 0;
+static int linelen = 0;
+static int mark = -1;
+
+extern char *configfile;
+
+extern int eflag;
+extern int iflag;
+
+#ifdef FLEX_SCANNER
+
+static int
+dbpmdaGetc (char * inbuf)
+{
+ int inch;
+
+#ifdef HAVE_READLINE
+ char rl_prompt_storage[64];
+ char *rl_prompt = rl_prompt_storage;
+ static char *str = NULL;
+ static int strpos = 0;
+
+ if (using_readline) {
+ if (iflag)
+ snprintf(rl_prompt_storage, 64, "%s> ", prompt);
+ else
+ rl_prompt = NULL;
+
+ rl_instream = yyin;
+
+ if (!str) {
+ do {
+ str = readline(rl_prompt);
+ if (!str) {
+ /* EOF */
+ inbuf[0] = inch = '\0';
+ goto done;
+ }
+ } while (!str[0]);
+ }
+
+ inch = str[strpos++];
+ if (inch == '\r')
+ inch = str[strpos++];
+
+ if (!inch) {
+ /* end of input line, fake out \n so parser notices */
+ inch = '\n';
+ /* and setup to call readline() next time */
+ free(str);
+ str = NULL;
+ strpos = 0;
+ }
+
+ inbuf[0] = inch;
+ goto done;
+ }
+ /* else fall through to the non-readline method */
+#endif
+
+ while ((inch = fgetc (yyin)) != EOF) {
+ inbuf[0] = inch & 0xFFU;
+ if (inbuf[0] == '\r') {
+ /* for windows, eat carriage returns */
+ continue;
+ }
+ if (eflag) {
+ putchar(inch);
+ fflush(stdout);
+ }
+ break;
+ }
+ if (inch == EOF)
+ inch = '\0';
+
+#ifdef HAVE_READLINE
+done:
+#endif
+#ifdef DESPERATE
+ fprintf(stderr, "dbpmdaGetc: yyin=%p (%d) using_readline=%d lastc=%x \"%c\" inch=%x \"%c\"\n", yyin, fileno(yyin), using_readline, lastc & 0xff, lastc, inch & 0xff, inch);
+#endif
+ return inch;
+}
+
+static int
+dbpmdaFlexInput (char * inbuf, int ms)
+{
+ static FILE * inf = NULL;
+ static int first = 1;
+ static int save_iflag, save_eflag;
+
+ if (first) {
+ first = 0;
+ if (!access (".dbpmdarc", R_OK)) {
+ inf = yyin;
+ if ((yyin = fopen (".dbpmdarc", "r")) != NULL) {
+ save_eflag = eflag;
+ save_iflag = iflag;
+ eflag = 1;
+ iflag = 1;
+ prompt = ".dbpmdarc";
+ configfile = ".dbpmdarc";
+ lineno = 0;
+ } else {
+ yyin = inf;
+ }
+ }
+#ifdef HAVE_READLINE
+ else {
+ using_readline = isatty(fileno(yyin));
+ }
+#endif
+ }
+
+ if (lastc == '\n') {
+#ifdef HAVE_READLINE
+ if (line != NULL && *line != '\0' && *line != '\n') {
+ /* line is not empty, push it into history */
+ char *newline = strchr(line, '\n');
+ if (newline != NULL) *newline = '\0';
+ add_history(line);
+ if (newline != NULL) *newline = '\n';
+ }
+#endif
+ if (iflag && !using_readline) {
+ printf ("%s> ", prompt);
+ fflush (stdout);
+ }
+ lineno++;
+ linepos = 0;
+ }
+
+ if (linepos == linelen) {
+ linelen = (linelen) ? linelen * 2 : 128;
+ if ((line = (char *)realloc(line, linelen * sizeof(char))) == NULL) {
+ fprintf(stderr, "%s: Lexer internal error\n", pmProgname);
+ exit(1);
+ }
+ }
+
+ if (ms > 0) {
+ while (1) {
+ if ((lastc = dbpmdaGetc(inbuf))) {
+ line[linepos++] = inbuf[0];
+ return (1);
+ } else {
+ /* It maybe an EOF */
+ if ((inf != NULL) && (inf != yyin)) {
+ yyin = inf;
+ lineno = 1;
+#ifdef HAVE_READLINE
+ using_readline = isatty(fileno(yyin));
+#endif
+ prompt = "dbpmda";
+ configfile = NULL;
+ iflag = save_iflag;
+ if (iflag) {
+ if (using_readline)
+ putchar('\n');
+ else
+ printf("%s> ", prompt);
+ fflush(stdout);
+ }
+ eflag = save_eflag;
+ } else {
+ return 0;
+ }
+ }
+ }
+ }
+
+ return ms;
+}
+
+#else /* AT&T Lex */
+
+static char peekc = '\0';
+
+char
+input(void)
+{
+ int get;
+ static int first = 1;
+ static int save_eflag;
+ static int save_iflag;
+ static int inrc;
+
+ if (first) {
+ if (access(".dbpmdarc", R_OK) == 0) {
+ int fd = open(".dbpmdarc", O_RDONLY);
+ if (fd >= 0) {
+ inrc = dup(0);
+ close(0);
+ dup(fd);
+ close(fd);
+ save_eflag = eflag;
+ save_iflag = iflag;
+ eflag = 1;
+ iflag = 1;
+ prompt = ".dbpmdarc";
+ configfile = ".dbpmdarc";
+ }
+ }
+ }
+
+ if (peekc) {
+ lastc = peekc;
+ peekc = '\0';
+ return lastc;
+ }
+
+ again:
+ if (lastc == '\n' || first) {
+ if (iflag) {
+ printf("%s> ", prompt);
+ fflush(stdout);
+ }
+ if (first)
+ first = 0;
+ else
+ lineno++;
+ linepos = 0;
+ }
+ else if (lastc == '\0') {
+ linepos = 0;
+ return lastc;
+ }
+
+ if (linepos == linelen) {
+ if (linelen == 0)
+ linelen = 128;
+ else
+ linelen *= 2;
+ line = (char*)realloc(line, linelen * sizeof(char));
+ }
+
+ get = getchar();
+
+ line[linepos++] = (char)get;
+
+ if (get == EOF) {
+ if (inrc) {
+ close(0);
+ dup(inrc);
+ close(inrc);
+ inrc = 0;
+ eflag = save_eflag;
+ iflag = save_iflag;
+ prompt = "dbpmda";
+ configfile = NULL;
+ putchar('\n');
+ lineno = 0;
+ lastc = '\n';
+ goto again;
+ }
+ lastc = '\0';
+ }
+ else {
+ lastc = get;
+ if (eflag) {
+ putchar(lastc);
+ fflush(stdout);
+ }
+ }
+
+ return lastc;
+}
+
+void
+unput(char c)
+{
+ peekc = c;
+}
+#endif
+
+int
+yywrap(void)
+{
+ return lastc == '\0';
+}
+
+char
+lastinput(void)
+{
+ return lastc;
+}
+
+int
+markpos(void)
+{
+ mark = linepos;
+ return mark;
+}
+
+void
+locateError(void)
+{
+ int i;
+
+ if (mark < 0) {
+ fprintf(stderr, "%s: Unrecoverable internal error in locateError()\n",
+ pmProgname);
+ exit(1);
+ }
+
+ for (i = 0; prompt[i]; i++)
+ putchar(' ');
+
+ putchar(' ');
+
+ for (i = 0; i < mark; i++) {
+ if (line[i] == '\t')
+ putchar('\t');
+ else if (line[i] == '\n' || line[i] == '\0')
+ break;
+ else
+ putchar(' ');
+ }
+
+ putchar('^');
+ printf(" at or near here\n");
+ fflush(stdout);
+}
+
+
+void
+doargs(void)
+{
+ /*
+ * a hack ... slide underneath lex/yacc to do the cmd-line args
+ */
+ char buf[256]; /* big enough for a single arg? */
+ char *p;
+ char c;
+ char delim = '\0';
+
+ initarglist();
+
+ if (lastc == '\n') {
+ addarglist(NULL);
+ return;
+ }
+
+ p = buf;
+ for ( ; ; ) {
+#ifdef FLEX_SCANNER
+ dbpmdaFlexInput (&c, 1);
+#else
+ c = input();
+#endif
+ if (delim) {
+ if (c == delim) {
+ delim = '\0';
+ continue;
+ }
+ }
+ else if (c == ' ' || c == '\t' || c == '\n' || c == '\0') {
+ if (p > buf) {
+ *p = '\0';
+ addarglist(buf);
+ p = buf;
+ }
+ if (c == '\n' || c == '\0') {
+ /*
+ * EOL removed from grammar after arglist, so no
+ * need push \n or \0 back into the input stream
+ * (which was not working well!)
+ */
+ addarglist(NULL);
+ return;
+ }
+ continue;
+ }
+ else if (c == '"' || c == '\'') {
+ delim = c;
+ continue;
+ }
+ *p++ = c;
+ }
+}
+
+void
+yywarn(char *s)
+{
+ extern int lineno;
+
+ if (configfile == NULL)
+ fprintf(stderr, "Warning: %s\n", s);
+ else
+ fprintf(stderr, "Warning [%s, line %d]\n%s\n",
+ configfile, lineno, s);
+}
+
+void
+yyerror(const char *s)
+{
+ extern int lineno;
+ extern int stmt_type;
+ char c;
+
+ markpos();
+
+ c = lastinput();
+ for ( ; ; ) {
+ if (c == '\0')
+ break;
+ if (c == '\n')
+ break;
+#ifdef FLEX_SCANNER
+ dbpmdaFlexInput (&c, 1);
+#else
+ c = input();
+#endif
+ }
+ stmt_type = EOL;
+
+ locateError();
+
+ if (configfile == NULL)
+ fprintf(stderr, "Error: %s\nType 'help' for a list of commands.\n", s);
+ else
+ fprintf(stderr,
+ "Error [%s, line %d]: %s\nType 'help' for a list of commands.\n",
+ configfile, lineno, s);
+
+
+}
diff --git a/src/dbpmda/src/pmda.c b/src/dbpmda/src/pmda.c
new file mode 100644
index 0000000..d9b454b
--- /dev/null
+++ b/src/dbpmda/src/pmda.c
@@ -0,0 +1,840 @@
+/*
+ * Copyright (c) 2013 Red Hat.
+ * Copyright (c) 1995,2003,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.
+ */
+
+#include <sys/stat.h>
+#include "pmapi.h"
+#include "impl.h"
+
+#ifdef HAVE_VALUES_H
+#include <values.h>
+#endif
+#include <float.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
+#include "./dbpmda.h"
+#include "./lex.h"
+#include "./gram.h"
+
+static __pmTimeval now = { 0, 0 };
+
+int infd;
+int outfd;
+char *myPmdaName = 0;
+
+extern int _creds_timeout;
+
+#ifndef HAVE_STRTOLL
+/*
+ * cheap hack ...won't work for large values!
+ */
+static __int64_t
+strtoll(char *p, char **endp, int base)
+{
+ return (__int64_t)strtol(p, endp, base);
+}
+#endif
+
+#ifndef HAVE_STRTOULL
+/*
+ * cheap hack ...won't work for large values!
+ */
+static __uint64_t
+strtoull(char *p, char **endp, int base)
+{
+ return (__uint64_t)strtoul(p, endp, base);
+}
+#endif
+
+/* version exchange - get a credentials PDU from 2.0 agents */
+
+static int
+agent_creds(__pmPDU *pb)
+{
+ int i;
+ int sts = 0;
+ int version = UNKNOWN_VERSION;
+ int credcount = 0;
+ int sender = 0;
+ int vflag = 0;
+ __pmCred *credlist = NULL;
+
+ if ((sts = __pmDecodeCreds(pb, &sender, &credcount, &credlist)) < 0)
+ return sts;
+
+ for (i = 0; i < credcount; i++) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_CONTEXT)
+ fprintf(stderr, "agent_creds: doing cred #%d from PID %d\n", i+1, sender);
+#endif
+ switch(credlist[i].c_type) {
+ case CVERSION:
+ version = credlist[i].c_vala;
+ vflag = 1;
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_CONTEXT)
+ fprintf(stderr, "agent_creds: version cred (%u)\n", version);
+#endif
+ break;
+ }
+ }
+
+ if (credlist)
+ free(credlist);
+
+ if (((sts = __pmSetVersionIPC(infd, version)) < 0) ||
+ ((sts = __pmSetVersionIPC(outfd, version)) < 0))
+ return sts;
+
+ if (vflag) { /* complete the version exchange - respond to agent */
+ __pmCred handshake[1];
+
+ handshake[0].c_type = CVERSION;
+ handshake[0].c_vala = PDU_VERSION;
+ handshake[0].c_valb = 0;
+ handshake[0].c_valc = 0;
+ if ((sts = __pmSendCreds(outfd, (int)getpid(), 1, handshake)) < 0)
+ return sts;
+ }
+
+ return 0;
+}
+
+static void
+pmdaversion(void)
+{
+ int sts;
+ __pmPDU *ack;
+ int pinpdu;
+
+ pinpdu = sts = __pmGetPDU(infd, ANY_SIZE, _creds_timeout, &ack);
+ if (sts == PDU_CREDS) {
+ if ((sts = agent_creds(ack)) < 0) {
+ fprintf(stderr, "Warning: version exchange failed "
+ "for PMDA %s: %s\n", myPmdaName, pmErrStr(sts));
+ }
+ }
+ else {
+ if (sts < 0)
+ fprintf(stderr, "__pmGetPDU(%d): %s\n", infd, pmErrStr(sts));
+ else
+ fprintf(stderr, "pmdaversion: expecting PDU_CREDS, got PDU type %d\n", sts);
+ fprintf(stderr, "Warning: no version exchange with PMDA %s\n",
+ myPmdaName);
+ }
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(ack);
+}
+
+void
+openpmda(char *fname)
+{
+ int i;
+ struct stat buf;
+
+ if (stat(fname, &buf) < 0) {
+ fprintf(stderr, "openpmda: %s: %s\n", fname, osstrerror());
+ return;
+ }
+
+ closepmda();
+ free(param.argv[0]);
+ param.argv[0] = strdup(fname);
+ param.argc--;
+ printf("Start %s PMDA: %s", basename(param.argv[0]), fname);
+ for (i = 1; i < param.argc; i++)
+ printf(" %s", param.argv[i]);
+ putchar('\n');
+
+ if (__pmProcessCreate(param.argv, &infd, &outfd) < (pid_t)0) {
+ fprintf(stderr, "openpmda: create process: %s\n", osstrerror());
+ }
+ else {
+ connmode = CONN_DAEMON;
+ reset_profile();
+ if (myPmdaName != NULL)
+ free(myPmdaName);
+ myPmdaName = strdup(fname);
+ pmdaversion();
+ }
+}
+
+#ifdef HAVE_STRUCT_SOCKADDR_UN
+void
+open_unix_socket(char *fname)
+{
+ int fd;
+ struct stat buf;
+ struct sockaddr_un s_un;
+ int len;
+
+ if (stat(fname, &buf) < 0) {
+ fprintf(stderr, "opensocket: %s: %s\n", fname, osstrerror());
+ return;
+ }
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ fprintf(stderr, "opensocket: socket: %s\n", netstrerror());
+ return;
+ }
+
+ memset(&s_un, 0, sizeof(s_un));
+ s_un.sun_family = AF_UNIX;
+ strncpy(s_un.sun_path, fname, strlen(fname));
+ len = (int)offsetof(struct sockaddr_un, sun_path) + (int)strlen(s_un.sun_path);
+
+ closepmda();
+
+ if (connect(fd, (struct sockaddr *)&s_un, len) < 0) {
+ fprintf(stderr, "opensocket: connect: %s\n", netstrerror());
+ close(fd);
+ return;
+ }
+
+ infd = fd;
+ outfd = fd;
+
+ printf("Connect to PMDA on socket %s\n", fname);
+
+ connmode = CONN_DAEMON;
+ reset_profile();
+ if (myPmdaName != NULL)
+ free(myPmdaName);
+ myPmdaName = strdup(fname);
+ pmdaversion();
+}
+#else
+void
+open_unix_socket(char *fname)
+{
+ __pmNotifyErr(LOG_CRIT, "UNIX domain sockets unsupported\n");
+}
+#endif
+
+static void
+open_socket(int port, int family, const char *protocol)
+{
+ __pmSockAddr *addr;
+ int fd, sts;
+ char socket[64];
+
+ fd = (family == AF_INET) ? __pmCreateSocket() : __pmCreateIPv6Socket();
+ if (fd < 0) {
+ fprintf(stderr, "opensocket: socket: %s\n", netstrerror());
+ return;
+ }
+
+ addr = __pmLoopBackAddress(family);
+ if (addr == NULL) {
+ fprintf(stderr, "opensocket: loopback: %s\n", netstrerror());
+ __pmCloseSocket(fd);
+ return;
+ }
+
+ closepmda();
+
+ __pmSockAddrSetPort(addr, port);
+ sts = __pmConnect(fd, addr, __pmSockAddrSize());
+ __pmSockAddrFree(addr);
+
+ if (sts < 0) {
+ fprintf(stderr, "opensocket: connect: %s\n", netstrerror());
+ __pmCloseSocket(fd);
+ return;
+ }
+
+ infd = fd;
+ outfd = fd;
+
+ sprintf(socket, "%s port %d", protocol, port);
+ printf("Connect to PMDA on %s\n", socket);
+
+ connmode = CONN_DAEMON;
+ reset_profile();
+ if (myPmdaName != NULL)
+ free(myPmdaName);
+ myPmdaName = strdup(socket);
+ pmdaversion();
+}
+
+void
+open_inet_socket(int port)
+{
+ open_socket(port, AF_INET, "inet");
+}
+
+void
+open_ipv6_socket(int port)
+{
+ open_socket(port, AF_INET6, "ipv6");
+}
+
+void
+closepmda(void)
+{
+ if (connmode != NO_CONN) {
+ /* End of context logic mimics PMCD, no error checking is needed. */
+ __pmSendError(outfd, FROM_ANON, PM_ERR_NOTCONN);
+ close(outfd);
+ close(infd);
+ __pmResetIPC(infd);
+ connmode = NO_CONN;
+ if (myPmdaName != NULL) {
+ free(myPmdaName);
+ myPmdaName = NULL;
+ }
+ }
+}
+
+
+int
+dopmda_desc(pmID pmid, pmDesc *desc, int print)
+{
+ int sts;
+ __pmPDU *pb;
+ int i;
+ int pinpdu;
+
+ if ((sts = __pmSendDescReq(outfd, FROM_ANON, pmid)) >= 0) {
+ if ((pinpdu = sts = __pmGetPDU(infd, ANY_SIZE, TIMEOUT_NEVER, &pb)) == PDU_DESC) {
+ if ((sts = __pmDecodeDesc(pb, desc)) >= 0) {
+ if (print)
+ __pmPrintDesc(stdout, desc);
+#ifdef PCP_DEBUG
+ else if (pmDebug & DBG_TRACE_PDU)
+ __pmPrintDesc(stdout, desc);
+#endif
+ }
+ else
+ printf("Error: __pmDecodeDesc() failed: %s\n", pmErrStr(sts));
+ }
+ else if (sts == PDU_ERROR) {
+ if ((i = __pmDecodeError(pb, &sts)) >= 0)
+ printf("Error PDU: %s\n", pmErrStr(sts));
+ else
+ printf("Error: __pmDecodeError() failed: %s\n", pmErrStr(i));
+ }
+ else if (sts == 0)
+ printf("Error: __pmGetPDU() failed: PDU empty, PMDA may have died\n");
+ else
+ printf("Error: __pmGetPDU() failed: wrong PDU (%x)\n", sts);
+
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+ }
+ else
+ printf("Error: __pmSendDescReq() failed: %s\n", pmErrStr(sts));
+
+ return sts;
+}
+
+void
+dopmda(int pdu)
+{
+ int sts;
+ pmDesc desc;
+ pmDesc *desc_list = NULL;
+ pmResult *result = NULL;
+ __pmInResult *inresult;
+ __pmPDU *pb;
+ int i;
+ int j;
+ int ident;
+ int length;
+ char *buffer;
+ struct timeval start;
+ struct timeval end;
+ char name[32];
+ char **namelist;
+ int *statuslist;
+ int numnames;
+ pmID pmid;
+ int pinpdu;
+
+ if (timer != 0)
+ __pmtimevalNow(&start);
+
+ switch (pdu) {
+
+ case PDU_DESC_REQ:
+ printf("PMID: %s\n", pmIDStr(param.pmid));
+ sts = dopmda_desc(param.pmid, &desc, 1);
+ break;
+
+ case PDU_FETCH:
+ printf("PMID(s):");
+ for (i = 0; i < param.numpmid; i++)
+ printf(" %s", pmIDStr(param.pmidlist[i]));
+ putchar('\n');
+
+ if (get_desc) {
+ desc_list = (pmDesc *)malloc(param.numpmid * sizeof(pmDesc));
+ if (desc_list == NULL) {
+ printf("Error: PDU fetch() failed: %s\n", pmErrStr(ENOMEM));
+ return;
+ }
+ for (i = 0; i < param.numpmid; i++) {
+ if ((sts = dopmda_desc(param.pmidlist[i], &desc_list[i], 0)) < 0) {
+ free(desc_list);
+ return;
+ }
+ }
+ }
+
+ sts = 0;
+ if (profile_changed) {
+ if ((sts = __pmSendProfile(outfd, FROM_ANON, 0, profile)) < 0)
+ printf("Error: __pmSendProfile() failed: %s\n", pmErrStr(sts));
+ else
+ profile_changed = 0;
+ }
+ if (sts >= 0) {
+ if ((sts = __pmSendFetch(outfd, FROM_ANON, 0, NULL, param.numpmid, param.pmidlist)) >= 0) {
+ if ((pinpdu = sts = __pmGetPDU(infd, ANY_SIZE, TIMEOUT_NEVER, &pb)) == PDU_RESULT) {
+ if ((sts = __pmDecodeResult(pb, &result)) >= 0) {
+ if (get_desc)
+ _dbDumpResult(stdout, result, desc_list);
+ else
+ __pmDumpResult(stdout, result);
+ pmFreeResult(result);
+ }
+ else
+ printf("Error: __pmDecodeResult() failed: %s\n", pmErrStr(sts));
+ }
+ else if (sts == PDU_ERROR) {
+ if ((i = __pmDecodeError(pb, &sts)) >= 0)
+ printf("Error PDU: %s\n", pmErrStr(sts));
+ else
+ printf("Error: __pmDecodeError() failed: %s\n", pmErrStr(i));
+ }
+ else if (sts == 0)
+ printf("Error: __pmGetPDU() failed: PDU empty, PMDA may have died\n");
+ else
+ printf("Error: __pmGetPDU() failed: wrong PDU (%x)\n", sts);
+
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+ }
+ else
+ printf("Error: __pmSendFetch() failed: %s\n", pmErrStr(sts));
+ }
+ if (desc_list)
+ free(desc_list);
+ break;
+
+ case PDU_INSTANCE_REQ:
+ printf("pmInDom: %s\n", pmInDomStr(param.indom));
+ if ((sts = __pmSendInstanceReq(outfd, FROM_ANON, &now, param.indom, param.number, param.name)) >= 0) {
+ if ((pinpdu = sts = __pmGetPDU(infd, ANY_SIZE, TIMEOUT_NEVER, &pb)) == PDU_INSTANCE) {
+ if ((sts = __pmDecodeInstance(pb, &inresult)) >= 0) {
+ printindom(stdout, inresult);
+ __pmFreeInResult(inresult);
+ }
+ else
+ printf("Error: __pmDecodeInstance() failed: %s\n", pmErrStr(sts));
+ }
+ else if (sts == PDU_ERROR) {
+ if ((i = __pmDecodeError(pb, &sts)) >= 0)
+ printf("Error PDU: %s\n", pmErrStr(sts));
+ else
+ printf("Error: __pmDecodeError() failed: %s\n", pmErrStr(i));
+ }
+ else
+ printf("Error: __pmGetPDU() failed: %s\n", pmErrStr(sts));
+
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+ }
+ else
+ printf("Error: __pmSendInstanceReq() failed: %s\n", pmErrStr(sts));
+ break;
+
+ case PDU_RESULT:
+ printf("PMID: %s\n", pmIDStr(param.pmid));
+
+ printf("Getting description...\n");
+
+ if ((sts = dopmda_desc(param.pmid, &desc, 0)) < 0)
+ return;
+
+ if (profile_changed) {
+ printf("Sending Profile...\n");
+ if ((sts = __pmSendProfile(outfd, FROM_ANON, 0, profile)) < 0) {
+ printf("Error: __pmSendProfile() failed: %s\n", pmErrStr(sts));
+ return;
+ }
+ else
+ profile_changed = 0;
+ }
+
+ printf("Getting Result Structure...\n");
+ pinpdu = 0;
+ if ((sts = __pmSendFetch(outfd, FROM_ANON, 0, NULL,
+ 1, &(desc.pmid))) >= 0) {
+ if ((pinpdu = sts = __pmGetPDU(infd, ANY_SIZE, TIMEOUT_NEVER,
+ &pb)) == PDU_RESULT) {
+ if ((sts = __pmDecodeResult(pb, &result)) < 0)
+ printf("Error: __pmDecodeResult() failed: %s\n",
+ pmErrStr(sts));
+#ifdef PCP_DEBUG
+ else if (pmDebug & DBG_TRACE_FETCH)
+ __pmDumpResult(stdout, result);
+#endif
+ }
+ else if (sts == PDU_ERROR) {
+ if ((i = __pmDecodeError(pb, &sts)) >= 0)
+ printf("Error PDU: %s\n", pmErrStr(sts));
+ else
+ printf("Error: __pmDecodeError() failed: %s\n", pmErrStr(i));
+ }
+ else
+ printf("Error: __pmGetPDU() failed: %s\n", pmErrStr(sts));
+ }
+ else
+ printf("Error: __pmSendFetch() failed: %s\n", pmErrStr(sts));
+ /*
+ * pb is still pinned, and result may contain pointers into
+ * a second PDU buffer from __pmDecodeResult() ... need to
+ * ensure all PDU buffers are unpinned once we're done with
+ * result or giving up
+ */
+
+ if (sts < 0) {
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+ return;
+ }
+
+ if ((sts = fillResult(result, desc.type)) < 0) {
+ pmFreeResult(result);
+ __pmUnpinPDUBuf(pb);
+ return;
+ }
+
+ printf("Sending Result...\n");
+ sts = __pmSendResult(outfd, FROM_ANON, result);
+ pmFreeResult(result);
+ __pmUnpinPDUBuf(pb);
+ if (sts >= 0) {
+ if ((pinpdu = sts = __pmGetPDU(infd, ANY_SIZE, TIMEOUT_NEVER,
+ &pb)) == PDU_ERROR) {
+ if ((i = __pmDecodeError(pb, &sts)) >= 0) {
+ if (sts < 0)
+ printf("Error PDU: %s\n", pmErrStr(sts));
+ }
+ else
+ printf("Error: __pmDecodeError() failed: %s\n", pmErrStr(i));
+ }
+ else
+ printf("Error: __pmGetPDU() failed: %s\n", pmErrStr(sts));
+
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+ }
+ else
+ printf("Error: __pmSendResult() failed: %s\n", pmErrStr(sts));
+
+ break;
+
+ case PDU_TEXT_REQ:
+ if (param.number == PM_TEXT_PMID) {
+ printf("PMID: %s\n", pmIDStr(param.pmid));
+ ident = param.pmid;
+ }
+ else {
+ printf("pmInDom: %s\n", pmInDomStr(param.indom));
+ ident = param.indom;
+ }
+
+ for (j = 0; j < 2; j++) {
+
+ if (j == 0)
+ param.number |= PM_TEXT_ONELINE;
+ else {
+ param.number &= ~PM_TEXT_ONELINE;
+ param.number |= PM_TEXT_HELP;
+ }
+
+ if ((sts = __pmSendTextReq(outfd, FROM_ANON, ident, param.number)) >= 0) {
+ if ((pinpdu = sts = __pmGetPDU(infd, ANY_SIZE, TIMEOUT_NEVER, &pb)) == PDU_TEXT) {
+ if ((sts = __pmDecodeText(pb, &i, &buffer)) >= 0) {
+ if (j == 0) {
+ if (*buffer != '\0')
+ printf("[%s]\n", buffer);
+ else
+ printf("[<no one line help text specified>]\n");
+ }
+ else if (*buffer != '\0')
+ printf("%s\n", buffer);
+ else
+ printf("<no help text specified>\n");
+ free(buffer);
+ }
+ else
+ printf("Error: __pmDecodeText() failed: %s\n", pmErrStr(sts));
+ }
+ else if (sts == PDU_ERROR) {
+ if ((i = __pmDecodeError(pb, &sts)) >= 0)
+ printf("Error PDU: %s\n", pmErrStr(sts));
+ else
+ printf("Error: __pmDecodeError() failed: %s\n", pmErrStr(i));
+ }
+ else
+ printf("Error: __pmGetPDU() failed: %s\n", pmErrStr(sts));
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+
+ }
+ else
+ printf("Error: __pmSendTextReq() failed: %s\n", pmErrStr(sts));
+
+ }
+ break;
+
+ case PDU_PMNS_IDS:
+ printf("PMID: %s\n", pmIDStr(param.pmid));
+ if ((sts = __pmSendIDList(outfd, FROM_ANON, 1, &param.pmid, 0)) >= 0) {
+ if ((pinpdu = sts = __pmGetPDU(infd, ANY_SIZE, TIMEOUT_NEVER, &pb)) == PDU_PMNS_NAMES) {
+ if ((sts = __pmDecodeNameList(pb, &numnames, &namelist, NULL)) >= 0) {
+ for (i = 0; i < sts; i++) {
+ printf(" %s\n", namelist[i]);
+ }
+ free(namelist);
+ }
+ else
+ printf("Error: __pmDecodeNameList() failed: %s\n", pmErrStr(sts));
+ }
+ else if (sts == PDU_ERROR) {
+ if ((i = __pmDecodeError(pb, &sts)) >= 0)
+ printf("Error PDU: %s\n", pmErrStr(sts));
+ else
+ printf("Error: __pmDecodeError() failed: %s\n", pmErrStr(i));
+ }
+ else
+ printf("Error: __pmGetPDU() failed: %s\n", pmErrStr(sts));
+
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+ }
+ else
+ printf("Error: __pmSendIDList() failed: %s\n", pmErrStr(sts));
+ break;
+
+ case PDU_PMNS_NAMES:
+ printf("Metric: %s\n", param.name);
+ if ((sts = __pmSendNameList(outfd, FROM_ANON, 1, &param.name, NULL)) >= 0) {
+ if ((pinpdu = sts = __pmGetPDU(infd, ANY_SIZE, TIMEOUT_NEVER, &pb)) == PDU_PMNS_IDS) {
+ int xsts;
+
+ if ((sts = __pmDecodeIDList(pb, 1, &pmid, &xsts)) >= 0)
+ printf(" %s\n", pmIDStr(pmid));
+ else
+ printf("Error: __pmDecodeIDList() failed: %s\n", pmErrStr(sts));
+ }
+ else if (sts == PDU_ERROR) {
+ if ((i = __pmDecodeError(pb, &sts)) >= 0)
+ printf("Error PDU: %s\n", pmErrStr(sts));
+ else
+ printf("Error: __pmDecodeError() failed: %s\n", pmErrStr(i));
+ }
+ else
+ printf("Error: __pmGetPDU() failed: %s\n", pmErrStr(sts));
+
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+ }
+ else
+ printf("Error: __pmSendIDList() failed: %s\n", pmErrStr(sts));
+ break;
+
+ case PDU_PMNS_CHILD:
+ printf("Metric: %s\n", param.name);
+ if ((sts = __pmSendChildReq(outfd, FROM_ANON, param.name, 1)) >= 0) {
+ if ((pinpdu = sts = __pmGetPDU(infd, ANY_SIZE, TIMEOUT_NEVER, &pb)) == PDU_PMNS_NAMES) {
+ if ((sts = __pmDecodeNameList(pb, &numnames, &namelist, &statuslist)) >= 0) {
+ for (i = 0; i < numnames; i++) {
+ printf(" %8.8s %s\n", statuslist[i] == 1 ? "non-leaf" : "leaf", namelist[i]);
+ }
+ free(namelist);
+ free(statuslist);
+ }
+ else
+ printf("Error: __pmDecodeNameList() failed: %s\n", pmErrStr(sts));
+ }
+ else if (sts == PDU_ERROR) {
+ if ((i = __pmDecodeError(pb, &sts)) >= 0)
+ printf("Error PDU: %s\n", pmErrStr(sts));
+ else
+ printf("Error: __pmDecodeError() failed: %s\n", pmErrStr(i));
+ }
+ else
+ printf("Error: __pmGetPDU() failed: %s\n", pmErrStr(sts));
+
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+ }
+ else
+ printf("Error: __pmSendChildReq() failed: %s\n", pmErrStr(sts));
+ break;
+
+ case PDU_PMNS_TRAVERSE:
+ printf("Metric: %s\n", param.name);
+ if ((sts = __pmSendTraversePMNSReq(outfd, FROM_ANON, param.name)) >= 0) {
+ if ((pinpdu = sts = __pmGetPDU(infd, ANY_SIZE, TIMEOUT_NEVER, &pb)) == PDU_PMNS_NAMES) {
+ if ((sts = __pmDecodeNameList(pb, &numnames, &namelist, NULL)) >= 0) {
+ for (i = 0; i < numnames; i++) {
+ printf(" %s\n", namelist[i]);
+ }
+ free(namelist);
+ }
+ else
+ printf("Error: __pmDecodeNameList() failed: %s\n", pmErrStr(sts));
+ }
+ else if (sts == PDU_ERROR) {
+ if ((i = __pmDecodeError(pb, &sts)) >= 0)
+ printf("Error PDU: %s\n", pmErrStr(sts));
+ else
+ printf("Error: __pmDecodeError() failed: %s\n", pmErrStr(i));
+ }
+ else
+ printf("Error: __pmGetPDU() failed: %s\n", pmErrStr(sts));
+
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+ }
+ else
+ printf("Error: __pmSendTraversePMNS() failed: %s\n", pmErrStr(sts));
+ break;
+
+ case PDU_AUTH:
+ j = param.number; /* attribute key */
+ buffer = param.name; /* attribute value */
+ length = !buffer ? 0 : strlen(buffer) + 1; /* value length */
+ i = 0; /* client ID */
+
+ __pmAttrKeyStr_r(j, name, sizeof(name)-1);
+ name[sizeof(name)-1] = '\0';
+
+ printf("Attribute: %s=%s\n", name, buffer ? buffer : "''");
+ if ((sts = __pmSendAuth(outfd, 0 /* context */, j, buffer, length)) >= 0)
+ printf("Success\n");
+ else
+ printf("Error: __pmSendAuth() failed: %s\n", pmErrStr(sts));
+ break;
+
+ default:
+ printf("Error: Daemon PDU (%s) botch!\n", __pmPDUTypeStr(pdu));
+ sts = PDU_ERROR;
+ break;
+ }
+
+ if (sts >= 0 && timer != 0) {
+ __pmtimevalNow(&end);
+ printf("Timer: %f seconds\n", __pmtimevalSub(&end, &start));
+ }
+}
+
+int
+fillResult(pmResult *result, int type)
+{
+ int i;
+ int sts = 0;
+ pmAtomValue atom;
+ pmValueSet *vsp;
+ char *endbuf = NULL;
+
+ switch(type) {
+ case PM_TYPE_32:
+ atom.l = (int)strtol(param.name, &endbuf, 10);
+ break;
+ case PM_TYPE_U32:
+ atom.ul = (unsigned int)strtoul(param.name, &endbuf, 10);
+ break;
+ case PM_TYPE_64:
+ atom.ll = strtoll(param.name, &endbuf, 10);
+ break;
+ case PM_TYPE_U64:
+ atom.ull = strtoull(param.name, &endbuf, 10);
+ break;
+ case PM_TYPE_FLOAT:
+ atom.d = strtod(param.name, &endbuf);
+ if (atom.d < FLT_MIN || atom.d > FLT_MAX)
+ sts = -ERANGE;
+ else {
+ atom.f = atom.d;
+ }
+ break;
+ case PM_TYPE_DOUBLE:
+ atom.d = strtod(param.name, &endbuf);
+ break;
+ case PM_TYPE_STRING:
+ atom.cp = (char *)malloc(strlen(param.name) + 1);
+ if (atom.cp == NULL)
+ sts = -ENOMEM;
+ else {
+ strcpy(atom.cp, param.name);
+ endbuf = "";
+ }
+ break;
+ default:
+ printf("Error: dbpmda does not support storing into %s metrics\n", pmTypeStr(type));
+ sts = PM_ERR_TYPE;
+ }
+
+ if (sts < 0) {
+ if (sts != PM_ERR_TYPE)
+ printf("Error: Decoding value: %s\n", pmErrStr(sts));
+ }
+ else if (endbuf != NULL && *endbuf != '\0') {
+ printf("Error: Value \"%s\" is incompatible with metric type (PM_TYPE_%s)\n",
+ param.name, pmTypeStr(type));
+ sts = PM_ERR_VALUE;
+ }
+
+ if (sts >= 0) {
+ vsp = result->vset[0];
+
+ if (vsp->numval == 0) {
+ printf("Error: %s not available!\n", pmIDStr(param.pmid));
+ return PM_ERR_VALUE;
+ }
+
+ if (vsp->numval < 0) {
+ printf("Error: %s: %s\n", pmIDStr(param.pmid), pmErrStr(vsp->numval));
+ return vsp->numval;
+ }
+
+ for (i = 0; i < vsp->numval; i++) {
+ if (vsp->numval > 1)
+ printf("%s [%d]: ", pmIDStr(param.pmid), i);
+ else
+ printf("%s: ", pmIDStr(param.pmid));
+
+ pmPrintValue(stdout, vsp->valfmt, type, &vsp->vlist[i], 1);
+ vsp->valfmt = __pmStuffValue(&atom, &vsp->vlist[i], type);
+ printf(" -> ");
+ pmPrintValue(stdout, vsp->valfmt, type, &vsp->vlist[i], 1);
+ putchar('\n');
+ }
+ }
+
+ return sts;
+}
+
diff --git a/src/dbpmda/src/util.c b/src/dbpmda/src/util.c
new file mode 100644
index 0000000..c81832a
--- /dev/null
+++ b/src/dbpmda/src/util.c
@@ -0,0 +1,587 @@
+/*
+ * Copyright (c) 2013 Red Hat.
+ * Copyright (c) 1995-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 "./dbpmda.h"
+#include "./lex.h"
+#include "./gram.h"
+
+extern pmdaInterface dispatch;
+extern int infd;
+extern int outfd;
+
+__pmProfile *profile;
+int profile_changed;
+int timer;
+int get_desc;
+
+static pmID *pmidlist;
+static int numpmid;
+static __pmContext *ctxp;
+
+static char **argv;
+static int argc;
+
+/*
+ * Warning: order of these strings _must_ match bit field sequence defined
+ * in impl.h for DBG_TRACE_* macros
+ */
+static char* debugFlags[] = {
+ "pdu", "fetch", "profile", "value", "context", "indom", "pdubuf", "log",
+ "logmeta", "optfetch", "af", "appl0", "appl1", "appl2", "pmns", "libpmda",
+ "timecontrol", "pmc", "derive", "lock", "interp", "config", "loop", "fault"
+};
+
+static int numFlags = sizeof(debugFlags)/sizeof(debugFlags[0]);
+
+void
+reset_profile(void)
+{
+ if ((profile = (__pmProfile *)realloc(profile, sizeof(__pmProfile))) == NULL) {
+ __pmNoMem("reset_profile", sizeof(__pmProfile), PM_FATAL_ERR);
+ exit(1);
+ }
+ ctxp->c_instprof = profile;
+ memset(profile, 0, sizeof(__pmProfile));
+ profile->state = PM_PROFILE_INCLUDE; /* default global state */
+ profile_changed = 1;
+}
+
+void
+setup_context(void)
+{
+ int sts;
+#ifdef PM_MULTI_THREAD
+ pthread_mutex_t save_c_lock;
+#endif
+
+ if ((sts = pmNewContext(PM_CONTEXT_LOCAL, NULL)) < 0) {
+ fprintf(stderr, "setup_context: creation failed: %s\n", pmErrStr(sts));
+ exit(1);
+ }
+
+ ctxp = __pmHandleToPtr(sts);
+ if (ctxp == NULL) {
+ fprintf(stderr, "botch: setup_context: __pmHandleToPtr(%d) returns NULL!\n", sts);
+ exit(1);
+ }
+ /*
+ * Note: ctxp->c_lock remains locked throughout ... setup_context()
+ * is only called once, and a single context is used throughout
+ * to "fake" out the connection to the current PMDA ... so
+ * there is no PM_UNLOCK(ctxp->c_lock) anywhere in the dbpmda
+ * code.
+ * This works because ctxp->c_lock is a recursive lock and
+ * dbpmda is single-threaded.
+ */
+
+#ifdef PM_MULTI_THREAD
+ /* need to be careful about the initialized lock */
+ save_c_lock = ctxp->c_lock;
+#endif
+ memset(ctxp, 0, sizeof(__pmContext));
+#ifdef PM_MULTI_THREAD
+ ctxp->c_lock = save_c_lock;
+#endif
+ ctxp->c_type = PM_CONTEXT_HOST;
+ reset_profile();
+}
+
+char *
+strcons(char *s1, char *s2)
+{
+ int i;
+ char *buf;
+
+ i = (int)strlen(s1) + (int)strlen(s2) + 1;
+
+ buf = (char *)malloc(i);
+ if (buf == NULL) {
+ fprintf(stderr, "strcons: malloc failed: %s\n", osstrerror());
+ exit(1);
+ }
+
+ strcpy(buf, s1);
+ strcat(buf, s2);
+
+ return buf;
+}
+
+char *
+strnum(int n)
+{
+ char *buf;
+
+ buf = (char *)malloc(13);
+ if (buf == NULL) {
+ fprintf(stderr, "strnum: malloc failed: %s\n", osstrerror());
+ exit(1);
+ }
+ sprintf(buf, "%d", n);
+ return buf;
+}
+
+void
+initmetriclist(void)
+{
+ param.numpmid = 0;
+ param.pmidlist = NULL;
+}
+
+void
+addmetriclist(pmID pmid)
+{
+ param.numpmid++;
+
+ if (param.numpmid >= numpmid) {
+ numpmid = param.numpmid;
+ pmidlist = (pmID *)realloc(pmidlist, numpmid * sizeof(pmidlist[0]));
+ if (pmidlist == NULL) {
+ fprintf(stderr, "addmetriclist: realloc failed: %s\n", osstrerror());
+ exit(1);
+ }
+ }
+
+ pmidlist[param.numpmid-1] = pmid;
+ param.pmidlist = pmidlist;
+}
+
+void
+initarglist(void)
+{
+ int i;
+
+ for (i = 0; i < param.argc; i++)
+ if (param.argv[i] != NULL)
+ free(param.argv[i]);
+ param.argc = 0;
+ param.argv = NULL;
+ addarglist("");
+}
+
+void
+addarglist(char *arg)
+{
+ param.argc++;
+
+ if (param.argc >= argc) {
+ argc = param.argc;
+ argv = (char **)realloc(argv, argc * sizeof(pmProgname));
+ if (argv == NULL) {
+ fprintf(stderr, "addarglist: realloc failed: %s\n", osstrerror());
+ exit(1);
+ }
+ }
+
+ if (arg != NULL)
+ argv[param.argc-1] = strdup(arg);
+ else
+ argv[param.argc-1] = arg;
+ param.argv = argv;
+}
+
+void
+watch(char *fname)
+{
+ char cmd[200];
+
+ sprintf(cmd, "xterm -hold -title \"dbpmda watch %s\" -geom 80x16 -bg dodgerblue4 -e tail -f %s &",
+ fname, fname);
+
+ if (system(cmd) != 0)
+ fprintf(stderr, "watch cmd: %s failed: %s\n", cmd, pmErrStr(-oserror()));
+}
+
+void
+printindom(FILE *f, __pmInResult *irp)
+{
+ int i;
+
+ for (i = 0; i < irp->numinst; i++) {
+ fprintf(f, "[%3d]", i);
+ if (irp->instlist != NULL)
+ fprintf(f, " inst: %d", irp->instlist[i]);
+ if (irp->namelist != NULL)
+ fprintf(f, " name: \"%s\"", irp->namelist[i]);
+ fputc('\n', f);
+ }
+}
+
+void
+dohelp(int command, int full)
+{
+ if (command < 0) {
+ puts("help [ command ]\n");
+ dohelp(ATTR, HELP_USAGE);
+ dohelp(PMNS_CHILDREN, HELP_USAGE);
+ dohelp(CLOSE, HELP_USAGE);
+ dohelp(DBG, HELP_USAGE);
+ dohelp(DESC, HELP_USAGE);
+ dohelp(FETCH, HELP_USAGE);
+ dohelp(GETDESC, HELP_USAGE);
+ dohelp(INSTANCE, HELP_USAGE);
+ dohelp(PMNS_NAME, HELP_USAGE);
+ dohelp(NAMESPACE, HELP_USAGE);
+ dohelp(OPEN, HELP_USAGE);
+ dohelp(PMNS_PMID, HELP_USAGE);
+ dohelp(PROFILE, HELP_USAGE);
+ dohelp(QUIT, HELP_USAGE);
+ dohelp(STATUS, HELP_USAGE);
+ dohelp(STORE, HELP_USAGE);
+ dohelp(INFO, HELP_USAGE);
+ dohelp(TIMER, HELP_USAGE);
+ dohelp(PMNS_TRAVERSE, HELP_USAGE);
+ dohelp(WAIT, HELP_USAGE);
+ dohelp(WATCH, HELP_USAGE);
+ putchar('\n');
+ }
+ else {
+ if (full == HELP_FULL)
+ putchar('\n');
+
+ switch (command) {
+ case ATTR:
+ puts("attr name [value]");
+ puts("attr attr# [value]");
+ break;
+ case CLOSE:
+ puts("close");
+ break;
+ case DBG:
+ puts("debug all | none");
+ puts("debug flag [ flag ... ] (flag is decimal or symbolic name)");
+ break;
+ case DESC:
+ puts("desc metric");
+ break;
+ case FETCH:
+ puts("fetch metric [ metric ... ]");
+ break;
+ case GETDESC:
+ puts("getdesc on | off");
+ break;
+ case INFO:
+ puts("text metric");
+ puts("text indom indom#");
+ break;
+ case INSTANCE:
+ puts("instance indom# [ number | name | \"name\" ]");
+ break;
+ case NAMESPACE:
+ puts("namespace fname");
+ break;
+ case OPEN:
+ puts("open dso dsoname init_routine [ domain# ]");
+ puts("open pipe execname [ arg ... ]");
+ puts("open socket unix sockname");
+ puts("open socket inet port#|service");
+ puts("open socket ipv6 port#|service");
+ break;
+ case PMNS_CHILDREN:
+ puts("children metric-name");
+ break;
+ case PMNS_NAME:
+ puts("name pmid#");
+ break;
+ case PMNS_PMID:
+ puts("pmid metric-name");
+ break;
+ case PMNS_TRAVERSE:
+ puts("traverse metric-name");
+ break;
+ case PROFILE:
+ puts("profile indom# [ all | none ]");
+ puts("profile indom# [ add | delete ] number");
+ break;
+ case QUIT:
+ puts("quit");
+ break;
+ case STATUS:
+ puts("status");
+ break;
+ case STORE:
+ puts("store metric \"value\"");
+ break;
+ case WATCH:
+ puts("watch logfilename");
+ break;
+ case TIMER:
+ puts("timer on | off");
+ break;
+ case WAIT:
+ puts("wait seconds");
+ break;
+ default:
+ fprintf(stderr, "Help for that command (%d) not supported!\n", command);
+ }
+
+ if (full == HELP_FULL) {
+ putchar('\n');
+ switch (command) {
+ case ATTR:
+ puts(
+"Set a security attribute. These set aspects of per-user authentication,\n"
+"allowing a PMDA to provide different metric views for different users.\n");
+ break;
+ case CLOSE:
+ puts(
+"Close the pipe to a daemon PMDA or dlclose(3) a DSO PMDA. dbpmda does not\n"
+"exit, allowing another PMDA to be opened.\n");
+ break;
+ case DBG:
+ puts(
+"Specify which debugging flags should be active (see pmdbg(1)). Flags may\n"
+"be specified as integers or by name, with multiple flags separated by\n"
+"white space. All flags may be selected or deselected if 'all' or 'none' is\n"
+"specified. The current setting is displayed by the status command.\n\n");
+ break;
+ case DESC:
+ puts(
+"Print out the meta data description for the 'metric'. The metric may be\n"
+"specified by name, or as a PMID of the form N, N.N or N.N.N.\n");
+ break;
+ case FETCH:
+ puts(
+"Fetch metrics from the PMDA. The metrics may be specified as a list of\n"
+"metric names, or PMIDs of the form N, N.N or N.N.N.\n");
+ break;
+ case GETDESC:
+ puts(
+"Before doing a fetch, get the descriptor so that the result of a fetch\n"
+"can be printed out correctly.\n");
+ break;
+ case INFO:
+ puts(
+"Retrieve the help text for the 'metric' or 'indom' from the PMDA. The one\n"
+"line message is shown between '[' and ']' with the long message on the next\n"
+"line. To get the help text for an instance domain requires the word\n"
+"``indom'' before the indom number\n");
+ break;
+ case INSTANCE:
+ puts(
+"List the instances in 'indom'. The list may be restricted to a specific\n"
+"instance 'name' or 'number'.\n");
+ break;
+ case NAMESPACE:
+ puts(
+"Unload the current Name Space and load up the given Name Space.\n"
+"If unsuccessful then will try to reload the previous Name Space.\n");
+ break;
+ case OPEN:
+ puts(
+"Open a PMDA as either a DSO, via a network socket (unix/inet/ipv6), or as a\n"
+"daemon (connected with a pipe). The 'dsoname' and 'execname' fields are\n"
+"the path to the PMDA shared object file or executable. The first socket PMDA\n"
+"field is the type - either unix (if supported), inet or ipv6. The 'sockname'\n"
+"argument for unix sockets is a path of a named pipe where a PMDA is listening\n"
+"for connections. The 'port' argument is a port number, 'serv' a service name\n"
+"typically defined in /etc/services (resolved to a port via getservent(3)).\n"
+"The arguments to this command are similar to a line in the pmcd.conf file.\n");
+ break;
+ case PMNS_CHILDREN:
+ puts(
+"Fetch and print the next name component of the direct decendents of\n"
+"metric-name in the PMNS, reporting for each if it is a leaf node or a\n"
+"non-leaf node.\n"
+"Most useful for PMDAs that support dynamic metrics in the PMNS.\n");
+ break;
+ case PMNS_NAME:
+ puts(
+"Print the name of the metric with PMID pmid#. The pmid# syntax follows\n"
+"the source PMNS syntax, namely 3 numbers separated by '.' to encode\n"
+"the domain, cluster and item components of the PMID, e.g.\n"
+" name 29.0.1004\n"
+"Most useful for PMDAs that support dynamic metrics in the PMNS.\n");
+ break;
+ case PMNS_PMID:
+ puts(
+"Print the PMID for the named metric\n"
+"Most useful for PMDAs that support dynamic metrics in the PMNS.\n");
+ break;
+ case PMNS_TRAVERSE:
+ puts(
+"Fetch and print all of the decendent metric names below metric-name\n"
+"in the PMNS.\n"
+"Most useful for PMDAs that support dynamic metrics in the PMNS.\n");
+ break;
+ case PROFILE:
+ puts(
+"For the instance domain specified, the profile may be changed to include\n"
+"'all' instances, no instances, add an instance or delete an instance.\n");
+ break;
+ case QUIT:
+ puts("Exit dbpmda. This also closes any open PMDAs.\n");
+ break;
+ case STATUS:
+ puts(
+"Display the state of dbpmda, including which PMDA is connected, which\n"
+"pmDebug flags are set, and the current profile.\n");
+ break;
+ case STORE:
+ puts(
+"Store the value (int, real or string) into the 'metric'. The metric may be\n"
+"specified by name or as a PMID with the format N, N.N, N.N.N. The value to\n"
+"be stored must be enclosed in quotes. Unlike the other commands, a store\n"
+"must request a metric description and fetch the metric to determine how to\n"
+"interpret the value, and to allocate the PDU for transmitting the value,\n"
+"respectively. The current profile will be used.\n");
+ break;
+ case TIMER:
+ puts(
+"Report the response time of the PMDA when sending and receiving PDUs.\n");
+ break;
+ case WATCH:
+ puts(
+"A xwsh window is opened which tails the specified log file. This window\n"
+"must be closed by the user when no longer required.\n");
+ break;
+ case WAIT:
+ puts("Sleep for this number of seconds\n");
+ break;
+ }
+ }
+ }
+}
+
+void
+dostatus(void)
+{
+ int i = 0;
+
+ putchar('\n');
+ printf("Namespace: ");
+ if (cmd_namespace != NULL)
+ printf("%s\n", cmd_namespace);
+ else {
+ if (pmnsfile == NULL)
+ printf("(default)\n");
+ else
+ printf("%s\n", pmnsfile);
+ }
+
+ if (myPmdaName == NULL || connmode == NO_CONN)
+ printf("PMDA: none\n");
+ else {
+ printf("PMDA: %s\n", myPmdaName);
+ printf("Connection: ");
+ switch (connmode) {
+ case CONN_DSO:
+ printf("dso\n");
+ printf("DSO Interface Version: %d\n", dispatch.comm.pmda_interface);
+ printf("PMDA PMAPI Version: %d\n", dispatch.comm.pmapi_version);
+ break;
+ case CONN_DAEMON:
+ printf("daemon\n");
+ printf("PMDA PMAPI Version: ");
+ i = __pmVersionIPC(infd);
+ if (i == UNKNOWN_VERSION)
+ printf("unknown!\n");
+ else
+ printf("%d\n", i);
+ break;
+ default:
+ printf("unknown!\n");
+ break;
+ }
+ }
+
+ printf("pmDebug: ");
+ if (pmDebug == (unsigned int) -1)
+ printf("-1 (all)\n");
+ else if (pmDebug == 0)
+ printf("0 (none)\n");
+ else {
+ printf("%u", pmDebug);
+ for (i = 0; i < numFlags; i++)
+ if (pmDebug & (1 << i)) {
+ printf(" ( %s", debugFlags[i]);
+ break;
+ }
+ for (i++; i < numFlags; i++)
+ if (pmDebug & (1 << i))
+ printf(" + %s", debugFlags[i]);
+ printf(" )\n");
+ }
+
+ printf("Timer: ");
+ if (timer == 0)
+ printf("off\n");
+ else
+ printf("on\n");
+
+ printf("Getdesc: ");
+ if (get_desc == 0)
+ printf("off\n");
+ else
+ printf("on\n");
+
+ putchar('\n');
+ __pmDumpProfile(stdout, PM_INDOM_NULL, profile);
+ putchar('\n');
+}
+
+
+/*
+ * Modified version of __pmDumpResult to use a descriptor list
+ * instead of calling pmLookupDesc.
+ * Notes:
+ * - desc_list should not be NULL
+ */
+
+void
+_dbDumpResult(FILE *f, pmResult *resp, pmDesc *desc_list)
+{
+ int i;
+ int j;
+ int n;
+ char *p;
+
+ fprintf(f,"pmResult dump from " PRINTF_P_PFX "%p timestamp: %d.%06d ",
+ resp, (int)resp->timestamp.tv_sec, (int)resp->timestamp.tv_usec);
+ __pmPrintStamp(f, &resp->timestamp);
+ fprintf(f, " numpmid: %d\n", resp->numpmid);
+ for (i = 0; i < resp->numpmid; i++) {
+ pmValueSet *vsp = resp->vset[i];
+ n = pmNameID(vsp->pmid, &p);
+ if (n < 0)
+ fprintf(f," %s (%s):", pmIDStr(vsp->pmid), "<noname>");
+ else {
+ fprintf(f," %s (%s):", pmIDStr(vsp->pmid), p);
+ free(p);
+ }
+ if (vsp->numval == 0) {
+ fprintf(f, " No values returned!\n");
+ continue;
+ }
+ else if (vsp->numval < 0) {
+ fprintf(f, " %s\n", pmErrStr(vsp->numval));
+ continue;
+ }
+ fprintf(f, " numval: %d", vsp->numval);
+ fprintf(f, " valfmt: %d vlist[]:\n", vsp->valfmt);
+ for (j = 0; j < vsp->numval; j++) {
+ pmValue *vp = &vsp->vlist[j];
+ if (vsp->numval > 1 || desc_list[i].indom != PM_INDOM_NULL) {
+ fprintf(f," inst [%d", vp->inst);
+ fprintf(f, " or ???]");
+ fputc(' ', f);
+ }
+ else
+ fprintf(f, " ");
+ fprintf(f, "value ");
+ pmPrintValue(f, vsp->valfmt, desc_list[i].type, vp, 1);
+ fputc('\n', f);
+ }/*for*/
+ }/*for*/
+}/*_dbDumpResult*/