Merge pull request #2613 from elfiesmelfie/update_dpdk_note
authorPavel Rochnyak <pavel2000@ngs.ru>
Sat, 10 Feb 2018 11:19:02 +0000 (18:19 +0700)
committerGitHub <noreply@github.com>
Sat, 10 Feb 2018 11:19:02 +0000 (18:19 +0700)
docs: update dpdkstats documentation

70 files changed:
ChangeLog
README
configure.ac
contrib/redhat/collectd.spec
contrib/systemd.collectd.service
src/Makefile.am
src/aggregation.c
src/amqp.c
src/apache.c
src/ascent.c
src/battery.c
src/bind.c
src/collectd-python.pod
src/collectd.conf.in
src/collectd.conf.pod
src/curl.c
src/curl_json.c
src/curl_xml.c
src/daemon/collectd.c
src/daemon/common.c
src/daemon/common.h
src/daemon/configfile.c
src/daemon/meta_data.c
src/daemon/plugin.c
src/daemon/utils_cache.c
src/dbi.c
src/dpdkstat.c
src/email.c
src/exec.c
src/gps.c
src/intel_rdt.c
src/ipc.c
src/liboconfig/parser.y
src/log_logstash.c
src/logfile.c
src/memcached.c
src/mqtt.c
src/msr-index.h [new file with mode: 0644]
src/netapp.c
src/netlink.c
src/network.c
src/nginx.c
src/ntpd.c
src/openldap.c
src/perl.c
src/ping.c
src/postgresql_default.conf
src/powerdns.c
src/processes.c
src/rrdtool.c
src/smart.c
src/snmp.c
src/table.c
src/target_set.c
src/tcpconns.c
src/turbostat.c
src/unixsock.c
src/utils_cmd_getthreshold.c
src/utils_cmd_putval.c
src/utils_format_graphite.c
src/utils_format_json.c
src/utils_match.c
src/write_graphite.c
src/write_http.c
src/write_kafka.c
src/write_prometheus.c
src/write_riemann.c
src/write_sensu.c
src/write_tsdb.c
version-gen.sh

index db0b062..f990dd4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,69 @@
+2017-06-06, Version 5.7.2
+       * Build system: The Notify Email plugin is no longer linked with
+         indirect dependencies. Thanks to Marc Fournier.
+       * collectd: A race condition when calculating a metric's rate has been
+         fixed. Thanks to Florian Forster. #1193
+       * AMQP, Exec, UnixSock, Write Kafka plugins: Parsing of the PUTVAL
+         command with multiple values has been fixed. Thanks to Florian
+         Forster. #2274
+       * AMQP plugin: The "ExchangeType" option is now also valid for
+         publishers. Thanks to Florian Forster. #2286
+       * BIND plugin: Fix parsing of the sample time provided by BIND.
+         Previously, the time was assumed to be in the local timezone when in
+         fact it was in UTC. Thanks to Ed Ravin. #1268
+       * BIND plugin: Memory leaks have been fixed. Thanks to Ruben Kerkhof.
+         #2303
+       * cURL-JSON plugin: Handling of arrays has been fixed. Thanks to Florian
+         Forster. #2266
+       * DPDKStat plugin: Error handling during initialization has been
+         improved. Thanks to Ruben Kerkhof.
+       * DPDKStat plugin: Handling of a number of metrics has been improved,
+         for example "rx_q0bytes". Thanks to Przemyslaw Szczerbik. #2167
+       * Intel RDT plugin: Configuration handling has been changed to be more
+         graceful. Thanks to Maryam Tahhan. #2165
+       * Log Logstash plugin: If writing the log entry fails, print it to
+         "STDERR" instead. Thanks to Marc Fournier.
+       * LogFile plugin: If writing to the file fails, print log messages on
+         "STDERR" instead. Thanks to Marc Fournier.
+       * memcachec, Tail plugins: A resource leak in the matching
+         infrastructure has been fixed. Thanks to Krzysztof Matczak. #2192
+       * MQTT plugin: Invalid symbols in topic names are now replaced and a
+         resource leak has been fixed. Thanks to Denys Fedoryshchenko. #2123
+       * Network plugin: A potential endless-loop has been fixed. This can be
+         triggered remotely by sending a signed network packet to a server
+         which is not set up to check signatures. Thanks to Marcin Kozlowski
+         and Pavel Rochnyack. #2174, #2233, CVE-2017-7401
+       * Perl plugin: A potential double-free has been fixed. Thanks to Florian
+         Forster. #2278
+       * Processes plugin: A compilation error on AIX has been fixed. Thanks to
+         Pavel Rochnyack. #2210
+       * SMART plugin: A check for the "CAP_SYS_RAWIO" capability has been
+         added. Thanks to Marc Fournier.
+       * Write Graphite plugin: Error handling in the case that calculating a
+         metric's rate fails has been improved. Previously, the raw counter
+         values were sent to Graphite. Thanks to Iain Buclaw. #2209
+       * Write Prometheus plugin: An incorrect use of "realloc(3)" has been
+         fixed. Thanks to Florian Forster. #2275
+
+2017-01-23, Version 5.7.1
+       * collectd: Handling of boolean configuration options has been unified.
+         Thanks to Sebastian Harl. #2083, #2098
+       * collectd: Reporting of internal statistics has been fixed. Thanks to
+         Florian Forster. #2108
+       * collectd, various plugins: Bugs and issues reported by scan-build and
+         coverity-scan have been fixed. Thanks to Ruben Kerkhof and Florian
+         Forster.
+       * Build system: Parallel build have been fixed. Thanks to Ruben Kerkhof.
+         #2110
+       * DPDKStat plugin: Portability issues and a double-close bug have been
+         fixed. Thanks to Ruben Kerkhof and Marc Fournier.
+       * Intel RDT plugin: A check for the libpqos library version has been
+         added. Thanks to Serhiy Pshyk.
+       * NetApp plugin: Compilation problems have been corrected. Thanks to
+         Florian Forster. #2120
+       * Write Prometheus plugin: A memory leak has been fixed. Thanks to Ruben
+         Kerkhof.
+
 2016-12-12, Version 5.7.0
        * Documentation: The Turbostat plugin section has been improved. Thanks
          to Florian Forster
          embedded HTTP server, in a format compatible with Prometheus'
          collectd_exporter. Thanks to Florian Forster. #1967
 
+2017-10-06, Version 5.6.3
+       * collectd: support for boolean string config values has been
+         reintroduced. Thanks to Sebastian Harl. #2083, #2098
+       * collectd: The capability checking has been changed to use
+         "cap_get_proc()". Thanks to Marc Fournier. #2151
+       * Documentation: A section documenting ignore lists has been added to
+         collectd.conf(5). Thanks to Florian Forster.
+       * AMQP plugin: The "ExchangeType" option is now also valid for
+         publishers. Thanks to Florian Forster. #2286
+       * Apache, Ascent, BIND, cURL, cURL-JSON, cURL-XML, nginx, Write HTTP
+         plugins: Handling of URLs that redirect elsewhere has been fixed.
+         Thanks to Pavel Rochnyack. #2328
+       * BIND plugin: Fix parsing of the sample time provided by BIND.
+         Previously, the time was assumed to be in the local time zone when in
+         fact it was in UTC. Thanks to Ed Ravin. #1268
+       * BIND plugin: Memory leaks have been fixed. Thanks to Ruben Kerkhof.
+         #2303
+       * Chrony plugin: Build flags have been fixed. Thanks to Thomas Jost and
+         Marc Fournier. #2133
+       * cURL-JSON plugin: The timeout value has been changed to default to the
+         collection interval. This fixes a regression. Thanks to Marc Fournier.
+       * cURL-JSON plugin: Handling of arrays has been fixed. Thanks to Florian
+         Forster. #2266
+       * DBI plugin: Memory leaks at shutdown have been fixes. Thanks to Pavel
+         Rochnyack and Florian Forster.
+       * E-Mail, Exec, UnixSock plugins: Group ID lookup on systems with many
+         groups has been fixed. Thanks to Ruben Kerkhof and Florian Forster.
+         #2208
+       * IPC plugin: A compilation error on AIX has been fixed. Thanks to Pavel
+         Rochnyack. #2305
+       * LogFile plugin: If writing to the file fails, print log messages on
+         "STDERR" instead. Thanks to Marc Fournier.
+       * Log Logstash plugin: If writing the log entry fails, print it to
+         "STDERR" instead. Thanks to Marc Fournier.
+       * memcachec, Tail plugins: A resource leak in the matching
+         infrastructure has been fixed. Thanks to Krzysztof Matczak. #2192
+       * MQTT plugin: Invalid symbols in topic names are now replaced and a
+         resource leak has been fixed. Thanks to Denys Fedoryshchenko. #2123
+       * Network plugin: A potential endless-loop has been fixed. This can be
+         triggered remotely by sending a signed network packet to a server
+         which is not set up to check signatures. Thanks to Marcin Kozlowski
+         and Pavel Rochnyack. #2174, #2233, CVE-2017-7401
+       * Network plugin: A use-after-free has been fixed. Thanks to Pavel
+         Rochnyack. #2375
+       * Notify Email plugin: The plugin is no longer explicitly linked against
+         libssl and libcrypto, relies on libesmtp being linked correctly.
+         Thanks to Marc Fournier. Debian#852924
+       * NTPd plugin: Calculation of loop offset and error has been fixed.
+         Thanks to Neil Wilson. #2188
+       * OpenLDAP plugin: An incorrect use of the ldap library, leading to a
+         crash, has been fixed. Thanks to Marc Fournier. #2331
+       * Perl plugin: A potential double-free has been fixed. Thanks to Florian
+         Forster. #2278
+       * Perl plugin: Print an error when an incorrect configuration is
+         encountered. Thanks to Pavel Rochnyack. #927
+       * RRDtool plugin: Incorrect handling of the flushes timeout option has
+         been fixed. Handling of the "RandomTimeout" has been fixed. Thanks to
+         Pavel Rochnyack. #2363
+       * SMART plugin: Some warning messages have been removed and the code has
+         been cleaned up. Thanks to Florian Forster. #2062
+       * SMART plugin: A check for the "CAP_SYS_RAWIO" capability has been
+         added. Thanks to Marc Fournier.
+       * SNMP plugin: A double free has been fixed. Thanks to Pavel Rochnyack.
+         #2291
+       * Write Graphite plugin: Error handling in the case that calculating a
+         metric's rate fails has been improved. Previously, the raw counter
+         values were sent to Graphite. Thanks to Iain Buclaw. #2209
+       * Write Kafka plugin: A 32 bit random number is now used when formatting
+         a random key. Thanks to Florian Forster. #2074
+
+
 2016-11-30, Version 5.6.2
        * collectd: A compile error on AIX has been fixed: "MSG_DONTWAIT" is not
          available on AIX. Thanks to Chao Yang.
diff --git a/README b/README
index 0989312..803fbaa 100644 (file)
--- a/README
+++ b/README
@@ -500,6 +500,10 @@ Features
     - write_mongodb
       Sends data to MongoDB, a NoSQL database.
 
+    - write_prometheus
+      Publish values using an embedded HTTP server, in a format compatible
+      with Prometheus' collectd_exporter.
+
     - write_redis
       Sends the values to a Redis key-value database server.
 
@@ -780,6 +784,10 @@ Prerequisites
     Used by the `memcachec' plugin to connect to a memcache daemon.
     <http://tangent.org/552/libmemcached.html>
 
+  * libmicrohttpd (optional)
+    Used by the write_prometheus plugin to run an http daemon.
+    <http://www.gnu.org/software/libmicrohttpd/>
+
   * libmnl (optional)
     Used by the `netlink' plugin.
     <http://www.netfilter.org/projects/libmnl/>
index 993e319..c4cdf4d 100644 (file)
@@ -805,42 +805,28 @@ AC_CACHE_CHECK([whether clock_boottime and clock_monotonic are supported],
 
 
 # For the turbostat plugin
-have_asm_msrindex_h="no"
-AC_CHECK_HEADERS(asm/msr-index.h, [have_asm_msrindex_h="yes"])
-
-if test "x$have_asm_msrindex_h" = "xyes"
-then
-  AC_CACHE_CHECK([whether asm/msr-index.h has MSR_PKG_C10_RESIDENCY],
-                 [c_cv_have_usable_asm_msrindex_h],
-                 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
-[[[
-#include<asm/msr-index.h>
-]]],
-[[[
-int y = MSR_PKG_C10_RESIDENCY;
-return(y);
-]]]
-  )],
-                 [c_cv_have_usable_asm_msrindex_h="yes"],
-                 [c_cv_have_usable_asm_msrindex_h="no"],
-                                  )
-                 )
-fi
-
-have_cpuid_h="no"
-AC_CHECK_HEADERS(cpuid.h, [have_cpuid_h="yes"])
+AC_CHECK_HEADERS([cpuid.h],
+  [have_cpuid_h="yes"],
+  [have_cpuid_h="no (cpuid.h not found)"]
+)
 
 have_capability="yes"
 AC_CHECK_HEADERS(sys/capability.h,
                  [have_capability="yes"],
                  [have_capability="no (<sys/capability.h> not found)"])
 if test "x$have_capability" = "xyes"; then
