Merge pull request #2722 from elfiesmelfie/increase_buffer
authorPavel Rochnyak <pavel2000@ngs.ru>
Wed, 28 Mar 2018 15:28:12 +0000 (22:28 +0700)
committerGitHub <noreply@github.com>
Wed, 28 Mar 2018 15:28:12 +0000 (22:28 +0700)
dpdk: increase buffer size for parsing lcores

104 files changed:
.travis.yml
Makefile.am
README
build.sh
configure.ac
contrib/exec-munin.px
contrib/exec-nagios.px
contrib/php-collection/functions.php
contrib/sles10.1/collectd.spec
contrib/snmp-probe-host.px
contrib/systemd.collectd.service
docs/BUILD.dpdkstat.md
docs/README.virt.md
src/amqp.c
src/barometer.c
src/ceph.c
src/collectd-exec.pod
src/collectd-nagios.pod
src/collectd-threshold.pod
src/collectd-unixsock.pod
src/collectd.conf.in
src/collectd.conf.pod
src/collectd.pod
src/cpu.c
src/csv.c
src/curl_xml.c
src/daemon/collectd.c
src/daemon/common.c
src/daemon/common_test.c
src/daemon/globals.h
src/daemon/plugin.c
src/daemon/plugin_mock.c
src/daemon/types_list.c
src/daemon/utils_cache.c
src/daemon/utils_subst.c
src/daemon/utils_subst_test.c
src/dbi.c
src/df.c
src/disk.c
src/dpdkstat.c
src/drbd.c
src/email.c
src/exec.c
src/gmond.c
src/grpc.cc
src/intel_pmu.c
src/intel_rdt.c
src/interface.c
src/ipmi.c
src/java.c
src/libcollectdclient/network_parse.c
src/libcollectdclient/network_parse_test.c
src/liboconfig/parser.y
src/memcached.c
src/modbus.c
src/mysql.c
src/netlink.c
src/network.c
src/nfs.c
src/ntpd.c
src/oracle.c
src/ovs_stats.c
src/perl.c
src/ping.c
src/postgresql.c
src/powerdns.c
src/processes.c
src/pyvalues.c
src/rrdcached.c
src/rrdtool.c
src/snmp.c
src/snmp_agent.c
src/table.c
src/tail_csv.c
src/tape.c
src/target_replace.c
src/turbostat.c
src/types.db
src/uptime.c
src/utils_cmd_getthreshold.c
src/utils_cmd_getval.c
src/utils_db_query.c
src/utils_format_graphite.c
src/utils_format_json.c
src/utils_format_kairosdb.c
src/utils_latency.c
src/utils_latency_test.c
src/utils_lua.c
src/utils_mount_test.c
src/utils_ovs.c
src/utils_tail_match.c
src/utils_taskstats.c [new file with mode: 0644]
src/utils_taskstats.h [new file with mode: 0644]
src/utils_vl_lookup.c
src/virt.c
src/write_graphite.c
src/write_http.c
src/write_kafka.c
src/write_mongodb.c
src/write_prometheus.c
src/write_riemann.c
src/write_sensu.c
src/write_tsdb.c
src/zfs_arc.c

index 339d2dc..1bd6142 100644 (file)
@@ -83,7 +83,7 @@ addons:
     project:
       name: "collectd/collectd"
       description: "Build submitted via Travis CI"
-    notification_email: octo@collectd.org
+    notification_email: collectd-changes@verplant.org
     build_command_prepend: "./configure; make clean"
     build_command: "make -j 4"
     branch_pattern: coverity_scan
index ae027a3..e37716f 100644 (file)
@@ -516,6 +516,7 @@ liboconfig_la_SOURCES = \
        src/liboconfig/aux_types.h \
        src/liboconfig/scanner.l \
        src/liboconfig/parser.y
+liboconfig_la_CPPFLAGS = -I$(srcdir)/src/liboconfig $(AM_CPPFLAGS)
 liboconfig_la_LDFLAGS = -avoid-version $(LEXLIB)
 
 
@@ -1421,14 +1422,28 @@ python_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBPYTHON_CPPFLAGS)
 python_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBPYTHON_LDFLAGS)
 endif
 
+if HAVE_LIBMNL
+noinst_LTLIBRARIES += libtaskstats.la
+libtaskstats_la_SOURCES = \
+       src/utils_taskstats.c \
+       src/utils_taskstats.h
+libtaskstats_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMNL_CFLAGS)
+libtaskstats_la_LIBADD = $(BUILD_WITH_LIBMNL_LIBS)
+endif
+
 if BUILD_PLUGIN_PROCESSES
 pkglib_LTLIBRARIES += processes.la
 processes_la_SOURCES = src/processes.c
+processes_la_CPPFLAGS = $(AM_CPPFLAGS)
 processes_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 processes_la_LIBADD =
 if BUILD_WITH_LIBKVM_GETPROCS
 processes_la_LIBADD += -lkvm
 endif
+if HAVE_LIBMNL
+processes_la_CPPFLAGS += -DHAVE_LIBTASKSTATS=1
+processes_la_LIBADD += libtaskstats.la
+endif
 endif
 
 if BUILD_PLUGIN_PROTOCOLS
diff --git a/README b/README
index ca86c84..a47b669 100644 (file)
--- a/README
+++ b/README
@@ -100,6 +100,9 @@ Features
       Collect DPDK interface statistics.
       See docs/BUILD.dpdkstat.md for detailed build instructions.
 
+      This plugin should be compiled with compiler defenses enabled, for
+      example -fstack-protector.
+
     - drbd
       Collect individual drbd resource statistics.
 
@@ -140,6 +143,9 @@ Features
       hugepages can be found here:
       https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt.
 
+      This plugin should be compiled with compiler defenses enabled, for
+      example -fstack-protector.
+
     - intel_pmu
       The intel_pmu plugin reads performance counters provided by the Linux
       kernel perf interface. The plugin uses jevents library to resolve named
index 40f5361..bd4c1a3 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -1,54 +1,51 @@
-#! /bin/sh
+#!/bin/sh
 
 GLOBAL_ERROR_INDICATOR=0
 
-check_for_application ()
+check_for_application()
 {
-       for PROG in "$@"
-       do
-               which "$PROG" >/dev/null 2>&1
-               if test $? -ne 0; then
-                       cat >&2 <<EOF
+    for PROG in "$@"
+    do
+        which "$PROG" >/dev/null 2>&1
+        if test $? -ne 0; then
+            cat >&2 <<EOF
 WARNING: \`$PROG' not found!
     Please make sure that \`$PROG' is installed and is in one of the
     directories listed in the PATH environment variable.
 EOF
-                       GLOBAL_ERROR_INDICATOR=1
-               fi
-       done
+            GLOBAL_ERROR_INDICATOR=1
+        fi
+    done
 }
 
 check_for_application lex bison autoheader aclocal automake autoconf pkg-config
 
 libtoolize=""
 libtoolize --version >/dev/null 2>/dev/null
-if test $? -eq 0
-then
-       libtoolize=libtoolize
+if test $? -eq 0; then
+    libtoolize=libtoolize
 else
-       glibtoolize --version >/dev/null 2>/dev/null
-       if test $? -eq 0
-       then
-               libtoolize=glibtoolize
-       else
-               cat >&2 <<EOF
+    glibtoolize --version >/dev/null 2>/dev/null
+    if test $? -eq 0; then
+        libtoolize=glibtoolize
+    else
+        cat >&2 <<EOF
 WARNING: Neither \`libtoolize' nor \`glibtoolize' have been found!
     Please make sure that one of them is installed and is in one of the
     directories listed in the PATH environment variable.
 EOF
-               GLOBAL_ERROR_INDICATOR=1
-       fi
+        GLOBAL_ERROR_INDICATOR=1
+    fi
  fi
 
-if test "$GLOBAL_ERROR_INDICATOR" != "0"
-then
-       exit 1
+if test "$GLOBAL_ERROR_INDICATOR" != "0"; then
+    exit 1
 fi
 
 set -x
 
 autoheader \
-&& aclocal \
+&& aclocal -I m4 \
 && $libtoolize --copy --force \
 && automake --add-missing --copy \
 && autoconf
index e869a6a..352a7b6 100644 (file)
@@ -2635,6 +2635,7 @@ AC_ARG_WITH([libgrpc++],
     if test "x$withval" != "xno" && test "x$withval" != "xyes"; then
       with_libgrpcpp_cppflags="-I$withval/include"
       with_libgrpcpp_ldflags="-L$withval/lib"
+      with_libgrpcpp_bin="$withval/bin"
       with_libgrpcpp="yes"
     fi
     if test "x$withval" = "xno"; then
@@ -2714,7 +2715,11 @@ AC_SUBST([BUILD_WITH_LIBGRPCPP_LIBS])
 # }}}
 
 AC_ARG_VAR([GRPC_CPP_PLUGIN], [path to the grpc_cpp_plugin binary])
-AC_PATH_PROG([GRPC_CPP_PLUGIN], [grpc_cpp_plugin])
+if test "x$with_libgrpcpp_bin" = "x"; then
+  AC_PATH_PROG([GRPC_CPP_PLUGIN], [grpc_cpp_plugin])
+else
+  AC_PATH_PROG([GRPC_CPP_PLUGIN], [grpc_cpp_plugin], [], "$with_libgrpcpp_bin:$PATH")
+fi
 AM_CONDITIONAL([HAVE_GRPC_CPP], [test "x$GRPC_CPP_PLUGIN" != "x"])
 
 # --with-libiptc {{{
@@ -3668,6 +3673,7 @@ if test "x$with_libmnl" = "xyes"; then
 fi
 AC_SUBST([BUILD_WITH_LIBMNL_CFLAGS])
 AC_SUBST([BUILD_WITH_LIBMNL_LIBS])
+AM_CONDITIONAL([HAVE_LIBMNL], [test "x$with_libmnl" = "xyes"])
 # }}}
 
 # --with-libnetapp {{{
@@ -6378,8 +6384,18 @@ if test "x$with_libgps" = "xyes"; then
   plugin_gps="yes"
 fi
 
-if test "x$with_libgrpcpp" = "xyes" && test "x$with_libprotobuf" = "xyes" && test "x$have_protoc3" = "xyes" && test "x$GRPC_CPP_PLUGIN" != "x"; then
-  plugin_grpc="yes"
+plugin_grpc="yes"
+if test "x$GRPC_CPP_PLUGIN" = "x"; then
+  plugin_grpc="no (grpc_cpp_plugin not found)"
+fi
+if test "x$have_protoc3" != "xyes"; then
+  plugin_grpc="no (protoc3 not found)"
+fi
+if test "x$with_libprotobuf" != "xyes"; then
+  plugin_grpc="no (libprotobuf not found)"
+fi
+if test "x$with_libgrpcpp" != "xyes"; then
+  plugin_grpc="no (libgrpc++ not found)"
 fi
 
 if test "x$have_getifaddrs" = "xyes"; then
index 3e62ce0..5309cc6 100755 (executable)
@@ -56,7 +56,7 @@ exit (0);
 
 =head1 CONFIGURATION
 
-This script reads it's configuration from F</etc/exec-munin.conf>. The
+This script reads its configuration from F</etc/exec-munin.conf>. The
 configuration is read using C<Config::General> which understands a Apache-like
 config syntax, so it's very similar to the F<collectd.conf> syntax, too.
 
index ec13b0a..b9758ec 100755 (executable)
@@ -36,7 +36,7 @@ exit (0);
 
 =head1 CONFIGURATION
 
-This script reads it's configuration from F</etc/exec-nagios.conf>. The
+This script reads its configuration from F</etc/exec-nagios.conf>. The
 configuration is read using C<Config::General> which understands a Apache-like
 config syntax, so it's very similar to the F<collectd.conf> syntax, too.
 
index fa2badc..c063d57 100644 (file)
@@ -536,7 +536,7 @@ function rrd_get_color($code, $line = true) {
 }
 
 /**
- * Draw RRD file based on it's structure
+ * Draw RRD file based on its structure
  * @host
  * @plugin
  * @pinst
@@ -635,7 +635,7 @@ function collectd_draw_rrd($host, $plugin, $pinst = null, $type, $tinst = null,
 }
 
 /**
- * Draw RRD file based on it's structure
+ * Draw RRD file based on its structure
  * @timespan
  * @host
  * @plugin
index 2d558bd..82d709a 100644 (file)
@@ -14,7 +14,7 @@ Vendor:               Florian octo Forster <octo@verplant.org>
 
 %description
 collectd is a small daemon written in C for performance.  It reads various
-system  statistics  and updates  RRD files,  creating  them if neccessary.
+system  statistics  and updates  RRD files,  creating  them if necessary.
 Since the daemon doesn't need to startup every time it wants to update the
 files it's very fast and easy on the system. Also, the statistics are very
 fine grained since the files are updated every 10 seconds.
index d1a7a88..9776af6 100755 (executable)
@@ -306,9 +306,9 @@ snmp-probe-host.px - Find out what information an SNMP device provides.
 The C<snmp-probe-host.px> script can be used to automatically generate SNMP
 configuration snippets for collectd's snmp plugin (see L<collectd-snmp(5)>).
 
-This script parses the collectd configuration and detecs all "data" blocks that
+This script parses the collectd configuration and detects all "data" blocks that
 are defined for the SNMP plugin. It then queries the device specified on the
-command line for all OIDs and registeres which OIDs could be answered correctly
+command line for all OIDs and registers which OIDs could be answered correctly
 and which resulted in an error. With that information the script figures out
 which "data" blocks can be used with this hosts and prints an appropriate
 "host" block to standard output.
index 9c037a4..c5b1142 100644 (file)
@@ -22,6 +22,7 @@ ProtectHome=true
 #   intel_pmu       CAP_SYS_ADMIN
 #   iptables        CAP_NET_ADMIN
 #   ping            CAP_NET_RAW
+#   processes       CAP_NET_ADMIN  (CollectDelayAccounting only)
 #   smart           CAP_SYS_RAWIO
 #   turbostat       CAP_SYS_RAWIO
 #
index 96f1eb9..457fc0f 100644 (file)
@@ -1,7 +1,17 @@
 # The dpdkstat plugin
 
+This plugin is optional and only has a specific use case: monitoring DPDK applications
+that don't expose stats in any other way than the DPDK xstats API.
+
 **Data Plane Development Kit** (DPDK) is a set of drivers and libraries for fast
-packet processing.
+packet processing. Please note that this plugin is a polling based plugin rather
+than an events based plugin (using it will drive up core utilization on a system).
+
+**PLEASE DO NOT USE THIS PLUGIN FOR OVS-DPDK**. dpdkstat is really for DPDK
+applications that have no other way of exposing stats. For OVS or OVS-with-DPDK the
+Open vSwitch plugins available in collectd 5.8.0 should be used for
+collecting stats and events. In addition the OVS plugin is events based rather
+than polling based and will have a smaller footprint on the system.
 
 ## Summary
 
index a80e9ea..9a63a18 100644 (file)
@@ -43,7 +43,7 @@ Collectd will just use the domain tags, but never enforces or requires them.
 It is up to an external entity, like a software management system,
 to attach and manage the tags to the domain.
 
-Please note that unless you have such tag-aware management sofware,
+Please note that unless you have such tag-aware management software,
 it most likely make no sense to enable more than one reader instance on your
 setup.
 
@@ -179,8 +179,8 @@ API, but it is rather a byproduct of how libvirt and QEMU interact.
 
 Whenever we query more than one VM, we should take care to avoid that one blocked VM prevent other,
 well behaving VMs to be queried. We don't want one rogue VM to disrupt well-behaving VMs.
-Unfortunately, any way we enumerate VMs, either implicitely, using the libvirt bulk stats API,
-or explicitely, listing all libvirt domains and query each one in turn, we may unpredictably encounter
+Unfortunately, any way we enumerate VMs, either implicitly, using the libvirt bulk stats API,
+or explicitly, listing all libvirt domains and query each one in turn, we may unpredictably encounter
 one unresponsive VM.
 
 There are many possible approaches to deal with this issue. The virt plugin supports
@@ -237,4 +237,3 @@ The QEMU core, including the handling of the QMP protocol, is single-threaded.
 All the above combined make it possible for a client to block forever waiting for one QMP
 request, if QEMU itself is blocked. The most likely cause of block is I/O, and this is especially
 true considering how QEMU is used in a datacenter.
-
index a8df888..6c18448 100644 (file)
@@ -503,7 +503,7 @@ static int camqp_connect(camqp_config_t *conf) /* {{{ */
 
 static int camqp_shutdown(void) /* {{{ */
 {
-  DEBUG("amqp plugin: Shutting down %zu subscriber threads.",
+  DEBUG("amqp plugin: Shutting down %" PRIsz " subscriber threads.",
         subscriber_threads_num);
 
   subscriber_threads_running = 0;
index 2db1ea4..6c6347c 100644 (file)
@@ -412,16 +412,16 @@ static int get_reference_temperature(double *result) {
         continue;
       }
 
-      DEBUG(
-          "barometer: get_reference_temperature - initialize \"%s\", %zu vals",
-          list->sensor_name, values_num);
+      DEBUG("barometer: get_reference_temperature - initialize \"%s\", %" PRIsz
+            " vals",
+            list->sensor_name, values_num);
 
       list->initialized = 1;
       list->num_values = values_num;
 
       for (size_t i = 0; i < values_num; ++i) {
-        DEBUG("barometer: get_reference_temperature - rate %zu: %lf **", i,
-              values[i]);
+        DEBUG("barometer: get_reference_temperature - rate %" PRIsz ": %lf **",
+              i, values[i]);
         if (!isnan(values[i])) {
           avg_sum += values[i];
           ++avg_num;
@@ -444,7 +444,7 @@ static int get_reference_temperature(double *result) {
     }
 
     for (size_t i = 0; i < REF_TEMP_AVG_NUM * list->num_values; ++i) {
-      DEBUG("barometer: get_reference_temperature - history %zu: %lf", i,
+      DEBUG("barometer: get_reference_temperature - history %" PRIsz ": %lf", i,
             values_history[i]);
       if (!isnan(values_history[i])) {
         avg_sum += values_history[i];
@@ -464,8 +464,9 @@ static int get_reference_temperature(double *result) {
       }
 
       for (size_t i = 0; i < values_num; ++i) {
-        DEBUG("barometer: get_reference_temperature - rate last %zu: %lf **", i,
-              values[i]);
+        DEBUG("barometer: get_reference_temperature - rate last %" PRIsz
+              ": %lf **",
+              i, values[i]);
         if (!isnan(values[i])) {
           avg_sum += values[i];
           ++avg_num;
index 3accbd3..df4a720 100644 (file)
@@ -280,7 +280,7 @@ static int ceph_cb_number(void *ctx, const char *number_val,
    * the same type of other "Bytes". Instead of keeping an "average" or
    * "rate", use the "sum" in the pair and assign that to the derive
    * value. */
-  if (convert_special_metrics && (state->depth >= 2) &&
+  if (convert_special_metrics && (state->depth > 2) &&
       (strcmp("filestore", state->stack[state->depth - 2]) == 0) &&
       (strcmp("journal_wr_bytes", state->stack[state->depth - 1]) == 0) &&
       (strcmp("avgcount", state->key) == 0)) {
@@ -1341,7 +1341,7 @@ static int cconn_main_loop(uint32_t request_type) {
       struct cconn *io = io_array + i;
       ret = cconn_prepare(io, fds + nfds);
       if (ret < 0) {
-        WARNING("ceph plugin: cconn_prepare(name=%s,i=%zu,st=%d)=%d",
+        WARNING("ceph plugin: cconn_prepare(name=%s,i=%" PRIsz ",st=%d)=%d",
                 io->d->name, i, io->state, ret);
         cconn_close(io);
         io->request_type = ASOK_REQ_NONE;
index c65966b..b878657 100644 (file)
@@ -73,7 +73,7 @@ Each line beginning with a C<#> (hash mark) is ignored.
 =item B<PUTVAL> I<Identifier> [I<OptionList>] I<Valuelist>
 
 Submits one or more values (identified by I<Identifier>, see below) to the
-daemon which will dispatch it to all it's write-plugins.
+daemon which will dispatch it to all its write-plugins.
 
 An I<Identifier> is of the form
 C<I<host>B</>I<plugin>B<->I<instance>B</>I<type>B<->I<instance>> with both
index e28ff4b..4ff0bf6 100644 (file)
@@ -107,7 +107,7 @@ consolidations simply ignore NaN values.
 =head1 RETURN VALUE
 
 As usual for Nagios plugins, this program writes a short, one line status
-message to STDOUT and signals success or failure with it's return value. It
+message to STDOUT and signals success or failure with its return value. It
 exits with a return value of B<0> for I<success>, B<1> for I<warning> and B<2>
 for I<critical>. If the values are not available or some other error occurred,
 it returns B<3> for I<unknown>.
index 35f8a9f..14f2c8c 100644 (file)
@@ -40,7 +40,7 @@ Also, all values that match a threshold are considered to be relevant or
 "interesting". As a consequence collectd will issue a notification if they are
 not received for B<Timeout> iterations. The B<Timeout> configuration option is
 explained in section L<collectd.conf(5)/"GLOBAL OPTIONS">. If, for example,
-B<Timeout> is set to "2" (the default) and some hosts sends it's CPU statistics
+B<Timeout> is set to "2" (the default) and some hosts sends its CPU statistics
 to the server every 60 seconds, a notification will be dispatched after about
 120 seconds. It may take a little longer because the timeout is checked only
 once each B<Interval> on the server.
index b241a9f..db7000a 100644 (file)
@@ -84,7 +84,7 @@ Example:
 =item B<PUTVAL> I<Identifier> [I<OptionList>] I<Valuelist>
 
 Submits one or more values (identified by I<Identifier>, see below) to the
-daemon which will dispatch it to all it's write-plugins.
+daemon which will dispatch it to all its write-plugins.
 
 An I<Identifier> is of the form
 C<I<host>B</>I<plugin>B<->I<instance>B</>I<type>B<->I<instance>> with both
index 4efa29e..6ec61f3 100644 (file)
 #              SSLCACertificateFile "/path/to/root.pem"
 #              SSLCertificateFile "/path/to/client.pem"
 #              SSLCertificateKeyFile "/path/to/client.key"
+#              VerifyPeer true
 #      </Listen>
 #</Plugin>
 
 #      CollectFileDescriptor true
 #      CollectContextSwitch true
 #      CollectMemoryMaps true
+#      CollectDelayAccounting false
 #      Process "name"
 #      ProcessMatch "name" "regex"
 #      <Process "collectd">
 #              CollectFileDescriptor false
 #              CollectContextSwitch false
+#              CollectDelayAccounting true
 #      </Process>
 #      <ProcessMatch "name" "regex">
 #              CollectFileDescriptor false
index 0e7a604..e971512 100644 (file)
@@ -3094,6 +3094,13 @@ Whether to enable SSL for incoming connections. Default: false.
 Filenames specifying SSL certificate and key material to be used with SSL
 connections.
 
+=item B<VerifyPeer> B<true>|B<false>
+
+When enabled, a valid client certificate is required to connect to the server.
+When disabled, a client certifiacte is not requested and any unsolicited client
+certificate is accepted.
+Enabled by default.
+
 =back
 
 =back
@@ -4121,11 +4128,19 @@ Configures the base register to read from the device. If the option
 B<RegisterType> has been set to B<Uint32> or B<Float>, this and the next
 register will be read (the register number is increased by one).
 
-=item B<RegisterType> B<Int16>|B<Int32>|B<Uint16>|B<Uint32>|B<Float>
+=item B<RegisterType> B<Int16>|B<Int32>|B<Uint16>|B<Uint32>|B<Float>|B<Int32LE>|B<Uint32LE>|B<FloatLE>
 
-Specifies what kind of data is returned by the device. If the type is B<Int32>,
-B<Uint32> or B<Float>, two 16E<nbsp>bit registers will be read and the data is
-combined into one value. Defaults to B<Uint16>.
+Specifies what kind of data is returned by the device. This defaults to
+B<Uint16>.  If the type is B<Int32>, B<Int32LE>, B<Uint32>, B<Uint32LE>,
+B<Float> or B<FloatLE>, two 16E<nbsp>bit registers at B<RegisterBase>
+and B<RegisterBase+1> will be read and the data is combined into one
+32E<nbsp>value. For B<Int32>, B<Uint32> and B<Float> the most significant
+16E<nbsp>bits are in the register at B<RegisterBase> and the least
+significant 16E<nbsp>bits are in the register at B<RegisterBase+1>.
+For B<Int32LE>, B<Uint32LE>, or B<Float32LE>, the high and low order
+registers are swapped with the most significant 16E<nbsp>bits in
+the B<RegisterBase+1> and the least significant 16E<nbsp>bits in
+B<RegisterBase>.
 
 =item B<RegisterCmd> B<ReadHolding>|B<ReadInput>
 
@@ -6842,22 +6857,25 @@ The statistics collected for matched processes are:
  - number of memory mapped files (under Linux)
  - io data (where available)
  - context switches (under Linux)
- - minor and major pagefaults.
+ - minor and major pagefaults
+ - Delay Accounting information (Linux only, requires libmnl)
 
 B<Synopsis:>
 
  <Plugin processes>
-   CollectFileDescriptor true
-   CollectContextSwitch true
+   CollectFileDescriptor  true
+   CollectContextSwitch   true
+   CollectDelayAccounting false
    Process "name"
    ProcessMatch "name" "regex"
    <Process "collectd">
-     CollectFileDescriptor false
-     CollectContextSwitch false
+     CollectFileDescriptor  false
+     CollectContextSwitch   false
+     CollectDelayAccounting true
    </Process>
    <ProcessMatch "name" "regex">
      CollectFileDescriptor false
-     CollectContextSwitch true
+     CollectContextSwitch  true
    </Process>
  </Plugin>
 
@@ -6883,6 +6901,18 @@ I<name> must not contain slashes.
 Collect the number of context switches for matched processes.
 Disabled by default.
 
+=item B<CollectDelayAccounting> I<Boolean>
+
+If enabled, collect Linux Delay Accounding information for matching processes.
+Delay Accounting provides the time processes wait for the CPU to become
+available, for I/O operations to finish, for pages to be swapped in and for
+freed pages to be reclaimed. The metrics are reported as "seconds per second"
+using the C<delay_rate> type, e.g. C<delay_rate-delay-cpu>.
+Disabled by default.
+
+This option is only available on Linux, requires the C<libmnl> library and
+requires the C<CAP_NET_ADMIN> capability at runtime.
+
 =item B<CollectFileDescriptor> I<Boolean>
 
 Collect number of file descriptors of matched processes.
@@ -6896,9 +6926,12 @@ the Linux kernel.
 
 =back
 
-Options B<CollectContextSwitch> and B<CollectFileDescriptor> may be used inside
-B<Process> and B<ProcessMatch> blocks - then they affect corresponding match
-only. Otherwise they set the default value for subsequent matches.
+The B<CollectContextSwitch>, B<CollectDelayAccounting>,
+B<CollectFileDescriptor> and B<CollectMemoryMaps> options may be used inside
+B<Process> and B<ProcessMatch> blocks. When used there, these options affect
+reporting the corresponding processes only. Outside of B<Process> and
+B<ProcessMatch> blocks these options set the default value for subsequent
+matches.
 
 =head2 Plugin C<protocols>
 
index 1dd899b..60707a1 100644 (file)
@@ -69,7 +69,7 @@ Output usage information and exit.
 
 =head1 PLUGINS
 
-As noted above, the real power of collectd lies within it's plugins. A
+As noted above, the real power of collectd lies within its plugins. A
 (hopefully complete) list of plugins and short descriptions can be found in the
 F<README> file that is distributed with the sourcecode. If you're using a
 package it's a good bet to search somewhere near F</usr/share/doc/collectd>.
index 0bf38e7..8480f11 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -134,6 +134,9 @@ static mach_msg_type_number_t cpu_list_len;
 /* #endif KERNEL_LINUX */
 
 #elif defined(HAVE_LIBKSTAT)
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
 /* colleague tells me that Sun doesn't sell systems with more than 100 or so
  * CPUs.. */
 #define MAX_NUMCPU 256
index 59d1d2f..f5126d2 100644 (file)
--- a/src/csv.c
+++ b/src/csv.c
@@ -74,8 +74,8 @@ static int value_list_to_string(char *buffer, int buffer_len,
       }
       status = snprintf(buffer + offset, buffer_len - offset, ",%lf", rates[i]);
     } else if (ds->ds[i].type == DS_TYPE_COUNTER) {
-      status = snprintf(buffer + offset, buffer_len - offset, ",%llu",
-                        vl->values[i].counter);
+      status = snprintf(buffer + offset, buffer_len - offset, ",%" PRIu64,
+                        (uint64_t)vl->values[i].counter);
     } else if (ds->ds[i].type == DS_TYPE_DERIVE) {
       status = snprintf(buffer + offset, buffer_len - offset, ",%" PRIi64,
                         vl->values[i].derive);
index c99e3f1..19ae5f4 100644 (file)
@@ -240,8 +240,8 @@ static int cx_check_type(const data_set_t *ds, cx_xpath_t *xpath) /* {{{ */
   }
 
   if (ds->ds_num != xpath->values_len) {
-    WARNING("curl_xml plugin: DataSet `%s' requires %zu values, but config "
-            "talks about %zu",
+    WARNING("curl_xml plugin: DataSet `%s' requires %" PRIsz
+            " values, but config talks about %" PRIsz,
             xpath->type, ds->ds_num, xpath->values_len);
     return -1;
   }
