Merge branch 'ym/utils_cache_bugfix'
authorFlorian Forster <octo@collectd.org>
Thu, 4 Oct 2012 08:16:56 +0000 (10:16 +0200)
committerFlorian Forster <octo@collectd.org>
Thu, 4 Oct 2012 08:16:56 +0000 (10:16 +0200)
22 files changed:
bindings/Makefile.am
configure.in
contrib/collectd_network.py
src/Makefile.am
src/apcups.c
src/collectd.c
src/common.c
src/contextswitch.c
src/curl_xml.c
src/ethstat.c
src/exec.c
src/meta_data.c
src/netlink.c
src/network.c
src/processes.c
src/swap.c
src/tcpconns.c
src/unixsock.c
src/uptime.c
src/utils_db_query.c
src/utils_fbhash.c
src/zfs_arc.c

index f39e9bb..69312fd 100644 (file)
@@ -23,7 +23,7 @@ perl: perl/Makefile
 
 perl/Makefile: .perl-directory-stamp perl/Makefile.PL \
        $(top_builddir)/config.status
-       cd perl && @PERL@ Makefile.PL PREFIX=$(prefix) @PERL_BINDINGS_OPTIONS@
+       cd perl && @PERL@ Makefile.PL INSTALL_BASE=$(prefix) @PERL_BINDINGS_OPTIONS@
 
 .perl-directory-stamp:
        if test ! -d perl; then \
index a63544a..b33cc90 100644 (file)
@@ -1228,6 +1228,7 @@ AC_CHECK_MEMBERS([struct kinfo_proc.ki_pid, struct kinfo_proc.ki_rssize, struct
                have_struct_kinfo_proc_freebsd="no"
        ],
        [
+AC_INCLUDES_DEFAULT
 #include <kvm.h>
 #include <sys/param.h>
 #include <sys/sysctl.h>
@@ -1244,6 +1245,7 @@ AC_CHECK_MEMBERS([struct kinfo_proc.kp_proc, struct kinfo_proc.kp_eproc],
                have_struct_kinfo_proc_openbsd="no"
        ],
        [
+AC_INCLUDES_DEFAULT
 #include <sys/param.h>
 #include <sys/sysctl.h>
 #include <kvm.h>
@@ -1903,10 +1905,12 @@ fi
 # This could be in iptc or ip4tc
 if test "x$with_libiptc" = "xpkgconfig"
 then
+       SAVE_LIBS="$LIBS"
        AC_SEARCH_LIBS(iptc_init, [iptc ip4tc],
                        [with_libiptc="pkgconfig"],
                        [with_libiptc="no"],
                        [$with_libiptc_libs])
+       LIBS="$SAVE_LIBS"
 fi
 if test "x$with_libiptc" = "xpkgconfig"
 then
@@ -2505,6 +2509,76 @@ then
 fi
 if test "x$with_libnetlink" = "xyes"
 then
+       SAVE_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS $with_libnetlink_cflags"
+
+       AC_CACHE_CHECK(
+               [if function 'rtnl_dump_filter' expects five arguments],
+               [c_cv_rtnl_dump_filter_five_args],
+               AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+                               [
+AC_INCLUDES_DEFAULT
+#include <asm/types.h>
+#include <sys/socket.h>
+#if HAVE_LIBNETLINK_H
+# include <libnetlink.h>
+#elif HAVE_IPROUTE_LIBNETLINK_H
+# include <iproute/libnetlink.h>
+#elif HAVE_LINUX_LIBNETLINK_H
+# include <linux/libnetlink.h>
+#endif
+                               ],
+                               [
+if (rtnl_dump_filter(NULL, NULL, NULL, NULL, NULL))
+       return 1;
+return 0;
+                               ]
+                       )],
+                       [c_cv_rtnl_dump_filter_five_args="yes"],
+                       [c_cv_rtnl_dump_filter_five_args="no"]
+               )
+       )
+
+       AC_CACHE_CHECK(
+               [if function 'rtnl_dump_filter' expects three arguments],
+               [c_cv_rtnl_dump_filter_three_args],
+               AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+                               [
+AC_INCLUDES_DEFAULT
+#include <asm/types.h>
+#include <sys/socket.h>
+#if HAVE_LIBNETLINK_H
+# include <libnetlink.h>
+#elif HAVE_IPROUTE_LIBNETLINK_H
+# include <iproute/libnetlink.h>
+#elif HAVE_LINUX_LIBNETLINK_H
+# include <linux/libnetlink.h>
+#endif
+                               ],
+                               [
+if (rtnl_dump_filter(NULL, NULL, NULL))
+       return 1;
+return 0;
+                               ]
+                       )],
+                       [c_cv_rtnl_dump_filter_three_args="yes"],
+                       [c_cv_rtnl_dump_filter_three_args="no"]
+               )
+       )
+
+       CFLAGS="$SAVE_CFLAGS"
+
+       if test "x$c_cv_rtnl_dump_filter_five_args" = "xyes"
+       then
+               AC_DEFINE(RTNL_DUMP_FILTER_FIVE_ARGS, 1,
+                               [Define to 1 if function 'rtnl_dump_filter' expects five arguments.])
+       fi
+       if test "x$c_cv_rtnl_dump_filter_three_args" = "xyes"
+       then
+               AC_DEFINE(RTNL_DUMP_FILTER_THREE_ARGS, 1,
+                               [Define to 1 if function 'rtnl_dump_filter' expects three arguments.])
+       fi
+
        BUILD_WITH_LIBNETLINK_CFLAGS="$with_libnetlink_cflags"
        BUILD_WITH_LIBNETLINK_LIBS="$with_libnetlink_libs"
        AC_SUBST(BUILD_WITH_LIBNETLINK_CFLAGS)
