Hi,

The following patch adds a new module called "ipc", which gathers
data from the OS IPC resources, like semaphores in use,
message queues or bytes in shared memory.

It's useful when some applications get an IPC resource, but do not
unlock it on exit.

The module was developed from master branch version, and was tested in
Linux and AIX7, but might work fine for AIX5 and 6 too. The AIX port
was developed by Manuel L. Sanmartin, so credits for him.

Enjoy!

-- 
Regards,
Andrés J. Díaz
diff --git a/README b/README
index 811c594..37e7149 100644
--- a/README
+++ b/README
@@ -103,6 +103,10 @@ Features
       Interface traffic: Number of octets, packets and errors for each
       interface.
 
+    - ipc
+      IPC counters: semaphores used, number of allocated segments in shared
+      memory and more.
+
     - iptables
       Iptables' counters: Number of bytes that were matched by a certain
       iptables rule.
diff --git a/configure.in b/configure.in
index 8db24ca..d7a47b8 100644
--- a/configure.in
+++ b/configure.in
@@ -4327,6 +4327,7 @@ plugin_curl_xml="no"
 plugin_df="no"
 plugin_disk="no"
 plugin_entropy="no"
+plugin_ipc="no"
 plugin_interface="no"
 plugin_ipmi="no"
 plugin_ipvs="no"
@@ -4362,6 +4363,7 @@ then
 	plugin_cpu="yes"
 	plugin_cpufreq="yes"
 	plugin_disk="yes"
+	plugin_ipc="yes"
 	plugin_entropy="yes"
 	plugin_interface="yes"
 	plugin_irq="yes"
@@ -4636,6 +4638,7 @@ AC_PLUGIN([filecount],   [yes],                [Count files in directories])
 AC_PLUGIN([fscache],     [$plugin_fscache],    [fscache statistics])
 AC_PLUGIN([gmond],       [$with_libganglia],   [Ganglia plugin])
 AC_PLUGIN([hddtemp],     [yes],                [Query hddtempd])
+AC_PLUGIN([ipc],         [$plugin_ipc],        [IPC statistics])
 AC_PLUGIN([interface],   [$plugin_interface],  [Interface traffic statistics])
 AC_PLUGIN([ipmi],        [$plugin_ipmi],       [IPMI sensor statistics])
 AC_PLUGIN([iptables],    [$with_libiptc],      [IPTables rule counters])
@@ -4963,6 +4966,7 @@ Configuration:
     fscache . . . . . . . $enable_fscache
     gmond . . . . . . . . $enable_gmond
     hddtemp . . . . . . . $enable_hddtemp
+    ipc . . . . . . . . . $enable_ipc
     interface . . . . . . $enable_interface
     ipmi  . . . . . . . . $enable_ipmi
     iptables  . . . . . . $enable_iptables
diff --git a/src/Makefile.am b/src/Makefile.am
index 5728144..524400c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -469,6 +469,14 @@ collectd_LDADD += "-dlopen" ipvs.la
 collectd_DEPENDENCIES += ipvs.la
 endif
 
+if BUILD_PLUGIN_IPC
+pkglib_LTLIBRARIES += ipc.la
+ipc_la_SOURCES = ipc.c
+ipc_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" ipc.la
+collectd_DEPENDENCIES += ipc.la
+endif
+
 if BUILD_PLUGIN_IRQ
 pkglib_LTLIBRARIES += irq.la
 irq_la_SOURCES = irq.c
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
index 94cf2a9..e9fa46c 100644
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
@@ -79,6 +79,7 @@
 #@BUILD_PLUGIN_GMOND_TRUE@LoadPlugin gmond
 #@BUILD_PLUGIN_HDDTEMP_TRUE@LoadPlugin hddtemp
 @BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_PLUGIN_INTERFACE_TRUE@LoadPlugin interface