index 517eec7..727876b 100644 (file)
 #include <statgrab.h>
 #endif
 
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+
 #ifndef COLLECTD_LOCALE
 #define COLLECTD_LOCALE "C"
 #endif
@@ -201,6 +205,7 @@ static int change_basedir(const char *orig_dir, _Bool create) {
 } /* static int change_basedir (char *dir) */
 
 #if HAVE_LIBKSTAT
+extern kstat_ctl_t *kc;
 static void update_kstat(void) {
   if (kc == NULL) {
     if ((kc = kstat_open()) == NULL)
@@ -367,7 +372,7 @@ static int notify_upstart(void) {
     return 0;
   }
 
-  NOTICE("Upstart detected, stopping now to signal readyness.");
+  NOTICE("Upstart detected, stopping now to signal readiness.");
   raise(SIGSTOP);
   unsetenv("UPSTART_JOB");
 
@@ -392,7 +397,7 @@ static int notify_systemd(void) {
           notifysocket);
     return 0;
   }
-  NOTICE("Systemd detected, trying to signal readyness.");
+  NOTICE("Systemd detected, trying to signal readiness.");
 
   unsetenv("NOTIFY_SOCKET");
 
index 60cebcf..fbbb608 100644 (file)
 #include <sys/capability.h>
 #endif
 
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+
 #ifdef HAVE_LIBKSTAT
 extern kstat_ctl_t *kc;
 #endif
@@ -889,7 +893,7 @@ int format_values(char *ret, size_t ret_len, /* {{{ */
       }
       BUFFER_ADD(":" GAUGE_FORMAT, rates[i]);
     } else if (ds->ds[i].type == DS_TYPE_COUNTER)
-      BUFFER_ADD(":%llu", vl->values[i].counter);
+      BUFFER_ADD(":%" PRIu64, (uint64_t)vl->values[i].counter);
     else if (ds->ds[i].type == DS_TYPE_DERIVE)
       BUFFER_ADD(":%" PRIi64, vl->values[i].derive);
     else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
index 4d2ccaa..af2840e 100644 (file)
 #include "common.h"
 #include "testing.h"
 
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+
 #if HAVE_LIBKSTAT
 kstat_ctl_t *kc;
 #endif /* HAVE_LIBKSTAT */
index bc11d6b..5a277c0 100644 (file)
 #define DATA_MAX_NAME_LEN 128
 #endif
 
+#ifndef PRIsz
+#define PRIsz "zu"
+#endif /* PRIsz */
+
 /* Type for time as used by "utils_time.h" */
 typedef uint64_t cdtime_t;
 
index 4b7a58e..438366c 100644 (file)
@@ -637,7 +637,7 @@ static void start_read_threads(size_t num) /* {{{ */
     }
 
     char name[THREAD_NAME_MAX];
-    snprintf(name, sizeof(name), "reader#%zu", read_threads_num);
+    snprintf(name, sizeof(name), "reader#%" PRIsz, read_threads_num);
     set_thread_name(read_threads[read_threads_num], name);
 
     read_threads_num++;
@@ -648,7 +648,7 @@ static void stop_read_threads(void) {
   if (read_threads == NULL)
     return;
 
-  INFO("collectd: Stopping %zu read threads.", read_threads_num);
+  INFO("collectd: Stopping %" PRIsz " read threads.", read_threads_num);
 
   pthread_mutex_lock(&read_lock);
   read_loop = 0;
@@ -843,7 +843,7 @@ static void start_write_threads(size_t num) /* {{{ */
     }
 
     char name[THREAD_NAME_MAX];
-    snprintf(name, sizeof(name), "writer#%zu", write_threads_num);
+    snprintf(name, sizeof(name), "writer#%" PRIsz, write_threads_num);
     set_thread_name(write_threads[write_threads_num], name);
 
     write_threads_num++;
@@ -858,7 +858,7 @@ static void stop_write_threads(void) /* {{{ */
   if (write_threads == NULL)
     return;
 
-  INFO("collectd: Stopping %zu write threads.", write_threads_num);
+  INFO("collectd: Stopping %" PRIsz " write threads.", write_threads_num);
 
   pthread_mutex_lock(&write_lock);
   write_loop = 0;