@@ -4060,7 +4134,7 @@ AC_ARG_WITH(libvarnish, [AS_HELP_STRING([--with-libvarnish@<:@=PREFIX@:>@], [Pat
        then
                AC_MSG_NOTICE([Not checking for libvarnish: Manually configured])
                with_libvarnish_cflags="-I$withval/include"
-               with_libvarnish_libs="-L$withval/lib -lvarnish -lvarnishcompat -lvarnishapi"
+               with_libvarnish_libs="-L$withval/lib -lvarnishapi"
                with_libvarnish="yes"
        fi; fi; fi
 ],
@@ -4563,11 +4637,13 @@ fi
 if test "x$with_perfstat" = "xyes"
 then
        plugin_cpu="yes"
+       plugin_contextswitch="yes"
        plugin_disk="yes"
        plugin_memory="yes"
        plugin_swap="yes"
        plugin_interface="yes"
        plugin_load="yes"
+       plugin_uptime="yes"
 fi
 
 if test "x$with_procinfo" = "xyes"
index 0a5d57e..9af0fb0 100644 (file)
@@ -4,7 +4,7 @@
 #
 # Copyright © 2009 Adrian Perez <aperez@igalia.com>
 #
-# Distributed under terms of the GPLv2 license.
+# Distributed under terms of the GPLv2 license or newer.
 # 
 # Frank Marien (frank@apsu.be) 6 Sep 2012
 # - quick fixes for 5.1 binary protocol
index eef2a60..2eac044 100644 (file)
@@ -213,6 +213,10 @@ if BUILD_PLUGIN_CONTEXTSWITCH
 pkglib_LTLIBRARIES += contextswitch.la
 contextswitch_la_SOURCES = contextswitch.c
 contextswitch_la_LDFLAGS = -module -avoid-version
+contextswitch_la_LIBADD =
+if BUILD_WITH_PERFSTAT
+contextswitch_la_LIBADD += -lperfstat
+endif
 collectd_LDADD += "-dlopen" contextswitch.la
 collectd_DEPENDENCIES += contextswitch.la
 endif
@@ -1192,6 +1196,9 @@ uptime_la_LIBADD =
 if BUILD_WITH_LIBKSTAT
 uptime_la_LIBADD += -lkstat
 endif
+if BUILD_WITH_PERFSTAT
+uptime_la_LIBADD += -lperfstat
+endif
 collectd_LDADD += "-dlopen" uptime.la
 collectd_DEPENDENCIES += uptime.la
 endif
index a0629d5..4fbbde6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * collectd - src/apcups.c
- * Copyright (C) 2006-2007  Florian octo Forster
+ * Copyright (C) 2006-2012  Florian octo Forster
  * Copyright (C) 2006       Anthony Gialluca <tonyabg at charter.net>
  * Copyright (C) 2000-2004  Kern Sibbald
  * Copyright (C) 1996-1999  Andre M. Hedrick <andre at suse.com>
@@ -73,6 +73,10 @@ static int   conf_port = NISPORT;
 
 static int global_sockfd = -1;
 
+static int count_retries = 0;
+static int count_iterations = 0;
+static _Bool close_socket = 0;
+
 static const char *config_keys[] =
 {
        "Host",
@@ -81,26 +85,31 @@ static const char *config_keys[] =
 };
 static int config_keys_num = 2;
 
-/* Close the network connection */
-static int apcups_shutdown (void)
+static int net_shutdown (int *fd)
 {
        uint16_t packet_size = 0;
 
-       if (global_sockfd < 0)
-               return (0);
+       if ((fd == NULL) || (*fd < 0))
+               return (EINVAL);
 
-       DEBUG ("Gracefully shutting down socket %i.", global_sockfd);
+       swrite (*fd, (void *) &packet_size, sizeof (packet_size));
+       close (*fd);
+       *fd = -1;
 
-       /* send EOF sentinel */
-       swrite (global_sockfd, (void *) &packet_size, sizeof (packet_size));
+       return (0);
+} /* int net_shutdown */
 
-       close (global_sockfd);
-       global_sockfd = -1;
+/* Close the network connection */
+static int apcups_shutdown (void)
+{
+       if (global_sockfd < 0)
+               return (0);
 
+       net_shutdown (&global_sockfd);
        return (0);
 } /* int apcups_shutdown */
 
-/*     
+/*
  * Open a TCP connection to the UPS network server
  * Returns -1 on error
  * Returns socket file descriptor otherwise
@@ -170,7 +179,7 @@ static int net_open (char *host, int port)
        return (sd);
 } /* int net_open (char *host, char *service, int port) */
 
-/* 
+/*
  * Receive a message from the other end. Each message consists of
  * two packets. The first is a header that contains the size
  * of the data that follows in the second packet.
@@ -186,6 +195,7 @@ static int net_recv (int *sockfd, char *buf, int buflen)
        /* get data size -- in short */
        if (sread (*sockfd, (void *) &packet_size, sizeof (packet_size)) != 0)
        {
+               close (*sockfd);
                *sockfd = -1;
                return (-1);
        }
@@ -193,7 +203,11 @@ static int net_recv (int *sockfd, char *buf, int buflen)
        packet_size = ntohs (packet_size);
        if (packet_size > buflen)
        {
-               DEBUG ("record length too large");
+               ERROR ("apcups plugin: Received %"PRIu16" bytes of payload "
+                               "but have only %i bytes of buffer available.",
+                               packet_size, buflen);
+               close (*sockfd);
+               *sockfd = -1;
                return (-2);
        }
 
@@ -203,6 +217,7 @@ static int net_recv (int *sockfd, char *buf, int buflen)
        /* now read the actual data */
        if (sread (*sockfd, (void *) buf, packet_size) != 0)
        {
+               close (*sockfd);
                *sockfd = -1;
                return (-1);
        }
@@ -229,6 +244,7 @@ static int net_send (int *sockfd, char *buff, int len)
 
        if (swrite (*sockfd, (void *) &packet_size, sizeof (packet_size)) != 0)
        {
+               close (*sockfd);
                *sockfd = -1;
                return (-1);
        }
@@ -236,6 +252,7 @@ static int net_send (int *sockfd, char *buff, int len)
        /* send data packet */
        if (swrite (*sockfd, (void *) buff, len) != 0)
        {
+               close (*sockfd);
                *sockfd = -1;
                return (-2);
        }
@@ -253,6 +270,8 @@ static int apc_query_server (char *host, int port,
        char   *toksaveptr;
        char   *key;
        double  value;
+       _Bool retry = 1;
+       int status;
 
 #if APCMAIN
 # define PRINT_VALUE(name, val) printf("  Found property: name = %s; value = %f;\n", name, val)
@@ -260,21 +279,51 @@ static int apc_query_server (char *host, int port,
 # define PRINT_VALUE(name, val) /**/
 #endif
 
-       if (global_sockfd < 0)
+       while (retry)
        {
-               global_sockfd = net_open (host, port);
                if (global_sockfd < 0)
                {
-                       ERROR ("apcups plugin: Connecting to the "
-                                       "apcupsd failed.");
+                       global_sockfd = net_open (host, port);
+                       if (global_sockfd < 0)
+                       {
+                               ERROR ("apcups plugin: Connecting to the "
+                                               "apcupsd failed.");
+                               return (-1);
+                       }
+               }
+
+
+               status = net_send (&global_sockfd, "status", strlen ("status"));
+               if (status != 0)
+               {
+                       /* net_send is closing the socket on error. */
+                       assert (global_sockfd < 0);
+                       if (retry)
+                       {
+                               retry = 0;
+                               count_retries++;
+                               continue;
+                       }
+
+                       ERROR ("apcups plugin: Writing to the socket failed.");
                        return (-1);
                }
-       }
 
-       if (net_send (&global_sockfd, "status", 6) < 0)
+               break;
+       } /* while (retry) */
+
+        /* When collectd's collection interval is larger than apcupsd's
+         * timeout, we would have to retry / re-connect each iteration. Try to
+         * detect this situation and shut down the socket gracefully in that
+         * case. Otherwise, keep the socket open to avoid overhead. */
+       count_iterations++;
+       if ((count_iterations == 10) && (count_retries > 2))
        {
-               ERROR ("apcups plugin: Writing to the socket failed.");
-               return (-1);
+               NOTICE ("apcups plugin: There have been %i retries in the "
+                               "first %i iterations. Will close the socket "
+                               "in future iterations.",
+                               count_retries, count_iterations);
+               close_socket = 1;
        }
 
        while ((n = net_recv (&global_sockfd, recvline, sizeof (recvline) - 1)) > 0)
@@ -298,7 +347,7 @@ static int apc_query_server (char *host, int port,
 
                        if (strcmp ("LINEV", key) == 0)
                                apcups_detail->linev = value;
-                       else if (strcmp ("BATTV", key) == 0) 
+                       else if (strcmp ("BATTV", key) == 0)
                                apcups_detail->battv = value;
                        else if (strcmp ("ITEMP", key) == 0)
                                apcups_detail->itemp = value;
@@ -316,10 +365,16 @@ static int apc_query_server (char *host, int port,
                        tokptr = strtok_r (NULL, ":", &toksaveptr);
                } /* while (tokptr != NULL) */
        }
-       
+       status = errno; /* save errno, net_shutdown() may re-set it. */
+
+       if (close_socket)
+               net_shutdown (&global_sockfd);
+
        if (n < 0)
        {
-               WARNING ("apcups plugin: Error reading from socket");
+               char errbuf[1024];
+               ERROR ("apcups plugin: Reading from socket failed: %s",
+                               sstrerror (status, errbuf, sizeof (errbuf)));
                return (-1);
        }
 
@@ -398,12 +453,12 @@ static int apcups_read (void)
        apcups_detail.timeleft =   -1.0;
        apcups_detail.itemp    = -300.0;
        apcups_detail.linefreq =   -1.0;
-  
+
        status = apc_query_server (conf_host == NULL
                        ? APCUPS_DEFAULT_HOST
                        : conf_host,
                        conf_port, &apcups_detail);
+
        /*
         * if we did not connect then do not bother submitting
         * zeros. We want rrd files to have NAN.
index 915560c..ceb184b 100644 (file)
@@ -79,6 +79,7 @@ static void sig_usr1_handler (int __attribute__((unused)) signal)
        pthread_attr_init (&attr);
        pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
        pthread_create (&thread, &attr, do_flush, NULL);
+       pthread_attr_destroy (&attr);
 }
 
 static int init_hostname (void)
index 406482a..0bd9f68 100644 (file)
@@ -636,24 +636,23 @@ long long get_kstat_value (kstat_t *ksp, char *name)
        kstat_named_t *kn;
        long long retval = -1LL;
 
-#ifdef assert
-       assert (ksp != NULL);
-       assert (ksp->ks_type == KSTAT_TYPE_NAMED);
-#else
        if (ksp == NULL)
        {
-               ERROR ("ERROR: %s:%i: ksp == NULL\n", __FILE__, __LINE__);
+               ERROR ("get_kstat_value (\"%s\"): ksp is NULL.", name);
                return (-1LL);
        }
        else if (ksp->ks_type != KSTAT_TYPE_NAMED)
        {
-               ERROR ("ERROR: %s:%i: ksp->ks_type != KSTAT_TYPE_NAMED\n", __FILE__, __LINE__);
+               ERROR ("get_kstat_value (\"%s\"): ksp->ks_type (%#x) "
+                               "is not KSTAT_TYPE_NAMED (%#x).",
+                               name,
+                               (unsigned int) ksp->ks_type,
+                               (unsigned int) KSTAT_TYPE_NAMED);
                return (-1LL);
        }
-#endif
 
        if ((kn = (kstat_named_t *) kstat_data_lookup (ksp, name)) == NULL)
-               return (retval);
+               return (-1LL);
 
        if (kn->data_type == KSTAT_DATA_INT32)
                retval = (long long) kn->value.i32;
index c207318..344f76e 100644 (file)
 /* no global variables */
 /* #endif KERNEL_LINUX */
 
+#elif HAVE_PERFSTAT
+# include <sys/protosw.h>
+# include <libperfstat.h>
+/* #endif HAVE_PERFSTAT */
+
 #else
 # error "No applicable input method."
 #endif
@@ -121,7 +126,24 @@ static int cs_read (void)
 
        if (status == -2)
                ERROR ("contextswitch plugin: Unable to find context switch value.");
-#endif /* KERNEL_LINUX */
+/* #endif  KERNEL_LINUX */
+
+#elif HAVE_PERFSTAT
+       int status = 0;
+       perfstat_cpu_total_t perfcputotal;
+
+       status = perfstat_cpu_total(NULL, &perfcputotal, sizeof(perfstat_cpu_total_t), 1);
+       if (status < 0)
+       {
+               char errbuf[1024];
+               ERROR ("contextswitch plugin: perfstat_cpu_total: %s",
+                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       cs_submit(perfcputotal.pswitch);
+       status = 0;
+#endif /* defined(HAVE_PERFSTAT) */
 
        return status;
 }
index 052ea1e..46e0d49 100644 (file)
@@ -419,7 +419,8 @@ static int cx_handle_instance_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */
   return (0);
 } /* }}} int cx_handle_instance_xpath */
 
-static int  cx_handle_base_xpath (char *plugin_instance, /* {{{ */
+static int  cx_handle_base_xpath (char const *plugin_instance, /* {{{ */
+    char const *host,
     xmlXPathContextPtr xpath_ctx, const data_set_t *ds, 
     char *base_xpath, cx_xpath_t *xpath)
 {
@@ -461,7 +462,7 @@ static int  cx_handle_base_xpath (char *plugin_instance, /* {{{ */
   vl.values_len = ds->ds_num;
   sstrncpy (vl.type, xpath->type, sizeof (vl.type));
   sstrncpy (vl.plugin, "curl_xml", sizeof (vl.plugin));
-  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.host, (host != NULL) ? host : hostname_g, sizeof (vl.host));
   if (plugin_instance != NULL)
     sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); 
 
@@ -504,7 +505,8 @@ static int cx_handle_parsed_xml(xmlDocPtr doc, /* {{{ */
     ds = plugin_get_ds (xpath->type);
 
     if ( (cx_check_type(ds, xpath) == 0) &&
-         (cx_handle_base_xpath(db->instance, xpath_ctx, ds, le->key, xpath) == 0) )
+         (cx_handle_base_xpath(db->instance, db->host,
+                               xpath_ctx, ds, le->key, xpath) == 0) )
       status = 0; /* we got atleast one success */
 
     le = le->next;
index ae1b689..08381a8 100644 (file)
@@ -66,6 +66,7 @@ static int ethstat_add_interface (const oconfig_item_t *ci) /* {{{ */
   if (tmp == NULL)
     return (-1);
   interfaces = tmp;
+  interfaces[interfaces_num] = NULL;
 
   status = cf_util_get_string (ci, interfaces + interfaces_num);
   if (status != 0)
@@ -104,7 +105,7 @@ static int ethstat_add_map (const oconfig_item_t *ci) /* {{{ */
   memset (map, 0, sizeof (*map));
 
   sstrncpy (map->type, ci->values[1].value.string, sizeof (map->type));
-  if (ci->values_num == 2)
+  if (ci->values_num == 3)
     sstrncpy (map->type_instance, ci->values[2].value.string,
         sizeof (map->type_instance));
 
index c5ea155..0e807c7 100644 (file)
@@ -635,17 +635,22 @@ static void *exec_read_one (void *arg) /* {{{ */
 
       if (len < 0)
       {
-        if (errno == EAGAIN || errno == EINTR)  continue;
+        if (errno == EAGAIN || errno == EINTR)
+          continue;
         break;
       }
       else if (len == 0)
       {
         /* We've reached EOF */
-        NOTICE ("exec plugin: Program `%s' has closed STDERR.",
-            pl->exec);
-        close (fd_err);
+        NOTICE ("exec plugin: Program `%s' has closed STDERR.", pl->exec);
+
+        /* Remove file descriptor form select() set. */
         FD_CLR (fd_err, &fdset);
+        copy = fdset;
         highest_fd = fd;
+
+        /* Clean up file descriptor */
+        close (fd_err);
         fd_err = -1;
         continue;
       }
@@ -822,6 +827,7 @@ static int exec_read (void) /* {{{ */
     pthread_attr_init (&attr);
     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
     pthread_create (&t, &attr, exec_read_one, (void *) pl);
+    pthread_attr_destroy (&attr);
   } /* for (pl) */
 
   return (0);
@@ -865,6 +871,7 @@ static int exec_notification (const notification_t *n, /* {{{ */
     pthread_attr_init (&attr);
     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
     pthread_create (&t, &attr, exec_notification_one, (void *) pln);
+    pthread_attr_destroy (&attr);
   } /* for (pl) */
 
   return (0);
index b502b37..ea98ba9 100644 (file)
@@ -250,6 +250,7 @@ void meta_data_destroy (meta_data_t *md) /* {{{ */
   if (md == NULL)
     return;
 
+  pthread_mutex_destroy(&md->lock);
   md_entry_free (md->head);
   pthread_mutex_destroy (&md->lock);
   free (md);
index ef851d3..7c4bef5 100644 (file)
@@ -570,8 +570,14 @@ static int ir_read (void)
     return (-1);
   }
 
+#ifdef RTNL_DUMP_FILTER_FIVE_ARGS
   if (rtnl_dump_filter (&rth, link_filter, /* arg1 = */ NULL,
        NULL, NULL) != 0)
+#elif defined(RTNL_DUMP_FILTER_THREE_ARGS)
+  if (rtnl_dump_filter (&rth, link_filter, /* arg = */ NULL) != 0)
+#else
+#error "Failed to determine the number of arguments to 'rtnl_dump_filter'!"
+#endif
   {
     ERROR ("netlink plugin: ir_read: rtnl_dump_filter failed.");
     return (-1);
@@ -608,8 +614,14 @@ static int ir_read (void)
        continue;
       }
 
+#ifdef RTNL_DUMP_FILTER_FIVE_ARGS
       if (rtnl_dump_filter (&rth, qos_filter, (void *) &ifindex,
            NULL, NULL) != 0)
+#elif defined(RTNL_DUMP_FILTER_THREE_ARGS)
+      if (rtnl_dump_filter (&rth, qos_filter, /* arg = */ &ifindex) != 0)
+#else
+#error "Failed to determine the number of arguments to 'rtnl_dump_filter'!"
+#endif
       {
        ERROR ("netlink plugin: ir_read: rtnl_dump_filter failed.");
        continue;
index 5fed1b1..0b299d6 100644 (file)
@@ -58,6 +58,7 @@
 #endif
 
 #if HAVE_LIBGCRYPT
+# include <pthread.h>
 # include <gcrypt.h>
 GCRY_THREAD_OPTION_PTHREAD_IMPL;
 #endif
@@ -1665,7 +1666,7 @@ static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
                                        sizeof (network_config_ttl)) != 0)
                {
                        char errbuf[1024];
-                       ERROR ("setsockopt: %s",
+                       ERROR ("network plugin: setsockopt (ipv4-ttl): %s",
                                        sstrerror (errno, errbuf, sizeof (errbuf)));
                        return (-1);
                }
@@ -1686,7 +1687,7 @@ static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
                                        sizeof (network_config_ttl)) != 0)
                {
                        char errbuf[1024];
-                       ERROR ("setsockopt: %s",
+                       ERROR ("network plugin: setsockopt(ipv6-ttl): %s",
                                        sstrerror (errno, errbuf,
                                                sizeof (errbuf)));
                        return (-1);
@@ -1733,7 +1734,7 @@ static int network_set_interface (const sockent_t *se, const struct addrinfo *ai
                                                &mreq, sizeof (mreq)) != 0)
                        {
                                char errbuf[1024];
-                               ERROR ("setsockopt: %s",
+                               ERROR ("network plugin: setsockopt (ipv4-multicast-if): %s",
                                                sstrerror (errno, errbuf, sizeof (errbuf)));
                                return (-1);
                        }
@@ -1752,7 +1753,7 @@ static int network_set_interface (const sockent_t *se, const struct addrinfo *ai
                                                sizeof (se->interface)) != 0)
                        {
                                char errbuf[1024];
-                               ERROR ("setsockopt: %s",
+                               ERROR ("network plugin: setsockopt (ipv6-multicast-if): %s",
                                                sstrerror (errno, errbuf,
                                                        sizeof (errbuf)));
                                return (-1);
@@ -1778,7 +1779,7 @@ static int network_set_interface (const sockent_t *se, const struct addrinfo *ai
                                        sizeof(interface_name)) == -1 )
                {
                        char errbuf[1024];
-                       ERROR ("setsockopt: %s",
+                       ERROR ("network plugin: setsockopt (bind-if): %s",
                                        sstrerror (errno, errbuf, sizeof (errbuf)));
                        return (-1);
                }
@@ -1802,14 +1803,18 @@ static int network_set_interface (const sockent_t *se, const struct addrinfo *ai
 
 static int network_bind_socket (int fd, const struct addrinfo *ai, const int interface_idx)
 {
+#if KERNEL_SOLARIS
+       char loop   = 0;
+#else
        int loop = 0;
+#endif
        int yes  = 1;
 
        /* allow multiple sockets to use the same PORT number */
        if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
                                &yes, sizeof(yes)) == -1) {
                 char errbuf[1024];
-                ERROR ("setsockopt: %s", 
+                ERROR ("network plugin: setsockopt (reuseaddr): %s",
                                 sstrerror (errno, errbuf, sizeof (errbuf)));
                return (-1);
        }
@@ -1852,7 +1857,7 @@ static int network_bind_socket (int fd, const struct addrinfo *ai, const int int
                                                &loop, sizeof (loop)) == -1)
                        {
                                char errbuf[1024];
-                               ERROR ("setsockopt: %s",
+                               ERROR ("network plugin: setsockopt (multicast-loop): %s",
                                                sstrerror (errno, errbuf,
                                                        sizeof (errbuf)));
                                return (-1);
@@ -1862,7 +1867,7 @@ static int network_bind_socket (int fd, const struct addrinfo *ai, const int int
                                                &mreq, sizeof (mreq)) == -1)
                        {
                                char errbuf[1024];
-                               ERROR ("setsockopt: %s",
+                               ERROR ("network plugin: setsockopt (add-membership): %s",
                                                sstrerror (errno, errbuf,
                                                        sizeof (errbuf)));
                                return (-1);
@@ -1900,7 +1905,7 @@ static int network_bind_socket (int fd, const struct addrinfo *ai, const int int
                                                &loop, sizeof (loop)) == -1)
                        {
                                char errbuf[1024];
-                               ERROR ("setsockopt: %s",
+                               ERROR ("network plugin: setsockopt (ipv6-multicast-loop): %s",
                                                sstrerror (errno, errbuf,
                                                        sizeof (errbuf)));
                                return (-1);
@@ -1910,7 +1915,7 @@ static int network_bind_socket (int fd, const struct addrinfo *ai, const int int
                                                &mreq, sizeof (mreq)) == -1)
                        {
                                char errbuf[1024];
-                               ERROR ("setsockopt: %s",
+                               ERROR ("network plugin: setsockopt (ipv6-add-membership): %s",
                                                sstrerror (errno, errbuf,
                                                        sizeof (errbuf)));
                                return (-1);
@@ -1938,7 +1943,7 @@ static int network_bind_socket (int fd, const struct addrinfo *ai, const int int
                                        sizeof(interface_name)) == -1 )
                {
                        char errbuf[1024];
-                       ERROR ("setsockopt: %s",
+                       ERROR ("network plugin: setsockopt (bind-if): %s",
                                        sstrerror (errno, errbuf, sizeof (errbuf)));
                        return (-1);
                }
index 66237dc..c77859d 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright (C) 2009       Andrés J. Díaz
  * Copyright (C) 2009       Manuel Sanmartin
  * Copyright (C) 2010       Clément Stenac
+ * Copyright (C) 2012       Cosmin Ioiart
  *
  * 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
@@ -30,6 +31,7 @@
  *   Andrés J. Díaz <ajdiaz at connectical.com>
  *   Manuel Sanmartin
  *   Clément Stenac <clement.stenac at diwi.org>
+ *   Cosmin Ioiart <cioiart at gmail.com>
  **/
 
 #include "collectd.h"
 #define MAXARGLN 1024
 /* #endif HAVE_PROCINFO_H */
 
+#elif KERNEL_SOLARIS
+# include <procfs.h>
+# include <dirent.h>
+/* #endif KERNEL_SOLARIS */
+
 #else
 # error "No applicable input method."
 #endif
 # include <regex.h>
 #endif
 
+#if HAVE_KSTAT_H
+# include <kstat.h>
+#endif
+
 #ifndef ARG_MAX
 #  define ARG_MAX 4096
 #endif
@@ -216,8 +227,8 @@ int getargs (struct procentry64 *processBuffer, int bufferLen, char *argsBuffer,
 #endif /* HAVE_PROCINFO_H */
 
 /* put name of process from config to list_head_g tree
  list_head_g is a list of 'procstat_t' structs with
  processes names we want to watch */
* list_head_g is a list of 'procstat_t' structs with
* processes names we want to watch */
 static void ps_list_register (const char *name, const char *regexp)
 {
        procstat_t *new;
@@ -712,7 +723,7 @@ static void ps_submit_proc_list (procstat_t *ps)
        }
 
        DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; "
-                        "vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
+                       "vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
                        "vmem_code = %lu; "
                        "vmem_minflt_counter = %"PRIi64"; vmem_majflt_counter = %"PRIi64"; "
                        "cpu_user_counter = %"PRIi64"; cpu_system_counter = %"PRIi64"; "
@@ -726,6 +737,26 @@ static void ps_submit_proc_list (procstat_t *ps)
                        ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw);
 } /* void ps_submit_proc_list */
 
+#if KERNEL_LINUX || KERNEL_SOLARIS
+static void ps_submit_fork_rate (derive_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy(vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy(vl.plugin, "processes", sizeof (vl.plugin));
+       sstrncpy(vl.plugin_instance, "", sizeof (vl.plugin_instance));
+       sstrncpy(vl.type, "fork_rate", sizeof (vl.type));
+       sstrncpy(vl.type_instance, "", sizeof (vl.type_instance));
+
+       plugin_dispatch_values(&vl);
+}
+#endif /* KERNEL_LINUX || KERNEL_SOLARIS*/
+
 /* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
 #if KERNEL_LINUX
 static int ps_read_tasks (int pid)
@@ -780,7 +811,7 @@ static procstat_t *ps_read_vmem (int pid, procstat_t *ps)
                        continue;
 
                numfields = strsplit (buffer, fields,
-                                      STATIC_ARRAY_SIZE (fields));
+                               STATIC_ARRAY_SIZE (fields));
 
                if (numfields < 2)
                        continue;
@@ -1117,70 +1148,226 @@ static char *ps_get_cmdline (pid_t pid, char *name, char *buf, size_t buf_len)
        return buf;
 } /* char *ps_get_cmdline (...) */
 
-static unsigned long read_fork_rate ()
+static int read_fork_rate ()
 {
        FILE *proc_stat;
-       char buf[1024];
-       unsigned long result = 0;
-       int numfields;
-       char *fields[3];
+       char buffer[1024];
+       value_t value;
+       _Bool value_valid = 0;
 
-       proc_stat = fopen("/proc/stat", "r");
-       if (proc_stat == NULL) {
+       proc_stat = fopen ("/proc/stat", "r");
+       if (proc_stat == NULL)
+       {
                char errbuf[1024];
                ERROR ("processes plugin: fopen (/proc/stat) failed: %s",
                                sstrerror (errno, errbuf, sizeof (errbuf)));
-               return ULONG_MAX;
+               return (-1);
        }
 
-       while (fgets (buf, sizeof(buf), proc_stat) != NULL)
+       while (fgets (buffer, sizeof (buffer), proc_stat) != NULL)
        {
-               char *endptr;
+               int status;
+               char *fields[3];
+               int fields_num;
 
-               numfields = strsplit(buf, fields, STATIC_ARRAY_SIZE (fields));
-               if (numfields != 2)
+               fields_num = strsplit (buffer, fields,
+                               STATIC_ARRAY_SIZE (fields));
+               if (fields_num != 2)
                        continue;
 
                if (strcmp ("processes", fields[0]) != 0)
                        continue;
 
-               errno = 0;
-               endptr = NULL;
-               result = strtoul(fields[1], &endptr, /* base = */ 10);
-               if ((endptr == fields[1]) || (errno != 0)) {
-                       ERROR ("processes plugin: Cannot parse fork rate: %s",
-                                       fields[1]);
-                       result = ULONG_MAX;
-                       break;
-               }
+               status = parse_value (fields[1], &value, DS_TYPE_DERIVE);
+               if (status == 0)
+                       value_valid = 1;
 
                break;
        }
-
        fclose(proc_stat);
 
-       return result;
+       if (!value_valid)
+               return (-1);
+
+       ps_submit_fork_rate (value.derive);
+       return (0);
 }
+#endif /*KERNEL_LINUX */
 
-static void ps_submit_fork_rate (unsigned long value)
+#if KERNEL_SOLARIS
+static const char *ps_get_cmdline (pid_t pid, /* {{{ */
+               char *buffer, size_t buffer_size)
 {
-       value_t values[1];
-       value_list_t vl = VALUE_LIST_INIT;
+       char path[PATH_MAX];
+       psinfo_t info;
+       int status;
 
-       values[0].derive = (derive_t) value;
+       snprintf(path, sizeof (path), "/proc/%i/psinfo", pid);
 
-       vl.values = values;
-       vl.values_len = 1;
-       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
-       sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
-       sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
-       sstrncpy (vl.type, "fork_rate", sizeof (vl.type));
-       sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
+       status = read_file_contents (path, (void *) &info, sizeof (info));
+       if (status != ((int) buffer_size))
+       {
+               ERROR ("processes plugin: Unexpected return value "
+                               "while reading \"%s\": "
+                               "Returned %i but expected %zu.",
+                               path, status, buffer_size);
+               return (NULL);
+       }
 
-       plugin_dispatch_values (&vl);
+       info.pr_psargs[sizeof (info.pr_psargs) - 1] = 0;
+       sstrncpy (buffer, info.pr_psargs, buffer_size);
+
+       return (buffer);
+} /* }}} int ps_get_cmdline */
+
+/*
+ * Reads process information on the Solaris OS. The information comes mainly from
+ * /proc/PID/status, /proc/PID/psinfo and /proc/PID/usage
+ * The values for input and ouput chars are calculated "by hand"
+ * Added a few "solaris" specific process states as well
+ */
+static int ps_read_process(int pid, procstat_t *ps, char *state)
+{
+       char filename[64];
+       char f_psinfo[64], f_usage[64];
+       char *buffer;
+
+       pstatus_t *myStatus;
+       psinfo_t *myInfo;
+       prusage_t *myUsage;
+
+       snprintf(filename, sizeof (filename), "/proc/%i/status", pid);
+       snprintf(f_psinfo, sizeof (f_psinfo), "/proc/%i/psinfo", pid);
+       snprintf(f_usage, sizeof (f_usage), "/proc/%i/usage", pid);
+
+
+       buffer = malloc(sizeof (pstatus_t));
+       memset(buffer, 0, sizeof (pstatus_t));
+       read_file_contents(filename, buffer, sizeof (pstatus_t));
+       myStatus = (pstatus_t *) buffer;
+
+       buffer = malloc(sizeof (psinfo_t));
+       memset(buffer, 0, sizeof(psinfo_t));
+       read_file_contents(f_psinfo, buffer, sizeof (psinfo_t));
+       myInfo = (psinfo_t *) buffer;
+
+       buffer = malloc(sizeof (prusage_t));
+       memset(buffer, 0, sizeof(prusage_t));
+       read_file_contents(f_usage, buffer, sizeof (prusage_t));
+       myUsage = (prusage_t *) buffer;
+
+       sstrncpy(ps->name, myInfo->pr_fname, sizeof (myInfo->pr_fname));
+       ps->num_lwp = myStatus->pr_nlwp;
+       if (myInfo->pr_wstat != 0) {
+               ps->num_proc = 0;
+               ps->num_lwp = 0;
+               *state = (char) 'Z';
+               return (0);
+       } else {
+               ps->num_proc = 1;
+               ps->num_lwp = myInfo->pr_nlwp;
+       }
+
+       /*
+        * Convert system time and user time from nanoseconds to microseconds
+        * for compatibility with the linux module
+        */
+       ps->cpu_system_counter = myStatus -> pr_stime.tv_nsec / 1000;
+       ps->cpu_user_counter = myStatus -> pr_utime.tv_nsec / 1000;
+
+       /*
+        * Convert rssize from KB to bytes to be consistent w/ the linux module
+        */
+       ps->vmem_rss = myInfo->pr_rssize * 1024;
+       ps->vmem_size = myInfo->pr_size * 1024;
+       ps->vmem_minflt_counter = myUsage->pr_minf;
+       ps->vmem_majflt_counter = myUsage->pr_majf;
+
+       /*
+        * TODO: Data and code segment calculations for Solaris
+        */
+
+       ps->vmem_data = -1;
+       ps->vmem_code = -1;
+       ps->stack_size = myStatus->pr_stksize;
+
+       /*
+        * Calculating input/ouput chars
+        * Formula used is total chars / total blocks => chars/block
+        * then convert input/output blocks to chars
+        */
+       ulong_t tot_chars = myUsage->pr_ioch;
+       ulong_t tot_blocks = myUsage->pr_inblk + myUsage->pr_oublk;
+       ulong_t chars_per_block = 1;
+       if (tot_blocks != 0)
+               chars_per_block = tot_chars / tot_blocks;
+       ps->io_rchar = myUsage->pr_inblk * chars_per_block;
+       ps->io_wchar = myUsage->pr_oublk * chars_per_block;
+       ps->io_syscr = myUsage->pr_sysc;
+       ps->io_syscw = myUsage->pr_sysc;
+
+
+       /*
+        * TODO: Find way of setting BLOCKED and PAGING status
+        */
+
+       *state = (char) 'R';
+       if (myStatus->pr_flags & PR_ASLEEP)
+               *state = (char) 'S';
+       else if (myStatus->pr_flags & PR_STOPPED)
+               *state = (char) 'T';
+       else if (myStatus->pr_flags & PR_DETACH)
+               *state = (char) 'E';
+       else if (myStatus->pr_flags & PR_DAEMON)
+               *state = (char) 'A';
+       else if (myStatus->pr_flags & PR_ISSYS)
+               *state = (char) 'Y';
+       else if (myStatus->pr_flags & PR_ORPHAN)
+               *state = (char) 'O';
+
+       sfree(myStatus);
+       sfree(myInfo);
+       sfree(myUsage);
+
+       return (0);
 }
 
-#endif /* KERNEL_LINUX */
+/*
+ * Reads the number of threads created since the last reboot. On Solaris these
+ * are retrieved from kstat (module cpu, name sys, class misc, stat nthreads).
+ * The result is the sum for all the threads created on each cpu
+ */
+static int read_fork_rate()
+{
+       extern kstat_ctl_t *kc;
+       kstat_t *ksp_chain = NULL;
+       derive_t result = 0;
+
+       if (kc == NULL)
+               return (-1);
+
+       for (ksp_chain = kc->kc_chain;
+                       ksp_chain != NULL;
+                       ksp_chain = ksp_chain->ks_next)
+       {
+               if ((strcmp (ksp_chain->ks_module, "cpu") == 0)
+                               && (strcmp (ksp_chain->ks_name, "sys") == 0)
+                               && (strcmp (ksp_chain->ks_class, "misc") == 0))
+               {
+                       long long tmp;
+
+                       kstat_read (kc, ksp_chain, NULL);
+
+                       tmp = get_kstat_value(ksp_chain, "nthreads");
+                       if (tmp != -1LL)
+                               result += tmp;
+               }
+       }
+
+       ps_submit_fork_rate (result);
+       return (0);
+}
+#endif /* KERNEL_SOLARIS */
 
 #if HAVE_THREAD_INFO
 static int mach_get_task_name (task_t t, int *pid, char *name, size_t name_max_len)
@@ -1506,8 +1693,6 @@ static int ps_read (void)
        procstat_entry_t pse;
        char       state;
 
-       unsigned long fork_rate;
-
        procstat_t *ps_ptr;
 
        running = sleeping = zombies = stopped = paging = blocked = 0;
@@ -1589,9 +1774,7 @@ static int ps_read (void)
        for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
                ps_submit_proc_list (ps_ptr);
 
-       fork_rate = read_fork_rate();
-       if (fork_rate != ULONG_MAX)
-               ps_submit_fork_rate(fork_rate);
+       read_fork_rate();
 /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD
@@ -1605,9 +1788,9 @@ static int ps_read (void)
 
        kvm_t *kd;
        char errbuf[1024];
-       struct kinfo_proc *procs;          /* array of processes */
+       struct kinfo_proc *procs;          /* array of processes */
        struct kinfo_proc *proc_ptr = NULL;
-       int count;                         /* returns number of processes */
+       int count;                         /* returns number of processes */
        int i;
 
        procstat_t *ps_ptr;
@@ -1778,7 +1961,7 @@ static int ps_read (void)
                                if (procentry[i].pi_pid == 0)
                                        cmdline = "swapper";
                                cargs = cmdline;
-                       }
+                       }
                        else
                        {
                                if (getargs(&procentry[i], sizeof(struct procentry64), arglist, MAXARGLN) >= 0)
@@ -1870,7 +2053,118 @@ static int ps_read (void)
 
        for (ps = list_head_g; ps != NULL; ps = ps->next)
                ps_submit_proc_list (ps);
-#endif /* HAVE_PROCINFO_H */
+/* #endif HAVE_PROCINFO_H */
+
+#elif KERNEL_SOLARIS
+       /*
+        * The Solaris section adds a few more process states and removes some
+        * process states compared to linux. Most notably there is no "PAGING"
+        * and "BLOCKED" state for a process.  The rest is similar to the linux
+        * code.
+        */
+       int running = 0;
+       int sleeping = 0;
+       int zombies = 0;
+       int stopped = 0;
+       int detached = 0;
+       int daemon = 0;
+       int system = 0;
+       int orphan = 0;
+
+       struct dirent *ent;
+       DIR *proc;
+
+       int status;
+       procstat_t *ps_ptr;
+       char state;
+
+       char cmdline[PRARGSZ];
+
+       ps_list_reset ();
+
+       proc = opendir ("/proc");
+       if (proc == NULL)
+               return (-1);
+
+       while ((ent = readdir(proc)) != NULL)
+       {
+               int pid;
+               struct procstat ps;
+               procstat_entry_t pse;
+
+               if (!isdigit ((int) ent->d_name[0]))
+                       continue;
+
+               if ((pid = atoi (ent->d_name)) < 1)
+                       continue;
+
+               status = ps_read_process (pid, &ps, &state);
+               if (status != 0)
+               {
+                       DEBUG("ps_read_process failed: %i", status);
+                       continue;
+               }
+
+               pse.id = pid;
+               pse.age = 0;
+
+               pse.num_proc   = ps.num_proc;
+               pse.num_lwp    = ps.num_lwp;
+               pse.vmem_size  = ps.vmem_size;
+               pse.vmem_rss   = ps.vmem_rss;
+               pse.vmem_data  = ps.vmem_data;
+               pse.vmem_code  = ps.vmem_code;
+               pse.stack_size = ps.stack_size;
+
+               pse.vmem_minflt = 0;
+               pse.vmem_minflt_counter = ps.vmem_minflt_counter;
+               pse.vmem_majflt = 0;
+               pse.vmem_majflt_counter = ps.vmem_majflt_counter;
+
+               pse.cpu_user = 0;
+               pse.cpu_user_counter = ps.cpu_user_counter;
+               pse.cpu_system = 0;
+               pse.cpu_system_counter = ps.cpu_system_counter;
+
+               pse.io_rchar = ps.io_rchar;
+               pse.io_wchar = ps.io_wchar;
+               pse.io_syscr = ps.io_syscr;
+               pse.io_syscw = ps.io_syscw;
+
+               switch (state)
+               {
+                       case 'R': running++;  break;
+                       case 'S': sleeping++; break;
+                       case 'E': detached++; break;
+                       case 'Z': zombies++;  break;
+                       case 'T': stopped++;  break;
+                       case 'A': daemon++;   break;
+                       case 'Y': system++;   break;
+                       case 'O': orphan++;   break;
+               }
+
+
+               ps_list_add (ps.name,
+                               ps_get_cmdline ((pid_t) pid,
+                                       cmdline, sizeof (cmdline)),
+                               &pse);
+       } /* while(readdir) */
+       closedir (proc);
+
+       ps_submit_state ("running",  running);
+       ps_submit_state ("sleeping", sleeping);
+       ps_submit_state ("zombies",  zombies);
+       ps_submit_state ("stopped",  stopped);
+       ps_submit_state ("detached", detached);
+       ps_submit_state ("daemon",   daemon);
+       ps_submit_state ("system",   system);
+       ps_submit_state ("orphan",   orphan);
+
+       for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+               ps_submit_proc_list (ps_ptr);
+
+       read_fork_rate();
+#endif /* KERNEL_SOLARIS */
 
        return (0);
 } /* int ps_read */
index c7b634b..46d3534 100644 (file)
@@ -221,7 +221,7 @@ static void swap_submit_gauge (const char *plugin_instance, /* {{{ */
        swap_submit (plugin_instance, "swap", type_instance, v);
 } /* }}} void swap_submit_gauge */
 
-#if KERNEL_LINUX
+#if KERNEL_LINUX || HAVE_PERFSTAT
 static void swap_submit_derive (const char *plugin_instance, /* {{{ */
                const char *type_instance, derive_t value)
 {
@@ -230,7 +230,9 @@ static void swap_submit_derive (const char *plugin_instance, /* {{{ */
        v.derive = value;
        swap_submit (plugin_instance, "swap_io", type_instance, v);
 } /* }}} void swap_submit_derive */
+#endif
 
+#if KERNEL_LINUX
 static int swap_read_separate (void) /* {{{ */
 {
        FILE *fh;
@@ -786,8 +788,12 @@ static int swap_read (void) /* {{{ */
                         sstrerror (errno, errbuf, sizeof (errbuf)));
                 return (-1);
         }
+
        swap_submit_gauge (NULL, "used", (gauge_t) (pmemory.pgsp_total - pmemory.pgsp_free) * pagesize);
        swap_submit_gauge (NULL, "free", (gauge_t) pmemory.pgsp_free * pagesize );
+       swap_submit_gauge (NULL, "reserved", (gauge_t) pmemory.pgsp_rsvd * pagesize);
+       swap_submit_derive (NULL, "in",  (derive_t) pmemory.pgspins * pagesize);
+       swap_submit_derive (NULL, "out", (derive_t) pmemory.pgspouts * pagesize);
 
        return (0);
 } /* }}} int swap_read */
index 4d90c41..765b892 100644 (file)
@@ -275,9 +275,9 @@ static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 static int port_collect_listening = 0;
 static port_entry_t *port_list_head = NULL;
 
+#if KERNEL_LINUX
 static uint32_t sequence_number = 0;
 
-#if KERNEL_LINUX
 enum
 {
   SRC_DUNNO,
index d729477..0dc7d65 100644 (file)
@@ -205,6 +205,7 @@ static void *us_handle_client (void *arg)
                close (fdin);
                close (fdout);
                pthread_exit ((void *) 1);
+               return ((void *) 1);
        }
 
        fhout = fdopen (fdout, "w");
@@ -216,6 +217,7 @@ static void *us_handle_client (void *arg)
                fclose (fhin); /* this closes fdin as well */
                close (fdout);
                pthread_exit ((void *) 1);
+               return ((void *) 1);
        }
 
        /* change output buffer to line buffered mode */
@@ -227,6 +229,7 @@ static void *us_handle_client (void *arg)
                fclose (fhin);
                fclose (fhout);
                pthread_exit ((void *) 1);
+               return ((void *) 0);
        }
 
        while (42)
@@ -240,6 +243,9 @@ static void *us_handle_client (void *arg)
                errno = 0;
                if (fgets (buffer, sizeof (buffer), fhin) == NULL)
                {
+                       if ((errno == EINTR) || (errno == EAGAIN))
+                               continue;
+
                        if (errno != 0)
                        {
                                char errbuf[1024];
@@ -268,6 +274,7 @@ static void *us_handle_client (void *arg)
                        fclose (fhin);
                        fclose (fhout);
                        pthread_exit ((void *) 1);
+                       return ((void *) 1);
                }
 
                if (strcasecmp (fields[0], "getval") == 0)
@@ -318,6 +325,9 @@ static void *us_server_thread (void __attribute__((unused)) *arg)
        pthread_t th;
        pthread_attr_t th_attr;
 
+       pthread_attr_init (&th_attr);
+       pthread_attr_setdetachstate (&th_attr, PTHREAD_CREATE_DETACHED);
+
        if (us_open_socket () != 0)
                pthread_exit ((void *) 1);
 
@@ -336,6 +346,7 @@ static void *us_server_thread (void __attribute__((unused)) *arg)
                                        sstrerror (errno, errbuf, sizeof (errbuf)));
                        close (sock_fd);
                        sock_fd = -1;
+                       pthread_attr_destroy (&th_attr);
                        pthread_exit ((void *) 1);
                }
 
@@ -352,9 +363,6 @@ static void *us_server_thread (void __attribute__((unused)) *arg)
 
                DEBUG ("Spawning child to handle connection on fd #%i", *remote_fd);
 
-               pthread_attr_init (&th_attr);
-               pthread_attr_setdetachstate (&th_attr, PTHREAD_CREATE_DETACHED);
-
                status = pthread_create (&th, &th_attr, us_handle_client, (void *) remote_fd);
                if (status != 0)
                {
@@ -369,6 +377,7 @@ static void *us_server_thread (void __attribute__((unused)) *arg)
 
        close (sock_fd);
        sock_fd = -1;
+       pthread_attr_destroy (&th_attr);
 
        status = unlink ((sock_file != NULL) ? sock_file : US_DEFAULT_PATH);
        if (status != 0)
index d2ba963..064c3ce 100644 (file)
 /* Using sysctl interface to retrieve the boot time on *BSD / Darwin / OS X systems */
 /* #endif HAVE_SYS_SYSCTL_H */
 
+#elif HAVE_PERFSTAT
+# include <sys/protosw.h>
+# include <libperfstat.h>
+/* Using perfstat_cpu_total to retrive the boot time in AIX */
+/* #endif HAVE_PERFSTAT */
+
 #else
 # error "No applicable input method."
 #endif
@@ -203,7 +209,29 @@ static int uptime_init (void) /* {{{ */
                                "but `boottime' is zero!");
                return (-1);
        }
-#endif /* HAVE_SYS_SYSCTL_H */
+/* #endif HAVE_SYS_SYSCTL_H */
+
+#elif HAVE_PERFSTAT
+       int status;
+       perfstat_cpu_total_t cputotal;
+       int hertz;
+
+       status = perfstat_cpu_total(NULL, &cputotal,
+               sizeof(perfstat_cpu_total_t), 1);
+       if (status < 0)
+       {
+               char errbuf[1024];
+               ERROR ("uptime plugin: perfstat_cpu_total: %s",
+                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       hertz = sysconf(_SC_CLK_TCK);
+       if (hertz <= 0)
+               hertz = HZ;
+
+       boottime = time(NULL) - cputotal.lbolt / hertz;
+#endif /* HAVE_PERFSTAT */
 
        return (0);
 } /* }}} int uptime_init */
index dcac807..7e7504d 100644 (file)
@@ -219,7 +219,7 @@ static int udb_result_submit (udb_result_t *r, /* {{{ */
 
   sstrncpy (vl.host, q_area->host, sizeof (vl.host));
   sstrncpy (vl.plugin, q_area->plugin, sizeof (vl.plugin));
-  sstrncpy (vl.plugin_instance, q_area->db_name, sizeof (vl.type_instance));
+  sstrncpy (vl.plugin_instance, q_area->db_name, sizeof (vl.plugin_instance));
   sstrncpy (vl.type, r->type, sizeof (vl.type));
 
   /* Set vl.type_instance {{{ */
index d20b7e3..97f21a1 100644 (file)
@@ -234,6 +234,7 @@ void fbh_destroy (fbhash_t *h) /* {{{ */
   if (h == NULL)
     return;
 
+  pthread_mutex_destroy (&h->lock);
   free (h->filename);
   fbh_free_tree (h->tree);
 } /* }}} void fbh_destroy */
index f4352ff..046b7b0 100644 (file)
@@ -28,7 +28,7 @@
 /*
  * Global variables
  */
-static kstat_t *ksp;
+
 extern kstat_ctl_t *kc;
 
 static void za_submit (const char* type, const char* type_instance, value_t* values, int values_len)
@@ -109,6 +109,7 @@ static int za_read (void)
 {
        gauge_t  arc_hits, arc_misses, l2_hits, l2_misses;
        value_t  l2_io[2];
+       kstat_t  *ksp   = NULL;
 
        get_kstat (&ksp, "zfs", 0, "arcstats");
        if (ksp == NULL)
@@ -165,8 +166,6 @@ static int za_read (void)
 
 static int za_init (void) /* {{{ */
 {
-       ksp = NULL;
-
        /* kstats chain already opened by update_kstat (using *kc), verify everything went fine. */
        if (kc == NULL)
        {