summaryrefslogtreecommitdiff
path: root/src/libpcp/src/instance.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libpcp/src/instance.c')
-rw-r--r--src/libpcp/src/instance.c352
1 files changed, 352 insertions, 0 deletions
diff --git a/src/libpcp/src/instance.c b/src/libpcp/src/instance.c
new file mode 100644
index 0000000..07fad87
--- /dev/null
+++ b/src/libpcp/src/instance.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2013 Red Hat.
+ * Copyright (c) 1995-2006 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ */
+
+#include "pmapi.h"
+#include "impl.h"
+#include "pmda.h"
+#include "internal.h"
+
+int
+pmLookupInDom(pmInDom indom, const char *name)
+{
+ int n;
+ __pmInResult *result;
+ __pmContext *ctxp;
+
+ if (indom == PM_INDOM_NULL)
+ return PM_ERR_INDOM;
+ if ((n = pmWhichContext()) >= 0) {
+ int ctx = n;
+ ctxp = __pmHandleToPtr(ctx);
+ if (ctxp == NULL)
+ return PM_ERR_NOCONTEXT;
+ if (ctxp->c_type == PM_CONTEXT_HOST) {
+ PM_LOCK(ctxp->c_pmcd->pc_lock);
+ n = __pmSendInstanceReq(ctxp->c_pmcd->pc_fd, __pmPtrToHandle(ctxp),
+ &ctxp->c_origin, indom, PM_IN_NULL, name);
+ if (n < 0)
+ n = __pmMapErrno(n);
+ else {
+ __pmPDU *pb;
+ int pinpdu;
+ pinpdu = n = __pmGetPDU(ctxp->c_pmcd->pc_fd, ANY_SIZE,
+ ctxp->c_pmcd->pc_tout_sec, &pb);
+ if (n == PDU_INSTANCE) {
+ __pmInResult *result;
+ if ((n = __pmDecodeInstance(pb, &result)) >= 0) {
+ n = result->instlist[0];
+ __pmFreeInResult(result);
+ }
+ }
+ else if (n == PDU_ERROR)
+ __pmDecodeError(pb, &n);
+ else if (n != PM_ERR_TIMEOUT)
+ n = PM_ERR_IPC;
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+ }
+ PM_UNLOCK(ctxp->c_pmcd->pc_lock);
+ }
+ else if (ctxp->c_type == PM_CONTEXT_LOCAL) {
+ __pmDSO *dp;
+ if (PM_MULTIPLE_THREADS(PM_SCOPE_DSO_PMDA))
+ /* Local context requires single-threaded applications */
+ n = PM_ERR_THREAD;
+ else if ((dp = __pmLookupDSO(((__pmInDom_int *)&indom)->domain)) == NULL)
+ n = PM_ERR_NOAGENT;
+ else {
+ /* We can safely cast away const here */
+ if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_5)
+ dp->dispatch.version.four.ext->e_context = ctx;
+ n = dp->dispatch.version.any.instance(indom, PM_IN_NULL,
+ (char *)name, &result,
+ dp->dispatch.version.any.ext);
+ }
+ if (n >= 0) {
+ n = result->instlist[0];
+ __pmFreeInResult(result);
+ }
+ }
+ else {
+ /* assume PM_CONTEXT_ARCHIVE */
+ n = __pmLogLookupInDom(ctxp->c_archctl->ac_log, indom, &ctxp->c_origin, name);
+ }
+ PM_UNLOCK(ctxp->c_lock);
+ }
+
+ return n;
+}
+
+int
+pmNameInDom(pmInDom indom, int inst, char **name)
+{
+ int n;
+ __pmInResult *result;
+ __pmContext *ctxp;
+
+ if (indom == PM_INDOM_NULL)
+ return PM_ERR_INDOM;
+ if ((n = pmWhichContext()) >= 0) {
+ int ctx = n;
+ ctxp = __pmHandleToPtr(ctx);
+ if (ctxp == NULL)
+ return PM_ERR_NOCONTEXT;
+ if (ctxp->c_type == PM_CONTEXT_HOST) {
+ PM_LOCK(ctxp->c_pmcd->pc_lock);
+ n = __pmSendInstanceReq(ctxp->c_pmcd->pc_fd, __pmPtrToHandle(ctxp),
+ &ctxp->c_origin, indom, inst, NULL);
+ if (n < 0)
+ n = __pmMapErrno(n);
+ else {
+ __pmPDU *pb;
+ int pinpdu;
+ pinpdu = n = __pmGetPDU(ctxp->c_pmcd->pc_fd, ANY_SIZE,
+ ctxp->c_pmcd->pc_tout_sec, &pb);
+ if (n == PDU_INSTANCE) {
+ __pmInResult *result;
+ if ((n = __pmDecodeInstance(pb, &result)) >= 0) {
+ if ((*name = strdup(result->namelist[0])) == NULL)
+ n = -oserror();
+ __pmFreeInResult(result);
+ }
+ }
+ else if (n == PDU_ERROR)
+ __pmDecodeError(pb, &n);
+ else if (n != PM_ERR_TIMEOUT)
+ n = PM_ERR_IPC;
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+ }
+ PM_UNLOCK(ctxp->c_pmcd->pc_lock);
+ }
+ else if (ctxp->c_type == PM_CONTEXT_LOCAL) {
+ __pmDSO *dp;
+ if (PM_MULTIPLE_THREADS(PM_SCOPE_DSO_PMDA))
+ /* Local context requires single-threaded applications */
+ n = PM_ERR_THREAD;
+ else if ((dp = __pmLookupDSO(((__pmInDom_int *)&indom)->domain)) == NULL)
+ n = PM_ERR_NOAGENT;
+ else {
+ if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_5)
+ dp->dispatch.version.four.ext->e_context = ctx;
+ n = dp->dispatch.version.any.instance(indom, inst, NULL, &result, dp->dispatch.version.any.ext);
+ }
+ if (n >= 0) {
+ if ((*name = strdup(result->namelist[0])) == NULL)
+ n = -oserror();
+ __pmFreeInResult(result);
+ }
+ }
+ else {
+ /* assume PM_CONTEXT_ARCHIVE */
+ char *tmp;
+ if ((n = __pmLogNameInDom(ctxp->c_archctl->ac_log, indom, &ctxp->c_origin, inst, &tmp)) >= 0) {
+ if ((*name = strdup(tmp)) == NULL)
+ n = -oserror();
+ }
+ }
+ PM_UNLOCK(ctxp->c_lock);
+ }
+
+ return n;
+}
+
+static int
+inresult_to_lists(__pmInResult *result, int **instlist, char ***namelist)
+{
+ int n, i, sts, need;
+ char *p;
+ int *ilist;
+ char **nlist;
+
+ if (result->numinst == 0) {
+ __pmFreeInResult(result);
+ return 0;
+ }
+ need = 0;
+ for (i = 0; i < result->numinst; i++) {
+ need += sizeof(**namelist) + strlen(result->namelist[i]) + 1;
+ }
+ ilist = (int *)malloc(result->numinst * sizeof(result->instlist[0]));
+ if (ilist == NULL) {
+ sts = -oserror();
+ __pmFreeInResult(result);
+ return sts;
+ }
+ if ((nlist = (char **)malloc(need)) == NULL) {
+ sts = -oserror();
+ free(ilist);
+ __pmFreeInResult(result);
+ return sts;
+ }
+
+ *instlist = ilist;
+ *namelist = nlist;
+ p = (char *)&nlist[result->numinst];
+ for (i = 0; i < result->numinst; i++) {
+ ilist[i] = result->instlist[i];
+ strcpy(p, result->namelist[i]);
+ nlist[i] = p;
+ p += strlen(result->namelist[i]) + 1;
+ }
+ n = result->numinst;
+ __pmFreeInResult(result);
+ return n;
+}
+
+int
+pmGetInDom(pmInDom indom, int **instlist, char ***namelist)
+{
+ int n;
+ int i;
+ __pmInResult *result;
+ __pmContext *ctxp;
+ char *p;
+ int need;
+ int *ilist;
+ char **nlist;
+
+ if (indom == PM_INDOM_NULL)
+ return PM_ERR_INDOM;
+
+ if ((n = pmWhichContext()) >= 0) {
+ int ctx = n;
+ ctxp = __pmHandleToPtr(ctx);
+ if (ctxp == NULL)
+ return PM_ERR_NOCONTEXT;
+ if (ctxp->c_type == PM_CONTEXT_HOST) {
+ PM_LOCK(ctxp->c_pmcd->pc_lock);
+ n = __pmSendInstanceReq(ctxp->c_pmcd->pc_fd, __pmPtrToHandle(ctxp),
+ &ctxp->c_origin, indom, PM_IN_NULL, NULL);
+ if (n < 0)
+ n = __pmMapErrno(n);
+ else {
+ __pmPDU *pb;
+ int pinpdu;
+ pinpdu = n = __pmGetPDU(ctxp->c_pmcd->pc_fd, ANY_SIZE,
+ ctxp->c_pmcd->pc_tout_sec, &pb);
+ if (n == PDU_INSTANCE) {
+ __pmInResult *result;
+ if ((n = __pmDecodeInstance(pb, &result)) < 0) {
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+ PM_UNLOCK(ctxp->c_pmcd->pc_lock);
+ return n;
+ }
+ n = inresult_to_lists(result, instlist, namelist);
+ }
+ else if (n == PDU_ERROR)
+ __pmDecodeError(pb, &n);
+ else if (n != PM_ERR_TIMEOUT)
+ n = PM_ERR_IPC;
+ if (pinpdu > 0)
+ __pmUnpinPDUBuf(pb);
+ }
+ PM_UNLOCK(ctxp->c_pmcd->pc_lock);
+ }
+ else if (ctxp->c_type == PM_CONTEXT_LOCAL) {
+ __pmDSO *dp;
+ if (PM_MULTIPLE_THREADS(PM_SCOPE_DSO_PMDA))
+ /* Local context requires single-threaded applications */
+ n = PM_ERR_THREAD;
+ else if ((dp = __pmLookupDSO(((__pmInDom_int *)&indom)->domain)) == NULL)
+ n = PM_ERR_NOAGENT;
+ else {
+ if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_5)
+ dp->dispatch.version.four.ext->e_context = ctx;
+ n = dp->dispatch.version.any.instance(indom, PM_IN_NULL, NULL,
+ &result,
+ dp->dispatch.version.any.ext);
+ }
+ if (n >= 0)
+ n = inresult_to_lists(result, instlist, namelist);
+ }
+ else {
+ /* assume PM_CONTEXT_ARCHIVE */
+ int *insttmp;
+ char **nametmp;
+ if ((n = __pmLogGetInDom(ctxp->c_archctl->ac_log, indom, &ctxp->c_origin, &insttmp, &nametmp)) >= 0) {
+ need = 0;
+ for (i = 0; i < n; i++)
+ need += sizeof(char *) + strlen(nametmp[i]) + 1;
+ if ((ilist = (int *)malloc(n * sizeof(insttmp[0]))) == NULL) {
+ PM_UNLOCK(ctxp->c_lock);
+ return -oserror();
+ }
+ if ((nlist = (char **)malloc(need)) == NULL) {
+ free(ilist);
+ PM_UNLOCK(ctxp->c_lock);
+ return -oserror();
+ }
+ *instlist = ilist;
+ *namelist = nlist;
+ p = (char *)&nlist[n];
+ for (i = 0; i < n; i++) {
+ ilist[i] = insttmp[i];
+ strcpy(p, nametmp[i]);
+ nlist[i] = p;
+ p += strlen(nametmp[i]) + 1;
+ }
+ }
+ }
+ PM_UNLOCK(ctxp->c_lock);
+ }
+
+ if (n == 0) {
+ /* avoid ambiguity when no instances or errors */
+ *instlist = NULL;
+ *namelist = NULL;
+ }
+
+ return n;
+}
+
+#ifdef PCP_DEBUG
+void
+__pmDumpInResult(FILE *f, const __pmInResult *irp)
+{
+ int i;
+ char strbuf[20];
+ fprintf(f,"pmInResult dump from " PRINTF_P_PFX "%p for InDom %s (0x%x), numinst=%d\n",
+ irp, pmInDomStr_r(irp->indom, strbuf, sizeof(strbuf)), irp->indom, irp->numinst);
+ for (i = 0; i < irp->numinst; i++) {
+ fprintf(f, " [%d]", 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);
+ }
+ return;
+}
+#endif
+
+void
+__pmFreeInResult(__pmInResult *res)
+{
+ int i;
+
+ if (res->namelist != NULL) {
+ for (i = 0; i < res->numinst; i++) {
+ if (res->namelist[i] != NULL) {
+ free(res->namelist[i]);
+ }
+ }
+ free(res->namelist);
+ }
+ if (res->instlist != NULL)
+ free(res->instlist);
+ free(res);
+}