@@ -890,7 +890,7 @@ static void stop_write_threads(void) /* {{{ */
   pthread_mutex_unlock(&write_lock);
 
   if (i > 0) {
-    WARNING("plugin: %zu value list%s left after shutting down "
+    WARNING("plugin: %" PRIsz " value list%s left after shutting down "
             "the write threads.",
             i, (i == 1) ? " was" : "s were");
   }
@@ -1956,8 +1956,8 @@ static int plugin_dispatch_values_internal(value_list_t *vl) {
 #else
   if (ds->ds_num != vl->values_len) {
     ERROR("plugin_dispatch_values: ds->type = %s: "
-          "(ds->ds_num = %zu) != "
-          "(vl->values_len = %zu)",
+          "(ds->ds_num = %" PRIsz ") != "
+          "(vl->values_len = %" PRIsz ")",
           ds->type, ds->ds_num, vl->values_len);
     return -1;
   }
index 6df4c15..96bf382 100644 (file)
 
 #include "plugin.h"
 
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+
 #if HAVE_LIBKSTAT
 kstat_ctl_t *kc = NULL;
 #endif /* HAVE_LIBKSTAT */
index 3b3b8f4..1ccf10b 100644 (file)
@@ -39,7 +39,7 @@ static int parse_ds(data_source_t *dsrc, char *buf, size_t buf_len) {
   int fields_num;
 
   if (buf_len < 11) {
-    ERROR("parse_ds: (buf_len = %zu) < 11", buf_len);
+    ERROR("parse_ds: (buf_len = %" PRIsz ") < 11", buf_len);
     return -1;
   }
 
@@ -121,8 +121,8 @@ static void parse_line(char *buf) {
 
   for (size_t i = 0; i < ds->ds_num; i++)
     if (parse_ds(ds->ds + i, fields[i + 1], strlen(fields[i + 1])) != 0) {
-      ERROR("types_list: parse_line: Cannot parse data source #%zu "
-            "of data set %s",
+      ERROR("types_list: parse_line: Cannot parse data source #%" PRIsz
+            " of data set %s",
             i, ds->type);
       sfree(ds->ds);
       sfree(ds);
index ea7c3e3..b756d3b 100644 (file)
@@ -154,7 +154,7 @@ static int uc_insert(const data_set_t *ds, const value_list_t *vl,
   ce = cache_alloc(ds->ds_num);
   if (ce == NULL) {
     sfree(key_copy);
-    ERROR("uc_insert: cache_alloc (%zu) failed.", ds->ds_num);
+    ERROR("uc_insert: cache_alloc (%" PRIsz ") failed.", ds->ds_num);
     return -1;
   }
 
@@ -381,7 +381,7 @@ int uc_update(const data_set_t *ds, const value_list_t *vl) {
       return -1;
     } /* switch (ds->ds[i].type) */
 
-    DEBUG("uc_update: %s: ds[%zu] = %lf", name, i, ce->values_gauge[i]);
+    DEBUG("uc_update: %s: ds[%" PRIsz "] = %lf", name, i, ce->values_gauge[i]);
   } /* for (i) */
 
   /* Update the history if it exists. */
@@ -469,8 +469,8 @@ 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 != ds->ds_num) {
-    ERROR("utils_cache: uc_get_rate: ds[%s] has %zu values, "
-          "but uc_get_rate_by_name returned %zu.",
+    ERROR("utils_cache: uc_get_rate: ds[%s] has %" PRIsz " values, "
+          "but uc_get_rate_by_name returned %" PRIsz ".",
           ds->type, ds->ds_num, ret_num);
     sfree(ret);
     return NULL;
@@ -488,7 +488,7 @@ int uc_get_value_by_name(const char *name, value_t **ret_values,
 
   pthread_mutex_lock(&cache_lock);
 
-  if (c_avl_get(cache_tree, name, (void *) &ce) == 0) {
+  if (c_avl_get(cache_tree, name, (void *)&ce) == 0) {
     assert(ce != NULL);
 
     /* remove missing values from getval */
@@ -504,8 +504,7 @@ int uc_get_value_by_name(const char *name, value_t **ret_values,
         memcpy(ret, ce->values_raw, ret_num * sizeof(value_t));
       }
     }
-  }
-  else {
+  } else {
     DEBUG("utils_cache: uc_get_value_by_name: No such value: %s", name);
     status = -1;
   }
@@ -537,10 +536,10 @@ value_t *uc_get_value(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) {
-    ERROR("utils_cache: uc_get_value: ds[%s] has %zu values, "
-          "but uc_get_value_by_name returned %zu.", ds->type, ds->ds_num,
-          ret_num);
+  if (ret_num != (size_t)ds->ds_num) {
+    ERROR("utils_cache: uc_get_value: ds[%s] has %" PRIsz " values, "
+          "but uc_get_value_by_name returned %" PRIsz ".",
+          ds->type, ds->ds_num, ret_num);
     sfree(ret);
     return (NULL);
   }
index a016342..546ca18 100644 (file)
@@ -152,7 +152,7 @@ char *subst_string(char *buf, size_t buflen, const char *string,
   }
 
   if (i >= buflen) {
-    WARNING("subst_string: Loop exited after %zu iterations: "
+    WARNING("subst_string: Loop exited after %" PRIsz " iterations: "
             "string = %s; needle = %s; replacement = %s;",
             i, string, needle, replacement);
   }
index 00ea0ea..2056096 100644 (file)
  *   Florian octo Forster <octo at collectd.org>
  */
 
-#include "common.h" /* for STATIC_ARRAY_SIZE */
 #include "collectd.h"
+#include "common.h" /* for STATIC_ARRAY_SIZE */
 
 #include "testing.h"
 #include "utils_subst.h"
 
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+
 #if HAVE_LIBKSTAT
 kstat_ctl_t *kc;
 #endif /* HAVE_LIBKSTAT */
index 62ef1dc..60324e8 100644 (file)
--- a/src/dbi.c
+++ b/src/dbi.c
@@ -497,8 +497,8 @@ static int cdbi_read_database_query(cdbi_database_t *db, /* {{{ */
     }
 
     column_num = (size_t)db_status;
-    DEBUG("cdbi_read_database_query (%s, %s): There are %zu columns.", db->name,
-          udb_query_get_name(q), column_num);
+    DEBUG("cdbi_read_database_query (%s, %s): There are %" PRIsz " columns.",
+          db->name, udb_query_get_name(q), column_num);
   }
 
   /* Allocate `column_names' and `column_values'. {{{ */
@@ -539,7 +539,7 @@ static int cdbi_read_database_query(cdbi_database_t *db, /* {{{ */
     column_name = dbi_result_get_field_name(res, (unsigned int)(i + 1));
     if (column_name == NULL) {
       ERROR("dbi plugin: cdbi_read_database_query (%s, %s): "
-            "Cannot retrieve name of field %zu.",
+            "Cannot retrieve name of field %" PRIsz ".",
             db->name, udb_query_get_name(q), i + 1);
       BAIL_OUT(-1);
     }
@@ -579,7 +579,7 @@ static int cdbi_read_database_query(cdbi_database_t *db, /* {{{ */
 
       if (status != 0) {
         ERROR("dbi plugin: cdbi_read_database_query (%s, %s): "
-              "cdbi_result_get_field (%zu) failed.",
+              "cdbi_result_get_field (%" PRIsz ") failed.",
               db->name, udb_query_get_name(q), i + 1);
         status = -1;
         break;
index db8e519..e1d5b51 100644 (file)
--- a/src/df.c
+++ b/src/df.c
@@ -152,6 +152,7 @@ static int df_read(void) {
 #elif HAVE_STATFS
   struct statfs statbuf;
 #endif
+  int retval = 0;
   /* struct STATANYFS statbuf; */
   cu_mount_t *mnt_list;
 
@@ -282,8 +283,10 @@ static int df_read(void) {
             (gauge_t)((float_t)(blk_reserved) / statbuf.f_blocks * 100));
         df_submit_one(disk_name, "percent_bytes", "used",
                       (gauge_t)((float_t)(blk_used) / statbuf.f_blocks * 100));
-      } else
-        return -1;
+      } else {
+        retval = -1;
+        break;
+      }
     }
 
     /* inode handling */
@@ -313,8 +316,10 @@ static int df_read(void) {
           df_submit_one(
               disk_name, "percent_inodes", "used",
               (gauge_t)((float_t)(inode_used) / statbuf.f_files * 100));
-        } else
-          return -1;
+        } else {
+          retval = -1;
+          break;
+        }
       }
       if (values_absolute) {
         df_submit_one(disk_name, "df_inodes", "free", (gauge_t)inode_free);
@@ -327,7 +332,7 @@ static int df_read(void) {
 
   cu_mount_freelist(mnt_list);
 
-  return 0;
+  return retval;
 } /* int df_read */
 
 void module_register(void) {
index 004ce9e..45706bc 100644 (file)
@@ -120,6 +120,9 @@ static struct gmesh geom_tree;
 /* #endif KERNEL_FREEBSD */
 
 #elif HAVE_LIBKSTAT
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
 #define MAX_NUMDISK 1024
 extern kstat_ctl_t *kc;
 static kstat_t *ksp[MAX_NUMDISK];
index 134801b..59ab976 100644 (file)
@@ -429,7 +429,7 @@ static int dpdk_stats_reinit_helper() {
   size_t data_size = sizeof(dpdk_stats_ctx_t) +
                      (ctx->stats_count * DPDK_STATS_CTX_GET_XSTAT_SIZE);
 
-  DEBUG("%s:%d helper reinit (new_size=%zu)", __FUNCTION__, __LINE__,
+  DEBUG("%s:%d helper reinit (new_size=%" PRIsz ")", __FUNCTION__, __LINE__,
         data_size);
 
   dpdk_stats_ctx_t tmp_ctx;
index 5a0eac3..69dc4ef 100644 (file)
@@ -72,7 +72,7 @@ static int drbd_submit_fields(long int resource, char **fields,
 
   if (fields_num != drbd_names_num) {
     WARNING("drbd plugin: Wrong number of fields for "
-            "r%ld statistics. Expected %zu, got %zu.",
+            "r%ld statistics. Expected %" PRIsz ", got %" PRIsz ".",
             resource, drbd_names_num, fields_num);
     return EINVAL;
   }
index c0f28d0..d94c542 100644 (file)
@@ -274,7 +274,7 @@ static void *collect(void *arg) {
 
       len = strlen(line);
       if ((line[len - 1] != '\n') && (line[len - 1] != '\r')) {
-        log_warn("collect: line too long (> %zu characters): "
+        log_warn("collect: line too long (> %" PRIsz " characters): "
                  "'%s' (truncated)",
                  sizeof(line) - 1, line);
 
@@ -297,22 +297,21 @@ static void *collect(void *arg) {
       }
 
       if (line[0] == 'e') { /* e:<type>:<bytes> */
-        char *ptr = NULL;
-        char *type = strtok_r(line + 2, ":", &ptr);
-        char *tmp = strtok_r(NULL, ":", &ptr);
-        int bytes = 0;
-
-        if (tmp == NULL) {
+        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);
@@ -370,7 +369,9 @@ static void *open_connection(void __attribute__((unused)) * arg) {
     pthread_exit((void *)1);
   }
 
-  struct sockaddr_un addr = {.sun_family = AF_UNIX};
+  struct sockaddr_un addr = {
+      .sun_family = AF_UNIX,
+  };
   sstrncpy(addr.sun_path, path, (size_t)(UNIX_PATH_MAX - 1));
 
   errno = 0;
index db093aa..36f2d4d 100644 (file)
@@ -788,7 +788,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) */
 
@@ -827,8 +831,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 09f94ae..cb005fd 100644 (file)
@@ -454,7 +454,8 @@ static int staging_entry_update(const char *host, const char *name, /* {{{ */
   }
 
   if (ds->ds_num <= ds_index) {
-    ERROR("gmond plugin: Invalid index %zu: %s has only %zu data source(s).",
+    ERROR("gmond plugin: Invalid index %" PRIsz ": %s has only %" PRIsz
+          " data source(s).",
           ds_index, ds->type, ds->ds_num);
     return -1;
   }
index 0f5cfec..977c5b2 100644 (file)
@@ -56,7 +56,8 @@ using collectd::QueryValuesResponse;
 
 using google::protobuf::util::TimeUtil;
 
-typedef google::protobuf::Map<grpc::string, collectd::types::MetadataValue> grpcMetadata;
+typedef google::protobuf::Map<grpc::string, collectd::types::MetadataValue>
+    grpcMetadata;
 
 /*
  * private types
@@ -175,10 +176,11 @@ static grpc::Status marshal_meta_data(meta_data_t *meta,
     switch (md_type) {
     case MD_TYPE_STRING:
       char *md_string;
-      if (meta_data_get_string(meta, key, &md_string) != 0 || md_string == nullptr) {
+      if (meta_data_get_string(meta, key, &md_string) != 0 ||
+          md_string == nullptr) {
         strarray_free(meta_data_keys, meta_data_keys_len);
         return grpc::Status(grpc::StatusCode::INTERNAL,
-                          grpc::string("missing metadata"));
+                            grpc::string("missing metadata"));
       }
       md_value.set_string_value(md_string);
       free(md_string);
@@ -188,7 +190,7 @@ static grpc::Status marshal_meta_data(meta_data_t *meta,
       if (meta_data_get_signed_int(meta, key, &int64_value) != 0) {
         strarray_free(meta_data_keys, meta_data_keys_len);
         return grpc::Status(grpc::StatusCode::INTERNAL,
-                          grpc::string("missing metadata"));
+                            grpc::string("missing metadata"));
       }
       md_value.set_int64_value(int64_value);
       break;
@@ -197,7 +199,7 @@ static grpc::Status marshal_meta_data(meta_data_t *meta,
       if (meta_data_get_unsigned_int(meta, key, &uint64_value) != 0) {
         strarray_free(meta_data_keys, meta_data_keys_len);
         return grpc::Status(grpc::StatusCode::INTERNAL,
-                          grpc::string("missing metadata"));
+                            grpc::string("missing metadata"));
       }
       md_value.set_uint64_value(uint64_value);
       break;
@@ -206,7 +208,7 @@ static grpc::Status marshal_meta_data(meta_data_t *meta,
       if (meta_data_get_double(meta, key, &double_value) != 0) {
         strarray_free(meta_data_keys, meta_data_keys_len);
         return grpc::Status(grpc::StatusCode::INTERNAL,
-                          grpc::string("missing metadata"));
+                            grpc::string("missing metadata"));
       }
       md_value.set_double_value(double_value);
       break;
@@ -215,7 +217,7 @@ static grpc::Status marshal_meta_data(meta_data_t *meta,
       if (meta_data_get_boolean(meta, key, &bool_value) != 0) {
         strarray_free(meta_data_keys, meta_data_keys_len);
         return grpc::Status(grpc::StatusCode::INTERNAL,
-                          grpc::string("missing metadata"));
+                            grpc::string("missing metadata"));
       }
       md_value.set_bool_value(bool_value);
       break;
@@ -239,9 +241,9 @@ static grpc::Status unmarshal_meta_data(const grpcMetadata &rpc_metadata,
   *md_out = meta_data_create();
   if (*md_out == nullptr) {
     return grpc::Status(grpc::StatusCode::RESOURCE_EXHAUSTED,
-                        grpc::string("failed to metadata list"));
+                        grpc::string("failed to create metadata list"));
   }
-  for (auto kv: rpc_metadata) {
+  for (auto kv : rpc_metadata) {
     auto k = kv.first.c_str();
     auto v = kv.second;
 
@@ -267,8 +269,8 @@ static grpc::Status unmarshal_meta_data(const grpcMetadata &rpc_metadata,
       break;
     default:
       meta_data_destroy(*md_out);
-      return  grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
-                           grpc::string("Metadata of unknown type"));
+      return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+                          grpc::string("Metadata of unknown type"));
     }
   }
   return grpc::Status::OK;
@@ -482,8 +484,9 @@ private:
         break;
       }
       if (uc_iterator_get_meta(iter, &vl.meta) < 0) {
-        status = grpc::Status(grpc::StatusCode::INTERNAL,
-                              grpc::string("failed to retrieve value metadata"));
+        status =
+            grpc::Status(grpc::StatusCode::INTERNAL,
+                         grpc::string("failed to retrieve value metadata"));
       }
 
       value_lists->push(vl);
@@ -626,7 +629,8 @@ static int c_grpc_config_listen(oconfig_item_t *ci) {
   listener.port = grpc::string(ci->values[1].value.string);
   listener.ssl = nullptr;
 
-  auto ssl_opts = new (grpc::SslServerCredentialsOptions);
+  auto ssl_opts = new grpc::SslServerCredentialsOptions(
+      GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
   grpc::SslServerCredentialsOptions::PemKeyCertPair pkcp = {};
   bool use_ssl = false;
 
@@ -659,6 +663,14 @@ static int c_grpc_config_listen(oconfig_item_t *ci) {
         return -1;
       }
       pkcp.cert_chain = read_file(cert);
+    } else if (!strcasecmp("VerifyPeer", child->key)) {
+      _Bool verify = 0;
+      if (cf_util_get_boolean(child, &verify)) {
+        return -1;
+      }
+      ssl_opts->client_certificate_request =
+          verify ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
+                 : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE;
     } else {
       WARNING("grpc: Option `%s` not allowed in <%s> block.", child->key,
               ci->key);
index fd2bd6f..d868c89 100644 (file)
@@ -192,7 +192,8 @@ static void pmu_dump_config(void) {
   DEBUG(PMU_PLUGIN ":   software_events   : %d", g_ctx.sw_events);
 
   for (size_t i = 0; i < g_ctx.hw_events_count; i++) {
-    DEBUG(PMU_PLUGIN ":   hardware_events[%zu]: %s", i, g_ctx.hw_events[i]);
+    DEBUG(PMU_PLUGIN ":   hardware_events[%" PRIsz "]: %s", i,
+          g_ctx.hw_events[i]);
   }
 }
 
@@ -204,6 +205,11 @@ static int pmu_config_hw_events(oconfig_item_t *ci) {
     return -EINVAL;
   }
 
+  if (g_ctx.hw_events) {
+    ERROR(PMU_PLUGIN ": Duplicate config for HardwareEvents.");
+    return -EINVAL;
+  }
+
   g_ctx.hw_events = calloc(ci->values_num, sizeof(char *));
   if (g_ctx.hw_events == NULL) {
     ERROR(PMU_PLUGIN ": Failed to allocate hw events.");
@@ -401,12 +407,6 @@ static int pmu_add_hw_events(struct eventlist *el, char **e, size_t count) {
     char *s, *tmp;
     for (s = strtok_r(events, ",", &tmp); s; s = strtok_r(NULL, ",", &tmp)) {
 
-      /* Multiple events parsed in one entry */
-      if (group_events_count == 1) {
-        /* Mark previously added event as group leader */
-        el->eventlist_last->group_leader = 1;
-      }
-
       /* Allocate memory for event struct that contains array of efd structs
          for all cores */
       struct event *e =
@@ -416,19 +416,26 @@ static int pmu_add_hw_events(struct eventlist *el, char **e, size_t count) {
         return -ENOMEM;
       }
 
-      if (resolve_event(s, &e->attr) == 0) {
-        e->next = NULL;
-        if (!el->eventlist)
-          el->eventlist = e;
-        if (el->eventlist_last)
-          el->eventlist_last->next = e;
-        el->eventlist_last = e;
-        e->event = strdup(s);
-      } else {
-        DEBUG(PMU_PLUGIN ": Cannot resolve %s", s);
+      if (resolve_event(s, &e->attr) != 0) {
+        WARNING(PMU_PLUGIN ": Cannot resolve %s", s);
         sfree(e);
+        continue;
       }
 
+      /* Multiple events parsed in one entry */
+      if (group_events_count == 1) {
+        /* Mark previously added event as group leader */
+        el->eventlist_last->group_leader = 1;
+      }
+
+      e->next = NULL;
+      if (!el->eventlist)
+        el->eventlist = e;
+      if (el->eventlist_last)
+        el->eventlist_last->next = e;
+      el->eventlist_last = e;
+      e->event = strdup(s);
+
       group_events_count++;
     }
 
index a3f77c9..29c02fe 100644 (file)
@@ -25,8 +25,8 @@
  *   Serhiy Pshyk <serhiyx.pshyk@intel.com>
  **/
 
-#include "common.h"
 #include "collectd.h"
+#include "common.h"
 
 #include <pqos.h>
 
@@ -308,7 +308,7 @@ static void rdt_dump_cgroups(void) {
     return;
 
   DEBUG(RDT_PLUGIN ": Core Groups Dump");
-  DEBUG(RDT_PLUGIN ":  groups count: %zu", g_rdt->num_groups);
+  DEBUG(RDT_PLUGIN ":  groups count: %" PRIsz, g_rdt->num_groups);
 
   for (int i = 0; i < g_rdt->num_groups; i++) {
 
@@ -426,8 +426,8 @@ static int rdt_config_cgroups(oconfig_item_t *item) {
          core_idx++) {
       if (!rdt_is_core_id_valid(g_rdt->cgroups[group_idx].cores[core_idx])) {
         ERROR(RDT_PLUGIN ": Core group '%s' contains invalid core id '%d'",
-                g_rdt->cgroups[group_idx].desc,
-                (int)g_rdt->cgroups[group_idx].cores[core_idx]);
+              g_rdt->cgroups[group_idx].desc,
+              (int)g_rdt->cgroups[group_idx].cores[core_idx]);
         rdt_free_cgroups();
         return -EINVAL;
       }
index 6c80334..c45ef66 100644 (file)
@@ -91,6 +91,9 @@ static ignorelist_t *ignorelist = NULL;
 static _Bool report_inactive = 1;
 
 #ifdef HAVE_LIBKSTAT
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
 #define MAX_NUMIF 256
 extern kstat_ctl_t *kc;
 static kstat_t *ksp[MAX_NUMIF];
index f28ac52..2db344e 100644 (file)
@@ -1065,7 +1065,7 @@ static int c_ipmi_config_add_instance(oconfig_item_t *ci) {
     oconfig_item_t *child = ci->children + i;
 
     if (strcasecmp("Sensor", child->key) == 0)
-      ignorelist_add(st->ignorelist, ci->values[0].value.string);
+      ignorelist_add(st->ignorelist, child->values[0].value.string);
     else if (strcasecmp("IgnoreSelected", child->key) == 0) {
       _Bool t;
       status = cf_util_get_boolean(child, &t);
index c7b0be3..a35ca46 100644 (file)
@@ -1840,7 +1840,8 @@ static int cjni_create_jvm(void) /* {{{ */
   vm_args.nOptions = (jint)jvm_argc;
 
   for (size_t i = 0; i < jvm_argc; i++) {
-    DEBUG("java plugin: cjni_create_jvm: jvm_argv[%zu] = %s", i, jvm_argv[i]);
+    DEBUG("java plugin: cjni_create_jvm: jvm_argv[%" PRIsz "] = %s", i,
+          jvm_argv[i]);
     vm_args.options[i].optionString = jvm_argv[i];
   }
 
@@ -2183,8 +2184,9 @@ static int cjni_config_perform(oconfig_item_t *ci) /* {{{ */
     }
   }
 
-  DEBUG("java plugin: jvm_argc = %zu;", jvm_argc);
-  DEBUG("java plugin: java_classes_list_len = %zu;", java_classes_list_len);
+  DEBUG("java plugin: jvm_argc = %" PRIsz ";", jvm_argc);
+  DEBUG("java plugin: java_classes_list_len = %" PRIsz ";",
+        java_classes_list_len);
 
   if ((success == 0) && (errors > 0)) {
     ERROR("java plugin: All statements failed.");
index 2365ab0..49b1a00 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "collectd/lcc_features.h"
 #include "collectd/network_parse.h"
+#include "globals.h"
 
 #include <errno.h>
 #include <math.h>
@@ -449,7 +450,7 @@ static int decrypt_aes256(buffer_t *b, void *iv, size_t iv_size,
   uint8_t pwhash[32] = {0};
   gcry_md_hash_buffer(GCRY_MD_SHA256, pwhash, password, strlen(password));
 
-  fprintf(stderr, "sizeof(iv) = %zu\n", sizeof(iv));
+  fprintf(stderr, "sizeof(iv) = %" PRIsz "\n", sizeof(iv));
   if (gcry_cipher_setkey(cipher, pwhash, sizeof(pwhash)) ||
       gcry_cipher_setiv(cipher, iv, iv_size) ||
       gcry_cipher_decrypt(cipher, b->data, b->len, /* in = */ NULL,
@@ -534,7 +535,7 @@ static int network_parse(void *data, size_t data_size, lcc_security_level_t sl,
 
     if ((sz < 5) || (((size_t)sz - 4) > b->len)) {
       DEBUG("lcc_network_parse(): invalid 'sz' field: sz = %" PRIu16
-            ", b->len = %zu\n",
+            ", b->len = %" PRIsz "\n",
             sz, b->len);
       return EINVAL;
     }
index 07010fb..a638642 100644 (file)
@@ -245,10 +245,9 @@ static int test_network_parse() {
     uint8_t buffer[LCC_NETWORK_BUFFER_SIZE_DEFAULT];
     size_t buffer_size = sizeof(buffer);
     if (decode_string(raw_packet_data[i], buffer, &buffer_size)) {
-      fprintf(
-          stderr,
-          "lcc_network_parse(raw_packet_data[%zu]): decoding string failed\n",
-          i);
+      fprintf(stderr, "lcc_network_parse(raw_packet_data[%" PRIsz "]):"
+                      " decoding string failed\n",
+              i);
       return -1;
     }
 
@@ -257,12 +256,13 @@ static int test_network_parse() {
                                                    .writer = nop_writer,
                                                });
     if (status != 0) {
-      fprintf(stderr, "lcc_network_parse(raw_packet_data[%zu]) = %d, want 0\n",
+      fprintf(stderr,
+              "lcc_network_parse(raw_packet_data[%" PRIsz "]) = %d, want 0\n",
               i, status);
       ret = status;
     }
 
-    printf("ok - lcc_network_parse(raw_packet_data[%zu])\n", i);
+    printf("ok - lcc_network_parse(raw_packet_data[%" PRIsz "])\n", i);
   }
 
   return ret;
@@ -376,7 +376,7 @@ static int test_parse_values() {
   }
 
   if (vl.values_len != 3) {
-    fprintf(stderr, "parse_values(): vl.values_len = %zu, want 3\n",
+    fprintf(stderr, "parse_values(): vl.values_len = %" PRIsz ", want 3\n",
             vl.values_len);
     return -1;
   }
@@ -384,7 +384,8 @@ static int test_parse_values() {
   int want_types[] = {LCC_TYPE_GAUGE, LCC_TYPE_DERIVE, LCC_TYPE_GAUGE};
   for (size_t i = 0; i < sizeof(want_types) / sizeof(want_types[0]); i++) {
     if (vl.values_types[i] != want_types[i]) {
-      fprintf(stderr, "parse_values(): vl.values_types[%zu] = %d, want %d\n", i,
+      fprintf(stderr,
+              "parse_values(): vl.values_types[%" PRIsz "] = %d, want %d\n", i,
               vl.values_types[i], want_types[i]);
       ret = -1;
     }
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 d62b25d..635088e 100644 (file)
@@ -285,6 +285,12 @@ static int memcached_query_daemon(char *buffer, size_t buffer_size,
       close(st->fd);
       st->fd = -1;
       return -1;
+    } else if (status == 0) {
+      ERROR("memcached plugin: Instance \"%s\": Connection closed by peer",
+            st->name);
+      close(st->fd);
+      st->fd = -1;
+      return -1;
     }
 
     buffer_fill += (size_t)status;
index ad5e58e..daa3c02 100644 (file)
 enum mb_register_type_e /* {{{ */
 { REG_TYPE_INT16,
   REG_TYPE_INT32,
+  REG_TYPE_INT32_CDAB,
   REG_TYPE_UINT16,
   REG_TYPE_UINT32,
-  REG_TYPE_FLOAT }; /* }}} */
+  REG_TYPE_UINT32_CDAB,
+  REG_TYPE_FLOAT,
+  REG_TYPE_FLOAT_CDAB }; /* }}} */
+
 enum mb_mreg_type_e /* {{{ */
 { MREG_HOLDING,
   MREG_INPUT }; /* }}} */
@@ -417,7 +421,7 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
   }
 
   if (ds->ds_num != 1) {
-    ERROR("Modbus plugin: The type \"%s\" has %zu data sources. "
+    ERROR("Modbus plugin: The type \"%s\" has %" PRIsz " data sources. "
           "I can only handle data sets with only one data source.",
           data->type, ds->ds_num);
     return -1;
@@ -425,7 +429,9 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
 
   if ((ds->ds[0].type != DS_TYPE_GAUGE) &&
       (data->register_type != REG_TYPE_INT32) &&
-      (data->register_type != REG_TYPE_UINT32)) {
+      (data->register_type != REG_TYPE_INT32_CDAB) &&
+      (data->register_type != REG_TYPE_UINT32) &&
+      (data->register_type != REG_TYPE_UINT32_CDAB)) {
     NOTICE(
         "Modbus plugin: The data source of type \"%s\" is %s, not gauge. "
         "This will most likely result in problems, because the register type "
@@ -434,8 +440,11 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
   }
 
   if ((data->register_type == REG_TYPE_INT32) ||
+      (data->register_type == REG_TYPE_INT32_CDAB) ||
       (data->register_type == REG_TYPE_UINT32) ||
-      (data->register_type == REG_TYPE_FLOAT))
+      (data->register_type == REG_TYPE_UINT32_CDAB) ||
+      (data->register_type == REG_TYPE_FLOAT) ||
+      (data->register_type == REG_TYPE_FLOAT_CDAB))
     values_num = 2;
   else
     values_num = 1;
@@ -496,8 +505,8 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
   }
   if (status != values_num) {
     ERROR("Modbus plugin: modbus read function (%s/%s) failed. "
-          " status = %i, values_num = %i. Giving up.",
-          host->host, host->node, status, values_num);
+          " status = %i, start_addr = %i, values_num = %i. Giving up.",
+          host->host, host->node, status, data->register_base, values_num);
 #if LEGACY_LIBMODBUS
     modbus_close(&host->connection);
 #else
@@ -523,6 +532,17 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
 
     CAST_TO_VALUE_T(ds, vt, float_value);
     mb_submit(host, slave, data, vt);
+  } else if (data->register_type == REG_TYPE_FLOAT_CDAB) {
+    float float_value;
+    value_t vt;
+
+    float_value = mb_register_to_float(values[1], values[0]);
+    DEBUG("Modbus plugin: mb_read_data: "
+          "Returned float value is %g",
+          (double)float_value);
+
+    CAST_TO_VALUE_T(ds, vt, float_value);
+    mb_submit(host, slave, data, vt);
   } else if (data->register_type == REG_TYPE_INT32) {
     union {
       uint32_t u32;
@@ -537,6 +557,20 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
 
     CAST_TO_VALUE_T(ds, vt, v.i32);
     mb_submit(host, slave, data, vt);
+  } else if (data->register_type == REG_TYPE_INT32_CDAB) {
+    union {
+      uint32_t u32;
+      int32_t i32;
+    } v;
+    value_t vt;
+
+    v.u32 = (((uint32_t)values[1]) << 16) | ((uint32_t)values[0]);
+    DEBUG("Modbus plugin: mb_read_data: "
+          "Returned int32 value is %" PRIi32,
+          v.i32);
+
+    CAST_TO_VALUE_T(ds, vt, v.i32);
+    mb_submit(host, slave, data, vt);
   } else if (data->register_type == REG_TYPE_INT16) {
     union {
       uint16_t u16;
@@ -563,6 +597,17 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */
 
     CAST_TO_VALUE_T(ds, vt, v32);
     mb_submit(host, slave, data, vt);
+  } else if (data->register_type == REG_TYPE_UINT32_CDAB) {
+    uint32_t v32;
+    value_t vt;
+
+    v32 = (((uint32_t)values[1]) << 16) | ((uint32_t)values[0]);
+    DEBUG("Modbus plugin: mb_read_data: "
+          "Returned uint32 value is %" PRIu32,
+          v32);
+
+    CAST_TO_VALUE_T(ds, vt, v32);
+    mb_submit(host, slave, data, vt);
   } else /* if (data->register_type == REG_TYPE_UINT16) */
   {
     value_t vt;
@@ -702,12 +747,18 @@ static int mb_config_add_data(oconfig_item_t *ci) /* {{{ */
         data.register_type = REG_TYPE_INT16;
       else if (strcasecmp("Int32", tmp) == 0)
         data.register_type = REG_TYPE_INT32;
+      else if (strcasecmp("Int32LE", tmp) == 0)
+        data.register_type = REG_TYPE_INT32_CDAB;
       else if (strcasecmp("Uint16", tmp) == 0)
         data.register_type = REG_TYPE_UINT16;
       else if (strcasecmp("Uint32", tmp) == 0)
         data.register_type = REG_TYPE_UINT32;
+      else if (strcasecmp("Uint32LE", tmp) == 0)
+        data.register_type = REG_TYPE_UINT32_CDAB;
       else if (strcasecmp("Float", tmp) == 0)
         data.register_type = REG_TYPE_FLOAT;
+      else if (strcasecmp("FloatLE", tmp) == 0)
+        data.register_type = REG_TYPE_FLOAT_CDAB;
       else {
         ERROR("Modbus plugin: The register type \"%s\" is unknown.", tmp);
         status = -1;
index 7fe6d76..448f7cb 100644 (file)
@@ -270,12 +270,16 @@ static MYSQL *getconnection(mysql_database_t *db) {
   }
   db->is_connected = 0;
 
+  /* Close the old connection before initializing a new one. */
+  if (db->con != NULL) {
+    mysql_close(db->con);
+    db->con = NULL;
+  }
+
+  db->con = mysql_init(NULL);
   if (db->con == NULL) {
-    db->con = mysql_init(NULL);
-    if (db->con == NULL) {
-      ERROR("mysql plugin: mysql_init failed: %s", mysql_error(db->con));
-      return NULL;
-    }
+    ERROR("mysql plugin: mysql_init failed: %s", mysql_error(db->con));
+    return NULL;
   }
 
   /* Configure TCP connect timeout (default: 0) */
index b5ae3bd..1978eb4 100644 (file)
@@ -358,10 +358,9 @@ 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: %s",
-            sstrerror(errno, errbuf, sizeof(errbuf)));
+            STRERRNO);
       return MNL_CB_ERROR;
     }
     stats.stats64 = mnl_attr_get_payload(attr);
@@ -376,10 +375,9 @@ 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: %s",
-            sstrerror(errno, errbuf, sizeof(errbuf)));
+            STRERRNO);
       return MNL_CB_ERROR;
     }
     stats.stats32 = mnl_attr_get_payload(attr);
@@ -404,10 +402,9 @@ 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(*q_stats->bs)) < 0) {
-      char errbuf[1024];
       ERROR("netlink plugin: qos_attr_cb: TCA_STATS_BASIC mnl_attr_validate2 "
             "failed: %s",
-            sstrerror(errno, errbuf, sizeof(errbuf)));
+            STRERRNO);
       return MNL_CB_ERROR;
     }
     q_stats->bs = mnl_attr_get_payload(attr);
@@ -464,7 +461,7 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) {
 
   if ((tm->tcm_ifindex >= 0) && ((size_t)tm->tcm_ifindex >= iflist_len)) {
     ERROR("netlink plugin: qos_filter_cb: tm->tcm_ifindex = %i "
-          ">= iflist_len = %zu",
+          ">= iflist_len = %" PRIsz,
           tm->tcm_ifindex, iflist_len);
     return MNL_CB_ERROR;
   }
@@ -556,10 +553,9 @@ 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: %s",
-            sstrerror(errno, errbuf, sizeof(errbuf)));
+            STRERRNO);
       return MNL_CB_ERROR;
     }
     ts = mnl_attr_get_payload(attr);
@@ -694,9 +690,7 @@ static int ir_read(void) {
     ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
   }
   if (ret < 0) {
-    char errbuf[1024];
-    ERROR("netlink plugin: ir_read: mnl_socket_recvfrom failed: %s",
-          sstrerror(errno, errbuf, sizeof(errbuf)));
+    ERROR("netlink plugin: ir_read: mnl_socket_recvfrom failed: %s", STRERRNO);
     return (-1);
   }
 
@@ -717,7 +711,7 @@ static int ir_read(void) {
         continue;
       }
 
-      DEBUG("netlink plugin: ir_read: querying %s from %s (%zu).",
+      DEBUG("netlink plugin: ir_read: querying %s from %s (%" PRIsz ").",
             type_name[type_index], iflist[ifindex], ifindex);
 
       nlh = mnl_nlmsg_put_header(buf);
@@ -741,9 +735,8 @@ static int ir_read(void) {
         ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
       }
       if (ret < 0) {
-        char errbuf[1024];
         ERROR("netlink plugin: ir_read: mnl_socket_recvfrom failed: %s",
-              sstrerror(errno, errbuf, sizeof(errbuf)));
+              STRERRNO);
         continue;
       }
     } /* for (type_index) */
index e5b8b3a..fcacd38 100644 (file)
@@ -753,7 +753,7 @@ static int parse_part_values(void **ret_buffer, size_t *ret_buffer_len,
 
   if (buffer_len < 15) {
     NOTICE("network plugin: packet is too short: "
-           "buffer_len = %zu",
+           "buffer_len = %" PRIsz,
            buffer_len);
     return -1;
   }
@@ -777,8 +777,8 @@ static int parse_part_values(void **ret_buffer, size_t *ret_buffer_len,
   if (buffer_len < exp_size) {
     WARNING("network plugin: parse_part_values: "
             "Packet too short: "
-            "Chunk of size %zu expected, "
-            "but buffer has only %zu bytes left.",
+            "Chunk of size %" PRIsz " expected, "
+            "but buffer has only %" PRIsz " bytes left.",
             exp_size, buffer_len);
     return -1;
   }
@@ -857,8 +857,8 @@ static int parse_part_number(void **ret_buffer, size_t *ret_buffer_len,
   if (buffer_len < exp_size) {
     WARNING("network plugin: parse_part_number: "
             "Packet too short: "
-            "Chunk of size %zu expected, "
-            "but buffer has only %zu bytes left.",
+            "Chunk of size %" PRIsz " expected, "
+            "but buffer has only %" PRIsz " bytes left.",
             exp_size, buffer_len);
     return -1;
   }
@@ -898,8 +898,8 @@ static int parse_part_string(void **ret_buffer, size_t *ret_buffer_len,
   if (buffer_len < header_size) {
     WARNING("network plugin: parse_part_string: "
             "Packet too short: "
-            "Chunk of at least size %zu expected, "
-            "but buffer has only %zu bytes left.",
+            "Chunk of at least size %" PRIsz " expected, "
+            "but buffer has only %" PRIsz " bytes left.",
             header_size, buffer_len);
     return -1;
   }
@@ -918,7 +918,7 @@ static int parse_part_string(void **ret_buffer, size_t *ret_buffer_len,
     WARNING("network plugin: parse_part_string: "
             "Packet too big: "
             "Chunk of size %" PRIu16 " received, "
-            "but buffer has only %zu bytes left.",
+            "but buffer has only %" PRIsz " bytes left.",
             pkg_length, buffer_len);
     return -1;
   }
@@ -939,9 +939,9 @@ static int parse_part_string(void **ret_buffer, size_t *ret_buffer_len,
   if (output_len < payload_size) {
     WARNING("network plugin: parse_part_string: "
             "Buffer too small: "
-            "Output buffer holds %zu bytes, "
+            "Output buffer holds %" PRIsz " bytes, "
             "which is too small to hold the received "
-            "%zu byte string.",
+            "%" PRIsz " byte string.",
             output_len, payload_size);
     return -1;
   }
@@ -2447,7 +2447,7 @@ static void network_send_buffer_encrypted(sockent_t *se, /* {{{ */
 
   assert(buffer_size <= sizeof(buffer));
   DEBUG("network plugin: network_send_buffer_encrypted: "
-        "buffer_size = %zu;",
+        "buffer_size = %" PRIsz ";",
         buffer_size);
 
   pea.head.length = htons(
@@ -2498,7 +2498,8 @@ static void network_send_buffer_encrypted(sockent_t *se, /* {{{ */
 
 static void network_send_buffer(char *buffer, size_t buffer_len) /* {{{ */
 {
-  DEBUG("network plugin: network_send_buffer: buffer_len = %zu", buffer_len);
+  DEBUG("network plugin: network_send_buffer: buffer_len = %" PRIsz,
+        buffer_len);
 
   for (sockent_t *se = sending_sockets; se != NULL; se = se->next) {
 #if HAVE_GCRYPT_H
index b556307..f50a352 100644 (file)
--- a/src/nfs.c
+++ b/src/nfs.c
@@ -397,7 +397,7 @@ static int nfs_submit_fields_safe(int nfs_version, const char *instance,
                                   size_t proc_names_num) {
   if (fields_num != proc_names_num) {
     WARNING("nfs plugin: Wrong number of fields for "
-            "NFSv%i %s statistics. Expected %zu, got %zu.",
+            "NFSv%i %s statistics. Expected %" PRIsz ", got %" PRIsz ".",
             nfs_version, instance, proc_names_num, fields_num);
     return EINVAL;
   }
@@ -421,7 +421,7 @@ static int nfs_submit_nfs4_server(const char *instance, char **fields,
   default:
     if (!suppress_warning) {
       WARNING("nfs plugin: Unexpected number of fields for "
-              "NFSv4 %s statistics: %zu. ",
+              "NFSv4 %s statistics: %" PRIsz ". ",
               instance, fields_num);
     }
 
@@ -486,9 +486,8 @@ static int nfs_submit_nfs4_client(const char *instance, char **fields,
     break;
   default:
     if (!suppress_warning) {
-      WARNING("nfs plugin: Unexpected number of "
-              "fields for NFSv4 %s "
-              "statistics: %zu. ",
+      WARNING("nfs plugin: Unexpected number of fields for NFSv4 %s "
+              "statistics: %" PRIsz ". ",
               instance, fields_num);
     }
 
index 39bbeeb..84512d2 100644 (file)
@@ -584,7 +584,7 @@ static int ntpd_receive_response(int *res_items, int *res_size, char **res_data,
      * Enough with the checks. Copy the data now.
      * We start by allocating some more memory.
      */
-    DEBUG("realloc (%p, %zu)", (void *)*res_data,
+    DEBUG("realloc (%p, %" PRIsz ")", (void *)*res_data,
           (items_num + pkt_item_num) * res_item_size);
     items = realloc(*res_data, (items_num + pkt_item_num) * res_item_size);
     if (items == NULL) {
index 099013e..bf6aef5 100644 (file)
@@ -308,10 +308,10 @@ static int o_config(oconfig_item_t *ci) /* {{{ */
     }
 
     if (queries_num > 0) {
-      DEBUG("oracle plugin: o_config: queries_num = %zu; queries[0] = %p; "
-            "udb_query_get_user_data (queries[0]) = %p;",
-            queries_num, (void *)queries[0],
-            udb_query_get_user_data(queries[0]));
+      DEBUG(
+          "oracle plugin: o_config: queries_num = %" PRIsz "; queries[0] = %p; "
+          "udb_query_get_user_data (queries[0]) = %p;",
+          queries_num, (void *)queries[0], udb_query_get_user_data(queries[0]));
     }
   } /* for (ci->children) */
 
@@ -532,8 +532,8 @@ static int o_read_database_query(o_database_t *db, /* {{{ */
     memcpy(column_names[i], column_name, column_name_length);
     column_names[i][column_name_length] = 0;
 
-    DEBUG("oracle plugin: o_read_database_query: column_names[%zu] = %s; "
-          "column_name_length = %" PRIu32 ";",
+    DEBUG("oracle plugin: o_read_database_query: column_names[%" PRIsz "] = %s;"
+          " column_name_length = %" PRIu32 ";",
           i, column_names[i], (uint32_t)column_name_length);
 
     status = OCIDefineByPos(oci_statement, &oci_defines[i], oci_error,
index e210374..e027845 100644 (file)
@@ -974,9 +974,9 @@ static int ovs_stats_plugin_read(__attribute__((unused)) user_data_t *ud) {
 
 /* Shutdown OvS Stats plugin */
 static int ovs_stats_plugin_shutdown(void) {
-  pthread_mutex_lock(&g_stats_lock);
   DEBUG("OvS Statistics plugin shutting down");
   ovs_db_destroy(g_ovs_db);
+  pthread_mutex_lock(&g_stats_lock);
   ovs_stats_free_bridge_list(g_bridge_list_head);
   ovs_stats_free_bridge_list(g_monitored_bridge_list_head);
   ovs_stats_free_port_list(g_port_list_head);
index 671d1f3..5ad99ee 100644 (file)
@@ -331,12 +331,12 @@ static size_t av2value(pTHX_ char *name, AV *array, value_t *value,
 
   if (array_len < ds->ds_num) {
     log_warn("av2value: array does not contain enough elements for type "
-             "\"%s\": got %zu, want %zu",
+             "\"%s\": got %" PRIsz ", want %" PRIsz,
              name, array_len, ds->ds_num);
     return 0;
   } else if (array_len > ds->ds_num) {
     log_warn("av2value: array contains excess elements for type \"%s\": got "
-             "%zu, want %zu",
+             "%" PRIsz ", want %" PRIsz,
              name, array_len, ds->ds_num);
   }
 
@@ -706,10 +706,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);
index 89aee75..1ffd72b 100644 (file)
@@ -521,7 +521,7 @@ static int ping_config(const char *key, const char *value) /* {{{ */
       } /* }}} for (i = 0; i < size; i++) */
       ping_data[size] = 0;
     } else
-      WARNING("ping plugin: Ignoring invalid Size %zu.", size);
+      WARNING("ping plugin: Ignoring invalid Size %" PRIsz ".", size);
   } else if (strcasecmp(key, "Timeout") == 0) {
     double tmp;
 
index 25bedf8..62b3d55 100644 (file)
@@ -742,7 +742,8 @@ static char *values_to_sqlarray(const data_set_t *ds, const value_list_t *vl,
 
       status = snprintf(str_ptr, str_len, ",%lf", rates[i]);
     } else if (ds->ds[i].type == DS_TYPE_COUNTER)
-      status = snprintf(str_ptr, str_len, ",%llu", vl->values[i].counter);
+      status = snprintf(str_ptr, str_len, ",%" PRIu64,
+                        (uint64_t)vl->values[i].counter);
     else if (ds->ds[i].type == DS_TYPE_DERIVE)
       status = snprintf(str_ptr, str_len, ",%" PRIi64, vl->values[i].derive);
     else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
index 13cdce8..729a15b 100644 (file)
@@ -352,7 +352,7 @@ static void submit(const char *plugin_instance, /* {{{ */
   }
 
   if (ds->ds_num != 1) {
-    ERROR("powerdns plugin: type `%s' has %zu data sources, "
+    ERROR("powerdns plugin: type `%s' has %" PRIsz " data sources, "
           "but I can only handle one.",
           type, ds->ds_num);
     return;
@@ -376,8 +376,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;
 
@@ -475,14 +475,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;
 
@@ -530,13 +527,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;
@@ -547,23 +545,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;
@@ -572,19 +567,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) {
@@ -592,16 +574,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);
@@ -609,12 +596,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;
 
@@ -688,7 +676,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;
@@ -711,7 +698,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 30c4954..d73d24a 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * collectd - src/processes.c
  * Copyright (C) 2005       Lyonel Vincent
- * Copyright (C) 2006-2010  Florian octo Forster
+ * Copyright (C) 2006-2017  Florian octo Forster
  * Copyright (C) 2008       Oleg King
  * Copyright (C) 2009       Sebastian Harl
  * Copyright (C) 2009       Andrés J. Díaz
 #include "common.h"
 #include "plugin.h"
 
+#if HAVE_LIBTASKSTATS
+#include "utils_complain.h"
+#include "utils_taskstats.h"
+#endif
+
 /* Include header files for the mach system, if they exist.. */
 #if HAVE_THREAD_INFO
 #if HAVE_MACH_MACH_INIT_H
 #include <kstat.h>
 #endif
 
+#ifdef HAVE_SYS_CAPABILITY_H
+#include <sys/capability.h>
+#endif
+
 #ifndef CMDLINE_BUFFER_SIZE
 #if defined(ARG_MAX) && (ARG_MAX < 4096)
 #define CMDLINE_BUFFER_SIZE ARG_MAX
@@ -195,6 +204,11 @@ typedef struct process_entry_s {
   derive_t cswitch_invol;
   _Bool has_cswitch;
 
+#if HAVE_LIBTASKSTATS
+  ts_delay_t delay;
+#endif
+  _Bool has_delay;
+
   _Bool has_fd;
 
   _Bool has_maps;
@@ -221,6 +235,13 @@ typedef struct procstat_entry_s {
   derive_t cswitch_vol;
   derive_t cswitch_invol;
 
+#if HAVE_LIBTASKSTATS
+  value_to_rate_state_t delay_cpu;
+  value_to_rate_state_t delay_blkio;
+  value_to_rate_state_t delay_swapin;
+  value_to_rate_state_t delay_freepages;
+#endif
+
   struct procstat_entry_s *next;
 } procstat_entry_t;
 
@@ -257,9 +278,16 @@ typedef struct procstat {
   derive_t cswitch_vol;
   derive_t cswitch_invol;
 
+  /* Linux Delay Accounting. Unit is ns/s. */
+  gauge_t delay_cpu;
+  gauge_t delay_blkio;
+  gauge_t delay_swapin;
+  gauge_t delay_freepages;
+
   _Bool report_fd_num;
   _Bool report_maps_num;
   _Bool report_ctx_switch;
+  _Bool report_delay;
 
   struct procstat *next;
   struct procstat_entry_s *instances;
@@ -271,6 +299,7 @@ static _Bool want_init = 1;
 static _Bool report_ctx_switch = 0;
 static _Bool report_fd_num = 0;
 static _Bool report_maps_num = 0;
+static _Bool report_delay = 0;
 
 #if HAVE_THREAD_INFO
 static mach_port_t port_host_self;
@@ -304,6 +333,10 @@ int getthrds64(pid_t, void *, int, tid64_t *, int);
 int getargs(void *processBuffer, int bufferLen, char *argsBuffer, int argsLen);
 #endif /* HAVE_PROCINFO_H */
 
+#if HAVE_LIBTASKSTATS
+static ts_t *taskstats_handle = NULL;
+#endif
+
 /* put name of process from config to list_head_g tree
  * list_head_g is a list of 'procstat_t' structs with
  * processes names we want to watch */
@@ -331,6 +364,7 @@ static procstat_t *ps_list_register(const char *name, const char *regexp) {
   new->report_fd_num = report_fd_num;
   new->report_maps_num = report_maps_num;
   new->report_ctx_switch = report_ctx_switch;
+  new->report_delay = report_delay;
 
 #if HAVE_REGEX_H
   if (regexp != NULL) {
@@ -439,6 +473,39 @@ static void ps_update_counter(derive_t *group_counter, derive_t *curr_counter,
   *group_counter += curr_value;
 }
 
+#if HAVE_LIBTASKSTATS
+static void ps_update_delay_one(gauge_t *out_rate_sum,
+                                value_to_rate_state_t *state, uint64_t cnt,
+                                cdtime_t t) {
+  gauge_t rate = NAN;
+  int status = value_to_rate(&rate, (value_t){.counter = (counter_t)cnt},
+                             DS_TYPE_COUNTER, t, state);
+  if ((status != 0) || isnan(rate)) {
+    return;
+  }
+
+  if (isnan(*out_rate_sum)) {
+    *out_rate_sum = rate;
+  } else {
+    *out_rate_sum += rate;
+  }
+}
+
+static void ps_update_delay(procstat_t *out, procstat_entry_t *prev,
+                            process_entry_t *curr) {
+  cdtime_t now = cdtime();
+
+  ps_update_delay_one(&out->delay_cpu, &prev->delay_cpu, curr->delay.cpu_ns,
+                      now);
+  ps_update_delay_one(&out->delay_blkio, &prev->delay_blkio,
+                      curr->delay.blkio_ns, now);
+  ps_update_delay_one(&out->delay_swapin, &prev->delay_swapin,
+                      curr->delay.swapin_ns, now);
+  ps_update_delay_one(&out->delay_freepages, &prev->delay_freepages,
+                      curr->delay.freepages_ns, now);
+}
+#endif
+
 /* add process entry to 'instances' of process 'name' (or refresh it) */
 static void ps_list_add(const char *name, const char *cmdline,
                         process_entry_t *entry) {
@@ -518,6 +585,10 @@ static void ps_list_add(const char *name, const char *cmdline,
                       entry->cpu_user_counter);
     ps_update_counter(&ps->cpu_system_counter, &pse->cpu_system_counter,
                       entry->cpu_system_counter);
+
+#if HAVE_LIBTASKSTATS
+    ps_update_delay(ps, pse, entry);
+#endif
   }
 }
 
@@ -537,6 +608,11 @@ static void ps_list_reset(void) {
     ps->vmem_code = 0;
     ps->stack_size = 0;
 
+    ps->delay_cpu = NAN;
+    ps->delay_blkio = NAN;
+    ps->delay_swapin = NAN;
+    ps->delay_freepages = NAN;
+
     pse_prev = NULL;
     pse = ps->instances;
     while (pse != NULL) {
@@ -573,8 +649,15 @@ static void ps_tune_instance(oconfig_item_t *ci, procstat_t *ps) {
       cf_util_get_boolean(c, &ps->report_fd_num);
     else if (strcasecmp(c->key, "CollectMemoryMaps") == 0)
       cf_util_get_boolean(c, &ps->report_maps_num);
-    else {
-      ERROR("processes plugin: Option `%s' not allowed here.", c->key);
+    else if (strcasecmp(c->key, "CollectDelayAccounting") == 0) {
+#if HAVE_LIBTASKSTATS
+      cf_util_get_boolean(c, &ps->report_delay);
+#else
+      WARNING("processes plugin: The plugin has been compiled without support "
+              "for the \"CollectDelayAccounting\" option.");
+#endif
+    } else {
+      ERROR("processes plugin: Option \"%s\" not allowed here.", c->key);
     }
   } /* for (ci->children) */
 } /* void ps_tune_instance */
@@ -602,7 +685,8 @@ static int ps_config(oconfig_item_t *ci) {
 
 #if KERNEL_LINUX || KERNEL_SOLARIS || KERNEL_FREEBSD
       if (strlen(c->values[0].value.string) > max_procname_len) {
-        WARNING("processes plugin: this platform has a %zu character limit "
+        WARNING("processes plugin: this platform has a %" PRIsz
+                " character limit "
                 "to process names. The `Process \"%s\"' option will "
                 "not work as expected.",
                 max_procname_len, c->values[0].value.string);
@@ -633,6 +717,13 @@ static int ps_config(oconfig_item_t *ci) {
       cf_util_get_boolean(c, &report_fd_num);
     } else if (strcasecmp(c->key, "CollectMemoryMaps") == 0) {
       cf_util_get_boolean(c, &report_maps_num);
+    } else if (strcasecmp(c->key, "CollectDelayAccounting") == 0) {
+#if HAVE_LIBTASKSTATS
+      cf_util_get_boolean(c, &report_delay);
+#else
+      WARNING("processes plugin: The plugin has been compiled without support "
+              "for the \"CollectDelayAccounting\" option.");
+#endif
     } else {
       ERROR("processes plugin: The `%s' configuration option is not "
             "understood and will be ignored.",
@@ -670,6 +761,15 @@ static int ps_init(void) {
 #elif KERNEL_LINUX
   pagesize_g = sysconf(_SC_PAGESIZE);
   DEBUG("pagesize_g = %li; CONFIG_HZ = %i;", pagesize_g, CONFIG_HZ);
+
+#if HAVE_LIBTASKSTATS
+  if (taskstats_handle == NULL) {
+    taskstats_handle = ts_create();
+    if (taskstats_handle == NULL) {
+      WARNING("processes plugin: Creating taskstats handle failed.");
+    }
+  }
+#endif
 /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKVM_GETPROCS &&                                                  \
@@ -804,6 +904,31 @@ static void ps_submit_proc_list(procstat_t *ps) {
     plugin_dispatch_values(&vl);
   }
 
+  /* The ps->delay_* metrics are in nanoseconds per second. Convert to seconds
+   * per second. */
+  gauge_t const delay_factor = 1000000000.0;
+
+  struct {
+    char *type_instance;
+    gauge_t rate_ns;
+  } delay_metrics[] = {
+      {"delay-cpu", ps->delay_cpu},
+      {"delay-blkio", ps->delay_blkio},
+      {"delay-swapin", ps->delay_swapin},
+      {"delay-freepages", ps->delay_freepages},
+  };
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE(delay_metrics); i++) {
+    if (isnan(delay_metrics[i].rate_ns)) {
+      continue;
+    }
+    sstrncpy(vl.type, "delay_rate", sizeof(vl.type));
+    sstrncpy(vl.type_instance, delay_metrics[i].type_instance,
+             sizeof(vl.type_instance));
+    vl.values[0].gauge = delay_metrics[i].rate_ns * delay_factor;
+    vl.values_len = 1;
+    plugin_dispatch_values(&vl);
+  }
+
   DEBUG(
       "name = %s; num_proc = %lu; num_lwp = %lu; num_fd = %lu; num_maps = %lu; "
       "vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
@@ -813,13 +938,16 @@ static void ps_submit_proc_list(procstat_t *ps) {
       "io_rchar = %" PRIi64 "; io_wchar = %" PRIi64 "; "
       "io_syscr = %" PRIi64 "; io_syscw = %" PRIi64 "; "
       "io_diskr = %" PRIi64 "; io_diskw = %" PRIi64 "; "
-      "cswitch_vol = %" PRIi64 "; cswitch_invol = %" PRIi64 ";",
+      "cswitch_vol = %" PRIi64 "; cswitch_invol = %" PRIi64 "; "
+      "delay_cpu = %g; delay_blkio = %g; "
+      "delay_swapin = %g; delay_freepages = %g;",
       ps->name, ps->num_proc, ps->num_lwp, ps->num_fd, ps->num_maps,
       ps->vmem_size, ps->vmem_rss, ps->vmem_data, ps->vmem_code,
       ps->vmem_minflt_counter, ps->vmem_majflt_counter, ps->cpu_user_counter,
       ps->cpu_system_counter, ps->io_rchar, ps->io_wchar, ps->io_syscr,
       ps->io_syscw, ps->io_diskr, ps->io_diskw, ps->cswitch_vol,
-      ps->cswitch_invol);
+      ps->cswitch_invol, ps->delay_cpu, ps->delay_blkio, ps->delay_swapin,
+      ps->delay_freepages);
 
 } /* void ps_submit_proc_list */
 
@@ -1072,6 +1200,57 @@ static int ps_count_fd(int pid) {
   return (count >= 1) ? count : 1;
 } /* int ps_count_fd (pid) */
 
+#if HAVE_LIBTASKSTATS
+static int ps_delay(process_entry_t *ps) {
+  if (taskstats_handle == NULL) {
+    return ENOTCONN;
+  }
+
+  int status = ts_delay_by_tgid(taskstats_handle, (uint32_t)ps->id, &ps->delay);
+  if (status == EPERM) {
+    static c_complain_t c;
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_NET_ADMIN)
+    if (check_capability(CAP_NET_ADMIN) != 0) {
+      if (getuid() == 0) {
+        c_complain(
+            LOG_ERR, &c,
+            "processes plugin: Reading Delay Accounting metric failed: %s. "
+            "collectd is running as root, but missing the CAP_NET_ADMIN "
+            "capability. The most common cause for this is that the init "
+            "system is dropping capabilities.",
+            STRERROR(status));
+      } else {
+        c_complain(
+            LOG_ERR, &c,
+            "processes plugin: Reading Delay Accounting metric failed: %s. "
+            "collectd is not running as root and missing the CAP_NET_ADMIN "
+            "capability. Either run collectd as root or grant it the "
+            "CAP_NET_ADMIN capability using \"setcap cap_net_admin=ep " PREFIX
+            "/sbin/collectd\".",
+            STRERROR(status));
+      }
+    } else {
+      ERROR("processes plugin: ts_delay_by_tgid failed: %s. The CAP_NET_ADMIN "
+            "capability is available (I checked), so this error is utterly "
+            "unexpected.",
+            STRERROR(status));
+    }
+#else
+    c_complain(LOG_ERR, &c,
+               "processes plugin: Reading Delay Accounting metric failed: %s. "
+               "Reading Delay Accounting metrics requires root privileges.",
+               STRERROR(status));
+#endif
+    return status;
+  } else if (status != 0) {
+    ERROR("processes plugin: ts_delay_by_tgid failed: %s", STRERROR(status));
+    return status;
+  }
+
+  return 0;
+}
+#endif
+
 static void ps_fill_details(const procstat_t *ps, process_entry_t *entry) {
   if (entry->has_io == 0) {
     ps_read_io(entry);
@@ -1100,8 +1279,17 @@ static void ps_fill_details(const procstat_t *ps, process_entry_t *entry) {
     }
     entry->has_fd = 1;
   }
+
+#if HAVE_LIBTASKSTATS
+  if (ps->report_delay && !entry->has_delay) {
+    if (ps_delay(entry) == 0) {
+      entry->has_delay = 1;
+    }
+  }
+#endif
 } /* void ps_fill_details (...) */
 
+/* ps_read_process reads process counters on Linux. */
 static int ps_read_process(long pid, process_entry_t *ps, char *state) {
   char filename[64];
   char buffer[1024];
@@ -1148,7 +1336,8 @@ static int ps_read_process(long pid, process_entry_t *ps, char *state) {
   /* Either '(' or ')' is not found or they are in the wrong order.
    * Anyway, something weird that shouldn't happen ever. */
   if (name_start_pos >= name_end_pos) {
-    ERROR("processes plugin: name_start_pos = %zu >= name_end_pos = %zu",
+    ERROR("processes plugin: name_start_pos = %" PRIsz
+          " >= name_end_pos = %" PRIsz,
           name_start_pos, name_end_pos);
     return -1;
   }
@@ -1382,7 +1571,7 @@ static char *ps_get_cmdline(long pid,
   if ((status < 0) || (((size_t)status) != sizeof(info))) {
     ERROR("processes plugin: Unexpected return value "
           "while reading \"%s\": "
-          "Returned %zd but expected %zu.",
+          "Returned %zd but expected %" PRIsz ".",
           path, status, buffer_size);
     return NULL;
   }
@@ -1587,8 +1776,7 @@ static int mach_get_task_name(task_t t, int *pid, char *name,
   return 0;
 }
 #endif /* HAVE_THREAD_INFO */
-/* ------- end of additional functions for KERNEL_LINUX/HAVE_THREAD_INFO -------
- */
+/* end of additional functions for KERNEL_LINUX/HAVE_THREAD_INFO */
 
 /* do actual readings from kernel */
 static int ps_read(void) {
index 15c1848..7fe0a31 100644 (file)
@@ -641,7 +641,8 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
   }
   size = (size_t)PySequence_Length(values);
   if (size != ds->ds_num) {
-    PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu",
+    PyErr_Format(PyExc_RuntimeError,
+                 "type %s needs %" PRIsz " values, got %" PRIsz,
                  value_list.type, ds->ds_num, size);
     return NULL;
   }
@@ -765,7 +766,8 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
   }
   size = (size_t)PySequence_Length(values);
   if (size != ds->ds_num) {
-    PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu",
+    PyErr_Format(PyExc_RuntimeError,
+                 "type %s needs %" PRIsz " values, got %" PRIsz,
                  value_list.type, ds->ds_num, size);
     return NULL;
   }
index 9f76f23..529d29c 100644 (file)
@@ -88,8 +88,8 @@ static int value_list_to_string(char *buffer, int buffer_len,
       return -1;
 
     if (ds->ds[i].type == DS_TYPE_COUNTER) {
-      status = snprintf(buffer + offset, buffer_len - offset, ":%llu",
-                        vl->values[i].counter);
+      status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
+                        (uint64_t)vl->values[i].counter);
     } else if (ds->ds[i].type == DS_TYPE_GAUGE) {
       status = snprintf(buffer + offset, buffer_len - offset, ":%f",
                         vl->values[i].gauge);
index 8856369..e3ad07e 100644 (file)
@@ -186,8 +186,8 @@ static int value_list_to_string_multiple(char *buffer, int buffer_len,
       return -1;
 
     if (ds->ds[i].type == DS_TYPE_COUNTER)
-      status = snprintf(buffer + offset, buffer_len - offset, ":%llu",
-                        vl->values[i].counter);
+      status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
+                        (uint64_t)vl->values[i].counter);
     else if (ds->ds[i].type == DS_TYPE_GAUGE)
       status = snprintf(buffer + offset, buffer_len - offset, ":" GAUGE_FORMAT,
                         vl->values[i].gauge);
@@ -226,8 +226,8 @@ static int value_list_to_string(char *buffer, int buffer_len,
                       vl->values[0].gauge);
     break;
   case DS_TYPE_COUNTER:
-    status = snprintf(buffer, buffer_len, "%u:%llu", (unsigned)tt,
-                      vl->values[0].counter);
+    status = snprintf(buffer, buffer_len, "%u:%" PRIu64, (unsigned)tt,
+                      (uint64_t)vl->values[0].counter);
     break;
   case DS_TYPE_ABSOLUTE:
     status = snprintf(buffer, buffer_len, "%u:%" PRIu64, (unsigned)tt,
@@ -620,9 +620,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);
@@ -1036,8 +1035,7 @@ static int rrd_init(void) {
     cache_flush_timeout = 0;
   } else if (cache_flush_timeout < cache_timeout) {
     INFO("rrdtool plugin: \"CacheFlush %.3f\" is less than \"CacheTimeout "
-         "%.3f\". "
-         "Ajusting \"CacheFlush\" to %.3f seconds.",
+         "%.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));
index 8cb866d..d0f9e84 100644 (file)
@@ -398,7 +398,7 @@ static int csnmp_config_add_data(oconfig_item_t *ci) {
   }
 
   DEBUG("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = "
-        "%zu }",
+        "%" PRIsz " }",
         dd->name, dd->type, (dd->is_table != 0) ? "true" : "false",
         dd->values_len);
 
@@ -1093,7 +1093,8 @@ static int csnmp_instance_list_add(csnmp_list_instances_t **head,
     value_t val = csnmp_value_list_to_value(
         vb, DS_TYPE_COUNTER,
         /* scale = */ 1.0, /* shift = */ 0.0, hd->name, dd->name);
-    snprintf(il->instance, sizeof(il->instance), "%llu", val.counter);
+    snprintf(il->instance, sizeof(il->instance), "%" PRIu64,
+             (uint64_t)val.counter);
   }
 
   /* TODO: Debugging output */
@@ -1296,8 +1297,9 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) {
   }
 
   if (ds->ds_num != data->values_len) {
-    ERROR("snmp plugin: DataSet `%s' requires %zu values, but config talks "
-          "about %zu",
+    ERROR("snmp plugin: DataSet `%s' requires %" PRIsz
+          " values, but config talks "
+          "about %" PRIsz,
           data->type, ds->ds_num, data->values_len);
     return -1;
   }
@@ -1474,7 +1476,7 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) {
          * suffix is increasing. This also checks if we left the subtree */
         ret = csnmp_oid_suffix(&suffix, &vb_name, data->values + i);
         if (ret != 0) {
-          DEBUG("snmp plugin: host = %s; data = %s; i = %zu; "
+          DEBUG("snmp plugin: host = %s; data = %s; i = %" PRIsz "; "
                 "Value probably left its subtree.",
                 host->name, data->name, i);
           oid_list_todo[i] = 0;
@@ -1486,7 +1488,7 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) {
          * table matching algorithm will get confused. */
         if ((value_list_tail[i] != NULL) &&
             (csnmp_oid_compare(&suffix, &value_list_tail[i]->suffix) <= 0)) {
-          DEBUG("snmp plugin: host = %s; data = %s; i = %zu; "
+          DEBUG("snmp plugin: host = %s; data = %s; i = %" PRIsz "; "
                 "Suffix is not increasing.",
                 host->name, data->name, i);
           oid_list_todo[i] = 0;
@@ -1578,8 +1580,9 @@ static int csnmp_read_value(host_definition_t *host, data_definition_t *data) {
   }
 
   if (ds->ds_num != data->values_len) {
-    ERROR("snmp plugin: DataSet `%s' requires %zu values, but config talks "
-          "about %zu",
+    ERROR("snmp plugin: DataSet `%s' requires %" PRIsz
+          " values, but config talks "
+          "about %" PRIsz,
           data->type, ds->ds_num, data->values_len);
     return -1;
   }
index 948107b..b213adb 100644 (file)
@@ -166,7 +166,7 @@ static void snmp_agent_dump_data(void) {
         DEBUG(PLUGIN_NAME ":     TypeInstance: %s", dd->type_instance);
       for (size_t i = 0; i < dd->oids_len; i++) {
         snmp_agent_oid_to_string(oid_str, sizeof(oid_str), &dd->oids[i]);
-        DEBUG(PLUGIN_NAME ":     OID[%zu]: %s", i, oid_str);
+        DEBUG(PLUGIN_NAME ":     OID[%" PRIsz "]: %s", i, oid_str);
       }
       DEBUG(PLUGIN_NAME ":   Scale: %g", dd->scale);
       DEBUG(PLUGIN_NAME ":   Shift: %g", dd->shift);
@@ -190,7 +190,7 @@ static void snmp_agent_dump_data(void) {
       DEBUG(PLUGIN_NAME ":   TypeInstance: %s", dd->type_instance);
     for (size_t i = 0; i < dd->oids_len; i++) {
       snmp_agent_oid_to_string(oid_str, sizeof(oid_str), &dd->oids[i]);
-      DEBUG(PLUGIN_NAME ":   OID[%zu]: %s", i, oid_str);
+      DEBUG(PLUGIN_NAME ":   OID[%" PRIsz "]: %s", i, oid_str);
     }
     DEBUG(PLUGIN_NAME ":   Scale: %g", dd->scale);
     DEBUG(PLUGIN_NAME ":   Shift: %g", dd->shift);
index cfe9a58..20f0275 100644 (file)
@@ -78,6 +78,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);
@@ -103,11 +107,17 @@ 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->plugin_name);
   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);
@@ -326,8 +336,8 @@ static int tbl_prepare(tbl_t *tbl) {
     }
 
     if (res->values_num != res->ds->ds_num) {
-      log_err("Invalid type \"%s\". Expected %zu data source%s, "
-              "got %zu.",
+      log_err("Invalid type \"%s\". Expected %" PRIsz " data source%s, "
+              "got %" PRIsz ".",
               res->type, res->values_num, (1 == res->values_num) ? "" : "s",
               res->ds->ds_num);
       return -1;
@@ -420,7 +430,7 @@ static int tbl_parse_line(tbl_t *tbl, char *line, size_t len) {
 
   if (i <= tbl->max_colnum) {
     log_warn("Not enough columns in line "
-             "(expected at least %zu, got %zu).",
+             "(expected at least %" PRIsz ", got %" PRIsz ").",
              tbl->max_colnum + 1, i);
     return -1;
   }
index 2e3ac5f..f963528 100644 (file)
@@ -128,7 +128,7 @@ static _Bool tcsv_check_index(ssize_t index, size_t fields_num,
     return 1;
 
   ERROR("tail_csv plugin: Metric \"%s\": Request for index %zd when "
-        "only %zu fields are available.",
+        "only %" PRIsz " fields are available.",
         name, index, fields_num);
   return 0;
 }
@@ -532,7 +532,7 @@ static int tcsv_init(void) { /* {{{ */
             md->type, md->name);
       continue;
     } else if (ds->ds_num != 1) {
-      ERROR("tail_csv plugin: The type \"%s\" has %zu data sources. "
+      ERROR("tail_csv plugin: The type \"%s\" has %" PRIsz " data sources. "
             "Only types with a single data source are supported.",
             ds->type, ds->ds_num);
       continue;
index debb1d2..f59b7ea 100644 (file)
 #error "No applicable input method."
 #endif
 
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+
 #define MAX_NUMTAPE 256
 extern kstat_ctl_t *kc;
 static kstat_t *ksp[MAX_NUMTAPE];
index 66fc98d..54d4164 100644 (file)
@@ -294,7 +294,8 @@ static int tr_action_invoke(tr_action_t *act_head, /* {{{ */
     subst_status = subst(temp, sizeof(temp), buffer, (size_t)matches[0].rm_so,
                          (size_t)matches[0].rm_eo, act->replacement);
     if (subst_status == NULL) {
-      ERROR("Target `replace': subst (buffer = %s, start = %zu, end = %zu, "
+      ERROR("Target `replace': subst (buffer = %s, start = %" PRIsz
+            ", end = %" PRIsz ", "
             "replacement = %s) failed.",
             buffer, (size_t)matches[0].rm_so, (size_t)matches[0].rm_eo,
             act->replacement);
@@ -386,7 +387,8 @@ static int tr_meta_data_action_invoke(/* {{{ */
     subst_status = subst(temp, sizeof(temp), value, (size_t)matches[0].rm_so,
                          (size_t)matches[0].rm_eo, act->replacement);
     if (subst_status == NULL) {
-      ERROR("Target `replace': subst (value = %s, start = %zu, end = %zu, "
+      ERROR("Target `replace': subst (value = %s, start = %" PRIsz
+            ", end = %" PRIsz ", "
             "replacement = %s) failed.",
             value, (size_t)matches[0].rm_so, (size_t)matches[0].rm_eo,
             act->replacement);
index e4419b8..85f7d87 100644 (file)
@@ -586,7 +586,8 @@ static int submit_counters(struct thread_data *t, struct core_data *c,
   /* If not using logical core numbering, set core id */
   if (!config_lcn) {
     if (topology.num_packages > 1)
-      snprintf(name, sizeof(name), "pkg%02d-core%02d", p->package_id, c->core_id);
+      snprintf(name, sizeof(name), "pkg%02d-core%02d", p->package_id,
+               c->core_id);
     else
       snprintf(name, sizeof(name), "core%02d", c->core_id);
   }
@@ -977,6 +978,7 @@ static int __attribute__((warn_unused_result)) probe_cpu(void) {
     case 0x45: /* HSW */
     case 0x46: /* HSW */
     case 0x3D: /* BDW */
+    case 0x5E: /* SKL */
       do_rapl = RAPL_PKG | RAPL_CORES | RAPL_GFX;
       break;
     case 0x3F: /* HSX */
index 4ca57aa..f27ba46 100644 (file)
@@ -44,6 +44,7 @@ current                 value:GAUGE:U:U
 current_connections     value:GAUGE:0:U
 current_sessions        value:GAUGE:0:U
 delay                   value:GAUGE:-1000000:1000000
+delay_rate              value:GAUGE:0:U
 derive                  value:DERIVE:0:U
 df                      used:GAUGE:0:1125899906842623, free:GAUGE:0:1125899906842623
 df_complex              value:GAUGE:0:U
index 31a2c1e..43d72e5 100644 (file)
  * Global variables
  */
 
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+
 #if HAVE_LIBKSTAT
 extern kstat_ctl_t *kc;
 #endif /* #endif HAVE_LIBKSTAT */
index 63e26e0..c1f3f56 100644 (file)
@@ -151,7 +151,7 @@ int handle_getthreshold(FILE *fh, char *buffer) {
     i++;
 
   /* Print the response */
-  print_to_socket(fh, "%zu Threshold found\n", i);
+  print_to_socket(fh, "%" PRIsz " Threshold found\n", i);
 
   if (threshold.host[0] != 0)
     print_to_socket(fh, "Host: %s\n", threshold.host);
index 23bafc7..f747d5b 100644 (file)
@@ -131,8 +131,8 @@ cmd_status_t cmd_handle_getval(FILE *fh, char *buffer) {
   }
 
   if (ds->ds_num != values_num) {
-    ERROR("ds[%s]->ds_num = %zu, "
-          "but uc_get_rate_by_name returned %zu values.",
+    ERROR("ds[%s]->ds_num = %" PRIsz ", "
+          "but uc_get_rate_by_name returned %" PRIsz " values.",
           ds->type, ds->ds_num, values_num);
     cmd_error(CMD_ERROR, &err, "Error reading value from cache.");
     sfree(values);
@@ -140,7 +140,7 @@ cmd_status_t cmd_handle_getval(FILE *fh, char *buffer) {
     return CMD_ERROR;
   }
 
-  print_to_socket(fh, "%zu Value%s found\n", values_num,
+  print_to_socket(fh, "%" PRIsz " Value%s found\n", values_num,
                   (values_num == 1) ? "" : "s");
   for (size_t i = 0; i < values_num; i++) {
     print_to_socket(fh, "%s=", ds->ds[i].name);
index 41f40d9..a58bc06 100644 (file)
@@ -363,7 +363,8 @@ static int udb_result_prepare_result(udb_result_t const *r, /* {{{ */
 
   if (prep_area->ds->ds_num != r->values_num) {
     ERROR("db query utils: udb_result_prepare_result: The type `%s' "
-          "requires exactly %zu value%s, but the configuration specifies %zu.",
+          "requires exactly %" PRIsz
+          " value%s, but the configuration specifies %" PRIsz ".",
           r->type, prep_area->ds->ds_num,
           (prep_area->ds->ds_num == 1) ? "" : "s", r->values_num);
     BAIL_OUT(-1);
@@ -892,7 +893,7 @@ int udb_query_handle_result(udb_query_t const *q, /* {{{ */
   do {
     for (size_t i = 0; i < prep_area->column_num; i++) {
       DEBUG("db query utils: udb_query_handle_result (%s, %s): "
-            "column[%zu] = %s;",
+            "column[%" PRIsz "] = %s;",
             prep_area->db_name, q->name, i, column_values[i]);
     }
   } while (0);
@@ -949,7 +950,7 @@ int udb_query_prepare_result(udb_query_t const *q, /* {{{ */
   do {
     for (size_t i = 0; i < column_num; i++) {
       DEBUG("db query utils: udb_query_prepare_result: "
-            "query = %s; column[%zu] = %s;",
+            "query = %s; column[%" PRIsz "] = %s;",
             q->name, i, column_names[i]);
     }
   } while (0);
index 87cead1..fbeff4f 100644 (file)
@@ -60,7 +60,7 @@ static int gr_format_values(char *ret, size_t ret_len, int ds_num,
   else if (rates != NULL)
     BUFFER_ADD("%f", rates[ds_num]);
   else if (ds->ds[ds_num].type == DS_TYPE_COUNTER)
-    BUFFER_ADD("%llu", vl->values[ds_num].counter);
+    BUFFER_ADD("%" PRIu64, (uint64_t)vl->values[ds_num].counter);
   else if (ds->ds[ds_num].type == DS_TYPE_DERIVE)
     BUFFER_ADD("%" PRIi64, vl->values[ds_num].derive);
   else if (ds->ds[ds_num].type == DS_TYPE_ABSOLUTE)
@@ -223,7 +223,7 @@ int format_graphite(char *buffer, size_t buffer_size, data_set_t const *ds,
                          (unsigned int)CDTIME_T_TO_TIME_T(vl->time));
     if (message_len >= sizeof(message)) {
       ERROR("format_graphite: message buffer too small: "
-            "Need %zu bytes.",
+            "Need %" PRIsz " bytes.",
             message_len + 1);
       sfree(rates);
       return -ENOMEM;
index 4ecbfbe..6a0c664 100644 (file)
@@ -130,7 +130,7 @@ static int values_to_json(char *buffer, size_t buffer_size, /* {{{ */
       else
         BUFFER_ADD("null");
     } else if (ds->ds[i].type == DS_TYPE_COUNTER)
-      BUFFER_ADD("%llu", vl->values[i].counter);
+      BUFFER_ADD("%" PRIu64, (uint64_t)vl->values[i].counter);
     else if (ds->ds[i].type == DS_TYPE_DERIVE)
       BUFFER_ADD("%" PRIi64, vl->values[i].derive);
     else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
index 460f807..4003243 100644 (file)
@@ -154,7 +154,7 @@ static int values_to_kairosdb(char *buffer, size_t buffer_size, /* {{{ */
     BUFFER_ADD("[[");
     BUFFER_ADD("%" PRIu64, CDTIME_T_TO_MS(vl->time));
     BUFFER_ADD(",");
-    BUFFER_ADD("%llu", vl->values[ds_idx].counter);
+    BUFFER_ADD("%" PRIu64, (uint64_t)vl->values[ds_idx].counter);
   } else if (ds->ds[ds_idx].type == DS_TYPE_DERIVE) {
     BUFFER_ADD("[[");
     BUFFER_ADD("%" PRIu64, CDTIME_T_TO_MS(vl->time));
index 625fc42..1d3bf2e 100644 (file)
@@ -65,7 +65,7 @@ struct latency_counter_s {
 * When a value above this range is added, Histogram's range is increased by
 * increasing the bin width (note that number of bins remains always at 1000).
 * This operation of increasing bin width is little expensive as each bin need
-* to be visited to update it's count. To reduce frequent change of bin width,
+* to be visited to update its count. To reduce frequent change of bin width,
 * new bin width will be the next nearest power of 2. Example: 2, 4, 8, 16, 32,
 * 64, 128, 256, 512, 1024, 2048, 5086, ...
 *
index 427a159..42a6e87 100644 (file)
@@ -26,8 +26,8 @@
 
 #define DBL_PRECISION 1e-6
 
-#include "common.h" /* for STATIC_ARRAY_SIZE */
 #include "collectd.h"
+#include "common.h" /* for STATIC_ARRAY_SIZE */
 
 #include "testing.h"
 #include "utils_latency.h"
@@ -52,7 +52,7 @@ DEF_TEST(simple) {
   CHECK_NOT_NULL(l = latency_counter_create());
 
   for (size_t i = 0; i < STATIC_ARRAY_SIZE(cases); i++) {
-    printf("# case %zu: DOUBLE_TO_CDTIME_T(%g) = %" PRIu64 "\n", i,
+    printf("# case %" PRIsz ": DOUBLE_TO_CDTIME_T(%g) = %" PRIu64 "\n", i,
            cases[i].val, DOUBLE_TO_CDTIME_T(cases[i].val));
     latency_counter_add(l, DOUBLE_TO_CDTIME_T(cases[i].val));
 
index 0990472..1f060f8 100644 (file)
@@ -28,8 +28,8 @@
  * GCC will complain about the macro definition. */
 #define DONT_POISON_SPRINTF_YET
 
-#include "utils_lua.h"
 #include "common.h"
+#include "utils_lua.h"
 
 static int ltoc_values(lua_State *L, /* {{{ */
                        const data_set_t *ds, value_t *ret_values) {
@@ -57,8 +57,8 @@ static int ltoc_values(lua_State *L, /* {{{ */
   } /* while (lua_next) */
 
   if (i != ds->ds_num) {
-    WARNING("ltoc_values: invalid size for datasource \"%s\": expected %zu, "
-            "got %zu",
+    WARNING("ltoc_values: invalid size for datasource \"%s\": expected %" PRIsz
+            ", got %" PRIsz,
             ds->type, ds->ds_num, i);
     return -1;
   }
index ca65950..e8f3009 100644 (file)
 #include "testing.h"
 #include "utils_mount.h"
 
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+
 #if HAVE_LIBKSTAT
 kstat_ctl_t *kc;
 #endif /* HAVE_LIBKSTAT */
index 2df9f2b..0ee05e0 100644 (file)
 #define OVS_DB_POLL_READ_BLOCK_SIZE 512 /* read block size (bytes) */
 #define OVS_DB_DEFAULT_DB_NAME "Open_vSwitch"
 
+#define OVS_DB_EVENT_NONE 0
 #define OVS_DB_EVENT_TIMEOUT 5 /* event thread timeout (sec) */
 #define OVS_DB_EVENT_TERMINATE 1
 #define OVS_DB_EVENT_CONN_ESTABLISHED 2
@@ -559,7 +560,7 @@ static int ovs_db_json_data_process(ovs_db_t *pdb, const char *data,
     return -1;
 
   sstrncpy(sjson, data, len + 1);
-  OVS_DEBUG("[len=%zu] %s", len, sjson);
+  OVS_DEBUG("[len=%" PRIsz "] %s", len, sjson);
 
   /* parse json data */
   jnode = yajl_tree_parse(sjson, yajl_errbuf, sizeof(yajl_errbuf));
@@ -760,8 +761,8 @@ static void ovs_db_reconnect(ovs_db_t *pdb) {
       OVS_DEBUG("connect(): %s [family=%d]", STRERRNO, rp->ai_family);
     } else {
       /* send notification to event thread */
-      ovs_db_event_post(pdb, OVS_DB_EVENT_CONN_ESTABLISHED);
       pdb->sock = sock;
+      ovs_db_event_post(pdb, OVS_DB_EVENT_CONN_ESTABLISHED);
       break;
     }
   }
@@ -862,26 +863,30 @@ static void *ovs_event_worker(void *arg) {
     ts.tv_sec += (OVS_DB_EVENT_TIMEOUT);
     int ret = pthread_cond_timedwait(&pdb->event_thread.cond,
                                      &pdb->event_thread.mutex, &ts);
-    if (!ret) {
+    if (!ret || ret == ETIMEDOUT) {
       /* handle the event */
       OVS_DEBUG("handle event %d", pdb->event_thread.value);
       switch (pdb->event_thread.value) {
       case OVS_DB_EVENT_CONN_ESTABLISHED:
         if (pdb->cb.post_conn_init)
           pdb->cb.post_conn_init(pdb);
+        /* reset event */
+        pdb->event_thread.value = OVS_DB_EVENT_NONE;
         break;
       case OVS_DB_EVENT_CONN_TERMINATED:
         if (pdb->cb.post_conn_terminate)
           pdb->cb.post_conn_terminate();
+        /* reset event */
+        pdb->event_thread.value = OVS_DB_EVENT_NONE;
+        break;
+      case OVS_DB_EVENT_NONE:
+        /* wait timeout */
+        OVS_DEBUG("no event received (timeout)");
         break;
       default:
         OVS_DEBUG("unknown event received");
         break;
       }
-    } else if (ret == ETIMEDOUT) {
-      /* wait timeout */
-      OVS_DEBUG("no event received (timeout)");
-      continue;
     } else {
       /* unexpected error */
       OVS_ERROR("pthread_cond_timedwait() failed");
@@ -927,11 +932,10 @@ static int ovs_db_event_thread_init(ovs_db_t *pdb) {
   return 0;
 }
 
-/* Destroy EVENT thread */
-/* XXX: Must hold pdb->mutex when calling! */
-static int ovs_db_event_thread_destroy(ovs_db_t *pdb) {
+/* Terminate EVENT thread */
+static int ovs_db_event_thread_terminate(ovs_db_t *pdb) {
   if (pthread_equal(pdb->event_thread.tid, (pthread_t){0})) {
-    /* already destroyed */
+    /* already terminated */
     return 0;
   }
   ovs_db_event_post(pdb, OVS_DB_EVENT_TERMINATE);
@@ -941,11 +945,16 @@ static int ovs_db_event_thread_destroy(ovs_db_t *pdb) {
    * performs some task (handles event) and releases it when
    * while sleeping. Thus, if event thread exits, the mutex
    * remains locked */
+  pdb->event_thread.tid = (pthread_t){0};
   pthread_mutex_unlock(&pdb->event_thread.mutex);
+  return 0;
+}
+
+/* Destroy EVENT thread private data */
+static void ovs_db_event_thread_data_destroy(ovs_db_t *pdb) {
+  /* destroy mutex */
   pthread_mutex_destroy(&pdb->event_thread.mutex);
   pthread_cond_destroy(&pdb->event_thread.cond);
-  pdb->event_thread.tid = (pthread_t){0};
-  return 0;
 }
 
 /* Initialize POLL thread */
@@ -1247,23 +1256,26 @@ int ovs_db_destroy(ovs_db_t *pdb) {
   if (pdb == NULL)
     return -1;
 
+  /* stop event thread */
+  if (ovs_db_event_thread_terminate(pdb) < 0) {
+    OVS_ERROR("stop event thread failed");
+    ovs_db_ret = -1;
+  }
+
   /* try to lock the structure before releasing */
   if ((ret = pthread_mutex_lock(&pdb->mutex))) {
     OVS_ERROR("pthread_mutex_lock() DB mutex lock failed (%d)", ret);
     return -1;
   }
 
-  /* stop poll thread */
-  if (ovs_db_event_thread_destroy(pdb) < 0) {
+  /* stop poll thread and destroy thread's private data */
+  if (ovs_db_poll_thread_destroy(pdb) < 0) {
     OVS_ERROR("destroy poll thread failed");
     ovs_db_ret = -1;
   }
 
-  /* stop event thread */
-  if (ovs_db_poll_thread_destroy(pdb) < 0) {
-    OVS_ERROR("stop event thread failed");
-    ovs_db_ret = -1;
-  }
+  /* destroy event thread private data */
+  ovs_db_event_thread_data_destroy(pdb);
 
   pthread_mutex_unlock(&pdb->mutex);
 
index 79868fc..5134a6e 100644 (file)
@@ -118,10 +118,10 @@ static int latency_submit_match(cu_match_t *match, void *user_data) {
   sstrncpy(vl.type, data->type, sizeof(vl.type));
   for (size_t i = 0; i < data->latency_config.percentile_num; i++) {
     if (strlen(data->type_instance) != 0)
-      snprintf(vl.type_instance, sizeof(vl.type_instance), "%.117s-%.2f",
+      snprintf(vl.type_instance, sizeof(vl.type_instance), "%.50s-%.5g",
                data->type_instance, data->latency_config.percentile[i]);
     else
-      snprintf(vl.type_instance, sizeof(vl.type_instance), "%.0f",
+      snprintf(vl.type_instance, sizeof(vl.type_instance), "%.5g",
                data->latency_config.percentile[i]);
 
     vl.values = &(value_t){
@@ -150,11 +150,10 @@ static int latency_submit_match(cu_match_t *match, void *user_data) {
         bucket.upper_bound ? CDTIME_T_TO_DOUBLE(bucket.upper_bound) : INFINITY;
 
     if (strlen(data->type_instance) != 0)
-      snprintf(vl.type_instance, sizeof(vl.type_instance),
-               "%.54s-%.54s-%.2g_%.2g", data->type, data->type_instance,
-               lower_bound, upper_bound);
+      snprintf(vl.type_instance, sizeof(vl.type_instance), "%.50s-%.50s-%g_%g",
+               data->type, data->type_instance, lower_bound, upper_bound);
     else
-      snprintf(vl.type_instance, sizeof(vl.type_instance), "%.107s-%.2g_%.2g",
+      snprintf(vl.type_instance, sizeof(vl.type_instance), "%.50s-%g_%g",
                data->type, lower_bound, upper_bound);
 
     vl.values = &(value_t){
diff --git a/src/utils_taskstats.c b/src/utils_taskstats.c
new file mode 100644 (file)
index 0000000..f0d7333
--- /dev/null
@@ -0,0 +1,306 @@
+/**
+ * collectd - src/utils_taskstats.c
+ * Copyright (C) 2017       Florian octo Forster
+ *
+ * ISC License (ISC)
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "collectd.h"
+#include "utils_taskstats.h"
+
+#include "common.h"
+#include "plugin.h"
+#include "utils_time.h"
+
+#include <libmnl/libmnl.h>
+#include <linux/genetlink.h>
+#include <linux/taskstats.h>
+
+struct ts_s {
+  struct mnl_socket *nl;
+  pid_t pid;
+  uint32_t seq;
+  uint16_t genl_id_taskstats;
+  unsigned int port_id;
+};
+
+/* nlmsg_errno returns the errno encoded in nlh or zero if not an error. */
+static int nlmsg_errno(struct nlmsghdr *nlh, size_t sz) {
+  if (!mnl_nlmsg_ok(nlh, (int)sz)) {
+    ERROR("utils_taskstats: mnl_nlmsg_ok failed.");
+    return EPROTO;
+  }
+
+  if (nlh->nlmsg_type != NLMSG_ERROR) {
+    return 0;
+  }
+
+  struct nlmsgerr *nlerr = mnl_nlmsg_get_payload(nlh);
+  /* (struct nlmsgerr).error holds a negative errno. */
+  return nlerr->error * (-1);
+}
+
+static int get_taskstats_attr_cb(const struct nlattr *attr, void *data) {
+  struct taskstats *ret_taskstats = data;
+
+  uint16_t type = mnl_attr_get_type(attr);
+  switch (type) {
+  case TASKSTATS_TYPE_STATS:
+    if (mnl_attr_get_payload_len(attr) != sizeof(*ret_taskstats)) {
+      ERROR("utils_taskstats: mnl_attr_get_payload_len(attr) = %" PRIu32
+            ", want %zu",
+            mnl_attr_get_payload_len(attr), sizeof(*ret_taskstats));
+      return MNL_CB_ERROR;
+    }
+    struct taskstats *ts = mnl_attr_get_payload(attr);
+    memmove(ret_taskstats, ts, sizeof(*ret_taskstats));
+    return MNL_CB_OK;
+
+  case TASKSTATS_TYPE_AGGR_PID: /* fall through */
+  case TASKSTATS_TYPE_AGGR_TGID:
+    return mnl_attr_parse_nested(attr, get_taskstats_attr_cb, ret_taskstats);
+
+  case TASKSTATS_TYPE_PID: /* fall through */
+  case TASKSTATS_TYPE_TGID:
+    /* ignore */
+    return MNL_CB_OK;
+
+  default:
+    DEBUG("utils_taskstats: unknown attribute %" PRIu16
+          ", want one of TASKSTATS_TYPE_AGGR_PID/TGID, TASKSTATS_TYPE_STATS",
+          type);
+  }
+  return MNL_CB_OK;
+}
+
+static int get_taskstats_msg_cb(const struct nlmsghdr *nlh, void *data) {
+  return mnl_attr_parse(nlh, sizeof(struct genlmsghdr), get_taskstats_attr_cb,
+                        data);
+}
+
+static int get_taskstats(ts_t *ts, uint32_t tgid,
+                         struct taskstats *ret_taskstats) {
+  char buffer[MNL_SOCKET_BUFFER_SIZE];
+  uint32_t seq = ts->seq++;
+
+  struct nlmsghdr *nlh = mnl_nlmsg_put_header(buffer);
+  *nlh = (struct nlmsghdr){
+      .nlmsg_len = nlh->nlmsg_len,
+      .nlmsg_type = ts->genl_id_taskstats,
+      .nlmsg_flags = NLM_F_REQUEST,
+      .nlmsg_seq = seq,
+      .nlmsg_pid = ts->pid,
+  };
+
+  struct genlmsghdr *genh = mnl_nlmsg_put_extra_header(nlh, sizeof(*genh));
+  *genh = (struct genlmsghdr){
+      .cmd = TASKSTATS_CMD_GET,
+      .version = TASKSTATS_GENL_VERSION, // or TASKSTATS_VERSION?
+  };
+
+  // mnl_attr_put_u32(nlh, TASKSTATS_CMD_ATTR_PID, tgid);
+  mnl_attr_put_u32(nlh, TASKSTATS_CMD_ATTR_TGID, tgid);
+
+  if (mnl_socket_sendto(ts->nl, nlh, nlh->nlmsg_len) < 0) {
+    int status = errno;
+    ERROR("utils_taskstats: mnl_socket_sendto() = %s", STRERROR(status));
+    return status;
+  }
+
+  int status = mnl_socket_recvfrom(ts->nl, buffer, sizeof(buffer));
+  if (status < 0) {
+    status = errno;
+    ERROR("utils_taskstats: mnl_socket_recvfrom() = %s", STRERROR(status));
+    return status;
+  } else if (status == 0) {
+    ERROR("utils_taskstats: mnl_socket_recvfrom() = 0");
+    return ECONNABORTED;
+  }
+  size_t buffer_size = (size_t)status;
+
+  if ((status = nlmsg_errno((void *)buffer, buffer_size)) != 0) {
+    ERROR("utils_taskstats: TASKSTATS_CMD_GET(TASKSTATS_CMD_ATTR_TGID = "
+          "%" PRIu32 ") = %s",
+          (uint32_t)tgid, STRERROR(status));
+    return status;
+  }
+
+  status = mnl_cb_run(buffer, buffer_size, seq, ts->port_id,
+                      get_taskstats_msg_cb, ret_taskstats);
+  if (status < MNL_CB_STOP) {
+    ERROR("utils_taskstats: Parsing message failed.");
+    return EPROTO;
+  }
+
+  return 0;
+}
+
+static int get_family_id_attr_cb(const struct nlattr *attr, void *data) {
+  uint16_t type = mnl_attr_get_type(attr);
+  if (type != CTRL_ATTR_FAMILY_ID) {
+    return MNL_CB_OK;
+  }
+
+  if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
+    ERROR("mnl_attr_validate() = %s", STRERRNO);
+    return MNL_CB_ERROR;
+  }
+
+  uint16_t *ret_family_id = data;
+  *ret_family_id = mnl_attr_get_u16(attr);
+  return MNL_CB_STOP;
+}
+
+static int get_family_id_msg_cb(const struct nlmsghdr *nlh, void *data) {
+  return mnl_attr_parse(nlh, sizeof(struct genlmsghdr), get_family_id_attr_cb,
+                        data);
+}
+
+/* get_family_id initializes ts->genl_id_taskstats. Returns 0 on success and
+ * an error code otherwise. */
+static int get_family_id(ts_t *ts) {
+  char buffer[MNL_SOCKET_BUFFER_SIZE];
+  uint32_t seq = ts->seq++;
+
+  struct nlmsghdr *nlh = mnl_nlmsg_put_header(buffer);
+  *nlh = (struct nlmsghdr){
+      .nlmsg_len = nlh->nlmsg_len,
+      .nlmsg_type = GENL_ID_CTRL,
+      .nlmsg_flags = NLM_F_REQUEST,
+      .nlmsg_seq = seq,
+      .nlmsg_pid = ts->pid,
+  };
+
+  struct genlmsghdr *genh = mnl_nlmsg_put_extra_header(nlh, sizeof(*genh));
+  *genh = (struct genlmsghdr){
+      .cmd = CTRL_CMD_GETFAMILY, .version = 0x01,
+  };
+
+  mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, TASKSTATS_GENL_NAME);
+
+  assert(genh->cmd == CTRL_CMD_GETFAMILY);
+  assert(genh->version == TASKSTATS_GENL_VERSION);
+
+  if (mnl_socket_sendto(ts->nl, nlh, nlh->nlmsg_len) < 0) {
+    int status = errno;
+    ERROR("utils_taskstats: mnl_socket_sendto() = %s", STRERROR(status));
+    return status;
+  }
+
+  ts->genl_id_taskstats = 0;
+  while (42) {
+    int status = mnl_socket_recvfrom(ts->nl, buffer, sizeof(buffer));
+    if (status < 0) {
+      status = errno;
+      ERROR("utils_taskstats: mnl_socket_recvfrom() = %s", STRERROR(status));
+      return status;
+    } else if (status == 0) {
+      break;
+    }
+    size_t buffer_size = (size_t)status;
+
+    if ((status = nlmsg_errno((void *)buffer, buffer_size)) != 0) {
+      ERROR("utils_taskstats: CTRL_CMD_GETFAMILY(\"%s\"): %s",
+            TASKSTATS_GENL_NAME, STRERROR(status));
+      return status;
+    }
+
+    status = mnl_cb_run(buffer, buffer_size, seq, ts->port_id,
+                        get_family_id_msg_cb, &ts->genl_id_taskstats);
+    if (status < MNL_CB_STOP) {
+      ERROR("utils_taskstats: Parsing message failed.");
+      return EPROTO;
+    } else if (status == MNL_CB_STOP) {
+      break;
+    }
+  }
+
+  if (ts->genl_id_taskstats == 0) {
+    ERROR("utils_taskstats: Netlink communication succeeded, but "
+          "genl_id_taskstats is still zero.");
+    return ENOENT;
+  }
+
+  return 0;
+}
+
+void ts_destroy(ts_t *ts) {
+  if (ts == NULL) {
+    return;
+  }
+
+  if (ts->nl != NULL) {
+    mnl_socket_close(ts->nl);
+    ts->nl = NULL;
+  }
+
+  sfree(ts);
+}
+
+ts_t *ts_create(void) {
+  ts_t *ts = calloc(1, sizeof(*ts));
+  if (ts == NULL) {
+    ERROR("utils_taskstats: calloc failed: %s", STRERRNO);
+    return NULL;
+  }
+
+  if ((ts->nl = mnl_socket_open(NETLINK_GENERIC)) == NULL) {
+    ERROR("utils_taskstats: mnl_socket_open(NETLINK_GENERIC) = %s", STRERRNO);
+    ts_destroy(ts);
+    return NULL;
+  }
+
+  if (mnl_socket_bind(ts->nl, 0, MNL_SOCKET_AUTOPID) != 0) {
+    ERROR("utils_taskstats: mnl_socket_bind() = %s", STRERRNO);
+    ts_destroy(ts);
+    return NULL;
+  }
+
+  ts->pid = getpid();
+  ts->port_id = mnl_socket_get_portid(ts->nl);
+
+  int status = get_family_id(ts);
+  if (status != 0) {
+    ERROR("utils_taskstats: get_family_id() = %s", STRERROR(status));
+    ts_destroy(ts);
+    return NULL;
+  }
+
+  return ts;
+}
+
+int ts_delay_by_tgid(ts_t *ts, uint32_t tgid, ts_delay_t *out) {
+  if ((ts == NULL) || (out == NULL)) {
+    return EINVAL;
+  }
+
+  struct taskstats raw = {0};
+
+  int status = get_taskstats(ts, tgid, &raw);
+  if (status != 0) {
+    return status;
+  }
+
+  *out = (ts_delay_t){
+      .cpu_ns = raw.cpu_delay_total,
+      .blkio_ns = raw.blkio_delay_total,
+      .swapin_ns = raw.swapin_delay_total,
+      .freepages_ns = raw.freepages_delay_total,
+  };
+  return 0;
+}
diff --git a/src/utils_taskstats.h b/src/utils_taskstats.h
new file mode 100644 (file)
index 0000000..de07427
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ * collectd - src/utils_taskstats.h
+ * Copyright (C) 2017       Florian octo Forster
+ *
+ * ISC License (ISC)
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#ifndef UTILS_TASKSTATS_H
+#define UTILS_TASKSTATS_H 1
+
+#include "collectd.h"
+
+#include "utils_time.h"
+
+struct ts_s;
+typedef struct ts_s ts_t;
+
+typedef struct {
+  uint64_t cpu_ns;
+  uint64_t blkio_ns;
+  uint64_t swapin_ns;
+  uint64_t freepages_ns;
+} ts_delay_t;
+
+ts_t *ts_create(void);
+void ts_destroy(ts_t *);
+
+/* ts_delay_by_tgid returns Linux delay accounting information for the task
+ * identified by tgid. Returns zero on success and an errno otherwise. */
+int ts_delay_by_tgid(ts_t *ts, uint32_t tgid, ts_delay_t *out);
+
+#endif /* UTILS_TASKSTATS_H */
index 76c0674..052c4c0 100644 (file)
 #include "utils_avltree.h"
 #include "utils_vl_lookup.h"
 
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+
 #if HAVE_LIBKSTAT
 kstat_ctl_t *kc;
 #endif /* HAVE_LIBKSTAT */
index 174db2f..06e2408 100644 (file)
@@ -697,10 +697,11 @@ static double cpu_ns_to_percent(unsigned int node_cpus,
               (time_diff_sec * node_cpus * NANOSEC_IN_SEC);
   }
 
-  DEBUG(PLUGIN_NAME ": node_cpus=%u cpu_time_old=%llu cpu_time_new=%llu"
-                    "cpu_time_diff=%llu time_diff_sec=%f percent=%f",
-        node_cpus, cpu_time_old, cpu_time_new, cpu_time_diff, time_diff_sec,
-        percent);
+  DEBUG(PLUGIN_NAME ": node_cpus=%u cpu_time_old=%" PRIu64
+                    " cpu_time_new=%" PRIu64 "cpu_time_diff=%" PRIu64
+                    " time_diff_sec=%f percent=%f",
+        node_cpus, (uint64_t)cpu_time_old, (uint64_t)cpu_time_new,
+        (uint64_t)cpu_time_diff, time_diff_sec, percent);
 
   return percent;
 }
@@ -1658,7 +1659,7 @@ static int lv_init_instance(size_t i, plugin_read_cb callback) {
 
   memset(lv_ud, 0, sizeof(*lv_ud));
 
-  snprintf(inst->tag, sizeof(inst->tag), "%s-%zu", PLUGIN_NAME, i);
+  snprintf(inst->tag, sizeof(inst->tag), "%s-%" PRIsz, PLUGIN_NAME, i);
   inst->id = i;
 
   user_data_t *ud = &(lv_ud->ud);
index c301ae6..b39448f 100644 (file)
@@ -175,7 +175,7 @@ static int wg_flush_nolock(cdtime_t timeout, struct wg_callback *cb) {
   int status;
 
   DEBUG("write_graphite plugin: wg_flush_nolock: timeout = %.3f; "
-        "send_buf_fill = %zu;",
+        "send_buf_fill = %" PRIsz ";",
         (double)timeout, cb->send_buf_fill);
 
   /* timeout == 0  => flush unconditionally */
@@ -373,7 +373,8 @@ static int wg_send_message(char const *message, struct wg_callback *cb) {
   cb->send_buf_fill += message_len;
   cb->send_buf_free -= message_len;
 
-  DEBUG("write_graphite plugin: [%s]:%s (%s) buf %zu/%zu (%.1f %%) \"%s\"",
+  DEBUG("write_graphite plugin: [%s]:%s (%s) buf %" PRIsz "/%" PRIsz
+        " (%.1f %%) \"%s\"",
         cb->node, cb->service, cb->protocol, cb->send_buf_fill,
         sizeof(cb->send_buf),
         100.0 * ((double)cb->send_buf_fill) / ((double)sizeof(cb->send_buf)),
index 87e518b..024dccc 100644 (file)
@@ -228,7 +228,7 @@ static int wh_flush_nolock(cdtime_t timeout, wh_callback_t *cb) /* {{{ */
   int status;
 
   DEBUG("write_http plugin: wh_flush_nolock: timeout = %.3f; "
-        "send_buffer_fill = %zu;",
+        "send_buffer_fill = %" PRIsz ";",
         CDTIME_T_TO_DOUBLE(timeout), cb->send_buffer_fill);
 
   /* timeout == 0  => flush unconditionally */
@@ -380,7 +380,7 @@ static int wh_write_command(const data_set_t *ds,
                                  CDTIME_T_TO_DOUBLE(vl->interval), values);
   if (command_len >= sizeof(command)) {
     ERROR("write_http plugin: Command buffer too small: "
-          "Need %zu bytes.",
+          "Need %" PRIsz " bytes.",
           command_len + 1);
     return -1;
   }
@@ -410,8 +410,8 @@ static int wh_write_command(const data_set_t *ds,
   cb->send_buffer_fill += command_len;
   cb->send_buffer_free -= command_len;
 
-  DEBUG("write_http plugin: <%s> buffer %zu/%zu (%g%%) \"%s\"", cb->location,
-        cb->send_buffer_fill, cb->send_buffer_size,
+  DEBUG("write_http plugin: <%s> buffer %" PRIsz "/%" PRIsz " (%g%%) \"%s\"",
+        cb->location, cb->send_buffer_fill, cb->send_buffer_size,
         100.0 * ((double)cb->send_buffer_fill) / ((double)cb->send_buffer_size),
         command);
 
@@ -452,8 +452,8 @@ static int wh_write_json(const data_set_t *ds, const value_list_t *vl, /* {{{ */
     return status;
   }
 
-  DEBUG("write_http plugin: <%s> buffer %zu/%zu (%g%%)", cb->location,
-        cb->send_buffer_fill, cb->send_buffer_size,
+  DEBUG("write_http plugin: <%s> buffer %" PRIsz "/%" PRIsz " (%g%%)",
+        cb->location, cb->send_buffer_fill, cb->send_buffer_size,
         100.0 * ((double)cb->send_buffer_fill) /
             ((double)cb->send_buffer_size));
 
@@ -501,8 +501,8 @@ static int wh_write_kairosdb(const data_set_t *ds,
     return status;
   }
 
-  DEBUG("write_http plugin: <%s> buffer %zu/%zu (%g%%)", cb->location,
-        cb->send_buffer_fill, cb->send_buffer_size,
+  DEBUG("write_http plugin: <%s> buffer %" PRIsz "/%" PRIsz " (%g%%)",
+        cb->location, cb->send_buffer_fill, cb->send_buffer_size,
         100.0 * ((double)cb->send_buffer_fill) /
             ((double)cb->send_buffer_size));
 
@@ -802,7 +802,8 @@ static int wh_config_node(oconfig_item_t *ci) /* {{{ */
   /* Allocate the buffer. */
   cb->send_buffer = malloc(cb->send_buffer_size);
   if (cb->send_buffer == NULL) {
-    ERROR("write_http plugin: malloc(%zu) failed.", cb->send_buffer_size);
+    ERROR("write_http plugin: malloc(%" PRIsz ") failed.",
+          cb->send_buffer_size);
     wh_callback_free(cb);
     return -1;
   }
index 3c57380..2baaf0e 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 46b6d86..a6b39d3 100644 (file)
@@ -96,7 +96,7 @@ static bson_t *wm_create_bson(const data_set_t *ds, /* {{{ */
   for (size_t i = 0; i < ds->ds_num; i++) {
     char key[16];
 
-    snprintf(key, sizeof(key), "%zu", i);
+    snprintf(key, sizeof(key), "%" PRIsz, i);
 
     if (ds->ds[i].type == DS_TYPE_GAUGE)
       BSON_APPEND_DOUBLE(&subarray, key, vl->values[i].gauge);
@@ -109,7 +109,7 @@ static bson_t *wm_create_bson(const data_set_t *ds, /* {{{ */
     else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
       BSON_APPEND_INT64(&subarray, key, vl->values[i].absolute);
     else {
-      ERROR("write_mongodb plugin: Unknown ds_type %d for index %zu",
+      ERROR("write_mongodb plugin: Unknown ds_type %d for index %" PRIsz,
             ds->ds[i].type, i);
       bson_destroy(ret);
       return NULL;
@@ -121,7 +121,7 @@ static bson_t *wm_create_bson(const data_set_t *ds, /* {{{ */
   for (size_t i = 0; i < ds->ds_num; i++) {
     char key[16];
 
-    snprintf(key, sizeof(key), "%zu", i);
+    snprintf(key, sizeof(key), "%" PRIsz, i);
 
     if (store_rates)
       BSON_APPEND_UTF8(&subarray, key, "gauge");
@@ -134,7 +134,7 @@ static bson_t *wm_create_bson(const data_set_t *ds, /* {{{ */
   for (size_t i = 0; i < ds->ds_num; i++) {
     char key[16];
 
-    snprintf(key, sizeof(key), "%zu", i);
+    snprintf(key, sizeof(key), "%" PRIsz, i);
     BSON_APPEND_UTF8(&subarray, key, ds->ds[i].name);
   }
   bson_append_array_end(ret, &subarray); /* }}} dsnames */
@@ -144,7 +144,7 @@ static bson_t *wm_create_bson(const data_set_t *ds, /* {{{ */
   size_t error_location;
   if (!bson_validate(ret, BSON_VALIDATE_UTF8, &error_location)) {
     ERROR("write_mongodb plugin: Error in generated BSON document "
-          "at byte %zu",
+          "at byte %" PRIsz,
           error_location);
     bson_destroy(ret);
     return NULL;
index 9e9ed2e..26b0b4d 100644 (file)
@@ -59,7 +59,7 @@ static struct MHD_Daemon *httpd;
 
 static cdtime_t staleness_delta = PROMETHEUS_DEFAULT_STALENESS_DELTA;
 
-/* Unfortunately, protoc-c doesn't export it's implementation of varint, so we
+/* Unfortunately, protoc-c doesn't export its implementation of varint, so we
  * need to implement our own. */
 static size_t varint(uint8_t buffer[static VARINT_UINT32_BYTES],
                      uint32_t value) {
@@ -764,6 +764,15 @@ static int prom_open_socket(int addrfamily) {
     if (fd == -1)
       continue;
 
+    int tmp = 1;
+    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp)) != 0) {
+      WARNING("write_prometheus: setsockopt(SO_REUSEADDR) failed: %s",
+              STRERRNO);
+      close(fd);
+      fd = -1;
+      continue;
+    }
+
     if (bind(fd, ai->ai_addr, ai->ai_addrlen) != 0) {
       close(fd);
       fd = -1;
index 86f0c1f..55699d5 100644 (file)
@@ -362,7 +362,7 @@ wrr_value_to_event(struct riemann_host const *host, /* {{{ */
   {
     char ds_index[DATA_MAX_NAME_LEN];
 
-    snprintf(ds_index, sizeof(ds_index), "%zu", index);
+    snprintf(ds_index, sizeof(ds_index), "%" PRIsz, index);
     riemann_event_string_attribute_add(event, "ds_index", ds_index);
   }
 
index ddeecf8..71dd585 100644 (file)
@@ -31,7 +31,6 @@
 #include "common.h"
 #include "plugin.h"
 #include "utils_cache.h"
-
 #include <arpa/inet.h>
 #include <errno.h>
 #include <inttypes.h>
@@ -455,7 +454,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
   // incorporate the data source index
   {
     char ds_index[DATA_MAX_NAME_LEN];
-    snprintf(ds_index, sizeof(ds_index), "%zu", index);
+    snprintf(ds_index, sizeof(ds_index), "%" PRIsz, index);
     res = my_asprintf(&temp_str, "%s, \"collectd_data_source_index\": %s",
                       ret_str, ds_index);
     free(ret_str);
@@ -520,7 +519,8 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
         return NULL;
       }
     } else {
-      res = my_asprintf(&value_str, "%llu", vl->values[index].counter);
+      res = my_asprintf(&value_str, "%" PRIu64,
+                        (uint64_t)vl->values[index].counter);
       if (res == -1) {
         free(ret_str);
         ERROR("write_sensu plugin: Unable to alloc memory");
index d5d5598..349b0d0 100644 (file)
@@ -129,7 +129,7 @@ static int wt_flush_nolock(cdtime_t timeout, struct wt_callback *cb) {
   int status;
 
   DEBUG("write_tsdb plugin: wt_flush_nolock: timeout = %.3f; "
-        "send_buf_fill = %zu;",
+        "send_buf_fill = %" PRIsz ";",
         (double)timeout, cb->send_buf_fill);
 
   /* timeout == 0  => flush unconditionally */
@@ -347,7 +347,7 @@ static int wt_format_values(char *ret, size_t ret_len, int ds_num,
     }
     BUFFER_ADD(GAUGE_FORMAT, rates[ds_num]);
   } else if (ds->ds[ds_num].type == DS_TYPE_COUNTER)
-    BUFFER_ADD("%llu", vl->values[ds_num].counter);
+    BUFFER_ADD("%" PRIu64, (uint64_t)vl->values[ds_num].counter);
   else if (ds->ds[ds_num].type == DS_TYPE_DERIVE)
     BUFFER_ADD("%" PRIi64, vl->values[ds_num].derive);
   else if (ds->ds[ds_num].type == DS_TYPE_ABSOLUTE)
@@ -464,7 +464,7 @@ static int wt_send_message(const char *key, const char *value, cdtime_t time,
 
   if (message_len >= sizeof(message)) {
     ERROR("write_tsdb plugin: message buffer too small: "
-          "Need %zu bytes.",
+          "Need %" PRIsz " bytes.",
           message_len + 1);
     return -1;
   }
@@ -497,8 +497,8 @@ static int wt_send_message(const char *key, const char *value, cdtime_t time,
   cb->send_buf_fill += message_len;
   cb->send_buf_free -= message_len;
 
-  DEBUG("write_tsdb plugin: [%s]:%s buf %zu/%zu (%.1f %%) \"%s\"", cb->node,
-        cb->service, cb->send_buf_fill, sizeof(cb->send_buf),
+  DEBUG("write_tsdb plugin: [%s]:%s buf %" PRIsz "/%" PRIsz " (%.1f %%) \"%s\"",
+        cb->node, cb->service, cb->send_buf_fill, sizeof(cb->send_buf),
         100.0 * ((double)cb->send_buf_fill) / ((double)sizeof(cb->send_buf)),
         message);
 
index af4bfcc..c9abdd5 100644 (file)
@@ -99,6 +99,11 @@ static void free_zfs_values(kstat_t *ksp) {
 }
 
 #elif defined(KERNEL_SOLARIS)
+
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+
 extern kstat_ctl_t *kc;
 
 static long long get_zfs_value(kstat_t *ksp, char *name) {