-AC_CHECK_LIB(cap, cap_get_bound,
+AC_CHECK_LIB(cap, cap_get_proc,
+                 [have_capability="yes"],
+                 [have_capability="no (cap_get_proc() not found)"])
+fi
+if test "x$have_capability" = "xyes"; then
+AC_CHECK_DECL([CAP_IS_SUPPORTED],
                  [have_capability="yes"],
-                 [have_capability="no (cap_get_bound() not found)"])
+                 [have_capability="no (CAP_IS_SUPPORTED not found)"],
+                 [[#include <sys/capability.h>]])
 fi
 if test "x$have_capability" = "xyes"; then
-  AC_DEFINE(HAVE_CAPABILITY, 1, [Define to 1 if you have cap_get_bound() (-lcap).])
+  AC_DEFINE(HAVE_CAPABILITY, 1, [Define to 1 if you have cap_get_proc() (-lcap).])
 fi
 AM_CONDITIONAL(BUILD_WITH_CAPABILITY, test "x$have_capability" = "xyes")
 
@@ -1062,6 +1048,92 @@ then
 fi
 # }}} Check for strptime
 
+# Check for timegm {{{
+
+# These checks need -Werror because implicit function declarations are only a
+# warning ...
+SAVE_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -Werror"
+
+AC_CACHE_CHECK([for timegm],
+  [c_cv_have_timegm],
+  AC_LINK_IFELSE(
+    [AC_LANG_PROGRAM(
+[[[
+#if STRPTIME_NEEDS_STANDARDS
+# ifndef _ISOC99_SOURCE
+#  define _ISOC99_SOURCE 1
+# endif
+# ifndef _POSIX_C_SOURCE
+#  define _POSIX_C_SOURCE 200112L
+# endif
+# ifndef _XOPEN_SOURCE
+#  define _XOPEN_SOURCE 500
+# endif
+#endif
+#include <time.h>
+]]],
+[[[
+ time_t t = timegm(&(struct tm){0});
+ if (t == ((time_t) -1)) {
+   return 1;
+ }
+]]]
+    )],
+    [c_cv_have_timegm="yes"],
+    [c_cv_have_timegm="no"]
+  )
+)
+
+if test "x$c_cv_have_timegm" != "xyes"
+then
+  AC_CACHE_CHECK([for timegm with _BSD_SOURCE],
+    [c_cv_have_timegm_bsd],
+    AC_LINK_IFELSE(
+      [AC_LANG_PROGRAM(
+[[[
+#if STRPTIME_NEEDS_STANDARDS
+# ifndef _ISOC99_SOURCE
+#  define _ISOC99_SOURCE 1
+# endif
+# ifndef _POSIX_C_SOURCE
+#  define _POSIX_C_SOURCE 200112L
+# endif
+# ifndef _XOPEN_SOURCE
+#  define _XOPEN_SOURCE 500
+# endif
+#endif
+#ifndef _BSD_SOURCE
+# define _BSD_SOURCE 1
+#endif
+#include <time.h>
+]]],
+[[[
+ time_t t = timegm(&(struct tm){0});
+ if (t == ((time_t) -1)) {
+   return 1;
+ }
+]]]
+      )],
+      [c_cv_have_timegm_bsd="yes"
+       c_cv_have_timegm="yes"],
+      [c_cv_have_timegm_bsd="no"]
+    )
+  )
+fi
+
+if test "x$c_cv_have_timegm" = "xyes"
+then
+  AC_DEFINE(HAVE_TIMEGM, 1, [Define if the timegm(3) function is available.])
+  if test "x$c_cv_have_timegm_bsd" = "xyes"
+  then
+    AC_DEFINE(TIMEGM_NEEDS_BSD, 1, [Set to true if timegm is only exported in BSD mode.])
+  fi
+fi
+
+CFLAGS="$SAVE_CFLAGS"
+# }}} Check for timegm
+
 AC_CHECK_FUNCS(swapctl, [have_swapctl="yes"], [have_swapctl="no"])
 if test "x$have_swapctl" = "xyes"; then
         AC_CACHE_CHECK([whether swapctl takes two arguments],
@@ -2607,34 +2679,69 @@ fi
 
 # --with-libdpdk {{{
 AC_ARG_VAR([LIBDPDK_CPPFLAGS], [Preprocessor flags for libdpdk])
+AC_ARG_VAR([LIBDPDK_CFLAGS], [Compiler flags for libdpdk])
 AC_ARG_VAR([LIBDPDK_LDFLAGS], [Linker flags for libdpdk])
+AC_ARG_VAR([LIBDPDK_LIBS], [Libraries to link for libdpdk])
 
-AC_ARG_WITH([libdpdk], [AS_HELP_STRING([--without-libdpdk], [Disable libdpdk.])])
+AC_ARG_WITH([libdpdk],
+  [AS_HELP_STRING([--without-libdpdk], [Disable libdpdk.])],
+  [with_libdpdk="$withval"],
+  [with_libdpdk="yes"]
+)
 
-if test "x$with_libdpdk" != "xno"
-then
-       if test "x$LIBDPDK_CPPFLAGS" = "x"
-       then
-               LIBDPDK_CPPFLAGS="-I/usr/include/dpdk"
-       fi
-       SAVE_CPPFLAGS="$CPPFLAGS"
-       CPPFLAGS="$LIBDPDK_CPPFLAGS $CPPFLAGS"
-       AC_CHECK_HEADERS([rte_config.h],
-               [with_libdpdk="yes"],
-               [with_libdpdk="no (rte_config.h not found)"]
-       )
-       CPPFLAGS="$SAVE_CPPFLAGS"
+if test "x$with_libdpdk" != "xno"; then
+  PKG_CHECK_MODULES([DPDK], [libdpdk], [],
+                   [AC_MSG_NOTICE([no DPDK pkg-config, using defaults])])
+  if test "x$LIBDPDK_CPPFLAGS" = "x"; then
+    LIBDPDK_CPPFLAGS="-I/usr/include/dpdk"
+  fi
+  if test "x$LIBDPDK_CFLAGS" = "x"; then
+      LIBDPDK_CFLAGS="$DPDK_CFLAGS"
+      LIBDPDK_CPPFLAGS="$LIBDPDK_CPPFLAGS $DPDK_CFLAGS"
+  fi
+  if test "x$LIBDPDK_LIBS" = "x"; then
+      if test "x$DPDK_LIBS" != "x"; then
+          LIBDPDK_LIBS="$DPDK_LIBS"
+      else
+          LIBDPDK_LIBS="-ldpdk"
+      fi
+  fi
+  SAVE_CPPFLAGS="$CPPFLAGS"
+  CPPFLAGS="$LIBDPDK_CPPFLAGS $CPPFLAGS"
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$LIBDPDK_CFLAGS $CFLAGS"
+  AC_CHECK_HEADERS([rte_config.h],
+    [
+      with_libdpdk="yes"
+      AC_PREPROC_IFELSE(
+        [
+          AC_LANG_SOURCE(
+            [[
+              #include <rte_version.h>
+              #if RTE_VERSION < RTE_VERSION_NUM(16,7,0,0)
+              #error "required DPDK >= 16.07"
+              #endif
+            ]]
+          )
+        ],
+        [dpdk_keepalive="yes"],
+        [dpdk_keepalive="no (DPDK version < 16.07)"]
+      )
+    ],
+    [with_libdpdk="no (rte_config.h not found)"]
+  )
+  CPPFLAGS="$SAVE_CPPFLAGS"
+  CFLAGS="$SAVE_CFLAGS"
 fi
 
-if test "x$with_libdpdk" = "xyes"
-then
-       SAVE_LDFLAGS="$LDFLAGS"
-       LDFLAGS="$LIBDPDK_LDFLAGS $LDFLAGS"
-       AC_CHECK_LIB([dpdk], [rte_eal_init],
-               [with_libdpdk="yes"],
-               [with_libdpdk="no (symbol 'rte_eal_init' not found)"]
-       )
-       LDFLAGS="$SAVE_LDFLAGS"
+if test "x$with_libdpdk" = "xyes"; then
+  SAVE_LDFLAGS="$LDFLAGS"
+  LDFLAGS="$LIBDPDK_LDFLAGS $LDFLAGS"
+  AC_CHECK_LIB([dpdk], [rte_eal_init],
+    [with_libdpdk="yes"],
+    [with_libdpdk="no (symbol 'rte_eal_init' not found)"]
+  )
+  LDFLAGS="$SAVE_LDFLAGS"
 fi
 
 # }}}
@@ -4235,6 +4342,16 @@ then
 fi
 if test "x$with_libpqos" = "xyes"
 then
+  SAVE_CPPFLAGS="$CPPFLAGS"
+  CPPFLAGS="$CPPFLAGS $with_libpqos_cppflags"
+  AC_RUN_IFELSE([AC_LANG_PROGRAM(
+    [[#include <pqos.h>]],
+    [[return !(PQOS_VERSION >= 106)]])],
+    [with_libpqos="yes"], [with_libpqos="no (pqos library version 1.06 or higher is required)"])
+  CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libpqos" = "xyes"
+then
        BUILD_WITH_LIBPQOS_CPPFLAGS="$with_libpqos_cppflags"
        BUILD_WITH_LIBPQOS_LDFLAGS="$with_libpqos_ldflags"
        BUILD_WITH_LIBPQOS_LIBS="-lpqos"
@@ -6006,8 +6123,7 @@ then
        then
                plugin_ipvs="yes"
        fi
-       if test "x$c_cv_have_usable_asm_msrindex_h" = "xyes" && test "x$have_cpuid_h" = "xyes"
-       then
+       if test "x$have_cpuid_h" = "xyes"; then
                plugin_turbostat="yes"
        fi
        
index 4fc76e1..9f93f41 100644 (file)
 %define with_write_log 0%{!?_without_write_log:1}
 %define with_write_prometheus 0%{!?_without_write_prometheus:1}
 %define with_write_redis 0%{!?_without_write_redis:1}
+%define with_write_riemann 0%{!?_without_write_riemann:1}
 %define with_write_sensu 0%{!?_without_write_sensu:1}
 %define with_write_tsdb 0%{!?_without_write_tsdb:1}
 %define with_xmms 0%{!?_without_xmms:0%{?_has_xmms}}
 %define with_write_kafka 0%{!?_without_write_kafka:0}
 # plugin write_mongodb disabled, requires libmongoc
 %define with_write_mongodb 0%{!?_without_write_mongodb:0}
-# plugin write_riemann disabled, requires a new enough riemann_c_client
-%define with_write_riemann 0%{!?_without_write_riemann:0}
 # plugin xencpu disabled, requires xen-devel from non-default repo
 %define with_xencpu 0%{!?_without_xencpu:0}
 # plugin zone disabled, requires Solaris
 %define with_turbostat 0
 %define with_write_prometheus 0
 %define with_write_redis 0
+%define with_write_riemann 0
 %endif
 
 # Plugins not buildable on RHEL < 7
 %define with_redis 0
 %define with_rrdcached 0
 %define with_write_redis 0
+%define with_write_riemann 0
 %define with_xmms 0
 %endif
 
 Summary:       Statistics collection and monitoring daemon
 Name:          collectd
-Version:       5.7.0
-Release:       2%{?dist}
+Version:       5.7.1
+Release:       3%{?dist}
 URL:           https://collectd.org
 Source:                https://collectd.org/files/%{name}-%{version}.tar.bz2
 License:       GPLv2
@@ -246,6 +247,7 @@ BuildRequires:      libgcrypt-devel, kernel-headers, libtool-ltdl-devel, libcap-devel
 Vendor:                collectd development team <collectd@verplant.org>
 
 %if 0%{?fedora} || 0%{?rhel} >= 7
+BuildRequires:         xfsprogs-devel
 %{?systemd_requires}
 BuildRequires:         systemd
 %else
@@ -499,8 +501,8 @@ the byte- and packet-counters of selected rules and submit them to collectd.
 Summary:       Java plugin for collectd
 Group:         System Environment/Daemons
 Requires:      %{name}%{?_isa} = %{version}-%{release}
-BuildRequires: java-devel, jpackage-utils
-Requires:      java, jpackage-utils
+BuildRequires: java-devel >= 1.6, jpackage-utils >= 1.6
+Requires:      java >= 1.6, jpackage-utils >= 1.6
 %description java
 This plugin for collectd allows plugins to be written in Java and executed
 in an embedded JVM.
@@ -858,7 +860,7 @@ The Write Redis plugin stores values in Redis, a “data structures server”.
 Summary:       riemann plugin for collectd
 Group:         System Environment/Daemons
 Requires:      %{name}%{?_isa} = %{version}-%{release}
-BuildRequires: protobuf-c-devel
+BuildRequires: riemann-c-client-devel >= 1.6
 %description write_riemann
 The riemann plugin submits values to Riemann, an event stream processor.
 %endif
@@ -2587,6 +2589,16 @@ fi
 %doc contrib/
 
 %changelog
+* Sun Mar 05 2017 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.7.1-2
+- Don't enable XFS support on RHEL6, it is missing for i386
+
+* Wed Feb 22 2017 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.7.1-2
+- Enable XFS support in df plugin
+- Fix bogus date in changelog
+
+* Sun Jan 01 2017 Marc Fournier <marc.fournier@camptocamp.com> - 5.7.1-1
+- New upstream version
+
 * Tue Nov 29 2016 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.7.0-2
 - Disable redis plugin on RHEL 6, hiredis has been retired from EPEL6
 
index d0f1bde..a3b689a 100644 (file)
@@ -20,6 +20,7 @@ ProtectHome=true
 #   exec            CAP_SETUID CAP_SETGID
 #   iptables        CAP_NET_ADMIN
 #   ping            CAP_NET_RAW
+#   smart           CAP_SYS_RAWIO
 #   turbostat       CAP_SYS_RAWIO
 #
 # Example, if you use the iptables plugin alongside the dns or ping plugin:
@@ -28,8 +29,6 @@ ProtectHome=true
 # By default, drop all capabilities:
 CapabilityBoundingSet=
 
-NoNewPrivileges=true
-
 # Tell systemd it will receive a notification from collectd over it's control
 # socket once the daemon is ready. See systemd.service(5) for more details.
 Type=notify
index bd6d901..e3627c3 100644 (file)
@@ -273,6 +273,7 @@ if BUILD_PLUGIN_CHRONY
 pkglib_LTLIBRARIES += chrony.la
 chrony_la_SOURCES = chrony.c
 chrony_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+chrony_la_LIBADD = -lm
 endif
 
 if BUILD_PLUGIN_CONNTRACK
@@ -419,8 +420,9 @@ if BUILD_PLUGIN_DPDKSTAT
 pkglib_LTLIBRARIES += dpdkstat.la
 dpdkstat_la_SOURCES = dpdkstat.c
 dpdkstat_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBDPDK_CPPFLAGS)
+dpdkstat_la_CFLAGS = $(AM_CFLAGS) $(LIBDPDK_CFLAGS)
 dpdkstat_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBDPDK_LDFLAGS)
-dpdkstat_la_LIBADD = -ldpdk
+dpdkstat_la_LIBADD = $(LIBDPDK_LIBS)
 endif
 
 if BUILD_PLUGIN_DRBD
@@ -444,7 +446,8 @@ endif
 if BUILD_PLUGIN_EXEC
 pkglib_LTLIBRARIES += exec.la
 exec_la_SOURCES = exec.c
-exec_la_LDFLAGS = $(PLUGIN_LDFLAGS) libcmds.la
+exec_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+exec_la_LIBADD = libcmds.la
 endif
 
 if BUILD_PLUGIN_ETHSTAT
@@ -823,7 +826,7 @@ if BUILD_PLUGIN_NOTIFY_EMAIL
 pkglib_LTLIBRARIES += notify_email.la
 notify_email_la_SOURCES = notify_email.c
 notify_email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-notify_email_la_LIBADD = -lesmtp -lssl -lcrypto
+notify_email_la_LIBADD = -lesmtp
 endif
 
 if BUILD_PLUGIN_NOTIFY_NAGIOS
@@ -1210,14 +1213,17 @@ endif
 
 if BUILD_PLUGIN_TURBOSTAT
 pkglib_LTLIBRARIES += turbostat.la
-turbostat_la_SOURCES = turbostat.c
+turbostat_la_SOURCES = \
+       turbostat.c \
+       msr-index.h
 turbostat_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 endif
 
 if BUILD_PLUGIN_UNIXSOCK
 pkglib_LTLIBRARIES += unixsock.la
 unixsock_la_SOURCES = unixsock.c
-unixsock_la_LDFLAGS = $(PLUGIN_LDFLAGS) libcmds.la
+unixsock_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+unixsock_la_LIBADD =  libcmds.la
 endif
 
 if BUILD_PLUGIN_UPTIME
index 4e20d0c..272a04f 100644 (file)
@@ -405,9 +405,10 @@ static int agg_instance_read(agg_instance_t *inst, cdtime_t t) /* {{{ */
     READ_FUNC(average, (inst->sum / ((gauge_t)inst->num)));
     READ_FUNC(min, inst->min);
     READ_FUNC(max, inst->max);
-    READ_FUNC(stddev, sqrt((((gauge_t)inst->num) * inst->squares_sum) -
-                           (inst->sum * inst->sum)) /
-                          ((gauge_t)inst->num));
+    READ_FUNC(stddev,
+              sqrt((((gauge_t)inst->num) * inst->squares_sum) -
+                   (inst->sum * inst->sum)) /
+                  ((gauge_t)inst->num));
   }
 
   /* Reset internal state. */
@@ -506,11 +507,7 @@ static int agg_config_handle_group_by(oconfig_item_t const *ci, /* {{{ */
 
 static int agg_config_aggregation(oconfig_item_t *ci) /* {{{ */
 {
-  aggregation_t *agg;
-  _Bool is_valid;
-  int status;
-
-  agg = calloc(1, sizeof(*agg));
+  aggregation_t *agg = calloc(1, sizeof(*agg));
   if (agg == NULL) {
     ERROR("aggregation plugin: calloc failed.");
     return (-1);
@@ -525,49 +522,55 @@ static int agg_config_aggregation(oconfig_item_t *ci) /* {{{ */
 
   for (int i = 0; i < ci->children_num; i++) {
     oconfig_item_t *child = ci->children + i;
+    int status = 0;
 
     if (strcasecmp("Host", child->key) == 0)
-      cf_util_get_string_buffer(child, agg->ident.host,
-                                sizeof(agg->ident.host));
+      status = cf_util_get_string_buffer(child, agg->ident.host,
+                                         sizeof(agg->ident.host));
     else if (strcasecmp("Plugin", child->key) == 0)
-      cf_util_get_string_buffer(child, agg->ident.plugin,
-                                sizeof(agg->ident.plugin));
+      status = cf_util_get_string_buffer(child, agg->ident.plugin,
+                                         sizeof(agg->ident.plugin));
     else if (strcasecmp("PluginInstance", child->key) == 0)
-      cf_util_get_string_buffer(child, agg->ident.plugin_instance,
-                                sizeof(agg->ident.plugin_instance));
+      status = cf_util_get_string_buffer(child, agg->ident.plugin_instance,
+                                         sizeof(agg->ident.plugin_instance));
     else if (strcasecmp("Type", child->key) == 0)
-      cf_util_get_string_buffer(child, agg->ident.type,
-                                sizeof(agg->ident.type));
+      status = cf_util_get_string_buffer(child, agg->ident.type,
+                                         sizeof(agg->ident.type));
     else if (strcasecmp("TypeInstance", child->key) == 0)
-      cf_util_get_string_buffer(child, agg->ident.type_instance,
-                                sizeof(agg->ident.type_instance));
+      status = cf_util_get_string_buffer(child, agg->ident.type_instance,
+                                         sizeof(agg->ident.type_instance));
     else if (strcasecmp("SetHost", child->key) == 0)
-      cf_util_get_string(child, &agg->set_host);
+      status = cf_util_get_string(child, &agg->set_host);
     else if (strcasecmp("SetPlugin", child->key) == 0)
-      cf_util_get_string(child, &agg->set_plugin);
+      status = cf_util_get_string(child, &agg->set_plugin);
     else if (strcasecmp("SetPluginInstance", child->key) == 0)
-      cf_util_get_string(child, &agg->set_plugin_instance);
+      status = cf_util_get_string(child, &agg->set_plugin_instance);
     else if (strcasecmp("SetTypeInstance", child->key) == 0)
-      cf_util_get_string(child, &agg->set_type_instance);
+      status = cf_util_get_string(child, &agg->set_type_instance);
     else if (strcasecmp("GroupBy", child->key) == 0)
-      agg_config_handle_group_by(child, agg);
+      status = agg_config_handle_group_by(child, agg);
     else if (strcasecmp("CalculateNum", child->key) == 0)
-      cf_util_get_boolean(child, &agg->calc_num);
+      status = cf_util_get_boolean(child, &agg->calc_num);
     else if (strcasecmp("CalculateSum", child->key) == 0)
-      cf_util_get_boolean(child, &agg->calc_sum);
+      status = cf_util_get_boolean(child, &agg->calc_sum);
     else if (strcasecmp("CalculateAverage", child->key) == 0)
-      cf_util_get_boolean(child, &agg->calc_average);
+      status = cf_util_get_boolean(child, &agg->calc_average);
     else if (strcasecmp("CalculateMinimum", child->key) == 0)
-      cf_util_get_boolean(child, &agg->calc_min);
+      status = cf_util_get_boolean(child, &agg->calc_min);
     else if (strcasecmp("CalculateMaximum", child->key) == 0)
-      cf_util_get_boolean(child, &agg->calc_max);
+      status = cf_util_get_boolean(child, &agg->calc_max);
     else if (strcasecmp("CalculateStddev", child->key) == 0)
-      cf_util_get_boolean(child, &agg->calc_stddev);
+      status = cf_util_get_boolean(child, &agg->calc_stddev);
     else
       WARNING("aggregation plugin: The \"%s\" key is not allowed inside "
               "<Aggregation /> blocks and will be ignored.",
               child->key);
-  }
+
+    if (status != 0) {
+      sfree(agg);
+      return status;
+    }
+  } /* for (int i = 0; i < ci->children_num; i++) */
 
   if (agg_is_regex(agg->ident.host))
     agg->regex_fields |= LU_GROUP_BY_HOST;
@@ -579,7 +582,7 @@ static int agg_config_aggregation(oconfig_item_t *ci) /* {{{ */
     agg->regex_fields |= LU_GROUP_BY_TYPE_INSTANCE;
 
   /* Sanity checking */
-  is_valid = 1;
+  _Bool is_valid = 1;
   if (strcmp("/.*/", agg->ident.type) == 0) /* {{{ */
   {
     ERROR("aggregation plugin: It appears you did not specify the required "
@@ -633,13 +636,12 @@ static int agg_config_aggregation(oconfig_item_t *ci) /* {{{ */
     is_valid = 0;
   } /* }}} */
 
-  if (!is_valid) /* {{{ */
-  {
+  if (!is_valid) { /* {{{ */
     sfree(agg);
     return (-1);
   } /* }}} */
 
-  status = lookup_add(lookup, &agg->ident, agg->group_by, agg);
+  int status = lookup_add(lookup, &agg->ident, agg->group_by, agg);
   if (status != 0) {
     ERROR("aggregation plugin: lookup_add failed with status %i.", status);
     sfree(agg);
index cd07023..c54a1e0 100644 (file)
@@ -901,7 +901,7 @@ static int camqp_config_connection(oconfig_item_t *ci, /* {{{ */
       status = cf_util_get_string(child, &conf->password);
     else if (strcasecmp("Exchange", child->key) == 0)
       status = cf_util_get_string(child, &conf->exchange);
-    else if ((strcasecmp("ExchangeType", child->key) == 0) && !publish)
+    else if (strcasecmp("ExchangeType", child->key) == 0)
       status = cf_util_get_string(child, &conf->exchange_type);
     else if ((strcasecmp("Queue", child->key) == 0) && !publish)
       status = cf_util_get_string(child, &conf->queue);
index eaef61b..29c36cc 100644 (file)
@@ -328,7 +328,6 @@ static int init_host(apache_t *st) /* {{{ */
 #endif
   }
 
-  curl_easy_setopt(st->curl, CURLOPT_URL, st->url);
   curl_easy_setopt(st->curl, CURLOPT_FOLLOWLOCATION, 1L);
   curl_easy_setopt(st->curl, CURLOPT_MAXREDIRS, 50L);
 
@@ -510,6 +509,9 @@ static int apache_read_host(user_data_t *user_data) /* {{{ */
   assert(st->curl != NULL);
 
   st->apache_buffer_fill = 0;
+
+  curl_easy_setopt(st->curl, CURLOPT_URL, st->url);
+
   if (curl_easy_perform(st->curl) != CURLE_OK) {
     ERROR("apache: curl_easy_perform failed: %s", st->apache_curl_error);
     return (-1);
index 840fe8b..74cef33 100644 (file)
@@ -511,7 +511,6 @@ static int ascent_init(void) /* {{{ */
 #endif
   }
 
-  curl_easy_setopt(curl, CURLOPT_URL, url);
   curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
   curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
 
@@ -554,6 +553,9 @@ static int ascent_read(void) /* {{{ */
   }
 
   ascent_buffer_fill = 0;
+
+  curl_easy_setopt(curl, CURLOPT_URL, url);
+
   if (curl_easy_perform(curl) != CURLE_OK) {
     ERROR("ascent plugin: curl_easy_perform failed: %s", ascent_curl_error);
     return (-1);
index 5c02fee..78e96b2 100644 (file)
@@ -350,10 +350,12 @@ static int sysfs_file_to_buffer(char const *dir, /* {{{ */
   ssnprintf(filename, sizeof(filename), "%s/%s/%s", dir, power_supply,
             basename);
 
-  status = (int)read_file_contents(filename, buffer, buffer_size);
+  status = (int)read_file_contents(filename, buffer, buffer_size - 1);
   if (status < 0)
     return status;
 
+  buffer[status] = '\0';
+
   strstripnewline(buffer);
   return 0;
 } /* }}} int sysfs_file_to_buffer */
@@ -364,7 +366,7 @@ static int sysfs_file_to_gauge(char const *dir, /* {{{ */
                                char const *power_supply, char const *basename,
                                gauge_t *ret_value) {
   int status;
-  char buffer[32] = "";
+  char buffer[32];
 
   status =
       sysfs_file_to_buffer(dir, power_supply, basename, buffer, sizeof(buffer));
index 9bb662f..8a3148c 100644 (file)
 #endif
 #endif /* STRPTIME_NEEDS_STANDARDS */
 
+#if TIMEGM_NEEDS_BSD
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE 1
+#endif
+#endif /* TIMEGM_NEEDS_BSD */
+
 #include "collectd.h"
 
 #include "common.h"
 #include "plugin.h"
 
+#include <time.h>
+
 /* Some versions of libcurl don't include this themselves and then don't have
  * fd_set available. */
 #if HAVE_SYS_SELECT_H
@@ -429,7 +437,28 @@ static int bind_xml_read_timestamp(const char *xpath_expression, /* {{{ */
     return (-1);
   }
 
-  *ret_value = mktime(&tm);
+#if HAVE_TIMEGM
+  time_t t = timegm(&tm);
+  if (t == ((time_t)-1)) {
+    char errbuf[1024];
+    ERROR("bind plugin: timegm() failed: %s",
+          sstrerror(errno, errbuf, sizeof(errbuf)));
+    return (-1);
+  }
+  *ret_value = t;
+#else
+  time_t t = mktime(&tm);
+  if (t == ((time_t)-1)) {
+    char errbuf[1024];
+    ERROR("bind plugin: mktime() failed: %s",
+          sstrerror(errno, errbuf, sizeof(errbuf)));
+    return (-1);
+  }
+  /* mktime assumes that tm is local time. Luckily, it also sets timezone to
+   * the offset used for the conversion, and we undo the conversion to convert
+   * back to UTC. */
+  *ret_value = t - timezone;
+#endif
 
   xmlXPathFreeObject(xpathObj);
   return (0);
@@ -493,8 +522,10 @@ static int bind_parse_generic_name_value(const char *xpath_expression, /* {{{ */
         status = bind_xml_read_gauge(doc, counter, &value.gauge);
       else
         status = bind_xml_read_derive(doc, counter, &value.derive);
-      if (status != 0)
+      if (status != 0) {
+        xmlFree(name);
         continue;
+      }
 
       status = (*list_callback)(name, value, current_time, user_data);
       if (status == 0)
@@ -626,12 +657,16 @@ static int bind_parse_generic_name_attr_value_list(
         status = bind_xml_read_gauge(doc, child, &value.gauge);
       else
         status = bind_xml_read_derive(doc, child, &value.derive);
-      if (status != 0)
+      if (status != 0) {
+        xmlFree(attr_name);
         continue;
+      }
 
       status = (*list_callback)(attr_name, value, current_time, user_data);
       if (status == 0)
         num_entries++;
+
+      xmlFree(attr_name);
     }
   }
 
@@ -1563,7 +1598,6 @@ static int bind_init(void) /* {{{ */
   curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, bind_curl_callback);
   curl_easy_setopt(curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
   curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, bind_curl_error);
-  curl_easy_setopt(curl, CURLOPT_URL, (url != NULL) ? url : BIND_DEFAULT_URL);
   curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
   curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
 #ifdef HAVE_CURLOPT_TIMEOUT_MS
@@ -1585,6 +1619,9 @@ static int bind_read(void) /* {{{ */
   }
 
   bind_buffer_fill = 0;
+
+  curl_easy_setopt(curl, CURLOPT_URL, (url != NULL) ? url : BIND_DEFAULT_URL);
+
   if (curl_easy_perform(curl) != CURLE_OK) {
     ERROR("bind plugin: curl_easy_perform failed: %s", bind_curl_error);
     return (-1);
index 16b26af..ada1ff5 100644 (file)
@@ -475,7 +475,7 @@ Methods defined here:
 
 =over 4
 
-=item B<dispatch>([type][, values][, plugin_instance][, type_instance][, plugin][, host][, time][, interval]) -> None.  Dispatch a value list.
+=item B<dispatch>([type][, message][, plugin_instance][, type_instance][, plugin][, host][, time][, severity]) -> None.  Dispatch a notification.
 
 Dispatch this instance to the collectd process. The object has members for each
 of the possible arguments for this method. For a detailed explanation of these
index e5b9643..c65191d 100644 (file)
 #      <Database bar>
 #              Interval 60
 #              Service "service_name"
-#              Query backend # predefined
+#              Query backends # predefined
 #              Query rt36_tickets
 #      </Database>
 #      <Database qux>
index 11cfaeb..3ab264a 100644 (file)
@@ -338,7 +338,7 @@ is enabled by default.
 =item B<PostCacheChain> I<ChainName>
 
 Configure the name of the "pre-cache chain" and the "post-cache chain". Please
-see L<FILTER CONFIGURATION> below on information on chains and how these
+see L</"FILTER CONFIGURATION"> below on information on chains and how these
 setting change the daemon's behavior.
 
 =back
@@ -1372,6 +1372,8 @@ Select I<cgroup> based on the name. Whether only matching I<cgroups> are
 collected or if they are ignored is controlled by the B<IgnoreSelected> option;
 see below.
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelected> B<true>|B<false>
 
 Invert the selection: If set to true, all cgroups I<except> the ones that
@@ -2268,14 +2270,20 @@ values. Defaults to the global hostname setting.
 
 Select partitions based on the devicename.
 
+See F</"IGNORELISTS"> for details.
+
 =item B<MountPoint> I<Directory>
 
 Select partitions based on the mountpoint.
 
+See F</"IGNORELISTS"> for details.
+
 =item B<FSType> I<FSType>
 
 Select partitions based on the filesystem type.
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelected> B<true>|B<false>
 
 Invert the selection: If set to true, all partitions B<except> the ones that
@@ -2337,6 +2345,8 @@ is interpreted as a regular expression. Examples:
   Disk "sdd"
   Disk "/hda[34]/"
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelected> B<true>|B<false>
 
 Sets whether selected disks, i.E<nbsp>e. the ones matches by any of the B<Disk>
@@ -2998,6 +3008,8 @@ than 1 sec.
 Select this interface. By default these interfaces will then be collected. For
 a more detailed description see B<IgnoreSelected> below.
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelected> I<true>|I<false>
 
 If no configuration if given, the B<interface>-plugin will collect data from
@@ -3059,6 +3071,8 @@ This option is only available on Solaris.
 
 Selects sensors to collect or to ignore, depending on B<IgnoreSelected>.
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelected> I<true>|I<false>
 
 If no configuration if given, the B<ipmi> plugin will collect data from all
@@ -3115,6 +3129,8 @@ comment or the number.
 Select this irq. By default these irqs will then be collected. For a more
 detailed description see B<IgnoreSelected> below.
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelected> I<true>|I<false>
 
 If no configuration if given, the B<irq>-plugin will collect data from all
@@ -3338,6 +3354,8 @@ Select md devices based on device name. The I<device name> is the basename of
 the device, i.e. the name of the block device without the leading C</dev/>.
 See B<IgnoreSelected> for more details.
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelected> B<true>|B<false>
 
 Invert device selection: If set to B<true>, all md devices B<except> those
@@ -4501,6 +4519,8 @@ regular and exact matching are case sensitive.
 If no volume was specified at all for either of the three options, that data
 will be collected for all available volumes.
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelectedIO> B<true>|B<false>
 
 =item B<IgnoreSelectedOps> B<true>|B<false>
@@ -4686,6 +4706,8 @@ Here are some examples to help you understand the above text more easily:
     Filter "ppp0" "u32-1:0"
   </Plugin>
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelected>
 
 The behavior is the same as with all other similar plugins: If nothing is
@@ -5208,6 +5230,8 @@ C</10.F10FCA000800/temperature>). B<IgnoreSelected> is not used.
 As there can be multiple devices on the bus you can list multiple sensor (use
 multiple B<Sensor> elements).
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelected> I<true>|I<false>
 
 If no configuration is given, the B<onewire> plugin will collect data from all
@@ -5532,10 +5556,10 @@ multiple hosts.
 =item B<Interval> I<Seconds>
 
 Sets the interval in which to send ICMP echo packets to the configured hosts.
-This is B<not> the interval in which statistics are queries from the plugin but
-the interval in which the hosts are "pinged". Therefore, the setting here
-should be smaller than or equal to the global B<Interval> setting. Fractional
-times, such as "1.24" are allowed.
+This is B<not> the interval in which metrics are read from the plugin but the
+interval in which the hosts are "pinged". Therefore, the setting here should be
+smaller than or equal to the global B<Interval> setting. Fractional times, such
+as "1.24" are allowed.
 
 Default: B<1.0>
 
@@ -5652,7 +5676,7 @@ L<http://www.postgresql.org/docs/manuals/>.
     <Database bar>
       Interval 300
       Service "service_name"
-      Query backend # predefined
+      Query backends # predefined
       Query rt36_tickets
     </Database>
 
@@ -6267,6 +6291,8 @@ Whether only matched values are selected or all matched values are ignored
 depends on the B<IgnoreSelected>. By default, only matched values are selected.
 If no value is configured at all, all values will be selected.
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelected> B<true>|B<false>
 
 If set to B<true>, inverts the selection made by B<Value>, i.E<nbsp>e. all
@@ -6620,14 +6646,20 @@ one (exclusive).
 
 When the C<rrdtool> plugin uses a cache (by setting B<CacheTimeout>, see below)
 it writes all values for a certain RRD-file if the oldest value is older than
-(or equal to) the number of seconds specified. If some RRD-file is not updated
+(or equal to) the number of seconds specified by B<CacheTimeout>.
+That check happens on new values arriwal. If some RRD-file is not updated
 anymore for some reason (the computer was shut down, the network is broken,
-etc.) some values may still be in the cache. If B<CacheFlush> is set, then the
-entire cache is searched for entries older than B<CacheTimeout> seconds and
-written to disk every I<Seconds> seconds. Since this is kind of expensive and
-does nothing under normal circumstances, this value should not be too small.
-900 seconds might be a good value, though setting this to 7200 seconds doesn't
-normally do much harm either.
+etc.) some values may still be in the cache. If B<CacheFlush> is set, then
+every I<Seconds> seconds the entire cache is searched for entries older than
+B<CacheTimeout> + B<RandomTimeout> seconds. The entries found are written to
+disk. Since scanning the entire cache is kind of expensive and does nothing
+under normal circumstances, this value should not be too small. 900 seconds
+might be a good value, though setting this to 7200 seconds doesn't normally
+do much harm either.
+
+Defaults to 10x B<CacheTimeout>.
+B<CacheFlush> must be larger than or equal to B<CacheTimeout>, otherwise the
+above default is used.
 
 =item B<CacheTimeout> I<Seconds>
 
@@ -6695,6 +6727,8 @@ on the B<IgnoreSelected> below. For example, the option "B<Sensor>
 I<it8712-isa-0290/voltage-in1>" will cause collectd to gather data for the
 voltage sensor I<in1> of the I<it8712> on the isa bus at the address 0290.
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelected> I<true>|I<false>
 
 If no configuration if given, the B<sensors>-plugin will collect data from all
@@ -6804,6 +6838,8 @@ is interpreted as a regular expression. Examples:
   Disk "sdd"
   Disk "/hda[34]/"
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelected> B<true>|B<false>
 
 Sets whether selected disks, i.E<nbsp>e. the ones matches by any of the B<Disk>
@@ -6903,6 +6939,8 @@ Calculate and dispatch various values out of I<Timer> metrics received during
 an interval. If set to B<False>, the default, these values aren't calculated /
 dispatched.
 
+Please note what reported timer values less than 0.001 are ignored in all B<Timer*> reports.
+
 =back
 
 =head2 Plugin C<swap>
@@ -7491,6 +7529,8 @@ Selects the name of the thermal device that you want to collect or ignore,
 depending on the value of the B<IgnoreSelected> option. This option may be
 used multiple times to specify a list of devices.
 
+See F</"IGNORELISTS"> for details.
+
 =item B<IgnoreSelected> I<true>|I<false>
 
 Invert the selection: If set to true, all devices B<except> the ones that
@@ -9855,6 +9895,48 @@ be an FQDN.
    Target "write"
  </Chain>
 
+=head1 IGNORELISTS
+
+B<Ignorelists> are a generic framework to either ignore some metrics or report
+specific metircs only. Plugins usually provide one or more options to specify
+the items (mounts points, devices, ...) and the boolean option
+C<IgnoreSelected>.
+
+=over 4
+
+=item B<Select> I<String>
+
+Selects the item I<String>. This option often has a plugin specific name, e.g.
+B<Sensor> in the C<sensors> plugin. It is also plugin specific what this string
+is compared to. For example, the C<df> plugin's B<MountPoint> compares it to a
+mount point and the C<sensors> plugin's B<Sensor> compares it to a sensor name.
+
+By default, this option is doing a case-sensitive full-string match. The
+following config will match C<foo>, but not C<Foo>:
+
+  Select "foo"
+
+If I<String> starts and ends with C</> (a slash), the string is compiled as a
+I<regular expression>. For example, so match all item starting with C<foo>, use
+could use the following syntax:
+
+  Select "/^foo/"
+
+The regular expression is I<not> anchored, i.e. the following config will match
+C<foobar>, C<barfoo> and C<AfooZ>:
+
+  Select "/foo/"
+
+The B<Select> option may be repeated to select multiple items.
+
+=item B<IgnoreSelected> B<true>|B<false>
+
+If set to B<true>, matching metrics are I<ignored> and all other metrics are
+collected. If set to B<false>, matching metrics are I<collected> and all other
+metrics are ignored.
+
+=back
+
 =head1 SEE ALSO
 
 L<collectd(1)>,
index c6f0b60..26ca7e7 100644 (file)
@@ -347,7 +347,6 @@ static int cc_page_init_curl(web_page_t *wp) /* {{{ */
   curl_easy_setopt(wp->curl, CURLOPT_WRITEDATA, wp);
   curl_easy_setopt(wp->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
   curl_easy_setopt(wp->curl, CURLOPT_ERRORBUFFER, wp->curl_errbuf);
-  curl_easy_setopt(wp->curl, CURLOPT_URL, wp->url);
   curl_easy_setopt(wp->curl, CURLOPT_FOLLOWLOCATION, 1L);
   curl_easy_setopt(wp->curl, CURLOPT_MAXREDIRS, 50L);
 
@@ -611,6 +610,9 @@ static int cc_read_page(web_page_t *wp) /* {{{ */
     start = cdtime();
 
   wp->buffer_fill = 0;
+
+  curl_easy_setopt(wp->curl, CURLOPT_URL, wp->url);
+
   status = curl_easy_perform(wp->curl);
   if (status != CURLE_OK) {
     ERROR("curl plugin: curl_easy_perform failed with status %i: %s", status,
index aa1ae79..8f6382b 100644 (file)
@@ -171,23 +171,53 @@ static int cj_get_type(cj_key_t *key) {
   return ds->ds[0].type;
 }
 
-static int cj_cb_map_key(void *ctx, const unsigned char *val, yajl_len_t len);
+/* cj_load_key loads the configuration for "key" from the parent context and
+ * sets either .key or .tree in the current context. */
+static int cj_load_key(cj_t *db, char const *key) {
+  if (db == NULL || key == NULL || db->depth <= 0)
+    return EINVAL;
 
-static void cj_cb_inc_array_index(void *ctx, _Bool update_key) {
-  cj_t *db = (cj_t *)ctx;
+  sstrncpy(db->state[db->depth].name, key, sizeof(db->state[db->depth].name));
+
+  c_avl_tree_t *tree = db->state[db->depth - 1].tree;
+  if (tree == NULL) {
+    return 0;
+  }
+
+  /* the parent has a key, so the tree pointer is invalid. */
+  if (CJ_IS_KEY(db->state[db->depth - 1].key)) {
+    return 0;
+  }
+
+  void *value = NULL;
+  if (c_avl_get(tree, key, (void *)&value) == 0) {
+    if (CJ_IS_KEY((cj_key_t *)value)) {
+      db->state[db->depth].key = value;
+    } else {
+      db->state[db->depth].tree = value;
+    }
+  } else if (c_avl_get(tree, CJ_ANY, (void *)&value) == 0) {
+    if (CJ_IS_KEY((cj_key_t *)value)) {
+      db->state[db->depth].key = value;
+    } else {
+      db->state[db->depth].tree = value;
+    }
+  } else {
+    db->state[db->depth].key = NULL;
+  }
+
+  return 0;
+}
 
+static void cj_advance_array(cj_t *db) {
   if (!db->state[db->depth].in_array)
     return;
 
   db->state[db->depth].index++;
 
-  if (update_key) {
-    char name[DATA_MAX_NAME_LEN];
-
-    ssnprintf(name, sizeof(name), "%d", db->state[db->depth].index - 1);
-
-    cj_cb_map_key(ctx, (unsigned char *)name, (yajl_len_t)strlen(name));
-  }
+  char name[DATA_MAX_NAME_LEN];
+  ssnprintf(name, sizeof(name), "%d", db->state[db->depth].index);
+  cj_load_key(db, name);
 }
 
 /* yajl callbacks */
@@ -195,12 +225,12 @@ static void cj_cb_inc_array_index(void *ctx, _Bool update_key) {
 #define CJ_CB_CONTINUE 1
 
 static int cj_cb_boolean(void *ctx, int boolVal) {
-  cj_cb_inc_array_index(ctx, /* update_key = */ 0);
+  cj_advance_array(ctx);
   return (CJ_CB_CONTINUE);
 }
 
 static int cj_cb_null(void *ctx) {
-  cj_cb_inc_array_index(ctx, /* update_key = */ 0);
+  cj_advance_array(ctx);
   return (CJ_CB_CONTINUE);
 }
 
@@ -209,40 +239,37 @@ static int cj_cb_number(void *ctx, const char *number, yajl_len_t number_len) {
 
   cj_t *db = (cj_t *)ctx;
   cj_key_t *key = db->state[db->depth].key;
-  value_t vt;
-  int type;
-  int status;
 
   /* Create a null-terminated version of the string. */
   memcpy(buffer, number, number_len);
   buffer[sizeof(buffer) - 1] = 0;
 
-  if ((key == NULL) || !CJ_IS_KEY(key)) {
-    if (key != NULL &&
-        !db->state[db->depth].in_array /*can be inhomogeneous*/) {
-      NOTICE("curl_json plugin: Found \"%s\", but the configuration expects"
-             " a map.",
-             buffer);
-      return (CJ_CB_CONTINUE);
-    }
 
-    cj_cb_inc_array_index(ctx, /* update_key = */ 1);
-    key = db->state[db->depth].key;
-    if ((key == NULL) || !CJ_IS_KEY(key)) {
-      return (CJ_CB_CONTINUE);
-    }
-  } else {
-    cj_cb_inc_array_index(ctx, /* update_key = */ 1);
-  }
 
-  type = cj_get_type(key);
-  status = parse_value(buffer, &vt, type);
+  if (key == NULL) {
+    /* no config for this element. */
+    cj_advance_array(ctx);
+    return CJ_CB_CONTINUE;
+  } else if (!CJ_IS_KEY(key)) {
+    /* the config expects a map or an array. */
+    NOTICE(
+        "curl_json plugin: Found \"%s\", but the configuration expects a map.",
+        buffer);
+    cj_advance_array(ctx);
+    return CJ_CB_CONTINUE;
+  }
+
+  int type = cj_get_type(key);
+  value_t vt;
+  int status = parse_value(buffer, &vt, type);
   if (status != 0) {
     NOTICE("curl_json plugin: Unable to parse number: \"%s\"", buffer);
+    cj_advance_array(ctx);
     return (CJ_CB_CONTINUE);
   }
 
   cj_submit(db, key, &vt);
+  cj_advance_array(ctx);
   return (CJ_CB_CONTINUE);
 } /* int cj_cb_number */
 
@@ -251,40 +278,15 @@ static int cj_cb_number(void *ctx, const char *number, yajl_len_t number_len) {
  * NULL. */
 static int cj_cb_map_key(void *ctx, unsigned char const *in_name,
                          yajl_len_t in_name_len) {
-  cj_t *db = (cj_t *)ctx;
-  c_avl_tree_t *tree;
+  char name[in_name_len + 1];
 
-  tree = db->state[db->depth - 1].tree;
-
-  if (tree != NULL) {
-    cj_key_t *value = NULL;
-    char *name;
-    size_t name_len;
-
-    /* Create a null-terminated version of the name. */
-    name = db->state[db->depth].name;
-    name_len =
-        COUCH_MIN((size_t)in_name_len, sizeof(db->state[db->depth].name) - 1);
-    memcpy(name, in_name, name_len);
-    name[name_len] = 0;
-
-    if (c_avl_get(tree, name, (void *)&value) == 0) {
-      if (CJ_IS_KEY((cj_key_t *)value)) {
-        db->state[db->depth].key = value;
-      } else {
-        db->state[db->depth].tree = (c_avl_tree_t *)value;
-      }
-    } else if (c_avl_get(tree, CJ_ANY, (void *)&value) == 0)
-      if (CJ_IS_KEY((cj_key_t *)value)) {
-        db->state[db->depth].key = value;
-      } else {
-        db->state[db->depth].tree = (c_avl_tree_t *)value;
-      }
-    else
-      db->state[db->depth].key = NULL;
-  }
+  memmove(name, in_name, in_name_len);
+  name[sizeof(name) - 1] = 0;
 
-  return (CJ_CB_CONTINUE);
+  if (cj_load_key(ctx, name) != 0)
+    return CJ_CB_ABORT;
+
+  return CJ_CB_CONTINUE;
 }
 
 static int cj_cb_string(void *ctx, const unsigned char *val, yajl_len_t len) {
@@ -292,38 +294,43 @@ static int cj_cb_string(void *ctx, const unsigned char *val, yajl_len_t len) {
   return (cj_cb_number(ctx, (const char *)val, len));
 } /* int cj_cb_string */
 
-static int cj_cb_start(void *ctx) {
-  cj_t *db = (cj_t *)ctx;
-  if (++db->depth >= YAJL_MAX_DEPTH) {
-    ERROR("curl_json plugin: %s depth exceeds max, aborting.",
-          db->url ? db->url : db->sock);
-    return (CJ_CB_ABORT);
-  }
-  return (CJ_CB_CONTINUE);
-}
-
 static int cj_cb_end(void *ctx) {
   cj_t *db = (cj_t *)ctx;
   db->state[db->depth].tree = NULL;
-  --db->depth;
+  db->depth--;
+  cj_advance_array(ctx);
   return (CJ_CB_CONTINUE);
 }
 
 static int cj_cb_start_map(void *ctx) {
-  cj_cb_inc_array_index(ctx, /* update_key = */ 1);
-  return cj_cb_start(ctx);
+  cj_t *db = (cj_t *)ctx;
+
+  if ((db->depth + 1) >= YAJL_MAX_DEPTH) {
+    ERROR("curl_json plugin: %s depth exceeds max, aborting.",
+          db->url ? db->url : db->sock);
+    return (CJ_CB_ABORT);
+  }
+  db->depth++;
+  return (CJ_CB_CONTINUE);
 }
 
 static int cj_cb_end_map(void *ctx) { return cj_cb_end(ctx); }
 
 static int cj_cb_start_array(void *ctx) {
   cj_t *db = (cj_t *)ctx;
-  cj_cb_inc_array_index(ctx, /* update_key = */ 1);
-  if (db->depth + 1 < YAJL_MAX_DEPTH) {
-    db->state[db->depth + 1].in_array = 1;
-    db->state[db->depth + 1].index = 0;
+
+  if ((db->depth + 1) >= YAJL_MAX_DEPTH) {
+    ERROR("curl_json plugin: %s depth exceeds max, aborting.",
+          db->url ? db->url : db->sock);
+    return CJ_CB_ABORT;
   }
-  return cj_cb_start(ctx);
+  db->depth++;
+  db->state[db->depth].in_array = 1;
+  db->state[db->depth].index = 0;
+
+  cj_load_key(db, "0");
+
+  return CJ_CB_CONTINUE;
 }
 
 static int cj_cb_end_array(void *ctx) {
@@ -555,7 +562,6 @@ static int cj_init_curl(cj_t *db) /* {{{ */
   curl_easy_setopt(db->curl, CURLOPT_WRITEDATA, db);
   curl_easy_setopt(db->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
   curl_easy_setopt(db->curl, CURLOPT_ERRORBUFFER, db->curl_errbuf);
-  curl_easy_setopt(db->curl, CURLOPT_URL, db->url);
   curl_easy_setopt(db->curl, CURLOPT_FOLLOWLOCATION, 1L);
   curl_easy_setopt(db->curl, CURLOPT_MAXREDIRS, 50L);
 
@@ -600,7 +606,7 @@ static int cj_init_curl(cj_t *db) /* {{{ */
     curl_easy_setopt(db->curl, CURLOPT_TIMEOUT_MS, (long)db->timeout);
   else if (db->interval > 0)
     curl_easy_setopt(db->curl, CURLOPT_TIMEOUT_MS,
-                     (long)CDTIME_T_TO_MS(db->timeout));
+                     (long)CDTIME_T_TO_MS(db->interval));
   else
     curl_easy_setopt(db->curl, CURLOPT_TIMEOUT_MS,
                      (long)CDTIME_T_TO_MS(plugin_get_interval()));
@@ -834,12 +840,13 @@ static int cj_curl_perform(cj_t *db) /* {{{ */
   int status;
   long rc;
   char *url;
-  url = db->url;
+
+  curl_easy_setopt(db->curl, CURLOPT_URL, db->url);
 
   status = curl_easy_perform(db->curl);
   if (status != CURLE_OK) {
     ERROR("curl_json plugin: curl_easy_perform failed with status %i: %s (%s)",
-          status, db->curl_errbuf, url);
+          status, db->curl_errbuf, db->url);
     return (-1);
   }
   if (db->stats != NULL)
index 4e4c6f9..7c422c7 100644 (file)
@@ -602,13 +602,15 @@ static int cx_curl_perform(cx_t *db, CURL *curl) /* {{{ */
   long rc;
   char *ptr;
   char *url;
-  url = db->url;
 
   db->buffer_fill = 0;
+
+  curl_easy_setopt(db->curl, CURLOPT_URL, db->url);
+
   status = curl_easy_perform(curl);
   if (status != CURLE_OK) {
     ERROR("curl_xml plugin: curl_easy_perform failed with status %i: %s (%s)",
-          status, db->curl_errbuf, url);
+          status, db->curl_errbuf, db->url);
     return (-1);
   }
   if (db->stats != NULL)
@@ -817,7 +819,6 @@ static int cx_init_curl(cx_t *db) /* {{{ */
   curl_easy_setopt(db->curl, CURLOPT_WRITEDATA, db);
   curl_easy_setopt(db->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
   curl_easy_setopt(db->curl, CURLOPT_ERRORBUFFER, db->curl_errbuf);
-  curl_easy_setopt(db->curl, CURLOPT_URL, db->url);
   curl_easy_setopt(db->curl, CURLOPT_FOLLOWLOCATION, 1L);
   curl_easy_setopt(db->curl, CURLOPT_MAXREDIRS, 50L);
 
index f3df795..6b7c413 100644 (file)
@@ -521,7 +521,7 @@ int main(int argc, char **argv) {
    */
   if (cf_read(configfile)) {
     fprintf(stderr, "Error: Reading the config file failed!\n"
-                    "Read the syslog for details.\n");
+                    "Read the logs for details.\n");
     return (1);
   }
 
index 0aa5345..ec5c7ab 100644 (file)
@@ -271,8 +271,10 @@ ssize_t swrite(int fd, const void *buf, size_t count) {
   ptr = (const char *)buf;
   nleft = count;
 
-  if (fd < 0)
-    return (-1);
+  if (fd < 0) {
+    errno = EINVAL;
+    return errno;
+  }
 
   /* checking for closed peer connection */
   pfd.fd = fd;
@@ -281,10 +283,9 @@ ssize_t swrite(int fd, const void *buf, size_t count) {
   if (poll(&pfd, 1, 0) > 0) {
     char buffer[32];
     if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
-      // if recv returns zero (even though poll() said there is data to be
-      // read),
-      // that means the connection has been closed
-      return -1;
+      /* if recv returns zero (even though poll() said there is data to be
+       * read), that means the connection has been closed */
+      return errno ? errno : -1;
     }
   }
 
@@ -295,7 +296,7 @@ ssize_t swrite(int fd, const void *buf, size_t count) {
       continue;
 
     if (status < 0)
-      return (status);
+      return errno ? errno : status;
 
     nleft = nleft - ((size_t)status);
     ptr = ptr + ((size_t)status);
@@ -1567,16 +1568,26 @@ void strarray_free(char **array, size_t array_len) /* {{{ */
 #if HAVE_CAPABILITY
 int check_capability(int arg) /* {{{ */
 {
-  cap_value_t cap = (cap_value_t)arg;
+  cap_value_t cap_value = (cap_value_t)arg;
+  cap_t cap;
+  cap_flag_value_t cap_flag_value;
 
-  if (!CAP_IS_SUPPORTED(cap))
+  if (!CAP_IS_SUPPORTED(cap_value))
     return (-1);
 
-  int have_cap = cap_get_bound(cap);
-  if (have_cap != 1)
+  if (!(cap = cap_get_proc())) {
+    ERROR("check_capability: cap_get_proc failed.");
     return (-1);
+  }
 
-  return (0);
+  if (cap_get_flag(cap, cap_value, CAP_EFFECTIVE, &cap_flag_value) < 0) {
+    ERROR("check_capability: cap_get_flag failed.");
+    cap_free(cap);
+    return (-1);
+  }
+  cap_free(cap);
+
+  return (cap_flag_value != CAP_SET);
 } /* }}} int check_capability */
 #else
 int check_capability(__attribute__((unused)) int arg) /* {{{ */
index a1a2528..8947c57 100644 (file)
@@ -385,7 +385,7 @@ void strarray_free(char **array, size_t array_len);
  * argument. Returns zero if it does, less than zero if it doesn't or on error.
  * See capabilities(7) for the list of possible capabilities.
  * */
-int check_capability(int capability);
+int check_capability(int arg);
 #endif /* HAVE_SYS_CAPABILITY_H */
 
 #endif /* COMMON_H */
index d5f01e0..3934e1f 100644 (file)
@@ -1119,14 +1119,36 @@ int cf_util_get_boolean(const oconfig_item_t *ci, _Bool *ret_bool) /* {{{ */
   if ((ci == NULL) || (ret_bool == NULL))
     return (EINVAL);
 
-  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) {
+  if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN) &&
+                                (ci->values[0].type != OCONFIG_TYPE_STRING))) {
     ERROR("cf_util_get_boolean: The %s option requires "
           "exactly one boolean argument.",
           ci->key);
     return (-1);
   }
 
-  *ret_bool = ci->values[0].value.boolean ? 1 : 0;
+  switch (ci->values[0].type) {
+  case OCONFIG_TYPE_BOOLEAN:
+    *ret_bool = ci->values[0].value.boolean ? 1 : 0;
+    break;
+  case OCONFIG_TYPE_STRING:
+    WARNING("cf_util_get_boolean: Using string value `%s' for boolean option "
+            "`%s' is deprecated and will be removed in future releases. "
+            "Use unquoted true or false instead.",
+            ci->values[0].value.string, ci->key);
+
+    if (IS_TRUE(ci->values[0].value.string))
+      *ret_bool = 1;
+    else if (IS_FALSE(ci->values[0].value.string))
+      *ret_bool = 0;
+    else {
+      ERROR("cf_util_get_boolean: Cannot parse string value `%s' of the `%s' "
+            "option as a boolean value.",
+            ci->values[0].value.string, ci->key);
+      return (-1);
+    }
+    break;
+  }
 
   return (0);
 } /* }}} int cf_util_get_boolean */
index 583d819..7684690 100644 (file)
@@ -737,7 +737,6 @@ int meta_data_as_string(meta_data_t *md, /* {{{ */
 
   temp = md_strdup(actual);
   if (temp == NULL) {
-    pthread_mutex_unlock(&md->lock);
     ERROR("meta_data_as_string: md_strdup failed for key `%s'.", key);
     return (-ENOMEM);
   }
index f313f36..0f06737 100644 (file)
@@ -153,14 +153,13 @@ static const char *plugin_get_dir(void) {
     return (plugindir);
 }
 
-static void plugin_update_internal_statistics(void) { /* {{{ */
-
+static int plugin_update_internal_statistics(void) { /* {{{ */
   gauge_t copy_write_queue_length = (gauge_t)write_queue_length;
 
   /* Initialize `vl' */
   value_list_t vl = VALUE_LIST_INIT;
-  sstrncpy(vl.host, hostname_g, sizeof(vl.host));
   sstrncpy(vl.plugin, "collectd", sizeof(vl.plugin));
+  vl.interval = plugin_get_interval();
 
   /* Write queue */
   sstrncpy(vl.plugin_instance, "write_queue", sizeof(vl.plugin_instance));
@@ -189,8 +188,8 @@ static void plugin_update_internal_statistics(void) { /* {{{ */
   vl.type_instance[0] = 0;
   plugin_dispatch_values(&vl);
 
-  return;
-} /* }}} void plugin_update_internal_statistics */
+  return 0;
+} /* }}} int plugin_update_internal_statistics */
 
 static void destroy_callback(callback_func_t *cf) /* {{{ */
 {
@@ -1572,8 +1571,10 @@ int plugin_init_all(void) {
   /* Init the value cache */
   uc_init();
 
-  if (IS_TRUE(global_option_get("CollectInternalStats")))
+  if (IS_TRUE(global_option_get("CollectInternalStats"))) {
     record_statistics = 1;
+    plugin_register_read("collectd", plugin_update_internal_statistics);
+  }
 
   chain_name = global_option_get("PreCacheChain");
   pre_cache_chain = fc_chain_get_by_name(chain_name);
@@ -1661,9 +1662,6 @@ int plugin_init_all(void) {
 
 /* TODO: Rename this function. */
 void plugin_read_all(void) {
-  if (record_statistics) {
-    plugin_update_internal_statistics();
-  }
   uc_check_timeout();
 
   return;
index fe0e083..aa8ce9e 100644 (file)
@@ -222,8 +222,6 @@ int uc_init(void) {
 } /* int uc_init */
 
 int uc_check_timeout(void) {
-  cdtime_t now = cdtime();
-
   struct {
     char *key;
     cdtime_t time;
@@ -232,6 +230,7 @@ int uc_check_timeout(void) {
   size_t expired_num = 0;
 
   pthread_mutex_lock(&cache_lock);
+  cdtime_t now = cdtime();
 
   /* Build a list of entries to be flushed */
   c_avl_iterator_t *iter = c_avl_get_iterator(cache_tree);
@@ -423,6 +422,9 @@ int uc_get_rate_by_name(const char *name, gauge_t **ret_values,
 
     /* remove missing values from getval */
     if (ce->state == STATE_MISSING) {
+      DEBUG("utils_cache: uc_get_rate_by_name: requested metric \"%s\" is in "
+            "state \"missing\".",
+            name);
       status = -1;
     } else {
       ret_num = ce->values_num;
@@ -466,7 +468,7 @@ gauge_t *uc_get_rate(const data_set_t *ds, const value_list_t *vl) {
 
   /* This is important - the caller has no other way of knowing how many
    * values are returned. */
-  if (ret_num != (size_t)ds->ds_num) {
+  if (ret_num != ds->ds_num) {
     ERROR("utils_cache: uc_get_rate: ds[%s] has %zu values, "
           "but uc_get_rate_by_name returned %zu.",
           ds->type, ds->ds_num, ret_num);
index 7cab1d5..0e5c5de 100644 (file)
--- a/src/dbi.c
+++ b/src/dbi.c
@@ -172,7 +172,9 @@ static void cdbi_database_free(cdbi_database_t *db) /* {{{ */
     return;
 
   sfree(db->name);
+  sfree(db->select_db);
   sfree(db->driver);
+  sfree(db->host);
 
   for (size_t i = 0; i < db->driver_options_num; i++) {
     sfree(db->driver_options[i].key);
@@ -184,7 +186,10 @@ static void cdbi_database_free(cdbi_database_t *db) /* {{{ */
   if (db->q_prep_areas)
     for (size_t i = 0; i < db->queries_num; ++i)
       udb_query_delete_preparation_area(db->q_prep_areas[i]);
-  free(db->q_prep_areas);
+  sfree(db->q_prep_areas);
+  /* N.B.: db->queries references objects "owned" by the global queries
+   * variable. Free the array here, but not the content. */
+  sfree(db->queries);
 
   sfree(db);
 } /* }}} void cdbi_database_free */
index de75c0c..6d0aabf 100644 (file)
@@ -159,8 +159,8 @@ static int dpdk_shm_init(size_t size);
 static void dpdk_config_init_default(void) {
   g_configuration->interval = plugin_get_interval();
   if (g_configuration->interval == cf_get_default_interval())
-    WARNING("dpdkstat: No time interval was configured, default value %lu ms "
-            "is set",
+    WARNING("dpdkstat: No time interval was configured, default value %" PRIu64
+            " ms is set",
             CDTIME_T_TO_MS(g_configuration->interval));
   /* Default is all ports enabled */
   g_configuration->enabled_port_mask = ~0;
@@ -289,13 +289,13 @@ static int dpdk_shm_init(size_t size) {
   if (err) {
     ERROR("dpdkstat semaphore init failed: %s",
           sstrerror(errno, errbuf, sizeof(errbuf)));
-    goto fail_close;
+    goto fail;
   }
   err = sem_init(&g_configuration->sema_stats_in_shm, 1, 0);
   if (err) {
     ERROR("dpdkstat semaphore init failed: %s",
           sstrerror(errno, errbuf, sizeof(errbuf)));
-    goto fail_close;
+    goto fail;
   }
 
   g_configuration->xstats = NULL;
@@ -413,7 +413,7 @@ static int dpdk_helper_spawn(enum DPDK_HELPER_ACTION action) {
   if (pid > 0) {
     close(g_configuration->helper_pipes[1]);
     g_configuration->helper_pid = pid;
-    DEBUG("dpdkstat: helper pid %lu", (long)g_configuration->helper_pid);
+    DEBUG("dpdkstat: helper pid %li", (long)g_configuration->helper_pid);
     /* Kick helper once its alive to have it start processing */
     sem_post(&g_configuration->sema_helper_get_stats);
   } else if (pid == 0) {
@@ -620,17 +620,17 @@ static void dpdk_submit_xstats(const char *dev_name, int count,
 
     if ((type_end != NULL) &&
         (strncmp(counter_name, "rx_", strlen("rx_")) == 0)) {
-      if (strncmp(type_end, "_errors", strlen("_errors")) == 0) {
+      if (strstr(type_end, "bytes") != NULL) {
+        sstrncpy(vl.type, "if_rx_octets", sizeof(vl.type));
+      } else if (strstr(type_end, "error") != NULL) {
         sstrncpy(vl.type, "if_rx_errors", sizeof(vl.type));
-      } else if (strncmp(type_end, "_dropped", strlen("_dropped")) == 0) {
+      } else if (strstr(type_end, "dropped") != NULL) {
         sstrncpy(vl.type, "if_rx_dropped", sizeof(vl.type));
-      } else if (strncmp(type_end, "_bytes", strlen("_bytes")) == 0) {
-        sstrncpy(vl.type, "if_rx_octets", sizeof(vl.type));
-      } else if (strncmp(type_end, "_packets", strlen("_packets")) == 0) {
+      } else if (strstr(type_end, "packets") != NULL) {
         sstrncpy(vl.type, "if_rx_packets", sizeof(vl.type));
-      } else if (strncmp(type_end, "_placement", strlen("_placement")) == 0) {
+      } else if (strstr(type_end, "_placement") != NULL) {
         sstrncpy(vl.type, "if_rx_errors", sizeof(vl.type));
-      } else if (strncmp(type_end, "_buff", strlen("_buff")) == 0) {
+      } else if (strstr(type_end, "_buff") != NULL) {
         sstrncpy(vl.type, "if_rx_errors", sizeof(vl.type));
       } else {
         /* Does not fit obvious type: use a more generic one */
@@ -639,13 +639,13 @@ static void dpdk_submit_xstats(const char *dev_name, int count,
 
     } else if ((type_end != NULL) &&
                (strncmp(counter_name, "tx_", strlen("tx_"))) == 0) {
-      if (strncmp(type_end, "_errors", strlen("_errors")) == 0) {
+      if (strstr(type_end, "bytes") != NULL) {
+        sstrncpy(vl.type, "if_tx_octets", sizeof(vl.type));
+      } else if (strstr(type_end, "error") != NULL) {
         sstrncpy(vl.type, "if_tx_errors", sizeof(vl.type));
-      } else if (strncmp(type_end, "_dropped", strlen("_dropped")) == 0) {
+      } else if (strstr(type_end, "dropped") != NULL) {
         sstrncpy(vl.type, "if_tx_dropped", sizeof(vl.type));
-      } else if (strncmp(type_end, "_bytes", strlen("_bytes")) == 0) {
-        sstrncpy(vl.type, "if_tx_octets", sizeof(vl.type));
-      } else if (strncmp(type_end, "_packets", strlen("_packets")) == 0) {
+      } else if (strstr(type_end, "packets") != NULL) {
         sstrncpy(vl.type, "if_tx_packets", sizeof(vl.type));
       } else {
         /* Does not fit obvious type: use a more generic one */
@@ -654,16 +654,14 @@ static void dpdk_submit_xstats(const char *dev_name, int count,
     } else if ((type_end != NULL) &&
                (strncmp(counter_name, "flow_", strlen("flow_"))) == 0) {
 
-      if (strncmp(type_end, "_filters", strlen("_filters")) == 0) {
+      if (strstr(type_end, "_filters") != NULL) {
         sstrncpy(vl.type, "operations", sizeof(vl.type));
-      } else if (strncmp(type_end, "_errors", strlen("_errors")) == 0) {
+      } else if (strstr(type_end, "error") != NULL)
         sstrncpy(vl.type, "errors", sizeof(vl.type));
-      } else if (strncmp(type_end, "_filters", strlen("_filters")) == 0) {
-        sstrncpy(vl.type, "filter_result", sizeof(vl.type));
-      }
+
     } else if ((type_end != NULL) &&
                (strncmp(counter_name, "mac_", strlen("mac_"))) == 0) {
-      if (strncmp(type_end, "_errors", strlen("_errors")) == 0) {
+      if (strstr(type_end, "error") != NULL) {
         sstrncpy(vl.type, "errors", sizeof(vl.type));
       }
     } else {
index 34e9998..611da56 100644 (file)
@@ -299,22 +299,21 @@ static void *collect(void *arg) {
       }
 
       if ('e' == line[0]) { /* e:<type>:<bytes> */
-        char *ptr = NULL;
-        char *type = strtok_r(line + 2, ":", &ptr);
-        char *tmp = strtok_r(NULL, ":", &ptr);
-        int bytes = 0;
-
-        if (NULL == tmp) {
+        char *type = line + 2;
+        char *bytes_str = strchr(type, ':');
+        if (bytes_str == NULL) {
           log_err("collect: syntax error in line '%s'", line);
           continue;
         }
 
-        bytes = atoi(tmp);
+        *bytes_str = 0;
+        bytes_str++;
 
         pthread_mutex_lock(&count_mutex);
         type_list_incr(&list_count, type, /* increment = */ 1);
         pthread_mutex_unlock(&count_mutex);
 
+        int bytes = atoi(bytes_str);
         if (bytes > 0) {
           pthread_mutex_lock(&size_mutex);
           type_list_incr(&list_size, type, /* increment = */ bytes);
@@ -374,7 +373,7 @@ static void *open_connection(void __attribute__((unused)) * arg) {
   }
 
   struct sockaddr_un addr = {
-    .sun_family = AF_UNIX
+      .sun_family = AF_UNIX,
   };
   sstrncpy(addr.sun_path, path, (size_t)(UNIX_PATH_MAX - 1));
 
@@ -403,15 +402,21 @@ static void *open_connection(void __attribute__((unused)) * arg) {
   {
     struct group sg;
     struct group *grp;
-    char grbuf[2048];
     int status;
 
+    long int grbuf_size = sysconf(_SC_GETGR_R_SIZE_MAX);
+    if (grbuf_size <= 0)
+      grbuf_size = sysconf(_SC_PAGESIZE);
+    if (grbuf_size <= 0)
+      grbuf_size = 4096;
+    char grbuf[grbuf_size];
+
     grp = NULL;
     status = getgrnam_r(group, &sg, grbuf, sizeof(grbuf), &grp);
     if (status != 0) {
       char errbuf[1024];
       log_warn("getgrnam_r (%s) failed: %s", group,
-               sstrerror(errno, errbuf, sizeof(errbuf)));
+               sstrerror(status, errbuf, sizeof(errbuf)));
     } else if (grp == NULL) {
       log_warn("No such group: `%s'", group);
     } else {
index d34f9d9..60bd961 100644 (file)
@@ -369,11 +369,17 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out,
 
   struct passwd *sp_ptr;
   struct passwd sp;
-  char nambuf[2048];
 
   if (pl->pid != 0)
     return (-1);
 
+  long int nambuf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
+  if (nambuf_size <= 0)
+    nambuf_size = sysconf(_SC_PAGESIZE);
+  if (nambuf_size <= 0)
+    nambuf_size = 4096;
+  char nambuf[nambuf_size];
+
   if ((create_pipe(fd_pipe_in) == -1) || (create_pipe(fd_pipe_out) == -1) ||
       (create_pipe(fd_pipe_err) == -1))
     goto failed;
@@ -382,7 +388,7 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out,
   status = getpwnam_r(pl->user, &sp, nambuf, sizeof(nambuf), &sp_ptr);
   if (status != 0) {
     ERROR("exec plugin: Failed to get user information for user ``%s'': %s",
-          pl->user, sstrerror(errno, errbuf, sizeof(errbuf)));
+          pl->user, sstrerror(status, errbuf, sizeof(errbuf)));
     goto failed;
   }
 
@@ -406,11 +412,18 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out,
       struct group *gr_ptr = NULL;
       struct group gr;
 
-      status = getgrnam_r(pl->group, &gr, nambuf, sizeof(nambuf), &gr_ptr);
+      long int grbuf_size = sysconf(_SC_GETGR_R_SIZE_MAX);
+      if (grbuf_size <= 0)
+        grbuf_size = sysconf(_SC_PAGESIZE);
+      if (grbuf_size <= 0)
+        grbuf_size = 4096;
+      char grbuf[grbuf_size];
+
+      status = getgrnam_r(pl->group, &gr, grbuf, sizeof(grbuf), &gr_ptr);
       if (0 != status) {
         ERROR("exec plugin: Failed to get group information "
               "for group ``%s'': %s",
-              pl->group, sstrerror(errno, errbuf, sizeof(errbuf)));
+              pl->group, sstrerror(status, errbuf, sizeof(errbuf)));
         goto failed;
       }
       if (NULL == gr_ptr) {
@@ -787,7 +800,11 @@ static int exec_read(void) /* {{{ */
 
     pthread_attr_init(&attr);
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-    plugin_thread_create(&t, &attr, exec_read_one, (void *)pl, "exec read");
+    int status =
+        plugin_thread_create(&t, &attr, exec_read_one, (void *)pl, "exec read");
+    if (status != 0) {
+      ERROR("exec plugin: plugin_thread_create failed.");
+    }
     pthread_attr_destroy(&attr);
   } /* for (pl) */
 
@@ -826,8 +843,11 @@ static int exec_notification(const notification_t *n, /* {{{ */
 
     pthread_attr_init(&attr);
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-    plugin_thread_create(&t, &attr, exec_notification_one, (void *)pln,
-                         "exec notify");
+    int status = plugin_thread_create(&t, &attr, exec_notification_one,
+                                      (void *)pln, "exec notify");
+    if (status != 0) {
+      ERROR("exec plugin: plugin_thread_create failed.");
+    }
     pthread_attr_destroy(&attr);
   } /* for (pl) */
 
index a4b3e2e..686710b 100644 (file)
--- a/src/gps.c
+++ b/src/gps.c
  *   Marc Fournier <marc.fournier at camptocamp.com>
  **/
 
+#include "collectd.h"
 #include "common.h"
 #include "plugin.h"
 #include "utils_time.h"
-#include "collectd.h"
 
 #define CGPS_TRUE 1
 #define CGPS_FALSE 0
@@ -80,7 +80,7 @@ static int cgps_thread_pause(cdtime_t pTime) {
 
   int ret = !cgps_thread_shutdown;
 
-  pthread_mutex_lock(&cgps_thread_lock);
+  pthread_mutex_unlock(&cgps_thread_lock);
   return ret;
 }
 
@@ -307,7 +307,6 @@ static int cgps_shutdown(void) {
   free(res);
 
   // Clean mutex:
-  pthread_mutex_unlock(&cgps_thread_lock);
   pthread_mutex_destroy(&cgps_thread_lock);
   pthread_mutex_unlock(&cgps_data_lock);
   pthread_mutex_destroy(&cgps_data_lock);
index 2ef65f5..6f157b8 100644 (file)
 #define RDT_MAX_SOCKET_CORES 64
 #define RDT_MAX_CORES (RDT_MAX_SOCKET_CORES * RDT_MAX_SOCKETS)
 
+typedef enum {
+  UNKNOWN = 0,
+  CONFIGURATION_ERROR,
+} rdt_config_status;
+
 struct rdt_core_group_s {
   char *desc;
   size_t num_cores;
@@ -56,6 +61,8 @@ typedef struct rdt_ctx_s rdt_ctx_t;
 
 static rdt_ctx_t *g_rdt = NULL;
 
+static rdt_config_status g_state = UNKNOWN;
+
 static int isdup(const uint64_t *nums, size_t size, uint64_t val) {
   for (size_t i = 0; i < size; i++)
     if (nums[i] == val)
@@ -520,25 +527,31 @@ rdt_preinit_error1:
 }
 
 static int rdt_config(oconfig_item_t *ci) {
-  int ret = 0;
-
-  ret = rdt_preinit();
-  if (ret != 0)
-    return ret;
+  if (rdt_preinit() != 0) {
+    g_state = CONFIGURATION_ERROR;
+    /* if we return -1 at this point collectd
+      reports a failure in configuration and
+      aborts
+    */
+    return (0);
+  }
 
   for (int i = 0; i < ci->children_num; i++) {
     oconfig_item_t *child = ci->children + i;
 
     if (strcasecmp("Cores", child->key) == 0) {
-
-      ret = rdt_config_cgroups(child);
-      if (ret != 0)
-        return ret;
+      if (rdt_config_cgroups(child) != 0) {
+        g_state = CONFIGURATION_ERROR;
+        /* if we return -1 at this point collectd
+           reports a failure in configuration and
+           aborts
+         */
+       return (0);
+      }
 
 #if COLLECT_DEBUG
       rdt_dump_cgroups();
 #endif /* COLLECT_DEBUG */
-
     } else {
       ERROR(RDT_PLUGIN ": Unknown configuration parameter \"%s\".", child->key);
     }
@@ -626,6 +639,9 @@ static int rdt_read(__attribute__((unused)) user_data_t *ud) {
 static int rdt_init(void) {
   int ret;
 
+  if(g_state == CONFIGURATION_ERROR)
+    return (-1);
+
   ret = rdt_preinit();
   if (ret != 0)
     return ret;
index c9fb003..74db3ad 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -251,14 +251,14 @@ static int ipc_read_shm(void) /* {{{ */
   ipcinfo_shm_t *pshm;
   unsigned int shm_segments = 0;
   size64_t shm_bytes = 0;
-  int n;
+  int i, n;
 
   ipcinfo_shm = (ipcinfo_shm_t *)ipc_get_info(
       0, GET_IPCINFO_SHM_ALL, IPCINFO_SHM_VERSION, sizeof(ipcinfo_shm_t), &n);
   if (ipcinfo_shm == NULL)
     return -1;
 
-  for (int i = 0, pshm = ipcinfo_shm; i < n; i++, pshm++) {
+  for (i = 0, pshm = ipcinfo_shm; i < n; i++, pshm++) {
     shm_segments++;
     shm_bytes += pshm->shm_segsz;
   }
index 4a550b3..90f51de 100644 (file)
@@ -31,7 +31,7 @@
 #include "aux_types.h"
 
 static char *unquote (const char *orig);
-static int yyerror (const char *s);
+static void yyerror(const char *s);
 
 /* Lexer variables */
 extern int yylineno;
@@ -94,13 +94,23 @@ argument_list:
        argument_list argument
        {
         $$ = $1;
+        oconfig_value_t *tmp = realloc($$.argument,
+                                       ($$.argument_num+1) * sizeof(*$$.argument));
+        if (tmp == NULL) {
+          yyerror("realloc failed");
+          YYERROR;
+        }
+        $$.argument = tmp;
+        $$.argument[$$.argument_num] = $2;
         $$.argument_num++;
-        $$.argument = realloc ($$.argument, $$.argument_num * sizeof (oconfig_value_t));
-        $$.argument[$$.argument_num-1] = $2;
        }
        | argument
        {
-        $$.argument = malloc (sizeof (oconfig_value_t));
+        $$.argument = calloc(1, sizeof(*$$.argument));
+        if ($$.argument == NULL) {
+          yyerror("calloc failed");
+          YYERROR;
+        }
         $$.argument[0] = $1;
         $$.argument_num = 1;
        }
@@ -113,7 +123,7 @@ identifier:
 option:
        identifier argument_list EOL
        {
-        memset (&$$, '\0', sizeof ($$));
+        memset(&$$, 0, sizeof($$));
         $$.key = $1;
         $$.values = $2.argument;
         $$.values_num = $2.argument_num;
@@ -123,13 +133,13 @@ option:
 block_begin:
        OPENBRAC identifier CLOSEBRAC EOL
        {
-        memset (&$$, '\0', sizeof ($$));
+        memset(&$$, 0, sizeof($$));
         $$.key = $2;
        }
        |
        OPENBRAC identifier argument_list CLOSEBRAC EOL
        {
-        memset (&$$, '\0', sizeof ($$));
+        memset(&$$, 0, sizeof($$));
         $$.key = $2;
         $$.values = $3.argument;
         $$.values_num = $3.argument_num;
@@ -146,11 +156,11 @@ block_end:
 block:
        block_begin statement_list block_end
        {
-        if (strcmp ($1.key, $3) != 0)
+        if (strcmp($1.key, $3) != 0)
         {
-               printf ("block_begin = %s; block_end = %s;\n", $1.key, $3);
-               yyerror ("Block not closed..\n");
-               exit (1);
+               printf("block_begin = %s; block_end = %s;\n", $1.key, $3);
+               yyerror("block not closed");
+               YYERROR;
         }
         free ($3); $3 = NULL;
         $$ = $1;
@@ -159,11 +169,11 @@ block:
        }
        | block_begin block_end
        {
-        if (strcmp ($1.key, $2) != 0)
+        if (strcmp($1.key, $2) != 0)
         {
-               printf ("block_begin = %s; block_end = %s;\n", $1.key, $2);
-               yyerror ("Block not closed..\n");
-               exit (1);
+               printf("block_begin = %s; block_end = %s;\n", $1.key, $2);
+               yyerror("block not closed");
+               YYERROR;
         }
         free ($2); $2 = NULL;
         $$ = $1;
@@ -184,16 +194,26 @@ statement_list:
         $$ = $1;
         if (($2.values_num > 0) || ($2.children_num > 0))
         {
+                oconfig_item_t *tmp = realloc($$.statement,
+                                              ($$.statement_num+1) * sizeof(*tmp));
+                if (tmp == NULL) {
+                  yyerror("realloc failed");
+                  YYERROR;
+                }
+                $$.statement = tmp;
+                $$.statement[$$.statement_num] = $2;
                 $$.statement_num++;
-                $$.statement = realloc ($$.statement, $$.statement_num * sizeof (oconfig_item_t));
-                $$.statement[$$.statement_num-1] = $2;
         }
        }
        | statement
        {
         if (($1.values_num > 0) || ($1.children_num > 0))
         {
-                $$.statement = malloc (sizeof (oconfig_item_t));
+                $$.statement = calloc(1, sizeof(*$$.statement));
+                if ($$.statement == NULL) {
+                  yyerror("calloc failed");
+                  YYERROR;
+                }
                 $$.statement[0] = $1;
                 $$.statement_num = 1;
         }
@@ -208,31 +228,38 @@ statement_list:
 entire_file:
        statement_list
        {
-        ci_root = calloc (1, sizeof (*ci_root));
+        ci_root = calloc(1, sizeof(*ci_root));
+        if (ci_root == NULL) {
+          yyerror("calloc failed");
+          YYERROR;
+        }
         ci_root->children = $1.statement;
         ci_root->children_num = $1.statement_num;
        }
        | /* epsilon */
        {
-        ci_root = calloc (1, sizeof (*ci_root));
-        ci_root->children = NULL;
-        ci_root->children_num = 0;
+        ci_root = calloc(1, sizeof(*ci_root));
+        if (ci_root == NULL) {
+          yyerror("calloc failed");
+          YYERROR;
+        }
        }
        ;
 
 %%
-static int yyerror (const char *s)
+static void yyerror(const char *s)
 {
        const char *text;
 
-       if (*yytext == '\n')
+       if (yytext == NULL)
+               text = "<empty>";
+       else if (*yytext == '\n')
                text = "<newline>";
        else
                text = yytext;
 
-       fprintf (stderr, "Parse error in file `%s', line %i near `%s': %s\n",
+       fprintf(stderr, "Parse error in file `%s', line %i near `%s': %s\n",
                c_file, yylineno, text, s);
-       return (-1);
 } /* int yyerror */
 
 static char *unquote (const char *orig)
@@ -250,7 +277,7 @@ static char *unquote (const char *orig)
 
        len -= 2;
        memmove (ret, ret + 1, len);
-       ret[len] = '\0';
+       ret[len] = 0;
 
        for (int i = 0; i < len; i++)
        {
index 303976b..8df4313 100644 (file)
@@ -41,8 +41,6 @@
 #define HAVE_YAJL_V2 1
 #endif
 
-#define DEFAULT_LOGFILE LOCALSTATEDIR "/log/" PACKAGE_NAME ".json.log"
-
 #if COLLECT_DEBUG
 static int log_level = LOG_DEBUG;
 #else
@@ -149,8 +147,7 @@ static void log_logstash_print(yajl_gen g, int severity,
   pthread_mutex_lock(&file_lock);
 
   if (log_file == NULL) {
-    fh = fopen(DEFAULT_LOGFILE, "a");
-    do_close = 1;
+    fh = stderr;
   } else if (strcasecmp(log_file, "stdout") == 0) {
     fh = stdout;
     do_close = 0;
@@ -164,8 +161,7 @@ static void log_logstash_print(yajl_gen g, int severity,
 
   if (fh == NULL) {
     char errbuf[1024];
-    fprintf(stderr, "log_logstash plugin: fopen (%s) failed: %s\n",
-            (log_file == NULL) ? DEFAULT_LOGFILE : log_file,
+    fprintf(stderr, "log_logstash plugin: fopen (%s) failed: %s\n", log_file,
             sstrerror(errno, errbuf, sizeof(errbuf)));
   } else {
     fprintf(fh, "%s\n", buf);
index db12291..6629c0b 100644 (file)
@@ -31,8 +31,6 @@
 #include "common.h"
 #include "plugin.h"
 
-#define DEFAULT_LOGFILE LOCALSTATEDIR "/log/collectd.log"
-
 #if COLLECT_DEBUG
 static int log_level = LOG_DEBUG;
 #else
@@ -117,8 +115,7 @@ static void logfile_print(const char *msg, int severity,
   pthread_mutex_lock(&file_lock);
 
   if (log_file == NULL) {
-    fh = fopen(DEFAULT_LOGFILE, "a");
-    do_close = 1;
+    fh = stderr;
   } else if (strcasecmp(log_file, "stderr") == 0)
     fh = stderr;
   else if (strcasecmp(log_file, "stdout") == 0)
@@ -130,8 +127,7 @@ static void logfile_print(const char *msg, int severity,
 
   if (fh == NULL) {
     char errbuf[1024];
-    fprintf(stderr, "logfile plugin: fopen (%s) failed: %s\n",
-            (log_file == NULL) ? DEFAULT_LOGFILE : log_file,
+    fprintf(stderr, "logfile plugin: fopen (%s) failed: %s\n", log_file,
             sstrerror(errno, errbuf, sizeof(errbuf)));
   } else {
     if (print_timestamp)
index 79c38a7..cfdf903 100644 (file)
@@ -341,9 +341,10 @@ static int memcached_read(user_data_t *user_data) {
      * CPU time consumed by the memcached process
      */
     if (FIELD_IS("rusage_user")) {
-      rusage_user = atoll(fields[2]);
+      /* Convert to useconds */
+      rusage_user = atof(fields[2]) * 1000000;
     } else if (FIELD_IS("rusage_system")) {
-      rusage_syst = atoll(fields[2]);
+      rusage_syst = atof(fields[2]) * 1000000;
     }
 
     /*
index b578b99..315974b 100644 (file)
@@ -448,6 +448,7 @@ static int publish(mqtt_client_conf_t *conf, char const *topic,
      * measure; we will try to reconnect the next time we have to publish a
      * message */
     conf->connected = 0;
+    mosquitto_disconnect(conf->mosq);
 
     pthread_mutex_unlock(&conf->lock);
     return (-1);
@@ -461,6 +462,7 @@ static int format_topic(char *buf, size_t buf_len, data_set_t const *ds,
                         value_list_t const *vl, mqtt_client_conf_t *conf) {
   char name[MQTT_MAX_TOPIC_SIZE];
   int status;
+  char *c;
 
   if ((conf->topic_prefix == NULL) || (conf->topic_prefix[0] == 0))
     return (FORMAT_VL(buf, buf_len, vl));
@@ -473,6 +475,10 @@ static int format_topic(char *buf, size_t buf_len, data_set_t const *ds,
   if ((status < 0) || (((size_t)status) >= buf_len))
     return (ENOMEM);
 
+  while((c = strchr(buf, '#')) || (c = strchr(buf, '+'))) {
+       *c = '_';
+  }
+
   return (0);
 } /* int format_topic */
 
diff --git a/src/msr-index.h b/src/msr-index.h
new file mode 100644 (file)
index 0000000..c8077b7
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Partial header file imported from the linux kernel
+ * (arch/x86/include/asm/msr-index.h)
+ * as it is not provided by the kernel sources anymore
+ *
+ * Only the minimal blocks of macro have been included
+ * ----
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * ----
+ */
+
+#ifndef _ASM_X86_MSR_INDEX_H
+#define _ASM_X86_MSR_INDEX_H
+
+/*
+ * CPU model specific register (MSR) numbers.
+ *
+ * Do not add new entries to this file unless the definitions are shared
+ * between multiple compilation units.
+ */
+
+/* Intel MSRs. Some also available on other CPUs */
+
+/* C-state Residency Counters */
+#define MSR_PKG_C3_RESIDENCY 0x000003f8
+#define MSR_PKG_C6_RESIDENCY 0x000003f9
+#define MSR_ATOM_PKG_C6_RESIDENCY 0x000003fa
+#define MSR_PKG_C7_RESIDENCY 0x000003fa
+#define MSR_CORE_C3_RESIDENCY 0x000003fc
+#define MSR_CORE_C6_RESIDENCY 0x000003fd
+#define MSR_CORE_C7_RESIDENCY 0x000003fe
+#define MSR_KNL_CORE_C6_RESIDENCY 0x000003ff
+#define MSR_PKG_C2_RESIDENCY 0x0000060d
+#define MSR_PKG_C8_RESIDENCY 0x00000630
+#define MSR_PKG_C9_RESIDENCY 0x00000631
+#define MSR_PKG_C10_RESIDENCY 0x00000632
+
+/* Run Time Average Power Limiting (RAPL) Interface */
+
+#define MSR_RAPL_POWER_UNIT 0x00000606
+
+#define MSR_PKG_POWER_LIMIT 0x00000610
+#define MSR_PKG_ENERGY_STATUS 0x00000611
+#define MSR_PKG_PERF_STATUS 0x00000613
+#define MSR_PKG_POWER_INFO 0x00000614
+
+#define MSR_DRAM_POWER_LIMIT 0x00000618
+#define MSR_DRAM_ENERGY_STATUS 0x00000619
+#define MSR_DRAM_PERF_STATUS 0x0000061b
+#define MSR_DRAM_POWER_INFO 0x0000061c
+
+#define MSR_PP0_POWER_LIMIT 0x00000638
+#define MSR_PP0_ENERGY_STATUS 0x00000639
+#define MSR_PP0_POLICY 0x0000063a
+#define MSR_PP0_PERF_STATUS 0x0000063b
+
+#define MSR_PP1_POWER_LIMIT 0x00000640
+#define MSR_PP1_ENERGY_STATUS 0x00000641
+#define MSR_PP1_POLICY 0x00000642
+
+/* Intel defined MSRs. */
+#define MSR_IA32_TSC 0x00000010
+#define MSR_SMI_COUNT 0x00000034
+
+#define MSR_IA32_MPERF 0x000000e7
+#define MSR_IA32_APERF 0x000000e8
+
+#define MSR_IA32_THERM_STATUS 0x0000019c
+
+#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2
+
+#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1
+
+#endif /* _ASM_X86_MSR_INDEX_H */
index 4d45879..45144bf 100644 (file)
@@ -674,7 +674,7 @@ static int submit_double(const char *host, const char *plugin_inst, /* {{{ */
                          const char *type, const char *type_inst, double d,
                          cdtime_t timestamp, cdtime_t interval) {
   return (submit_values(host, plugin_inst, type, type_inst,
-                        &(value_t){.gauge = counter}, 1, timestamp, interval));
+                        &(value_t){.gauge = d}, 1, timestamp, interval));
 } /* }}} int submit_uint64 */
 
 /* Calculate hit ratio from old and new counters and submit the resulting
@@ -1910,15 +1910,13 @@ static int cna_query_quota(host_config_t *host) /* {{{ */
 static int cna_handle_snapvault_data(const char *hostname, /* {{{ */
                                      cfg_snapvault_t *cfg_snapvault,
                                      na_elem_t *data, cdtime_t interval) {
-  na_elem_iter_t status_iter;
-
-  status = na_elem_child(data, "status-list");
-  if (!status) {
+  na_elem_t *status_list = na_elem_child(data, "status-list");
+  if (status_list == NULL) {
     ERROR("netapp plugin: SnapVault status record missing status-list");
     return (0);
   }
 
-  status_iter = na_child_iterator(status);
+  na_elem_iter_t status_iter = na_child_iterator(status_list);
   for (na_elem_t *status = na_iterator_next(&status_iter); status != NULL;
        status = na_iterator_next(&status_iter)) {
     const char *dest_sys, *dest_path, *src_sys, *src_path;
index 8076c1f..66129ad 100644 (file)
@@ -353,8 +353,10 @@ static int link_filter_cb(const struct nlmsghdr *nlh,
       continue;
 
     if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*stats.stats64)) < 0) {
+      char errbuf[1024];
       ERROR("netlink plugin: link_filter_cb: IFLA_STATS64 mnl_attr_validate2 "
-            "failed.");
+            "failed: %s",
+            sstrerror(errno, errbuf, sizeof(errbuf)));
       return MNL_CB_ERROR;
     }
     stats.stats64 = mnl_attr_get_payload(attr);
@@ -369,8 +371,10 @@ static int link_filter_cb(const struct nlmsghdr *nlh,
       continue;
 
     if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*stats.stats32)) < 0) {
+      char errbuf[1024];
       ERROR("netlink plugin: link_filter_cb: IFLA_STATS mnl_attr_validate2 "
-            "failed.");
+            "failed: %s",
+            sstrerror(errno, errbuf, sizeof(errbuf)));
       return MNL_CB_ERROR;
     }
     stats.stats32 = mnl_attr_get_payload(attr);
@@ -395,8 +399,10 @@ static int qos_attr_cb(const struct nlattr *attr, void *data) {
 
   if (mnl_attr_get_type(attr) == TCA_STATS_BASIC) {
     if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(**bs)) < 0) {
+      char errbuf[1024];
       ERROR("netlink plugin: qos_attr_cb: TCA_STATS_BASIC mnl_attr_validate2 "
-            "failed.");
+            "failed: %s",
+            sstrerror(errno, errbuf, sizeof(errbuf)));
       return MNL_CB_ERROR;
     }
     *bs = mnl_attr_get_payload(attr);
@@ -529,8 +535,10 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) {
       continue;
 
     if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*ts)) < 0) {
+      char errbuf[1024];
       ERROR("netlink plugin: qos_filter_cb: TCA_STATS mnl_attr_validate2 "
-            "failed.");
+            "failed: %s",
+            sstrerror(errno, errbuf, sizeof(errbuf)));
       return MNL_CB_ERROR;
     }
     ts = mnl_attr_get_payload(attr);
@@ -666,7 +674,9 @@ static int ir_read(void) {
     ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
   }
   if (ret < 0) {
-    ERROR("netlink plugin: ir_read: mnl_socket_recvfrom failed.");
+    char errbuf[1024];
+    ERROR("netlink plugin: ir_read: mnl_socket_recvfrom failed: %s",
+          sstrerror(errno, errbuf, sizeof(errbuf)));
     return (-1);
   }
 
@@ -711,10 +721,11 @@ static int ir_read(void) {
         ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
       }
       if (ret < 0) {
-        ERROR("netlink plugin: ir_read:mnl_socket_recvfrom failed.");
+        char errbuf[1024];
+        ERROR("netlink plugin: ir_read: mnl_socket_recvfrom failed: %s",
+              sstrerror(errno, errbuf, sizeof(errbuf)));
         continue;
       }
-
     } /* for (type_index) */
   }   /* for (if_index) */
 
index 8eab08b..e28316d 100644 (file)
@@ -1003,14 +1003,6 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */
   buffer_len = *ret_buffer_len;
   buffer_offset = 0;
 
-  if (se->data.server.userdb == NULL) {
-    c_complain(
-        LOG_NOTICE, &complain_no_users,
-        "network plugin: Received signed network packet but can't verify it "
-        "because no user DB has been configured. Will accept it.");
-    return (0);
-  }
-
   /* Check if the buffer has enough data for this structure. */
   if (buffer_len <= PART_SIGNATURE_SHA256_SIZE)
     return (-ENOMEM);
@@ -1027,6 +1019,18 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */
     return (-1);
   }
 
+  if (se->data.server.userdb == NULL) {
+    c_complain(
+        LOG_NOTICE, &complain_no_users,
+        "network plugin: Received signed network packet but can't verify it "
+        "because no user DB has been configured. Will accept it.");
+
+    *ret_buffer = buffer + pss_head_length;
+    *ret_buffer_len -= pss_head_length;
+
+    return (0);
+  }
+
   /* Copy the hash. */
   BUFFER_READ(pss.hash, sizeof(pss.hash));
 
@@ -1226,9 +1230,9 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */
                             part_size - buffer_offset,
                             /* in = */ NULL, /* in len = */ 0);
   if (err != 0) {
-    sfree(pea.username);
     ERROR("network plugin: gcry_cipher_decrypt returned: %s. Username: %s",
           gcry_strerror(err), pea.username);
+    sfree(pea.username);
     return (-1);
   }
 
@@ -1250,8 +1254,6 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */
   parse_packet(se, buffer + buffer_offset, payload_len, flags | PP_ENCRYPTED,
                pea.username);
 
-  /* XXX: Free pea.username?!? */
-
   /* Update return values */
   *ret_buffer = buffer + part_size;
   *ret_buffer_len = buffer_len - part_size;
index ffc545c..060eae2 100644 (file)
@@ -133,10 +133,6 @@ static int init(void) {
 #endif
   }
 
-  if (url != NULL) {
-    curl_easy_setopt(curl, CURLOPT_URL, url);
-  }
-
   curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
   curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
 
@@ -207,6 +203,9 @@ static int nginx_read(void) {
     return (-1);
 
   nginx_buffer_len = 0;
+
+  curl_easy_setopt(curl, CURLOPT_URL, url);
+
   if (curl_easy_perform(curl) != CURLE_OK) {
     WARNING("nginx plugin: curl_easy_perform failed: %s", nginx_curl_error);
     return (-1);
index 1dc1857..bc81cdd 100644 (file)
@@ -850,9 +850,9 @@ static int ntpd_read(void) {
   }
 
   /* kerninfo -> estimated error */
-  offset_loop = scale_loop * ((gauge_t)ntohl(ik->offset));
+  offset_loop = (gauge_t)((int32_t)ntohl(ik->offset) * scale_loop);
   freq_loop = ntpd_read_fp(ik->freq);
-  offset_error = scale_error * ((gauge_t)ntohl(ik->esterror));
+  offset_error = (gauge_t)((int32_t)ntohl(ik->esterror) * scale_error);
 
   DEBUG("info_kernel:\n"
         "  pll offset    = %.8g\n"
index 5269e5f..50757db 100644 (file)
@@ -92,7 +92,8 @@ static int cldap_init_host(cldap_t *st) /* {{{ */
   if (rc != LDAP_SUCCESS) {
     ERROR("openldap plugin: ldap_initialize failed: %s", ldap_err2string(rc));
     st->state = 0;
-    ldap_unbind_ext_s(ld, NULL, NULL);
+    if (ld != NULL)
+      ldap_unbind_ext_s(ld, NULL, NULL);
     return (-1);
   }
 
@@ -119,7 +120,8 @@ static int cldap_init_host(cldap_t *st) /* {{{ */
       ERROR("openldap plugin: Failed to start tls on %s: %s", st->url,
             ldap_err2string(rc));
       st->state = 0;
-      ldap_unbind_ext_s(st->ld, NULL, NULL);
+      if (st->ld != NULL)
+        ldap_unbind_ext_s(st->ld, NULL, NULL);
       return (-1);
     }
   }
@@ -139,7 +141,8 @@ static int cldap_init_host(cldap_t *st) /* {{{ */
     ERROR("openldap plugin: Failed to bind to %s: %s", st->url,
           ldap_err2string(rc));
     st->state = 0;
-    ldap_unbind_ext_s(st->ld, NULL, NULL);
+    if (st->ld != NULL)
+      ldap_unbind_ext_s(st->ld, NULL, NULL);
     return (-1);
   } else {
     DEBUG("openldap plugin: Successfully connected to %s", st->url);
@@ -214,7 +217,8 @@ static int cldap_read_host(user_data_t *ud) /* {{{ */
     ERROR("openldap plugin: Failed to execute search: %s", ldap_err2string(rc));
     ldap_msgfree(result);
     st->state = 0;
-    ldap_unbind_ext_s(st->ld, NULL, NULL);
+    if (st->ld != NULL)
+      ldap_unbind_ext_s(st->ld, NULL, NULL);
     return (-1);
   }
 
index 5910913..b39250f 100644 (file)
@@ -496,16 +496,16 @@ static int av2data_set(pTHX_ AV *array, char *name, data_set_t *ds) {
  *   meta     => [ { name => <name>, value => <value> }, ... ]
  * }
  */
-static int av2notification_meta(pTHX_ AV *array, notification_meta_t **meta) {
-  notification_meta_t **m = meta;
+static int av2notification_meta(pTHX_ AV *array,
+                                notification_meta_t **ret_meta) {
+  notification_meta_t *tail = NULL;
 
   int len = av_len(array);
 
   for (int i = 0; i <= len; ++i) {
     SV **tmp = av_fetch(array, i, 0);
-    HV *hash;
 
-    if (NULL == tmp)
+    if (tmp == NULL)
       return -1;
 
     if (!(SvROK(*tmp) && (SVt_PVHV == SvTYPE(SvRV(*tmp))))) {
@@ -514,42 +514,51 @@ static int av2notification_meta(pTHX_ AV *array, notification_meta_t **meta) {
       continue;
     }
 
-    hash = (HV *)SvRV(*tmp);
+    HV *hash = (HV *)SvRV(*tmp);
 
-    *m = smalloc(sizeof(**m));
+    notification_meta_t *m = calloc(1, sizeof(*m));
+    if (m == NULL)
+      return ENOMEM;
 
-    if (NULL == (tmp = hv_fetch(hash, "name", 4, 0))) {
+    SV **name = hv_fetch(hash, "name", strlen("name"), 0);
+    if (name == NULL) {
       log_warn("av2notification_meta: Skipping invalid "
                "meta information.");
-      free(*m);
+      sfree(m);
       continue;
     }
-    sstrncpy((*m)->name, SvPV_nolen(*tmp), sizeof((*m)->name));
+    sstrncpy(m->name, SvPV_nolen(*name), sizeof(m->name));
 
-    if (NULL == (tmp = hv_fetch(hash, "value", 5, 0))) {
+    SV **value = hv_fetch(hash, "value", strlen("value"), 0);
+    if (value == NULL) {
       log_warn("av2notification_meta: Skipping invalid "
                "meta information.");
-      free(*m);
+      sfree(m);
       continue;
     }
 
-    if (SvNOK(*tmp)) {
-      (*m)->nm_value.nm_double = SvNVX(*tmp);
-      (*m)->type = NM_TYPE_DOUBLE;
-    } else if (SvUOK(*tmp)) {
-      (*m)->nm_value.nm_unsigned_int = SvUVX(*tmp);
-      (*m)->type = NM_TYPE_UNSIGNED_INT;
-    } else if (SvIOK(*tmp)) {
-      (*m)->nm_value.nm_signed_int = SvIVX(*tmp);
-      (*m)->type = NM_TYPE_SIGNED_INT;
+    if (SvNOK(*value)) {
+      m->nm_value.nm_double = SvNVX(*value);
+      m->type = NM_TYPE_DOUBLE;
+    } else if (SvUOK(*value)) {
+      m->nm_value.nm_unsigned_int = SvUVX(*value);
+      m->type = NM_TYPE_UNSIGNED_INT;
+    } else if (SvIOK(*value)) {
+      m->nm_value.nm_signed_int = SvIVX(*value);
+      m->type = NM_TYPE_SIGNED_INT;
     } else {
-      (*m)->nm_value.nm_string = sstrdup(SvPV_nolen(*tmp));
-      (*m)->type = NM_TYPE_STRING;
+      m->nm_value.nm_string = sstrdup(SvPV_nolen(*value));
+      m->type = NM_TYPE_STRING;
     }
 
-    (*m)->next = NULL;
-    m = &((*m)->next);
+    m->next = NULL;
+    if (tail == NULL)
+      *ret_meta = m;
+    else
+      tail->next = m;
+    tail = m;
   }
+
   return 0;
 } /* static int av2notification_meta (AV *, notification_meta_t *) */
 
@@ -707,10 +716,8 @@ static int value_list2hv(pTHX_ value_list_t *vl, data_set_t *ds, HV *hash) {
 
 static int notification_meta2av(pTHX_ notification_meta_t *meta, AV *array) {
   int meta_num = 0;
-
-  while (meta) {
+  for (notification_meta_t *m = meta; m != NULL; m = m->next) {
     ++meta_num;
-    meta = meta->next;
   }
 
   av_extend(array, meta_num);
@@ -2343,14 +2350,25 @@ static int g_interval_set(pTHX_ SV *var, MAGIC *mg) {
   return 0;
 } /* static int g_interval_set (pTHX_ SV *, MAGIC *) */
 
-static MGVTBL g_pv_vtbl = {g_pv_get, g_pv_set, NULL, NULL, NULL, NULL, NULL
+static MGVTBL g_pv_vtbl = {g_pv_get,
+                           g_pv_set,
+                           NULL,
+                           NULL,
+                           NULL,
+                           NULL,
+                           NULL
 #if HAVE_PERL_STRUCT_MGVTBL_SVT_LOCAL
                            ,
                            NULL
 #endif
 };
-static MGVTBL g_interval_vtbl = {g_interval_get, g_interval_set, NULL, NULL,
-                                 NULL, NULL, NULL
+static MGVTBL g_interval_vtbl = {g_interval_get,
+                                 g_interval_set,
+                                 NULL,
+                                 NULL,
+                                 NULL,
+                                 NULL,
+                                 NULL
 #if HAVE_PERL_STRUCT_MGVTBL_SVT_LOCAL
                                  ,
                                  NULL
@@ -2610,6 +2628,12 @@ static int perl_config_plugin(pTHX_ oconfig_item_t *ci) {
   char *plugin;
   HV *config;
 
+  if (NULL == perl_threads) {
+    log_err("A `Plugin' block was encountered but no plugin was loaded yet. "
+            "Put the appropriate `LoadPlugin' option in front of it.");
+    return -1;
+  }
+
   dSP;
 
   if ((1 != ci->values_num) || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
index 82de59f..03dea6d 100644 (file)
@@ -81,11 +81,11 @@ static double ping_interval = 1.0;
 static double ping_timeout = 0.9;
 static int ping_max_missed = -1;
 
+static pthread_mutex_t ping_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t ping_cond = PTHREAD_COND_INITIALIZER;
 static int ping_thread_loop = 0;
 static int ping_thread_error = 0;
 static pthread_t ping_thread_id;
-static pthread_mutex_t ping_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t ping_cond = PTHREAD_COND_INITIALIZER;
 
 static const char *config_keys[] = {"Host",    "SourceAddress",
 #ifdef HAVE_OPING_1_3
@@ -224,8 +224,6 @@ static int ping_dispatch_all(pingobj_t *pingobj) /* {{{ */
 
 static void *ping_thread(void *arg) /* {{{ */
 {
-  pingobj_t *pingobj = NULL;
-
   struct timeval tv_begin;
   struct timeval tv_end;
   struct timespec ts_wait;
@@ -235,11 +233,10 @@ static void *ping_thread(void *arg) /* {{{ */
 
   c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
 
-  pthread_mutex_lock(&ping_lock);
-
-  pingobj = ping_construct();
+  pingobj_t *pingobj = ping_construct();
   if (pingobj == NULL) {
     ERROR("ping plugin: ping_construct failed.");
+    pthread_mutex_lock(&ping_lock);
     ping_thread_error = 1;
     pthread_mutex_unlock(&ping_lock);
     return ((void *)-1);
@@ -276,6 +273,7 @@ static void *ping_thread(void *arg) /* {{{ */
 
   if (count == 0) {
     ERROR("ping plugin: No host could be added to ping object. Giving up.");
+    pthread_mutex_lock(&ping_lock);
     ping_thread_error = 1;
     pthread_mutex_unlock(&ping_lock);
     return ((void *)-1);
@@ -291,8 +289,8 @@ static void *ping_thread(void *arg) /* {{{ */
     ts_int.tv_nsec = (long)(temp_nsec * 1000000000L);
   }
 
+  pthread_mutex_lock(&ping_lock);
   while (ping_thread_loop > 0) {
-    int status;
     _Bool send_successful = 0;
 
     if (gettimeofday(&tv_begin, NULL) < 0) {
@@ -305,7 +303,7 @@ static void *ping_thread(void *arg) /* {{{ */
 
     pthread_mutex_unlock(&ping_lock);
 
-    status = ping_send(pingobj);
+    int status = ping_send(pingobj);
     if (status < 0) {
       c_complain(LOG_ERR, &complaint, "ping plugin: ping_send failed: %s",
                  ping_get_error(pingobj));
index 0aac41e..5079901 100644 (file)
@@ -38,9 +38,9 @@
 </Query>
 
 <Query queries>
-       Statement "SELECT sum(n_tup_ins) AS ins, \
-                       sum(n_tup_upd) AS upd, \
-                       sum(n_tup_del) AS del \
+       Statement "SELECT coalesce(sum(n_tup_ins), 0) AS ins, \
+                       coalesce(sum(n_tup_upd), 0) AS upd, \
+                       coalesce(sum(n_tup_del), 0) AS del \
                FROM pg_stat_user_tables;"
 
        <Result>
 </Query>
 
 <Query queries>
-       Statement "SELECT sum(n_tup_ins) AS ins, \
-                       sum(n_tup_upd) AS upd, \
-                       sum(n_tup_del) AS del, \
-                       sum(n_tup_hot_upd) AS hot_upd \
+       Statement "SELECT coalesce(sum(n_tup_ins), 0) AS ins, \
+                       coalesce(sum(n_tup_upd), 0) AS upd, \
+                       coalesce(sum(n_tup_del), 0) AS del, \
+                       coalesce(sum(n_tup_hot_upd), 0) AS hot_upd \
                FROM pg_stat_user_tables;"
 
        <Result>
 </Query>
 
 <Query table_states>
-       Statement "SELECT sum(n_live_tup) AS live, sum(n_dead_tup) AS dead \
+       Statement "SELECT coalesce(sum(n_live_tup), 0) AS live, \
+               coalesce(sum(n_dead_tup), 0) AS dead \
                FROM pg_stat_user_tables;"
 
        <Result>
index f2149ef..da72ec8 100644 (file)
@@ -379,8 +379,8 @@ static void submit(const char *plugin_instance, /* {{{ */
   plugin_dispatch_values(&vl);
 } /* }}} static void submit */
 
-static int powerdns_get_data_dgram(list_item_t *item, /* {{{ */
-                                   char **ret_buffer, size_t *ret_buffer_size) {
+static int powerdns_get_data_dgram(list_item_t *item, char **ret_buffer) {
+  /* {{{ */
   int sd;
   int status;
 
@@ -478,14 +478,11 @@ static int powerdns_get_data_dgram(list_item_t *item, /* {{{ */
   buffer[buffer_size - 1] = 0;
 
   *ret_buffer = buffer;
-  *ret_buffer_size = buffer_size;
-
   return (0);
 } /* }}} int powerdns_get_data_dgram */
 
-static int powerdns_get_data_stream(list_item_t *item, /* {{{ */
-                                    char **ret_buffer,
-                                    size_t *ret_buffer_size) {
+static int powerdns_get_data_stream(list_item_t *item, char **ret_buffer) {
+  /* {{{ */
   int sd;
   int status;
 
@@ -533,13 +530,14 @@ static int powerdns_get_data_stream(list_item_t *item, /* {{{ */
     if (status < 0) {
       SOCK_ERROR("recv", item->sockaddr.sun_path);
       break;
-    } else if (status == 0)
+    } else if (status == 0) {
       break;
+    }
 
     buffer_new = realloc(buffer, buffer_size + status + 1);
     if (buffer_new == NULL) {
       FUNC_ERROR("realloc");
-      status = -1;
+      status = ENOMEM;
       break;
     }
     buffer = buffer_new;
@@ -550,23 +548,20 @@ static int powerdns_get_data_stream(list_item_t *item, /* {{{ */
   } /* while (42) */
   close(sd);
 
-  if (status < 0) {
+  if (status != 0) {
     sfree(buffer);
-  } else {
-    assert(status == 0);
-    *ret_buffer = buffer;
-    *ret_buffer_size = buffer_size;
+    return status;
   }
 
-  return (status);
+  *ret_buffer = buffer;
+  return 0;
 } /* }}} int powerdns_get_data_stream */
 
-static int powerdns_get_data(list_item_t *item, char **ret_buffer,
-                             size_t *ret_buffer_size) {
+static int powerdns_get_data(list_item_t *item, char **ret_buffer) {
   if (item->socktype == SOCK_DGRAM)
-    return (powerdns_get_data_dgram(item, ret_buffer, ret_buffer_size));
+    return (powerdns_get_data_dgram(item, ret_buffer));
   else if (item->socktype == SOCK_STREAM)
-    return (powerdns_get_data_stream(item, ret_buffer, ret_buffer_size));
+    return (powerdns_get_data_stream(item, ret_buffer));
   else {
     ERROR("powerdns plugin: Unknown socket type: %i", (int)item->socktype);
     return (-1);
@@ -575,19 +570,6 @@ static int powerdns_get_data(list_item_t *item, char **ret_buffer,
 
 static int powerdns_read_server(list_item_t *item) /* {{{ */
 {
-  char *buffer = NULL;
-  size_t buffer_size = 0;
-  int status;
-
-  char *dummy;
-  char *saveptr;
-
-  char *key;
-  char *value;
-
-  const char *const *fields;
-  int fields_num;
-
   if (item->command == NULL)
     item->command = strdup(SERVER_COMMAND);
   if (item->command == NULL) {
@@ -595,16 +577,21 @@ static int powerdns_read_server(list_item_t *item) /* {{{ */
     return (-1);
   }
 
-  status = powerdns_get_data(item, &buffer, &buffer_size);
-  if (status != 0)
-    return (-1);
+  char *buffer = NULL;
+  int status = powerdns_get_data(item, &buffer);
+  if (status != 0) {
+    ERROR("powerdns plugin: powerdns_get_data failed.");
+    return (status);
+  }
+  if (buffer == NULL) {
+    return EINVAL;
+  }
 
+  const char *const *fields = default_server_fields;
+  int fields_num = default_server_fields_num;
   if (item->fields_num != 0) {
     fields = (const char *const *)item->fields;
     fields_num = item->fields_num;
-  } else {
-    fields = default_server_fields;
-    fields_num = default_server_fields_num;
   }
 
   assert(fields != NULL);
@@ -612,12 +599,13 @@ static int powerdns_read_server(list_item_t *item) /* {{{ */
 
   /* corrupt-packets=0,deferred-cache-inserts=0,deferred-cache-lookup=0,latency=0,packetcache-hit=0,packetcache-miss=0,packetcache-size=0,qsize-q=0,query-cache-hit=0,query-cache-miss=0,recursing-answers=0,recursing-questions=0,servfail-packets=0,tcp-answers=0,tcp-queries=0,timedout-packets=0,udp-answers=0,udp-queries=0,udp4-answers=0,udp4-queries=0,udp6-answers=0,udp6-queries=0,
    */
-  dummy = buffer;
-  saveptr = NULL;
+  char *dummy = buffer;
+  char *saveptr = NULL;
+  char *key;
   while ((key = strtok_r(dummy, ",", &saveptr)) != NULL) {
     dummy = NULL;
 
-    value = strchr(key, '=');
+    char *value = strchr(key, '=');
     if (value == NULL)
       break;
 
@@ -691,7 +679,6 @@ static int powerdns_update_recursor_command(list_item_t *li) /* {{{ */
 static int powerdns_read_recursor(list_item_t *item) /* {{{ */
 {
   char *buffer = NULL;
-  size_t buffer_size = 0;
   int status;
 
   char *dummy;
@@ -714,7 +701,7 @@ static int powerdns_read_recursor(list_item_t *item) /* {{{ */
   }
   assert(item->command != NULL);
 
-  status = powerdns_get_data(item, &buffer, &buffer_size);
+  status = powerdns_get_data(item, &buffer);
   if (status != 0) {
     ERROR("powerdns plugin: powerdns_get_data failed.");
     return (-1);
index 86f690f..87c96c8 100644 (file)
@@ -2127,7 +2127,6 @@ static int ps_read(void) {
       pse.cpu_user_counter = procentry[i].pi_ru.ru_utime.tv_sec * 1000000 +
                              procentry[i].pi_ru.ru_utime.tv_usec / 1000;
 
-      pse.cpu_system = 0;
       /* tv_usec is nanosec ??? */
       pse.cpu_system_counter = procentry[i].pi_ru.ru_stime.tv_sec * 1000000 +
                                procentry[i].pi_ru.ru_stime.tv_usec / 1000;
index e29d637..4fcbad4 100644 (file)
@@ -87,7 +87,7 @@ static rrdcreate_config_t rrdcreate_config = {
  * ALWAYS lock `cache_lock' first! */
 static cdtime_t cache_timeout = 0;
 static cdtime_t cache_flush_timeout = 0;
-static cdtime_t random_timeout = TIME_T_TO_CDTIME_T_STATIC(1);
+static cdtime_t random_timeout = 0;
 static cdtime_t cache_flush_last;
 static c_avl_tree_t *cache = NULL;
 static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -505,7 +505,6 @@ static void rrd_cache_flush(cdtime_t timeout) {
         CDTIME_T_TO_DOUBLE(timeout));
 
   now = cdtime();
-  timeout = TIME_T_TO_CDTIME_T(timeout);
 
   /* Build a list of entries to be flushed */
   iter = c_avl_get_iterator(cache);
@@ -606,23 +605,10 @@ static int rrd_cache_flush_identifier(cdtime_t timeout,
 } /* int rrd_cache_flush_identifier */
 
 static int64_t rrd_get_random_variation(void) {
-  long min;
-  long max;
-
   if (random_timeout == 0)
     return (0);
 
-  /* Assure that "cache_timeout + random_variation" is never negative. */
-  if (random_timeout > cache_timeout) {
-    INFO("rrdtool plugin: Adjusting \"RandomTimeout\" to %.3f seconds.",
-         CDTIME_T_TO_DOUBLE(cache_timeout));
-    random_timeout = cache_timeout;
-  }
-
-  max = (long)(random_timeout / 2);
-  min = max - ((long)random_timeout);
-
-  return ((int64_t)cdrand_range(min, max));
+  return (int64_t)cdrand_range(-random_timeout, random_timeout);
 } /* int64_t rrd_get_random_variation */
 
 static int rrd_cache_insert(const char *filename, const char *value,
@@ -641,9 +627,8 @@ static int rrd_cache_insert(const char *filename, const char *value,
     return (-1);
   }
 
-  c_avl_get(cache, filename, (void *)&rc);
-
-  if (rc == NULL) {
+  int status = c_avl_get(cache, filename, (void *)&rc);
+  if ((status != 0) || (rc == NULL)) {
     rc = malloc(sizeof(*rc));
     if (rc == NULL) {
       pthread_mutex_unlock(&cache_lock);
@@ -740,7 +725,7 @@ static int rrd_cache_insert(const char *filename, const char *value,
 
   if ((cache_timeout > 0) &&
       ((cdtime() - cache_flush_last) > cache_flush_timeout))
-    rrd_cache_flush(cache_flush_timeout);
+    rrd_cache_flush(cache_timeout + random_timeout);
 
   pthread_mutex_unlock(&cache_lock);
 
@@ -877,7 +862,7 @@ static int rrd_config(const char *key, const char *value) {
     }
     cache_timeout = DOUBLE_TO_CDTIME_T(tmp);
   } else if (strcasecmp("CacheFlush", key) == 0) {
-    int tmp = atoi(value);
+    double tmp = atof(value);
     if (tmp < 0) {
       fprintf(stderr, "rrdtool: `CacheFlush' must "
                       "be greater than 0.\n");
@@ -885,7 +870,7 @@ static int rrd_config(const char *key, const char *value) {
             "be greater than 0.\n");
       return (1);
     }
-    cache_flush_timeout = tmp;
+    cache_flush_timeout = DOUBLE_TO_CDTIME_T(tmp);
   } else if (strcasecmp("DataDir", key) == 0) {
     char *tmp;
     size_t len;
@@ -1065,9 +1050,23 @@ static int rrd_init(void) {
 
   cache_flush_last = cdtime();
   if (cache_timeout == 0) {
+    random_timeout = 0;
     cache_flush_timeout = 0;
-  } else if (cache_flush_timeout < cache_timeout)
+  } else if (cache_flush_timeout < cache_timeout) {
+    INFO("rrdtool plugin: \"CacheFlush %.3f\" is less than \"CacheTimeout "
+         "%.3f\". Adjusting \"CacheFlush\" to %.3f seconds.",
+         CDTIME_T_TO_DOUBLE(cache_flush_timeout),
+         CDTIME_T_TO_DOUBLE(cache_timeout),
+         CDTIME_T_TO_DOUBLE(cache_timeout * 10));
     cache_flush_timeout = 10 * cache_timeout;
+  }
+
+  /* Assure that "cache_timeout + random_variation" is never negative. */
+  if (random_timeout > cache_timeout) {
+    INFO("rrdtool plugin: Adjusting \"RandomTimeout\" to %.3f seconds.",
+         CDTIME_T_TO_DOUBLE(cache_timeout));
+    random_timeout = cache_timeout;
+  }
 
   pthread_mutex_unlock(&cache_lock);
 
index 9395945..3188d1c 100644 (file)
 #include <atasmart.h>
 #include <libudev.h>
 
+#ifdef HAVE_SYS_CAPABILITY_H
+#include <sys/capability.h>
+#endif
+
 static const char *config_keys[] = {"Disk", "IgnoreSelected", "IgnoreSleepMode",
                                     "UseSerial"};
 
@@ -238,7 +242,25 @@ static int smart_read(void) {
   return (0);
 } /* int smart_read */
 
+static int smart_init(void) {
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_RAWIO)
+  if (check_capability(CAP_SYS_RAWIO) != 0) {
+    if (getuid() == 0)
+      WARNING("smart plugin: Running collectd as root, but the "
+              "CAP_SYS_RAWIO capability is missing. The plugin's read "
+              "function will probably fail. Is your init system dropping "
+              "capabilities?");
+    else
+      WARNING("smart plugin: collectd doesn't have the CAP_SYS_RAWIO "
+              "capability. If you don't want to run collectd as root, try "
+              "running \"setcap cap_sys_rawio=ep\" on the collectd binary.");
+  }
+#endif
+  return (0);
+} /* int smart_init */
+
 void module_register(void) {
   plugin_register_config("smart", smart_config, config_keys, config_keys_num);
+  plugin_register_init("smart", smart_init);
   plugin_register_read("smart", smart_read);
 } /* void module_register */
index 3bfec47..ffeface 100644 (file)
@@ -1357,12 +1357,17 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) {
     if (oid_list_todo_num == 0) {
       /* The request is still empty - so we are finished */
       DEBUG("snmp plugin: all variables have left their subtree");
+      snmp_free_pdu(req);
       status = 0;
       break;
     }
 
     res = NULL;
     status = snmp_sess_synch_response(host->sess_handle, req, &res);
+
+    /* snmp_sess_synch_response always frees our req PDU */
+    req = NULL;
+
     if ((status != STAT_SUCCESS) || (res == NULL)) {
       char *errstr = NULL;
 
@@ -1376,8 +1381,6 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) {
         snmp_free_pdu(res);
       res = NULL;
 
-      /* snmp_synch_response already freed our PDU */
-      req = NULL;
       sfree(errstr);
       csnmp_host_close_session(host);
 
@@ -1400,8 +1403,12 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) {
     for (vb = res->variables, i = 0; (vb != NULL);
          vb = vb->next_variable, i++) {
       /* Calculate value index from todo list */
-      while ((i < oid_list_len) && !oid_list_todo[i])
+      while ((i < oid_list_len) && !oid_list_todo[i]) {
         i++;
+      }
+      if (i >= oid_list_len) {
+        break;
+      }
 
       /* An instance is configured and the res variable we process is the
        * instance value (last index) */
@@ -1492,10 +1499,6 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) {
     snmp_free_pdu(res);
   res = NULL;
 
-  if (req != NULL)
-    snmp_free_pdu(req);
-  req = NULL;
-
   if (status == 0)
     csnmp_dispatch_table(host, data, instance_list_head, value_list_head);
 
index 3e8fead..eb18660 100644 (file)
@@ -77,6 +77,10 @@ static void tbl_result_setup(tbl_result_t *res) {
 } /* tbl_result_setup */
 
 static void tbl_result_clear(tbl_result_t *res) {
+  if (res == NULL) {
+    return;
+  }
+
   sfree(res->type);
 
   sfree(res->instance_prefix);
@@ -101,10 +105,16 @@ static void tbl_setup(tbl_t *tbl, char *file) {
 } /* tbl_setup */
 
 static void tbl_clear(tbl_t *tbl) {
+  if (tbl == NULL) {
+    return;
+  }
+
   sfree(tbl->file);
   sfree(tbl->sep);
   sfree(tbl->instance);
 
+  /* (tbl->results == NULL) -> (tbl->results_num == 0) */
+  assert((tbl->results != NULL) || (tbl->results_num == 0));
   for (size_t i = 0; i < tbl->results_num; ++i)
     tbl_result_clear(tbl->results + i);
   sfree(tbl->results);
@@ -166,16 +176,13 @@ static int tbl_config_append_array_i(char *name, size_t **var, size_t *len,
 } /* tbl_config_append_array_s */
 
 static int tbl_config_result(tbl_t *tbl, oconfig_item_t *ci) {
-  tbl_result_t *res;
-
-  int status = 0;
-
   if (0 != ci->values_num) {
     log_err("<Result> does not expect any arguments.");
     return 1;
   }
 
-  res = realloc(tbl->results, (tbl->results_num + 1) * sizeof(*tbl->results));
+  tbl_result_t *res =
+      realloc(tbl->results, (tbl->results_num + 1) * sizeof(*tbl->results));
   if (res == NULL) {
     char errbuf[1024];
     log_err("realloc failed: %s.", sstrerror(errno, errbuf, sizeof(errbuf)));
@@ -183,9 +190,8 @@ static int tbl_config_result(tbl_t *tbl, oconfig_item_t *ci) {
   }
 
   tbl->results = res;
-  ++tbl->results_num;
 
-  res = tbl->results + tbl->results_num - 1;
+  res = tbl->results + tbl->results_num;
   tbl_result_setup(res);
 
   for (int i = 0; i < ci->children_num; ++i) {
@@ -206,39 +212,35 @@ static int tbl_config_result(tbl_t *tbl, oconfig_item_t *ci) {
                c->key);
   }
 
+  int status = 0;
   if (NULL == res->type) {
-    log_err("No \"Type\" option specified for <Result> "
-            "in table \"%s\".",
+    log_err("No \"Type\" option specified for <Result> in table \"%s\".",
             tbl->file);
     status = 1;
   }
 
   if (NULL == res->values) {
-    log_err("No \"ValuesFrom\" option specified for <Result> "
-            "in table \"%s\".",
+    log_err("No \"ValuesFrom\" option specified for <Result> in table \"%s\".",
             tbl->file);
     status = 1;
   }
 
   if (0 != status) {
     tbl_result_clear(res);
-    --tbl->results_num;
     return status;
   }
+
+  tbl->results_num++;
   return 0;
 } /* tbl_config_result */
 
 static int tbl_config_table(oconfig_item_t *ci) {
-  tbl_t *tbl;
-
-  int status = 0;
-
   if ((1 != ci->values_num) || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
     log_err("<Table> expects a single string argument.");
     return 1;
   }
 
-  tbl = realloc(tables, (tables_num + 1) * sizeof(*tables));
+  tbl_t *tbl = realloc(tables, (tables_num + 1) * sizeof(*tables));
   if (NULL == tbl) {
     char errbuf[1024];
     log_err("realloc failed: %s.", sstrerror(errno, errbuf, sizeof(errbuf)));
@@ -246,9 +248,8 @@ static int tbl_config_table(oconfig_item_t *ci) {
   }
 
   tables = tbl;
-  ++tables_num;
 
-  tbl = tables + tables_num - 1;
+  tbl = tables + tables_num;
   tbl_setup(tbl, ci->values[0].value.string);
 
   for (size_t i = 0; i < ((size_t)ci->children_num); ++i) {
@@ -266,6 +267,7 @@ static int tbl_config_table(oconfig_item_t *ci) {
                c->key, tbl->file);
   }
 
+  int status = 0;
   if (NULL == tbl->sep) {
     log_err("Table \"%s\" does not specify any separator.", tbl->file);
     status = 1;
@@ -279,13 +281,13 @@ static int tbl_config_table(oconfig_item_t *ci) {
   }
 
   if (NULL == tbl->results) {
+    assert(tbl->results_num == 0);
     log_err("Table \"%s\" does not specify any (valid) results.", tbl->file);
     status = 1;
   }
 
   if (0 != status) {
     tbl_clear(tbl);
-    --tables_num;
     return status;
   }
 
@@ -300,6 +302,8 @@ static int tbl_config_table(oconfig_item_t *ci) {
       if (res->values[j] > tbl->max_colnum)
         tbl->max_colnum = res->values[j];
   }
+
+  tables_num++;
   return 0;
 } /* tbl_config_table */
 
index 5bf40fa..e7a3288 100644 (file)
@@ -183,9 +183,13 @@ static void ts_subst(char *dest, size_t size, const char *string, /* {{{ */
   REPLACE_FIELD("%{type_instance}", vl->type_instance);
 
   if (vl->meta != NULL) {
-    char **meta_toc;
-    int meta_entries = meta_data_toc(vl->meta, &meta_toc);
-    for (int i = 0; i < meta_entries; i++) {
+    char **meta_toc = NULL;
+    int status = meta_data_toc(vl->meta, &meta_toc);
+    if (status <= 0)
+      return;
+    size_t meta_entries = (size_t)status;
+
+    for (size_t i = 0; i < meta_entries; i++) {
       char meta_name[DATA_MAX_NAME_LEN];
       char *value_str;
       const char *key = meta_toc[i];
@@ -339,7 +343,6 @@ static int ts_invoke(const data_set_t *ds, value_list_t *vl, /* {{{ */
 
   if (data->meta != NULL) {
     char temp[DATA_MAX_NAME_LEN * 2];
-    int meta_entries;
     char **meta_toc;
 
     if ((new_meta = meta_data_create()) == NULL) {
@@ -347,8 +350,15 @@ static int ts_invoke(const data_set_t *ds, value_list_t *vl, /* {{{ */
       return (-ENOMEM);
     }
 
-    meta_entries = meta_data_toc(data->meta, &meta_toc);
-    for (int i = 0; i < meta_entries; i++) {
+    int status = meta_data_toc(data->meta, &meta_toc);
+    if (status < 0) {
+      ERROR("Target `set': meta_data_toc failed with status %d.", status);
+      meta_data_destroy(new_meta);
+      return status;
+    }
+    size_t meta_entries = (size_t)status;
+
+    for (size_t i = 0; i < meta_entries; i++) {
       const char *key = meta_toc[i];
       char *string;
       int status;
@@ -357,7 +367,8 @@ static int ts_invoke(const data_set_t *ds, value_list_t *vl, /* {{{ */
       if (status) {
         ERROR("Target `set': Unable to get replacement metadata value `%s'.",
               key);
-        strarray_free(meta_toc, (size_t)meta_entries);
+        strarray_free(meta_toc, meta_entries);
+        meta_data_destroy(new_meta);
         return (status);
       }
 
@@ -372,12 +383,13 @@ static int ts_invoke(const data_set_t *ds, value_list_t *vl, /* {{{ */
       status = meta_data_add_string(new_meta, key, temp);
       if (status) {
         ERROR("Target `set': Unable to set metadata value `%s'.", key);
-        strarray_free(meta_toc, (size_t)meta_entries);
+        strarray_free(meta_toc, meta_entries);
+        meta_data_destroy(new_meta);
         return (status);
       }
     }
 
-    strarray_free(meta_toc, (size_t)meta_entries);
+    strarray_free(meta_toc, meta_entries);
   }
 
 #define SUBST_FIELD(f)                                                         \
index f949d34..7036d08 100644 (file)
@@ -745,9 +745,15 @@ static int conn_read(void) {
   for (in_ptr = (struct xinpgen *)(((char *)in_orig) + in_orig->xig_len);
        in_ptr->xig_len > sizeof(struct xinpgen);
        in_ptr = (struct xinpgen *)(((char *)in_ptr) + in_ptr->xig_len)) {
+#if __FreeBSD_version >= 1200026
+    struct xtcpcb *tp = (struct xtcpcb *)in_ptr;
+    struct xinpcb *inp = &tp->xt_inp;
+    struct xsocket *so = &inp->xi_socket;
+#else
     struct tcpcb *tp = &((struct xtcpcb *)in_ptr)->xt_tp;
     struct inpcb *inp = &((struct xtcpcb *)in_ptr)->xt_inp;
     struct xsocket *so = &((struct xtcpcb *)in_ptr)->xt_socket;
+#endif
 
     /* Ignore non-TCP sockets */
     if (so->xso_protocol != IPPROTO_TCP)
index 62bd92b..568fb1e 100644 (file)
@@ -41,7 +41,7 @@
 #include "plugin.h"
 #include "utils_time.h"
 
-#include <asm/msr-index.h>
+#include "msr-index.h"
 #include <cpuid.h>
 #ifdef HAVE_SYS_CAPABILITY_H
 #include <sys/capability.h>
@@ -567,9 +567,9 @@ static int submit_counters(struct thread_data *t, struct core_data *c,
                    1.0 / 1000000 * t->aperf / interval_float);
 
   if ((!aperf_mperf_unstable) || (!(t->aperf > t->tsc || t->mperf > t->tsc)))
-    turbostat_submit(name, "frequency", "busy", 1.0 * t->tsc / 1000000 *
-                                                    t->aperf / t->mperf /
-                                                    interval_float);
+    turbostat_submit(name, "frequency", "busy",
+                     1.0 * t->tsc / 1000000 * t->aperf / t->mperf /
+                         interval_float);
 
   /* Sanity check (should stay stable) */
   turbostat_submit(name, "gauge", "TSC",
index f61360e..a424568 100644 (file)
@@ -134,7 +134,13 @@ static int us_open_socket(void) {
     const char *grpname;
     struct group *g;
     struct group sg;
-    char grbuf[2048];
+
+    long int grbuf_size = sysconf(_SC_GETGR_R_SIZE_MAX);
+    if (grbuf_size <= 0)
+      grbuf_size = sysconf(_SC_PAGESIZE);
+    if (grbuf_size <= 0)
+      grbuf_size = 4096;
+    char grbuf[grbuf_size];
 
     grpname = (sock_group != NULL) ? sock_group : COLLECTD_GRP_NAME;
     g = NULL;
@@ -143,7 +149,7 @@ static int us_open_socket(void) {
     if (status != 0) {
       char errbuf[1024];
       WARNING("unixsock plugin: getgrnam_r (%s) failed: %s", grpname,
-              sstrerror(errno, errbuf, sizeof(errbuf)));
+              sstrerror(status, errbuf, sizeof(errbuf)));
       break;
     }
     if (g == NULL) {
index 60363da..926375d 100644 (file)
@@ -155,48 +155,31 @@ int handle_getthreshold(FILE *fh, char *buffer) {
   print_to_socket(fh, "%zu Threshold found\n", i);
 
   if (threshold.host[0] != 0)
-    print_to_socket(fh, "Host: %s\n", threshold.host) if (
-        threshold.plugin[0] !=
-        0) print_to_socket(fh, "Plugin: %s\n",
-                           threshold.plugin) if (threshold.plugin_instance[0] !=
-                                                 0)
-        print_to_socket(fh, "Plugin Instance: %s\n",
-                        threshold.plugin_instance) if (threshold.type[0] != 0)
-            print_to_socket(fh, "Type: %s\n", threshold.type) if (
-                threshold.type_instance[0] !=
-                0) print_to_socket(fh, "Type Instance: %s\n",
-                                   threshold
-                                       .type_instance) if (threshold.data_source
-                                                               [0] != 0)
-                print_to_socket(
-                    fh, "Data Source: %s\n",
-                    threshold.data_source) if (!isnan(threshold.warning_min))
-                    print_to_socket(
-                        fh, "Warning Min: %g\n",
-                        threshold
-                            .warning_min) if (!isnan(threshold.warning_max))
-                        print_to_socket(
-                            fh, "Warning Max: %g\n",
-                            threshold
-                                .warning_max) if (!isnan(threshold.failure_min))
-                            print_to_socket(
-                                fh, "Failure Min: %g\n",
-                                threshold
-                                    .failure_min) if (!isnan(threshold
-                                                                 .failure_max))
-                                print_to_socket(
-                                    fh, "Failure Max: %g\n",
-                                    threshold.failure_max) if (threshold
-                                                                   .hysteresis >
-                                                               0.0)
-                                    print_to_socket(
-                                        fh, "Hysteresis: %g\n",
-                                        threshold.hysteresis) if (threshold
-                                                                      .hits > 1)
-                                        print_to_socket(fh, "Hits: %i\n",
-                                                        threshold.hits)
-
-                                            return (0);
+    print_to_socket(fh, "Host: %s\n", threshold.host);
+  if (threshold.plugin[0] != 0)
+    print_to_socket(fh, "Plugin: %s\n", threshold.plugin);
+  if (threshold.plugin_instance[0] != 0)
+    print_to_socket(fh, "Plugin Instance: %s\n", threshold.plugin_instance);
+  if (threshold.type[0] != 0)
+    print_to_socket(fh, "Type: %s\n", threshold.type);
+  if (threshold.type_instance[0] != 0)
+    print_to_socket(fh, "Type Instance: %s\n", threshold.type_instance);
+  if (threshold.data_source[0] != 0)
+    print_to_socket(fh, "Data Source: %s\n", threshold.data_source);
+  if (!isnan(threshold.warning_min))
+    print_to_socket(fh, "Warning Min: %g\n", threshold.warning_min);
+  if (!isnan(threshold.warning_max))
+    print_to_socket(fh, "Warning Max: %g\n", threshold.warning_max);
+  if (!isnan(threshold.failure_min))
+    print_to_socket(fh, "Failure Min: %g\n", threshold.failure_min);
+  if (!isnan(threshold.failure_max))
+    print_to_socket(fh, "Failure Max: %g\n", threshold.failure_max);
+  if (threshold.hysteresis > 0.0)
+    print_to_socket(fh, "Hysteresis: %g\n", threshold.hysteresis);
+  if (threshold.hits > 1)
+    print_to_socket(fh, "Hits: %i\n", threshold.hits);
+
+  return (0);
 } /* int handle_getthreshold */
 
 /* vim: set sw=2 sts=2 ts=8 et : */
index 817f954..f1fe6d7 100644 (file)
@@ -138,14 +138,6 @@ cmd_status_t cmd_parse_putval(size_t argc, char **argv,
   type = NULL;
   type_instance = NULL;
 
-  vl.values_len = ds->ds_num;
-  vl.values = malloc(vl.values_len * sizeof(*vl.values));
-  if (vl.values == NULL) {
-    cmd_error(CMD_ERROR, err, "malloc failed.");
-    sfree(identifier_copy);
-    return (CMD_ERROR);
-  }
-
   ret_putval->raw_identifier = identifier_copy;
   if (ret_putval->raw_identifier == NULL) {
     cmd_error(CMD_ERROR, err, "malloc failed.");
@@ -177,33 +169,46 @@ cmd_status_t cmd_parse_putval(size_t argc, char **argv,
     /* else: cmd_parse_option did not find an option; treat this as a
      * value list. */
 
+    vl.values_len = ds->ds_num;
+    vl.values = calloc(vl.values_len, sizeof(*vl.values));
+    if (vl.values == NULL) {
+      cmd_error(CMD_ERROR, err, "malloc failed.");
+      result = CMD_ERROR;
+      break;
+    }
+
     status = parse_values(argv[i], &vl, ds);
     if (status != 0) {
       cmd_error(CMD_PARSE_ERROR, err, "Parsing the values string failed.");
       result = CMD_PARSE_ERROR;
+      vl.values_len = 0;
+      sfree(vl.values);
       break;
     }
 
-    tmp = (value_list_t *)realloc(ret_putval->vl, (ret_putval->vl_num + 1) *
-                                                      sizeof(*ret_putval->vl));
+    tmp = realloc(ret_putval->vl,
+                  (ret_putval->vl_num + 1) * sizeof(*ret_putval->vl));
     if (tmp == NULL) {
       cmd_error(CMD_ERROR, err, "realloc failed.");
       cmd_destroy_putval(ret_putval);
       result = CMD_ERROR;
+      vl.values_len = 0;
+      sfree(vl.values);
       break;
     }
 
     ret_putval->vl = tmp;
     ret_putval->vl_num++;
     memcpy(&ret_putval->vl[ret_putval->vl_num - 1], &vl, sizeof(vl));
+
+    /* pointer is now owned by ret_putval->vl[] */
+    vl.values_len = 0;
+    vl.values = NULL;
   } /* while (*buffer != 0) */
   /* Done parsing the options. */
 
-  if (result != CMD_OK) {
-    if (ret_putval->vl_num == 0)
-      sfree(vl.values);
+  if (result != CMD_OK)
     cmd_destroy_putval(ret_putval);
-  }
 
   return (result);
 } /* cmd_status_t cmd_parse_putval */
@@ -215,8 +220,7 @@ void cmd_destroy_putval(cmd_putval_t *putval) {
   sfree(putval->raw_identifier);
 
   for (size_t i = 0; i < putval->vl_num; ++i) {
-    if (i == 0) /* values is shared between all entries */
-      sfree(putval->vl[i].values);
+    sfree(putval->vl[i].values);
     meta_data_destroy(putval->vl[i].meta);
     putval->vl[i].meta = NULL;
   }
index 4f509f4..9c7d96f 100644 (file)
@@ -180,8 +180,13 @@ int format_graphite(char *buffer, size_t buffer_size, data_set_t const *ds,
   int buffer_pos = 0;
 
   gauge_t *rates = NULL;
-  if (flags & GRAPHITE_STORE_RATES)
+  if (flags & GRAPHITE_STORE_RATES) {
     rates = uc_get_rate(ds, vl);
+    if (rates == NULL) {
+      ERROR("format_graphite: error with uc_get_rate");
+      return -1;
+    }
+  }
 
   for (size_t i = 0; i < ds->ds_num; i++) {
     char const *ds_name = NULL;
index 0a95a86..9fb8f39 100644 (file)
@@ -500,6 +500,14 @@ static int json_add_string(yajl_gen g, char const *str) /* {{{ */
     }                                                                          \
   } while (0)
 
+#define CHECK_SUCCESS(cmd)                                                     \
+  do {                                                                         \
+    yajl_gen_status s = (cmd);                                                 \
+    if (s != yajl_gen_status_ok) {                                             \
+      return (int)s;                                                           \
+    }                                                                          \
+  } while (0)
+
 static int format_json_meta(yajl_gen g, notification_meta_t *meta) /* {{{ */
 {
   if (meta == NULL)
@@ -525,7 +533,7 @@ static int format_json_meta(yajl_gen g, notification_meta_t *meta) /* {{{ */
   default:
     ERROR("format_json_meta: unknown meta data type %d (name \"%s\")",
           meta->type, meta->name);
-    yajl_gen_null(g);
+    CHECK_SUCCESS(yajl_gen_null(g));
   }
 
   return format_json_meta(g, meta->next);
@@ -544,14 +552,14 @@ static int format_time(yajl_gen g, cdtime_t t) /* {{{ */
 
 static int format_alert(yajl_gen g, notification_t const *n) /* {{{ */
 {
-  yajl_gen_array_open(g);
-  yajl_gen_map_open(g); /* BEGIN alert */
+  CHECK_SUCCESS(yajl_gen_array_open(g)); /* BEGIN array */
+  CHECK_SUCCESS(yajl_gen_map_open(g));   /* BEGIN alert */
 
   /*
    * labels
    */
   JSON_ADD(g, "labels");
-  yajl_gen_map_open(g); /* BEGIN labels */
+  CHECK_SUCCESS(yajl_gen_map_open(g)); /* BEGIN labels */
 
   JSON_ADD(g, "alertname");
   if (strncmp(n->plugin, n->type, strlen(n->plugin)) == 0)
@@ -577,36 +585,40 @@ static int format_alert(yajl_gen g, notification_t const *n) /* {{{ */
   }
 
   JSON_ADD(g, "severity");
-  JSON_ADD(g, (n->severity == NOTIF_FAILURE)
-                  ? "FAILURE"
-                  : (n->severity == NOTIF_WARNING)
-                        ? "WARNING"
-                        : (n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN");
+  JSON_ADD(g,
+           (n->severity == NOTIF_FAILURE)
+               ? "FAILURE"
+               : (n->severity == NOTIF_WARNING)
+                     ? "WARNING"
+                     : (n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN");
 
   JSON_ADD(g, "service");
   JSON_ADD(g, "collectd");
 
-  yajl_gen_map_close(g); /* END labels */
+  CHECK_SUCCESS(yajl_gen_map_close(g)); /* END labels */
 
   /*
    * annotations
    */
   JSON_ADD(g, "annotations");
-  yajl_gen_map_open(g); /* BEGIN annotations */
+  CHECK_SUCCESS(yajl_gen_map_open(g)); /* BEGIN annotations */
 
   JSON_ADD(g, "summary");
   JSON_ADD(g, n->message);
 
-  if (format_json_meta(g, n->meta) != 0)
+  if (format_json_meta(g, n->meta) != 0) {
     return -1;
+  }
 
-  yajl_gen_map_close(g); /* END annotations */
+  CHECK_SUCCESS(yajl_gen_map_close(g)); /* END annotations */
 
   JSON_ADD(g, "startsAt");
-  format_time(g, n->time);
+  if (format_time(g, n->time) != 0) {
+    return -1;
+  }
 
-  yajl_gen_map_close(g); /* END alert */
-  yajl_gen_array_close(g);
+  CHECK_SUCCESS(yajl_gen_map_close(g));   /* END alert */
+  CHECK_SUCCESS(yajl_gen_array_close(g)); /* END array */
 
   return 0;
 } /* }}} format_alert */
@@ -671,7 +683,11 @@ int format_json_notification(char *buffer, size_t buffer_size, /* {{{ */
   }
 
   /* copy to output buffer */
-  yajl_gen_get_buf(g, &out, &unused_out_len);
+  if (yajl_gen_get_buf(g, &out, &unused_out_len) != yajl_gen_status_ok) {
+    yajl_gen_clear(g);
+    yajl_gen_free(g);
+    return -1;
+  }
   sstrncpy(buffer, (void *)out, buffer_size);
 
   yajl_gen_clear(g);
index 2e487b5..11b3f74 100644 (file)
@@ -34,6 +34,7 @@
 #include <regex.h>
 
 #define UTILS_MATCH_FLAGS_EXCLUDE_REGEX 0x02
+#define UTILS_MATCH_FLAGS_REGEX 0x04
 
 struct cu_match_s {
   regex_t regex;
@@ -234,6 +235,7 @@ match_create_callback(const char *regex, const char *excluderegex,
     sfree(obj);
     return (NULL);
   }
+  obj->flags |= UTILS_MATCH_FLAGS_REGEX;
 
   if (excluderegex && strcmp(excluderegex, "") != 0) {
     status = regcomp(&obj->excluderegex, excluderegex, REG_EXTENDED);
@@ -301,6 +303,10 @@ void match_destroy(cu_match_t *obj) {
   if (obj == NULL)
     return;
 
+  if (obj->flags & UTILS_MATCH_FLAGS_REGEX)
+    regfree(&obj->regex);
+  if (obj->flags & UTILS_MATCH_FLAGS_EXCLUDE_REGEX)
+    regfree(&obj->excluderegex);
   if ((obj->user_data != NULL) && (obj->free != NULL))
     (*obj->free)(obj->user_data);
 
index b85ab47..13adff5 100644 (file)
@@ -312,6 +312,7 @@ static void wg_callback_free(void *data) {
   sfree(cb->prefix);
   sfree(cb->postfix);
 
+  pthread_mutex_unlock(&cb->send_lock);
   pthread_mutex_destroy(&cb->send_lock);
 
   sfree(cb);
index c1b3f0b..4688928 100644 (file)
@@ -114,6 +114,7 @@ static int wh_post_nolock(wh_callback_t *cb, char const *data) /* {{{ */
 {
   int status = 0;
 
+  curl_easy_setopt(cb->curl, CURLOPT_URL, cb->location);
   curl_easy_setopt(cb->curl, CURLOPT_POSTFIELDS, data);
   status = curl_easy_perform(cb->curl);
 
@@ -163,7 +164,6 @@ static int wh_callback_init(wh_callback_t *cb) /* {{{ */
   curl_easy_setopt(cb->curl, CURLOPT_HTTPHEADER, cb->headers);
 
   curl_easy_setopt(cb->curl, CURLOPT_ERRORBUFFER, cb->curl_errbuf);
-  curl_easy_setopt(cb->curl, CURLOPT_URL, cb->location);
   curl_easy_setopt(cb->curl, CURLOPT_FOLLOWLOCATION, 1L);
   curl_easy_setopt(cb->curl, CURLOPT_MAXREDIRS, 50L);
 
index 306d92c..17a83e0 100644 (file)
@@ -77,6 +77,14 @@ static void kafka_log(const rd_kafka_t *rkt, int level, const char *fac,
 }
 #endif
 
+static rd_kafka_resp_err_t kafka_error() {
+#if RD_KAFKA_VERSION >= 0x000b00ff
+  return rd_kafka_last_error();
+#else
+  return rd_kafka_errno2err(errno);
+#endif
+}
+
 static uint32_t kafka_hash(const char *keydata, size_t keylen) {
   uint32_t hash = 5381;
   for (; keylen > 0; keylen--)
@@ -147,7 +155,7 @@ static int kafka_handle(struct kafka_topic_context *ctx) /* {{{ */
     if ((ctx->topic = rd_kafka_topic_new(ctx->kafka, ctx->topic_name,
                                          topic_conf)) == NULL) {
       ERROR("write_kafka plugin: cannot create topic : %s\n",
-            rd_kafka_err2str(rd_kafka_errno2err(errno)));
+            rd_kafka_err2str(kafka_error()));
       return errno;
     }
 
index 991415e..97f583f 100644 (file)
 
 #include <microhttpd.h>
 
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
 #ifndef PROMETHEUS_DEFAULT_STALENESS_DELTA
 #define PROMETHEUS_DEFAULT_STALENESS_DELTA TIME_T_TO_CDTIME_T_STATIC(300)
 #endif
@@ -546,9 +550,14 @@ metric_family_delete_metric(Io__Prometheus__Client__MetricFamily *fam,
             ((fam->n_metric - 1) - i) * sizeof(fam->metric[i]));
   fam->n_metric--;
 
+  if (fam->n_metric == 0) {
+    sfree(fam->metric);
+    return 0;
+  }
+
   Io__Prometheus__Client__Metric **tmp =
       realloc(fam->metric, fam->n_metric * sizeof(*fam->metric));
-  if ((tmp != NULL) || (fam->n_metric == 0))
+  if (tmp != NULL)
     fam->metric = tmp;
 
   return 0;
@@ -694,8 +703,10 @@ metric_family_get(data_set_t const *ds, value_list_t const *vl, size_t ds_index,
     return fam;
   }
 
-  if (!allocate)
+  if (!allocate) {
+    sfree(name);
     return NULL;
+  }
 
   fam = metric_family_create(name, ds, vl, ds_index);
   if (fam == NULL) {
@@ -720,6 +731,100 @@ metric_family_get(data_set_t const *ds, value_list_t const *vl, size_t ds_index,
 }
 /* }}} */
 
+static void prom_logger(__attribute__((unused)) void *arg, char const *fmt,
+                        va_list ap) {
+  /* {{{ */
+  char errbuf[1024];
+  vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
+
+  ERROR("write_prometheus plugin: %s", errbuf);
+} /* }}} prom_logger */
+
+#if MHD_VERSION >= 0x00090000
+static int prom_open_socket(int addrfamily) {
+  /* {{{ */
+  char service[NI_MAXSERV];
+  snprintf(service, sizeof(service), "%hu", httpd_port);
+
+  struct addrinfo *res;
+  int status = getaddrinfo(NULL, service,
+                           &(struct addrinfo){
+                               .ai_flags = AI_PASSIVE | AI_ADDRCONFIG,
+                               .ai_family = addrfamily,
+                               .ai_socktype = SOCK_STREAM,
+                           },
+                           &res);
+  if (status != 0) {
+    return -1;
+  }
+
+  int fd = -1;
+  for (struct addrinfo *ai = res; ai != NULL; ai = ai->ai_next) {
+    fd = socket(ai->ai_family, ai->ai_socktype | SOCK_CLOEXEC, 0);
+    if (fd == -1)
+      continue;
+
+    if (bind(fd, ai->ai_addr, ai->ai_addrlen) != 0) {
+      close(fd);
+      fd = -1;
+      continue;
+    }
+
+    if (listen(fd, /* backlog = */ 16) != 0) {
+      close(fd);
+      fd = -1;
+      continue;
+    }
+
+    break;
+  }
+
+  freeaddrinfo(res);
+
+  return fd;
+} /* }}} int prom_open_socket */
+
+static struct MHD_Daemon *prom_start_daemon() {
+  /* {{{ */
+  int fd = prom_open_socket(PF_INET6);
+  if (fd == -1)
+    fd = prom_open_socket(PF_INET);
+  if (fd == -1) {
+    ERROR("write_prometheus plugin: Opening a listening socket failed.");
+    return NULL;
+  }
+
+  struct MHD_Daemon *d = MHD_start_daemon(
+      MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG, httpd_port,
+      /* MHD_AcceptPolicyCallback = */ NULL,
+      /* MHD_AcceptPolicyCallback arg = */ NULL, http_handler, NULL,
+      MHD_OPTION_LISTEN_SOCKET, fd, MHD_OPTION_EXTERNAL_LOGGER, prom_logger,
+      NULL, MHD_OPTION_END);
+  if (d == NULL) {
+    ERROR("write_prometheus plugin: MHD_start_daemon() failed.");
+    close(fd);
+    return NULL;
+  }
+
+  return d;
+} /* }}} struct MHD_Daemon *prom_start_daemon */
+#else /* if MHD_VERSION < 0x00090000 */
+static struct MHD_Daemon *prom_start_daemon() {
+  /* {{{ */
+  struct MHD_Daemon *d = MHD_start_daemon(
+      MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG, httpd_port,
+      /* MHD_AcceptPolicyCallback = */ NULL,
+      /* MHD_AcceptPolicyCallback arg = */ NULL, http_handler, NULL,
+      MHD_OPTION_EXTERNAL_LOGGER, prom_logger, NULL, MHD_OPTION_END);
+  if (d == NULL) {
+    ERROR("write_prometheus plugin: MHD_start_daemon() failed.");
+    return NULL;
+  }
+
+  return d;
+} /* }}} struct MHD_Daemon *prom_start_daemon */
+#endif
+
 /*
  * collectd callbacks
  */
@@ -753,15 +858,7 @@ static int prom_init() {
   }
 
   if (httpd == NULL) {
-    unsigned int flags = MHD_USE_THREAD_PER_CONNECTION;
-#if MHD_VERSION >= 0x00093300
-    flags |= MHD_USE_DUAL_STACK;
-#endif
-
-    httpd = MHD_start_daemon(flags, httpd_port,
-                             /* MHD_AcceptPolicyCallback = */ NULL,
-                             /* MHD_AcceptPolicyCallback arg = */ NULL,
-                             http_handler, NULL, MHD_OPTION_END);
+    httpd = prom_start_daemon();
     if (httpd == NULL) {
       ERROR("write_prometheus plugin: MHD_start_daemon() failed.");
       return -1;
index 3835a3d..00852ff 100644 (file)
@@ -601,6 +601,7 @@ static void wrr_free(void *p) /* {{{ */
 
   wrr_disconnect(host);
 
+  pthread_mutex_lock(&host->lock);
   pthread_mutex_destroy(&host->lock);
   sfree(host);
 } /* }}} void wrr_free */
index 72ed6bc..92f1743 100644 (file)
 
 #include "collectd.h"
 
+#include "common.h"
+#include "plugin.h"
+#include "utils_cache.h"
+
 #include <arpa/inet.h>
 #include <errno.h>
 #include <inttypes.h>
 #include <netdb.h>
 #include <stddef.h>
-#include "common.h"
-#include "plugin.h"
-#include "utils_cache.h"
 
 #include <stdlib.h>
 #define SENSU_HOST "localhost"
@@ -998,7 +999,10 @@ static void sensu_free(void *p) /* {{{ */
   sfree(host->separator);
   free_str_list(&(host->metric_handlers));
   free_str_list(&(host->notification_handlers));
+
+  pthread_mutex_unlock(&host->lock);
   pthread_mutex_destroy(&host->lock);
+
   sfree(host);
 } /* }}} void sensu_free */
 
index 0c87c47..9cb3c97 100644 (file)
@@ -219,6 +219,7 @@ static void wt_callback_free(void *data) {
   sfree(cb->service);
   sfree(cb->host_tags);
 
+  pthread_mutex_unlock(&cb->send_lock);
   pthread_mutex_destroy(&cb->send_lock);
 
   sfree(cb);
index 2083ec3..2c7a2e5 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-DEFAULT_VERSION="5.7.0.git"
+DEFAULT_VERSION="5.7.2.git"
 
 if [ -d .git ]; then
        VERSION="`git describe --dirty=+ --abbrev=7 2> /dev/null | grep collectd | sed -e 's/^collectd-//' -e 's/-/./g'`"