Merge remote-tracking branch 'tokkee/sh/collectd-5.0' into collectd-5.0
authorFlorian Forster <octo@collectd.org>
Sat, 28 Jan 2012 11:03:35 +0000 (12:03 +0100)
committerFlorian Forster <octo@collectd.org>
Sat, 28 Jan 2012 11:03:35 +0000 (12:03 +0100)
50 files changed:
.gitignore
AUTHORS
ChangeLog
configure.in
contrib/aix/collectd.spec [new file with mode: 0644]
contrib/aix/init.d-collectd [new file with mode: 0755]
contrib/collectd_unixsock.py
contrib/migrate-4-5.px
src/apache.c
src/ascent.c
src/bind.c
src/collectd-perl.pod
src/collectd.conf.in
src/collectd.conf.pod
src/common.c
src/csv.c
src/curl.c
src/curl_json.c
src/curl_xml.c
src/df.c
src/disk.c
src/exec.c
src/interface.c
src/irq.c
src/java.c
src/libvirt.c
src/match_empty_counter.c
src/memory.c
src/meta_data.c
src/meta_data.h
src/mysql.c
src/network.c
src/nginx.c
src/notify_desktop.c
src/notify_email.c
src/oracle.c
src/owniptc/libiptc.c
src/plugin.c
src/plugin.h
src/processes.c
src/pyvalues.c
src/rrdtool.c
src/teamspeak2.c
src/utils_dns.c
src/utils_format_json.c
src/utils_rrdcreate.c
src/utils_rrdcreate.h
src/varnish.c
src/write_http.c
version-gen.sh

index cbdd62f..75cb307 100644 (file)
@@ -33,6 +33,7 @@ src/stamp-h1
 .libs/
 src/collectd
 src/collectd-nagios
+src/collectdctl
 src/collectdmon
 src/*.1
 src/*.5
diff --git a/AUTHORS b/AUTHORS
index c57f90b..0e0a5fe 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -67,6 +67,9 @@ Edward “Koko” Konetzko <konetzed at quixoticagony.com>
 Fabian Linzberger <e at lefant.net>
  - Percentage aggregation for `collectd-nagios'.
 
+Fabien Wernli <cpan at faxm0dem.org>
+ - Solaris improvements in the memory and interfaces plugin.
+
 Flavio Stanchina <flavio at stanchina.net>
  - mbmon plugin.
 
index fb55560..4642da9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,54 @@
+2012-01-21, Version 5.0.2
+       * curl_xml plugin: Fix handling of file:// and other URLs (which don't
+         follow HTTP status codes). Thanks to Fabien Wernli for his patch!
+       * df plugin: Fix handling of negative "available" counts. This can
+         occur with some file systems, for example UFS. Thanks to Toni Ylenius
+         for his patch.
+       * interface plugin: "mac" interfaces are now ignored on Solaris. These
+         pseudo-interfaces occur multiple times, causing warnings. Also switch
+         to 64-bit counters on Solaris, improving overflow behavior for
+         high-speed interfaces. Thanks to Eddy Geez and Fabien Wernli for
+         their patches.
+       * memory plugin: Account kernel and unused memory under Solaris. Thanks
+         to Fabien Wernli for his patch.
+       * network plugin: A bug in the interaction between the Network plugin
+         and filter chains has been fixed: When a filter modified a field such
+         as the hostname, subsequent values in the same network packets could
+         have ended up using the modified name rather than the original name.
+         Thanks to Sebastian Harl for identifying the problem.
+       * oracle plugin: A memory leak has been fixed in the parameter handling.
+       * python plugin: A memory leak has been fixed. Thanks to Sven Trenkel
+         for fixing this bug!
+
+2011-10-07, Version 5.0.1
+       * collectd: A mutex leak has been fixed in the meta data code. Thanks
+         to Rafal Lesniak for his patch.
+       * collectd: Compatibility fixes for GCC 4.6 have been applied. Thanks
+         to Peter Green for his patch.
+       * csv plugin: The line buffer size has been increased. Thanks to Colin
+         McCabe for the patch.
+       * curl_json plugin: Don't use the "parent" node to build the type
+         instance, if it is empty. Compatibility with libyajl 2 has been
+         added. Thanks to "spupykin" of the Arch Linux project for the initial
+         code. Formatting of time has been fixed in the JSON module.
+       * exec plugin: Fix the timestamp value passed to notification scripts.
+         Thanks to Alexander Kovalenko for fixing this.
+       * iptables plugin: Fix linking with some versions of libiptc.
+       * irq plugin: Fix support for interrupts under Linux. The old code
+         assumed that interrupts have a numeric value -- this is no longer
+         true for Linux. Thanks to Bostjan Skufca for implementing this.
+       * notify_desktop plugin: Compatibility with libnotify 0.7 has been
+         added. Thanks to Samuli Suominen for his patch.
+       * processes plugin: Fix handling of regular expressions containing
+         spaces. Thanks for Sebastian Harl for fixing this.
+       * rrdtool, rrdcached plugins: Improve precision of the XFF parameter.
+         Previously, values like 0.999 would have been rounded to 1.0. Thanks
+         to Francois-Xavier Bourlet for fixing this.
+       * varnish plugin: Fix data type handling of some metrics. Some values
+         were submitted as gauge even though they were derives.
+       * Various plugin: Set a multi-threading flag in libcurl. Thanks to Mike
+         Flisher for the fix.
+
 2011-03-28, Version 5.0.0
        * collectd: The "FQDNLookup" option is now enabled by default.
        * collectd: The internal representation of time has been changed to
        * v5upgrade target: Target for converting v4 data sets to the v5
          schema.
 
+2012-01-21, Version 4.10.5
+       * curl_xml plugin: Fix handling of file:// and other URLs (which don't
+         follow HTTP status codes). Thanks to Fabien Wernli for his patch!
+       * df plugin: Fix handling of negative "available" counts. This can
+         occur with some file systems, for example UFS. Thanks to Toni Ylenius
+         for his patch.
+       * interface plugin: "mac" interfaces are now ignored on Solaris. These
+         pseudo-interfaces occur multiple times, causing warnings. Also switch
+         to 64-bit counters on Solaris, improving overflow behavior for
+         high-speed interfaces. Thanks to Eddy Geez and Fabien Wernli for
+         their patches.
+       * memory plugin: Account kernel and unused memory under Solaris. Thanks
+         to Fabien Wernli for his patch.
+       * network plugin: A bug in the interaction between the Network plugin
+         and filter chains has been fixed: When a filter modified a field such
+         as the hostname, subsequent values in the same network packets could
+         have ended up using the modified name rather than the original name.
+         Thanks to Sebastian Harl for identifying the problem.
+       * oracle plugin: A memory leak has been fixed in the parameter handling.
+       * python plugin: A memory leak has been fixed. Thanks to Sven Trenkel
+         for fixing this bug!
+
+2011-10-14, Version 4.10.4
+       * collectd: A mutex leak has been fixed in the meta data code. Thanks
+         to Rafal Lesniak for his patch.
+       * collectd: Compatibility fixes for GCC 4.6 have been applied. Thanks
+         to Peter Green for his patch.
+       * csv plugin: The line buffer size has been increased. Thanks to Colin
+         McCabe for the patch.
+       * curl_json plugin: Don't use the "parent" node to build the type
+         instance, if it is empty. Compatibility with libyajl 2 has been
+         added. Thanks to "spupykin" of the Arch Linux project for the initial
+         code.
+       * iptables plugin: Fix linking with some versions of libiptc.
+       * irq plugin: Fix support for interrupts under Linux. The old code
+         assumed that interrupts have a numeric value -- this is no longer
+         true for Linux. Thanks to Bostjan Skufca for implementing this.
+       * notify_desktop plugin: Compatibility with libnotify 0.7 has been
+         added. Thanks to Samuli Suominen for his patch.
+       * processes plugin: Fix handling of regular expressions containing
+         spaces. Thanks for Sebastian Harl for fixing this.
+       * rrdtool, rrdcached plugins: Improve precision of the XFF parameter.
+         Previously, values like 0.999 would have been rounded to 1.0. Thanks
+         to Francois-Xavier Bourlet for fixing this.
+       * Various plugin: Set a multi-threading flag in libcurl. Thanks to Mike
+         Flisher for the fix.
+
 2011-03-26, Version 4.10.3
        * Documentation: Several updates and additions. Thanks to Sebastian Harl.
        * collectd: Build issues (compiler warnings) have been fixed. Thanks to
index 8db24ca..f0a189c 100644 (file)
@@ -2,6 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
 AC_INIT(collectd, m4_esyscmd(./version-gen.sh))
 AC_CONFIG_SRCDIR(src/collectd.c)
 AC_CONFIG_HEADERS(src/config.h)
+AC_CONFIG_AUX_DIR([libltdl/config])
 
 m4_ifdef([LT_PACKAGE_VERSION],
        # libtool >= 2.2
@@ -1841,7 +1842,8 @@ then
        [
                with_libiptc="yes"
                with_own_libiptc="yes"
-       ])
+       ],
+       [-lip4tc -lip6tc])
 fi
 # The system wide version failed for some reason. Check if we have the required
 # headers to build the shipped version.
@@ -3863,6 +3865,7 @@ then
        CPPFLAGS="$CPPFLAGS $with_libyajl_cppflags"
 
        AC_CHECK_HEADERS(yajl/yajl_parse.h, [with_libyajl="yes"], [with_libyajl="no (yajl/yajl_parse.h not found)"])
+       AC_CHECK_HEADERS(yajl/yajl_version.h)
 
        CPPFLAGS="$SAVE_CPPFLAGS"
 fi
diff --git a/contrib/aix/collectd.spec b/contrib/aix/collectd.spec
new file mode 100644 (file)
index 0000000..c148d79
--- /dev/null
@@ -0,0 +1,75 @@
+
+%define name    collectd
+%define version 4.10.1
+%define release 1
+
+Name:           %{name}
+Summary:        Statistics collection daemon for filling RRD files.
+Version:        %{version}
+Release:        %{release}
+#Source:         http://collectd.org/files/%{name}-%{version}.tar.gz
+Source0:        %{name}-%{version}.tar.gz
+Group:          System Environment/Daemons
+BuildRoot:      %{_tmppath}/%{name}-%{version}-buildroot
+License:        GPL
+BuildPrereq:    rrdtool-devel,net-snmp-devel
+Requires:       rrdtool,net-snmp
+Packager:       Aurelien Reynaud <collectd@wattapower.net>
+Vendor:         collectd development team <collectd@verplant.org>
+
+%description
+collectd is a small daemon which collects system information periodically and
+provides mechanisms to monitor and store the values in a variety of ways. It
+is written in C for performance. Since the daemon doesn't need to startup
+every time it wants to update the values it's very fast and easy on the
+system. Also, the statistics are very fine grained since the files are updated
+every 10 seconds.
+
+%prep
+%setup
+
+%build
+# The RM variable in the RPM environment conflicts with that of the build environment,
+# at least when building on AIX 6.1. This is definitely a bug in one of the tools but
+# for now we work around it by unsetting the variable below.
+[ -n "$RM" ] && unset RM
+./configure LDFLAGS="-Wl,-brtl" --prefix=/opt/freeware --mandir=/opt/freeware/man --disable-dns --with-libnetsnmp=/opt/freeware/bin/net-snmp-config
+make
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/lib/%{name}
+mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/run
+mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
+cp contrib/aix/init.d-collectd $RPM_BUILD_ROOT/etc/rc.d/init.d/collectd
+
+%clean
+[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf "$RPM_BUILD_ROOT"
+
+%files
+%defattr(-,root,system)
+%doc AUTHORS COPYING ChangeLog INSTALL NEWS README
+%config(noreplace) %attr(0644,root,system) %{_sysconfdir}/collectd.conf
+%attr(0755,root,system) /etc/rc.d/init.d/collectd
+%attr(0755,root,system) %{_sbindir}/collectd
+%attr(0755,root,system) %{_bindir}/collectd-nagios
+%attr(0755,root,system) %{_sbindir}/collectdmon
+%attr(0644,root,system) %{_mandir}/man1/*
+%attr(0644,root,system) %{_mandir}/man5/*
+
+# client
+%attr(0644,root,system) %{_includedir}/%{name}/client.h
+%attr(0644,root,system) %{_includedir}/%{name}/lcc_features.h
+
+%attr(0644,root,system) %{_libdir}/libcollectdclient.*
+%attr(0644,root,system) %{_libdir}/pkgconfig/libcollectdclient.pc
+
+%attr(0444,root,system) %{_libdir}/%{name}/*.so
+%attr(0444,root,system) %{_libdir}/%{name}/*.a
+%attr(0444,root,system) %{_libdir}/%{name}/*.la
+
+%attr(0644,root,system) %{_datadir}/%{name}/types.db
+
+%dir %{_localstatedir}/lib/%{name}
+%dir %{_localstatedir}/run
+
diff --git a/contrib/aix/init.d-collectd b/contrib/aix/init.d-collectd
new file mode 100755 (executable)
index 0000000..d893153
--- /dev/null
@@ -0,0 +1,79 @@
+#!/bin/sh
+#
+# description: collectd startup script
+#
+# March 2010, Aurelien Reynaud <collectd@wattapower.net>
+#
+
+# Some plugins need libs in non-standard paths
+case `uname` in
+       SunOS)
+               LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib:/usr/local/ssl/lib"
+               export LD_LIBRARY_PATH
+               ;;
+       *)
+               ;;
+esac
+
+# Set umask
+umask 022
+
+COLLECTD_BIN=/opt/freeware/sbin/collectd
+PIDFILE=/opt/freeware/var/run/collectd.pid
+
+# Check for missing binaries (stale symlinks should not happen)
+if [ ! -x $COLLECTD_BIN ]; then
+       echo "$COLLECTD_BIN not installed"
+       [ "$1" = "stop" ] && exit 0
+       exit 5
+fi
+
+# Check for existence of needed config file and read it
+COLLECTD_CONFIG=/opt/freeware/etc/collectd.conf
+if [ ! -r $COLLECTD_CONFIG ]; then
+       echo "$COLLECTD_CONFIG not existing"
+       [ "$1" = "stop" ] && exit 0
+       exit 6
+fi
+
+case "$1" in
+    start)
+       if [ -r $PIDFILE ]; then
+           echo "collectd daemon is already running with PID `cat $PIDFILE`."
+           exit 1
+       fi
+       echo "Starting collectd..."
+
+       ## Start daemon
+       $COLLECTD_BIN
+       ;;
+    stop)
+       echo "Shutting down collectd daemon... "
+       ## Stop daemon.
+       if [ -r $PIDFILE ]; then
+           pid=`cat $PIDFILE`
+           kill -15 $pid
+           while ps -p $pid >/dev/null; do
+               sleep 1
+           done
+           rm -f $PIDFILE
+       fi
+       ;;
+    status)
+       if [ -r $PIDFILE ]; then
+           echo "collectd daemon is running with PID `cat $PIDFILE`."
+       else
+           echo "collectd daemon is not running."
+       fi
+       ;;
+    restart)
+       ## Stop the service and regardless of whether it was
+       ## running or not, start it again.
+       $0 stop
+       $0 start
+       ;;
+    *)
+       echo "Usage: $0 {start|stop|status|restart}"
+       exit 1
+       ;;
+esac
index ebe040d..1b8e6b1 100644 (file)
@@ -68,8 +68,9 @@ class Collectd():
         """
         numvalues = self._cmd('GETTHRESHOLD "%s"' % identifier)
         lines = []
-        if numvalues:
-            lines = self._readlines(numvalues)
+        if not numvalues or numvalues < 0:
+            raise KeyError("Identifier '%s' not found" % identifier)
+        lines = self._readlines(numvalues)
         return lines
 
     def getval(self, identifier, flush_after=True):
@@ -83,8 +84,9 @@ class Collectd():
         """
         numvalues = self._cmd('GETVAL "%s"' % identifier)
         lines = []
-        if numvalues:
-            lines = self._readlines(numvalues)
+        if not numvalues or numvalues < 0:
+            raise KeyError("Identifier '%s' not found" % identifier)
+        lines = self._readlines(numvalues)
         if flush_after:
             self.flush(identifiers=[identifier])
         return lines
index 539eaa3..d3ff796 100755 (executable)
@@ -183,6 +183,7 @@ sub handle_file # {{{
     && (!$plugin_inst) && ($type_inst))
   {
     my $dir = join ('/', @path);
+    print "mkdir -p \"$dir/$plugin-$type_inst\"\n";
     print "mv \"$path\" \"$dir/$plugin-$type_inst/$type.rrd\"\n";
   }
 } # }}} sub handle_file
index 9be32d1..c31dd87 100644 (file)
@@ -373,6 +373,7 @@ static int init_host (apache_t *st) /* {{{ */
                return (-1);
        }
 
