This patch introduces a new agent to collect the maximum memory
bandwidth in PCP. Right now, the support is basic and limited by a
configuration file. The way this works is, this agent has a config file
called memory_bandwidth.conf file which has entries for numa nodes on a
system :
node0:40960
node1:40960
...
Each row represents a numa node of the system along with the maximum
memory bandwidth (in MB/sec) it supports. The maximum memory bandwidth
can be found using several benchmarking tools by saturating and
measuring the bandwidth.
The agent first parses the sysfs nodes directory and creates a list of
numa nodes. Then, it parses the config file and verifies whether
the node name specified in the .conf file has a match in the sysfs nodes
list. If not, it throws an error. The agent updates the bandwidth
information in the node_info struct. And, whenever a client asks for the
information, it gives the values for each node:
# pminfo | grep memory_bandwidth
memory_bandwidth.max
# pmval memory_bandwidth.max
metric: memory_bandwidth.max
host: <some_host>
semantics: instantaneous value
units: Mbyte / sec
samples: all
node0 node1
4.096E+04 4.096E+04
Few things to note:
- The user has to give the bandwidth information in the .config file.
- The max bandwidth value can be given as a floating point.
- The node names mentioned in the .config must match any of the node
names found in sysfs/devices/system/node/ directory.
- Right now, automatic update of max bandwidth is not supported due to
lack of non-standard/arch-independent tools.
- Support for automatic updates for max bandwidth using some
benchmarking tools will be added later.
Usefulness of the metric provided by this agent :
As of now, we have hardware counters for measuring the current memory
bandwidth (read and write) and that can be aggregated per
node. "perfevent" agent for PCP can be used for that. However, to make
decisions regarding placement/migration of workloads across nodes(or
systems) solely based on the current bandwidth is not sufficient. We
also need the maximum bandwidth supported on the nodes to find out the
utilization. And hence, the maximum bandwidth can be used for this
purpose.
Thanks!
Signed-off-by: Hemant Kumar <hemant@xxxxxxxxxxxxxxxxxx>
---
src/pmdas/memory_bandwidth/GNUmakefile | 57 ++++++
src/pmdas/memory_bandwidth/Install | 35 ++++
src/pmdas/memory_bandwidth/Remove | 28 +++
src/pmdas/memory_bandwidth/help | 21 +++
src/pmdas/memory_bandwidth/mem_bandwidth.c | 126 ++++++++++++++
src/pmdas/memory_bandwidth/mem_bandwidth.h | 41 +++++
src/pmdas/memory_bandwidth/memory_bandwidth.conf | 8 +
src/pmdas/memory_bandwidth/numanodes.c | 97 +++++++++++
src/pmdas/memory_bandwidth/pmda.c | 213 +++++++++++++++++++++++
src/pmdas/memory_bandwidth/pmns | 19 ++
src/pmdas/memory_bandwidth/root | 8 +
src/pmns/stdpmid.pcp | 1 +
12 files changed, 654 insertions(+)
create mode 100644 src/pmdas/memory_bandwidth/GNUmakefile
create mode 100755 src/pmdas/memory_bandwidth/Install
create mode 100644 src/pmdas/memory_bandwidth/Remove
create mode 100644 src/pmdas/memory_bandwidth/help
create mode 100644 src/pmdas/memory_bandwidth/mem_bandwidth.c
create mode 100644 src/pmdas/memory_bandwidth/mem_bandwidth.h
create mode 100644 src/pmdas/memory_bandwidth/memory_bandwidth.conf
create mode 100644 src/pmdas/memory_bandwidth/numanodes.c
create mode 100644 src/pmdas/memory_bandwidth/pmda.c
create mode 100644 src/pmdas/memory_bandwidth/pmns
create mode 100644 src/pmdas/memory_bandwidth/root
diff --git a/src/pmdas/memory_bandwidth/GNUmakefile
b/src/pmdas/memory_bandwidth/GNUmakefile
new file mode 100644
index 0000000..56172bf
--- /dev/null
+++ b/src/pmdas/memory_bandwidth/GNUmakefile
@@ -0,0 +1,57 @@
+#
+# Copyright (c) 2016 Hemant K. Shaw, IBM Corporation.
+# Copyright (c) 2000,2003,2004,2008 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
+
+IAM = memory_bandwidth
+DOMAIN = MEMORY_BANDWIDTH
+CMDTARGET = pmda$(IAM)
+
+PMDADIR = $(PCP_PMDAS_DIR)/$(IAM)
+
+CFILES = pmda.c mem_bandwidth.c numanodes.c
+
+HFILES = mem_bandwidth.h
+
+SCRIPTS = Install Remove
+
+DFILES = README help
+
+default_pcp default: build-me
+
+include $(BUILDRULES)
+
+build-me: $(CMDTARGET)
+
+install_pcp install: default
+ $(INSTALL) -m 755 -d $(PMDADIR)
+ $(INSTALL) -m 644 domain.h help root pmns memory_bandwidth.conf
$(PMDADIR)
+ $(INSTALL) -m 755 $(CMDTARGET) $(SCRIPTS) $(PMDADIR)
+
+TARGETS = $(CMDTARGET)
+
+LLDLIBS = $(PCP_PMDALIB) $(PFM_LIBS)
+LLDLIBS += $(LIB_FOR_MATH)
+LCFLAGS = -I.
+CFLAGS += -DVERSION=\"$(VERSION)\"
+
+$(OBJECTS): domain.h
+
+domain.h: ../../pmns/stdpmid
+ $(DOMAIN_MAKERULE)
+
+clean clobber::
+ $(RM) *.o $(CMDTARGET)
diff --git a/src/pmdas/memory_bandwidth/Install
b/src/pmdas/memory_bandwidth/Install
new file mode 100755
index 0000000..6564a75
--- /dev/null
+++ b/src/pmdas/memory_bandwidth/Install
@@ -0,0 +1,35 @@
+#! /bin/sh
+#
+# Copyright (c) 2016 Hemant K. Shaw, IBM Corporation
+# 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.
+#
+# Install the PMDA and/or PMNS
+#
+
+. $PCP_DIR/etc/pcp.env
+. $PCP_SHARE_DIR/lib/pmdaproc.sh
+
+iam=memory_bandwidth
+forced_restart=true
+pmda_interface=2
+
+dso_opt=true
+perl_opt=false
+python_opt=false
+socket_opt=true
+socket_inet_def=2082
+
+pmdaSetup
+pmdaInstall
+
+exit 0
diff --git a/src/pmdas/memory_bandwidth/Remove
b/src/pmdas/memory_bandwidth/Remove
new file mode 100644
index 0000000..f639dbe
--- /dev/null
+++ b/src/pmdas/memory_bandwidth/Remove
@@ -0,0 +1,28 @@
+#! /bin/sh
+# 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.
+#
+# 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
+#
+# Remove the memory_bandwidth PMDA
+#
+
+. $PCP_DIR/etc/pcp.env
+. $PCP_SHARE_DIR/lib/pmdaproc.sh
+
+iam=memory_bandwidth
+
+pmdaSetup
+pmdaRemove
+exit 0
diff --git a/src/pmdas/memory_bandwidth/help b/src/pmdas/memory_bandwidth/help
new file mode 100644
index 0000000..717449b
--- /dev/null
+++ b/src/pmdas/memory_bandwidth/help
@@ -0,0 +1,21 @@
+#
+# Copyright (c) 2016 Hemant K. Shaw, IBM Corporation.
+#
+# 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.
+#
+# memory_bandwidth PMDA help file in ASCII format
+#
+
+@ memory_bandwidth.max Maximum memory bandwidth per node
diff --git a/src/pmdas/memory_bandwidth/mem_bandwidth.c
b/src/pmdas/memory_bandwidth/mem_bandwidth.c
new file mode 100644
index 0000000..6d5dda3
--- /dev/null
+++ b/src/pmdas/memory_bandwidth/mem_bandwidth.c
@@ -0,0 +1,126 @@
+/* Memory bandwidth config file parser
+ *
+ * Copyright (c) 2016 Hemant K. Shaw, IBM Corporation.
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "mem_bandwidth.h"
+
+void print_err_msg(int val)
+{
+ switch (val) {
+ case CONFIG_PARSE_ERR:
+ fprintf(stderr, "Error in parsing the bandwidth.config file\n");
+ break;
+ case ALLOC_ERR:
+ fprintf(stderr, "Error in memory allocation\n");
+ break;
+ case SEMANTIC_ERR:
+ fprintf(stderr, "Semantic error\n");
+ break;
+ }
+}
+
+static void skim_through_whitespace(char *start_ptr, char *end_ptr)
+{
+ while((start_ptr != end_ptr) && isspace(*start_ptr))
+ start_ptr++;
+}
+
+/*
+ * Parse the configuration file to find the nodes information
+ * and match that up with the sysfs information in *nodes.
+ * The syntax should be :
+ * node_num:bandwidth_value
+ * For e.g:
+ * node0:2500
+ * The node name must match with the numa node names as present
+ * in sysfs nodes directory.
+ */
+int find_bandwidth_from_conf(char *config_path, struct node_info *nodes,
+ int nr_nodes)
+
+{
+ size_t len = 0;
+ char *start_ptr, *end_ptr, *value_str, *line = NULL;
+ FILE *fp;
+ ssize_t ret = 0;
+ char *node_name;
+ struct node_info *node = NULL;
+ int nodes_found = 0;
+
+ fp = fopen(config_path, "r");
+ if (NULL == fp) {
+ fprintf(stderr, "Error in opening %s\n", config_path);
+ return CONFIG_PARSE_ERR;
+ }
+
+ while(ret >= 0) {
+ ret = getline(&line, &len, fp);
+ if (ret > 0) {
+ /* Ignore the comments */
+ if (line[0] == '#') {
+ continue;
+ }
+ /* Remove the new line from the end of the string here (if any) */
+ if (line[strlen(line) - 1] == '\n')
+ line[strlen(line) - 1] = '\0';
+
+ start_ptr = line;
+ end_ptr = start_ptr + strlen(line) - 1;
+
+ /* Ignore white-space */
+ skim_through_whitespace(start_ptr, end_ptr);
+
+ value_str = strchr(line, ':');
+ if (NULL == value_str) {
+ ret = CONFIG_PARSE_ERR;
+ goto free_line;
+ }
+
+ *value_str = '\0';
+ value_str++;
+
+ node_name = strdup(start_ptr);
+ if (NULL == node_name) {
+ ret = ALLOC_ERR;
+ goto free_line;
+ }
+ node = find_node_by_name_in_list(nodes, nr_nodes, node_name);
+ if (NULL == node) {
+ ret = CONFIG_PARSE_ERR;
+ goto free_line;
+ }
+ node->bandwidth = atof(value_str);
+ nodes_found++;
+ }
+ }
+
+ if (nodes_found == nr_nodes)
+ ret = 0;
+
+ free_line:
+ if (line)
+ free(line);
+ fclose(fp);
+
+ return ret;
+}
diff --git a/src/pmdas/memory_bandwidth/mem_bandwidth.h
b/src/pmdas/memory_bandwidth/mem_bandwidth.h
new file mode 100644
index 0000000..73e972d
--- /dev/null
+++ b/src/pmdas/memory_bandwidth/mem_bandwidth.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016 Hemant K. Shaw, IBM Corporation.
+ *
+ * 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 MEM_BANDWIDTH_H_
+#define MEM_BANDWIDTH_H_
+
+#include <stdint.h>
+
+struct node_info {
+ char *node_name;
+ double bandwidth;
+};
+
+#define CONFIG_PARSE_ERR -1
+#define ALLOC_ERR -2
+#define SEMANTIC_ERR -3
+
+int find_bandwidth_from_conf(char *config_path, struct node_info *nodes,
+ int nr_nodes);
+struct node_info *get_numa_node_info(int *nr_nodes);
+struct node_info *find_node_by_name_in_list(struct node_info *nodes,
+ int nr_nodes, char *name);
+
+void print_err_msg(int err);
+
+#endif /* MEM_BANDWIDTH_H_ */
diff --git a/src/pmdas/memory_bandwidth/memory_bandwidth.conf
b/src/pmdas/memory_bandwidth/memory_bandwidth.conf
new file mode 100644
index 0000000..51771a0
--- /dev/null
+++ b/src/pmdas/memory_bandwidth/memory_bandwidth.conf
@@ -0,0 +1,8 @@
+# This file has the per node memory bandwidth information.
+# To add a node, just say :
+# NodeNum:Bandwidth
+# NodeNum must match with any of the nodes present in
+# sysfs/devices/system/node/.
+# Bandwidth is a floating point value which is the maximum memory
+# bandwidth supported on that node and is expressed in MBytes/sec.
+#
diff --git a/src/pmdas/memory_bandwidth/numanodes.c
b/src/pmdas/memory_bandwidth/numanodes.c
new file mode 100644
index 0000000..f81097e
--- /dev/null
+++ b/src/pmdas/memory_bandwidth/numanodes.c
@@ -0,0 +1,97 @@
+/* Find Numa nodes info from sysfs
+ *
+ * Copyright (c) 2016 Hemant K. Shaw, IBM Corporation.
+ *
+ * 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.
+ */
+
+/*
+ * Look for the sysfs node directory and find out the number of numa nodes
+ */
+
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include "mem_bandwidth.h"
+
+#define SYSFS_NUMA_NODE_PATH "devices/system/node"
+#define NODE_NAME_LEN 32
+
+/*
+ * Search for node info with "name" in "nodes".
+ * Return the node if found, else return NULL.
+ */
+struct node_info *find_node_by_name_in_list(struct node_info *nodes,
+ int nr_nodes, char *name)
+{
+ int i;
+
+ for (i = 0; i < nr_nodes; i++) {
+ if (!strcmp(name, nodes[i].node_name))
+ return &nodes[i];
+ }
+ return NULL;
+}
+
+static int node_filter_func(const struct dirent *dentry)
+{
+ if (!strncmp(dentry->d_name, "node", 4))
+ return 1;
+ return 0;
+}
+
+/*
+ * Search in sysfs node directory to find out the number of nodes.
+ */
+struct node_info *get_numa_node_info(int *nr_nodes)
+{
+ struct dirent **names;
+ char *sysfs_path;
+ int nr_entries, i;
+ char buf[PATH_MAX];
+ struct node_info *nodes = NULL;
+
+ sysfs_path = getenv("SYSFS_MOUNT_POINT");
+ if (!sysfs_path) {
+ sysfs_path = "/sys";
+ }
+
+ snprintf(buf, PATH_MAX, "%s/%s", sysfs_path, SYSFS_NUMA_NODE_PATH);
+
+ nr_entries = scandir(buf, &names, &node_filter_func, versionsort);
+ if (nr_entries) {
+ /* Set no. of nodes */
+ *nr_nodes = nr_entries;
+ nodes = calloc(*nr_nodes, sizeof(*nodes));
+ if (!nodes) {
+ print_err_msg(ALLOC_ERR);
+ return NULL;
+ }
+ }
+
+ for (i = 0; i < nr_entries; i++) {
+ /* Got the node name list, now initialize the nodes */
+ nodes[i].node_name = strdup(names[i]->d_name);
+ if (NULL == nodes[i].node_name) {
+ print_err_msg(ALLOC_ERR);
+ return NULL;
+ }
+ nodes[i].bandwidth = 0;
+ }
+
+ return nodes;
+}
diff --git a/src/pmdas/memory_bandwidth/pmda.c
b/src/pmdas/memory_bandwidth/pmda.c
new file mode 100644
index 0000000..0127474
--- /dev/null
+++ b/src/pmdas/memory_bandwidth/pmda.c
@@ -0,0 +1,213 @@
+/* Memory bandwidth PMDA
+ *
+ * Copyright (c) 2016 Hemant K. Shaw, IBM Corporation.
+ * 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.
+ *
+ * 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.
+ */
+
+#include <pcp/pmapi.h>
+#include <pcp/impl.h>
+#include <pcp/pmda.h>
+#include "domain.h"
+#include <sys/stat.h>
+#include <unistd.h>
+#include <pthread.h>
+#include "mem_bandwidth.h"
+
+/*
+ * memory_bandwidth PMDA
+ *
+ * Metrics
+ * memory_bandwidth.max - Gives the per node max bandwidth
+ */
+
+/*
+ * instance domains
+ */
+static pmdaIndom indomtab[] = {
+#define NODE_INDOM 0
+ {NODE_INDOM, 0, NULL},
+};
+
+static pmInDom *node_indom = &indomtab[NODE_INDOM].it_indom;
+
+/*
+ * Definition for "maximum" metric for "memory_bandwidth"
+ */
+static pmdaMetric metrictab[] = {
+/* max */
+ { NULL,
+ { PMDA_PMID(0,0), PM_TYPE_DOUBLE, NODE_INDOM, PM_SEM_INSTANT,
+ PMDA_PMUNITS(1,-1,0,PM_SPACE_MBYTE,PM_TIME_SEC,0) }, },
+};
+
+static int isDSO = 1; /* =0 I am a daemon */
+static char *username;
+
+static char mypath[MAXPATHLEN];
+
+/* command line option handling - both short and long options */
+static pmLongOptions longopts[] = {
+ PMDA_OPTIONS_HEADER("Options"),
+ PMOPT_DEBUG,
+ PMDAOPT_DOMAIN,
+ PMDAOPT_LOGFILE,
+ PMDAOPT_USERNAME,
+ PMOPT_HELP,
+ PMDA_OPTIONS_TEXT("\nExactly one of the following options may appear:"),
+ PMDAOPT_INET,
+ PMDAOPT_PIPE,
+ PMDAOPT_UNIX,
+ PMDAOPT_IPV6,
+ PMDA_OPTIONS_END
+};
+static pmdaOptions opts = {
+ .short_options = "D:d:i:l:pu:U:6:?",
+ .long_options = longopts,
+};
+
+#define PMDANAME "memory_bandwidth"
+
+/*
+ * callback provided to pmdaFetch
+ */
+static int
+bandwidth_fetchCallBack(pmdaMetric *mdesc, unsigned int inst, pmAtomValue
*atom)
+{
+ int sts;
+ __pmID_int *idp = (__pmID_int *)&(mdesc->m_desc.pmid);
+ struct node_info *node;
+
+ if (inst != PM_IN_NULL &&
+ (idp->cluster != 0 && idp->item != 0))
+ return PM_ERR_INST;
+
+ if ((sts = pmdaCacheLookup(*node_indom, inst, NULL,
+ (void *)&node)) != PMDA_CACHE_ACTIVE) {
+ if (sts < 0)
+ __pmNotifyErr(LOG_ERR, "pmdaCacheLookup failed: inst=%d: %s",
+ inst, pmErrStr(sts));
+ return PM_ERR_INST;
+ }
+ atom->d = node->bandwidth;
+
+ return 0;
+}
+
+static void
+find_memory_bandwidth(void)
+{
+ struct node_info *numa_nodes = NULL;
+ char config_path[PATH_MAX];
+ int nr_nodes = 0;
+ int i = 0, sts, sep;
+
+ /* Find out numa nodes info from sysfs */
+ numa_nodes = get_numa_node_info(&nr_nodes);
+ if (0 == nr_nodes) {
+ fprintf(stderr, "Trouble in getting the number of nodes\n");
+ return;
+ }
+
+ sep = __pmPathSeparator();
+ snprintf(config_path, PATH_MAX, "%s%c" PMDANAME "%c" PMDANAME ".conf",
+ pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
+
+ /* Parse the config file and find out the bandwidth of the nodes */
+ sts = find_bandwidth_from_conf(config_path, numa_nodes, nr_nodes);
+ if (sts < 0) {
+ print_err_msg(sts);
+ fprintf(stderr, "Error in finding node information from .conf\n");
+ free(numa_nodes);
+ return;
+ }
+
+ for (i = 0; i < nr_nodes; i++) {
+ sts = pmdaCacheStore(*node_indom, PMDA_CACHE_ADD,
numa_nodes[i].node_name,
+ &numa_nodes[i]);
+ if (sts < 0) {
+ __pmNotifyErr(LOG_ERR, "pmdaCacheStore failed: %s", pmErrStr(sts));
+ return;
+ }
+ }
+ if (pmdaCacheOp(*node_indom, PMDA_CACHE_SIZE_ACTIVE) < 1)
+ __pmNotifyErr(LOG_WARNING, "No instance domains for node");
+}
+
+/*
+ * Initialize the agent (both daemon and DSO).
+ */
+void
+bandwidth_init(pmdaInterface *dp)
+{
+ size_t nindoms;
+
+ if (isDSO) {
+ int sep = __pmPathSeparator();
+ snprintf(mypath, sizeof(mypath), "%s%c" "memory_bandwidth" "%c" "help",
+ pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
+ pmdaDSO(dp, PMDA_INTERFACE_2, "memory_bandwidth DSO", mypath);
+ } else {
+ __pmSetProcessIdentity(username);
+ }
+
+ if (dp->status != 0)
+ return;
+
+ pmdaSetFetchCallBack(dp, bandwidth_fetchCallBack);
+
+ nindoms = sizeof(indomtab)/sizeof(indomtab[0]);
+
+ pmdaInit(dp, indomtab, nindoms, metrictab,
+ sizeof(metrictab)/sizeof(metrictab[0]));
+}
+
+/*
+ * Set up the agent if running as a daemon.
+ */
+int
+main(int argc, char **argv)
+{
+ int sep = __pmPathSeparator();
+ pmdaInterface dispatch;
+
+ isDSO = 0;
+ __pmSetProgname(argv[0]);
+ __pmGetUsername(&username);
+
+ snprintf(mypath, sizeof(mypath), "%s%c" PMDANAME "%c" "help",
+ pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
+ pmdaDaemon(&dispatch, PMDA_INTERFACE_2, pmProgname, MEMORY_BANDWIDTH,
+ "memory_bandwidth.log", mypath);
+
+ pmdaGetOptions(argc, argv, &opts, &dispatch);
+ if (opts.errors) {
+ pmdaUsageMessage(&opts);
+ exit(1);
+ }
+ if (opts.username)
+ username = opts.username;
+
+ pmdaOpenLog(&dispatch);
+ pmdaConnect(&dispatch);
+
+ bandwidth_init(&dispatch);
+ find_memory_bandwidth();
+
+ pmdaMain(&dispatch);
+
+ exit(0);
+}
diff --git a/src/pmdas/memory_bandwidth/pmns b/src/pmdas/memory_bandwidth/pmns
new file mode 100644
index 0000000..0cac2c7
--- /dev/null
+++ b/src/pmdas/memory_bandwidth/pmns
@@ -0,0 +1,19 @@
+/*
+ * Metrics for memory_bandwidth PMDA
+ *
+ * Copyright (c) 2016 Hemant K. Shaw, IBM Corporation.
+ *
+ * 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.
+ */
+
+memory_bandwidth {
+ max MEMORY_BANDWIDTH:0:0
+}
\ No newline at end of file
diff --git a/src/pmdas/memory_bandwidth/root b/src/pmdas/memory_bandwidth/root
new file mode 100644
index 0000000..d1e5855
--- /dev/null
+++ b/src/pmdas/memory_bandwidth/root
@@ -0,0 +1,8 @@
+/*
+ * fake "root" for validating the local PMNS subtree
+ */
+#include <stdpmid>
+
+root { memory_bandwidth }
+
+#include "pmns"
diff --git a/src/pmns/stdpmid.pcp b/src/pmns/stdpmid.pcp
index 9ed5b80..da83a63 100644
--- a/src/pmns/stdpmid.pcp
+++ b/src/pmns/stdpmid.pcp
@@ -113,6 +113,7 @@ CEPH 136
JSON 137
MIC 138
OPENBSD 139
+MEMORY_BANDWIDTH 238
### NEXT FREE SLOT ###
SCHIZO 241
SLOW_PYTHON 242
--
1.9.3
|