+@BUILD_PLUGIN_IPC_TRUE@@BUILD_PLUGIN_IPC_TRUE@LoadPlugin ipc
 #@BUILD_PLUGIN_IPTABLES_TRUE@LoadPlugin iptables
 #@BUILD_PLUGIN_IPMI_TRUE@LoadPlugin ipmi
 #@BUILD_PLUGIN_IPVS_TRUE@LoadPlugin ipvs
diff --git a/src/ipc.c b/src/ipc.c
new file mode 100644
index 0000000..c10cdb1
--- /dev/null
+++ b/src/ipc.c
@@ -0,0 +1,308 @@
+/**
+ * collectd - src/ipc.c, based on src/memcached.c
+ * Copyright (C) 2010       Andres J. Diaz <[email protected]>
+ * Copyright (C) 2010       Manuel L. Sanmartin <[email protected]>
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Andres J. Diaz <[email protected]>
+ *   Manuel L. Sanmartin <manuel.luis@gmail>
+ **/
+
+/* Many of this code is based on busybox ipc implementation, which is:
+ *   (C) Rodney Radford <[email protected]> and distributed under GPLv2.
+ */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#if KERNEL_LINUX
+  /* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
+  /* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
+  /* X/OPEN tells us to use <sys/{types,ipc,shm}.h> for shmctl() */
+# include <sys/types.h>
+# include <sys/ipc.h>
+# include <sys/sem.h>
+# include <sys/msg.h>
+# include <sys/shm.h>
+
+  /* For older kernels the same holds for the defines below */
+# ifndef MSG_STAT
+#  define MSG_STAT    11
+#  define MSG_INFO    12
+# endif
+
+# ifndef SHM_STAT
+#   define SHM_STAT        13
+#   define SHM_INFO        14
+    struct shm_info {
+        int used_ids;
+        ulong shm_tot;      /* total allocated shm */
+        ulong shm_rss;      /* total resident shm */
+        ulong shm_swp;      /* total swapped shm */
+        ulong swap_attempts;
+        ulong swap_successes;
+    };
+# endif
+
+# ifndef SEM_STAT
+#  define SEM_STAT    18
+#  define SEM_INFO    19
+# endif
+
+  /* The last arg of semctl is a union semun, but where is it defined?
+     X/OPEN tells us to define it ourselves, but until recently
+     Linux include files would also define it. */
+# if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
+    /* union semun is defined by including <sys/sem.h> */
+# else
+    /* according to X/OPEN we have to define it ourselves */
+    union semun {
+      int val;
+      struct semid_ds *buf;
+      unsigned short *array;
+      struct seminfo *__buf;
+    };
+# endif
+static long pagesize_g;
+/* #endif  KERNEL_LINUX */
+#elif KERNEL_AIX
+# include <sys/ipc_info.h>
+/* #endif KERNEL_AIX */
+#else
+# error "No applicable input method."
+#endif
+
+__attribute__ ((nonnull(1)))
+static void ipc_submit_g (const char *type, gauge_t value) /* {{{ */
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "ipc", sizeof (vl.plugin));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+
+  plugin_dispatch_values (&vl);
+} /* }}} */
+
+#if KERNEL_AIX
+static caddr_t ipc_get_info (cid_t cid, int cmd, int version, int stsize, int *nmemb) /* {{{ */
+{
+  int size = 0;
+  caddr_t buff = NULL;
+
+  if (get_ipc_info(cid, cmd, version, buff, &size) < 0)
+  {
+    if (errno != ENOSPC) {
+      char errbuf[1024];
+      WARNING ("ipc plugin: get_ipc_info: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+      return (NULL);
+    }
+  }
+
+  if (size == 0)
+    return NULL;
+
+  if (size % stsize) {
+    ERROR ("ipc plugin: ipc_get_info: missmatch struct size and buffer size");
+    return (NULL);
+  }
+
+  *nmemb = size / stsize;
+
+  buff = (caddr_t)malloc (size);
+  if (buff == NULL)  {
+    ERROR ("ipc plugin: ipc_get_info malloc failed.");
+    return (NULL);
+  }
+
+  if (get_ipc_info(cid, cmd, version, buff, &size) < 0)
+  {
+    char errbuf[1024];
+    WARNING ("ipc plugin: get_ipc_info: %s",
+      sstrerror (errno, errbuf, sizeof (errbuf)));
+    free(buff);
+    return (NULL);
+  }
+
+  return buff;
+} /* }}} */
+#endif /* KERNEL_AIX */
+
+static int ipc_read_sem (void) /* {{{ */
+{
+#if KERNEL_LINUX
+  struct seminfo seminfo;
+  union semun arg;
+
+  arg.array = (ushort *) (void *) &seminfo;
+
+  if ( semctl(0, 0, SEM_INFO, arg) < 0 )
+  {
+    ERROR("Kernel is not configured for semaphores");
+    return (-1);
+  }
+
+  ipc_submit_g("sem_used_arrays", seminfo.semusz);
+  ipc_submit_g("sem_used", seminfo.semaem);
+
+/* #endif KERNEL_LINUX */
+#elif KERNEL_AIX
+  ipcinfo_sem_t *ipcinfo_sem;
+  unsigned short sem_nsems=0;
+  unsigned short sems=0;
+  int i,n;
+
+  ipcinfo_sem = (ipcinfo_sem_t *)ipc_get_info(0,
+    GET_IPCINFO_SEM_ALL, IPCINFO_SEM_VERSION, sizeof(ipcinfo_sem_t), &n);
+  if (ipcinfo_sem == NULL)
+    return -1;
+
+  for (i=0; i<n; i++) {
+    sem_nsems += ipcinfo_sem[i].sem_nsems;
+    sems++;
+  }
+  free(ipcinfo_sem);
+
+  ipc_submit_g("sem_used_arrays", sem_nsems);
+  ipc_submit_g("sem_used", sems);
+#endif /* KERNEL_AIX */
+
+  return (0);
+}
+/* }}} */
+
+static int ipc_read_shm (void) /* {{{ */
+{
+#if KERNEL_LINUX
+  struct shm_info shm_info;
+  pagesize_g = sysconf(_SC_PAGESIZE);
+
+  if ( shmctl(0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info) < 0 )
+  {
+    ERROR("Kernel is not configured for shared memory");
+    return (-1);
+  }
+  ipc_submit_g("shm_segments", shm_info.used_ids);
+  ipc_submit_g("shm_bytes_total", shm_info.shm_tot * pagesize_g);
+  ipc_submit_g("shm_bytes_rss", shm_info.shm_rss * pagesize_g);
+  ipc_submit_g("shm_bytes_swapped", shm_info.shm_swp * pagesize_g);
+/* #endif KERNEL_LINUX */
+#elif KERNEL_AIX
+  ipcinfo_shm_t *ipcinfo_shm;
+  ipcinfo_shm_t *pshm;
+  unsigned int shm_segments=0;
+  size64_t shm_bytes=0;
+  int i,n;
+
+  ipcinfo_shm = (ipcinfo_shm_t *)ipc_get_info(0,
+    GET_IPCINFO_SHM_ALL, IPCINFO_SHM_VERSION, sizeof(ipcinfo_shm_t), &n);
+  if (ipcinfo_shm == NULL)
+    return -1;
+
+  for (i=0, pshm=ipcinfo_shm; i<n; i++, pshm++) {
+    shm_segments++;
+    shm_bytes += pshm->shm_segsz;
+  }
+  free(ipcinfo_shm);
+
+  ipc_submit_g("shm_segments", shm_segments);
+  ipc_submit_g("shm_bytes_total", shm_bytes);
+
+#endif /* KERNEL_AIX */
+  return (0);
+}
+/* }}} */
+
+static int ipc_read_msg (void) /* {{{ */
+{
+#if KERNEL_LINUX
+  struct msginfo msginfo;
+
+  if ( msgctl(0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo) < 0 )
+  {
+    ERROR("Kernel is not configured for message queues");
+    return (-1);
+  }
+  ipc_submit_g("msg_alloc_queues", msginfo.msgmni);
+  ipc_submit_g("msg_used_headers", msginfo.msgmap);
+  ipc_submit_g("msg_used_space", msginfo.msgtql);
+/* #endif KERNEL_LINUX */
+#elif KERNEL_AIX
+  ipcinfo_msg_t *ipcinfo_msg;
+  uint32_t msg_used_space=0;
+  uint32_t msg_alloc_queues=0;
+  msgqnum32_t msg_qnum=0;
+  int i,n;
+
+  ipcinfo_msg = (ipcinfo_msg_t *)ipc_get_info(0,
+    GET_IPCINFO_MSG_ALL, IPCINFO_MSG_VERSION, sizeof(ipcinfo_msg_t), &n);
+  if (ipcinfo_msg == NULL)
+    return -1;
+
+  for (i=0; i<n; i++) {
+    msg_alloc_queues++;
+    msg_used_space += ipcinfo_msg[i].msg_cbytes;
+    msg_qnum += ipcinfo_msg[i].msg_qnum;
+  }
+  free(ipcinfo_msg);
+
+  ipc_submit_g("msg_alloc_queues", msg_alloc_queues);
+  ipc_submit_g("msg_used_headers", msg_qnum);
+  ipc_submit_g("msg_used_space", msg_used_space);
+#endif /* KERNEL_AIX */
+  return (0);
+}
+/* }}} */
+
+static int ipc_read (void) /* {{{ */
+{
+  int x = 0;
+  x |= ipc_read_shm();
+  x |= ipc_read_sem();
+  x |= ipc_read_msg();
+
+  return (x);
+}
+/* }}} */
+
+#ifdef KERNEL_LINUX
+static int ipc_init (void) /* {{{ */
+{
+  pagesize_g = sysconf(_SC_PAGESIZE);
+  return (0);
+}
+/* }}} */
+#endif /* KERNEL_LINUX */
+
+void module_register (void) /* {{{ */
+{
+#ifdef KERNEL_LINUX
+  plugin_register_init ("ipc", ipc_init);
+#endif
+  plugin_register_read ("ipc", ipc_read);
+}
+/* }}} */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/types.db b/src/types.db
index e6345ab..1fb1062 100644
--- a/src/types.db
+++ b/src/types.db
@@ -90,6 +90,9 @@ memcached_items		value:GAUGE:0:U
 memcached_octets	rx:DERIVE:0:U, tx:DERIVE:0:U
 memcached_ops		value:DERIVE:0:U
 memory			value:GAUGE:0:281474976710656
+msg_alloc_queues value:GAUGE:0:9223372036854775807
+msg_used_headers value:GAUGE:0:9223372036854775807
+msg_used_space value:GAUGE:0:9223372036854775807
 multimeter		value:GAUGE:U:U
 mysql_commands		value:DERIVE:0:U
 mysql_handler		value:DERIVE:0:U
@@ -136,7 +139,13 @@ response_time		value:GAUGE:0:U
 route_etx		value:GAUGE:0:U
 route_metric		value:GAUGE:0:U
 routes			value:GAUGE:0:U
-serial_octets		rx:DERIVE:0:U, tx:DERIVE:0:U
+sem_used     value:GAUGE:0:9223372036854775807
+sem_used_arrays     value:GAUGE:0:9223372036854775807
+serial_octets rx:DERIVE:0:U, tx:DERIVE:0:U
+shm_segments      value:GAUGE:0:281474976710656
+shm_bytes_total       value:GAUGE:0:9223372036854775807
+shm_bytes_rss       value:GAUGE:0:9223372036854775807
+shm_bytes_swapped     value:GAUGE:0:9223372036854775807
 signal_noise		value:GAUGE:U:0
 signal_power		value:GAUGE:U:0
 signal_quality		value:GAUGE:0:U

Attachment: signature.asc
Description: PGP signature

_______________________________________________
collectd mailing list
[email protected]
http://mailman.verplant.org/listinfo/collectd

Reply via email to