+       curl_easy_setopt (st->curl, CURLOPT_NOSIGNAL, 1);
        curl_easy_setopt (st->curl, CURLOPT_WRITEFUNCTION, apache_curl_callback);
        curl_easy_setopt (st->curl, CURLOPT_WRITEDATA, st);
 
index 6782fce..993e480 100644 (file)
@@ -539,6 +539,7 @@ static int ascent_init (void) /* {{{ */
     return (-1);
   }
 
+  curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1);
   curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ascent_curl_callback);
   curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
   curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, ascent_curl_error);
index db8a891..b640a59 100644 (file)
@@ -1385,6 +1385,7 @@ static int bind_init (void) /* {{{ */
     return (-1);
   }
 
+  curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1);
   curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, bind_curl_callback);
   curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
   curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, bind_curl_error);
index 6b44722..d5401dd 100644 (file)
@@ -656,9 +656,9 @@ A very simple read function might look like:
 
   sub foobar_read
   {
-    my $vl = { plugin => 'foobar' };
+    my $vl = { plugin => 'foobar', type => 'gauge' };
     $vl->{'values'} = [ rand(42) ];
-    plugin_dispatch_values ('gauge', $vl);
+    plugin_dispatch_values ($vl);
     return 1;
   }
 
index f1b6bfd..cd65fd2 100644 (file)
 #@BUILD_PLUGIN_ONEWIRE_TRUE@LoadPlugin onewire
 #@BUILD_PLUGIN_OPENVPN_TRUE@LoadPlugin openvpn
 #@BUILD_PLUGIN_ORACLE_TRUE@LoadPlugin oracle
-#@BUILD_PLUGIN_PERL_TRUE@LoadPlugin perl
+#@BUILD_PLUGIN_PERL_TRUE@<LoadPlugin perl>
+#@BUILD_PLUGIN_PERL_TRUE@  Globals true
+#@BUILD_PLUGIN_PERL_TRUE@</LoadPlugin>
 #@BUILD_PLUGIN_PINBA_TRUE@LoadPlugin pinba
 #@BUILD_PLUGIN_PING_TRUE@LoadPlugin ping
 #@BUILD_PLUGIN_POSTGRESQL_TRUE@LoadPlugin postgresql
 #@BUILD_PLUGIN_POWERDNS_TRUE@LoadPlugin powerdns
 #@BUILD_PLUGIN_PROCESSES_TRUE@LoadPlugin processes
 #@BUILD_PLUGIN_PROTOCOLS_TRUE@LoadPlugin protocols
-#@BUILD_PLUGIN_PYTHON_TRUE@LoadPlugin python
+#@BUILD_PLUGIN_PYTHON_TRUE@<LoadPlugin python>
+#@BUILD_PLUGIN_PYTHON_TRUE@  Globals true
+#@BUILD_PLUGIN_PYTHON_TRUE@</LoadPlugin>
 #@BUILD_PLUGIN_REDIS_TRUE@LoadPlugin redis
 #@BUILD_PLUGIN_ROUTEROS_TRUE@LoadPlugin routeros
 #@BUILD_PLUGIN_RRDCACHED_TRUE@LoadPlugin rrdcached
index de3e516..3d81110 100644 (file)
@@ -823,7 +823,7 @@ The B<curl_xml plugin> uses B<libcurl> (L<http://curl.haxx.se/>) and B<libxml2>
  </Plugin>
 
 In the B<Plugin> block, there may be one or more B<URL> blocks, each defining a
-URL to be fetched via HTTP (using libcurl). Within each B<URL> block there are
+URL to be fetched using libcurl. Within each B<URL> block there are
 options which specify the connection parameters, for example authentication
 information, and one or more B<XPath> blocks.
 
index 7015c87..e1f204b 100644 (file)
@@ -980,12 +980,15 @@ int parse_value (const char *value, value_t *ret_value, int ds_type)
   }
 
   if (value == endptr) {
-    ERROR ("parse_value: Failed to parse string as number: %s.", value);
+    ERROR ("parse_value: Failed to parse string as %s: %s.",
+        DS_TYPE_TO_STRING (ds_type), value);
     return -1;
   }
   else if ((NULL != endptr) && ('\0' != *endptr))
-    WARNING ("parse_value: Ignoring trailing garbage after number: %s.",
-        endptr);
+    INFO ("parse_value: Ignoring trailing garbage \"%s\" after %s value. "
+        "Input string was \"%s\".",
+        endptr, DS_TYPE_TO_STRING (ds_type), value);
+
   return 0;
 } /* int parse_value */
 
index 87a7b4e..02d62c1 100644 (file)
--- a/src/csv.c
+++ b/src/csv.c
@@ -264,7 +264,7 @@ static int csv_write (const data_set_t *ds, const value_list_t *vl,
 {
        struct stat  statbuf;
        char         filename[512];
-       char         values[512];
+       char         values[4096];
        FILE        *csv;
        int          csv_fd;
        struct flock fl;
index 8b95c80..2160b98 100644 (file)
@@ -370,6 +370,7 @@ static int cc_page_init_curl (web_page_t *wp) /* {{{ */
     return (-1);
   }
 
+  curl_easy_setopt (wp->curl, CURLOPT_NOSIGNAL, 1);
   curl_easy_setopt (wp->curl, CURLOPT_WRITEFUNCTION, cc_curl_callback);
   curl_easy_setopt (wp->curl, CURLOPT_WRITEDATA, wp);
   curl_easy_setopt (wp->curl, CURLOPT_USERAGENT,
index 5549f0a..cc8b4ad 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * collectd - src/curl_json.c
  * Copyright (C) 2009       Doug MacEachern
- * Copyright (C) 2006-2010  Florian octo Forster
+ * Copyright (C) 2006-2011  Florian octo Forster
  *
  * 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
@@ -18,7 +18,7 @@
  *
  * Authors:
  *   Doug MacEachern <dougm at hyperic.com>
- *   Florian octo Forster <octo at verplant.org>
+ *   Florian octo Forster <octo at collectd.org>
  **/
 
 #include "collectd.h"
 #include "plugin.h"
 #include "configfile.h"
 #include "utils_avltree.h"
+#include "utils_complain.h"
 
 #include <curl/curl.h>
 #include <yajl/yajl_parse.h>
+#if HAVE_YAJL_YAJL_VERSION_H
+# include <yajl/yajl_version.h>
+#endif
+
+#if defined(YAJL_MAJOR) && (YAJL_MAJOR > 1)
+# define HAVE_YAJL_V2 1
+#endif
 
 #define CJ_DEFAULT_HOST "localhost"
 #define CJ_KEY_MAGIC 0x43484b59UL /* CHKY */
@@ -77,6 +85,12 @@ struct cj_s /* {{{ */
 };
 typedef struct cj_s cj_t; /* }}} */
 
+#if HAVE_YAJL_V2
+typedef size_t yajl_len_t;
+#else
+typedef unsigned int yajl_len_t;
+#endif
+
 static int cj_read (user_data_t *ud);
 static int cj_curl_perform (cj_t *db, CURL *curl);
 static void cj_submit (cj_t *db, cj_key_t *key, value_t *value);
@@ -97,9 +111,22 @@ static size_t cj_curl_callback (void *buf, /* {{{ */
   if (db == NULL)
     return (0);
 
-  status = yajl_parse(db->yajl, (unsigned char *)buf, len);
-  if ((status != yajl_status_ok)
-      && (status != yajl_status_insufficient_data))
+  status = yajl_parse(db->yajl, (unsigned char *) buf, len);
+  if (status == yajl_status_ok)
+  {
+#if HAVE_YAJL_V2
+    status = yajl_complete_parse(db->yajl);
+#else
+    status = yajl_parse_complete(db->yajl);
+#endif
+    return (len);
+  }
+#if !HAVE_YAJL_V2
+  else if (status == yajl_status_insufficient_data)
+    return (len);
+#endif
+
+  if (status != yajl_status_ok)
   {
     unsigned char *msg =
       yajl_get_error(db->yajl, /* verbose = */ 1,
@@ -118,9 +145,31 @@ static int cj_get_type (cj_key_t *key)
 
   ds = plugin_get_ds (key->type);
   if (ds == NULL)
-    return -1; /* let plugin_write do the complaining */
-  else
-    return ds->ds[0].type; /* XXX support ds->ds_len > 1 */
+  {
+    static char type[DATA_MAX_NAME_LEN] = "!!!invalid!!!";
+
+    assert (key->type != NULL);
+    if (strcmp (type, key->type) != 0)
+    {
+      ERROR ("curl_json plugin: Unable to look up DS type \"%s\".",
+          key->type);
+      sstrncpy (type, key->type, sizeof (type));
+    }
+
+    return -1;
+  }
+  else if (ds->ds_num > 1)
+  {
+    static c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
+
+    c_complain_once (LOG_WARNING, &complaint,
+        "curl_json plugin: The type \"%s\" has more than one data source. "
+        "This is currently not supported. I will return the type of the "
+        "first data source, but this will likely lead to problems later on.",
+        key->type);
+  }
+
+  return ds->ds[0].type;
 }
 
 /* yajl callbacks */
@@ -130,7 +179,7 @@ static int cj_get_type (cj_key_t *key)
 /* "number" may not be null terminated, so copy it into a buffer before
  * parsing. */
 static int cj_cb_number (void *ctx,
-    const char *number, unsigned int number_len)
+    const char *number, yajl_len_t number_len)
 {
   char buffer[number_len + 1];
 
@@ -159,7 +208,7 @@ static int cj_cb_number (void *ctx,
 } /* int cj_cb_number */
 
 static int cj_cb_map_key (void *ctx, const unsigned char *val,
-                            unsigned int len)
+    yajl_len_t len)
 {
   cj_t *db = (cj_t *)ctx;
   c_avl_tree_t *tree;
@@ -187,7 +236,7 @@ static int cj_cb_map_key (void *ctx, const unsigned char *val,
 }
 
 static int cj_cb_string (void *ctx, const unsigned char *val,
-                           unsigned int len)
+    yajl_len_t len)
 {
   cj_t *db = (cj_t *)ctx;
   char str[len + 1];
@@ -472,6 +521,7 @@ static int cj_init_curl (cj_t *db) /* {{{ */
     return (-1);
   }
 
+  curl_easy_setopt (db->curl, CURLOPT_NOSIGNAL, 1);
   curl_easy_setopt (db->curl, CURLOPT_WRITEFUNCTION, cj_curl_callback);
   curl_easy_setopt (db->curl, CURLOPT_WRITEDATA, db);
   curl_easy_setopt (db->curl, CURLOPT_USERAGENT,
@@ -677,8 +727,13 @@ static void cj_submit (cj_t *db, cj_key_t *key, value_t *value) /* {{{ */
     host = db->host;
 
   if (key->instance == NULL)
-    ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s",
-               db->state[db->depth-1].name, db->state[db->depth].name);
+  {
+    if ((db->depth == 0) || (strcmp ("", db->state[db->depth-1].name) == 0))
+      sstrncpy (vl.type_instance, db->state[db->depth].name, sizeof (vl.type_instance));
+    else
+      ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s",
+          db->state[db->depth-1].name, db->state[db->depth].name);
+  }
   else
     sstrncpy (vl.type_instance, key->instance, sizeof (vl.type_instance));
 
@@ -697,7 +752,13 @@ static int cj_curl_perform (cj_t *db, CURL *curl) /* {{{ */
   char *url;
   yajl_handle yprev = db->yajl;
 
-  db->yajl = yajl_alloc (&ycallbacks, NULL, NULL, (void *)db);
+  db->yajl = yajl_alloc (&ycallbacks,
+#if HAVE_YAJL_V2
+      /* alloc funcs = */ NULL,
+#else
+      /* alloc funcs = */ NULL, NULL,
+#endif
+      /* context = */ (void *)db);
   if (db->yajl == NULL)
   {
     ERROR ("curl_json plugin: yajl_alloc failed.");
@@ -730,7 +791,11 @@ static int cj_curl_perform (cj_t *db, CURL *curl) /* {{{ */
     return (-1);
   }
 
-  status = yajl_parse_complete (db->yajl);
+#if HAVE_YAJL_V2
+    status = yajl_complete_parse(db->yajl);
+#else
+    status = yajl_parse_complete(db->yajl);
+#endif
   if (status != yajl_status_ok)
   {
     unsigned char *errmsg;
index c10955c..052ea1e 100644 (file)
@@ -555,7 +555,8 @@ static int cx_curl_perform (cx_t *db, CURL *curl) /* {{{ */
   curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
   curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rc);
 
-  if (rc != 200)
+  /* The response code is zero if a non-HTTP transport was used. */
+  if ((rc != 0) && (rc != 200))
   {
     ERROR ("curl_xml plugin: curl_easy_perform failed with response code %ld (%s)",
            rc, url);
@@ -734,6 +735,7 @@ static int cx_init_curl (cx_t *db) /* {{{ */
     return (-1);
   }
 
+  curl_easy_setopt (db->curl, CURLOPT_NOSIGNAL, 1);
   curl_easy_setopt (db->curl, CURLOPT_WRITEFUNCTION, cx_curl_callback);
   curl_easy_setopt (db->curl, CURLOPT_WRITEDATA, db);
   curl_easy_setopt (db->curl, CURLOPT_USERAGENT,
index 4b3cba0..371a7fc 100644 (file)
--- a/src/df.c
+++ b/src/df.c
 #  include <sys/statvfs.h>
 # endif
 # define STATANYFS statvfs
+# define STATANYFS_STR "statvfs"
 # define BLOCKSIZE(s) ((s).f_frsize ? (s).f_frsize : (s).f_bsize)
 #elif HAVE_STATFS
 # if HAVE_SYS_STATFS_H
 #  include <sys/statfs.h>
 # endif
 # define STATANYFS statfs
+# define STATANYFS_STR "statfs"
 # define BLOCKSIZE(s) (s).f_bsize
 #else
 # error "No applicable input method."
@@ -198,7 +200,8 @@ static int df_read (void)
                if (STATANYFS (mnt_ptr->dir, &statbuf) < 0)
                {
                        char errbuf[1024];
-                       ERROR ("statv?fs failed: %s",
+                       ERROR (STATANYFS_STR"(%s) failed: %s",
+                                       mnt_ptr->dir,
                                        sstrerror (errno, errbuf,
                                                sizeof (errbuf)));
                        continue;
@@ -242,7 +245,22 @@ static int df_read (void)
 
                blocksize = BLOCKSIZE(statbuf);
 
-               /* Sanity-check for the values in the struct */
+               /*
+                * Sanity-check for the values in the struct
+                */
+               /* Check for negative "available" byes. For example UFS can
+                * report negative free space for user. Notice. blk_reserved
+                * will start to diminish after this. */
+#if HAVE_STATVFS
+               /* Cast is needed to avoid compiler warnings.
+                * ((struct statvfs).f_bavail is unsigned (POSIX)) */
+               if (((int64_t) statbuf.f_bavail) < 0)
+                       statbuf.f_bavail = 0;
+#elif HAVE_STATFS
+               if (statbuf.f_bavail < 0)
+                       statbuf.f_bavail = 0;
+#endif
+               /* Make sure that f_blocks >= f_bfree >= f_bavail */
                if (statbuf.f_bfree < statbuf.f_bavail)
                        statbuf.f_bfree = statbuf.f_bavail;
                if (statbuf.f_blocks < statbuf.f_bfree)
index 697d850..fde0dcd 100644 (file)
@@ -426,7 +426,6 @@ static int disk_read (void)
        int numfields;
        int fieldshift = 0;
 
-       int major = 0;
        int minor = 0;
 
        derive_t read_sectors  = 0;
@@ -464,7 +463,6 @@ static int disk_read (void)
                if ((numfields != (14 + fieldshift)) && (numfields != 7))
                        continue;
 
-               major = atoll (fields[0]);
                minor = atoll (fields[1]);
 
                disk_name = fields[2 + fieldshift];
index 0d33b29..4f6f9df 100644 (file)
@@ -729,8 +729,8 @@ static void *exec_notification_one (void *arg) /* {{{ */
 
   fprintf (fh,
       "Severity: %s\n"
-      "Time: %u\n",
-      severity, (unsigned int) n->time);
+      "Time: %.3f\n",
+      severity, CDTIME_T_TO_DOUBLE (n->time));
 
   /* Print the optional fields */
   if (strlen (n->host) > 0)
index c1e28e3..9501161 100644 (file)
@@ -141,11 +141,17 @@ static int interface_init (void)
        {
                if (strncmp (ksp_chain->ks_class, "net", 3))
                        continue;
+               /* Ignore kstat entry if not the regular statistic set. This
+                * avoids problems with "bogus" interfaces, such as
+                * "wrsmd<num>" */
+               if (strncmp (ksp_chain->ks_name, ksp_chain->ks_module,
+                                       strlen (ksp_chain->ks_module)) != 0)
+                       continue;
                if (ksp_chain->ks_type != KSTAT_TYPE_NAMED)
                        continue;
                if (kstat_read (kc, ksp_chain, NULL) == -1)
                        continue;
-               if ((val = get_kstat_value (ksp_chain, "obytes")) == -1LL)
+               if ((val = get_kstat_value (ksp_chain, "ifspeed")) == -1LL)
                        continue;
                ksp[numif++] = ksp_chain;
        }
@@ -296,16 +302,29 @@ static int interface_read (void)
                if (kstat_read (kc, ksp[i], NULL) == -1)
                        continue;
 
-               rx = get_kstat_value (ksp[i], "rbytes");
-               tx = get_kstat_value (ksp[i], "obytes");
+               /* try to get 64bit counters */
+               rx = get_kstat_value (ksp[i], "rbytes64");
+               tx = get_kstat_value (ksp[i], "obytes64");
+               /* or fallback to 32bit */
+               if (rx == -1LL)
+                       rx = get_kstat_value (ksp[i], "rbytes");
+               if (tx == -1LL)
+                       tx = get_kstat_value (ksp[i], "obytes");
                if ((rx != -1LL) || (tx != -1LL))
                        if_submit (ksp[i]->ks_name, "if_octets", rx, tx);
 
-               rx = get_kstat_value (ksp[i], "ipackets");
-               tx = get_kstat_value (ksp[i], "opackets");
+               /* try to get 64bit counters */
+               rx = get_kstat_value (ksp[i], "ipackets64");
+               tx = get_kstat_value (ksp[i], "opackets64");
+               /* or fallback to 32bit */
+               if (rx == -1LL)
+                       rx = get_kstat_value (ksp[i], "ipackets");
+               if (tx == -1LL)
+                       tx = get_kstat_value (ksp[i], "opackets");
                if ((rx != -1LL) || (tx != -1LL))
                        if_submit (ksp[i]->ks_name, "if_packets", rx, tx);
 
+               /* no 64bit error counters yet */
                rx = get_kstat_value (ksp[i], "ierrors");
                tx = get_kstat_value (ksp[i], "oerrors");
                if ((rx != -1LL) || (tx != -1LL))
index 94e4253..7e73829 100644 (file)
--- a/src/irq.c
+++ b/src/irq.c
@@ -29,8 +29,6 @@
 # error "No applicable input method."
 #endif
 
-#define BUFSIZE 128
-
 /*
  * (Module-)Global variables
  */
@@ -41,8 +39,8 @@ static const char *config_keys[] =
 };
 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
-static unsigned int *irq_list;
-static unsigned int irq_list_num;
+static char         **irq_list;
+static unsigned int   irq_list_num = 0;
 
 /* 
  * irq_list_action:
@@ -55,11 +53,9 @@ static int irq_config (const char *key, const char *value)
 {
        if (strcasecmp (key, "Irq") == 0)
        {
-               unsigned int *temp;
-               unsigned int irq;
-               char *endptr;
+               char **temp;
 
-               temp = (unsigned int *) realloc (irq_list, (irq_list_num + 1) * sizeof (unsigned int *));
+               temp = realloc (irq_list, (irq_list_num + 1) * sizeof (*irq_list));
                if (temp == NULL)
                {
                        fprintf (stderr, "irq plugin: Cannot allocate more memory.\n");
@@ -68,19 +64,13 @@ static int irq_config (const char *key, const char *value)
                }
                irq_list = temp;
 
-               /* Clear errno, because we need it to see if an error occured. */
-               errno = 0;
-
-               irq = strtol(value, &endptr, 10);
-               if ((endptr == value) || (errno != 0))
+               irq_list[irq_list_num] = strdup (value);
+               if (irq_list[irq_list_num] == NULL)
                {
-                       fprintf (stderr, "irq plugin: Irq value is not a "
-                                       "number: `%s'\n", value);
-                       ERROR ("irq plugin: Irq value is not a "
-                                       "number: `%s'", value);
+                       ERROR ("irq plugin: strdup(3) failed.");
                        return (1);
                }
-               irq_list[irq_list_num] = irq;
+
                irq_list_num++;
        }
        else if (strcasecmp (key, "IgnoreSelected") == 0)
@@ -102,27 +92,26 @@ static int irq_config (const char *key, const char *value)
  * both, `submit' and `write' to give client and server the ability to
  * ignore certain stuff..
  */
-static int check_ignore_irq (const unsigned int irq)
+static int check_ignore_irq (const char *irq)
 {
-       int i;
+       unsigned int i;
 
        if (irq_list_num < 1)
                return (0);
 
-       for (i = 0; (unsigned int)i < irq_list_num; i++)
-               if (irq == irq_list[i])
+       for (i = 0; i < irq_list_num; i++)
+               if (strcmp (irq, irq_list[i]) == 0)
                        return (irq_list_action);
 
        return (1 - irq_list_action);
 }
 
-static void irq_submit (unsigned int irq, derive_t value)
+static void irq_submit (const char *irq_name, derive_t value)
 {
        value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
-       int status;
 
-       if (check_ignore_irq (irq))
+       if (check_ignore_irq (irq_name))
                return;
 
        values[0].derive = value;
@@ -132,11 +121,7 @@ static void irq_submit (unsigned int irq, derive_t value)
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "irq", sizeof (vl.plugin));
        sstrncpy (vl.type, "irq", sizeof (vl.type));
-
-       status = ssnprintf (vl.type_instance, sizeof (vl.type_instance),
-                       "%u", irq);
-       if ((status < 1) || ((unsigned int)status >= sizeof (vl.type_instance)))
-               return;
+       sstrncpy (vl.type_instance, irq_name, sizeof (vl.type_instance));
 
        plugin_dispatch_values (&vl);
 } /* void irq_submit */
@@ -155,11 +140,11 @@ static int irq_read (void)
                return (-1);
        }
 
-       while (fgets (buffer, BUFSIZE, fh) != NULL)
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
        {
-               unsigned int irq;
+               char *irq_name;
+               size_t irq_name_len;
                derive_t irq_value;
-               char *endptr;
                int i;
 
                char *fields[64];
@@ -169,12 +154,19 @@ static int irq_read (void)
                if (fields_num < 2)
                        continue;
 
-               errno = 0;    /* To distinguish success/failure after call */
-               irq = (unsigned int) strtoul (fields[0], &endptr, /* base = */ 10);
+               irq_name = fields[0];
+               irq_name_len = strlen (irq_name);
+               if (irq_name_len < 2)
+                       continue;
 
-               if ((endptr == fields[0]) || (errno != 0) || (*endptr != ':'))
+               /* Check if irq name ends with colon.
+                * Otherwise it's a header. */
+               if (irq_name[irq_name_len - 1] != ':')
                        continue;
 
+               irq_name[irq_name_len - 1] = 0;
+               irq_name_len--;
+
                irq_value = 0;
                for (i = 1; i < fields_num; i++)
                {
@@ -189,10 +181,11 @@ static int irq_read (void)
                        irq_value += v.derive;
                } /* for (i) */
 
-               if (i < fields_num)
+               /* No valid fields -> do not submit anything. */
+               if (i <= 1)
                        continue;
 
-               irq_submit (irq, irq_value);
+               irq_submit (irq_name, irq_value);
        }
 
        fclose (fh);
@@ -206,5 +199,3 @@ void module_register (void)
                        config_keys, config_keys_num);
        plugin_register_read ("irq", irq_read);
 } /* void module_register */
-
-#undef BUFSIZE
index af0861f..b69ca94 100644 (file)
@@ -2256,7 +2256,6 @@ static int cjni_config_plugin_block (oconfig_item_t *ci) /* {{{ */
   cjni_callback_info_t *cbi;
   jobject o_ocitem;
   const char *name;
-  int status;
   size_t i;
 
   jclass class;
@@ -2311,7 +2310,7 @@ static int cjni_config_plugin_block (oconfig_item_t *ci) /* {{{ */
   method = (*jvm_env)->GetMethodID (jvm_env, class,
       "config", "(Lorg/collectd/api/OConfigItem;)I");
 
-  status = (*jvm_env)->CallIntMethod (jvm_env,
+  (*jvm_env)->CallIntMethod (jvm_env,
       cbi->object, method, o_ocitem);
 
   (*jvm_env)->DeleteLocalRef (jvm_env, o_ocitem);
@@ -3080,9 +3079,8 @@ static int cjni_init (void) /* {{{ */
 
   if (config_block != NULL)
   {
-    int status;
 
-    status = cjni_config_perform (config_block);
+    cjni_config_perform (config_block);
     oconfig_free (config_block);
     config_block = NULL;
   }
index c74b937..774067c 100644 (file)
@@ -138,16 +138,12 @@ init_value_list (value_list_t *vl, virDomainPtr dom)
     int i, n;
     const char *name;
     char uuid[VIR_UUID_STRING_BUFLEN];
-    char  *host_ptr;
-    size_t host_len;
 
     vl->interval = interval_g;
 
     sstrncpy (vl->plugin, "libvirt", sizeof (vl->plugin));
 
     vl->host[0] = '\0';
-    host_ptr = vl->host;
-    host_len = sizeof (vl->host);
 
     /* Construct the hostname field according to HostnameFormat. */
     for (i = 0; i < HF_MAX_FIELDS; ++i) {
index b9afd81..1ab445a 100644 (file)
@@ -73,7 +73,6 @@ static int mec_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
     const value_list_t *vl,
     notification_meta_t __attribute__((unused)) **meta, void **user_data)
 {
-  mec_match_t *m;
   int num_counters;
   int num_empty;
   int i;
@@ -81,7 +80,6 @@ static int mec_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
   if ((user_data == NULL) || (*user_data == NULL))
     return (-1);
 
-  m = *user_data;
 
   num_counters = 0;
   num_empty = 0;
index b79a74b..6a50161 100644 (file)
@@ -321,9 +321,17 @@ static int memory_read (void)
 /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKSTAT
+        /* Most of the additions here were taken as-is from the k9toolkit from
+         * Brendan Gregg and are subject to change I guess */
        long long mem_used;
        long long mem_free;
        long long mem_lock;
+       long long mem_kern;
+       long long mem_unus;
+
+       long long pp_kernel;
+       long long physmem;
+       long long availrmem;
 
        if (ksp == NULL)
                return (-1);
@@ -331,20 +339,61 @@ static int memory_read (void)
        mem_used = get_kstat_value (ksp, "pagestotal");
        mem_free = get_kstat_value (ksp, "pagesfree");
        mem_lock = get_kstat_value (ksp, "pageslocked");
+       mem_kern = 0;
+       mem_unus = 0;
+
+       pp_kernel = get_kstat_value (ksp, "pp_kernel");
+       physmem = get_kstat_value (ksp, "physmem");
+       availrmem = get_kstat_value (ksp, "availrmem");
 
        if ((mem_used < 0LL) || (mem_free < 0LL) || (mem_lock < 0LL))
+       {
+               WARNING ("memory plugin: one of used, free or locked is negative.");
                return (-1);
+       }
+
+       mem_unus = physmem - mem_used;
+
        if (mem_used < (mem_free + mem_lock))
-               return (-1);
+       {
+               /* source: http://wesunsolve.net/bugid/id/4909199
+                * this seems to happen when swap space is small, e.g. 2G on a 32G system
+                * we will make some assumptions here
+                * educated solaris internals help welcome here */
+               DEBUG ("memory plugin: pages total is smaller than \"free\" "
+                               "+ \"locked\". This is probably due to small "
+                               "swap space");
+               mem_free = availrmem;
+               mem_used = 0;
+       }
+       else
+       {
+               mem_used -= mem_free + mem_lock;
+       }
+
+       /* mem_kern is accounted for in mem_lock */
+       if ( pp_kernel < mem_lock )
+       {
+               mem_kern = pp_kernel;
+               mem_lock -= pp_kernel;
+       }
+       else
+       {
+               mem_kern = mem_lock;
+               mem_lock = 0;
+       }
 
-       mem_used -= mem_free + mem_lock;
        mem_used *= pagesize; /* If this overflows you have some serious */
        mem_free *= pagesize; /* memory.. Why not call me up and give me */
        mem_lock *= pagesize; /* some? ;) */
+       mem_kern *= pagesize; /* it's 2011 RAM is cheap */
+       mem_unus *= pagesize;
 
        memory_submit ("used",   mem_used);
        memory_submit ("free",   mem_free);
        memory_submit ("locked", mem_lock);
+       memory_submit ("kernel", mem_kern);
+       memory_submit ("unusable", mem_unus);
 /* #endif HAVE_LIBKSTAT */
 
 #elif HAVE_SYSCTL
index 6a336c4..b502b37 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/meta_data.c
- * Copyright (C) 2008,2009  Florian octo Forster
+ * Copyright (C) 2008-2011  Florian octo Forster
  *
  * 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
@@ -101,6 +101,24 @@ static meta_entry_t *md_entry_alloc (const char *key) /* {{{ */
   return (e);
 } /* }}} meta_entry_t *md_entry_alloc */
 
+static meta_entry_t *md_entry_clone (const meta_entry_t *orig) /* {{{ */
+{
+  meta_entry_t *copy;
+
+  if (orig == NULL)
+    return (NULL);
+
+  copy = md_entry_alloc (orig->key);
+  copy->type = orig->type;
+  if (copy->type == MD_TYPE_STRING)
+    copy->value.mv_string = strdup (orig->value.mv_string);
+  else
+    copy->value = orig->value;
+
+  copy->next = md_entry_clone (orig->next);
+  return (copy);
+} /* }}} meta_entry_t *md_entry_clone */
+
 static void md_entry_free (meta_entry_t *e) /* {{{ */
 {
   if (e == NULL)
@@ -209,12 +227,31 @@ meta_data_t *meta_data_create (void) /* {{{ */
   return (md);
 } /* }}} meta_data_t *meta_data_create */
 
+meta_data_t *meta_data_clone (meta_data_t *orig) /* {{{ */
+{
+  meta_data_t *copy;
+
+  if (orig == NULL)
+    return (NULL);
+
+  copy = meta_data_create ();
+  if (copy == NULL)
+    return (NULL);
+
+  pthread_mutex_lock (&orig->lock);
+  copy->head = md_entry_clone (orig->head);
+  pthread_mutex_unlock (&orig->lock);
+
+  return (copy);
+} /* }}} meta_data_t *meta_data_clone */
+
 void meta_data_destroy (meta_data_t *md) /* {{{ */
 {
   if (md == NULL)
     return;
 
   md_entry_free (md->head);
+  pthread_mutex_destroy (&md->lock);
   free (md);
 } /* }}} void meta_data_destroy */
 
index 9ef7b0a..f1af40e 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/meta_data.h
- * Copyright (C) 2008,2009  Florian octo Forster
+ * Copyright (C) 2008-2011  Florian octo Forster
  *
  * 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
@@ -37,6 +37,7 @@ struct meta_data_s;
 typedef struct meta_data_s meta_data_t;
 
 meta_data_t *meta_data_create (void);
+meta_data_t *meta_data_clone (meta_data_t *orig);
 void meta_data_destroy (meta_data_t *md);
 
 int meta_data_exists (meta_data_t *md, const char *key);
index cae6760..6b63678 100644 (file)
@@ -555,7 +555,6 @@ static int mysql_read (user_data_t *ud)
        MYSQL_RES *res;
        MYSQL_ROW  row;
        char      *query;
-       int        field_num;
 
        derive_t qcache_hits          = 0;
        derive_t qcache_inserts       = 0;
@@ -591,7 +590,6 @@ static int mysql_read (user_data_t *ud)
        if (res == NULL)
                return (-1);
 
-       field_num = mysql_num_fields (res);
        while ((row = mysql_fetch_row (res)))
        {
                char *key;
index cc3d6b3..840577f 100644 (file)
@@ -405,7 +405,7 @@ static int network_dispatch_values (value_list_t *vl, /* {{{ */
     }
   }
 
-  plugin_dispatch_values (vl);
+  plugin_dispatch_values_secure (vl);
   stats_values_dispatched++;
 
   meta_data_destroy (vl->meta);
@@ -788,7 +788,6 @@ static int parse_part_number (void **ret_buffer, size_t *ret_buffer_len,
        size_t exp_size = 2 * sizeof (uint16_t) + sizeof (uint64_t);
 
        uint16_t pkg_length;
-       uint16_t pkg_type;
 
        if ((buffer_len < 0) || ((size_t) buffer_len < exp_size))
        {
@@ -802,7 +801,7 @@ static int parse_part_number (void **ret_buffer, size_t *ret_buffer_len,
 
        memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
        buffer += sizeof (tmp16);
-       pkg_type = ntohs (tmp16);
+       /* pkg_type = ntohs (tmp16); */
 
        memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
        buffer += sizeof (tmp16);
@@ -828,7 +827,6 @@ static int parse_part_string (void **ret_buffer, size_t *ret_buffer_len,
        size_t header_size = 2 * sizeof (uint16_t);
 
        uint16_t pkg_length;
-       uint16_t pkg_type;
 
        if ((buffer_len < 0) || (buffer_len < header_size))
        {
@@ -842,7 +840,7 @@ static int parse_part_string (void **ret_buffer, size_t *ret_buffer_len,
 
        memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
        buffer += sizeof (tmp16);
-       pkg_type = ntohs (tmp16);
+       /* pkg_type = ntohs (tmp16); */
 
        memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
        buffer += sizeof (tmp16);
@@ -3235,13 +3233,13 @@ static int network_stats_read (void) /* {{{ */
        vl.values[0].derive = (derive_t) copy_octets_rx;
        vl.values[1].derive = (derive_t) copy_octets_tx;
        sstrncpy (vl.type, "if_octets", sizeof (vl.type));
-       plugin_dispatch_values (&vl);
+       plugin_dispatch_values_secure (&vl);
 
        /* Packets received / send */
        vl.values[0].derive = (derive_t) copy_packets_rx;
        vl.values[1].derive = (derive_t) copy_packets_tx;
        sstrncpy (vl.type, "if_packets", sizeof (vl.type));
-       plugin_dispatch_values (&vl);
+       plugin_dispatch_values_secure (&vl);
 
        /* Values (not) dispatched and (not) send */
        sstrncpy (vl.type, "total_values", sizeof (vl.type));
@@ -3250,28 +3248,28 @@ static int network_stats_read (void) /* {{{ */
        vl.values[0].derive = (derive_t) copy_values_dispatched;
        sstrncpy (vl.type_instance, "dispatch-accepted",
                        sizeof (vl.type_instance));
-       plugin_dispatch_values (&vl);
+       plugin_dispatch_values_secure (&vl);
 
        vl.values[0].derive = (derive_t) copy_values_not_dispatched;
        sstrncpy (vl.type_instance, "dispatch-rejected",
                        sizeof (vl.type_instance));
-       plugin_dispatch_values (&vl);
+       plugin_dispatch_values_secure (&vl);
 
        vl.values[0].derive = (derive_t) copy_values_sent;
        sstrncpy (vl.type_instance, "send-accepted",
                        sizeof (vl.type_instance));
-       plugin_dispatch_values (&vl);
+       plugin_dispatch_values_secure (&vl);
 
        vl.values[0].derive = (derive_t) copy_values_not_sent;
        sstrncpy (vl.type_instance, "send-rejected",
                        sizeof (vl.type_instance));
-       plugin_dispatch_values (&vl);
+       plugin_dispatch_values_secure (&vl);
 
        /* Receive queue length */
        vl.values[0].gauge = (gauge_t) copy_receive_list_length;
        sstrncpy (vl.type, "queue_length", sizeof (vl.type));
        vl.type_instance[0] = 0;
-       plugin_dispatch_values (&vl);
+       plugin_dispatch_values_secure (&vl);
 
        return (0);
 } /* }}} int network_stats_read */
index 1cb7a90..3e162ba 100644 (file)
@@ -120,6 +120,7 @@ static int init (void)
     return (-1);
   }
 
+  curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1);
   curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, nginx_curl_callback);
   curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
   curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, nginx_curl_error);
index 839bc61..3f3c6df 100644 (file)
 #include <glib.h>
 #include <libnotify/notify.h>
 
+#ifndef NOTIFY_CHECK_VERSION
+# define NOTIFY_CHECK_VERSION(x,y,z) 0
+#endif
+
 #define log_info(...) INFO ("notify_desktop: " __VA_ARGS__)
 #define log_warn(...) WARNING ("notify_desktop: " __VA_ARGS__)
 #define log_err(...) ERROR ("notify_desktop: " __VA_ARGS__)
@@ -95,7 +99,12 @@ static int c_notify (const notification_t *n,
                                : (NOTIF_WARNING == n->severity) ? "WARNING"
                                : (NOTIF_OKAY == n->severity) ? "OKAY" : "UNKNOWN");
 
-       notification = notify_notification_new (summary, n->message, NULL, NULL);
+       notification = notify_notification_new (summary, n->message, NULL
+#if NOTIFY_CHECK_VERSION (0, 7, 0)
+       );
+#else
+       , NULL);
+#endif
        if (NULL == notification) {
                log_err ("Failed to create a new notification.");
                return -1;
index da6894a..cd216ca 100644 (file)
@@ -228,7 +228,6 @@ static int notify_email_config (const char *key, const char *value)
 static int notify_email_notification (const notification_t *n,
     user_data_t __attribute__((unused)) *user_data)
 {
-  smtp_recipient_t recipient;
 
   time_t tt;
   struct tm timestamp_tm;
@@ -290,7 +289,7 @@ static int notify_email_notification (const notification_t *n,
   smtp_set_message_str (message, buf);
 
   for (i = 0; i < recipients_len; i++)
-    recipient = smtp_add_recipient (message, recipients[i]);
+    smtp_add_recipient (message, recipients[i]);
 
   /* Initiate a connection to the SMTP server and transfer the message. */
   if (!smtp_start_session (session)) {
@@ -300,11 +299,13 @@ static int notify_email_notification (const notification_t *n,
     pthread_mutex_unlock (&session_lock);
     return (-1);
   } else {
+    #if COLLECT_DEBUG
     const smtp_status_t *status;
     /* Report on the success or otherwise of the mail transfer. */
     status = smtp_message_transfer_status (message);
     DEBUG ("notify_email plugin: SMTP server report: %d %s",
-        status->code, (status->text != NULL) ? status->text : "\n");
+      status->code, (status->text != NULL) ? status->text : "\n");
+    #endif
     smtp_enumerate_recipients (message, print_recipient_status, NULL);
   }
 
index 0356749..ec45996 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * collectd - src/oracle.c
- * Copyright (C) 2008,2009  Florian octo Forster
+ * Copyright (C) 2008,2009  noris network AG
+ * Copyright (C) 2012       Florian octo Forster
  *
  * 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
@@ -41,7 +42,7 @@
  * affiliates. Other names may be trademarks of their respective owners.
  *
  * Authors:
- *   Florian octo Forster <octo at noris.net>
+ *   Florian octo Forster <octo at collectd.org>
  **/
 
 #include "collectd.h"
@@ -91,32 +92,44 @@ static void o_report_error (const char *where, /* {{{ */
   sb4 error_code;
   int status;
 
-  status = OCIErrorGet (eh, /* record number = */ 1,
-      /* sqlstate = */ NULL,
-      &error_code,
-      (text *) &buffer[0],
-      (ub4) sizeof (buffer),
-      OCI_HTYPE_ERROR);
-  buffer[sizeof (buffer) - 1] = 0;
-
-  if (status == OCI_SUCCESS)
+  /* An operation may cause / return multiple errors. Loop until we have
+   * handled all errors available. */
+  while (42)
   {
-    size_t buffer_length;
+    memset (buffer, 0, sizeof (buffer));
+    error_code = -1;
+
+    status = OCIErrorGet (eh, /* record number = */ 1,
+        /* sqlstate = */ NULL,
+        &error_code,
+        (text *) &buffer[0],
+        (ub4) sizeof (buffer),
+        OCI_HTYPE_ERROR);
+    buffer[sizeof (buffer) - 1] = 0;
+
+    if (status == OCI_NO_DATA)
+      return;
 
-    buffer_length = strlen (buffer);
-    while ((buffer_length > 0) && (buffer[buffer_length - 1] < 32))
+    if (status == OCI_SUCCESS)
     {
-      buffer_length--;
-      buffer[buffer_length] = 0;
-    }
+      size_t buffer_length;
 
-    ERROR ("oracle plugin: %s: %s failed: %s",
-        where, what, buffer);
-  }
-  else
-  {
-    ERROR ("oracle plugin: %s: %s failed. Additionally, OCIErrorGet failed with status %i.",
-        where, what, status);
+      buffer_length = strlen (buffer);
+      while ((buffer_length > 0) && (buffer[buffer_length - 1] < 32))
+      {
+        buffer_length--;
+        buffer[buffer_length] = 0;
+      }
+
+      ERROR ("oracle plugin: %s: %s failed: %s",
+          where, what, buffer);
+    }
+    else
+    {
+      ERROR ("oracle plugin: %s: %s failed. Additionally, OCIErrorGet failed with status %i.",
+          where, what, status);
+      return;
+    }
   }
 } /* }}} void o_report_error */
 
@@ -555,11 +568,15 @@ static int o_read_database_query (o_database_t *db, /* {{{ */
         &column_name, &column_name_length, OCI_ATTR_NAME, oci_error);
     if (status != OCI_SUCCESS)
     {
+      OCIDescriptorFree (oci_param, OCI_DTYPE_PARAM);
       o_report_error ("o_read_database_query", "OCIAttrGet (OCI_ATTR_NAME)",
           oci_error);
       continue;
     }
 
+    OCIDescriptorFree (oci_param, OCI_DTYPE_PARAM);
+    oci_param = NULL;
+
     /* Copy the name to column_names. Warning: The ``string'' returned by OCI
      * may not be null terminated! */
     memset (column_names[i], 0, DATA_MAX_NAME_LEN);
@@ -737,6 +754,7 @@ static int o_shutdown (void) /* {{{ */
   }
   
   OCIHandleFree (oci_env, OCI_HTYPE_ENV);
+  oci_env = NULL;
 
   udb_query_free (queries, queries_num);
   queries = NULL;
index 8f0b0f0..7e48e18 100644 (file)
@@ -549,7 +549,7 @@ static int iptcc_chain_index_rebuild(TC_HANDLE_T h)
  */
 static int iptcc_chain_index_delete_chain(struct chain_head *c, TC_HANDLE_T h)
 {
-       struct list_head *index_ptr, *index_ptr2, *next;
+       struct list_head *index_ptr, *next;
        struct chain_head *c2;
        unsigned int idx, idx2;
 
@@ -569,7 +569,7 @@ static int iptcc_chain_index_delete_chain(struct chain_head *c, TC_HANDLE_T h)
                 * is located in the same index bucket.
                 */
                c2         = list_entry(next, struct chain_head, list);
-               index_ptr2 = iptcc_bsearch_chain_index(c2->name, &idx2, h);
+               iptcc_bsearch_chain_index(c2->name, &idx2, h);
                if (idx != idx2) {
                        /* Rebuild needed */
                        return iptcc_chain_index_rebuild(h);
@@ -1192,10 +1192,8 @@ static int iptcc_compile_table(TC_HANDLE_T h, STRUCT_REPLACE *repl)
 static TC_HANDLE_T
 alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules)
 {
-       size_t len;
        TC_HANDLE_T h;
 
-       len = sizeof(STRUCT_TC_HANDLE) + size;
 
        h = malloc(sizeof(STRUCT_TC_HANDLE));
        if (!h) {
index 89a2e00..91c40b6 100644 (file)
@@ -1423,7 +1423,8 @@ int plugin_dispatch_values (value_list_t *vl)
        if ((vl == NULL) || (vl->type[0] == 0)
                        || (vl->values == NULL) || (vl->values_len < 1))
        {
-               ERROR ("plugin_dispatch_values: Invalid value list.");
+               ERROR ("plugin_dispatch_values: Invalid value list "
+                               "from plugin %s.", vl->plugin);
                return (-1);
        }
 
@@ -1585,6 +1586,52 @@ int plugin_dispatch_values (value_list_t *vl)
        return (0);
 } /* int plugin_dispatch_values */
 
+int plugin_dispatch_values_secure (const value_list_t *vl)
+{
+  value_list_t vl_copy;
+  int status;
+
+  if (vl == NULL)
+    return EINVAL;
+
+  memcpy (&vl_copy, vl, sizeof (vl_copy));
+
+  /* Write callbacks must not change the values and meta pointers, so we can
+   * savely skip copying those and make this more efficient. */
+  if ((pre_cache_chain == NULL) && (post_cache_chain == NULL))
+    return (plugin_dispatch_values (&vl_copy));
+
+  /* Set pointers to NULL, just to be on the save side. */
+  vl_copy.values = NULL;
+  vl_copy.meta = NULL;
+
+  vl_copy.values = malloc (sizeof (*vl_copy.values) * vl->values_len);
+  if (vl_copy.values == NULL)
+  {
+    ERROR ("plugin_dispatch_values_secure: malloc failed.");
+    return (ENOMEM);
+  }
+  memcpy (vl_copy.values, vl->values, sizeof (*vl_copy.values) * vl->values_len);
+
+  if (vl->meta != NULL)
+  {
+    vl_copy.meta = meta_data_clone (vl->meta);
+    if (vl_copy.meta == NULL)
+    {
+      ERROR ("plugin_dispatch_values_secure: meta_data_clone failed.");
+      free (vl_copy.values);
+      return (ENOMEM);
+    }
+  } /* if (vl->meta) */
+
+  status = plugin_dispatch_values (&vl_copy);
+
+  meta_data_destroy (vl_copy.meta);
+  free (vl_copy.values);
+
+  return (status);
+} /* int plugin_dispatch_values_secure */
+
 int plugin_dispatch_notification (const notification_t *notif)
 {
        llentry_t *le;
index e880472..86d4034 100644 (file)
@@ -2,7 +2,7 @@
 #define PLUGIN_H
 /**
  * collectd - src/plugin.h
- * Copyright (C) 2005-2010  Florian octo Forster
+ * Copyright (C) 2005-2011  Florian octo Forster
  *
  * 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
@@ -318,6 +318,7 @@ int plugin_unregister_notification (const char *name);
  *              function.
  */
 int plugin_dispatch_values (value_list_t *vl);
+int plugin_dispatch_values_secure (const value_list_t *vl);
 int plugin_dispatch_missing (const value_list_t *vl);
 
 int plugin_dispatch_notification (const notification_t *notif);
index 72442f0..8f4eb88 100644 (file)
 #  define ARG_MAX 4096
 #endif
 
-static const char *config_keys[] =
-{
-       "Process",
-       "ProcessMatch"
-};
-static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
-
 typedef struct procstat_entry_s
 {
        unsigned long id;
@@ -520,42 +513,61 @@ static void ps_list_reset (void)
 }
 
 /* put all pre-defined 'Process' names from config to list_head_g tree */
-static int ps_config (const char *key, const char *value)
+static int ps_config (oconfig_item_t *ci)
 {
-       if (strcasecmp (key, "Process") == 0)
-       {
-               ps_list_register (value, NULL);
-       }
-       else if (strcasecmp (key, "ProcessMatch") == 0)
-       {
-               char *new_val;
-               char *fields[3];
-               int fields_num;
-
-               new_val = strdup (value);
-               if (new_val == NULL) {
-                       ERROR ("processes plugin: strdup failed when processing "
-                                       "`ProcessMatch %s'.", value);
-                       return (1);
+       int i;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *c = ci->children + i;
+
+               if (strcasecmp (c->key, "Process") == 0)
+               {
+                       if ((c->values_num != 1)
+                                       || (OCONFIG_TYPE_STRING != c->values[0].type)) {
+                               ERROR ("processes plugin: `Process' expects exactly "
+                                               "one string argument (got %i).",
+                                               c->values_num);
+                               continue;
+                       }
+
+                       if (c->children_num != 0) {
+                               WARNING ("processes plugin: the `Process' config option "
+                                               "does not expect any child elements -- ignoring "
+                                               "content (%i elements) of the <Process '%s'> block.",
+                                               c->children_num, c->values[0].value.string);
+                       }
+
+                       ps_list_register (c->values[0].value.string, NULL);
                }
+               else if (strcasecmp (c->key, "ProcessMatch") == 0)
+               {
+                       if ((c->values_num != 2)
+                                       || (OCONFIG_TYPE_STRING != c->values[0].type)
+                                       || (OCONFIG_TYPE_STRING != c->values[1].type))
+                       {
+                               ERROR ("processes plugin: `ProcessMatch' needs exactly "
+                                               "two string arguments (got %i).",
+                                               c->values_num);
+                               continue;
+                       }
 
-               fields_num = strsplit (new_val, fields,
-                               STATIC_ARRAY_SIZE (fields));
-               if (fields_num != 2)
+                       if (c->children_num != 0) {
+                               WARNING ("processes plugin: the `ProcessMatch' config option "
+                                               "does not expect any child elements -- ignoring "
+                                               "content (%i elements) of the <ProcessMatch '%s' '%s'> "
+                                               "block.", c->children_num, c->values[0].value.string,
+                                               c->values[1].value.string);
+                       }
+
+                       ps_list_register (c->values[0].value.string,
+                                       c->values[1].value.string);
+               }
+               else
                {
-                       ERROR ("processes plugin: `ProcessMatch' needs exactly "
-                                       "two string arguments.");
-                       sfree (new_val);
-                       return (1);
+                       ERROR ("processes plugin: The `%s' configuration option is not "
+                                       "understood and will be ignored.", c->key);
+                       continue;
                }
-               ps_list_register (fields[0], fields[1]);
-               sfree (new_val);
-       }
-       else
-       {
-               ERROR ("processes plugin: The `%s' configuration option is not "
-                               "understood and will be ignored.", key);
-               return (-1);
        }
 
        return (0);
@@ -871,7 +883,6 @@ int ps_read_process (int pid, procstat_t *ps, char *state)
 
        int   i;
 
-       int   ppid;
        int   name_len;
 
        derive_t cpu_user_counter;
@@ -909,7 +920,6 @@ int ps_read_process (int pid, procstat_t *ps, char *state)
        fields[1][name_len] = '\0';
        strncpy (ps->name, fields[1], PROCSTAT_NAME_LEN);
 
-       ppid = atoi (fields[3]);
 
        *state = fields[2][0];
 
@@ -1829,8 +1839,7 @@ static int ps_read (void)
 
 void module_register (void)
 {
-       plugin_register_config ("processes", ps_config,
-                       config_keys, config_keys_num);
+       plugin_register_complex_config ("processes", ps_config);
        plugin_register_init ("processes", ps_init);
        plugin_register_read ("processes", ps_read);
 } /* void module_register */
index 36a717e..9d8760a 100644 (file)
@@ -408,8 +408,12 @@ static meta_data_t *cpy_build_meta(PyObject *meta) {
        if (!meta)
                return NULL;
 
+       l = PyDict_Items(meta); /* New reference. */
+       if (!l) {
+               cpy_log_exception("building meta data");
+               return NULL;
+       }
        m = meta_data_create();
-       l = PyDict_Items(meta);
        s = PyList_Size(l);
        for (i = 0; i < s; ++i) {
                const char *string, *keystring;
@@ -474,6 +478,7 @@ static meta_data_t *cpy_build_meta(PyObject *meta) {
                Py_XDECREF(value);
                Py_DECREF(key);
        }
+       Py_XDECREF(l);
        return m;
 }
 
@@ -523,27 +528,35 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
        value = malloc(size * sizeof(*value));
        for (i = 0; i < size; ++i) {
                PyObject *item, *num;
-               item = PySequence_GetItem(values, i);
+               item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
                if (ds->ds->type == DS_TYPE_COUNTER) {
-                       num = PyNumber_Long(item);
-                       if (num != NULL)
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].counter = PyLong_AsUnsignedLongLong(num);
+                               Py_XDECREF(num);
+                       }
                } else if (ds->ds->type == DS_TYPE_GAUGE) {
-                       num = PyNumber_Float(item);
-                       if (num != NULL)
+                       num = PyNumber_Float(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].gauge = PyFloat_AsDouble(num);
+                               Py_XDECREF(num);
+                       }
                } else if (ds->ds->type == DS_TYPE_DERIVE) {
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
-                       num = PyNumber_Long(item);
-                       if (num != NULL)
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].derive = PyLong_AsLongLong(num);
+                               Py_XDECREF(num);
+                       }
                } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
-                       num = PyNumber_Long(item);
-                       if (num != NULL)
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].absolute = PyLong_AsUnsignedLongLong(num);
+                               Py_XDECREF(num);
+                       }
                } else {
                        free(value);
                        PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, type);
@@ -571,11 +584,12 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
        Py_BEGIN_ALLOW_THREADS;
        ret = plugin_dispatch_values(&value_list);
        Py_END_ALLOW_THREADS;
+       meta_data_destroy(value_list.meta);
+       free(value);
        if (ret != 0) {
                PyErr_SetString(PyExc_RuntimeError, "error dispatching values, read the logs");
                return NULL;
        }
-       free(value);
        Py_RETURN_NONE;
 }
 
@@ -622,27 +636,35 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
        value = malloc(size * sizeof(*value));
        for (i = 0; i < size; ++i) {
                PyObject *item, *num;
-               item = PySequence_GetItem(values, i);
+               item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
                if (ds->ds->type == DS_TYPE_COUNTER) {
-                       num = PyNumber_Long(item);
-                       if (num != NULL)
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].counter = PyLong_AsUnsignedLongLong(num);
+                               Py_XDECREF(num);
+                       }
                } else if (ds->ds->type == DS_TYPE_GAUGE) {
-                       num = PyNumber_Float(item);
-                       if (num != NULL)
+                       num = PyNumber_Float(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].gauge = PyFloat_AsDouble(num);
+                               Py_XDECREF(num);
+                       }
                } else if (ds->ds->type == DS_TYPE_DERIVE) {
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
-                       num = PyNumber_Long(item);
-                       if (num != NULL)
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].derive = PyLong_AsLongLong(num);
+                               Py_XDECREF(num);
+                       }
                } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
-                       num = PyNumber_Long(item);
-                       if (num != NULL)
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].absolute = PyLong_AsUnsignedLongLong(num);
+                               Py_XDECREF(num);
+                       }
                } else {
                        free(value);
                        PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, type);
@@ -670,11 +692,12 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
        Py_BEGIN_ALLOW_THREADS;
        ret = plugin_write(dest, NULL, &value_list);
        Py_END_ALLOW_THREADS;
+       meta_data_destroy(value_list.meta);
+       free(value);
        if (ret != 0) {
                PyErr_SetString(PyExc_RuntimeError, "error dispatching values, read the logs");
                return NULL;
        }
-       free(value);
        Py_RETURN_NONE;
 }
 
index b366a9c..56a82d0 100644 (file)
@@ -998,7 +998,7 @@ static int rrd_config (const char *key, const char *value)
        }
        else if (strcasecmp ("StepSize", key) == 0)
        {
-               int temp = atoi (value);
+               unsigned long temp = strtoul (value, NULL, 0);
                if (temp > 0)
                        rrdcreate_config.stepsize = temp;
        }
@@ -1161,8 +1161,6 @@ static int rrd_init (void)
                return (0);
        init_once = 1;
 
-       if (rrdcreate_config.stepsize < 0)
-               rrdcreate_config.stepsize = 0;
        if (rrdcreate_config.heartbeat <= 0)
                rrdcreate_config.heartbeat = 2 * rrdcreate_config.stepsize;
 
@@ -1206,7 +1204,7 @@ static int rrd_init (void)
        }
        queue_thread_running = 1;
 
-       DEBUG ("rrdtool plugin: rrd_init: datadir = %s; stepsize = %i;"
+       DEBUG ("rrdtool plugin: rrd_init: datadir = %s; stepsize = %lu;"
                        " heartbeat = %i; rrarows = %i; xff = %lf;",
                        (datadir == NULL) ? "(null)" : datadir,
                        rrdcreate_config.stepsize,
index a78e700..2552ad3 100644 (file)
@@ -299,6 +299,13 @@ static int tss2_get_socket (FILE **ret_read_fh, FILE **ret_write_fh)
                char *buffer_ptr;
 
                buffer_ptr = fgets (buffer, sizeof (buffer), global_read_fh);
+               if (buffer_ptr == NULL)
+               {
+                       WARNING ("teamspeak2 plugin: Unexpected EOF received "
+                                       "from remote host %s:%s.",
+                                       config_host ? config_host : DEFAULT_HOST,
+                                       config_port ? config_port : DEFAULT_PORT);
+               }
                buffer[sizeof (buffer) - 1] = 0;
 
                if (memcmp ("[TS]\r\n", buffer, 6) != 0)
index d1c8d5d..cfa4a5c 100644 (file)
@@ -450,7 +450,6 @@ handle_ipv6 (struct ip6_hdr *ipv6, int len)
     int nexthdr;
 
     struct in6_addr s_addr;
-    struct in6_addr d_addr;
     uint16_t payload_len;
 
     if (0 > len)
@@ -459,7 +458,6 @@ handle_ipv6 (struct ip6_hdr *ipv6, int len)
     offset = sizeof (struct ip6_hdr);
     nexthdr = ipv6->ip6_nxt;
     s_addr = ipv6->ip6_src;
-    d_addr = ipv6->ip6_dst;
     payload_len = ntohs (ipv6->ip6_plen);
 
     if (ignore_list_match (&s_addr))
index 65c886b..2a5526b 100644 (file)
@@ -264,7 +264,7 @@ static int value_list_to_json (char *buffer, size_t buffer_size, /* {{{ */
     return (status);
   BUFFER_ADD (",\"dsnames\":%s", temp);
 
-  BUFFER_ADD (",\"time\":%lu", (unsigned long) vl->time);
+  BUFFER_ADD (",\"time\":%.3f", CDTIME_T_TO_DOUBLE (vl->time));
   BUFFER_ADD (",\"interval\":%.3f", CDTIME_T_TO_DOUBLE (vl->interval));
 
 #define BUFFER_ADD_KEYVAL(key, value) do { \
index 5b13238..91ac6ce 100644 (file)
@@ -156,7 +156,7 @@ static int rra_get (char ***ret, const value_list_t *vl, /* {{{ */
       if (rra_num >= rra_max)
         break;
 
-      status = ssnprintf (buffer, sizeof (buffer), "RRA:%s:%3.1f:%u:%u",
+      status = ssnprintf (buffer, sizeof (buffer), "RRA:%s:%.10f:%u:%u",
           rra_types[j], cfg->xff, cdp_len, cdp_num);
 
       if ((status < 0) || ((size_t) status >= sizeof (buffer)))
@@ -374,7 +374,7 @@ int cu_rrd_create_file (const char *filename, /* {{{ */
   int ds_num;
   int status = 0;
   time_t last_up;
-  int stepsize;
+  unsigned long stepsize;
 
   if (check_create_dir (filename))
     return (-1);
@@ -413,11 +413,9 @@ int cu_rrd_create_file (const char *filename, /* {{{ */
   if (cfg->stepsize > 0)
     stepsize = cfg->stepsize;
   else
-    stepsize = (int) CDTIME_T_TO_TIME_T (vl->interval);
+    stepsize = (unsigned long) CDTIME_T_TO_TIME_T (vl->interval);
 
-  status = srrd_create (filename,
-      (cfg->stepsize > 0) ? cfg->stepsize : CDTIME_T_TO_TIME_T (vl->interval),
-      last_up,
+  status = srrd_create (filename, stepsize, last_up,
       argc, (const char **) argv);
 
   free (argv);
index 935e4e0..103ca57 100644 (file)
@@ -28,7 +28,7 @@
 
 struct rrdcreate_config_s
 {
-  int    stepsize;
+  unsigned long stepsize;
   int    heartbeat;
   int    rrarows;
   double xff;
index 859df21..37fd4bb 100644 (file)
@@ -307,9 +307,9 @@ static void varnish_monitor (const user_config_t *conf, struct varnish_stats *VS
                /* outstanding allocations */
                varnish_submit_gauge (conf->instance,  "sm", "requests", "outstanding", VSL_stats->sm_nobj);
                /* bytes allocated */
-               varnish_submit_gauge (conf->instance,  "sm", "total_bytes", "allocated",      VSL_stats->sm_balloc);
+               varnish_submit_derive (conf->instance,  "sm", "total_bytes", "allocated",      VSL_stats->sm_balloc);
                /* bytes free */
-               varnish_submit_gauge (conf->instance,  "sm", "total_bytes", "free",           VSL_stats->sm_bfree);
+               varnish_submit_derive (conf->instance,  "sm", "total_bytes", "free",           VSL_stats->sm_bfree);
        }
 
        if (conf->collect_sma)
@@ -321,9 +321,9 @@ static void varnish_monitor (const user_config_t *conf, struct varnish_stats *VS
                /* SMA outstanding bytes */
                varnish_submit_gauge (conf->instance,  "sma", "bytes", "outstanding",    VSL_stats->sma_nbytes);
                /* SMA bytes allocated */
-               varnish_submit_gauge (conf->instance,  "sma", "total_bytes", "allocated",      VSL_stats->sma_balloc);
+               varnish_submit_derive (conf->instance,  "sma", "total_bytes", "allocated",      VSL_stats->sma_balloc);
                /* SMA bytes free */
-               varnish_submit_gauge (conf->instance,  "sma", "total_bytes", "free" ,          VSL_stats->sma_bfree);
+               varnish_submit_derive (conf->instance,  "sma", "total_bytes", "free" ,          VSL_stats->sma_bfree);
        }
 
        if (conf->collect_sms)
@@ -335,9 +335,9 @@ static void varnish_monitor (const user_config_t *conf, struct varnish_stats *VS
                /* SMS outstanding bytes */
                varnish_submit_gauge (conf->instance,  "sms", "bytes", "outstanding",        VSL_stats->sms_nbytes);
                /* SMS bytes allocated */
-               varnish_submit_gauge (conf->instance,  "sms", "total_bytes", "allocated",          VSL_stats->sms_balloc);
+               varnish_submit_derive (conf->instance,  "sms", "total_bytes", "allocated",          VSL_stats->sms_balloc);
                /* SMS bytes freed */
-               varnish_submit_gauge (conf->instance,  "sms", "total_bytes", "free",               VSL_stats->sms_bfree);
+               varnish_submit_derive (conf->instance,  "sms", "total_bytes", "free",               VSL_stats->sms_bfree);
        }
 
        if (conf->collect_totals)
@@ -363,17 +363,17 @@ static void varnish_monitor (const user_config_t *conf, struct varnish_stats *VS
                /* worker threads */
                varnish_submit_gauge (conf->instance, "workers", "threads", "worker",            VSL_stats->n_wrk);
                /* worker threads created */
-               varnish_submit_gauge (conf->instance, "workers", "total_threads", "created",     VSL_stats->n_wrk_create);
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "created",     VSL_stats->n_wrk_create);
                /* worker threads not created */
-               varnish_submit_gauge (conf->instance, "workers", "total_threads", "failed",      VSL_stats->n_wrk_failed);
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "failed",      VSL_stats->n_wrk_failed);
                /* worker threads limited */
-               varnish_submit_gauge (conf->instance, "workers", "total_threads", "limited",     VSL_stats->n_wrk_max);
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",     VSL_stats->n_wrk_max);
                /* queued work requests */
-               varnish_submit_gauge (conf->instance, "workers", "total_requests", "queued",     VSL_stats->n_wrk_queue);
+               varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",     VSL_stats->n_wrk_queue);
                /* overflowed work requests */
-               varnish_submit_gauge (conf->instance, "workers", "total_requests", "overflowed", VSL_stats->n_wrk_overflow);
+               varnish_submit_derive (conf->instance, "workers", "total_requests", "overflowed", VSL_stats->n_wrk_overflow);
                /* dropped work requests */
-               varnish_submit_gauge (conf->instance, "workers", "total_requests", "dropped",    VSL_stats->n_wrk_drop);
+               varnish_submit_derive (conf->instance, "workers", "total_requests", "dropped",    VSL_stats->n_wrk_drop);
        }
 } /* }}} void varnish_monitor */
 
index 1a0e4ef..3035e43 100644 (file)
@@ -111,6 +111,7 @@ static int wh_callback_init (wh_callback_t *cb) /* {{{ */
                 return (-1);
         }
 
+        curl_easy_setopt (cb->curl, CURLOPT_NOSIGNAL, 1);
         curl_easy_setopt (cb->curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
 
         headers = NULL;
index f232dc8..5bc20a1 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-DEFAULT_VERSION="5.0.0.git"
+DEFAULT_VERSION="5.0.2.git"
 
 VERSION="`git describe 2> /dev/null | sed -e 's/^collectd-//'`"