Merge branch 'collectd-5.5'
authorRuben Kerkhof <ruben@rubenkerkhof.com>
Thu, 11 Aug 2016 16:40:40 +0000 (18:40 +0200)
committerRuben Kerkhof <ruben@rubenkerkhof.com>
Thu, 11 Aug 2016 16:40:40 +0000 (18:40 +0200)
270 files changed:
.clang-format [new file with mode: 0644]
.gitignore
.travis.yml [new file with mode: 0644]
AUTHORS
CONTRIBUTING.md [new file with mode: 0644]
Makefile.am
README
bindings/java/org/collectd/java/GenericJMXConfConnection.java
bindings/java/org/collectd/java/GenericJMXConfValue.java
bindings/perl/lib/Collectd/Unixsock.pm
bindings/perl/t/01_methods.t
build.sh
configure.ac
contrib/README
contrib/collectd.service [deleted file]
contrib/collection3/lib/Collectd/Graph/Common.pm
contrib/examples/myplugin.c
contrib/fedora/collectd.spec [deleted file]
contrib/fedora/init.d-collectd [deleted file]
contrib/redhat/collectd.spec
contrib/systemd.collectd.service
proto/Makefile.am [new file with mode: 0644]
proto/collectd.proto [new file with mode: 0644]
proto/types.proto [new file with mode: 0644]
src/Makefile.am
src/aggregation.c
src/amqp.c
src/apache.c
src/apcups.c
src/apple_sensors.c
src/aquaero.c
src/ascent.c
src/barometer.c
src/battery.c
src/bind.c
src/ceph.c
src/ceph_test.c
src/cgroups.c
src/chrony.c [new file with mode: 0644]
src/collectd-java.pod
src/collectd-nagios.c
src/collectd-python.pod
src/collectd-tg.c
src/collectd.conf.in
src/collectd.conf.pod
src/collectdctl.c
src/collectdmon.c
src/conntrack.c
src/contextswitch.c
src/cpu.c
src/cpufreq.c
src/cpusleep.c [new file with mode: 0644]
src/cpython.h
src/csv.c
src/curl.c
src/curl_json.c
src/curl_xml.c
src/daemon/Makefile.am
src/daemon/collectd.c
src/daemon/collectd.h
src/daemon/common.c
src/daemon/common.h
src/daemon/common_test.c
src/daemon/configfile.c
src/daemon/configfile.h
src/daemon/filter_chain.c
src/daemon/filter_chain.h
src/daemon/meta_data.c
src/daemon/meta_data.h
src/daemon/meta_data_test.c [new file with mode: 0644]
src/daemon/plugin.c
src/daemon/plugin.h
src/daemon/types_list.c
src/daemon/utils_avltree.c
src/daemon/utils_avltree.h
src/daemon/utils_avltree_test.c
src/daemon/utils_cache.c
src/daemon/utils_cache.h
src/daemon/utils_cache_mock.c
src/daemon/utils_complain.c
src/daemon/utils_complain.h
src/daemon/utils_heap.c
src/daemon/utils_heap.h
src/daemon/utils_heap_test.c
src/daemon/utils_ignorelist.c
src/daemon/utils_llist.c
src/daemon/utils_match.c
src/daemon/utils_random.c
src/daemon/utils_subst.c
src/daemon/utils_subst.h
src/daemon/utils_subst_test.c [new file with mode: 0644]
src/daemon/utils_tail.c
src/daemon/utils_tail_match.c
src/daemon/utils_threshold.c
src/daemon/utils_threshold.h
src/daemon/utils_time.c
src/daemon/utils_time.h
src/daemon/utils_time_mock.c [deleted file]
src/daemon/utils_time_test.c [new file with mode: 0644]
src/dbi.c
src/df.c
src/disk.c
src/dns.c
src/drbd.c
src/email.c
src/entropy.c
src/ethstat.c
src/exec.c
src/fhcount.c
src/filecount.c
src/fscache.c
src/gmond.c
src/gps.c [new file with mode: 0644]
src/grpc.cc [new file with mode: 0644]
src/hddtemp.c
src/interface.c
src/ipc.c
src/ipmi.c
src/iptables.c
src/ipvs.c
src/irq.c
src/java.c
src/libcollectdclient/Makefile.am
src/libcollectdclient/client.c
src/libcollectdclient/collectd/client.h
src/libcollectdclient/collectd/network.h
src/libcollectdclient/network.c
src/libcollectdclient/network_buffer.c
src/liboconfig/Makefile.am
src/liboconfig/oconfig.c
src/liboconfig/parser.y
src/liboconfig/scanner.l
src/load.c
src/log_logstash.c
src/logfile.c
src/lpar.c
src/lvm.c
src/madwifi.c
src/match_empty_counter.c
src/match_hashed.c
src/match_regex.c
src/match_timediff.c
src/match_value.c
src/mbmon.c
src/md.c
src/memcachec.c
src/memcached.c
src/memory.c
src/mic.c
src/modbus.c
src/mqtt.c [new file with mode: 0644]
src/multimeter.c
src/mysql.c
src/netapp.c
src/netlink.c
src/network.c
src/nfs.c
src/nginx.c
src/notify_desktop.c
src/notify_email.c
src/notify_nagios.c [new file with mode: 0644]
src/ntpd.c
src/numa.c
src/nut.c
src/olsrd.c
src/onewire.c
src/openldap.c
src/openvpn.c
src/oracle.c
src/perl.c
src/pf.c
src/pinba.c
src/pinba.proto
src/ping.c
src/postgresql.c
src/powerdns.c
src/processes.c
src/protocols.c
src/pyconfig.c
src/python.c
src/pyvalues.c
src/redis.c
src/riemann.proto [deleted file]
src/routeros.c
src/rrdcached.c
src/rrdtool.c
src/sensors.c
src/serial.c
src/sigrok.c
src/smart.c
src/snmp.c
src/statsd.c
src/swap.c
src/syslog.c
src/table.c
src/tail.c
src/tail_csv.c
src/tape.c
src/target_notification.c
src/target_replace.c
src/target_scale.c
src/target_set.c
src/target_v5upgrade.c
src/tcpconns.c
src/teamspeak2.c
src/ted.c
src/testing.h
src/thermal.c
src/threshold.c
src/tokyotyrant.c
src/turbostat.c
src/types.db
src/unixsock.c
src/uptime.c
src/users.c
src/utils_cmd_flush.c
src/utils_cmd_getthreshold.c
src/utils_cmd_getval.c
src/utils_cmd_listval.c
src/utils_cmd_putnotif.c
src/utils_cmd_putval.c
src/utils_crc32.c
src/utils_curl_stats.c [new file with mode: 0644]
src/utils_curl_stats.h [new file with mode: 0644]
src/utils_db_query.c
src/utils_db_query.h
src/utils_dns.c
src/utils_dns.h
src/utils_fbhash.c
src/utils_format_graphite.c
src/utils_format_graphite.h
src/utils_format_json.c
src/utils_format_json.h
src/utils_format_json_test.c [new file with mode: 0644]
src/utils_format_kairosdb.c [new file with mode: 0644]
src/utils_format_kairosdb.h [new file with mode: 0644]
src/utils_latency.c
src/utils_latency.h
src/utils_latency_test.c [new file with mode: 0644]
src/utils_mount.c
src/utils_mount.h
src/utils_mount_test.c
src/utils_parse_option.c
src/utils_rrdcreate.c
src/utils_vl_lookup.c
src/utils_vl_lookup_test.c
src/uuid.c
src/valgrind.FreeBSD.suppress [new file with mode: 0644]
src/varnish.c
src/virt.c
src/vmem.c
src/vserver.c
src/wireless.c
src/write_graphite.c
src/write_http.c
src/write_kafka.c
src/write_log.c
src/write_mongodb.c
src/write_redis.c
src/write_riemann.c
src/write_riemann_threshold.c
src/write_sensu.c
src/write_tsdb.c
src/xencpu.c [new file with mode: 0644]
src/xmms.c
src/zfs_arc.c
src/zone.c [new file with mode: 0644]
src/zookeeper.c
testwrapper.sh [new file with mode: 0755]
version-gen.sh

diff --git a/.clang-format b/.clang-format
new file mode 100644 (file)
index 0000000..70f50ad
--- /dev/null
@@ -0,0 +1,5 @@
+---
+BasedOnStyle: LLVM
+IncludeCategories:
+  - Regex: '"collectd.h"'
+  - Priority: -1
index 54eaa97..8154d73 100644 (file)
@@ -20,7 +20,6 @@ Makefile
 config.log
 config.status
 libtool
-src/.deps
 src/collectd.conf
 src/config.h
 src/libcollectdclient/libcollectdclient.pc
@@ -31,7 +30,7 @@ src/stamp-h1
 *.lo
 *.o
 .libs/
-src/collectd
+.deps/
 src/collectd-nagios
 src/collectd-tg
 src/collectdctl
@@ -53,6 +52,9 @@ src/liboconfig/scanner.c
 
 # protobuf stuff:
 src/*.pb-c.[ch]
+src/*.grpc.pb.cc
+src/*.pb.cc
+src/*.pb.h
 
 # make dist stuff:
 /collectd-*.tar.gz
@@ -73,19 +75,23 @@ bindings/java/org/collectd/java/*.class
 # python stuff
 *.pyc
 
-# tag stuff
-src/tags
-
 # backup stuff
 *~
-# tests stuff
-src/tests/.deps/
-src/tests/mock/.deps/
-src/tests/.dirstamp
-src/tests/mock/.dirstamp
-test*.log
 
-# new daemon repo
-src/daemon/.deps/
-src/daemon/.dirstamp
+# lint stuff
+*.ln
+
+#ide stuff
+.vscode
+
+# cscope stuff
+cscope.*
+
+# Unit tests
+src/daemon/test-suite.log
+src/tests/
+src/test-suite.log
+test_*
+
+# src/daemon/...
 src/daemon/collectd
diff --git a/.travis.yml b/.travis.yml
new file mode 100644 (file)
index 0000000..03d9dde
--- /dev/null
@@ -0,0 +1,56 @@
+sudo: required
+dist: trusty
+compiler:
+  - gcc
+  - clang
+language: c
+before_install:
+  - sudo apt-get update -qq
+  - sudo apt-get install -qq --no-install-recommends
+      iptables-dev
+      libatasmart-dev
+      libcap-dev
+      libcurl4-gnutls-dev
+      libdbi0-dev
+      libesmtp-dev
+      libganglia1-dev
+      libgcrypt11-dev
+      libglib2.0-dev
+      libhiredis-dev
+      libi2c-dev
+      libldap2-dev
+      libltdl-dev
+      liblvm2-dev
+      libmemcached-dev
+      libmnl-dev
+      libmodbus-dev
+      libmosquitto0-dev
+      libmysqlclient-dev
+      libnotify-dev
+      libopenipmi-dev
+      liboping-dev
+      libow-dev
+      libpcap-dev
+      libperl-dev
+      libpq-dev
+      libprotobuf-c0-dev
+      librabbitmq-dev
+      librdkafka-dev
+      librrd-dev
+      libsensors4-dev
+      libsigrok-dev
+      libsnmp-dev
+      libstatgrab-dev
+      libtokyocabinet-dev
+      libtokyotyrant-dev
+      libudev-dev
+      libupsclient-dev
+      libvarnish-dev
+      libvirt-dev
+      libxml2-dev
+      libyajl-dev
+      linux-libc-dev
+      perl
+      protobuf-c-compiler
+      python-dev
+script: sh build.sh && ./configure --with-python=/usr/bin/python && make distcheck DISTCHECK_CONFIGURE_FLAGS="--with-python=/usr/bin/python"
diff --git a/AUTHORS b/AUTHORS
index 3f63c3d..f5f6db0 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -4,9 +4,31 @@ Permanent project members
 Florian "octo" Forster <octo at verplant.org>
  - Initial author.
 
+Marc Fournier <marc.fournier at camptocamp.com>
+ - Various fixes to the varnish plugin.
+ - RPM specfile maintenance.
+ - libmnl support in the netlink plugin.
+ - linux support in the zfs_arc plugin.
+ - openldap plugin.
+ - continuous integration system.
+
+Pierre-Yves Ritschard <pyr at spootnik.org>
+ - Write-Riemann plugin.
+ - Write-Graphite plugin: Notification support.
+ - Write-Kafka plugin.
+ - Log-Logstash plugin.
+ - Normalization in the CPU plugin.
+ - Relative values in the Load plugin.
+
+Ruben Kerkhof <ruben at rubenkerkhof.com>
+ - Bugfixes and enhancements in many places all around the project.
+ - Fedora and EPEL packages.
+
 Sebastian "tokkee" Harl <sh at tokkee.org>
  - Bugfixes and enhancements in many places all around the project.
+ - grpc plugin.
  - perl plugin.
+ - postgresql plugin.
  - users plugin.
  - vserver plugin.
  - Debian package.
@@ -75,9 +97,16 @@ Christophe Kalt <collectd at klb.taranis.org>
  - The version 3 `log' mode.
  - Many Solaris related hints and fixes.
 
+Claudius Zingerli <gitmail at zeuz.ch>
+ - chrony plugin.
+
 Cyril Feraudet <cyril at feraudet.com>
  - ethstat plugin.
 
+Dagobert Michelsen <dam at opencsw.org>
+ - zone plugin.
+ - Many Solaris related hints and fixes.
+
 Dan Berrange <berrange at redhat.com>
  - uuid plugin.
 
@@ -115,6 +144,9 @@ Flavio Stanchina <flavio at stanchina.net>
 Franck Lombardi
  - UNIX socket code for the memcached plugin.
 
+Gergely Nagy <algernon at madhouse-project.org>
+ - Write-Riemann plugin.
+
 Jason Pepas <cell at ices.utexas.edu>
  - nfs plugin.
 
@@ -162,18 +194,14 @@ Manuel Sanmartin
    + swap
  - Various AIX-related fixes and hacks.
 
-Marc Fournier <marc.fournier at camptocamp.com>
- - Various fixes to the varnish plugin.
- - RPM specfile update.
- - libmnl support in the netlink plugin.
- - linux support in the zfs_arc plugin.
- - openldap plugin.
-
 Marco Chiappero <marco at absence.it>
  - uptime plugin.
  - ip6tables support in the iptables plugin.
  - openvpn plugin (support for more status file formats)
 
+Mathijs Möhlmann <collectd at mmrc.nl>
+ - zone plugin.
+
 Michael Hanselmann <public at hansmi.ch>
  - md plugin.
 
@@ -191,6 +219,9 @@ Michał Mirosław <mirq-linux at rere.qmqm.pl>
 Mirko Buffoni <briareos at eswat.org>
  - Port/Socket selection in the MySQL plugin.
 
+Nicolas Jourden <nicolas.jourden at laposte.net>
+ - gps plugin.
+
 Niki W. Waibel <niki.waibel at newlogic.com>
  - Initial autotools fixes.
  - libltdl code.
@@ -215,6 +246,10 @@ Paul Sadauskas <psadauskas at gmail.com>
  - `ReportByDevice' option of the df plugin.
  - write_http plugin.
 
+Pavel Rochnyack <pavel2000 at ngs.ru>
+ - xencpu plugin.
+ - Bugfixes and enhancements in many places all around the project.
+
 Peter Holik <peter at holik.at>
  - cpufreq plugin.
  - multimeter plugin.
@@ -225,14 +260,6 @@ Peter Holik <peter at holik.at>
 Phoenix Kayo <kayo.k11.4 at gmail.com>
  - pinba plugin.
 
-Pierre-Yves Ritschard <pyr at spootnik.org>
- - Write-Riemann plugin.
- - Write-Graphite plugin: Notification support.
- - Write-Kafka plugin.
- - Log-Logstash plugin.
- - Normalization in the CPU plugin.
- - Relative values in the Load plugin.
-
 Piotr Hosowicz <the55 at wp.pl>
  - SMF manifest for collectd.
 
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644 (file)
index 0000000..befb76e
--- /dev/null
@@ -0,0 +1,38 @@
+# Thanks !
+
+Thanks for your feedback & contributions to the
+[collectd project](https://collectd.org/) !
+
+## Need help using collectd ?
+
+Please use the
+[collectd mailing list](http://mailman.verplant.org/listinfo/collectd) or the
+[#collectd IRC channel](https://webchat.freenode.net/?channels=#collectd).
+We'd like to keep the github issue tracker for bugreports and patch reviews.
+
+## Found a bug ?
+
+Please mention the exact collectd version you're using, how it was installed
+(built from source, or installed from packages. Where was it downloaded
+from). Which operating system/architecture, distribution and version are you
+running collectd on.
+
+If collectd crashes, try to get a
+[stack trace](https://collectd.org/wiki/index.php/Core_file).
+
+## Fixed a bug ? Want to add a feature ?
+
+Using git/github to submit changes is not mandatory. Sending patches to the
+[mailing-list](http://mailman.verplant.org/listinfo/collectd) is also fine.
+In both cases, take a quick look at the
+[submission guidelines](https://collectd.org/wiki/index.php/Submitting_patches)
+and the [coding style recommendations](https://collectd.org/wiki/index.php/Coding_style).
+
+Please try to submit **bugfixes** to the
+[oldest release branch](https://github.com/collectd/collectd/milestones) on
+which the bug is found, so that it gets included in every future **bugfix
+release**.
+
+Please try to submit **new features** to the master branch (which will become
+the next **feature release**).
+
index b79ea1c..03bdd39 100644 (file)
@@ -6,11 +6,11 @@ if BUILD_INCLUDED_LTDL
 SUBDIRS += libltdl
 endif
 
-SUBDIRS += src bindings .
+SUBDIRS += proto src bindings .
 
 AM_CPPFLAGS = $(LTDLINCL)
 
-EXTRA_DIST = contrib version-gen.sh
+EXTRA_DIST = contrib version-gen.sh testwrapper.sh
 
 install-exec-hook:
        $(mkinstalldirs) $(DESTDIR)$(localstatedir)/run
diff --git a/README b/README
index 3e2c023..f2df12c 100644 (file)
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
  collectd - System information collection daemon
 =================================================
-http://collectd.org/
+https://collectd.org/
 
 About
 -----
@@ -51,6 +51,9 @@ Features
     - cgroups
       CPU accounting information for process groups under Linux.
 
+    - chrony
+      Chrony daemon statistics: Local clock drift, offset to peers, etc.
+
     - conntrack
       Number of nf_conntrack entries.
 
@@ -64,6 +67,9 @@ Features
     - cpufreq
       CPU frequency (For laptops with speed step or a similar technology)
 
+    - cpusleep
+      CPU sleep: Time spent in suspend (For mobile devices which enter suspend automatically)
+
     - curl
       Parse statistics from websites using regular expressions.
 
@@ -119,6 +125,12 @@ Features
     - gmond
       Receive multicast traffic from Ganglia instances.
 
+    - gps
+      Monitor gps related data through gpsd.
+
+    - grpc
+      Receive values over the network using the gRPC framework.
+
     - hddtemp
       Hard disk temperatures using hddtempd.
 
@@ -191,6 +203,9 @@ Features
       Reads values from Modbus/TCP enabled devices. Supports reading values
       from multiple "slaves" so gateway devices can be used.
 
+    - mqtt
+      Publishes and subscribes to MQTT topics.
+
     - multimeter
       Information provided by serial multimeters, such as the `Metex
       M-4650CR'.
@@ -379,12 +394,19 @@ Features
     - wireless
       Link quality of wireless cards. Linux only.
 
+    - xencpu
+      XEN Hypervisor CPU stats.
+
     - xmms
       Bitrate and frequency of music played with XMMS.
 
     - zfs_arc
       Statistics for ZFS' “Adaptive Replacement Cache” (ARC).
 
+    - zone
+      Measures the percentage of cpu load per container (zone) under Solaris 10
+      and higher
+
     - zookeeper
       Read data from Zookeeper's MNTR command.
 
@@ -495,6 +517,9 @@ Features
       Send an E-mail with the notification message to the configured
       recipients.
 
+    - notify_nagios
+      Submit notifications as passive check results to a local nagios instance.
+
     - exec
       Execute a program or script to handle the notification.
       See collectd-exec(5).
@@ -669,10 +694,19 @@ Prerequisites
     Used by the `gmond' plugin to process data received from Ganglia.
     <http://ganglia.info/>
 
+  * libgrpc (optional)
+    Used by the `grpc' plugin. gRPC requires a C++ compiler supporting the
+    C++11 standard.
+    <https://grpc.io/>
+
   * libgcrypt (optional)
     Used by the `network' plugin for encryption and authentication.
     <http://www.gnupg.org/>
 
+  * libgps (optional)
+    Used by the `gps' plugin.
+    <http://developer.berlios.de/projects/gpsd/>
+
   * libhal (optional)
     If present, the `uuid' plugin will check for UUID from HAL.
     <http://hal.freedesktop.org/>
@@ -758,10 +792,14 @@ Prerequisites
     The PostgreSQL C client library used by the `postgresql' plugin.
     <http://www.postgresql.org/>
 
+  * libprotobuf, protoc 3.0+ (optional)
+    Used by the `grpc' plugin to generate service stubs and code to handle
+    network packets of collectd's protobuf-based network protocol.
+    <https://developers.google.com/protocol-buffers/>
+
   * libprotobuf-c, protoc-c (optional)
     Used by the `pinba' plugin to generate a parser for the network packets
-    sent by the Pinba PHP extension, and by the `write_riemann' plugin to
-    generate events to be sent to a Riemann server.
+    sent by the Pinba PHP extension.
     <http://code.google.com/p/protobuf-c/>
 
   * libpython (optional)
@@ -823,6 +861,10 @@ Prerequisites
     `virt' plugins.
     <http://xmlsoft.org/>
 
+  * libxen (optional)
+    Used by the `xencpu' plugin.
+    <http://xenbits.xensource.com/>
+
   * libxmms (optional)
     <http://www.xmms.org/>
 
@@ -836,6 +878,10 @@ Prerequisites
      `varnish' plugin.
      <http://varnish-cache.org>
 
+  * riemann-c-client (optional)
+     For the `write_riemann' plugin.
+     <https://github.com/algernon/riemann-c-client>
+
 Configuring / Compiling / Installing
 ------------------------------------
 
@@ -889,18 +935,19 @@ Configuring with libjvm
   library checks succeed.
 
   If this doesn't work for you, you have the possibility to specify CPP-flags,
-  C-flags and LD-flags for the ‘Java’ plugin by hand, using the following three
-  (environment) variables:
+  C-flags, LD-flags and LIBS for the ‘Java’ plugin by hand, using the
+  following environment variables:
 
     - JAVA_CPPFLAGS
     - JAVA_CFLAGS
     - JAVA_LDFLAGS
+    - JAVA_LIBS
 
   For example (shortened for demonstration purposes):
 
     ./configure JAVA_CPPFLAGS="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
 
-  Adding "-ljvm" to the JAVA_LDFLAGS is done automatically, you don't have to
+  Adding "-ljvm" to JAVA_LIBS is done automatically, you don't have to
   do that.
 
 Generating the configure script
@@ -917,6 +964,7 @@ To generate the `configure` script, you'll need the following dependencies:
 - bison
 - libtool
 - libtool-ltdl
+- pkg-config
 
 The `build.sh' script takes no arguments.
 
index ea0f2fa..887c289 100644 (file)
@@ -52,7 +52,8 @@ class GenericJMXConfConnection
   private String _host = null;
   private String _instance_prefix = null;
   private String _service_url = null;
-  private MBeanServerConnection _jmx_connection = null;
+  private JMXConnector _jmx_connector = null;
+  private MBeanServerConnection _mbean_connection = null;
   private List<GenericJMXConfMBean> _mbeans = null;
 
   /*
@@ -92,55 +93,74 @@ class GenericJMXConfConnection
     return Collectd.getHostname();
   } /* }}} String getHost */
 
-private void connect () /* {{{ */
-{
-  JMXServiceURL service_url;
-  JMXConnector connector;
-  Map environment;
+  private void connect () /* {{{ */
+  {
+    JMXServiceURL service_url;
+    Map<String,Object> environment;
 
-  if (_jmx_connection != null)
-    return;
+    // already connected
+    if (this._jmx_connector != null) {
+      return;
+    }
 
-  environment = null;
-  if (this._password != null)
-  {
-    String[] credentials;
+    environment = null;
+    if (this._password != null)
+    {
+      String[] credentials;
 
-    if (this._username == null)
-      this._username = new String ("monitorRole");
+      if (this._username == null)
+        this._username = new String ("monitorRole");
 
-    credentials = new String[] { this._username, this._password };
+      credentials = new String[] { this._username, this._password };
 
-    environment = new HashMap ();
-    environment.put (JMXConnector.CREDENTIALS, credentials);
-    environment.put(JMXConnectorFactory.PROTOCOL_PROVIDER_CLASS_LOADER, this.getClass().getClassLoader());
-  }
+      environment = new HashMap<String,Object> ();
+      environment.put (JMXConnector.CREDENTIALS, credentials);
+      environment.put (JMXConnectorFactory.PROTOCOL_PROVIDER_CLASS_LOADER, this.getClass().getClassLoader());
+    }
 
-  try
-  {
-    service_url = new JMXServiceURL (this._service_url);
-    connector = JMXConnectorFactory.connect (service_url, environment);
-    _jmx_connection = connector.getMBeanServerConnection ();
-  }
-  catch (Exception e)
+    try
+    {
+      service_url = new JMXServiceURL (this._service_url);
+      this._jmx_connector = JMXConnectorFactory.connect (service_url, environment);
+      this._mbean_connection = _jmx_connector.getMBeanServerConnection ();
+    }
+    catch (Exception e)
+    {
+      Collectd.logError ("GenericJMXConfConnection: "
+          + "Creating MBean server connection failed: " + e);
+      disconnect ();
+      return;
+    }
+  } /* }}} void connect */
+
+  private void disconnect () /* {{{ */
   {
-    Collectd.logError ("GenericJMXConfConnection: "
-        + "Creating MBean server connection failed: " + e);
-    return;
-  }
-} /* }}} void connect */
+    try
+    {
+      if (this._jmx_connector != null) {
+        this._jmx_connector.close();
+      }
+    }
+    catch (Exception e)
+    {
+      // It's fine if close throws an exception
+    }
 
-/*
- * public methods
- *
- * <Connection>
- *   Host "tomcat0.mycompany"
- *   ServiceURL "service:jmx:rmi:///jndi/rmi://localhost:17264/jmxrmi"
- *   Collect "java.lang:type=GarbageCollector,name=Copy"
- *   Collect "java.lang:type=Memory"
- * </Connection>
- *
- */
+    this._jmx_connector = null;
+    this._mbean_connection = null;
+  } /* }}} void disconnect */
+
+  /*
+   * public methods
+   *
+   * <Connection>
+   *   Host "tomcat0.mycompany"
+   *   ServiceURL "service:jmx:rmi:///jndi/rmi://localhost:17264/jmxrmi"
+   *   Collect "java.lang:type=GarbageCollector,name=Copy"
+   *   Collect "java.lang:type=Memory"
+   * </Connection>
+   *
+   */
   public GenericJMXConfConnection (OConfigItem ci) /* {{{ */
     throws IllegalArgumentException
   {
@@ -217,9 +237,10 @@ private void connect () /* {{{ */
   {
     PluginData pd;
 
+    // try to connect
     connect ();
 
-    if (this._jmx_connection == null)
+    if (this._mbean_connection == null)
       return;
 
     Collectd.logDebug ("GenericJMXConfConnection.query: "
@@ -234,11 +255,11 @@ private void connect () /* {{{ */
     {
       int status;
 
-      status = this._mbeans.get (i).query (this._jmx_connection, pd,
+      status = this._mbeans.get (i).query (this._mbean_connection, pd,
           this._instance_prefix);
       if (status != 0)
       {
-        this._jmx_connection = null;
+        disconnect ();
         return;
       }
     } /* for */
index 4b42c91..25b70d4 100644 (file)
@@ -28,6 +28,7 @@ package org.collectd.java;
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Collection;
 import java.util.Set;
 import java.util.Iterator;
 import java.util.ArrayList;
@@ -39,6 +40,7 @@ import javax.management.MBeanServerConnection;
 import javax.management.ObjectName;
 import javax.management.openmbean.OpenType;
 import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
 import javax.management.openmbean.InvalidKeyException;
 
 import org.collectd.api.Collectd;
@@ -68,6 +70,7 @@ class GenericJMXConfValue
   private List<String> _attributes;
   private String _instance_prefix;
   private List<String> _instance_from;
+  private String _plugin_name;
   private boolean _is_table;
 
   /**
@@ -295,6 +298,46 @@ class GenericJMXConfValue
     {
       if (value instanceof CompositeData)
         return (queryAttributeRecursive ((CompositeData) value, attrName));
+      else if (value instanceof TabularData)
+        return (queryAttributeRecursive ((TabularData) value, attrName));
+      else
+        return (null);
+    }
+  } /* }}} queryAttributeRecursive */
+
+  private Object queryAttributeRecursive (TabularData parent, /* {{{ */
+      List<String> attrName)
+  {
+    String key;
+    Object value = null;
+
+    key = attrName.remove (0);
+
+    TabularData tabularData = (TabularData) parent;
+    Collection<CompositeData> table =
+        (Collection<CompositeData>)tabularData.values();
+    for (CompositeData compositeData : table)
+    {
+      if (key.equals(compositeData.get("key")))
+      {
+        value = compositeData.get("value");
+      }
+    }
+    if (null == value)
+    {
+      return (null);
+    }
+
+    if (attrName.size () == 0)
+    {
+      return (value);
+    }
+    else
+    {
+      if (value instanceof CompositeData)
+        return (queryAttributeRecursive ((CompositeData) value, attrName));
+      else if (value instanceof TabularData)
+        return (queryAttributeRecursive ((TabularData) value, attrName));
       else
         return (null);
     }
@@ -341,6 +384,8 @@ class GenericJMXConfValue
     {
       if (value instanceof CompositeData)
         return (queryAttributeRecursive((CompositeData) value, attrNameList));
+      else if (value instanceof TabularData)
+        return (queryAttributeRecursive((TabularData) value, attrNameList));
       else if (value instanceof OpenType)
       {
         OpenType ot = (OpenType) value;
@@ -351,7 +396,7 @@ class GenericJMXConfValue
       else
       {
         Collectd.logError ("GenericJMXConfValue: Received object of "
-            + "unknown class.");
+            + "unknown class. " + attrName + " " + ((value == null)?"null":value.getClass().getName()));
         return (null);
       }
     }
@@ -436,6 +481,7 @@ class GenericJMXConfValue
     this._attributes = new ArrayList<String> ();
     this._instance_prefix = null;
     this._instance_from = new ArrayList<String> ();
+    this._plugin_name = null;
     this._is_table = false;
 
     /*
@@ -485,6 +531,12 @@ class GenericJMXConfValue
         if (tmp != null)
           this._instance_from.add (tmp);
       }
+      else if (child.getKey ().equalsIgnoreCase ("PluginName"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp != null)
+          this._plugin_name = tmp;
+      }
       else
         throw (new IllegalArgumentException ("Unknown option: "
               + child.getKey ()));
@@ -538,6 +590,10 @@ class GenericJMXConfValue
 
     vl = new ValueList (pd);
     vl.setType (this._ds_name);
+    if (this._plugin_name != null)
+    {
+      vl.setPlugin (this._plugin_name);
+    }
 
     /*
      * Build the instnace prefix from the fixed string prefix and the
index 5e79d26..304bbbc 100644 (file)
@@ -137,13 +137,13 @@ sub _parse_identifier
 
 sub _escape_argument
 {
-       local $_ = shift;
+    my $arg = shift;
 
-       return $_ if /^\w+$/;
+       return $arg if $arg =~ /^\w+$/;
 
-       s#\\#\\\\#g;
-       s#"#\\"#g;
-       return "\"$_\"";
+       $arg =~ s#\\#\\\\#g;
+       $arg =~ s#"#\\"#g;
+       return "\"$arg\"";
 }
 
 # Send a command on a socket, including any required argument escaping.
@@ -193,6 +193,32 @@ sub _socket_chat
        return $cbdata;
 }
 
+# Send a raw message on a socket.
+# Returns true upon success and false otherwise.
+sub _send_message
+{
+       my ($self, $msg) = @_;
+       
+       my $fh = $self->{'sock'} or confess ('object has no filehandle');
+       
+       $msg .= "\n" unless $msg =~/\n$/;
+       
+       #1024 is default buffer size at unixsock.c us_handle_client()
+       warn "Collectd::Unixsock->_send_message(\$msg): message is too long!" if length($msg) > 1024;
+       
+       _debug "-> $msg";
+       $fh->print($msg);
+
+       $msg = <$fh>;
+       chomp ($msg);
+       _debug "<- $msg\n";
+
+       my ($status, $error) = split / /, $msg, 2;
+       return 1 if $status == 0;
+
+       $self->{error} = $error;
+       return;
+}
 
 =head1 PUBLIC METHODS
 
@@ -330,18 +356,8 @@ sub putval
        . _escape_argument ($identifier)
        . $interval
        . ' ' . _escape_argument ($values) . "\n";
-       _debug "-> $msg";
-       $fh->print($msg);
 
-       $msg = <$fh>;
-       chomp $msg;
-       _debug "<- $msg\n";
-
-       ($status, $msg) = split / /, $msg, 2;
-       return 1 if $status == 0;
-
-       $self->{error} = $msg;
-       return;
+       return $self->_send_message($msg);
 } # putval
 
 =item I<$res> = I<$self>-E<gt>B<listval_filter> ( C<%identifier> )
@@ -500,18 +516,7 @@ sub putnotif
        . join (' ', map { $_ . '=' . _escape_argument ($args{$_}) } keys %args)
        . "\n";
 
-       _debug "-> $msg";
-       $fh->print($msg);
-
-       $msg = <$fh>;
-       chomp $msg;
-       _debug "<- $msg\n";
-
-       ($status, $msg) = split / /, $msg, 2;
-       return 1 if $status == 0;
-
-       $self->{error} = $msg;
-       return;
+       return $self->_send_message($msg);
 } # putnotif
 
 =item I<$self>-E<gt>B<flush> (B<timeout> =E<gt> I<$timeout>, B<plugins> =E<gt> [...], B<identifier>  =E<gt> [...]);
@@ -549,7 +554,6 @@ sub flush
 
        my $fh = $self->{sock} or confess;
 
-       my $status = 0;
        my $msg    = "FLUSH";
 
     $msg .= " timeout=$args{timeout}" if defined $args{timeout};
@@ -564,6 +568,7 @@ sub flush
 
        if ($args{identifier})
        {
+               my $pre = $msg;
                for my $identifier (@{$args{identifier}})
                {
                        my $ident_str;
@@ -576,24 +581,18 @@ sub flush
                        }
 
                        $ident_str = _create_identifier ($identifier) or return;
-                       $msg .= ' identifier=' . _escape_argument ($ident_str);
+                       $ident_str = ' identifier=' . _escape_argument ($ident_str);
+
+                       if (length($msg)+length($ident_str) >= 1023) { #1024 - 1 byte for \n
+                               $self->_send_message($msg) or return;
+                               $msg = $pre;
+                       }
+            
+                       $msg .= $ident_str;
                }
        }
-
-       $msg .= "\n";
-
-       _debug "-> $msg";
-       $fh->print($msg);
-
-       $msg = <$fh>;
-       chomp ($msg);
-       _debug "<- $msg\n";
-
-       ($status, $msg) = split / /, $msg, 2;
-       return 1 if $status == 0;
-
-       $self->{error} = $msg;
-       return;
+    
+       return $self->_send_message($msg);
 }
 
 sub error
index 2f7818b..4e94f8e 100644 (file)
@@ -16,7 +16,7 @@ sub test_query {
     my ($nresults, $resultdata) = @$results;
     my $r = $s->getval(%{Collectd::Unixsock::_parse_identifier($attr)});
     is(ref $r, 'HASH', "Got a result for $attr");
-    is(scalar keys $r, $nresults, "$nresults result result for $attr");
+    is(scalar keys %$r, $nresults, "$nresults result result for $attr");
     is_deeply($r, $resultdata, "Data or $attr matches");
 }
 
index 20854b1..57f3d44 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -18,7 +18,7 @@ EOF
        done
 }
 
-check_for_application lex yacc autoheader aclocal automake autoconf
+check_for_application lex bison autoheader aclocal automake autoconf
 
 # Actually we don't need the pkg-config executable, but we need the M4 macros.
 # We check for `pkg-config' here and hope that M4 macros will then be
index d214d57..8dda710 100644 (file)
@@ -1,6 +1,7 @@
 dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ([2.60])
 AC_INIT([collectd],[m4_esyscmd(./version-gen.sh)])
-AC_CONFIG_SRCDIR(src/)
+AC_CONFIG_SRCDIR(src/target_set.c)
 AC_CONFIG_HEADERS(src/config.h)
 AC_CONFIG_AUX_DIR([libltdl/config])
 
@@ -31,7 +32,7 @@ m4_ifdef([LT_PACKAGE_VERSION],
 
 AM_CONDITIONAL([BUILD_INCLUDED_LTDL], [test "x$LTDLDEPS" != "x"])
 
-AM_INIT_AUTOMAKE([tar-pax dist-bzip2 foreign])
+AM_INIT_AUTOMAKE([subdir-objects tar-pax dist-bzip2 no-dist-gzip foreign])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 AC_LANG(C)
 
@@ -42,7 +43,10 @@ AC_SYS_LARGEFILE
 #
 # Checks for programs.
 #
-AC_PROG_CC
+AC_PROG_CC_C99([],
+  [AC_MSG_ERROR([No compiler found that supports C99])]
+)
+AC_PROG_CXX
 AC_PROG_CPP
 AC_PROG_EGREP
 AC_PROG_INSTALL
@@ -56,6 +60,8 @@ AC_PROG_LIBTOOL
 AC_PROG_LEX
 AC_PROG_YACC
 
+AC_PATH_PROG([VALGRIND], [valgrind])
+
 # Warn when pkg.m4 is missing
 m4_pattern_forbid([^_?PKG_[A-Z_]+$],[*** pkg.m4 missing, please install pkg-config])
 
@@ -73,26 +79,33 @@ then
        AC_MSG_ERROR([bison is missing and you do not have ${srcdir}/src/liboconfig/parser.c. Please install bison])
 fi
 
-AC_CHECK_PROG([have_protoc_c], [protoc-c], [yes], [no])
-if test "x$have_protoc_c" = "xno"
-then
-       have_protoc_c="no (protoc-c compiler not found)"
+AC_ARG_VAR([PROTOC], [path to the protoc binary])
+AC_PATH_PROG([PROTOC], [protoc])
+have_protoc3="no"
+if test "x$PROTOC" != "x"; then
+       AC_MSG_CHECKING([for protoc 3.0.0+])
+       if $PROTOC --version | $EGREP libprotoc.3 >/dev/null; then
+               protoc3="yes (`$PROTOC --version`)"
+               have_protoc3="yes"
+       else
+               protoc3="no (`$PROTOC --version`)"
+       fi
+       AC_MSG_RESULT([$protoc3])
 fi
+AM_CONDITIONAL(HAVE_PROTOC3, test "x$have_protoc3" = "xyes")
 
-if test "x$have_protoc_c" = "xyes"
-then
-       AC_CHECK_HEADERS([protobuf-c/protobuf-c.h google/protobuf-c/protobuf-c.h],
-                        [have_protoc_c="yes"; break],
-                        [have_protoc_c="no (<google/protobuf-c/protobuf-c.h> not found)"])
-fi
-if test "x$have_protoc_c" = "xyes"
-then
-       AC_CHECK_LIB([protobuf-c], [protobuf_c_message_pack],
-                    [have_protoc_c="yes"],
-                    [have_protoc_c="no (libprotobuf-c not found)"])
+AC_ARG_VAR([GRPC_CPP_PLUGIN], [path to the grpc_cpp_plugin binary])
+AC_PATH_PROG([GRPC_CPP_PLUGIN], [grpc_cpp_plugin])
+AM_CONDITIONAL(HAVE_GRPC_CPP, test "x$GRPC_CPP_PLUGIN" != "x")
 
+AC_ARG_VAR([PROTOC_C], [path to the protoc-c binary])
+AC_PATH_PROG([PROTOC_C], [protoc-c])
+if test "x$PROTOC_C" = "x"
+then
+  have_protoc_c="no (protoc-c compiler not found)"
+else
+  have_protoc_c="yes"
 fi
-AM_CONDITIONAL(HAVE_PROTOC_C, test "x$have_protoc_c" = "xyes")
 
 AC_MSG_CHECKING([for kernel type ($host_os)])
 case $host_os in
@@ -112,6 +125,10 @@ case $host_os in
        AC_DEFINE([KERNEL_OPENBSD], 1, [True if program is to be compiled for an OpenBSD kernel])
        ac_system="OpenBSD"
        ;;
+       *netbsd*)
+       AC_DEFINE([KERNEL_NETBSD], 1, [True if program is to be compiled for a NetBSD kernel])
+       ac_system="NetBSD"
+       ;;
        *aix*)
        AC_DEFINE([KERNEL_AIX], 1, [True if program is to be compiled for a AIX kernel])
        ac_system="AIX"
@@ -125,12 +142,12 @@ case $host_os in
 esac
 AC_MSG_RESULT([$ac_system])
 
-AM_CONDITIONAL([BUILD_LINUX],[test "x$ac_system" = "xLinux"])
-AM_CONDITIONAL([BUILD_SOLARIS],[test "x$ac_system" = "xSolaris"])
-AM_CONDITIONAL([BUILD_DARWIN],[test "x$ac_system" = "xDarwin"])
-AM_CONDITIONAL([BUILD_OPENBSD],[test "x$ac_system" = "xOpenBSD"])
-AM_CONDITIONAL([BUILD_AIX],[test "x$ac_system" = "xAIX"])
-AM_CONDITIONAL([BUILD_FREEBSD],[test "x$ac_system" = "xFreeBSD"])
+AM_CONDITIONAL([BUILD_AIX], [test "x$ac_system" = "xAIX"])
+AM_CONDITIONAL([BUILD_DARWIN], [test "x$ac_system" = "xDarwin"])
+AM_CONDITIONAL([BUILD_FREEBSD], [test "x$ac_system" = "xFreeBSD"])
+AM_CONDITIONAL([BUILD_LINUX], [test "x$ac_system" = "xLinux"])
+AM_CONDITIONAL([BUILD_OPENBSD], [test "x$ac_system" = "xOpenBSD"])
+AM_CONDITIONAL([BUILD_SOLARIS], [test "x$ac_system" = "xSolaris"])
 
 if test "x$ac_system" = "xLinux"
 then
@@ -199,6 +216,19 @@ AC_HEADER_STDBOOL
 
 AC_CHECK_HEADERS(stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h sys/isa_defs.h fnmatch.h libgen.h)
 
+# For entropy plugin on newer NetBSD
+AC_CHECK_HEADERS(sys/rndio.h, [], [],
+[#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+])
+
 # For ping library
 AC_CHECK_HEADERS(netinet/in_systm.h, [], [],
 [#if HAVE_STDINT_H
@@ -413,7 +443,7 @@ AC_CHECK_HEADERS(sys/sysctl.h, [], [],
 AC_MSG_CHECKING([for sysctl kern.cp_times])
 if test -x /sbin/sysctl
 then
-       /sbin/sysctl kern.cp_times 2>/dev/null
+       /sbin/sysctl kern.cp_times >/dev/null 2>&1
        if test $? -eq 0
        then
                AC_MSG_RESULT([yes])
@@ -426,6 +456,22 @@ else
        AC_MSG_RESULT([no])
 fi
 
+AC_MSG_CHECKING([for sysctl kern.cp_time])
+if test -x /sbin/sysctl
+then
+       /sbin/sysctl kern.cp_time >/dev/null 2>&1
+       if test $? -eq 0
+       then
+               AC_MSG_RESULT([yes])
+               AC_DEFINE(HAVE_SYSCTL_KERN_CP_TIME, 1,
+                       [Define if sysctl supports kern.cp_time])
+       else
+               AC_MSG_RESULT([no])
+       fi
+else
+       AC_MSG_RESULT([no])
+fi
+
 # For hddtemp module
 AC_CHECK_HEADERS(linux/major.h)
 
@@ -445,7 +491,7 @@ else
        have_linux_raid_md_u_h="no"
 fi
 
-# For the swap module
+# For the wireless module
 have_linux_wireless_h="no"
 if test "x$ac_system" = "xLinux"
 then
@@ -680,8 +726,6 @@ AC_CHECK_HEADERS(netinet/if_ether.h, [], [],
 #endif
 ])
 
-AC_CHECK_HEADERS(netinet/ip_compat.h)
-
 have_net_pfvar_h="no"
 AC_CHECK_HEADERS(net/pfvar.h,
                [have_net_pfvar_h="yes"],
@@ -705,6 +749,23 @@ AC_CHECK_HEADERS(net/pfvar.h,
 have_termios_h="no"
 AC_CHECK_HEADERS(termios.h, [have_termios_h="yes"])
 
+# For cpusleep plugin
+AC_CACHE_CHECK([whether clock_boottime and clock_monotonic are supported],
+                      [c_cv_have_clock_boottime_monotonic],
+                      AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[
+#include <time.h>
+]],
+[[
+ struct timespec b, m;
+ clock_gettime(CLOCK_BOOTTIME, &b );
+ clock_gettime(CLOCK_MONOTONIC, &m );
+]]
+                      )],
+                      [c_cv_have_clock_boottime_monotonic="yes"],
+                      [c_cv_have_clock_boottime_monotonic="no"]))
+
+
 # For the turbostat plugin
 have_asm_msrindex_h="no"
 AC_CHECK_HEADERS(asm/msr-index.h, [have_asm_msrindex_h="yes"])
@@ -736,23 +797,30 @@ AC_CHECK_HEADERS(sys/capability.h)
 # Checks for typedefs, structures, and compiler characteristics.
 #
 AC_C_CONST
-AC_C_INLINE
-AC_TYPE_OFF_T
 AC_TYPE_PID_T
 AC_TYPE_SIZE_T
-AC_TYPE_SSIZE_T
 AC_TYPE_UID_T
-AC_TYPE_UINT32_T
 AC_HEADER_TIME
 
 #
 # Checks for library functions.
 #
-AC_PROG_GCC_TRADITIONAL
-AC_CHECK_FUNCS(gettimeofday select strdup strtol getaddrinfo getnameinfo strchr memcpy strstr strcmp strncmp strncpy strlen strncasecmp strcasecmp openlog closelog sysconf setenv if_indextoname setlocale)
+AC_CHECK_FUNCS(gettimeofday select strdup strtol getaddrinfo getnameinfo strchr memcpy strstr strcmp strncmp strncpy strlen strncasecmp strcasecmp openlog closelog sysconf setenv if_indextoname setlocale asprintf)
 
 AC_FUNC_STRERROR_R
 
+test_cxx_flags() {
+       AC_LANG_PUSH([C++])
+       AC_LANG_CONFTEST([
+               AC_LANG_SOURCE([[int main(void){}]])
+       ])
+       $CXX -c conftest.cpp $CXXFLAGS $@ > /dev/null 2> /dev/null
+       ret=$?
+       rm -f conftest.o
+       AC_LANG_POP([C++])
+       return $ret
+}
+
 SAVE_CFLAGS="$CFLAGS"
 # Emulate behavior of src/Makefile.am
 if test "x$GCC" = "xyes"
@@ -852,8 +920,6 @@ fi
 if test "x$have_clock_gettime" = "xyes"
 then
        AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if the clock_gettime(2) function is available.])
-else
-       AC_MSG_WARN(cannot find clock_gettime)
 fi
 
 nanosleep_needs_rt="no"
@@ -1305,6 +1371,20 @@ AC_ARG_WITH(useragent, [AS_HELP_STRING([--with-useragent@<:@=AGENT@:>@], [User a
 
 # }}}
 
+# --with-data-max-name-len {{{
+AC_ARG_WITH(data-max-name-len, [AS_HELP_STRING([--with-data-max-name-len@<:@=VALUE@:>@], [Maximum length of data buffers])],
+[
+    if test "x$withval" != "x" && test $withval -gt 0
+    then
+        AC_DEFINE_UNQUOTED(DATA_MAX_NAME_LEN, [$withval], [Maximum length of data buffers])
+    else
+        AC_MSG_ERROR([DATA_MAX_NAME_LEN must be a positive integer -- $withval given])
+    fi
+],
+[   AC_DEFINE(DATA_MAX_NAME_LEN, 128, [Maximum length of data buffers])]
+)
+# }}}
+
 have_getfsstat="no"
 AC_CHECK_FUNCS(getfsstat, [have_getfsstat="yes"])
 have_getvfsstat="no"
@@ -1382,15 +1462,15 @@ if test "x$have_getmntent" = "xc"; then
 fi
 if test "x$have_getmntent" = "xsun"; then
        AC_DEFINE(HAVE_SUN_GETMNTENT, 1,
-                 [Define if the function getmntent exists. It's the version from libsun.])
+                 [Define if the function getmntent exists. It is the version from libsun.])
 fi
 if test "x$have_getmntent" = "xseq"; then
        AC_DEFINE(HAVE_SEQ_GETMNTENT, 1,
-                 [Define if the function getmntent exists. It's the version from libseq.])
+                 [Define if the function getmntent exists. It is the version from libseq.])
 fi
 if test "x$have_getmntent" = "xgen"; then
        AC_DEFINE(HAVE_GEN_GETMNTENT, 1,
-                 [Define if the function getmntent exists. It's the version from libgen.])
+                 [Define if the function getmntent exists. It is the version from libgen.])
 fi
 
 # Check for htonll
@@ -1481,6 +1561,24 @@ AC_CHECK_MEMBERS([struct kinfo_proc.p_pid, struct kinfo_proc.p_vm_rssize],
 #include <kvm.h>
        ])
 
+
+AC_CHECK_MEMBERS([struct kinfo_proc2.p_pid, struct kinfo_proc2.p_uru_maxrss],
+       [
+               AC_DEFINE(HAVE_STRUCT_KINFO_PROC2_NETBSD, 1,
+                       [Define if struct kinfo_proc2 exists in the NetBSD variant.])
+               have_struct_kinfo_proc2_netbsd="yes"
+       ],
+       [
+               have_struct_kinfo_proc2_netbsd="no"
+       ],
+       [
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <kvm.h>
+       ])
+
+
+
 AC_CHECK_MEMBERS([struct udphdr.uh_dport, struct udphdr.uh_sport], [], [],
 [#define _BSD_SOURCE
 #define _DEFAULT_SOURCE
@@ -1548,18 +1646,48 @@ AC_CHECK_LIB(resolv, res_search,
 AM_CONDITIONAL(BUILD_WITH_LIBRESOLV, test "x$with_libresolv" = "xyes")
 
 dnl Check for HAL (hardware abstraction library)
-with_libhal="yes"
-AC_CHECK_LIB(hal,libhal_device_property_exists,
-            [AC_DEFINE(HAVE_LIBHAL, 1, [Define to 1 if you have 'hal' library])],
-            [with_libhal="no"])
-if test "x$with_libhal" = "xyes"; then
-       if test "x$PKG_CONFIG" != "x"; then
-               BUILD_WITH_LIBHAL_CFLAGS="`$PKG_CONFIG --cflags hal`"
-               BUILD_WITH_LIBHAL_LIBS="`$PKG_CONFIG --libs hal`"
-               AC_SUBST(BUILD_WITH_LIBHAL_CFLAGS)
-               AC_SUBST(BUILD_WITH_LIBHAL_LIBS)
-       fi
-fi
+with_libhal="no"
+PKG_CHECK_MODULES([HAL], [hal],
+  [
+    SAVE_LIBS="$LIBS"
+    LIBS="$HAL_LIBS $LIBS"
+    AC_CHECK_LIB([hal], [libhal_device_property_exists],
+      [
+        SAVE_CPPFLAGS="$CPPFLAGS"
+        CPPFLAGS="$HAL_CFLAGS $CPPFLAGS"
+        AC_CHECK_HEADERS([libhal.h],
+        [
+          with_libhal="yes"
+          BUILD_WITH_LIBHAL_CFLAGS="$HAL_CFLAGS"
+          BUILD_WITH_LIBHAL_LIBS="$HAL_LIBS"
+        ])
+        CPPFLAGS="$SAVE_CPPFLAGS"
+      ],
+      [ : ]
+    )
+    LIBS="$SAVE_LIBS"
+  ],
+  [ : ]
+)
+AC_SUBST(BUILD_WITH_LIBHAL_CFLAGS)
+AC_SUBST(BUILD_WITH_LIBHAL_LIBS)
+
+
+SAVE_LIBS="$LIBS"
+AC_CHECK_LIB([pthread],
+  [pthread_create],
+  [],
+  [AC_MSG_ERROR([Symbol 'pthread_create' not found in libpthread"])],
+  []
+)
+PTHREAD_LIBS="$LIBS"
+LIBS="$SAVE_LIBS"
+
+AC_CHECK_HEADERS([pthread.h],
+  [],
+  [AC_MSG_ERROR([pthread.h not found])]
+)
+AC_SUBST([PTHREAD_LIBS])
 
 m4_divert_once([HELP_WITH], [
 collectd additional packages:])
@@ -1859,6 +1987,36 @@ then
 fi
 if test "x$with_libcurl" = "xyes"
 then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_curl_cflags"
+       LDFLAGS="$LDFLAGS $with_curl_libs"
+       AC_CACHE_CHECK([for CURLINFO_APPCONNECT_TIME],
+               [c_cv_have_curlinfo_appconnect_time],
+               AC_LINK_IFELSE([AC_LANG_PROGRAM(
+[[
+#include <curl/curl.h>
+]],
+[[
+int val = CURLINFO_APPCONNECT_TIME;
+return val;
+]]
+                       )],
+                       [c_cv_have_curlinfo_appconnect_time="yes"],
+                       [c_cv_have_curlinfo_appconnect_time="no"]
+               )
+       )
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBCURL, test "x$with_libcurl" = "xyes")
+if test "x$c_cv_have_curlinfo_appconnect_time" = "xyes"
+then
+       AC_DEFINE(HAVE_CURLINFO_APPCONNECT_TIME, 1, [Define if curl.h defines CURLINFO_APPCONNECT_TIME.])
+fi
+
+if test "x$with_libcurl" = "xyes"
+then
        BUILD_WITH_LIBCURL_CFLAGS="$with_curl_cflags"
        BUILD_WITH_LIBCURL_LIBS="$with_curl_libs"
        AC_SUBST(BUILD_WITH_LIBCURL_CFLAGS)
@@ -1874,7 +2032,6 @@ then
                AC_DEFINE(HAVE_CURLOPT_TIMEOUT_MS, 1, [Define if libcurl supports CURLOPT_TIMEOUT_MS option.])
        fi
 fi
-AM_CONDITIONAL(BUILD_WITH_LIBCURL, test "x$with_libcurl" = "xyes")
 # }}}
 
 # --with-libdbi {{{
@@ -2111,12 +2268,6 @@ then
        AC_CHECK_LIB(gcrypt, gcry_md_hash_buffer,
                [with_libgcrypt="yes"],
                [with_libgcrypt="no (symbol gcry_md_hash_buffer not found)"])
-
-       if test "$with_libgcrypt" != "no"; then
-               m4_ifdef([AM_PATH_LIBGCRYPT],[AM_PATH_LIBGCRYPT(1:1.2.0,,with_libgcrypt="no (version 1.2.0+ required)")])
-               GCRYPT_CPPFLAGS="$LIBGCRYPT_CPPFLAGS $LIBGCRYPT_CFLAGS"
-               GCRYPT_LIBS="$LIBGCRYPT_LIBS"
-       fi
 fi
 
 CPPFLAGS="$SAVE_CPPFLAGS"
@@ -2134,6 +2285,146 @@ AC_SUBST(GCRYPT_LIBS)
 AM_CONDITIONAL(BUILD_WITH_LIBGCRYPT, test "x$with_libgcrypt" = "xyes")
 # }}}
 
+# --with-libgps {{{
+with_libgps_cflags=""
+with_libgps_ldflags=""
+AC_ARG_WITH(libgps, [AS_HELP_STRING([--with-libgps@<:@=PREFIX@:>@], [Path to libgps.])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libgps_cflags="-I$withval/include"
+               with_libgps_ldflags="-L$withval/lib"
+               with_libgps="yes"
+       else
+               with_libgps="$withval"
+       fi
+],
+[
+       with_libgps="yes"
+])
+if test "x$with_libgps" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS $with_libgps_cflags"
+
+       AC_CHECK_HEADERS(gps.h, [with_libgps="yes"], [with_libgps="no (gps.h not found)"])
+
+       CFLAGS="$SAVE_CFLAGS"
+fi
+if test "x$with_libgps" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CFLAGS="$CFLAGS $with_libgps_cflags"
+       LDFLAGS="$LDFLAGS $with_libgps_ldflags"
+
+       AC_CHECK_LIB(gps, gps_open, [with_libgps="yes"], [with_libgps="no (symbol gps_open not found)"])
+
+       CFLAGS="$SAVE_CFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libgps" = "xyes"
+then
+       BUILD_WITH_LIBGPS_CFLAGS="$with_libgps_cflags"
+       BUILD_WITH_LIBGPS_LDFLAGS="$with_libgps_ldflags"
+       BUILD_WITH_LIBGPS_LIBS="-lgps"
+       AC_SUBST(BUILD_WITH_LIBGPS_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBGPS_LDFLAGS)
+       AC_SUBST(BUILD_WITH_LIBGPS_LIBS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBGPS, test "x$with_libgps" = "xyes")
+# }}}
+
+# --with-libgrpc++ {{{
+with_libgrpcpp_cppflags=""
+with_libgrpcpp_ldflags=""
+AC_ARG_WITH([libgrpc++], [AS_HELP_STRING([--with-libgrpc++@<:@=PREFIX@:>@], [Path to libgrpc++.])],
+  [
+    with_grpcpp="$withval"
+    if test "x$withval" != "xno" && test "x$withval" != "xyes"
+    then
+      with_libgrpcpp_cppflags="-I$withval/include"
+      with_libgrpcpp_ldflags="-L$withval/lib"
+      with_libgrpcpp="yes"
+    fi
+    if test "x$withval" = "xno"
+    then
+      with_libgrpcpp="no (disabled on command line)"
+    fi
+  ],
+  [withval="yes"]
+)
+if test "x$withval" = "xyes"
+then
+PKG_CHECK_MODULES([GRPCPP], [grpc++],
+  [with_libgrpcpp="yes"],
+  [with_libgrpcpp="no (pkg-config could not find libgrpc++)"]
+)
+fi
+
+if test "x$withval" != "xno"
+then
+  AC_MSG_CHECKING([whether $CXX accepts -std=c++11])
+  if test_cxx_flags -std=c++11; then
+    AC_MSG_RESULT([yes])
+  else
+    AC_MSG_RESULT([no])
+    with_libgrpcpp="no (requires C++11 support)"
+  fi
+fi
+
+if test "x$with_libgrpcpp" = "xyes"
+then
+  AC_LANG_PUSH(C++)
+  SAVE_CPPFLAGS="$CPPFLAGS"
+  CPPFLAGS="-std=c++11 $with_libgrpcpp_cppflags $GRPCPP_CFLAGS $CPPFLAGS"
+  AC_CHECK_HEADERS([grpc++/grpc++.h], [],
+    [with_libgrpcpp="no (<grpc++/grpc++.h> not found)"]
+  )
+  CPPFLAGS="$SAVE_CPPFLAGS"
+  AC_LANG_POP(C++)
+fi
+if test "x$with_libgrpcpp" = "xyes"
+then
+  AC_LANG_PUSH(C++)
+  SAVE_CPPFLAGS="$CPPFLAGS"
+  SAVE_LDFLAGS="$LDFLAGS"
+  SAVE_LIBS="$LIBS"
+  CPPFLAGS="-std=c++11 $with_libgrpcpp_cppflags $GRPCPP_CFLAGS $CPPFLAGS"
+  LDFLAGS="$with_libgrpcpp_ldflags"
+  if test "x$GRPCPP_LIBS" = "x"
+  then
+    LIBS="-lgrpc++"
+  else
+    LIBS="$GRPCPP_LIBS"
+  fi
+  AC_LINK_IFELSE(
+    [AC_LANG_PROGRAM(
+      [[#include <grpc++/grpc++.h>]],
+      [[grpc::ServerBuilder sb;]]
+    )],
+    [
+      with_libgrpcpp="yes"
+      if test "x$GRPCPP_LIBS" = "x"
+      then
+        GRPCPP_LIBS="-lgrpc++"
+      fi
+    ],
+    [with_libgrpcpp="no (libgrpc++ not found)"]
+  )
+  CPPFLAGS="$SAVE_CPPFLAGS"
+  LDFLAGS="$SAVE_LDFLAGS"
+  LIBS="$SAVE_LIBS"
+  AC_LANG_POP(C++)
+fi
+BUILD_WITH_LIBGRPCPP_CPPFLAGS="-std=c++11 $with_libgrpcpp_cppflags $GRPCPP_CFLAGS"
+BUILD_WITH_LIBGRPCPP_LDFLAGS="$with_libgrpcpp_ldflags"
+BUILD_WITH_LIBGRPCPP_LIBS="$GRPCPP_LIBS"
+AC_SUBST([BUILD_WITH_LIBGRPCPP_CPPFLAGS])
+AC_SUBST([BUILD_WITH_LIBGRPCPP_LDFLAGS])
+AC_SUBST([BUILD_WITH_LIBGRPCPP_LIBS])
+# }}}
+
 # --with-libiptc {{{
 AC_ARG_WITH(libiptc, [AS_HELP_STRING([--with-libiptc@<:@=PREFIX@:>@], [Path to libiptc.])],
 [
@@ -2158,11 +2449,6 @@ AC_ARG_WITH(libiptc, [AS_HELP_STRING([--with-libiptc@<:@=PREFIX@:>@], [Path to l
        fi
 ])
 
-if test "x$with_libiptc" = "xpkgconfig" && test "x$PKG_CONFIG" = "x"
-then
-       with_libiptc="no (Don't have pkg-config)"
-fi
-
 if test "x$with_libiptc" = "xpkgconfig"
 then
        $PKG_CONFIG --exists 'libiptc' 2>/dev/null
@@ -2235,9 +2521,6 @@ if test "x$with_java_home" = "x"
 then
        with_java_home="/usr/lib/jvm"
 fi
-with_java_vmtype="client"
-with_java_cflags=""
-with_java_libs=""
 JAVAC="$JAVAC"
 JAR="$JAR"
 AC_ARG_WITH(java, [AS_HELP_STRING([--with-java@<:@=PREFIX@:>@], [Path to Java home.])],
@@ -2330,6 +2613,10 @@ if test "x$JAVA_LDFLAGS" != "x"
 then
        AC_MSG_NOTICE([Building with JAVA_LDFLAGS set to: $JAVA_LDFLAGS])
 fi
+if test "x$JAVA_LIBS" != "x"
+then
+       AC_MSG_NOTICE([Building with JAVA_LIBS set to: $JAVA_LIBS])
+fi
 if test "x$JAVAC" = "x"
 then
        with_javac_path="$PATH"
@@ -2370,9 +2657,11 @@ fi
 SAVE_CPPFLAGS="$CPPFLAGS"
 SAVE_CFLAGS="$CFLAGS"
 SAVE_LDFLAGS="$LDFLAGS"
+SAVE_LIBS="$LIBS"
 CPPFLAGS="$CPPFLAGS $JAVA_CPPFLAGS"
 CFLAGS="$CFLAGS $JAVA_CFLAGS"
 LDFLAGS="$LDFLAGS $JAVA_LDFLAGS"
+LIBS="$LIBS $JAVA_LIBS"
 
 if test "x$with_java" = "xyes"
 then
@@ -2382,8 +2671,8 @@ if test "x$with_java" = "xyes"
 then
        AC_CHECK_LIB(jvm, JNI_CreateJavaVM,
        [with_java="yes"],
-       [with_java="no (libjvm not found)"],
-       [$JAVA_LIBS])
+       [with_java="no (Symbol 'JNI_CreateJavaVM' not found)"],
+       [$JAVA_LIBS $PTHREAD_LIBS])
 fi
 if test "x$with_java" = "xyes"
 then
@@ -2394,6 +2683,7 @@ fi
 CPPFLAGS="$SAVE_CPPFLAGS"
 CFLAGS="$SAVE_CFLAGS"
 LDFLAGS="$SAVE_LDFLAGS"
+LIBS="$SAVE_LIBS"
 
 AC_SUBST(JAVA_CPPFLAGS)
 AC_SUBST(JAVA_CFLAGS)
@@ -2465,17 +2755,25 @@ with_liblvm2app_cppflags=""
 with_liblvm2app_ldflags=""
 AC_ARG_WITH(liblvm2app, [AS_HELP_STRING([--with-liblvm2app@<:@=PREFIX@:>@], [Path to liblvm2app.])],
 [
-        if test "x$withval" != "xno" && test "x$withval" != "xyes"
-        then
-                with_liblvm2app_cppflags="-I$withval/include"
-                with_liblvm2app_ldflags="-L$withval/lib"
-                with_liblvm2app="yes"
-        else
-                with_liblvm2app="$withval"
+       if test "x$withval" = "xno"
+       then
+               with_liblvm2app="no"
+       else
+               with_liblvm2app="yes"
+               if test "x$withval" != "xyes"
+               then
+                       with_liblvm2app_cppflags="-I$withval/include"
+                       with_liblvm2app_ldflags="-L$withval/lib"
+               fi
         fi
 ],
 [
-        with_liblvm2app="yes"
+       if test "x$ac_system" = "xLinux"
+       then
+               with_liblvm2app="yes"
+       else
+               with_liblvm2app="no (Linux only library)"
+       fi
 ])
 if test "x$with_liblvm2app" = "xyes"
 then
@@ -2588,13 +2886,6 @@ AC_ARG_WITH(libmodbus, [AS_HELP_STRING([--with-libmodbus@<:@=PREFIX@:>@], [Path
 # configure using pkg-config
 if test "x$with_libmodbus" = "xuse_pkgconfig"
 then
-       if test "x$PKG_CONFIG" = "x"
-       then
-               with_libmodbus="no (Don't have pkg-config)"
-       fi
-fi
-if test "x$with_libmodbus" = "xuse_pkgconfig"
-then
        AC_MSG_NOTICE([Checking for libmodbus using $PKG_CONFIG])
        $PKG_CONFIG --exists 'libmodbus' 2>/dev/null
        if test $? -ne 0
@@ -2718,6 +3009,55 @@ fi
 AM_CONDITIONAL(BUILD_WITH_LIBMONGOC, test "x$with_libmongoc" = "xyes")
 # }}}
 
+# --with-libmosquitto {{{
+with_libmosquitto_cppflags=""
+with_libmosquitto_ldflags=""
+AC_ARG_WITH(libmosquitto, [AS_HELP_STRING([--with-libmosquitto@<:@=PREFIX@:>@], [Path to libmosquitto.])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libmosquitto_cppflags="-I$withval/include"
+               with_libmosquitto_ldflags="-L$withval/lib"
+               with_libmosquitto="yes"
+       else
+               with_libmosquitto="$withval"
+       fi
+],
+[
+       with_libmosquitto="yes"
+])
+if test "x$with_libmosquitto" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libmosquitto_cppflags"
+
+       AC_CHECK_HEADERS(mosquitto.h, [with_libmosquitto="yes"], [with_libmosquitto="no (mosquitto.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libmosquitto" = "xyes"
+then
+       SAVE_LDFLAGS="$LDFLAGS"
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       LDFLAGS="$LDFLAGS $with_libmosquitto_ldflags"
+       CPPFLAGS="$CPPFLAGS $with_libmosquitto_cppflags"
+
+       AC_CHECK_LIB(mosquitto, mosquitto_connect, [with_libmosquitto="yes"], [with_libmosquitto="no (libmosquitto not found)"])
+
+       LDFLAGS="$SAVE_LDFLAGS"
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libmosquitto" = "xyes"
+then
+       BUILD_WITH_LIBMOSQUITTO_CPPFLAGS="$with_libmosquitto_cppflags"
+       BUILD_WITH_LIBMOSQUITTO_LDFLAGS="$with_libmosquitto_ldflags"
+       BUILD_WITH_LIBMOSQUITTO_LIBS="-lmosquitto"
+       AC_SUBST(BUILD_WITH_LIBMOSQUITTO_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBMOSQUITTO_LDFLAGS)
+       AC_SUBST(BUILD_WITH_LIBMOSQUITTO_LIBS)
+fi
+# }}}
+
 # --with-libmysql {{{
 with_mysql_config="mysql_config"
 with_mysql_cflags=""
@@ -2836,10 +3176,6 @@ AC_ARG_WITH(libmnl, [AS_HELP_STRING([--with-libmnl@<:@=PREFIX@:>@], [Path to lib
         with_libmnl="no (Linux only library)"
  fi
 ])
-if test "x$PKG_CONFIG" = "x"
-then
-       with_libmnl="no (Don't have pkg-config)"
-fi
 if test "x$with_libmnl" = "xyes"
 then
        if $PKG_CONFIG --exists libmnl 2>/dev/null; then
@@ -2970,7 +3306,7 @@ then
 
        if test "x$LIBNETAPP_LIBS" = "x"
        then
-               LIBNETAPP_LIBS="-lpthread -lxml -ladt -lssl -lm -lcrypto -lz"
+               LIBNETAPP_LIBS="$PTHREAD_LIBS -lxml -ladt -lssl -lm -lcrypto -lz"
        fi
        AC_MSG_NOTICE([netapp LIBS: $LIBNETAPP_LIBS])
 
@@ -3229,22 +3565,22 @@ then
 fi
 if test "x$with_oracle" = "xyes"
 then
-       BUILD_WITH_ORACLE_CFLAGS="$with_oracle_cppflags"
+       BUILD_WITH_ORACLE_CPPFLAGS="$with_oracle_cppflags"
        BUILD_WITH_ORACLE_LIBS="$with_oracle_libs"
-       AC_SUBST(BUILD_WITH_ORACLE_CFLAGS)
+       AC_SUBST(BUILD_WITH_ORACLE_CPPFLAGS)
        AC_SUBST(BUILD_WITH_ORACLE_LIBS)
 fi
 # }}}
 
 # --with-libowcapi {{{
 with_libowcapi_cppflags=""
-with_libowcapi_libs="-lowcapi"
+with_libowcapi_ldflags=""
 AC_ARG_WITH(libowcapi, [AS_HELP_STRING([--with-libowcapi@<:@=PREFIX@:>@], [Path to libowcapi.])],
 [
        if test "x$withval" != "xno" && test "x$withval" != "xyes"
        then
                with_libowcapi_cppflags="-I$withval/include"
-               with_libowcapi_libs="-L$withval/lib -lowcapi"
+               with_libowcapi_ldflags="-L$withval/lib"
                with_libowcapi="yes"
        else
                with_libowcapi="$withval"
@@ -3256,7 +3592,7 @@ AC_ARG_WITH(libowcapi, [AS_HELP_STRING([--with-libowcapi@<:@=PREFIX@:>@], [Path
 if test "x$with_libowcapi" = "xyes"
 then
        SAVE_CPPFLAGS="$CPPFLAGS"
-       CPPFLAGS="$with_libowcapi_cppflags"
+       CPPFLAGS="$CPPFLAGS $with_libowcapi_cppflags"
 
        AC_CHECK_HEADERS(owcapi.h, [with_libowcapi="yes"], [with_libowcapi="no (owcapi.h not found)"])
 
@@ -3266,7 +3602,7 @@ if test "x$with_libowcapi" = "xyes"
 then
        SAVE_LDFLAGS="$LDFLAGS"
        SAVE_CPPFLAGS="$CPPFLAGS"
-       LDFLAGS="$with_libowcapi_libs"
+       LDFLAGS="$LDFLAGS $with_libowcapi_ldflags"
        CPPFLAGS="$with_libowcapi_cppflags"
 
        AC_CHECK_LIB(owcapi, OW_get, [with_libowcapi="yes"], [with_libowcapi="no (libowcapi not found)"])
@@ -3277,8 +3613,10 @@ fi
 if test "x$with_libowcapi" = "xyes"
 then
        BUILD_WITH_LIBOWCAPI_CPPFLAGS="$with_libowcapi_cppflags"
-       BUILD_WITH_LIBOWCAPI_LIBS="$with_libowcapi_libs"
+       BUILD_WITH_LIBOWCAPI_LDFLAGS="$with_libowcapi_ldflags"
+       BUILD_WITH_LIBOWCAPI_LIBS="-lowcapi"
        AC_SUBST(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBOWCAPI_LDFLAGS)
        AC_SUBST(BUILD_WITH_LIBOWCAPI_LIBS)
 fi
 # }}}
@@ -3373,7 +3711,7 @@ then
   SAVE_CFLAGS="$CFLAGS"
   SAVE_LIBS="$LIBS"
 dnl ARCHFLAGS="" -> disable multi -arch on OSX (see Config_heavy.pl:fetch_string)
-  PERL_CFLAGS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ccopts`
+  PERL_CFLAGS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e perl_inc`
   PERL_LIBS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ldopts`
   CFLAGS="$CFLAGS $PERL_CFLAGS"
   LIBS="$LIBS $PERL_LIBS"
 AM_CONDITIONAL(BUILD_WITH_LIBPQ, test "x$with_libpq" = "xyes")
 # }}}
 
-# --with-libpthread {{{
-AC_ARG_WITH(libpthread, [AS_HELP_STRING([--with-libpthread=@<:@=PREFIX@:>@], [Path to libpthread.])],
-[      if test "x$withval" != "xno" \
-               && test "x$withval" != "xyes"
-       then
-               LDFLAGS="$LDFLAGS -L$withval/lib"
-               CPPFLAGS="$CPPFLAGS -I$withval/include"
-               with_libpthread="yes"
-       else
-               if test "x$withval" = "xno"
-               then
-                       with_libpthread="no (disabled)"
-               fi
-       fi
-], [with_libpthread="yes"])
-if test "x$with_libpthread" = "xyes"
+# --with-libprotobuf {{{
+with_libprotobuf_cppflags=""
+with_libprotobuf_ldflags=""
+AC_ARG_WITH([libprotobuf], [AS_HELP_STRING([--with-libprotobuf@<:@=PREFIX@:>@], [Path to libprotobuf.])],
+  [
+    if test "x$withval" != "xno" && test "x$withval" != "xyes"
+    then
+      with_libprotobuf_cppflags="-I$withval/include"
+      with_libprotobuf_ldflags="-L$withval/lib"
+      with_libprotobuf="yes"
+    fi
+    if test "x$withval" = "xno"
+    then
+      with_libprotobuf="no (disabled on command line)"
+    fi
+  ],
+  [withval="yes"]
+)
+if test "x$withval" = "xyes"
 then
-       AC_CHECK_LIB(pthread, pthread_create, [with_libpthread="yes"], [with_libpthread="no (libpthread not found)"], [])
+PKG_CHECK_MODULES([PROTOBUF], [protobuf],
+  [with_libprotobuf="yes"],
+  [with_libprotobuf="no (pkg-config could not find libprotobuf)"]
+)
 fi
 
-if test "x$with_libpthread" = "xyes"
+if test "x$withval" != "xno"
 then
-       AC_CHECK_HEADERS(pthread.h,, [with_libpthread="no (pthread.h not found)"])
-fi
-if test "x$with_libpthread" = "xyes"
-then
-       collect_pthread=1
-else
-       collect_pthread=0
+  SAVE_LDFLAGS="$LDFLAGS"
+  SAVE_LIBS="$LIBS"
+  LDFLAGS="$with_libprotobuf_ldflags"
+  LIBS="$PROTOBUF_LIBS $LIBS"
+  AC_LANG_PUSH([C++])
+  AC_CHECK_LIB([protobuf], [main],
+    [
+      SAVE_CPPFLAGS="$CPPFLAGS"
+      CPPFLAGS="$with_libprotobuf_cppflags $PROTOBUF_CFLAGS"
+      if test "x$PROTOBUF_LIBS" = "x"
+      then
+        PROTOBUF_LIBS="-lprotobuf"
+      fi
+      AC_CHECK_HEADERS([google/protobuf/util/time_util.h],
+        [with_libprotobuf="yes"],
+        [with_libprotobuf="no (<google/protobuf/util/time_util.h> not found)"]
+      )
+      CPPFLAGS="$SAVE_CPPFLAGS"
+    ],
+    [with_libprotobuf="no (libprotobuf not found)"]
+  )
+  AC_LANG_POP([C++])
+  LDFLAGS="$SAVE_LDFLAGS"
+  LIBS="$SAVE_LIBS"
 fi
-AC_DEFINE_UNQUOTED(HAVE_LIBPTHREAD, [$collect_pthread],
-       [Wether or not to use pthread (POSIX threads) library])
-AM_CONDITIONAL(BUILD_WITH_LIBPTHREAD, test "x$with_libpthread" = "xyes")
+BUILD_WITH_LIBPROTOBUF_CPPFLAGS="$with_libprotobuf_cppflags $PROTOBUF_CFLAGS"
+BUILD_WITH_LIBPROTOBUF_LDFLAGS="$with_libprotobuf_ldflags"
+BUILD_WITH_LIBPROTOBUF_LIBS="$PROTOBUF_LIBS"
+AC_SUBST([BUILD_WITH_LIBPROTOBUF_CPPFLAGS])
+AC_SUBST([BUILD_WITH_LIBPROTOBUF_LDFLAGS])
+AC_SUBST([BUILD_WITH_LIBPROTOBUF_LIBS])
 # }}}
 
-# --with-python {{{
-with_python_prog=""
-with_python_path="$PATH"
-AC_ARG_WITH(python, [AS_HELP_STRING([--with-python@<:@=PREFIX@:>@], [Path to the python interpreter.])],
-[
- if test "x$withval" = "xyes" || test "x$withval" = "xno"
- then
-        with_python="$withval"
- else if test -x "$withval"
- then
-        with_python_prog="$withval"
-        with_python_path="`dirname \"$withval\"`$PATH_SEPARATOR$with_python_path"
-        with_python="yes"
- else if test -d "$withval"
- then
-        with_python_path="$withval$PATH_SEPARATOR$with_python_path"
-        with_python="yes"
- else
-        AC_MSG_WARN([Argument not recognized: $withval])
- fi; fi; fi
-], [with_python="yes"])
-
-SAVE_PATH="$PATH"
-SAVE_CPPFLAGS="$CPPFLAGS"
-SAVE_LDFLAGS="$LDFLAGS"
-SAVE_LIBS="$LIBS"
-
-PATH="$with_python_path"
-
-if test "x$with_python" = "xyes" && test "x$with_python_prog" = "x"
-then
-       AC_MSG_CHECKING([for python])
-       with_python_prog="`which python 2>/dev/null`"
-       if test "x$with_python_prog" = "x"
-       then
-               AC_MSG_RESULT([not found])
-               with_python="no (interpreter not found)"
-       else
-               AC_MSG_RESULT([$with_python_prog])
-       fi
-fi
-
-if test "x$with_python" = "xyes"
-then
-       AC_MSG_CHECKING([for Python CPPFLAGS])
-       python_include_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_python_inc())" | "$with_python_prog" 2>&1`
-       python_config_status=$?
-
-       if test "$python_config_status" -ne 0 || test "x$python_include_path" = "x"
-       then
-               AC_MSG_RESULT([failed with status $python_config_status (output: $python_include_path)])
-               with_python="no"
-       else
-               AC_MSG_RESULT([$python_include_path])
-       fi
-fi
-
-if test "x$with_python" = "xyes"
+# --with-libprotobuf-c {{{
+with_libprotobuf_c_cppflags=""
+with_libprotobuf_c_ldflags=""
+AC_ARG_WITH([libprotobuf-c], [AS_HELP_STRING([--with-libprotobuf-c@<:@=PREFIX@:>@], [Path to libprotobuf-c.])],
+  [
+    if test "x$withval" != "xno" && test "x$withval" != "xyes"
+    then
+      with_libprotobuf_c_cppflags="-I$withval/include"
+      with_libprotobuf_c_ldflags="-L$withval/lib"
+      with_libprotobuf_c="yes"
+    fi
+    if test "x$withval" = "xno"
+    then
+      with_libprotobuf_c="no (disabled on command line)"
+    fi
+  ],
+  [withval="yes"]
+)
+if test "x$withval" = "xyes"
 then
-       CPPFLAGS="-I$python_include_path $CPPFLAGS"
-       AC_CHECK_HEADERS(Python.h,
-                        [with_python="yes"],
-                        [with_python="no ('Python.h' not found)"])
+PKG_CHECK_MODULES([PROTOBUF_C], [libprotobuf-c],
+  [with_libprotobuf_c="yes"],
+  [with_libprotobuf_c="no (pkg-config could not find libprotobuf-c)"]
+)
 fi
 
-if test "x$with_python" = "xyes"
+if test "x$withval" != "xno"
 then
-       AC_MSG_CHECKING([for Python LDFLAGS])
-       python_library_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"LIBDIR\").__getitem__(0))" | "$with_python_prog" 2>&1`
-       python_config_status=$?
-
-       if test "$python_config_status" -ne 0 || test "x$python_library_path" = "x"
-       then
-               AC_MSG_RESULT([failed with status $python_config_status (output: $python_library_path)])
-               with_python="no"
-       else
-               AC_MSG_RESULT([$python_library_path])
-       fi
+  SAVE_LDFLAGS="$LDFLAGS"
+  SAVE_LIBS="$LIBS"
+  LDFLAGS="$with_libprotobuf_c_ldflags"
+  LIBS="$PROTOBUF_C_LIBS $LIBS"
+  AC_CHECK_LIB([protobuf-c], [protobuf_c_message_pack],
+    [
+      SAVE_CPPFLAGS="$CPPFLAGS"
+      CPPFLAGS="$with_libprotobuf_c_cppflags $PROTOBUF_C_CFLAGS"
+      if test "x$PROTOBUF_C_LIBS" = "x"
+      then
+        PROTOBUF_C_LIBS="-lprotobuf-c"
+      fi
+      AC_CHECK_HEADERS([protobuf-c/protobuf-c.h google/protobuf-c/protobuf-c.h],
+        [
+          with_libprotobuf_c="yes"
+          break
+        ],
+        [with_libprotobuf_c="no (<protobuf-c.h> not found)"]
+      )
+      CPPFLAGS="$SAVE_CPPFLAGS"
+    ],
+    [with_libprotobuf_c="no (libprotobuf-c not found)"]
+  )
+  LDFLAGS="$SAVE_LDFLAGS"
+  LIBS="$SAVE_LIBS"
 fi
+BUILD_WITH_LIBPROTOBUF_C_CPPFLAGS="$with_libprotobuf_c_cppflags $PROTOBUF_C_CFLAGS"
+BUILD_WITH_LIBPROTOBUF_C_LDFLAGS="$with_libprotobuf_c_ldflags"
+BUILD_WITH_LIBPROTOBUF_C_LIBS="$PROTOBUF_C_LIBS"
+AC_SUBST([BUILD_WITH_LIBPROTOBUF_C_CPPFLAGS])
+AC_SUBST([BUILD_WITH_LIBPROTOBUF_C_LDFLAGS])
+AC_SUBST([BUILD_WITH_LIBPROTOBUF_C_LIBS])
+# }}}
 
-if test "x$with_python" = "xyes"
-then
-       AC_MSG_CHECKING([for Python LIBS])
-       python_library_flags=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"BLDLIBRARY\").__getitem__(0))" | "$with_python_prog" 2>&1`
-       python_config_status=$?
+# --with-libpython {{{
+AC_ARG_VAR([LIBPYTHON_CPPFLAGS], [Preprocessor flags for libpython])
+AC_ARG_VAR([LIBPYTHON_LDFLAGS], [Linker flags for libpython])
+AC_ARG_VAR([LIBPYTHON_LIBS], [Libraries for libpython])
 
-       if test "$python_config_status" -ne 0 || test "x$python_library_flags" = "x"
-       then
-               AC_MSG_RESULT([failed with status $python_config_status (output: $python_library_flags)])
-               with_python="no"
-       else
-               AC_MSG_RESULT([$python_library_flags])
-       fi
+AC_ARG_WITH([libpython],
+  [AS_HELP_STRING([--with-libpython],
+    [if we should build with libpython @<:@default=yes@:>@])
+  ],
+  [with_libpython="$withval"],
+  [with_libpython="check"]
+)
+if test "$with_libpython" != "no"; then
+  if test "$LIBPYTHON_CPPFLAGS" = "" && test "$LIBPYTHON_LDFLAGS" = ""; then
+    AC_ARG_VAR([PYTHON_CONFIG], [path to python-config])
+    AC_PATH_PROGS([PYTHON_CONFIG],
+      [python3-config python2-config python-config]
+    )
+    if test "$PYTHON_CONFIG" = ""; then
+      if test "$with_libpython" = "yes"; then
+        AC_MSG_ERROR([Unable to find python-config])
+      fi
+      with_libpython="no"
+    fi
+  fi
 fi
 
-if test "x$with_python" = "xyes"
-then
-       LDFLAGS="-L$python_library_path $LDFLAGS"
-       LIBS="$python_library_flags $LIBS"
-
-       AC_CHECK_FUNC(PyObject_CallFunction,
-                     [with_python="yes"],
-                     [with_python="no (Symbol 'PyObject_CallFunction' not found)"])
+if test "$PYTHON_CONFIG" != ""; then
+  LIBPYTHON_CPPFLAGS="`${PYTHON_CONFIG} --includes`"
+  if test $? -ne 0; then
+    with_libpython="no"
+  fi
+  LIBPYTHON_LDFLAGS="`${PYTHON_CONFIG} --ldflags`"
+  if test $? -ne 0; then
+    with_libpython="no"
+  fi
+  LIBPYTHON_LIBS="`${PYTHON_CONFIG} --libs`"
+  if test $? -ne 0; then
+    with_libpython="no"
+  fi
 fi
 
-PATH="$SAVE_PATH"
-CPPFLAGS="$SAVE_CPPFLAGS"
-LDFLAGS="$SAVE_LDFLAGS"
-LIBS="$SAVE_LIBS"
-
-if test "x$with_python" = "xyes"
-then
-       BUILD_WITH_PYTHON_CPPFLAGS="-I$python_include_path"
-       BUILD_WITH_PYTHON_LDFLAGS="-L$python_library_path"
-       BUILD_WITH_PYTHON_LIBS="$python_library_flags"
-       AC_SUBST(BUILD_WITH_PYTHON_CPPFLAGS)
-       AC_SUBST(BUILD_WITH_PYTHON_LDFLAGS)
-       AC_SUBST(BUILD_WITH_PYTHON_LIBS)
+if test "$with_libpython" != "xno"; then
+  SAVE_CPPFLAGS="$CPPFLAGS"
+  SAVE_LDFLAGS="$LDFLAGS"
+  SAVE_LIBS="$LIBS"
+  CPPFLAGS="$LIBPYTHON_CPPFLAGS $CPPFLAGS"
+  LDFLAGS="$LIBPYTHON_LDFLAGS $LDFLAGS"
+  LIBS="$LIBPYTHON_LIBS $LIBS"
+  AC_CHECK_HEADERS([Python.h],
+    [
+      AC_MSG_CHECKING([for libpython])
+      AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[#include <Python.h>]],
+          [[Py_Initialize();]])
+        ],
+        [with_libpython="yes"],
+        [with_libpython="no"]
+      )
+      AC_MSG_RESULT([$with_libpython])
+    ],
+    [with_libpython="no"]
+  )
+  CPPFLAGS="$SAVE_CPPFLAGS"
+  LDFLAGS="$SAVE_LDFLAGS"
+  LIBS="$SAVE_LIBS"
 fi
-# }}} --with-python
+# }}} --with-libpython
 
 # --with-librabbitmq {{{
 with_librabbitmq_cppflags=""
@@ -4114,11 +4488,6 @@ then
        SAVE_CPPFLAGS="$CPPFLAGS"
        CPPFLAGS="$CPPFLAGS $with_sensors_cflags"
 
-#      AC_CHECK_HEADERS(sensors/sensors.h,
-#      [
-#              AC_DEFINE(HAVE_SENSORS_SENSORS_H, 1, [Define to 1 if you have the <sensors/sensors.h> header file.])
-#      ],
-#      [with_libsensors="no (sensors/sensors.h not found)"])
        AC_CHECK_HEADERS(sensors/sensors.h, [], [with_libsensors="no (sensors/sensors.h not found)"])
 
        CPPFLAGS="$SAVE_CPPFLAGS"
@@ -4149,74 +4518,13 @@ fi
 AM_CONDITIONAL(BUILD_WITH_LM_SENSORS, test "x$with_libsensors" = "xyes")
 # }}}
 
-# --with-libsigrok {{{
-with_libsigrok_cflags=""
-with_libsigrok_ldflags=""
-AC_ARG_WITH(libsigrok, [AS_HELP_STRING([--with-libsigrok@<:@=PREFIX@:>@], [Path to libsigrok.])],
-[
-       if test "x$withval" = "xno"
-       then
-               with_libsigrok="no"
-       else
-               with_libsigrok="yes"
-               if test "x$withval" != "xyes"
-               then
-                       with_libsigrok_cflags="-I$withval/include"
-                       with_libsigrok_ldflags="-L$withval/lib"
-               fi
-       fi
-],[with_libsigrok="yes"])
-
-# libsigrok has a glib dependency
-if test "x$with_libsigrok" = "xyes"
-then
-m4_ifdef([AM_PATH_GLIB_2_0],
-       [
-        AM_PATH_GLIB_2_0([2.28.0],
-               [with_libsigrok_cflags="$with_libsigrok_cflags $GLIB_CFLAGS"; with_libsigrok_ldflags="$with_libsigrok_ldflags $GLIB_LIBS"])
-       ],
-       [
-        with_libsigrok="no (glib not available)"
-       ]
+# libsigrok {{{
+AC_SUBST([LIBSIGROK_CFLAGS])
+AC_SUBST([LIBSIGROK_LIBS])
+PKG_CHECK_MODULES([LIBSIGROK], [libsigrok < 0.4],
+  [with_libsigrok="yes"],
+  [with_libsigrok="no (pkg-config could not find libsigrok)"]
 )
-fi
-
-# libsigrok headers
-if test "x$with_libsigrok" = "xyes"
-then
-       SAVE_CPPFLAGS="$CPPFLAGS"
-       CPPFLAGS="$CPPFLAGS $with_libsigrok_cflags"
-
-       AC_CHECK_HEADERS(libsigrok/libsigrok.h, [], [with_libsigrok="no (libsigrok/libsigrok.h not found)"])
-
-       CPPFLAGS="$SAVE_CPPFLAGS"
-fi
-
-# libsigrok library
-if test "x$with_libsigrok" = "xyes"
-then
-       SAVE_CPPFLAGS="$CPPFLAGS"
-       SAVE_LDFLAGS="$LDFLAGS"
-       CPPFLAGS="$CPPFLAGS $with_libsigrok_cflags"
-       LDFLAGS="$LDFLAGS $with_libsigrok_ldflags"
-
-       AC_CHECK_LIB(sigrok, sr_init,
-       [
-               AC_DEFINE(HAVE_LIBSIGROK, 1, [Define to 1 if you have the sigrok library (-lsigrok).])
-       ],
-       [with_libsigrok="no (libsigrok not found)"])
-
-       CPPFLAGS="$SAVE_CPPFLAGS"
-       LDFLAGS="$SAVE_LDFLAGS"
-fi
-if test "x$with_libsigrok" = "xyes"
-then
-       BUILD_WITH_LIBSIGROK_CFLAGS="$with_libsigrok_cflags"
-       BUILD_WITH_LIBSIGROK_LDFLAGS="$with_libsigrok_ldflags"
-       AC_SUBST(BUILD_WITH_LIBSIGROK_CFLAGS)
-       AC_SUBST(BUILD_WITH_LIBSIGROK_LDFLAGS)
-fi
-AM_CONDITIONAL(BUILD_WITH_LIBSIGROK, test "x$with_libsigrok" = "xyes")
 # }}}
 
 # --with-libstatgrab {{{
@@ -4244,23 +4552,16 @@ AC_ARG_WITH(libstatgrab, [AS_HELP_STRING([--with-libstatgrab@<:@=PREFIX@:>@], [P
 if test "x$with_libstatgrab" = "xyes" \
   && test "x$with_libstatgrab_pkg_config" = "xyes"
 then
-  if test "x$PKG_CONFIG" != "x"
+  AC_MSG_CHECKING([pkg-config for libstatgrab])
+  temp_result="found"
+  $PKG_CONFIG --exists libstatgrab 2>/dev/null
+  if test "$?" != "0"
   then
-    AC_MSG_CHECKING([pkg-config for libstatgrab])
-    temp_result="found"
-    $PKG_CONFIG --exists libstatgrab 2>/dev/null
-    if test "$?" != "0"
-    then
-      with_libstatgrab_pkg_config="no"
-      with_libstatgrab="no (pkg-config doesn't know libstatgrab)"
-      temp_result="not found"
-    fi
-    AC_MSG_RESULT([$temp_result])
-  else
-    AC_MSG_NOTICE([pkg-config not available, trying to guess flags for the statgrab library.])
     with_libstatgrab_pkg_config="no"
-    with_libstatgrab_ldflags="$with_libstatgrab_ldflags -lstatgrab"
+    with_libstatgrab="no (pkg-config doesn't know libstatgrab)"
+    temp_result="not found"
   fi
+  AC_MSG_RESULT([$temp_result])
 fi
 
 if test "x$with_libstatgrab" = "xyes" \
@@ -4326,6 +4627,7 @@ fi
 if test "x$with_libstatgrab" = "xyes"
 then
   SAVE_CFLAGS="$CFLAGS"
+  SAVE_LDFLAGS="$LDFLAGS"
   SAVE_LIBS="$LIBS"
 
   CFLAGS="$CFLAGS $with_libstatgrab_cflags"
@@ -4558,13 +4860,6 @@ fi
 # configure using pkg-config
 if test "x$with_libupsclient" = "xuse_pkgconfig"
 then
-       if test "x$PKG_CONFIG" = "x"
-       then
-               with_libupsclient="no (Don't have pkg-config)"
-       fi
-fi
-if test "x$with_libupsclient" = "xuse_pkgconfig"
-then
        AC_MSG_NOTICE([Checking for libupsclient using $PKG_CONFIG])
        $PKG_CONFIG --exists 'libupsclient' 2>/dev/null
        if test $? -ne 0
@@ -4637,6 +4932,51 @@ then
 fi
 # }}}
 
+# --with-libxenctrl {{{
+with_libxenctrl_cppflags=""
+with_libxenctrl_ldflags=""
+AC_ARG_WITH(libxenctrl, [AS_HELP_STRING([--with-libxenctrl@<:@=PREFIX@:>@], [Path to libxenctrl.])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libxenctrl_cppflags="-I$withval/include"
+               with_libxenctrl_ldflags="-L$withval/lib"
+               with_libxenctrl="yes"
+       else
+               with_libxenctrl="$withval"
+       fi
+],
+[
+       with_libxenctrl="yes"
+])
+if test "x$with_libxenctrl" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libxenctrl_cppflags"
+
+       AC_CHECK_HEADERS(xenctrl.h, [with_libxenctrl="yes"], [with_libxenctrl="no (xenctrl.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libxenctrl" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libxenctrl_cppflags"
+       LDFLAGS="$LDFLAGS $with_libxenctrl_ldflags"
+
+       #Xen versions older than 3.4 has no xc_getcpuinfo()
+       AC_CHECK_LIB(xenctrl, xc_getcpuinfo, [with_libxenctrl="yes"], [with_libxenctrl="no (symbol 'xc_getcpuinfo' not found)"], [])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+       LIBXENCTL_CPPFLAGS="$with_libxenctl_cppflags"
+       LIBXENCTL_LDFLAGS="$with_libxenctl_ldflags"
+       AC_SUBST(LIBXENCTL_CPPFLAGS)
+       AC_SUBST(LIBXENCTL_LDFLAGS)
+fi
+# }}}
+
 # --with-libxmms {{{
 with_xmms_config="xmms-config"
 with_xmms_cflags=""
@@ -4776,7 +5116,7 @@ AC_ARG_WITH(mic,[AS_HELP_STRING([--with-mic@<:@=PREFIX@:>@], [Path to Intel MIC
                AC_MSG_NOTICE([Not checking for Intel Mic: Manually configured])
                with_mic_cflags="-I$withval/include"
                with_mic_ldpath="-L$withval/lib/Linux"
-               with_mic_libs="-lMicAccessSDK -lscif -lpthread"
+               with_mic_libs="$PTHREAD_LIBS -lMicAccessSDK -lscif"
                with_mic="yes"
        fi; fi; fi
 ],
@@ -4798,8 +5138,8 @@ then
 
        AC_CHECK_LIB(MicAccessSDK, MicInitAPI,
                        [with_mic_ldpath="$with_mic_ldpath"
-                       with_mic_libs="-lMicAccessSDK -lscif -lpthread"],
-                       [with_mic="no (symbol MicInitAPI not found)"],[-lscif -lpthread])
+                       with_mic_libs="$PTHREAD_LIBS -lMicAccessSDK -lscif"],
+                       [with_mic="no (symbol MicInitAPI not found)"],[$PTHREAD_LIBS -lscif])
 
        CPPFLAGS="$SAVE_CPPFLAGS"
        LDFLAGS="$SAVE_LDFLAGS"
@@ -4841,13 +5181,6 @@ AC_ARG_WITH(libvarnish, [AS_HELP_STRING([--with-libvarnish@<:@=PREFIX@:>@], [Pat
 # configure using pkg-config
 if test "x$with_libvarnish" = "xuse_pkgconfig"
 then
-       if test "x$PKG_CONFIG" = "x"
-       then
-               with_libvarnish="no (Don't have pkg-config)"
-       fi
-fi
-if test "x$with_libvarnish" = "xuse_pkgconfig"
-then
        AC_MSG_NOTICE([Checking for varnishapi using $PKG_CONFIG])
        $PKG_CONFIG --exists 'varnishapi' 2>/dev/null
        if test $? -ne 0
@@ -4907,23 +5240,20 @@ with_libxml2_ldflags=""
 with_libvirt="no (pkg-config isn't available)"
 with_libvirt_cflags=""
 with_libvirt_ldflags=""
-if test "x$PKG_CONFIG" != "x"
+$PKG_CONFIG --exists 'libxml-2.0' 2>/dev/null
+if test "$?" = "0"
 then
-       $PKG_CONFIG --exists 'libxml-2.0' 2>/dev/null
-       if test "$?" = "0"
-       then
-               with_libxml2="yes"
-       else
-               with_libxml2="no (pkg-config doesn't know libxml-2.0)"
-       fi
+       with_libxml2="yes"
+else
+       with_libxml2="no (pkg-config doesn't know libxml-2.0)"
+fi
 
-       $PKG_CONFIG --exists libvirt 2>/dev/null
-       if test "$?" = "0"
-       then
-               with_libvirt="yes"
-       else
-               with_libvirt="no (pkg-config doesn't know libvirt)"
-       fi
+$PKG_CONFIG --exists libvirt 2>/dev/null
+if test "$?" = "0"
+then
+       with_libvirt="yes"
+else
+       with_libvirt="no (pkg-config doesn't know libvirt)"
 fi
 if test "x$with_libxml2" = "xyes"
 then
@@ -5022,17 +5352,6 @@ with_libopenipmipthread="yes"
 with_libopenipmipthread_cflags=""
 with_libopenipmipthread_libs=""
 
-AC_MSG_CHECKING([for pkg-config])
-temp_result="no"
-if test "x$PKG_CONFIG" = "x"
-then
-       with_libopenipmipthread="no"
-       temp_result="no"
-else
-       temp_result="$PKG_CONFIG"
-fi
-AC_MSG_RESULT([$temp_result])
-
 if test "x$with_libopenipmipthread" = "xyes"
 then
        AC_MSG_CHECKING([for libOpenIPMIpthread])
@@ -5156,11 +5475,12 @@ AM_CONDITIONAL(BUILD_WITH_LIBATASMART, test "x$with_libatasmart" = "xyes")
 
 PKG_CHECK_MODULES([LIBNOTIFY], [libnotify],
                [with_libnotify="yes"],
-               [if test "x$LIBNOTIFY_PKG_ERRORS" = "x"; then
-                        with_libnotify="no"
-                else
-                        with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"
-                fi])
+               [with_libnotify="no (pkg-config doesn't know libnotify)"]
+)
+
+PKG_CHECK_MODULES([LIBRIEMANN_CLIENT], [riemann-client >= 1.8.0],
+ [with_libriemann_client="yes"],
+ [with_libriemann_client="no (pkg-config doesn't know libriemann-client)"])
 
 # Check for enabled/disabled features
 #
@@ -5253,7 +5573,7 @@ AC_DEFUN(
             then
                     enable_plugin="yes"
             else
-                    enable_plugin="no"
+                    enable_plugin="$2"
             fi
         else
             enable_plugin="$enable_all_plugins"
@@ -5270,7 +5590,7 @@ AC_DEFUN(
                    fi
            else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
                    dependency_error="yes"
-                   enable_plugin="no (dependency error)"
+                   enable_plugin="$2 (dependency error)"
            fi
     fi
     AM_CONDITIONAL([BUILD_PLUGIN_]my_toupper([$1]), test "x$enable_plugin" = "xyes")
@@ -5284,6 +5604,7 @@ collectd features:])
 AC_COLLECTD([debug],     [enable],  [feature], [debugging])
 AC_COLLECTD([daemon],    [disable], [feature], [daemon mode])
 AC_COLLECTD([getifaddrs],[enable],  [feature], [getifaddrs under Linux])
+AC_COLLECTD([werror],    [disable], [feature], [building with -Werror])
 
 dependency_warning="no"
 dependency_error="no"
@@ -5298,6 +5619,7 @@ plugin_conntrack="no"
 plugin_contextswitch="no"
 plugin_cpu="no"
 plugin_cpufreq="no"
+plugin_cpusleep="no"
 plugin_curl_json="no"
 plugin_curl_xml="no"
 plugin_df="no"
@@ -5307,6 +5629,8 @@ plugin_entropy="no"
 plugin_ethstat="no"
 plugin_fhcount="no"
 plugin_fscache="no"
+plugin_gps="no"
+plugin_grpc="no"
 plugin_interface="no"
 plugin_ipmi="no"
 plugin_ipvs="no"
@@ -5318,8 +5642,10 @@ plugin_multimeter="no"
 plugin_nfs="no"
 plugin_numa="no"
 plugin_perl="no"
+plugin_pinba="no"
 plugin_processes="no"
 plugin_protocols="no"
+plugin_python="no"
 plugin_serial="no"
 plugin_smart="no"
 plugin_swap="no"
@@ -5334,16 +5660,18 @@ plugin_virt="no"
 plugin_vmem="no"
 plugin_vserver="no"
 plugin_wireless="no"
+plugin_xencpu="no"
 plugin_zfs_arc="no"
+plugin_zone="no"
 plugin_zookeeper="no"
 
 # Linux
 if test "x$ac_system" = "xLinux"
 then
        plugin_battery="yes"
+       plugin_cgroups="yes"
        plugin_conntrack="yes"
        plugin_contextswitch="yes"
-       plugin_cgroups="yes"
        plugin_cpu="yes"
        plugin_cpufreq="yes"
        plugin_disk="yes"
@@ -5379,6 +5707,11 @@ then
        then
                plugin_turbostat="yes"
        fi
+       
+       if test "x$c_cv_have_clock_boottime_monotonic" = "xyes"
+       then
+               plugin_cpusleep="yes"
+       fi
 fi
 
 if test "x$ac_system" = "xOpenBSD"
@@ -5386,6 +5719,14 @@ then
        plugin_tcpconns="yes"
 fi
 
+if test "x$ac_system" = "xNetBSD"
+then
+       plugin_disk="yes"
+       plugin_entropy="yes"
+       plugin_irq="yes"
+       plugin_processes="yes"
+fi
+
 # Mac OS X devices
 if test "x$with_libiokit" = "xyes"
 then
@@ -5397,27 +5738,28 @@ fi
 
 if test "x$ac_system" = "xAIX"
 then
-       plugin_tcpconns="yes"
        plugin_ipc="yes"
+       plugin_tcpconns="yes"
 fi
 
 # FreeBSD
 
 if test "x$ac_system" = "xFreeBSD"
 then
+       plugin_disk="yes"
        plugin_zfs_arc="yes"
 fi
 
 
 if test "x$with_perfstat" = "xyes"
 then
-       plugin_cpu="yes"
        plugin_contextswitch="yes"
+       plugin_cpu="yes"
        plugin_disk="yes"
-       plugin_memory="yes"
-       plugin_swap="yes"
        plugin_interface="yes"
        plugin_load="yes"
+       plugin_memory="yes"
+       plugin_swap="yes"
        plugin_uptime="yes"
 fi
 
@@ -5433,6 +5775,7 @@ then
        plugin_processes="yes"
        plugin_uptime="yes"
        plugin_zfs_arc="yes"
+       plugin_zone="yes"
 fi
 
 if test "x$with_devinfo$with_kstat" = "xyesyes"
@@ -5445,7 +5788,6 @@ then
 fi
 
 # libi2c-dev
-with_libi2c="no"
 if test "x$ac_system" = "xLinux"
 then
 AC_CHECK_DECL(i2c_smbus_read_i2c_block_data,
@@ -5453,6 +5795,8 @@ AC_CHECK_DECL(i2c_smbus_read_i2c_block_data,
        [with_libi2c="no (symbol i2c_smbus_read_i2c_block_data not found - have you installed libi2c-dev ?)"],
        [[#include <stdlib.h>
        #include <linux/i2c-dev.h>]])
+else
+       with_libi2c="no (Linux only)"
 fi
 
 if test "x$with_libi2c" = "xyes"
@@ -5569,11 +5913,21 @@ then
        plugin_ethstat="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"
+fi
+
 if test "x$have_getifaddrs" = "xyes"
 then
        plugin_interface="yes"
 fi
 
+if test "x$with_libgps" = "xyes"
+then
+       plugin_gps="yes"
+fi
+
 if test "x$have_getloadavg" = "xyes"
 then
        plugin_load="yes"
@@ -5589,6 +5943,11 @@ then
        plugin_perl="yes"
 fi
 
+if test "x$have_protoc_c" = "xyes" && test "x$with_libprotobuf_c" = "xyes"
+then
+       plugin_pinba="yes"
+fi
+
 # Mac OS X memory interface
 if test "x$have_host_statistics" = "xyes"
 then
@@ -5619,6 +5978,11 @@ then
        plugin_processes="yes"
 fi
 
+if test "x$with_libpython" != "xno"
+then
+       plugin_python="yes"
+fi
+
 if test "x$with_libatasmart" = "xyes" && test "x$with_libudev" = "xyes"
 then
        plugin_smart="yes"
@@ -5634,6 +5998,11 @@ then
        plugin_swap="yes"
 fi
 
+if test "x$have_swapctl" = "xyes" && test "x$c_cv_have_swapctl_three_args" = "xyes"
+then
+       plugin_swap="yes"
+fi
+
 if test "x$with_kvm_openfiles$with_kvm_nlist" = "xyesyes"
 then
        plugin_tcpconns="yes"
@@ -5653,6 +6022,10 @@ then
        plugin_virt="yes"
 fi
 
+if test "x$with_libxenctrl" = "xyes"
+then
+  plugin_xencpu="yes"
+fi
 
 m4_divert_once([HELP_ENABLE], [
 collectd plugins:])
@@ -5674,141 +6047,149 @@ AC_ARG_ENABLE([all-plugins],
 
 m4_divert_once([HELP_ENABLE], [])
 
-AC_PLUGIN([aggregation], [yes],                [Aggregation plugin])
-AC_PLUGIN([amqp],        [$with_librabbitmq],  [AMQP output plugin])
-AC_PLUGIN([apache],      [$with_libcurl],      [Apache httpd statistics])
-AC_PLUGIN([apcups],      [yes],                [Statistics of UPSes by APC])
-AC_PLUGIN([apple_sensors], [$with_libiokit],   [Apple's hardware sensors])
-AC_PLUGIN([aquaero],     [$with_libaquaero5],  [Aquaero's hardware sensors])
-AC_PLUGIN([ascent],      [$plugin_ascent],     [AscentEmu player statistics])
-AC_PLUGIN([barometer],   [$plugin_barometer],  [Barometer sensor on I2C])
-AC_PLUGIN([battery],     [$plugin_battery],    [Battery statistics])
-AC_PLUGIN([bind],        [$plugin_bind],       [ISC Bind nameserver statistics])
-AC_PLUGIN([ceph],        [$plugin_ceph],       [Ceph daemon statistics])
-AC_PLUGIN([conntrack],   [$plugin_conntrack],  [nf_conntrack statistics])
-AC_PLUGIN([contextswitch], [$plugin_contextswitch], [context switch statistics])
-AC_PLUGIN([cpufreq],     [$plugin_cpufreq],    [CPU frequency statistics])
-AC_PLUGIN([cpu],         [$plugin_cpu],        [CPU usage statistics])
-AC_PLUGIN([csv],         [yes],                [CSV output plugin])
-AC_PLUGIN([curl],        [$with_libcurl],      [CURL generic web statistics])
-AC_PLUGIN([curl_json],   [$plugin_curl_json],    [CouchDB statistics])
-AC_PLUGIN([curl_xml],   [$plugin_curl_xml],    [CURL generic xml statistics])
-AC_PLUGIN([cgroups],     [$plugin_cgroups],    [CGroups CPU usage accounting])
-AC_PLUGIN([dbi],         [$with_libdbi],       [General database statistics])
-AC_PLUGIN([df],          [$plugin_df],         [Filesystem usage statistics])
-AC_PLUGIN([disk],        [$plugin_disk],       [Disk usage statistics])
-AC_PLUGIN([drbd],        [$plugin_drbd],       [DRBD statistics])
-AC_PLUGIN([dns],         [$with_libpcap],      [DNS traffic analysis])
-AC_PLUGIN([email],       [yes],                [EMail statistics])
-AC_PLUGIN([entropy],     [$plugin_entropy],    [Entropy statistics])
-AC_PLUGIN([ethstat],     [$plugin_ethstat],    [Stats from NIC driver])
-AC_PLUGIN([exec],        [yes],                [Execution of external programs])
-AC_PLUGIN([fhcount],     [$plugin_fhcount],    [File handles statistics])
-AC_PLUGIN([filecount],   [yes],                [Count files in directories])
-AC_PLUGIN([fscache],     [$plugin_fscache],    [fscache statistics])
-AC_PLUGIN([gmond],       [$with_libganglia],   [Ganglia plugin])
-AC_PLUGIN([hddtemp],     [yes],                [Query hddtempd])
-AC_PLUGIN([interface],   [$plugin_interface],  [Interface traffic statistics])
-AC_PLUGIN([ipc],         [$plugin_ipc],        [IPC statistics])
-AC_PLUGIN([ipmi],        [$plugin_ipmi],       [IPMI sensor statistics])
-AC_PLUGIN([iptables],    [$with_libiptc],      [IPTables rule counters])
-AC_PLUGIN([ipvs],        [$plugin_ipvs],       [IPVS connection statistics])
-AC_PLUGIN([irq],         [$plugin_irq],        [IRQ statistics])
-AC_PLUGIN([java],        [$with_java],         [Embed the Java Virtual Machine])
-AC_PLUGIN([load],        [$plugin_load],       [System load])
-AC_PLUGIN([logfile],     [yes],                [File logging plugin])
-AC_PLUGIN([log_logstash], [$plugin_log_logstash], [Logstash json_event compatible logging])
-AC_PLUGIN([lpar],        [$with_perfstat],     [AIX logical partitions statistics])
-AC_PLUGIN([lvm],         [$with_liblvm2app],   [LVM statistics])
-AC_PLUGIN([madwifi],     [$have_linux_wireless_h], [Madwifi wireless statistics])
-AC_PLUGIN([match_empty_counter], [yes],        [The empty counter match])
-AC_PLUGIN([match_hashed], [yes],               [The hashed match])
-AC_PLUGIN([match_regex], [yes],                [The regex match])
-AC_PLUGIN([match_timediff], [yes],             [The timediff match])
-AC_PLUGIN([match_value], [yes],                [The value match])
-AC_PLUGIN([mbmon],       [yes],                [Query mbmond])
-AC_PLUGIN([md],          [$have_linux_raid_md_u_h], [md (Linux software RAID) devices])
-AC_PLUGIN([memcachec],   [$with_libmemcached], [memcachec statistics])
-AC_PLUGIN([memcached],   [yes],                [memcached statistics])
-AC_PLUGIN([memory],      [$plugin_memory],     [Memory usage])
-AC_PLUGIN([mic],         [$with_mic],          [Intel Many Integrated Core stats])
-AC_PLUGIN([modbus],      [$with_libmodbus],    [Modbus plugin])
-AC_PLUGIN([multimeter],  [$plugin_multimeter], [Read multimeter values])
-AC_PLUGIN([mysql],       [$with_libmysql],     [MySQL statistics])
-AC_PLUGIN([netapp],      [$with_libnetapp],    [NetApp plugin])
-AC_PLUGIN([netlink],     [$with_libmnl],       [Enhanced Linux network statistics])
-AC_PLUGIN([network],     [yes],                [Network communication plugin])
-AC_PLUGIN([nfs],         [$plugin_nfs],        [NFS statistics])
-AC_PLUGIN([nginx],       [$with_libcurl],      [nginx statistics])
-AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications])
-AC_PLUGIN([notify_email], [$with_libesmtp],    [Email notifier])
-AC_PLUGIN([ntpd],        [yes],                [NTPd statistics])
-AC_PLUGIN([numa],        [$plugin_numa],       [NUMA virtual memory statistics])
-AC_PLUGIN([nut],         [$with_libupsclient], [Network UPS tools statistics])
-AC_PLUGIN([olsrd],       [yes],                [olsrd statistics])
-AC_PLUGIN([onewire],     [$with_libowcapi],    [OneWire sensor statistics])
-AC_PLUGIN([openldap],    [$with_libldap],      [OpenLDAP statistics])
-AC_PLUGIN([openvpn],     [yes],                [OpenVPN client statistics])
-AC_PLUGIN([oracle],      [$with_oracle],       [Oracle plugin])
-AC_PLUGIN([perl],        [$plugin_perl],       [Embed a Perl interpreter])
-AC_PLUGIN([pf],          [$have_net_pfvar_h],  [BSD packet filter (PF) statistics])
+AC_PLUGIN([aggregation],         [yes],                     [Aggregation plugin])
+AC_PLUGIN([amqp],                [$with_librabbitmq],       [AMQP output plugin])
+AC_PLUGIN([apache],              [$with_libcurl],           [Apache httpd statistics])
+AC_PLUGIN([apcups],              [yes],                     [Statistics of UPSes by APC])
+AC_PLUGIN([apple_sensors],       [$with_libiokit],          [Apple hardware sensors])
+AC_PLUGIN([aquaero],             [$with_libaquaero5],       [Aquaero hardware sensors])
+AC_PLUGIN([ascent],              [$plugin_ascent],          [AscentEmu player statistics])
+AC_PLUGIN([barometer],           [$plugin_barometer],       [Barometer sensor on I2C])
+AC_PLUGIN([battery],             [$plugin_battery],         [Battery statistics])
+AC_PLUGIN([bind],                [$plugin_bind],            [ISC Bind nameserver statistics])
+AC_PLUGIN([ceph],                [$plugin_ceph],            [Ceph daemon statistics])
+AC_PLUGIN([cgroups],             [$plugin_cgroups],         [CGroups CPU usage accounting])
+AC_PLUGIN([chrony],              [yes],                     [Chrony statistics])
+AC_PLUGIN([conntrack],           [$plugin_conntrack],       [nf_conntrack statistics])
+AC_PLUGIN([contextswitch],       [$plugin_contextswitch],   [context switch statistics])
+AC_PLUGIN([cpu],                 [$plugin_cpu],             [CPU usage statistics])
+AC_PLUGIN([cpufreq],             [$plugin_cpufreq],         [CPU frequency statistics])
+AC_PLUGIN([cpusleep],            [$plugin_cpusleep],        [CPU sleep statistics])
+AC_PLUGIN([csv],                 [yes],                     [CSV output plugin])
+AC_PLUGIN([curl],                [$with_libcurl],           [CURL generic web statistics])
+AC_PLUGIN([curl_json],           [$plugin_curl_json],       [CouchDB statistics])
+AC_PLUGIN([curl_xml],            [$plugin_curl_xml],        [CURL generic xml statistics])
+AC_PLUGIN([dbi],                 [$with_libdbi],            [General database statistics])
+AC_PLUGIN([df],                  [$plugin_df],              [Filesystem usage statistics])
+AC_PLUGIN([disk],                [$plugin_disk],            [Disk usage statistics])
+AC_PLUGIN([dns],                 [$with_libpcap],           [DNS traffic analysis])
+AC_PLUGIN([drbd],                [$plugin_drbd],            [DRBD statistics])
+AC_PLUGIN([email],               [yes],                     [EMail statistics])
+AC_PLUGIN([entropy],             [$plugin_entropy],         [Entropy statistics])
+AC_PLUGIN([ethstat],             [$plugin_ethstat],         [Stats from NIC driver])
+AC_PLUGIN([exec],                [yes],                     [Execution of external programs])
+AC_PLUGIN([fhcount],             [$plugin_fhcount],         [File handles statistics])
+AC_PLUGIN([filecount],           [yes],                     [Count files in directories])
+AC_PLUGIN([fscache],             [$plugin_fscache],         [fscache statistics])
+AC_PLUGIN([gmond],               [$with_libganglia],        [Ganglia plugin])
+AC_PLUGIN([gps],                 [$plugin_gps],             [GPS plugin])
+AC_PLUGIN([grpc],                [$plugin_grpc],            [gRPC plugin])
+AC_PLUGIN([hddtemp],             [yes],                     [Query hddtempd])
+AC_PLUGIN([interface],           [$plugin_interface],       [Interface traffic statistics])
+AC_PLUGIN([ipc],                 [$plugin_ipc],             [IPC statistics])
+AC_PLUGIN([ipmi],                [$plugin_ipmi],            [IPMI sensor statistics])
+AC_PLUGIN([iptables],            [$with_libiptc],           [IPTables rule counters])
+AC_PLUGIN([ipvs],                [$plugin_ipvs],            [IPVS connection statistics])
+AC_PLUGIN([irq],                 [$plugin_irq],             [IRQ statistics])
+AC_PLUGIN([java],                [$with_java],              [Embed the Java Virtual Machine])
+AC_PLUGIN([load],                [$plugin_load],            [System load])
+AC_PLUGIN([log_logstash],        [$plugin_log_logstash],    [Logstash json_event compatible logging])
+AC_PLUGIN([logfile],             [yes],                     [File logging plugin])
+AC_PLUGIN([lpar],                [$with_perfstat],          [AIX logical partitions statistics])
+AC_PLUGIN([lvm],                 [$with_liblvm2app],        [LVM statistics])
+AC_PLUGIN([madwifi],             [$have_linux_wireless_h],  [Madwifi wireless statistics])
+AC_PLUGIN([match_empty_counter], [yes],                     [The empty counter match])
+AC_PLUGIN([match_hashed],        [yes],                     [The hashed match])
+AC_PLUGIN([match_regex],         [yes],                     [The regex match])
+AC_PLUGIN([match_timediff],      [yes],                     [The timediff match])
+AC_PLUGIN([match_value],         [yes],                     [The value match])
+AC_PLUGIN([mbmon],               [yes],                     [Query mbmond])
+AC_PLUGIN([md],                  [$have_linux_raid_md_u_h], [md (Linux software RAID) devices])
+AC_PLUGIN([memcachec],           [$with_libmemcached],      [memcachec statistics])
+AC_PLUGIN([memcached],           [yes],                     [memcached statistics])
+AC_PLUGIN([memory],              [$plugin_memory],          [Memory usage])
+AC_PLUGIN([mic],                 [$with_mic],               [Intel Many Integrated Core stats])
+AC_PLUGIN([modbus],              [$with_libmodbus],         [Modbus plugin])
+AC_PLUGIN([mqtt],                [$with_libmosquitto],      [MQTT output plugin])
+AC_PLUGIN([multimeter],          [$plugin_multimeter],      [Read multimeter values])
+AC_PLUGIN([mysql],               [$with_libmysql],          [MySQL statistics])
+AC_PLUGIN([netapp],              [$with_libnetapp],         [NetApp plugin])
+AC_PLUGIN([netlink],             [$with_libmnl],            [Enhanced Linux network statistics])
+AC_PLUGIN([network],             [yes],                     [Network communication plugin])
+AC_PLUGIN([nfs],                 [$plugin_nfs],             [NFS statistics])
+AC_PLUGIN([nginx],               [$with_libcurl],           [nginx statistics])
+AC_PLUGIN([notify_desktop],      [$with_libnotify],         [Desktop notifications])
+AC_PLUGIN([notify_email],        [$with_libesmtp],          [Email notifier])
+AC_PLUGIN([notify_nagios],       [yes],                     [Nagios notification plugin])
+AC_PLUGIN([ntpd],                [yes],                     [NTPd statistics])
+AC_PLUGIN([numa],                [$plugin_numa],            [NUMA virtual memory statistics])
+AC_PLUGIN([nut],                 [$with_libupsclient],      [Network UPS tools statistics])
+AC_PLUGIN([olsrd],               [yes],                     [olsrd statistics])
+AC_PLUGIN([onewire],             [$with_libowcapi],         [OneWire sensor statistics])
+AC_PLUGIN([openldap],            [$with_libldap],           [OpenLDAP statistics])
+AC_PLUGIN([openvpn],             [yes],                     [OpenVPN client statistics])
+AC_PLUGIN([oracle],              [$with_oracle],            [Oracle plugin])
+AC_PLUGIN([perl],                [$plugin_perl],            [Embed a Perl interpreter])
+AC_PLUGIN([pf],                  [$have_net_pfvar_h],       [BSD packet filter (PF) statistics])
 # FIXME: Check for libevent, too.
-AC_PLUGIN([pinba],       [$have_protoc_c],     [Pinba statistics])
-AC_PLUGIN([ping],        [$with_liboping],     [Network latency statistics])
-AC_PLUGIN([postgresql],  [$with_libpq],        [PostgreSQL database statistics])
-AC_PLUGIN([powerdns],    [yes],                [PowerDNS statistics])
-AC_PLUGIN([processes],   [$plugin_processes],  [Process statistics])
-AC_PLUGIN([protocols],   [$plugin_protocols],  [Protocol (IP, TCP, ...) statistics])
-AC_PLUGIN([python],      [$with_python],       [Embed a Python interpreter])
-AC_PLUGIN([redis],       [$with_libhiredis],    [Redis plugin])
-AC_PLUGIN([routeros],    [$with_librouteros],  [RouterOS plugin])
-AC_PLUGIN([rrdcached],   [$librrd_rrdc_update], [RRDTool output plugin])
-AC_PLUGIN([rrdtool],     [$with_librrd],       [RRDTool output plugin])
-AC_PLUGIN([sensors],     [$with_libsensors],   [lm_sensors statistics])
-AC_PLUGIN([serial],      [$plugin_serial],     [serial port traffic])
-AC_PLUGIN([sigrok],      [$with_libsigrok],    [sigrok acquisition sources])
-AC_PLUGIN([smart],       [$plugin_smart],      [SMART statistics])
-AC_PLUGIN([snmp],        [$with_libnetsnmp],   [SNMP querying plugin])
-AC_PLUGIN([statsd],      [yes],                [StatsD plugin])
-AC_PLUGIN([swap],        [$plugin_swap],       [Swap usage statistics])
-AC_PLUGIN([syslog],      [$have_syslog],       [Syslog logging plugin])
-AC_PLUGIN([table],       [yes],                [Parsing of tabular data])
-AC_PLUGIN([tail],        [yes],                [Parsing of logfiles])
-AC_PLUGIN([tail_csv],    [yes],                [Parsing of CSV files])
-AC_PLUGIN([tape],        [$plugin_tape],       [Tape drive statistics])
-AC_PLUGIN([target_notification], [yes],        [The notification target])
-AC_PLUGIN([target_replace], [yes],             [The replace target])
-AC_PLUGIN([target_scale],[yes],                [The scale target])
-AC_PLUGIN([target_set],  [yes],                [The set target])
-AC_PLUGIN([target_v5upgrade], [yes],           [The v5upgrade target])
-AC_PLUGIN([tcpconns],    [$plugin_tcpconns],   [TCP connection statistics])
-AC_PLUGIN([teamspeak2],  [yes],                [TeamSpeak2 server statistics])
-AC_PLUGIN([ted],         [$plugin_ted],        [Read The Energy Detective values])
-AC_PLUGIN([thermal],     [$plugin_thermal],    [Linux ACPI thermal zone statistics])
-AC_PLUGIN([threshold],   [yes],                [Threshold checking plugin])
-AC_PLUGIN([tokyotyrant], [$with_libtokyotyrant],  [TokyoTyrant database statistics])
-AC_PLUGIN([turbostat],   [$plugin_turbostat],  [Advanced statistic on Intel cpu states])
-AC_PLUGIN([unixsock],    [yes],                [Unixsock communication plugin])
-AC_PLUGIN([uptime],      [$plugin_uptime],     [Uptime statistics])
-AC_PLUGIN([users],       [$plugin_users],      [User statistics])
-AC_PLUGIN([uuid],        [yes],                [UUID as hostname plugin])
-AC_PLUGIN([varnish],     [$with_libvarnish],   [Varnish cache statistics])
-AC_PLUGIN([virt],        [$plugin_virt],       [Virtual machine statistics])
-AC_PLUGIN([vmem],        [$plugin_vmem],       [Virtual memory statistics])
-AC_PLUGIN([vserver],     [$plugin_vserver],    [Linux VServer statistics])
-AC_PLUGIN([wireless],    [$plugin_wireless],   [Wireless statistics])
-AC_PLUGIN([write_graphite], [yes],             [Graphite / Carbon output plugin])
-AC_PLUGIN([write_http],  [$with_libcurl],      [HTTP output plugin])
-AC_PLUGIN([write_kafka],  [$with_librdkafka],  [Kafka output plugin])
-AC_PLUGIN([write_log], [yes],                  [Log output plugin])
-AC_PLUGIN([write_mongodb], [$with_libmongoc],  [MongoDB output plugin])
-AC_PLUGIN([write_redis], [$with_libhiredis],    [Redis output plugin])
-AC_PLUGIN([write_riemann], [$have_protoc_c],   [Riemann output plugin])
-AC_PLUGIN([write_sensu], [yes],                [Sensu output plugin])
-AC_PLUGIN([write_tsdb],  [yes],                [TSDB output plugin])
-AC_PLUGIN([xmms],        [$with_libxmms],      [XMMS statistics])
-AC_PLUGIN([zfs_arc],     [$plugin_zfs_arc],    [ZFS ARC statistics])
-AC_PLUGIN([zookeeper],   [yes],               [Zookeeper statistics])
+AC_PLUGIN([pinba],               [$plugin_pinba],           [Pinba statistics])
+AC_PLUGIN([ping],                [$with_liboping],          [Network latency statistics])
+AC_PLUGIN([postgresql],          [$with_libpq],             [PostgreSQL database statistics])
+AC_PLUGIN([powerdns],            [yes],                     [PowerDNS statistics])
+AC_PLUGIN([processes],           [$plugin_processes],       [Process statistics])
+AC_PLUGIN([protocols],           [$plugin_protocols],       [Protocol (IP, TCP, ...) statistics])
+AC_PLUGIN([python],              [$plugin_python],          [Embed a Python interpreter])
+AC_PLUGIN([redis],               [$with_libhiredis],        [Redis plugin])
+AC_PLUGIN([routeros],            [$with_librouteros],       [RouterOS plugin])
+AC_PLUGIN([rrdcached],           [$librrd_rrdc_update],     [RRDTool output plugin])
+AC_PLUGIN([rrdtool],             [$with_librrd],            [RRDTool output plugin])
+AC_PLUGIN([sensors],             [$with_libsensors],        [lm_sensors statistics])
+AC_PLUGIN([serial],              [$plugin_serial],          [serial port traffic])
+AC_PLUGIN([sigrok],              [$with_libsigrok],         [sigrok acquisition sources])
+AC_PLUGIN([smart],               [$plugin_smart],           [SMART statistics])
+AC_PLUGIN([snmp],                [$with_libnetsnmp],        [SNMP querying plugin])
+AC_PLUGIN([statsd],              [yes],                     [StatsD plugin])
+AC_PLUGIN([swap],                [$plugin_swap],            [Swap usage statistics])
+AC_PLUGIN([syslog],              [$have_syslog],            [Syslog logging plugin])
+AC_PLUGIN([table],               [yes],                     [Parsing of tabular data])
+AC_PLUGIN([tail],                [yes],                     [Parsing of logfiles])
+AC_PLUGIN([tail_csv],            [yes],                     [Parsing of CSV files])
+AC_PLUGIN([tape],                [$plugin_tape],            [Tape drive statistics])
+AC_PLUGIN([target_notification], [yes],                     [The notification target])
+AC_PLUGIN([target_replace],      [yes],                     [The replace target])
+AC_PLUGIN([target_scale],        [yes],                     [The scale target])
+AC_PLUGIN([target_set],          [yes],                     [The set target])
+AC_PLUGIN([target_v5upgrade],    [yes],                     [The v5upgrade target])
+AC_PLUGIN([tcpconns],            [$plugin_tcpconns],        [TCP connection statistics])
+AC_PLUGIN([teamspeak2],          [yes],                     [TeamSpeak2 server statistics])
+AC_PLUGIN([ted],                 [$plugin_ted],             [Read The Energy Detective values])
+AC_PLUGIN([thermal],             [$plugin_thermal],         [Linux ACPI thermal zone statistics])
+AC_PLUGIN([threshold],           [yes],                     [Threshold checking plugin])
+AC_PLUGIN([tokyotyrant],         [$with_libtokyotyrant],    [TokyoTyrant database statistics])
+AC_PLUGIN([turbostat],           [$plugin_turbostat],       [Advanced statistic on Intel cpu states])
+AC_PLUGIN([unixsock],            [yes],                     [Unixsock communication plugin])
+AC_PLUGIN([uptime],              [$plugin_uptime],          [Uptime statistics])
+AC_PLUGIN([users],               [$plugin_users],           [User statistics])
+AC_PLUGIN([uuid],                [yes],                     [UUID as hostname plugin])
+AC_PLUGIN([varnish],             [$with_libvarnish],        [Varnish cache statistics])
+AC_PLUGIN([virt],                [$plugin_virt],            [Virtual machine statistics])
+AC_PLUGIN([vmem],                [$plugin_vmem],            [Virtual memory statistics])
+AC_PLUGIN([vserver],             [$plugin_vserver],         [Linux VServer statistics])
+AC_PLUGIN([wireless],            [$plugin_wireless],        [Wireless statistics])
+AC_PLUGIN([write_graphite],      [yes],                     [Graphite / Carbon output plugin])
+AC_PLUGIN([write_http],          [$with_libcurl],           [HTTP output plugin])
+AC_PLUGIN([write_kafka],         [$with_librdkafka],        [Kafka output plugin])
+AC_PLUGIN([write_log],           [yes],                     [Log output plugin])
+AC_PLUGIN([write_mongodb],       [$with_libmongoc],         [MongoDB output plugin])
+AC_PLUGIN([write_redis],         [$with_libhiredis],        [Redis output plugin])
+AC_PLUGIN([write_riemann],       [$with_libriemann_client], [Riemann output plugin])
+AC_PLUGIN([write_sensu],         [yes],                     [Sensu output plugin])
+AC_PLUGIN([write_tsdb],          [yes],                     [TSDB output plugin])
+AC_PLUGIN([xencpu],              [$plugin_xencpu],          [Xen Host CPU usage])
+AC_PLUGIN([xmms],                [$with_libxmms],           [XMMS statistics])
+AC_PLUGIN([zfs_arc],             [$plugin_zfs_arc],         [ZFS ARC statistics])
+AC_PLUGIN([zone],                [$plugin_zone],            [Solaris container statistics])
+AC_PLUGIN([zookeeper],           [yes],                     [Zookeeper statistics])
 
 dnl Default configuration file
 # Load either syslog or logfile
@@ -5959,7 +6340,17 @@ AC_SUBST(LCC_VERSION_STRING)
 
 AC_CONFIG_FILES(src/libcollectdclient/collectd/lcc_features.h)
 
-AC_CONFIG_FILES([Makefile src/Makefile src/daemon/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile])
+AM_CFLAGS="-Wall"
+AM_CXXFLAGS="-Wall"
+if test "x$enable_werror" != "xno"
+then
+        AM_CFLAGS="$AM_CFLAGS -Werror"
+        AM_CXXFLAGS="$AM_CXXFLAGS -Werror"
+fi
+AC_SUBST([AM_CFLAGS])
+AC_SUBST([AM_CXXFLAGS])
+
+AC_CONFIG_FILES([Makefile proto/Makefile src/Makefile src/daemon/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile])
 AC_OUTPUT
 
 if test "x$with_librrd" = "xyes" \
@@ -5986,208 +6377,235 @@ then
        with_perl_bindings="yes ($PERL_BINDINGS_OPTIONS)"
 fi
 
-cat <<EOF;
-
-Configuration:
-  Libraries:
-    intel mic . . . . . . $with_mic
-    libaquaero5 . . . . . $with_libaquaero5
-    libatasmart . . . . . $with_libatasmart
-    libcurl . . . . . . . $with_libcurl
-    libdbi  . . . . . . . $with_libdbi
-    libesmtp  . . . . . . $with_libesmtp
-    libganglia  . . . . . $with_libganglia
-    libgcrypt . . . . . . $with_libgcrypt
-    libhal  . . . . . . . $with_libhal
-    libhiredis  . . . . . $with_libhiredis
-    libi2c-dev  . . . . . $with_libi2c
-    libiokit  . . . . . . $with_libiokit
-    libiptc . . . . . . . $with_libiptc
-    libjvm  . . . . . . . $with_java
-    libkstat  . . . . . . $with_kstat
-    libkvm  . . . . . . . $with_libkvm
-    libldap . . . . . . . $with_libldap
-    liblvm2app  . . . . . $with_liblvm2app
-    libmemcached  . . . . $with_libmemcached
-    libmnl  . . . . . . . $with_libmnl
-    libmodbus . . . . . . $with_libmodbus
-    libmongoc . . . . . . $with_libmongoc
-    libmysql  . . . . . . $with_libmysql
-    libnetapp . . . . . . $with_libnetapp
-    libnetsnmp  . . . . . $with_libnetsnmp
-    libnotify . . . . . . $with_libnotify
-    liboconfig  . . . . . $with_liboconfig
-    libopenipmi . . . . . $with_libopenipmipthread
-    liboping  . . . . . . $with_liboping
-    libowcapi . . . . . . $with_libowcapi
-    libpcap . . . . . . . $with_libpcap
-    libperfstat . . . . . $with_perfstat
-    libperl . . . . . . . $with_libperl
-    libpq . . . . . . . . $with_libpq
-    libpthread  . . . . . $with_libpthread
-    librabbitmq . . . . . $with_librabbitmq
-    librdkafka  . . . . . $with_librdkafka
-    librouteros . . . . . $with_librouteros
-    librrd  . . . . . . . $with_librrd
-    libsensors  . . . . . $with_libsensors
-    libsigrok   . . . . . $with_libsigrok
-    libstatgrab . . . . . $with_libstatgrab
-    libtokyotyrant  . . . $with_libtokyotyrant
-    libudev . . . . . . . $with_libudev
-    libupsclient  . . . . $with_libupsclient
-    libvarnish  . . . . . $with_libvarnish
-    libvirt . . . . . . . $with_libvirt
-    libxml2 . . . . . . . $with_libxml2
-    libxmms . . . . . . . $with_libxmms
-    libyajl . . . . . . . $with_libyajl
-    oracle  . . . . . . . $with_oracle
-    protobuf-c  . . . . . $have_protoc_c
-    python  . . . . . . . $with_python
-
-  Features:
-    daemon mode . . . . . $enable_daemon
-    debug . . . . . . . . $enable_debug
-
-  Bindings:
-    perl  . . . . . . . . $with_perl_bindings
-
-  Modules:
-    aggregation . . . . . $enable_aggregation
-    amqp    . . . . . . . $enable_amqp
-    apache  . . . . . . . $enable_apache
-    apcups  . . . . . . . $enable_apcups
-    apple_sensors . . . . $enable_apple_sensors
-    aquaero . . . . . . . $enable_aquaero
-    ascent  . . . . . . . $enable_ascent
-    barometer . . . . . . $enable_barometer
-    battery . . . . . . . $enable_battery
-    bind  . . . . . . . . $enable_bind
-    ceph  . . . . . . . . $enable_ceph
-    cgroups . . . . . . . $enable_cgroups
-    conntrack . . . . . . $enable_conntrack
-    contextswitch . . . . $enable_contextswitch
-    cpu . . . . . . . . . $enable_cpu
-    cpufreq . . . . . . . $enable_cpufreq
-    csv . . . . . . . . . $enable_csv
-    curl  . . . . . . . . $enable_curl
-    curl_json . . . . . . $enable_curl_json
-    curl_xml  . . . . . . $enable_curl_xml
-    dbi . . . . . . . . . $enable_dbi
-    df  . . . . . . . . . $enable_df
-    disk  . . . . . . . . $enable_disk
-    dns . . . . . . . . . $enable_dns
-    drbd  . . . . . . . . $enable_drbd
-    email . . . . . . . . $enable_email
-    entropy . . . . . . . $enable_entropy
-    ethstat . . . . . . . $enable_ethstat
-    exec  . . . . . . . . $enable_exec
-    fhcount . . . . . . . $enable_fhcount
-    filecount . . . . . . $enable_filecount
-    fscache . . . . . . . $enable_fscache
-    gmond . . . . . . . . $enable_gmond
-    hddtemp . . . . . . . $enable_hddtemp
-    interface . . . . . . $enable_interface
-    ipc . . . . . . . . . $enable_ipc
-    ipmi  . . . . . . . . $enable_ipmi
-    iptables  . . . . . . $enable_iptables
-    ipvs  . . . . . . . . $enable_ipvs
-    irq . . . . . . . . . $enable_irq
-    java  . . . . . . . . $enable_java
-    load  . . . . . . . . $enable_load
-    logfile . . . . . . . $enable_logfile
-    log_logstash  . . . . $enable_log_logstash
-    lpar  . . . . . . . . $enable_lpar
-    lvm . . . . . . . . . $enable_lvm
-    madwifi . . . . . . . $enable_madwifi
-    match_empty_counter . $enable_match_empty_counter
-    match_hashed  . . . . $enable_match_hashed
-    match_regex . . . . . $enable_match_regex
-    match_timediff  . . . $enable_match_timediff
-    match_value . . . . . $enable_match_value
-    mbmon . . . . . . . . $enable_mbmon
-    md  . . . . . . . . . $enable_md
-    memcachec . . . . . . $enable_memcachec
-    memcached . . . . . . $enable_memcached
-    memory  . . . . . . . $enable_memory
-    mic . . . . . . . . . $enable_mic
-    modbus  . . . . . . . $enable_modbus
-    multimeter  . . . . . $enable_multimeter
-    mysql . . . . . . . . $enable_mysql
-    netapp  . . . . . . . $enable_netapp
-    netlink . . . . . . . $enable_netlink
-    network . . . . . . . $enable_network
-    nfs . . . . . . . . . $enable_nfs
-    nginx . . . . . . . . $enable_nginx
-    notify_desktop  . . . $enable_notify_desktop
-    notify_email  . . . . $enable_notify_email
-    ntpd  . . . . . . . . $enable_ntpd
-    numa  . . . . . . . . $enable_numa
-    nut . . . . . . . . . $enable_nut
-    olsrd . . . . . . . . $enable_olsrd
-    onewire . . . . . . . $enable_onewire
-    openldap  . . . . . . $enable_openldap
-    openvpn . . . . . . . $enable_openvpn
-    oracle  . . . . . . . $enable_oracle
-    perl  . . . . . . . . $enable_perl
-    pf  . . . . . . . . . $enable_pf
-    pinba . . . . . . . . $enable_pinba
-    ping  . . . . . . . . $enable_ping
-    postgresql  . . . . . $enable_postgresql
-    powerdns  . . . . . . $enable_powerdns
-    processes . . . . . . $enable_processes
-    protocols . . . . . . $enable_protocols
-    python  . . . . . . . $enable_python
-    redis . . . . . . . . $enable_redis
-    routeros  . . . . . . $enable_routeros
-    rrdcached . . . . . . $enable_rrdcached
-    rrdtool . . . . . . . $enable_rrdtool
-    sensors . . . . . . . $enable_sensors
-    serial  . . . . . . . $enable_serial
-    sigrok  . . . . . . . $enable_sigrok
-    smart . . . . . . . . $enable_smart
-    snmp  . . . . . . . . $enable_snmp
-    statsd  . . . . . . . $enable_statsd
-    swap  . . . . . . . . $enable_swap
-    syslog  . . . . . . . $enable_syslog
-    table . . . . . . . . $enable_table
-    tail_csv  . . . . . . $enable_tail_csv
-    tail  . . . . . . . . $enable_tail
-    tape  . . . . . . . . $enable_tape
-    target_notification . $enable_target_notification
-    target_replace  . . . $enable_target_replace
-    target_scale  . . . . $enable_target_scale
-    target_set  . . . . . $enable_target_set
-    target_v5upgrade  . . $enable_target_v5upgrade
-    tcpconns  . . . . . . $enable_tcpconns
-    teamspeak2  . . . . . $enable_teamspeak2
-    ted . . . . . . . . . $enable_ted
-    thermal . . . . . . . $enable_thermal
-    threshold . . . . . . $enable_threshold
-    tokyotyrant . . . . . $enable_tokyotyrant
-    turbostat . . . . . . $enable_turbostat
-    unixsock  . . . . . . $enable_unixsock
-    uptime  . . . . . . . $enable_uptime
-    users . . . . . . . . $enable_users
-    uuid  . . . . . . . . $enable_uuid
-    varnish . . . . . . . $enable_varnish
-    virt  . . . . . . . . $enable_virt
-    vmem  . . . . . . . . $enable_vmem
-    vserver . . . . . . . $enable_vserver
-    wireless  . . . . . . $enable_wireless
-    write_graphite  . . . $enable_write_graphite
-    write_http  . . . . . $enable_write_http
-    write_kafka . . . . . $enable_write_kafka
-    write_log . . . . . . $enable_write_log
-    write_mongodb . . . . $enable_write_mongodb
-    write_redis . . . . . $enable_write_redis
-    write_riemann . . . . $enable_write_riemann
-    write_sensu . . . . . $enable_write_sensu
-    write_tsdb  . . . . . $enable_write_tsdb
-    xmms  . . . . . . . . $enable_xmms
-    zfs_arc . . . . . . . $enable_zfs_arc
-    zookeeper . . . . . . $enable_zookeeper
-
-EOF
+AC_MSG_RESULT()
+AC_MSG_RESULT([Configuration:])
+AC_MSG_RESULT([  Build:])
+AC_MSG_RESULT([    Platform  . . . . . . $ac_system])
+AC_MSG_RESULT([    CC  . . . . . . . . . $CC])
+AC_MSG_RESULT([    CFLAGS  . . . . . . . $AM_CFLAGS $CFLAGS])
+AC_MSG_RESULT([    CXXFLAGS  . . . . . . $AM_CXXFLAGS $CXXFLAGS])
+AC_MSG_RESULT([    CPP . . . . . . . . . $CPP])
+AC_MSG_RESULT([    CPPFLAGS  . . . . . . $CPPFLAGS])
+AC_MSG_RESULT([    GRPC_CPP_PLUGIN . . . $GRPC_CPP_PLUGIN])
+AC_MSG_RESULT([    LD  . . . . . . . . . $LD])
+AC_MSG_RESULT([    LDFLAGS . . . . . . . $LDFLAGS])
+AC_MSG_RESULT([    PROTOC  . . . . . . . $PROTOC])
+AC_MSG_RESULT([    YACC  . . . . . . . . $YACC])
+AC_MSG_RESULT([    YFLAGS  . . . . . . . $YFLAGS])
+AC_MSG_RESULT()
+AC_MSG_RESULT([  Libraries:])
+AC_MSG_RESULT([    intel mic . . . . . . $with_mic])
+AC_MSG_RESULT([    libaquaero5 . . . . . $with_libaquaero5])
+AC_MSG_RESULT([    libatasmart . . . . . $with_libatasmart])
+AC_MSG_RESULT([    libcurl . . . . . . . $with_libcurl])
+AC_MSG_RESULT([    libdbi  . . . . . . . $with_libdbi])
+AC_MSG_RESULT([    libesmtp  . . . . . . $with_libesmtp])
+AC_MSG_RESULT([    libganglia  . . . . . $with_libganglia])
+AC_MSG_RESULT([    libgcrypt . . . . . . $with_libgcrypt])
+AC_MSG_RESULT([    libgps  . . . . . . . $with_libgps])
+AC_MSG_RESULT([    libgrpc++ . . . . . . $with_libgrpcpp])
+AC_MSG_RESULT([    libhal  . . . . . . . $with_libhal])
+AC_MSG_RESULT([    libhiredis  . . . . . $with_libhiredis])
+AC_MSG_RESULT([    libi2c-dev  . . . . . $with_libi2c])
+AC_MSG_RESULT([    libiokit  . . . . . . $with_libiokit])
+AC_MSG_RESULT([    libiptc . . . . . . . $with_libiptc])
+AC_MSG_RESULT([    libjvm  . . . . . . . $with_java])
+AC_MSG_RESULT([    libkstat  . . . . . . $with_kstat])
+AC_MSG_RESULT([    libkvm  . . . . . . . $with_libkvm])
+AC_MSG_RESULT([    libldap . . . . . . . $with_libldap])
+AC_MSG_RESULT([    liblvm2app  . . . . . $with_liblvm2app])
+AC_MSG_RESULT([    libmemcached  . . . . $with_libmemcached])
+AC_MSG_RESULT([    libmnl  . . . . . . . $with_libmnl])
+AC_MSG_RESULT([    libmodbus . . . . . . $with_libmodbus])
+AC_MSG_RESULT([    libmongoc . . . . . . $with_libmongoc])
+AC_MSG_RESULT([    libmosquitto  . . . . $with_libmosquitto])
+AC_MSG_RESULT([    libmysql  . . . . . . $with_libmysql])
+AC_MSG_RESULT([    libnetapp . . . . . . $with_libnetapp])
+AC_MSG_RESULT([    libnetsnmp  . . . . . $with_libnetsnmp])
+AC_MSG_RESULT([    libnotify . . . . . . $with_libnotify])
+AC_MSG_RESULT([    liboconfig  . . . . . $with_liboconfig])
+AC_MSG_RESULT([    libopenipmi . . . . . $with_libopenipmipthread])
+AC_MSG_RESULT([    liboping  . . . . . . $with_liboping])
+AC_MSG_RESULT([    libowcapi . . . . . . $with_libowcapi])
+AC_MSG_RESULT([    libpcap . . . . . . . $with_libpcap])
+AC_MSG_RESULT([    libperfstat . . . . . $with_perfstat])
+AC_MSG_RESULT([    libperl . . . . . . . $with_libperl])
+AC_MSG_RESULT([    libpq . . . . . . . . $with_libpq])
+AC_MSG_RESULT([    libprotobuf . . . . . $with_libprotobuf])
+AC_MSG_RESULT([    libprotobuf-c . . . . $with_libprotobuf_c])
+AC_MSG_RESULT([    libpython . . . . . . $with_libpython])
+AC_MSG_RESULT([    librabbitmq . . . . . $with_librabbitmq])
+AC_MSG_RESULT([    libriemann-client . . $with_libriemann_client])
+AC_MSG_RESULT([    librdkafka  . . . . . $with_librdkafka])
+AC_MSG_RESULT([    librouteros . . . . . $with_librouteros])
+AC_MSG_RESULT([    librrd  . . . . . . . $with_librrd])
+AC_MSG_RESULT([    libsensors  . . . . . $with_libsensors])
+AC_MSG_RESULT([    libsigrok   . . . . . $with_libsigrok])
+AC_MSG_RESULT([    libstatgrab . . . . . $with_libstatgrab])
+AC_MSG_RESULT([    libtokyotyrant  . . . $with_libtokyotyrant])
+AC_MSG_RESULT([    libudev . . . . . . . $with_libudev])
+AC_MSG_RESULT([    libupsclient  . . . . $with_libupsclient])
+AC_MSG_RESULT([    libvarnish  . . . . . $with_libvarnish])
+AC_MSG_RESULT([    libvirt . . . . . . . $with_libvirt])
+AC_MSG_RESULT([    libxenctrl  . . . . . $with_libxenctrl])
+AC_MSG_RESULT([    libxml2 . . . . . . . $with_libxml2])
+AC_MSG_RESULT([    libxmms . . . . . . . $with_libxmms])
+AC_MSG_RESULT([    libyajl . . . . . . . $with_libyajl])
+AC_MSG_RESULT([    oracle  . . . . . . . $with_oracle])
+AC_MSG_RESULT([    protobuf-c  . . . . . $have_protoc_c])
+AC_MSG_RESULT([    protoc 3  . . . . . . $have_protoc3])
+AC_MSG_RESULT()
+AC_MSG_RESULT([  Features:])
+AC_MSG_RESULT([    daemon mode . . . . . $enable_daemon])
+AC_MSG_RESULT([    debug . . . . . . . . $enable_debug])
+AC_MSG_RESULT()
+AC_MSG_RESULT([  Bindings:])
+AC_MSG_RESULT([    perl  . . . . . . . . $with_perl_bindings])
+AC_MSG_RESULT()
+AC_MSG_RESULT([  Modules:])
+AC_MSG_RESULT([    aggregation . . . . . $enable_aggregation])
+AC_MSG_RESULT([    amqp    . . . . . . . $enable_amqp])
+AC_MSG_RESULT([    apache  . . . . . . . $enable_apache])
+AC_MSG_RESULT([    apcups  . . . . . . . $enable_apcups])
+AC_MSG_RESULT([    apple_sensors . . . . $enable_apple_sensors])
+AC_MSG_RESULT([    aquaero . . . . . . . $enable_aquaero])
+AC_MSG_RESULT([    ascent  . . . . . . . $enable_ascent])
+AC_MSG_RESULT([    barometer . . . . . . $enable_barometer])
+AC_MSG_RESULT([    battery . . . . . . . $enable_battery])
+AC_MSG_RESULT([    bind  . . . . . . . . $enable_bind])
+AC_MSG_RESULT([    ceph  . . . . . . . . $enable_ceph])
+AC_MSG_RESULT([    cgroups . . . . . . . $enable_cgroups])
+AC_MSG_RESULT([    chrony. . . . . . . . $enable_chrony])
+AC_MSG_RESULT([    conntrack . . . . . . $enable_conntrack])
+AC_MSG_RESULT([    contextswitch . . . . $enable_contextswitch])
+AC_MSG_RESULT([    cpu . . . . . . . . . $enable_cpu])
+AC_MSG_RESULT([    cpufreq . . . . . . . $enable_cpufreq])
+AC_MSG_RESULT([    cpusleep  . . . . . . $enable_cpusleep])
+AC_MSG_RESULT([    csv . . . . . . . . . $enable_csv])
+AC_MSG_RESULT([    curl  . . . . . . . . $enable_curl])
+AC_MSG_RESULT([    curl_json . . . . . . $enable_curl_json])
+AC_MSG_RESULT([    curl_xml  . . . . . . $enable_curl_xml])
+AC_MSG_RESULT([    dbi . . . . . . . . . $enable_dbi])
+AC_MSG_RESULT([    df  . . . . . . . . . $enable_df])
+AC_MSG_RESULT([    disk  . . . . . . . . $enable_disk])
+AC_MSG_RESULT([    dns . . . . . . . . . $enable_dns])
+AC_MSG_RESULT([    drbd  . . . . . . . . $enable_drbd])
+AC_MSG_RESULT([    email . . . . . . . . $enable_email])
+AC_MSG_RESULT([    entropy . . . . . . . $enable_entropy])
+AC_MSG_RESULT([    ethstat . . . . . . . $enable_ethstat])
+AC_MSG_RESULT([    exec  . . . . . . . . $enable_exec])
+AC_MSG_RESULT([    fhcount . . . . . . . $enable_fhcount])
+AC_MSG_RESULT([    filecount . . . . . . $enable_filecount])
+AC_MSG_RESULT([    fscache . . . . . . . $enable_fscache])
+AC_MSG_RESULT([    gmond . . . . . . . . $enable_gmond])
+AC_MSG_RESULT([    gps . . . . . . . . . $enable_gps])
+AC_MSG_RESULT([    grpc  . . . . . . . . $enable_grpc])
+AC_MSG_RESULT([    hddtemp . . . . . . . $enable_hddtemp])
+AC_MSG_RESULT([    interface . . . . . . $enable_interface])
+AC_MSG_RESULT([    ipc . . . . . . . . . $enable_ipc])
+AC_MSG_RESULT([    ipmi  . . . . . . . . $enable_ipmi])
+AC_MSG_RESULT([    iptables  . . . . . . $enable_iptables])
+AC_MSG_RESULT([    ipvs  . . . . . . . . $enable_ipvs])
+AC_MSG_RESULT([    irq . . . . . . . . . $enable_irq])
+AC_MSG_RESULT([    java  . . . . . . . . $enable_java])
+AC_MSG_RESULT([    load  . . . . . . . . $enable_load])
+AC_MSG_RESULT([    logfile . . . . . . . $enable_logfile])
+AC_MSG_RESULT([    log_logstash  . . . . $enable_log_logstash])
+AC_MSG_RESULT([    lpar  . . . . . . . . $enable_lpar])
+AC_MSG_RESULT([    lvm . . . . . . . . . $enable_lvm])
+AC_MSG_RESULT([    madwifi . . . . . . . $enable_madwifi])
+AC_MSG_RESULT([    match_empty_counter . $enable_match_empty_counter])
+AC_MSG_RESULT([    match_hashed  . . . . $enable_match_hashed])
+AC_MSG_RESULT([    match_regex . . . . . $enable_match_regex])
+AC_MSG_RESULT([    match_timediff  . . . $enable_match_timediff])
+AC_MSG_RESULT([    match_value . . . . . $enable_match_value])
+AC_MSG_RESULT([    mbmon . . . . . . . . $enable_mbmon])
+AC_MSG_RESULT([    md  . . . . . . . . . $enable_md])
+AC_MSG_RESULT([    memcachec . . . . . . $enable_memcachec])
+AC_MSG_RESULT([    memcached . . . . . . $enable_memcached])
+AC_MSG_RESULT([    memory  . . . . . . . $enable_memory])
+AC_MSG_RESULT([    mic . . . . . . . . . $enable_mic])
+AC_MSG_RESULT([    modbus  . . . . . . . $enable_modbus])
+AC_MSG_RESULT([    mqtt  . . . . . . . . $enable_mqtt])
+AC_MSG_RESULT([    multimeter  . . . . . $enable_multimeter])
+AC_MSG_RESULT([    mysql . . . . . . . . $enable_mysql])
+AC_MSG_RESULT([    netapp  . . . . . . . $enable_netapp])
+AC_MSG_RESULT([    netlink . . . . . . . $enable_netlink])
+AC_MSG_RESULT([    network . . . . . . . $enable_network])
+AC_MSG_RESULT([    nfs . . . . . . . . . $enable_nfs])
+AC_MSG_RESULT([    nginx . . . . . . . . $enable_nginx])
+AC_MSG_RESULT([    notify_desktop  . . . $enable_notify_desktop])
+AC_MSG_RESULT([    notify_email  . . . . $enable_notify_email])
+AC_MSG_RESULT([    notify_nagios . . . . $enable_notify_nagios])
+AC_MSG_RESULT([    ntpd  . . . . . . . . $enable_ntpd])
+AC_MSG_RESULT([    numa  . . . . . . . . $enable_numa])
+AC_MSG_RESULT([    nut . . . . . . . . . $enable_nut])
+AC_MSG_RESULT([    olsrd . . . . . . . . $enable_olsrd])
+AC_MSG_RESULT([    onewire . . . . . . . $enable_onewire])
+AC_MSG_RESULT([    openldap  . . . . . . $enable_openldap])
+AC_MSG_RESULT([    openvpn . . . . . . . $enable_openvpn])
+AC_MSG_RESULT([    oracle  . . . . . . . $enable_oracle])
+AC_MSG_RESULT([    perl  . . . . . . . . $enable_perl])
+AC_MSG_RESULT([    pf  . . . . . . . . . $enable_pf])
+AC_MSG_RESULT([    pinba . . . . . . . . $enable_pinba])
+AC_MSG_RESULT([    ping  . . . . . . . . $enable_ping])
+AC_MSG_RESULT([    postgresql  . . . . . $enable_postgresql])
+AC_MSG_RESULT([    powerdns  . . . . . . $enable_powerdns])
+AC_MSG_RESULT([    processes . . . . . . $enable_processes])
+AC_MSG_RESULT([    protocols . . . . . . $enable_protocols])
+AC_MSG_RESULT([    python  . . . . . . . $enable_python])
+AC_MSG_RESULT([    redis . . . . . . . . $enable_redis])
+AC_MSG_RESULT([    routeros  . . . . . . $enable_routeros])
+AC_MSG_RESULT([    rrdcached . . . . . . $enable_rrdcached])
+AC_MSG_RESULT([    rrdtool . . . . . . . $enable_rrdtool])
+AC_MSG_RESULT([    sensors . . . . . . . $enable_sensors])
+AC_MSG_RESULT([    serial  . . . . . . . $enable_serial])
+AC_MSG_RESULT([    sigrok  . . . . . . . $enable_sigrok])
+AC_MSG_RESULT([    smart . . . . . . . . $enable_smart])
+AC_MSG_RESULT([    snmp  . . . . . . . . $enable_snmp])
+AC_MSG_RESULT([    statsd  . . . . . . . $enable_statsd])
+AC_MSG_RESULT([    swap  . . . . . . . . $enable_swap])
+AC_MSG_RESULT([    syslog  . . . . . . . $enable_syslog])
+AC_MSG_RESULT([    table . . . . . . . . $enable_table])
+AC_MSG_RESULT([    tail_csv  . . . . . . $enable_tail_csv])
+AC_MSG_RESULT([    tail  . . . . . . . . $enable_tail])
+AC_MSG_RESULT([    tape  . . . . . . . . $enable_tape])
+AC_MSG_RESULT([    target_notification . $enable_target_notification])
+AC_MSG_RESULT([    target_replace  . . . $enable_target_replace])
+AC_MSG_RESULT([    target_scale  . . . . $enable_target_scale])
+AC_MSG_RESULT([    target_set  . . . . . $enable_target_set])
+AC_MSG_RESULT([    target_v5upgrade  . . $enable_target_v5upgrade])
+AC_MSG_RESULT([    tcpconns  . . . . . . $enable_tcpconns])
+AC_MSG_RESULT([    teamspeak2  . . . . . $enable_teamspeak2])
+AC_MSG_RESULT([    ted . . . . . . . . . $enable_ted])
+AC_MSG_RESULT([    thermal . . . . . . . $enable_thermal])
+AC_MSG_RESULT([    threshold . . . . . . $enable_threshold])
+AC_MSG_RESULT([    tokyotyrant . . . . . $enable_tokyotyrant])
+AC_MSG_RESULT([    turbostat . . . . . . $enable_turbostat])
+AC_MSG_RESULT([    unixsock  . . . . . . $enable_unixsock])
+AC_MSG_RESULT([    uptime  . . . . . . . $enable_uptime])
+AC_MSG_RESULT([    users . . . . . . . . $enable_users])
+AC_MSG_RESULT([    uuid  . . . . . . . . $enable_uuid])
+AC_MSG_RESULT([    varnish . . . . . . . $enable_varnish])
+AC_MSG_RESULT([    virt  . . . . . . . . $enable_virt])
+AC_MSG_RESULT([    vmem  . . . . . . . . $enable_vmem])
+AC_MSG_RESULT([    vserver . . . . . . . $enable_vserver])
+AC_MSG_RESULT([    wireless  . . . . . . $enable_wireless])
+AC_MSG_RESULT([    write_graphite  . . . $enable_write_graphite])
+AC_MSG_RESULT([    write_http  . . . . . $enable_write_http])
+AC_MSG_RESULT([    write_kafka . . . . . $enable_write_kafka])
+AC_MSG_RESULT([    write_log . . . . . . $enable_write_log])
+AC_MSG_RESULT([    write_mongodb . . . . $enable_write_mongodb])
+AC_MSG_RESULT([    write_redis . . . . . $enable_write_redis])
+AC_MSG_RESULT([    write_riemann . . . . $enable_write_riemann])
+AC_MSG_RESULT([    write_sensu . . . . . $enable_write_sensu])
+AC_MSG_RESULT([    write_tsdb  . . . . . $enable_write_tsdb])
+AC_MSG_RESULT([    xencpu  . . . . . . . $enable_xencpu])
+AC_MSG_RESULT([    xmms  . . . . . . . . $enable_xmms])
+AC_MSG_RESULT([    zfs_arc . . . . . . . $enable_zfs_arc])
+AC_MSG_RESULT([    zone  . . . . . . . . $enable_zone])
+AC_MSG_RESULT([    zookeeper . . . . . . $enable_zookeeper])
+AC_MSG_RESULT()
 
 if test "x$dependency_error" = "xyes"; then
        AC_MSG_ERROR("Some plugins are missing dependencies - see the summary above for details")
index 1ebf1f1..897d619 100644 (file)
@@ -65,11 +65,6 @@ file. That is very handy when you realise that you have bundled up DSes in one
 RRD-file that should have been in multiple RRD-files instead. Is is used by
 `migrate-3-4.px' to split up the cpu-, nfs-, swap-files and possibly others.
 
-fedora/
--------
-  Init-script and Spec-file that can be used when creating RPM-packages for
-Fedora.
-
 GenericJMX.conf
 ---------------
   Example configuration file for the ‘GenericJMX’ Java plugin. Please read the
diff --git a/contrib/collectd.service b/contrib/collectd.service
deleted file mode 100644 (file)
index ee4d596..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-[Unit]
-Description=statistics collection daemon
-Documentation=man:collectd(1)
-After=local-fs.target network.target
-Requires=local-fs.target network.target
-
-[Service]
-ExecStart=/usr/sbin/collectd -C /etc/collectd/collectd.conf -f
-Restart=always
-RestartSec=10
-StandardOutput=syslog
-StandardError=syslog
-
-[Install]
-WantedBy=multi-user.target
index cc7e141..31c530f 100644 (file)
@@ -487,6 +487,8 @@ sub get_files_by_ident
   my $ident = shift;
   my $all_files;
   my @ret = ();
+  my $temp;
+  my $hosts;
 
   my $cache_key = ident_to_string ($ident);
   if (defined ($Cache->{'get_files_by_ident'}{$cache_key}))
@@ -496,7 +498,20 @@ sub get_files_by_ident
     return ($ret)
   }
 
-  $all_files = _get_all_files ();
+  if ($ident->{'hostname'})
+  {
+    $all_files = [];
+    $hosts = $ident->{'hostname'};
+    foreach (@$hosts)
+    {
+      $temp = get_files_for_host ($_);
+      push (@$all_files, @$temp);
+    }
+  }
+  else
+  {
+    $all_files = _get_all_files ();
+  }
 
   @ret = grep { _filter_ident ($ident, $_) == 0 } (@$all_files);
 
index 9539062..e1b89f6 100644 (file)
@@ -39,6 +39,7 @@
 #endif /* ! HAVE_CONFIG */
 
 #include <collectd/collectd.h>
+
 #include <collectd/common.h>
 #include <collectd/plugin.h>
 
diff --git a/contrib/fedora/collectd.spec b/contrib/fedora/collectd.spec
deleted file mode 100644 (file)
index a35923c..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-Summary:       Statistics collection daemon for filling RRD files.
-Name:           collectd
-Version:       4.2.0
-Release:       1.fc6
-Source:                http://collectd.org/files/%{name}-%{version}.tar.gz
-License:       GPL
-Group:         System Environment/Daemons
-BuildRoot:     %{_tmppath}/%{name}-%{version}-root
-BuildPrereq:   lm_sensors-devel
-BuildPrereq:   mysql-devel
-BuildPrereq:   rrdtool-devel
-BuildPrereq:   net-snmp-devel
-Requires:      rrdtool
-Requires:      perl-Regexp-Common
-Packager:      Florian octo Forster <octo@verplant.org>
-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.
-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.
-
-%package apache
-Summary:       apache-plugin for collectd.
-Group:         System Environment/Daemons
-Requires:      collectd = %{version}, curl
-%description apache
-This plugin collectd data provided by Apache's `mod_status'.
-
-%package email
-Summary:       email-plugin for collectd.
-Group:         System Environment/Daemons
-Requires:      collectd = %{version}, spamassassin
-%description email
-This plugin collectd data provided by spamassassin.
-
-%package mysql
-Summary:       mysql-module for collectd.
-Group:         System Environment/Daemons
-Requires:      collectd = %{version}, mysql
-%description mysql
-MySQL  querying  plugin.  This plugins  provides data of  issued commands,
-called handlers and database traffic.
-
-%package sensors
-Summary:       libsensors-module for collectd.
-Group:         System Environment/Daemons
-Requires:      collectd = %{version}, lm_sensors
-%description sensors
-This  plugin  for  collectd  provides  querying  of sensors  supported  by
-lm_sensors.
-
-%prep
-rm -rf $RPM_BUILD_ROOT
-%setup
-
-%build
-./configure --prefix=%{_prefix} --sbindir=%{_sbindir} --mandir=%{_mandir} --libdir=%{_libdir} --sysconfdir=%{_sysconfdir}
-make
-
-%install
-make install DESTDIR=$RPM_BUILD_ROOT
-mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
-mkdir -p $RPM_BUILD_ROOT/var/www/cgi-bin
-cp src/collectd.conf $RPM_BUILD_ROOT/etc/collectd.conf
-cp contrib/fedora/init.d-collectd $RPM_BUILD_ROOT/etc/rc.d/init.d/collectd
-cp contrib/collection.cgi $RPM_BUILD_ROOT/var/www/cgi-bin
-cp contrib/collection.conf $RPM_BUILD_ROOT/etc/collection.conf
-mkdir -p $RPM_BUILD_ROOT/var/lib/collectd
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%post
-/sbin/chkconfig --add collectd
-/sbin/chkconfig collectd on
-
-%preun
-if [ "$1" = 0 ]; then
-   /sbin/chkconfig collectd off
-   /etc/init.d/collectd stop
-   /sbin/chkconfig --del collectd
-fi
-exit 0
-
-%postun
-if [ "$1" -ge 1 ]; then
-    /etc/init.d/collectd restart
-fi
-exit 0
-
-%files
-%defattr(-,root,root)
-%doc AUTHORS COPYING ChangeLog INSTALL NEWS README
-%attr(0644,root,root) %config(noreplace) /etc/collectd.conf
-%attr(0644,root,root) %config(noreplace) /etc/collection.conf
-%attr(0755,root,root) /etc/rc.d/init.d/collectd
-%attr(0755,root,root) /var/www/cgi-bin/collection.cgi
-%attr(0755,root,root) %{_sbindir}/collectd
-%attr(0755,root,root) %{_bindir}/collectd-nagios
-%attr(0644,root,root) %{_mandir}/man1/*
-%attr(0644,root,root) %{_mandir}/man5/*
-
-%attr(0644,root,root) /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod
-%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/Collectd.pm
-%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/Collectd/Unixsock.pm
-%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/Collectd/.packlist
-%attr(0644,root,root) %{_mandir}/man3/Collectd::Unixsock.3pm.gz
-
-%attr(0644,root,root) %{_libdir}/%{name}/apcups.so*
-%attr(0644,root,root) %{_libdir}/%{name}/apcups.la
-
-# FIXME!!!
-#%attr(0644,root,root) %{_libdir}/%{name}/apple_sensors.so*
-#%attr(0644,root,root) %{_libdir}/%{name}/apple_sensors.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/battery.so*
-%attr(0644,root,root) %{_libdir}/%{name}/battery.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/conntrack.so*
-%attr(0644,root,root) %{_libdir}/%{name}/conntrack.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/cpufreq.so*
-%attr(0644,root,root) %{_libdir}/%{name}/cpufreq.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/cpu.so*
-%attr(0644,root,root) %{_libdir}/%{name}/cpu.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/csv.so*
-%attr(0644,root,root) %{_libdir}/%{name}/csv.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/df.so*
-%attr(0644,root,root) %{_libdir}/%{name}/df.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/disk.so*
-%attr(0644,root,root) %{_libdir}/%{name}/disk.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/dns.so*
-%attr(0644,root,root) %{_libdir}/%{name}/dns.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/entropy.so*
-%attr(0644,root,root) %{_libdir}/%{name}/entropy.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/exec.so*
-%attr(0644,root,root) %{_libdir}/%{name}/exec.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/hddtemp.so*
-%attr(0644,root,root) %{_libdir}/%{name}/hddtemp.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/interface.so*
-%attr(0644,root,root) %{_libdir}/%{name}/interface.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/iptables.so*
-%attr(0644,root,root) %{_libdir}/%{name}/iptables.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/irq.so*
-%attr(0644,root,root) %{_libdir}/%{name}/irq.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/load.so*
-%attr(0644,root,root) %{_libdir}/%{name}/load.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/logfile.so*
-%attr(0644,root,root) %{_libdir}/%{name}/logfile.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/mbmon.so*
-%attr(0644,root,root) %{_libdir}/%{name}/mbmon.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/memcached.so*
-%attr(0644,root,root) %{_libdir}/%{name}/memcached.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/memory.so*
-%attr(0644,root,root) %{_libdir}/%{name}/memory.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/multimeter.so*
-%attr(0644,root,root) %{_libdir}/%{name}/multimeter.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/network.so*
-%attr(0644,root,root) %{_libdir}/%{name}/network.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/nfs.so*
-%attr(0644,root,root) %{_libdir}/%{name}/nfs.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/nginx.so*
-%attr(0644,root,root) %{_libdir}/%{name}/nginx.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/ntpd.so*
-%attr(0644,root,root) %{_libdir}/%{name}/ntpd.la
-
-# FIXME!!!
-#%attr(0644,root,root) %{_libdir}/%{name}/nut.so*
-#%attr(0644,root,root) %{_libdir}/%{name}/nut.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/perl.so*
-%attr(0644,root,root) %{_libdir}/%{name}/perl.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/ping.so*
-%attr(0644,root,root) %{_libdir}/%{name}/ping.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/processes.so*
-%attr(0644,root,root) %{_libdir}/%{name}/processes.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/rrdtool.so*
-%attr(0644,root,root) %{_libdir}/%{name}/rrdtool.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/serial.so*
-%attr(0644,root,root) %{_libdir}/%{name}/serial.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/swap.so*
-%attr(0644,root,root) %{_libdir}/%{name}/swap.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/snmp.so*
-%attr(0644,root,root) %{_libdir}/%{name}/snmp.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/syslog.so*
-%attr(0644,root,root) %{_libdir}/%{name}/syslog.la
-
-# FIXME!!!
-#%attr(0644,root,root) %{_libdir}/%{name}/tape.so*
-#%attr(0644,root,root) %{_libdir}/%{name}/tape.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/tcpconns.so*
-%attr(0644,root,root) %{_libdir}/%{name}/tcpconns.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/unixsock.so*
-%attr(0644,root,root) %{_libdir}/%{name}/unixsock.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/users.so*
-%attr(0644,root,root) %{_libdir}/%{name}/users.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/vserver.so*
-%attr(0644,root,root) %{_libdir}/%{name}/vserver.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/wireless.so*
-%attr(0644,root,root) %{_libdir}/%{name}/wireless.la
-
-%attr(0644,root,root) %{_datadir}/%{name}/types.db
-
-%dir /var/lib/collectd
-
-%files apache
-%attr(0644,root,root) %{_libdir}/%{name}/apache.so*
-%attr(0644,root,root) %{_libdir}/%{name}/apache.la
-
-%files email
-%attr(0644,root,root) %{_libdir}/%{name}/email.so*
-%attr(0644,root,root) %{_libdir}/%{name}/email.la
-
-%files mysql
-%attr(0644,root,root) %{_libdir}/%{name}/mysql.so*
-%attr(0644,root,root) %{_libdir}/%{name}/mysql.la
-
-%files sensors
-%attr(0644,root,root) %{_libdir}/%{name}/sensors.so*
-%attr(0644,root,root) %{_libdir}/%{name}/sensors.la
-
-%changelog
-* Wed Oct 31 2007 Iain Lea <iain@bricbrac.de> 4.2.0
-- New major release
-- Changes to support 4.2.0 (ie. contrib/collection.conf)
-
-* Mon Aug 06 2007 Kjell Randa <Kjell.Randa@broadpark.no> 4.0.6
-- New upstream version
-
-* Wed Jul 25 2007 Kjell Randa <Kjell.Randa@broadpark.no> 4.0.5
-- New major release
-- Changes to support 4.0.5 
-
-* Wed Jan 11 2007 Iain Lea <iain@bricbrac.de> 3.11.0-0
-- fixed spec file to build correctly on fedora core
-- added improved init.d script to work with chkconfig
-- added %post and %postun to call chkconfig automatically
-
-* Sun Jul 09 2006 Florian octo Forster <octo@verplant.org> 3.10.0-1
-- New upstream version
-
-* Tue Jun 25 2006 Florian octo Forster <octo@verplant.org> 3.9.4-1
-- New upstream version
-
-* Tue Jun 01 2006 Florian octo Forster <octo@verplant.org> 3.9.3-1
-- New upstream version
-
-* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.9.2-1
-- New upstream version
-
-* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.8.5-1
-- New upstream version
-
-* Fri Apr 21 2006 Florian octo Forster <octo@verplant.org> 3.9.1-1
-- New upstream version
-
-* Fri Apr 14 2006 Florian octo Forster <octo@verplant.org> 3.9.0-1
-- New upstream version
-- Added the `apache' package.
-
-* Thu Mar 14 2006 Florian octo Forster <octo@verplant.org> 3.8.2-1
-- New upstream version
-
-* Thu Mar 13 2006 Florian octo Forster <octo@verplant.org> 3.8.1-1
-- New upstream version
-
-* Thu Mar 09 2006 Florian octo Forster <octo@verplant.org> 3.8.0-1
-- New upstream version
-
-* Sat Feb 18 2006 Florian octo Forster <octo@verplant.org> 3.7.2-1
-- Include `tape.so' so the build doesn't terminate because of missing files..
-- New upstream version
-
-* Sat Feb 04 2006 Florian octo Forster <octo@verplant.org> 3.7.1-1
-- New upstream version
-
-* Mon Jan 30 2006 Florian octo Forster <octo@verplant.org> 3.7.0-1
-- New upstream version
-- Removed the extra `hddtemp' package
-
-* Tue Jan 24 2006 Florian octo Forster <octo@verplant.org> 3.6.2-1
-- New upstream version
-
-* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.1-1
-- New upstream version
-
-* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.0-1
-- New upstream version
-- Added config file, `collectd.conf(5)', `df.so'
-- Added package `collectd-mysql', dependency on `mysqlclient10 | mysql'
-
-* Wed Dec 07 2005 Florian octo Forster <octo@verplant.org> 3.5.0-1
-- New upstream version
-
-* Sat Nov 26 2005 Florian octo Forster <octo@verplant.org> 3.4.0-1
-- New upstream version
-
-* Sat Nov 05 2005 Florian octo Forster <octo@verplant.org> 3.3.0-1
-- New upstream version
-
-* Tue Oct 26 2005 Florian octo Forster <octo@verplant.org> 3.2.0-1
-- New upstream version
-- Added statement to remove the `*.la' files. This fixes a problem when
-  `Unpackaged files terminate build' is in effect.
-- Added `processes.so*' to the main package
-
-* Fri Oct 14 2005 Florian octo Forster <octo@verplant.org> 3.1.0-1
-- New upstream version
-- Added package `collectd-hddtemp'
-
-* Fri Sep 30 2005 Florian octo Forster <octo@verplant.org> 3.0.0-1
-- New upstream version
-- Split the package into `collectd' and `collectd-sensors'
-
-* Fri Sep 16 2005 Florian octo Forster <octo@verplant.org> 2.1.0-1
-- New upstream version
-
-* Mon Sep 10 2005 Florian octo Forster <octo@verplant.org> 2.0.0-1
-- New upstream version
-
-* Mon Aug 29 2005 Florian octo Forster <octo@verplant.org> 1.8.0-1
-- New upstream version
-
-* Sun Aug 25 2005 Florian octo Forster <octo@verplant.org> 1.7.0-1
-- New upstream version
-
-* Sun Aug 21 2005 Florian octo Forster <octo@verplant.org> 1.6.0-1
-- New upstream version
-
-* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5.1-1
-- New upstream version
-
-* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5-1
-- New upstream version
-
-* Mon Jul 11 2005 Florian octo Forster <octo@verplant.org> 1.4.2-1
-- New upstream version
-
-* Sat Jul 09 2005 Florian octo Forster <octo@verplant.org> 1.4-1
-- Built on RedHat 7.3
diff --git a/contrib/fedora/init.d-collectd b/contrib/fedora/init.d-collectd
deleted file mode 100644 (file)
index ea8662a..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/bash
-#
-# collectd    Startup script for the Collectd statistics gathering daemon
-# chkconfig: - 86 15
-# description: Collectd is a statistics gathering daemon used to collect \
-#   system information ie. cpu, memory, disk, network
-# processname: collectd
-# config: /etc/collectd.conf
-# config: /etc/sysconfig/collectd
-# pidfile: /var/run/collectd.pid
-
-# Source function library.
-. /etc/init.d/functions
-
-RETVAL=0
-ARGS=""
-prog="collectd"
-CONFIG=/etc/collectd.conf
-
-if [ -r /etc/default/$prog ]; then
-       . /etc/default/$prog
-fi
-
-start () {
-       echo -n $"Starting $prog: "
-       if [ -r "$CONFIG" ]
-       then
-               daemon /usr/sbin/collectd -C "$CONFIG"
-               RETVAL=$?
-               echo
-               [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
-       fi
-}
-stop () {
-       echo -n $"Stopping $prog: "
-       killproc $prog
-       RETVAL=$?
-       echo
-       [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
-}
-# See how we were called.
-case "$1" in
-  start)
-       start
-       ;;
-  stop)
-       stop
-       ;;
-  status)
-       status $prog
-       ;;
-  restart|reload)
-       stop
-       start
-       ;;
-  condrestart)
-       [ -f /var/lock/subsys/$prog ] && stop && start || :
-       ;;
-  *)
-       echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
-       exit 1
-esac
-
-exit $?
-
-# vim:syntax=sh
index eaf32b3..355c9e3 100644 (file)
 %global _hardened_build 1
 %{?perl_default_filter}
 
-# plugins only buildable on RHEL6
-# (NB: %{elN} macro is not available on RHEL < 6)
-%{?el6:%global _has_libyajl 1}
-%{?el6:%global _has_recent_libpcap 1}
-%{?el6:%global _has_recent_sockios_h 1}
-%{?el6:%global _has_recent_libganglia 1}
-%{?el6:%global _has_working_libiptc 1}
-%{?el6:%global _has_ip_vs_h 1}
-%{?el6:%global _has_lvm2app_h 1}
-%{?el6:%global _has_libmodbus 1}
-%{?el6:%global _has_libudev 1}
-%{?el6:%global _has_iproute 1}
-%{?el6:%global _has_atasmart 1}
-%{?el6:%global _has_hiredis 1}
-%{?el6:%global _has_asm_msr_index 1}
-
-%{?el7:%global _has_libyajl 1}
-%{?el7:%global _has_recent_libpcap 1}
-%{?el7:%global _has_recent_sockios_h 1}
-%{?el7:%global _has_working_libiptc 1}
-%{?el7:%global _has_ip_vs_h 1}
-%{?el7:%global _has_lvm2app_h 1}
-%{?el7:%global _has_libudev 1}
-%{?el7:%global _has_recent_librrd 1}
-%{?el7:%global _has_iproute 1}
-%{?el7:%global _has_atasmart 1}
-%{?el7:%global _has_hiredis 1}
-%{?el7:%global _has_asm_msr_index 1}
-%{?el7:%global _has_libmodbus 1}
-%{?el7:%global _has_xmms 1}
-
 # plugins enabled by default
 %define with_aggregation 0%{!?_without_aggregation:1}
 %define with_amqp 0%{!?_without_amqp:1}
 %define with_ascent 0%{!?_without_ascent:1}
 %define with_battery 0%{!?_without_battery:1}
 %define with_bind 0%{!?_without_bind:1}
-%define with_ceph 0%{!?_without_ceph:0%{?_has_libyajl}}
+%define with_ceph 0%{!?_without_ceph:1}
 %define with_cgroups 0%{!?_without_cgroups:1}
+%define with_chrony 0%{!?_without_chrony:1}
 %define with_conntrack 0%{!?_without_conntrack:1}
 %define with_contextswitch 0%{!?_without_contextswitch:1}
 %define with_cpu 0%{!?_without_cpu:1}
 %define with_cpufreq 0%{!?_without_cpufreq:1}
+%define with_cpusleep 0%{!?_without_cpusleep:1}
 %define with_csv 0%{!?_without_csv:1}
 %define with_curl 0%{!?_without_curl:1}
-%define with_curl_json 0%{!?_without_curl_json:0%{?_has_libyajl}}
+%define with_curl_json 0%{!?_without_curl_json:1}
 %define with_curl_xml 0%{!?_without_curl_xml:1}
 %define with_dbi 0%{!?_without_dbi:1}
 %define with_df 0%{!?_without_df:1}
 %define with_disk 0%{!?_without_disk:1}
-%define with_dns 0%{!?_without_dns:0%{?_has_recent_libpcap}}
+%define with_dns 0%{!?_without_dns:1}
 %define with_drbd 0%{!?_without_drbd:1}
 %define with_email 0%{!?_without_email:1}
 %define with_entropy 0%{!?_without_entropy:1}
-%define with_ethstat 0%{!?_without_ethstat:0%{?_has_recent_sockios_h}}
+%define with_ethstat 0%{!?_without_ethstat:1}
 %define with_exec 0%{!?_without_exec:1}
 %define with_fhcount 0%{!?_without_fhcount:1}
 %define with_filecount 0%{!?_without_filecount:1}
 %define with_fscache 0%{!?_without_fscache:1}
-%define with_gmond 0%{!?_without_gmond:0%{?_has_recent_libganglia}}
+%define with_gmond 0%{!?_without_gmond:1}
+%define with_gps 0%{!?_without_gps:1}
 %define with_hddtemp 0%{!?_without_hddtemp:1}
 %define with_interface 0%{!?_without_interface:1}
 %define with_ipc 0%{!?_without_ipc:1}
 %define with_ipmi 0%{!?_without_ipmi:1}
-%define with_iptables 0%{!?_without_iptables:0%{?_has_working_libiptc}}
-%define with_ipvs 0%{!?_without_ipvs:0%{?_has_ip_vs_h}}
+%define with_iptables 0%{!?_without_iptables:1}
+%define with_ipvs 0%{!?_without_ipvs:1}
 %define with_irq 0%{!?_without_irq:1}
 %define with_java 0%{!?_without_java:1}
-%define with_virt 0%{!?_without_virt:1}
 %define with_load 0%{!?_without_load:1}
+%define with_log_logstash 0%{!?_without_log_logstash:1}
 %define with_logfile 0%{!?_without_logfile:1}
-%define with_log_logstash 0%{!?_without_log_logstash:0%{?_has_libyajl}}
-%define with_lvm 0%{!?_without_lvm:0%{?_has_lvm2app_h}}
+%define with_lvm 0%{!?_without_lvm:1}
 %define with_madwifi 0%{!?_without_madwifi:1}
 %define with_mbmon 0%{!?_without_mbmon:1}
 %define with_md 0%{!?_without_md:1}
 %define with_memcachec 0%{!?_without_memcachec:1}
 %define with_memcached 0%{!?_without_memcached:1}
 %define with_memory 0%{!?_without_memory:1}
+%define with_modbus 0%{!?_without_modbus:1}
+%define with_mqtt 0%{!?_without_mqtt:1}
 %define with_multimeter 0%{!?_without_multimeter:1}
-%define with_modbus 0%{!?_without_modbus:0%{?_has_libmodbus}}
 %define with_mysql 0%{!?_without_mysql:1}
-%define with_netlink 0%{!?_without_netlink:0%{?_has_iproute}}
+%define with_netlink 0%{!?_without_netlink:1}
 %define with_network 0%{!?_without_network:1}
 %define with_nfs 0%{!?_without_nfs:1}
 %define with_nginx 0%{!?_without_nginx:1}
 %define with_notify_desktop 0%{!?_without_notify_desktop:1}
 %define with_notify_email 0%{!?_without_notify_email:1}
+%define with_notify_nagios 0%{!?_without_notify_nagios:1}
 %define with_ntpd 0%{!?_without_ntpd:1}
 %define with_numa 0%{!?_without_numa:1}
 %define with_nut 0%{!?_without_nut:1}
 %define with_processes 0%{!?_without_processes:1}
 %define with_protocols 0%{!?_without_protocols:1}
 %define with_python 0%{!?_without_python:1}
-%define with_redis 0%{!?_without_redis:0%{?_has_hiredis}}
-%define with_rrdcached 0%{!?_without_rrdcached:0%{?_has_recent_librrd}}
+%define with_redis 0%{!?_without_redis:1}
+%define with_rrdcached 0%{!?_without_rrdcached:1}
 %define with_rrdtool 0%{!?_without_rrdtool:1}
 %define with_sensors 0%{!?_without_sensors:1}
 %define with_serial 0%{!?_without_serial:1}
-%define with_smart 0%{!?_without_smart:0%{?_has_atasmart}}
+%define with_smart 0%{!?_without_smart:1}
 %define with_snmp 0%{!?_without_snmp:1}
 %define with_statsd 0%{!?_without_statsd:1}
 %define with_swap 0%{!?_without_swap:1}
 %define with_ted 0%{!?_without_ted:1}
 %define with_thermal 0%{!?_without_thermal:1}
 %define with_threshold 0%{!?_without_threshold:1}
-%define with_turbostat 0%{!?_without_turbostat:0%{?_has_asm_msr_index}}
+%define with_turbostat 0%{!?_without_turbostat:1}
 %define with_unixsock 0%{!?_without_unixsock:1}
 %define with_uptime 0%{!?_without_uptime:1}
 %define with_users 0%{!?_without_users:1}
 %define with_uuid 0%{!?_without_uuid:1}
 %define with_varnish 0%{!?_without_varnish:1}
+%define with_virt 0%{!?_without_virt:1}
 %define with_vmem 0%{!?_without_vmem:1}
 %define with_vserver 0%{!?_without_vserver:1}
 %define with_wireless 0%{!?_without_wireless:1}
 %define with_write_graphite 0%{!?_without_write_graphite:1}
 %define with_write_http 0%{!?_without_write_http:1}
 %define with_write_log 0%{!?_without_write_log:1}
-%define with_write_redis 0%{!?_without_write_redis:0%{?_has_hiredis}}
-%define with_write_riemann 0%{!?_without_write_riemann:1}
+%define with_write_redis 0%{!?_without_write_redis:1}
 %define with_write_sensu 0%{!?_without_write_sensu:1}
 %define with_write_tsdb 0%{!?_without_write_tsdb:1}
 %define with_xmms 0%{!?_without_xmms:0%{?_has_xmms}}
 %define with_aquaero 0%{!?_without_aquaero:0}
 # plugin barometer disabled, requires a libi2c
 %define with_barometer 0%{!?_without_barometer:0}
+# plugin grpc disabled, requires protobuf-compiler >= 3.0
+%define with_grpc 0%{!?_without_grpc:0}
 # plugin lpar disabled, requires AIX
 %define with_lpar 0%{!?_without_lpar:0}
 # plugin mic disabled, requires Mic
 %define with_write_kafka 0%{!?_without_write_kafka:0}
 # plugin write_mongodb disabled, requires libmongoc
 %define with_write_mongodb 0%{!?_without_write_mongodb:0}
-
-Summary:       statistics collection and monitoring daemon
+# plugin write_riemann disabled, requires a new enough riemann_c_client
+%define with_write_riemann 0%{!?_without_write_riemann:0}
+# plugin xencpu disabled, requires xen-devel from non-default repo
+%define with_xencpu 0%{!?_without_xencpu:0}
+# plugin zone disabled, requires Solaris
+%define with_zone 0%{!?_without_zone:0}
+
+# Plugins not buildable on RHEL < 6
+%if 0%{?rhel} && 0%{?rhel} < 6
+%define with_ceph 0
+%define with_curl_json 0
+%define with_log_logstash 0
+%define with_dns 0
+%define with_ethstat 0
+%define with_gmond 0
+%define with_iptables 0
+%define with_ipvs 0
+%define with_lvm 0
+%define with_modbus 0
+%define with_netlink 0
+%define with_redis 0
+%define with_smart 0
+%define with_turbostat 0
+%define with_write_redis 0
+%endif
+
+# Plugins not buildable on RHEL < 7
+%if 0%{?rhel} && 0%{?rhel} < 7
+%define with_cpusleep 0
+%define with_gps 0
+%define with_mqtt 0
+%define with_rrdcached 0
+%define with_xmms 0
+%endif
+
+Summary:       Statistics collection and monitoring daemon
 Name:          collectd
 Version:       5.5.2
 Release:       1%{?dist}
@@ -223,14 +232,12 @@ Source:           https://collectd.org/files/%{name}-%{version}.tar.bz2
 License:       GPLv2
 Group:         System Environment/Daemons
 BuildRoot:     %{_tmppath}/%{name}-%{version}-root
-BuildRequires: libgcrypt-devel, kernel-headers, libtool-ltdl-devel, libcap-devel
+BuildRequires: libgcrypt-devel, kernel-headers, libtool-ltdl-devel, libcap-devel, which
 Vendor:                collectd development team <collectd@verplant.org>
 
-%if 0%{?el7:1}
-Requires(pre):         initscripts
-Requires(post):                systemd
-Requires(preun):       systemd
-Requires(postun):      systemd
+%if 0%{?fedora} || 0%{?rhel} >= 7
+%{?systemd_requires}
+BuildRequires:         systemd
 %else
 Requires(post):                chkconfig
 Requires(preun):       chkconfig, initscripts
@@ -317,6 +324,15 @@ BuildRequires: yajl-devel
 Ceph plugin for collectd
 %endif
 
+%if %{with_chrony}
+%package chrony
+Summary:       Chrony plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+%description chrony
+Chrony plugin for collectd
+%endif
+
 %if %{with_curl}
 %package curl
 Summary:       Curl plugin for collectd
@@ -404,6 +420,26 @@ The gmond plugin subscribes to a Multicast group to receive data from gmond,
 the client daemon of the Ganglia project.
 %endif
 
+%if %{with_gps}
+%package gps
+Summary:       GPS plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: gpsd-devel
+%description gps
+This plugin monitor gps related data through gpsd.
+%endif
+
+%if %{with_grpc}
+%package grpc
+Summary:       GRPC plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: protobuf-compiler
+%description grpc
+This plugin embeds a gRPC server into Collectd.
+%endif
+
 %if %{with_hddtemp}
 %package hddtemp
 Summary:       Hddtemp plugin for collectd
@@ -513,6 +549,16 @@ MySQL querying plugin. This plugin provides data of issued commands, called
 handlers and database traffic.
 %endif
 
+%if %{with_mqtt}
+%package mqtt
+Summary:       mqtt plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: mosquitto-devel
+%description mqtt
+The MQTT plugin publishes and subscribes to MQTT topics.
+%endif
+
 %if %{with_netlink}
 %package netlink
 Summary:       netlink plugin for collectd
@@ -581,10 +627,10 @@ Summary:  Perl plugin for collectd
 Group:         System Environment/Daemons
 Requires:      %{name}%{?_isa} = %{version}-%{release}
 Requires:      perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
-       %if 0%{?rhel} >= 6
-BuildRequires: perl-ExtUtils-Embed
-       %else
+       %if 0%{?rhel} && 0%{?rhel} < 6
 BuildRequires: perl
+       %else
+BuildRequires: perl-ExtUtils-Embed
        %endif
 %description perl
 The Perl plugin embeds a Perl interpreter into collectd and exposes the
@@ -629,10 +675,10 @@ database.
 Summary:       Python plugin for collectd
 Group:         System Environment/Daemons
 Requires:      %{name}%{?_isa} = %{version}-%{release}
-       %if 0%{?rhel} >= 6
-BuildRequires: python-devel
-       %else
+       %if 0%{?rhel} && 0%{?rhel} < 6
 BuildRequires: python26-devel
+       %else
+BuildRequires: python-devel
        %endif
 %description python
 The Python plugin embeds a Python interpreter into collectd and exposes the
@@ -749,7 +795,7 @@ using HTTP POST requests.
 Summary:       Write-kafka plugin for collectd
 Group:         System Environment/Daemons
 Requires:      %{name}%{?_isa} = %{version}-%{release}
-BuildRequires: rdkafka-devel
+BuildRequires: librdkafka-devel
 %description write_kafka
 The write_kafka plugin sends values to kafka, a distributed messaging system.
 %endif
@@ -774,6 +820,16 @@ BuildRequires:     protobuf-c-devel
 The riemann plugin submits values to Riemann, an event stream processor.
 %endif
 
+%if %{with_xencpu}
+%package xencpu
+Summary:       xencpu plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: xen-devel
+%description xencpu
+The xencpu plugin collects CPU statistics from Xen.
+%endif
+
 %if %{with_xmms}
 %package xmms
 Summary:       XMMS plugin for collectd
@@ -904,6 +960,12 @@ Collectd utilities
 %define _with_cgroups --disable-cgroups
 %endif
 
+%if %{with_chrony}
+%define _with_chrony --enable-chrony
+%else
+%define _with_chrony --disable-chrony
+%endif
+
 %if %{with_conntrack}
 %define _with_conntrack --enable-conntrack
 %else
@@ -928,6 +990,12 @@ Collectd utilities
 %define _with_cpufreq --disable-cpufreq
 %endif
 
+%if %{with_cpusleep}
+%define _with_cpusleep --enable-cpusleep
+%else
+%define _with_cpusleep --disable-cpusleep
+%endif
+
 %if %{with_csv}
 %define _with_csv --enable-csv
 %else
@@ -1036,6 +1104,18 @@ Collectd utilities
 %define _with_gmond --disable-gmond
 %endif
 
+%if %{with_gps}
+%define _with_gps --enable-gps
+%else
+%define _with_gps --disable-gps
+%endif
+
+%if %{with_grpc}
+%define _with_grpc --enable-grpc
+%else
+%define _with_grpc --disable-grpc
+%endif
+
 %if %{with_hddtemp}
 %define _with_hddtemp --enable-hddtemp
 %else
@@ -1174,6 +1254,12 @@ Collectd utilities
 %define _with_multimeter --disable-multimeter
 %endif
 
+%if %{with_mqtt}
+%define _with_mqtt --enable-mqtt
+%else
+%define _with_mqtt --disable-mqtt
+%endif
+
 %if %{with_mysql}
 %define _with_mysql --enable-mysql
 %else
@@ -1222,6 +1308,12 @@ Collectd utilities
 %define _with_notify_email --disable-notify_email
 %endif
 
+%if %{with_notify_nagios}
+%define _with_notify_nagios --enable-notify_nagios
+%else
+%define _with_notify_nagios --disable-notify_nagios
+%endif
+
 %if %{with_ntpd}
 %define _with_ntpd --enable-ntpd
 %else
@@ -1319,10 +1411,11 @@ Collectd utilities
 %endif
 
 %if %{with_python}
-       %if 0%{?rhel} >= 6
-%define _with_python --enable-python
-       %else
+       %if 0%{?rhel} && 0%{?rhel} < 6
 %define _with_python --enable-python --with-python=%{_bindir}/python2.6
+%define _python_config PYTHON_CONFIG="%{_bindir}/python2.6-config"
+       %else
+%define _with_python --enable-python
        %endif
 %else
 %define _with_python --disable-python
@@ -1568,6 +1661,12 @@ Collectd utilities
 %define _with_write_tsdb --disable-write_tsdb
 %endif
 
+%if %{with_xencpu}
+%define _with_xencpu --enable-xencpu
+%else
+%define _with_xencpu --disable-xencpu
+%endif
+
 %if %{with_xmms}
 %define _with_xmms --enable-xmms
 %else
@@ -1580,6 +1679,12 @@ Collectd utilities
 %define _with_zfs_arc --disable-zfs_arc
 %endif
 
+%if %{with_zone}
+%define _with_zone --enable-zone
+%else
+%define _with_zone --disable-zone
+%endif
+
 %if %{with_zookeeper}
 %define _with_zookeeper --enable-zookeeper
 %else
@@ -1587,6 +1692,7 @@ Collectd utilities
 %endif
 
 %configure CFLAGS="%{optflags} -DLT_LAZY_OR_NOW=\"RTLD_LAZY|RTLD_GLOBAL\"" \
+       %{?_python_config} \
        --disable-static \
        --without-included-ltdl \
        --enable-all-plugins=yes \
@@ -1612,14 +1718,16 @@ Collectd utilities
        %{?_with_bind} \
        %{?_with_ceph} \
        %{?_with_cgroups} \
+       %{?_with_chrony} \
        %{?_with_conntrack} \
        %{?_with_contextswitch} \
-       %{?_with_cpu} \
        %{?_with_cpufreq} \
+       %{?_with_cpusleep} \
+       %{?_with_cpu} \
        %{?_with_csv} \
-       %{?_with_curl} \
        %{?_with_curl_json} \
        %{?_with_curl_xml} \
+       %{?_with_curl} \
        %{?_with_dbi} \
        %{?_with_df} \
        %{?_with_disk} \
@@ -1633,98 +1741,104 @@ Collectd utilities
        %{?_with_filecount} \
        %{?_with_fscache} \
        %{?_with_gmond} \
+       %{?_with_gps} \
+       %{?_with_grpc} \
        %{?_with_hddtemp} \
        %{?_with_interface} \
        %{?_with_ipc} \
        %{?_with_ipmi} \
        %{?_with_iptables} \
        %{?_with_ipvs} \
+       %{?_with_irq} \
        %{?_with_java} \
-       %{?_with_virt} \
+       %{?_with_load} \
        %{?_with_log_logstash} \
+       %{?_with_logfile} \
        %{?_with_lpar} \
        %{?_with_lvm} \
+       %{?_with_madwifi} \
+       %{?_with_mbmon} \
+       %{?_with_md} \
        %{?_with_memcachec} \
+       %{?_with_memcached} \
+       %{?_with_memory} \
        %{?_with_mic} \
        %{?_with_modbus} \
+       %{?_with_mqtt} \
        %{?_with_multimeter} \
        %{?_with_mysql} \
        %{?_with_netapp} \
        %{?_with_netlink} \
+       %{?_with_network} \
+       %{?_with_nfs} \
        %{?_with_nginx} \
        %{?_with_notify_desktop} \
        %{?_with_notify_email} \
+       %{?_with_notify_nagios} \
+       %{?_with_ntpd} \
+       %{?_with_numa} \
        %{?_with_nut} \
+       %{?_with_olsrd} \
        %{?_with_onewire} \
        %{?_with_openldap} \
+       %{?_with_openvpn} \
        %{?_with_oracle} \
        %{?_with_perl} \
        %{?_with_pf} \
        %{?_with_pinba} \
        %{?_with_ping} \
        %{?_with_postgresql} \
+       %{?_with_powerdns} \
+       %{?_with_processes} \
+       %{?_with_protocols} \
        %{?_with_python} \
        %{?_with_redis} \
        %{?_with_routeros} \
        %{?_with_rrdcached} \
        %{?_with_rrdtool} \
        %{?_with_sensors} \
+       %{?_with_serial} \
        %{?_with_sigrok} \
        %{?_with_smart} \
        %{?_with_snmp} \
-       %{?_with_tape} \
-       %{?_with_tokyotyrant} \
-       %{?_with_varnish} \
-       %{?_with_write_http} \
-       %{?_with_write_kafka} \
-       %{?_with_write_mongodb} \
-       %{?_with_write_redis} \
-       %{?_with_xmms} \
-       %{?_with_zfs_arc} \
-       %{?_with_zookeeper} \
-       %{?_with_irq} \
-       %{?_with_load} \
-       %{?_with_logfile} \
-       %{?_with_madwifi} \
-       %{?_with_mbmon} \
-       %{?_with_md} \
-       %{?_with_memcached} \
-       %{?_with_memory} \
-       %{?_with_network} \
-       %{?_with_nfs} \
-       %{?_with_ntpd} \
-       %{?_with_numa} \
-       %{?_with_olsrd} \
-       %{?_with_openvpn} \
-       %{?_with_powerdns} \
-       %{?_with_processes} \
-       %{?_with_protocols} \
-       %{?_with_serial} \
        %{?_with_statsd} \
        %{?_with_swap} \
        %{?_with_syslog} \
        %{?_with_table} \
-       %{?_with_tail} \
        %{?_with_tail_csv} \
+       %{?_with_tail} \
+       %{?_with_tape} \
        %{?_with_tcpconns} \
        %{?_with_teamspeak2} \
        %{?_with_ted} \
        %{?_with_thermal} \
        %{?_with_threshold} \
+       %{?_with_tokyotyrant} \
        %{?_with_turbostat} \
        %{?_with_unixsock} \
        %{?_with_uptime} \
        %{?_with_users} \
        %{?_with_uuid} \
+       %{?_with_varnish} \
+       %{?_with_virt} \
        %{?_with_vmem} \
        %{?_with_vserver} \
        %{?_with_wireless}\
        %{?_with_write_graphite} \
        %{?_with_write_http} \
+       %{?_with_write_http} \
+       %{?_with_write_kafka} \
        %{?_with_write_log} \
+       %{?_with_write_mongodb} \
+       %{?_with_write_redis} \
        %{?_with_write_riemann} \
        %{?_with_write_sensu} \
-       %{?_with_write_tsdb}
+       %{?_with_write_tsdb} \
+       %{?_with_xencpu} \
+       %{?_with_xmms} \
+       %{?_with_zfs_arc} \
+       %{?_with_zone} \
+       %{?_with_zookeeper}
 
 
 %{__make} %{?_smp_mflags}
@@ -1733,7 +1847,7 @@ Collectd utilities
 %install
 rm -rf %{buildroot}
 %{__make} install DESTDIR=%{buildroot}
-%if 0%{?el7:1}
+%if 0%{?fedora} || 0%{?rhel} >= 7
 %{__install} -Dp -m0644 contrib/systemd.collectd.service %{buildroot}%{_unitdir}/collectd.service
 %else
 %{__install} -Dp -m0755 contrib/redhat/init.d-collectd %{buildroot}%{_initrddir}/collectd
@@ -1789,26 +1903,15 @@ rm -f %{buildroot}%{_mandir}/man5/collectd-snmp.5*
 %clean
 rm -rf %{buildroot}
 
-%pre
-%if 0%{?el7:1}
-# stop sysv-based instance before upgrading to systemd
-if [ $1 -eq 2 ] && [ -f /var/lock/subsys/collectd ]; then
-       SYSTEMCTL_SKIP_REDIRECT=1 %{_initddir}/collectd stop >/dev/null 2>&1 || :
-fi
-%endif
-
 %post
-%if 0%{?el7:1}
-if [ $1 -eq 2 ]; then
-       /usr/bin/systemctl daemon-reload >/dev/null 2>&1 || :
-fi
+%if 0%{?fedora} || 0%{?rhel} >= 7
 %systemd_post collectd.service
 %else
 /sbin/chkconfig --add collectd || :
 %endif
 
 %preun
-%if 0%{?el7:1}
+%if 0%{?fedora} || 0%{?rhel} >= 7
 %systemd_preun collectd.service
 %else
 # stop collectd only when uninstalling
@@ -1819,7 +1922,7 @@ fi
 %endif
 
 %postun
-%if 0%{?el7:1}
+%if 0%{?fedora} || 0%{?rhel} >= 7
 %systemd_postun_with_restart collectd.service
 %else
 # restart collectd only when upgrading
@@ -1835,7 +1938,7 @@ fi
 %files
 %doc AUTHORS COPYING ChangeLog README
 %config(noreplace) %{_sysconfdir}/collectd.conf
-%if 0%{?el7:1}
+%if 0%{?fedora} || 0%{?rhel} >= 7
 %{_unitdir}/collectd.service
 %else
 %{_initrddir}/collectd
@@ -1889,6 +1992,9 @@ fi
 %if %{with_cpufreq}
 %{_libdir}/%{name}/cpufreq.so
 %endif
+%if %{with_cpusleep}
+%{_libdir}/%{name}/cpusleep.so
+%endif
 %if %{with_csv}
 %{_libdir}/%{name}/csv.so
 %endif
@@ -1958,6 +2064,9 @@ fi
 %if %{with_nfs}
 %{_libdir}/%{name}/nfs.so
 %endif
+%if %{with_notify_nagios}
+%{_libdir}/%{name}/notify_nagios.so
+%endif
 %if %{with_ntpd}
 %{_libdir}/%{name}/ntpd.so
 %endif
@@ -2112,6 +2221,11 @@ fi
 %{_libdir}/%{name}/ceph.so
 %endif
 
+%if %{with_chrony}
+%files chrony
+%{_libdir}/%{name}/chrony.so
+%endif
+
 %if %{with_curl}
 %files curl
 %{_libdir}/%{name}/curl.so
@@ -2152,6 +2266,16 @@ fi
 %{_libdir}/%{name}/gmond.so
 %endif
 
+%if %{with_gps}
+%files gps
+%{_libdir}/%{name}/gps.so
+%endif
+
+%if %{with_grpc}
+%files grpc
+%{_libdir}/%{name}/grpc.so
+%endif
+
 %if %{with_hddtemp}
 %files hddtemp
 %{_libdir}/%{name}/hddtemp.so
@@ -2205,6 +2329,11 @@ fi
 %{_libdir}/%{name}/modbus.so
 %endif
 
+%if %{with_mqtt}
+%files mqtt
+%{_libdir}/%{name}/mqtt.so
+%endif
+
 %if %{with_mysql}
 %files mysql
 %{_libdir}/%{name}/mysql.so
@@ -2332,6 +2461,11 @@ fi
 %{_libdir}/%{name}/write_riemann.so
 %endif
 
+%if %{with_xencpu}
+%files xencpu
+%{_libdir}/%{name}/xencpu.so
+%endif
+
 %if %{with_xmms}
 %files xmms
 %{_libdir}/%{name}/xmms.so
index c7806fe..d0f1bde 100644 (file)
@@ -1,7 +1,8 @@
 [Unit]
-Description=Collectd
-After=local-fs.target network.target
-Requires=local-fs.target network.target
+Description=Collectd statistics daemon
+Documentation=man:collectd(1) man:collectd.conf(5)
+After=local-fs.target network-online.target
+Requires=local-fs.target network-online.target
 
 [Service]
 ExecStart=/usr/sbin/collectd
@@ -33,7 +34,7 @@ NoNewPrivileges=true
 # socket once the daemon is ready. See systemd.service(5) for more details.
 Type=notify
 
-# Restart the collectd daemon after a 10 seconds delay, in case it crashes.
+# Restart the collectd daemon when it fails.
 Restart=on-failure
 
 [Install]
diff --git a/proto/Makefile.am b/proto/Makefile.am
new file mode 100644 (file)
index 0000000..3c0bfd7
--- /dev/null
@@ -0,0 +1 @@
+EXTRA_DIST = collectd.proto types.proto
diff --git a/proto/collectd.proto b/proto/collectd.proto
new file mode 100644 (file)
index 0000000..5134dbf
--- /dev/null
@@ -0,0 +1,59 @@
+// collectd - proto/collectd.proto
+// Copyright (C) 2015-2016 Sebastian Harl
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// Authors:
+//   Sebastian Harl <sh at tokkee.org>
+
+syntax = "proto3";
+
+package collectd;
+
+import "types.proto";
+
+service Collectd {
+       // Dispatch collected values to collectd.
+       rpc DispatchValues(DispatchValuesRequest) returns (DispatchValuesReply);
+
+       // Query a list of values available from collectd's value cache.
+       rpc QueryValues(QueryValuesRequest) returns (QueryValuesReply);
+}
+
+// The arguments to DispatchValues.
+message DispatchValuesRequest {
+       collectd.types.ValueList values = 1;
+}
+
+// The response from DispatchValues.
+message DispatchValuesReply {
+}
+
+// The arguments to QueryValues.
+message QueryValuesRequest {
+       // Query by the fields of the identifier. Only return values matching the
+       // specified shell wildcard patterns (see fnmatch(3)). Use '*' to match
+       // any value.
+       collectd.types.Identifier identifier = 1;
+}
+
+// The response from QueryValues.
+message QueryValuesReply {
+       repeated collectd.types.ValueList values = 1;
+}
diff --git a/proto/types.proto b/proto/types.proto
new file mode 100644 (file)
index 0000000..4a852e4
--- /dev/null
@@ -0,0 +1,56 @@
+// collectd - proto/types.proto
+// Copyright (C) 2015-2016 Sebastian Harl
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// Authors:
+//   Sebastian Harl <sh at tokkee.org>
+
+syntax = "proto3";
+
+package collectd.types;
+
+import "google/protobuf/duration.proto";
+import "google/protobuf/timestamp.proto";
+
+message Identifier {
+       string host = 1;
+       string plugin = 2;
+       string plugin_instance = 3;
+       string type = 4;
+       string type_instance = 5;
+}
+
+message Value {
+       oneof value {
+               uint64 counter = 1;
+               double gauge = 2;
+               int64 derive = 3;
+               uint64 absolute = 4;
+       };
+}
+
+message ValueList {
+       repeated Value value = 1;
+
+       google.protobuf.Timestamp time = 2;
+       google.protobuf.Duration interval = 3;
+
+       Identifier identifier = 4;
+}
index dc07cb7..12c7730 100644 (file)
@@ -6,10 +6,6 @@ SUBDIRS += daemon
 
 PLUGIN_LDFLAGS = -module -avoid-version -export-symbols-regex '\<module_register\>'
 
-if COMPILER_IS_GCC
-AM_CFLAGS = -Wall -Werror
-endif
-
 AM_CPPFLAGS = -I$(srcdir)/daemon
 AM_CPPFLAGS += -DPREFIX='"${prefix}"'
 AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
@@ -21,25 +17,69 @@ endif
 AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"'
 AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
 
-AUTOMAKE_OPTIONS = subdir-objects
-
-noinst_LTLIBRARIES = libmount.la liblookup.la
+LOG_COMPILER = env VALGRIND="@VALGRIND@" $(abs_top_srcdir)/testwrapper.sh
+
+V_PROTOC = $(v_protoc_@AM_V@)
+v_protoc_ = $(v_protoc_@AM_DEFAULT_V@)
+v_protoc_0 = @echo "  PROTOC  " $@;
+
+noinst_LTLIBRARIES =
+check_PROGRAMS =
+TESTS =
+
+noinst_LTLIBRARIES += libformat_json.la
+libformat_json_la_SOURCES   = utils_format_json.c utils_format_json.h
+libformat_json_la_CPPFLAGS  = $(AM_CPPFLAGS)
+libformat_json_la_LDFLAGS   = $(AM_LDFLAGS)
+libformat_json_la_LIBADD    =
+if BUILD_WITH_LIBYAJL
+libformat_json_la_CPPFLAGS += $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+libformat_json_la_LDFLAGS  += $(BUILD_WITH_LIBYAJL_LDFLAGS)
+libformat_json_la_LIBADD   += $(BUILD_WITH_LIBYAJL_LIBS)
+check_PROGRAMS += test_format_json
+TESTS += test_format_json
+test_format_json_SOURCES = utils_format_json_test.c testing.h
+test_format_json_LDADD = libformat_json.la daemon/libmetadata.la daemon/libplugin_mock.la -lm
+endif
+
+noinst_LTLIBRARIES += liblatency.la
+liblatency_la_SOURCES = utils_latency.c utils_latency.h
+check_PROGRAMS += test_utils_latency
+TESTS += test_utils_latency
+test_utils_latency_SOURCES = utils_latency_test.c testing.h
+test_utils_latency_LDADD = liblatency.la daemon/libplugin_mock.la -lm
+
+noinst_LTLIBRARIES += liblookup.la
+liblookup_la_SOURCES = utils_vl_lookup.c utils_vl_lookup.h
+liblookup_la_LIBADD = daemon/libavltree.la
+check_PROGRAMS += test_utils_vl_lookup
+TESTS += test_utils_vl_lookup
+test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h
+test_utils_vl_lookup_LDADD = liblookup.la daemon/libplugin_mock.la
+if BUILD_WITH_LIBKSTAT
+test_utils_vl_lookup_LDADD += -lkstat
+endif
 
+noinst_LTLIBRARIES += libmount.la
 libmount_la_SOURCES = utils_mount.c utils_mount.h
-libmount_la_LIBADD = daemon/libcommon.la
-
-liblookup_la_SOURCES = utils_vl_lookup.c utils_vl_lookup.h
-liblookup_la_LIBADD = daemon/libavltree.la daemon/libcommon.la
+check_PROGRAMS += test_utils_mount
+TESTS += test_utils_mount
+test_utils_mount_SOURCES = utils_mount_test.c testing.h
+test_utils_mount_LDADD = libmount.la daemon/libplugin_mock.la
+if BUILD_WITH_LIBKSTAT
+test_utils_mount_LDADD += -lkstat
+endif
 
 sbin_PROGRAMS = collectdmon
 bin_PROGRAMS = collectd-nagios collectdctl collectd-tg
 
 collectdmon_SOURCES = collectdmon.c
-collectdmon_CPPFLAGS = $(AM_CPPFLAGS)
 
 collectd_nagios_SOURCES = collectd-nagios.c
-collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
-collectd_nagios_LDADD =
+collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) \
+       -I$(top_srcdir)/src/libcollectdclient/collectd \
+       -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_nagios_LDADD = libcollectdclient/libcollectdclient.la
 if BUILD_WITH_LIBSOCKET
 collectd_nagios_LDADD += -lsocket
 endif
@@ -47,26 +87,28 @@ if BUILD_AIX
 collectd_nagios_LDADD += -lm
 endif
 
-collectd_nagios_LDADD += libcollectdclient/libcollectdclient.la
-collectd_nagios_DEPENDENCIES = libcollectdclient/libcollectdclient.la
-
 
 collectdctl_SOURCES = collectdctl.c
-collectdctl_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
-collectdctl_LDADD =
+collectdctl_CPPFLAGS = $(AM_CPPFLAGS) \
+       -I$(top_srcdir)/src/libcollectdclient/collectd \
+       -I$(top_builddir)/src/libcollectdclient/collectd
+collectdctl_LDADD = libcollectdclient/libcollectdclient.la
 if BUILD_WITH_LIBSOCKET
 collectdctl_LDADD += -lsocket
 endif
 if BUILD_AIX
 collectdctl_LDADD += -lm
 endif
-collectdctl_LDADD += libcollectdclient/libcollectdclient.la
-collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la
+
 
 collectd_tg_SOURCES = collectd-tg.c
 collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) \
-                      -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
-collectd_tg_LDADD = daemon/libheap.la
+       -I$(top_srcdir)/src/libcollectdclient/collectd \
+       -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_tg_LDADD = \
+       $(PTHREAD_LIBS) \
+       daemon/libheap.la \
+       libcollectdclient/libcollectdclient.la
 if BUILD_WITH_LIBSOCKET
 collectd_tg_LDADD += -lsocket
 endif
@@ -76,11 +118,6 @@ endif
 if BUILD_AIX
 collectd_tg_LDADD += -lm
 endif
-if BUILD_WITH_LIBPTHREAD
-collectd_tg_LDADD += -lpthread
-endif
-collectd_tg_LDADD += libcollectdclient/libcollectdclient.la
-collectd_tg_DEPENDENCIES = libcollectdclient/libcollectdclient.la
 
 
 pkglib_LTLIBRARIES =
@@ -88,6 +125,24 @@ pkglib_LTLIBRARIES =
 BUILT_SOURCES =
 CLEANFILES =
 
+if HAVE_PROTOC3
+if HAVE_GRPC_CPP
+BUILT_SOURCES += collectd.grpc.pb.cc collectd.pb.cc types.pb.cc
+CLEANFILES += collectd.grpc.pb.cc collectd.pb.cc types.pb.cc \
+               collectd.grpc.pb.h collectd.pb.h types.pb.h
+
+collectd.grpc.pb.cc: $(top_srcdir)/proto/collectd.proto $(top_srcdir)/proto/types.proto
+       $(V_PROTOC)@PROTOC@ -I$(top_srcdir)/proto \
+               --grpc_out=$(builddir) --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN) $<
+
+collectd.pb.cc: $(top_srcdir)/proto/collectd.proto $(top_srcdir)/proto/types.proto
+       $(V_PROTOC)@PROTOC@ -I$(top_srcdir)/proto --cpp_out=$(builddir) $<
+
+types.pb.cc: $(top_srcdir)/proto/types.proto
+       $(V_PROTOC)@PROTOC@ -I$(top_srcdir)/proto --cpp_out=$(builddir) $<
+endif
+endif
+
 if BUILD_PLUGIN_AGGREGATION
 pkglib_LTLIBRARIES += aggregation.la
 aggregation_la_SOURCES = aggregation.c \
@@ -100,24 +155,19 @@ if BUILD_PLUGIN_AMQP
 pkglib_LTLIBRARIES += amqp.la
 amqp_la_SOURCES = amqp.c \
                  utils_cmd_putval.c utils_cmd_putval.h \
-                 utils_parse_option.c utils_parse_option.h \
-                 utils_format_graphite.c utils_format_graphite.h \
-                 utils_format_json.c utils_format_json.h
+                 utils_parse_option.c utils_parse_option.h \
+                 utils_format_graphite.c utils_format_graphite.h
 amqp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRABBITMQ_LDFLAGS)
 amqp_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRABBITMQ_CPPFLAGS)
-amqp_la_LIBADD = $(BUILD_WITH_LIBRABBITMQ_LIBS)
+amqp_la_LIBADD = $(BUILD_WITH_LIBRABBITMQ_LIBS) libformat_json.la
 endif
 
 if BUILD_PLUGIN_APACHE
 pkglib_LTLIBRARIES += apache.la
 apache_la_SOURCES = apache.c
 apache_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-apache_la_CFLAGS = $(AM_CFLAGS)
-apache_la_LIBADD =
-if BUILD_WITH_LIBCURL
-apache_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-apache_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+apache_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
+apache_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS)
 endif
 
 if BUILD_PLUGIN_APCUPS
@@ -133,16 +183,15 @@ endif
 if BUILD_PLUGIN_APPLE_SENSORS
 pkglib_LTLIBRARIES += apple_sensors.la
 apple_sensors_la_SOURCES = apple_sensors.c
-apple_sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-apple_sensors_la_LDFLAGS += -framework IOKit
+apple_sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS) -framework IOKit
 endif
 
 if BUILD_PLUGIN_AQUAERO
 pkglib_LTLIBRARIES += aquaero.la
 aquaero_la_SOURCES = aquaero.c
-aquaero_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 aquaero_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBAQUAERO5_CFLAGS)
-aquaero_la_LIBADD = $(BUILD_WITH_LIBAQUAERO5_LDFLAGS) -laquaero5
+aquaero_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBAQUAERO5_LDFLAGS)
+aquaero_la_LIBADD = -laquaero5
 endif
 
 if BUILD_PLUGIN_ASCENT
@@ -165,7 +214,6 @@ if BUILD_PLUGIN_BATTERY
 pkglib_LTLIBRARIES += battery.la
 battery_la_SOURCES = battery.c
 battery_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-battery_la_LIBADD =
 if BUILD_WITH_LIBIOKIT
 battery_la_LDFLAGS += -framework IOKit
 endif
@@ -196,6 +244,12 @@ cgroups_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 cgroups_la_LIBADD = libmount.la
 endif
 
+if BUILD_PLUGIN_CHRONY
+pkglib_LTLIBRARIES += chrony.la
+chrony_la_SOURCES = chrony.c
+chrony_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
 if BUILD_PLUGIN_CONNTRACK
 pkglib_LTLIBRARIES += conntrack.la
 conntrack_la_SOURCES = conntrack.c
@@ -239,6 +293,12 @@ cpufreq_la_SOURCES = cpufreq.c
 cpufreq_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 endif
 
+if BUILD_PLUGIN_CPUSLEEP
+pkglib_LTLIBRARIES += cpusleep.la
+cpusleep_la_SOURCES = cpusleep.c
+cpusleep_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
 if BUILD_PLUGIN_CSV
 pkglib_LTLIBRARIES += csv.la
 csv_la_SOURCES = csv.c
@@ -247,32 +307,27 @@ endif
 
 if BUILD_PLUGIN_CURL
 pkglib_LTLIBRARIES += curl.la
-curl_la_SOURCES = curl.c
+curl_la_SOURCES = curl.c \
+                 utils_curl_stats.c utils_curl_stats.h
 curl_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-curl_la_CFLAGS = $(AM_CFLAGS)
-curl_la_LIBADD =
-if BUILD_WITH_LIBCURL
-curl_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-curl_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+curl_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
+curl_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS)
 endif
 
 if BUILD_PLUGIN_CURL_JSON
 pkglib_LTLIBRARIES += curl_json.la
-curl_json_la_SOURCES = curl_json.c
-curl_json_la_CFLAGS = $(AM_CFLAGS)
-curl_json_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+curl_json_la_SOURCES = curl_json.c \
+                 utils_curl_stats.c utils_curl_stats.h
+curl_json_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
 curl_json_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
-curl_json_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
-if BUILD_WITH_LIBCURL
-curl_json_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-curl_json_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+curl_json_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+curl_json_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBYAJL_LIBS)
 endif
 
 if BUILD_PLUGIN_CURL_XML
 pkglib_LTLIBRARIES += curl_xml.la
-curl_xml_la_SOURCES = curl_xml.c
+curl_xml_la_SOURCES = curl_xml.c \
+                 utils_curl_stats.c utils_curl_stats.h
 curl_xml_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 curl_xml_la_CFLAGS = $(AM_CFLAGS) \
                $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
@@ -319,6 +374,9 @@ disk_la_CFLAGS += $(BUILD_WITH_LIBUDEV_CFLAGS)
 disk_la_LDFLAGS += $(BUILD_WITH_LIBUDEV_LDFLAGS)
 disk_la_LIBADD += $(BUILD_WITH_LIBUDEV_LIBS)
 endif
+if BUILD_FREEBSD
+disk_la_LIBADD += -ldevstat -lgeom
+endif
 if BUILD_WITH_PERFSTAT
 disk_la_LIBADD += -lperfstat
 endif
@@ -328,21 +386,19 @@ if BUILD_PLUGIN_DNS
 pkglib_LTLIBRARIES += dns.la
 dns_la_SOURCES = dns.c utils_dns.c utils_dns.h
 dns_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-dns_la_LIBADD = -lpcap -lpthread
+dns_la_LIBADD = -lpcap
 endif
 
 if BUILD_PLUGIN_DRBD
 pkglib_LTLIBRARIES += drbd.la
 drbd_la_SOURCES = drbd.c
 drbd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-drbd_la_LIBADD = -lpthread
 endif
 
 if BUILD_PLUGIN_EMAIL
 pkglib_LTLIBRARIES += email.la
 email_la_SOURCES = email.c
 email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-email_la_LIBADD = -lpthread
 endif
 
 if BUILD_PLUGIN_ENTROPY
@@ -358,7 +414,6 @@ exec_la_SOURCES = exec.c \
                  utils_cmd_putval.c utils_cmd_putval.h \
                  utils_parse_option.h utils_parse_option.c
 exec_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-exec_la_LIBADD = -lpthread
 endif
 
 if BUILD_PLUGIN_ETHSTAT
@@ -387,6 +442,23 @@ gmond_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(GANGLIA_LDFLAGS)
 gmond_la_LIBADD = $(GANGLIA_LIBS)
 endif
 
+if BUILD_PLUGIN_GPS
+pkglib_LTLIBRARIES += gps.la
+gps_la_SOURCES = gps.c
+gps_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBGPS_CFLAGS)
+gps_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBGPS_LDFLAGS)
+gps_la_LIBADD = -lpthread $(BUILD_WITH_LIBGPS_LIBS)
+endif
+
+if BUILD_PLUGIN_GRPC
+pkglib_LTLIBRARIES += grpc.la
+grpc_la_SOURCES = grpc.cc
+nodist_grpc_la_SOURCES = collectd.grpc.pb.cc collectd.pb.cc types.pb.cc
+grpc_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBGRPCPP_CPPFLAGS) $(BUILD_WITH_LIBPROTOBUF_CPPFLAGS)
+grpc_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBGRPCPP_LDFLAGS) $(BUILD_WITH_LIBPROTOBUF_LDFLAGS)
+grpc_la_LIBADD = $(BUILD_WITH_LIBGRPCPP_LIBS) $(BUILD_WITH_LIBPROTOBUF_LIBS)
+endif
+
 if BUILD_PLUGIN_HDDTEMP
 pkglib_LTLIBRARIES += hddtemp.la
 hddtemp_la_SOURCES = hddtemp.c
@@ -422,7 +494,6 @@ endif # BUILD_PLUGIN_INTERFACE
 if BUILD_PLUGIN_IPC
 pkglib_LTLIBRARIES += ipc.la
 ipc_la_SOURCES = ipc.c
-ipc_la_CFLAGS = $(AM_CFLAGS)
 ipc_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 endif
 
@@ -445,8 +516,9 @@ endif
 if BUILD_PLUGIN_IPVS
 pkglib_LTLIBRARIES += ipvs.la
 ipvs_la_SOURCES = ipvs.c
+ipvs_la_CFLAGS = $(AM_CFLAGS)
 if IP_VS_H_NEEDS_KERNEL_CFLAGS
-ipvs_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
+ipvs_la_CFLAGS += $(KERNEL_CFLAGS)
 endif
 ipvs_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 endif
@@ -490,7 +562,6 @@ endif
 if BUILD_PLUGIN_LOG_LOGSTASH
 pkglib_LTLIBRARIES += log_logstash.la
 log_logstash_la_SOURCES = log_logstash.c
-log_logstash_la_CFLAGS = $(AM_CFLAGS)
 log_logstash_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
 log_logstash_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
 log_logstash_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
@@ -506,7 +577,8 @@ endif
 if BUILD_PLUGIN_LVM
 pkglib_LTLIBRARIES += lvm.la
 lvm_la_SOURCES = lvm.c
-lvm_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+lvm_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBLVM2APP_CPPFLAGS)
+lvm_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBLVM2APP_LDFLAGS)
 lvm_la_LIBADD = $(BUILD_WITH_LIBLVM2APP_LIBS)
 endif
 
@@ -617,6 +689,14 @@ modbus_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMODBUS_CFLAGS)
 modbus_la_LIBADD = $(BUILD_WITH_LIBMODBUS_LIBS)
 endif
 
+if BUILD_PLUGIN_MQTT
+pkglib_LTLIBRARIES += mqtt.la
+mqtt_la_SOURCES = mqtt.c
+mqtt_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMOSQUITTO_CPPFLAGS)
+mqtt_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBMOSQUITTO_LDFLAGS)
+mqtt_la_LIBADD = $(BUILD_WITH_LIBMOSQUITTO_LIBS)
+endif
+
 if BUILD_PLUGIN_MULTIMETER
 pkglib_LTLIBRARIES += multimeter.la
 multimeter_la_SOURCES = multimeter.c
@@ -626,13 +706,9 @@ endif
 if BUILD_PLUGIN_MYSQL
 pkglib_LTLIBRARIES += mysql.la
 mysql_la_SOURCES = mysql.c
+mysql_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMYSQL_CFLAGS)
 mysql_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-mysql_la_CFLAGS = $(AM_CFLAGS)
-mysql_la_LIBADD =
-if BUILD_WITH_LIBMYSQL
-mysql_la_CFLAGS += $(BUILD_WITH_LIBMYSQL_CFLAGS)
-mysql_la_LIBADD += $(BUILD_WITH_LIBMYSQL_LIBS)
-endif
+mysql_la_LIBADD = $(BUILD_WITH_LIBMYSQL_LIBS)
 endif
 
 if BUILD_PLUGIN_NETAPP
@@ -657,7 +733,7 @@ network_la_SOURCES = network.c network.h \
                     utils_fbhash.c utils_fbhash.h
 network_la_CPPFLAGS = $(AM_CPPFLAGS)
 network_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-network_la_LIBADD = -lpthread
+network_la_LIBADD =
 if BUILD_WITH_LIBSOCKET
 network_la_LIBADD += -lsocket
 endif
@@ -683,13 +759,9 @@ endif
 if BUILD_PLUGIN_NGINX
 pkglib_LTLIBRARIES += nginx.la
 nginx_la_SOURCES = nginx.c
-nginx_la_CFLAGS = $(AM_CFLAGS)
-nginx_la_LIBADD =
+nginx_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
 nginx_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-if BUILD_WITH_LIBCURL
-nginx_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-nginx_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+nginx_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS)
 endif
 
 if BUILD_PLUGIN_NOTIFY_DESKTOP
@@ -704,7 +776,13 @@ if BUILD_PLUGIN_NOTIFY_EMAIL
 pkglib_LTLIBRARIES += notify_email.la
 notify_email_la_SOURCES = notify_email.c
 notify_email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-notify_email_la_LIBADD = -lesmtp -lssl -lcrypto -lpthread
+notify_email_la_LIBADD = -lesmtp -lssl -lcrypto
+endif
+
+if BUILD_PLUGIN_NOTIFY_NAGIOS
+pkglib_LTLIBRARIES += notify_nagios.la
+notify_nagios_la_SOURCES = notify_nagios.c
+notify_nagios_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 endif
 
 if BUILD_PLUGIN_NTPD
@@ -728,7 +806,7 @@ pkglib_LTLIBRARIES += nut.la
 nut_la_SOURCES = nut.c
 nut_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBUPSCLIENT_CFLAGS)
 nut_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-nut_la_LIBADD = -lpthread $(BUILD_WITH_LIBUPSCLIENT_LIBS)
+nut_la_LIBADD = $(BUILD_WITH_LIBUPSCLIENT_LIBS)
 endif
 
 if BUILD_PLUGIN_OLSRD
@@ -744,24 +822,22 @@ endif
 if BUILD_PLUGIN_ONEWIRE
 pkglib_LTLIBRARIES += onewire.la
 onewire_la_SOURCES = onewire.c
-onewire_la_CFLAGS = $(AM_CFLAGS)
 onewire_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
 onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS)
-onewire_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+onewire_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBOWCAPI_LDFLAGS)
 endif
 
 if BUILD_PLUGIN_OPENLDAP
 pkglib_LTLIBRARIES += openldap.la
 openldap_la_SOURCES = openldap.c
-openldap_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBLDAP_LDFLAGS)
-openldap_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBLDAP_CPPFLAGS)
+openldap_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBLDAP_CPPFLAGS)
+openldap_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBLDAP_LDFLAGS)
 openldap_la_LIBADD = -lldap
 endif
 
 if BUILD_PLUGIN_OPENVPN
 pkglib_LTLIBRARIES += openvpn.la
 openvpn_la_SOURCES = openvpn.c
-openvpn_la_CFLAGS = $(AM_CFLAGS)
 openvpn_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 endif
 
@@ -769,8 +845,7 @@ if BUILD_PLUGIN_ORACLE
 pkglib_LTLIBRARIES += oracle.la
 oracle_la_SOURCES = oracle.c \
        utils_db_query.c utils_db_query.h
-oracle_la_CFLAGS = $(AM_CFLAGS)
-oracle_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_ORACLE_CFLAGS)
+oracle_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_ORACLE_CPPFLAGS)
 oracle_la_LIBADD = $(BUILD_WITH_ORACLE_LIBS)
 oracle_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 endif
@@ -781,6 +856,10 @@ perl_la_SOURCES = perl.c
 # Despite C99 providing the "bool" type thru stdbool.h, Perl defines its own
 # version of that type if HAS_BOOL is not defined... *sigh*
 perl_la_CPPFLAGS = $(AM_CPPFLAGS) -DHAS_BOOL=1
+# Despite off_t being 64 bit wide on 64 bit platforms, Perl insist on using
+# off64_t which is only exposed when _LARGEFILE64_SOURCE is defined... *sigh*
+# On older platforms we also need _REENTRANT. _GNU_SOURCE sets both of these.
+perl_la_CPPFLAGS += -D_GNU_SOURCE
 perl_la_CFLAGS  = $(AM_CFLAGS) \
                $(PERL_CFLAGS) \
                -DXS_VERSION=\"$(VERSION)\" -DVERSION=\"$(VERSION)\"
@@ -804,8 +883,9 @@ if BUILD_PLUGIN_PINBA
 pkglib_LTLIBRARIES += pinba.la
 pinba_la_SOURCES = pinba.c
 nodist_pinba_la_SOURCES = pinba.pb-c.c pinba.pb-c.h
-pinba_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-pinba_la_LIBADD = -lprotobuf-c
+pinba_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBPROTOBUF_C_CPPFLAGS)
+pinba_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBPROTOBUF_C_LDFLAGS)
+pinba_la_LIBADD = $(BUILD_WITH_LIBPROTOBUF_C_LIBS)
 endif
 
 if BUILD_PLUGIN_PING
@@ -835,13 +915,11 @@ endif
 if BUILD_PLUGIN_PYTHON
 pkglib_LTLIBRARIES += python.la
 python_la_SOURCES = python.c pyconfig.c pyvalues.c cpython.h
-python_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_PYTHON_CPPFLAGS)
-python_la_CFLAGS = $(AM_CFLAGS)
+python_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBPYTHON_CPPFLAGS)
 if COMPILER_IS_GCC
-python_la_CFLAGS += -fno-strict-aliasing -Wno-strict-aliasing
+python_la_CPPFLAGS += -fno-strict-aliasing -Wno-strict-aliasing
 endif
-python_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_PYTHON_LDFLAGS)
-python_la_LIBADD = $(BUILD_WITH_PYTHON_LIBS)
+python_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBPYTHON_LDFLAGS)
 endif
 
 if BUILD_PLUGIN_PROCESSES
@@ -909,9 +987,9 @@ endif
 if BUILD_PLUGIN_SIGROK
 pkglib_LTLIBRARIES += sigrok.la
 sigrok_la_SOURCES = sigrok.c
-sigrok_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSIGROK_CFLAGS)
-sigrok_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSIGROK_LDFLAGS)
-sigrok_la_LIBADD = -lsigrok
+sigrok_la_CFLAGS = $(AM_CFLAGS) $(LIBSIGROK_CFLAGS)
+sigrok_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+sigrok_la_LIBADD = $(LIBSIGROK_LIBS)
 endif
 
 if BUILD_PLUGIN_SMART
@@ -934,17 +1012,13 @@ if BUILD_WITH_LIBNETSNMP
 snmp_la_CFLAGS += $(BUILD_WITH_LIBSNMP_CFLAGS)
 snmp_la_LIBADD += $(BUILD_WITH_LIBSNMP_LIBS)
 endif
-if BUILD_WITH_LIBPTHREAD
-snmp_la_LIBADD += -lpthread
-endif
 endif
 
 if BUILD_PLUGIN_STATSD
 pkglib_LTLIBRARIES += statsd.la
-statsd_la_SOURCES = statsd.c \
-                    utils_latency.h utils_latency.c
+statsd_la_SOURCES = statsd.c
 statsd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-statsd_la_LIBADD = -lpthread -lm
+statsd_la_LIBADD = liblatency.la -lm
 endif
 
 if BUILD_PLUGIN_SWAP
@@ -1095,7 +1169,6 @@ unixsock_la_SOURCES = unixsock.c \
                      utils_cmd_putnotif.h utils_cmd_putnotif.c \
                      utils_parse_option.h utils_parse_option.c
 unixsock_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-unixsock_la_LIBADD = -lpthread
 endif
 
 if BUILD_PLUGIN_UPTIME
@@ -1170,34 +1243,29 @@ endif
 if BUILD_PLUGIN_WRITE_GRAPHITE
 pkglib_LTLIBRARIES += write_graphite.la
 write_graphite_la_SOURCES = write_graphite.c \
-                        utils_format_graphite.c utils_format_graphite.h \
-                        utils_format_json.c utils_format_json.h
+                        utils_format_graphite.c utils_format_graphite.h
 write_graphite_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+write_graphite_la_LIBADD = libformat_json.la
 endif
 
 if BUILD_PLUGIN_WRITE_HTTP
 pkglib_LTLIBRARIES += write_http.la
 write_http_la_SOURCES = write_http.c \
-                       utils_format_json.c utils_format_json.h
+                       utils_format_kairosdb.c utils_format_kairosdb.h
 write_http_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-write_http_la_CFLAGS = $(AM_CFLAGS)
-write_http_la_LIBADD =
-if BUILD_WITH_LIBCURL
-write_http_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-write_http_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+write_http_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
+write_http_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) libformat_json.la
 endif
 
 if BUILD_PLUGIN_WRITE_KAFKA
 pkglib_LTLIBRARIES += write_kafka.la
 write_kafka_la_SOURCES = write_kafka.c \
                         utils_format_graphite.c utils_format_graphite.h \
-                        utils_format_json.c utils_format_json.h \
                         utils_cmd_putval.c utils_cmd_putval.h \
                         utils_crc32.c utils_crc32.h
 write_kafka_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRDKAFKA_CPPFLAGS)
 write_kafka_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRDKAFKA_LDFLAGS)
-write_kafka_la_LIBADD = $(BUILD_WITH_LIBRDKAFKA_LIBS)
+write_kafka_la_LIBADD = $(BUILD_WITH_LIBRDKAFKA_LIBS) libformat_json.la
 endif
 
 if BUILD_PLUGIN_WRITE_LOG
@@ -1219,16 +1287,15 @@ if BUILD_PLUGIN_WRITE_REDIS
 pkglib_LTLIBRARIES += write_redis.la
 write_redis_la_SOURCES = write_redis.c
 write_redis_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBHIREDIS_LDFLAGS)
-write_redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
+write_redis_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
 write_redis_la_LIBADD = -lhiredis
 endif
 
 if BUILD_PLUGIN_WRITE_RIEMANN
 pkglib_LTLIBRARIES += write_riemann.la
 write_riemann_la_SOURCES = write_riemann.c write_riemann_threshold.c write_riemann_threshold.h
-nodist_write_riemann_la_SOURCES = riemann.pb-c.c riemann.pb-c.h
-write_riemann_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-write_riemann_la_LIBADD = -lprotobuf-c
+write_riemann_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBRIEMANN_CLIENT_LIBS)
+write_riemann_la_CFLAGS = $(AM_CFLAGS) $(LIBRIEMANN_CLIENT_CFLAGS)
 endif
 
 if BUILD_PLUGIN_WRITE_SENSU
@@ -1243,6 +1310,14 @@ write_tsdb_la_SOURCES = write_tsdb.c
 write_tsdb_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 endif
 
+if BUILD_PLUGIN_XENCPU
+pkglib_LTLIBRARIES += xencpu.la
+xencpu_la_SOURCES = xencpu.c
+xencpu_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBXENCTL_CPPFLAGS)
+xencpu_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBXENCTL_LDFLAGS)
+xencpu_la_LIBADD = -lxenctrl
+endif
+
 if BUILD_PLUGIN_XMMS
 pkglib_LTLIBRARIES += xmms.la
 xmms_la_SOURCES = xmms.c
@@ -1254,17 +1329,12 @@ endif
 if BUILD_PLUGIN_ZFS_ARC
 pkglib_LTLIBRARIES += zfs_arc.la
 zfs_arc_la_SOURCES = zfs_arc.c
-zfs_arc_la_CFLAGS = $(AM_CFLAGS)
 zfs_arc_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 if BUILD_FREEBSD
 zfs_arc_la_LIBADD = -lm
-else
-if BUILD_LINUX
-# zfs_arc requires no library on linux
-else
-# solaris
-zfs_arc_la_LIBADD = -lkstat
 endif
+if BUILD_SOLARIS
+zfs_arc_la_LIBADD = -lkstat
 endif
 endif
 
@@ -1276,6 +1346,12 @@ endif
 
 BUILT_SOURCES += $(dist_man_MANS)
 
+if BUILD_PLUGIN_ZONE
+pkglib_LTLIBRARIES += zone.la
+zone_la_SOURCES = zone.c
+zone_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
 dist_man_MANS = collectd.1 \
                collectd.conf.5 \
                collectd-email.5 \
@@ -1292,11 +1368,7 @@ dist_man_MANS = collectd.1 \
                collectd-unixsock.5 \
                types.db.5
 
-#collectd_1_SOURCES = collectd.pod
-
-EXTRA_DIST = types.db
-
-EXTRA_DIST +=   collectd.conf.pod \
+EXTRA_DIST =   collectd.conf.pod \
                collectd-email.pod \
                collectd-exec.pod \
                collectdctl.pod \
@@ -1311,10 +1383,17 @@ EXTRA_DIST +=   collectd.conf.pod \
                collectd-threshold.pod \
                collectd-unixsock.pod \
                postgresql_default.conf \
-               types.db.pod
+               types.db \
+               types.db.pod \
+               valgrind.FreeBSD.suppress
+
+AM_V_POD2MAN_C = $(am__v_POD2MAN_C_@AM_V@)
+am__v_POD2MAN_C_ = $(am__v_POD2MAN_C_@AM_DEFAULT_V@)
+am__v_POD2MAN_C_0 = @echo "  POD2MAN " $@;
+am__v_POD2MAN_C_1 =
 
 .pod.1:
-       pod2man --release=$(VERSION) --center=$(PACKAGE) $< \
+       $(AM_V_POD2MAN_C)pod2man --release=$(VERSION) --center=$(PACKAGE) $< \
                >.pod2man.tmp.$$$$ 2>/dev/null && mv -f .pod2man.tmp.$$$$ $@ || true
        @if grep '\<POD ERRORS\>' $@ >/dev/null 2>&1; \
        then \
@@ -1322,7 +1401,7 @@ EXTRA_DIST +=   collectd.conf.pod \
        fi
 
 .pod.5:
-       pod2man --section=5 --release=$(VERSION) --center=$(PACKAGE) $< \
+       $(AM_V_POD2MAN_C)pod2man --section=5 --release=$(VERSION) --center=$(PACKAGE) $< \
                >.pod2man.tmp.$$$$ 2>/dev/null && mv -f .pod2man.tmp.$$$$ $@ || true
        @if grep '\<POD ERRORS\>' $@ >/dev/null 2>&1; \
        then \
@@ -1331,7 +1410,7 @@ EXTRA_DIST +=   collectd.conf.pod \
 
 AM_V_PROTOC_C = $(am__v_PROTOC_C_@AM_V@)
 am__v_PROTOC_C_ = $(am__v_PROTOC_C_@AM_DEFAULT_V@)
-am__v_PROTOC_C_0 = @echo "  PROTOC-C    " $@;
+am__v_PROTOC_C_0 = @echo "  PROTOC-C" $@;
 am__v_PROTOC_C_1 =
 
 # Protocol buffer for the "pinba" plugin.
@@ -1341,18 +1420,7 @@ CLEANFILES += pinba.pb-c.c pinba.pb-c.h
 BUILT_SOURCES += pinba.pb-c.c pinba.pb-c.h
 
 pinba.pb-c.c pinba.pb-c.h: pinba.proto
-       $(AM_V_PROTOC_C)protoc-c -I$(srcdir) --c_out . $(srcdir)/pinba.proto
-endif
-
-# Protocol buffer for the "write_riemann" plugin.
-EXTRA_DIST += riemann.proto
-if BUILD_PLUGIN_WRITE_RIEMANN
-CLEANFILES += riemann.pb-c.c riemann.pb-c.h
-
-BUILT_SOURCES += riemann.pb-c.c riemann.pb-c.h
-
-riemann.pb-c.c riemann.pb-c.h: riemann.proto
-       $(AM_V_PROTOC_C)protoc-c -I$(srcdir) --c_out . $(srcdir)/riemann.proto
+       $(AM_V_PROTOC_C)$(PROTOC_C) -I$(srcdir) --c_out . $(srcdir)/pinba.proto
 endif
 
 install-exec-hook:
@@ -1373,27 +1441,11 @@ uninstall-hook:
        rm -f $(DESTDIR)$(sysconfdir)/collectd.conf
        rm -f $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
 
-check_PROGRAMS = test_utils_mount test_utils_vl_lookup
-
-test_utils_mount_SOURCES = utils_mount_test.c testing.h
-test_utils_mount_LDADD = libmount.la daemon/libplugin_mock.la
-if BUILD_WITH_LIBKSTAT
-test_utils_mount_LDADD += -lkstat
-endif
-
-test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h
-test_utils_vl_lookup_LDADD = liblookup.la daemon/libplugin_mock.la
-if BUILD_WITH_LIBKSTAT
-test_utils_vl_lookup_LDADD += -lkstat
-endif
-
-TESTS = test_utils_mount test_utils_vl_lookup
-
 if BUILD_PLUGIN_CEPH
 test_plugin_ceph_SOURCES = ceph_test.c
 test_plugin_ceph_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
 test_plugin_ceph_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
-test_plugin_ceph_LDADD = daemon/libcommon.la daemon/libplugin_mock.la $(BUILD_WITH_LIBYAJL_LIBS)
+test_plugin_ceph_LDADD = daemon/libplugin_mock.la $(BUILD_WITH_LIBYAJL_LIBS)
 check_PROGRAMS += test_plugin_ceph
 TESTS += test_plugin_ceph
 endif
index 56e4955..b9db500 100644 (file)
@@ -26,8 +26,6 @@
 
 #include "collectd.h"
 
-#include <pthread.h>
-
 #include "plugin.h"
 #include "common.h"
 #include "configfile.h"
@@ -240,13 +238,12 @@ static agg_instance_t *agg_instance_create (data_set_t const *ds, /* {{{ */
 
   DEBUG ("aggregation plugin: Creating new instance.");
 
-  inst = malloc (sizeof (*inst));
+  inst = calloc (1, sizeof (*inst));
   if (inst == NULL)
   {
-    ERROR ("aggregation plugin: malloc() failed.");
+    ERROR ("aggregation plugin: calloc() failed.");
     return (NULL);
   }
-  memset (inst, 0, sizeof (*inst));
   pthread_mutex_init (&inst->lock, /* attr = */ NULL);
 
   inst->ds_type = ds->ds[0].type;
@@ -259,14 +256,13 @@ static agg_instance_t *agg_instance_create (data_set_t const *ds, /* {{{ */
 #define INIT_STATE(field) do { \
   inst->state_ ## field = NULL; \
   if (agg->calc_ ## field) { \
-    inst->state_ ## field = malloc (sizeof (*inst->state_ ## field)); \
+    inst->state_ ## field = calloc (1, sizeof (*inst->state_ ## field)); \
     if (inst->state_ ## field == NULL) { \
       agg_instance_destroy (inst); \
       free (inst); \
-      ERROR ("aggregation plugin: malloc() failed."); \
+      ERROR ("aggregation plugin: calloc() failed."); \
       return (NULL); \
     } \
-    memset (inst->state_ ## field, 0, sizeof (*inst->state_ ## field)); \
   } \
 } while (0)
 
@@ -350,7 +346,6 @@ static int agg_instance_read_func (agg_instance_t *inst, /* {{{ */
   else
     sstrncpy (vl->plugin_instance, func, sizeof (vl->plugin_instance));
 
-  memset (&v, 0, sizeof (v));
   status = rate_to_value (&v, rate, state, inst->ds_type, t);
   if (status != 0)
   {
@@ -488,9 +483,7 @@ static void agg_lookup_free_obj_callback (void *user_obj) /* {{{ */
 static int agg_config_handle_group_by (oconfig_item_t const *ci, /* {{{ */
     aggregation_t *agg)
 {
-  int i;
-
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
   {
     char const *value;
 
@@ -526,15 +519,13 @@ static int agg_config_aggregation (oconfig_item_t *ci) /* {{{ */
   aggregation_t *agg;
   _Bool is_valid;
   int status;
-  int i;
 
-  agg = malloc (sizeof (*agg));
+  agg = calloc (1, sizeof (*agg));
   if (agg == NULL)
   {
-    ERROR ("aggregation plugin: malloc failed.");
+    ERROR ("aggregation plugin: calloc failed.");
     return (-1);
   }
-  memset (agg, 0, sizeof (*agg));
 
   sstrncpy (agg->ident.host, "/.*/", sizeof (agg->ident.host));
   sstrncpy (agg->ident.plugin, "/.*/", sizeof (agg->ident.plugin));
@@ -544,7 +535,7 @@ static int agg_config_aggregation (oconfig_item_t *ci) /* {{{ */
   sstrncpy (agg->ident.type_instance, "/.*/",
       sizeof (agg->ident.type_instance));
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -682,8 +673,6 @@ static int agg_config_aggregation (oconfig_item_t *ci) /* {{{ */
 
 static int agg_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
   pthread_mutex_lock (&agg_instance_list_lock);
 
   if (lookup == NULL)
@@ -700,7 +689,7 @@ static int agg_config (oconfig_item_t *ci) /* {{{ */
     }
   }
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -718,7 +707,6 @@ static int agg_config (oconfig_item_t *ci) /* {{{ */
 
 static int agg_read (void) /* {{{ */
 {
-  agg_instance_t *this;
   cdtime_t t;
   int success;
 
@@ -739,7 +727,7 @@ static int agg_read (void) /* {{{ */
     return (0);
   }
 
-  for (this = agg_instance_list_head; this != NULL; this = this->next)
+  for (agg_instance_t *this = agg_instance_list_head; this != NULL; this = this->next)
   {
     int status;
 
index 4206bdc..89f051e 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_cmd_putval.h"
 #include "utils_format_json.h"
 #include "utils_format_graphite.h"
 
-#include <pthread.h>
-
 #include <amqp.h>
 #include <amqp_framing.h>
 
@@ -529,13 +528,11 @@ static int camqp_connect (camqp_config_t *conf) /* {{{ */
 
 static int camqp_shutdown (void) /* {{{ */
 {
-    size_t i;
-
     DEBUG ("amqp plugin: Shutting down %zu subscriber threads.",
             subscriber_threads_num);
 
     subscriber_threads_running = 0;
-    for (i = 0; i < subscriber_threads_num; i++)
+    for (size_t i = 0; i < subscriber_threads_num; i++)
     {
         /* FIXME: Sending a signal is not very elegant here. Maybe find out how
          * to use a timeout in the thread and check for the variable in regular
@@ -736,7 +733,7 @@ static int camqp_subscribe_init (camqp_config_t *conf) /* {{{ */
     if (tmp == NULL)
     {
         ERROR ("amqp plugin: realloc failed.");
-        camqp_config_free (conf);
+        sfree (subscriber_threads);
         return (ENOMEM);
     }
     subscriber_threads = tmp;
@@ -750,7 +747,6 @@ static int camqp_subscribe_init (camqp_config_t *conf) /* {{{ */
         char errbuf[1024];
         ERROR ("amqp plugin: pthread_create failed: %s",
                 sstrerror (status, errbuf, sizeof (errbuf)));
-        camqp_config_free (conf);
         return (status);
     }
 
@@ -766,17 +762,20 @@ static int camqp_subscribe_init (camqp_config_t *conf) /* {{{ */
 static int camqp_write_locked (camqp_config_t *conf, /* {{{ */
         const char *buffer, const char *routing_key)
 {
-    amqp_basic_properties_t props;
     int status;
 
     status = camqp_connect (conf);
     if (status != 0)
         return (status);
 
-    memset (&props, 0, sizeof (props));
-    props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG
-        | AMQP_BASIC_DELIVERY_MODE_FLAG
-        | AMQP_BASIC_APP_ID_FLAG;
+    amqp_basic_properties_t props = {
+        ._flags = AMQP_BASIC_CONTENT_TYPE_FLAG
+            | AMQP_BASIC_DELIVERY_MODE_FLAG
+            | AMQP_BASIC_APP_ID_FLAG,
+        .delivery_mode = conf->delivery_mode,
+        .app_id = amqp_cstring_bytes("collectd")
+    };
+
     if (conf->format == CAMQP_FORMAT_COMMAND)
         props.content_type = amqp_cstring_bytes("text/collectd");
     else if (conf->format == CAMQP_FORMAT_JSON)
@@ -785,8 +784,6 @@ static int camqp_write_locked (camqp_config_t *conf, /* {{{ */
         props.content_type = amqp_cstring_bytes("text/graphite");
     else
         assert (23 == 42);
-    props.delivery_mode = conf->delivery_mode;
-    props.app_id = amqp_cstring_bytes("collectd");
 
     status = amqp_basic_publish(conf->connection,
                 /* channel = */ 1,
@@ -817,15 +814,12 @@ static int camqp_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
     if ((ds == NULL) || (vl == NULL) || (conf == NULL))
         return (EINVAL);
 
-    memset (buffer, 0, sizeof (buffer));
-
     if (conf->routing_key != NULL)
     {
         sstrncpy (routing_key, conf->routing_key, sizeof (routing_key));
     }
     else
     {
-        size_t i;
         ssnprintf (routing_key, sizeof (routing_key), "collectd/%s/%s/%s/%s/%s",
                 vl->host,
                 vl->plugin, vl->plugin_instance,
@@ -833,7 +827,7 @@ static int camqp_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
 
         /* Switch slashes (the only character forbidden by collectd) and dots
          * (the separation character used by AMQP). */
-        for (i = 0; routing_key[i] != 0; i++)
+        for (size_t i = 0; routing_key[i] != 0; i++)
         {
             if (routing_key[i] == '.')
                 routing_key[i] = '/';
@@ -923,17 +917,15 @@ static int camqp_config_connection (oconfig_item_t *ci, /* {{{ */
 {
     camqp_config_t *conf;
     int status;
-    int i;
 
-    conf = malloc (sizeof (*conf));
+    conf = calloc (1, sizeof (*conf));
     if (conf == NULL)
     {
-        ERROR ("amqp plugin: malloc failed.");
+        ERROR ("amqp plugin: calloc failed.");
         return (ENOMEM);
     }
 
     /* Initialize "conf" {{{ */
-    memset (conf, 0, sizeof (*conf));
     conf->publish = publish;
     conf->name = NULL;
     conf->format = CAMQP_FORMAT_COMMAND;
@@ -971,7 +963,7 @@ static int camqp_config_connection (oconfig_item_t *ci, /* {{{ */
         return (status);
     }
 
-    for (i = 0; i < ci->children_num; i++)
+    for (int i = 0; i < ci->children_num; i++)
     {
         oconfig_item_t *child = ci->children + i;
 
@@ -1104,9 +1096,7 @@ static int camqp_config_connection (oconfig_item_t *ci, /* {{{ */
 
 static int camqp_config (oconfig_item_t *ci) /* {{{ */
 {
-    int i;
-
-    for (i = 0; i < ci->children_num; i++)
+    for (int i = 0; i < ci->children_num; i++)
     {
         oconfig_item_t *child = ci->children + i;
 
index c515e3c..650d678 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -63,8 +64,10 @@ typedef struct apache_s apache_t;
 /* TODO: Remove this prototype */
 static int apache_read_host (user_data_t *user_data);
 
-static void apache_free (apache_t *st)
+static void apache_free (void *arg)
 {
+       apache_t *st = arg;
+
        if (st == NULL)
                return;
 
@@ -98,14 +101,14 @@ static size_t apache_curl_callback (void *buf, size_t size, size_t nmemb,
                return (0);
        }
 
-       if (len <= 0)
+       if (len == 0)
                return (len);
 
        if ((st->apache_buffer_fill + len) >= st->apache_buffer_size)
        {
                char *temp;
 
-               temp = (char *) realloc (st->apache_buffer,
+               temp = realloc (st->apache_buffer,
                                st->apache_buffer_fill + len + 1);
                if (temp == NULL)
                {
@@ -137,7 +140,7 @@ static size_t apache_header_callback (void *buf, size_t size, size_t nmemb,
                return (0);
        }
 
-       if (len <= 0)
+       if (len == 0)
                return (len);
 
        /* look for the Server header */
@@ -172,16 +175,14 @@ static size_t apache_header_callback (void *buf, size_t size, size_t nmemb,
 static int config_add (oconfig_item_t *ci)
 {
        apache_t *st;
-       int i;
        int status;
 
-       st = malloc (sizeof (*st));
+       st = calloc (1, sizeof (*st));
        if (st == NULL)
        {
-               ERROR ("apache plugin: malloc failed.");
+               ERROR ("apache plugin: calloc failed.");
                return (-1);
        }
-       memset (st, 0, sizeof (*st));
 
        st->timeout = -1;
 
@@ -193,7 +194,7 @@ static int config_add (oconfig_item_t *ci)
        }
        assert (st->name != NULL);
 
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
 
@@ -239,14 +240,13 @@ static int config_add (oconfig_item_t *ci)
 
        if (status == 0)
        {
-               user_data_t ud;
-               char callback_name[3*DATA_MAX_NAME_LEN];
+               user_data_t ud = {
+                       .data = st,
+                       .free_func = apache_free
+               };
 
-               memset (&ud, 0, sizeof (ud));
-               ud.data = st;
-               ud.free_func = (void *) apache_free;
+               char callback_name[3*DATA_MAX_NAME_LEN];
 
-               memset (callback_name, 0, sizeof (callback_name));
                ssnprintf (callback_name, sizeof (callback_name),
                                "apache/%s/%s",
                                (st->host != NULL) ? st->host : hostname_g,
@@ -255,7 +255,7 @@ static int config_add (oconfig_item_t *ci)
                status = plugin_register_complex_read (/* group = */ NULL,
                                /* name      = */ callback_name,
                                /* callback  = */ apache_read_host,
-                               /* interval  = */ NULL,
+                               /* interval  = */ 0,
                                /* user_data = */ &ud);
        }
 
@@ -271,9 +271,8 @@ static int config_add (oconfig_item_t *ci)
 static int config (oconfig_item_t *ci)
 {
        int status = 0;
-       int i;
 
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
 
@@ -383,8 +382,7 @@ static int init_host (apache_t *st) /* {{{ */
        if (st->timeout >= 0)
                curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS, (long) st->timeout);
        else
-               curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS,
-                               CDTIME_T_TO_MS(plugin_get_interval()));
+               curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
 #endif
 
        return (0);
@@ -465,8 +463,7 @@ static void submit_scoreboard (char *buf, apache_t *st)
        long long response_start = 0LL;
        long long response_end   = 0LL;
 
-       int i;
-       for (i = 0; buf[i] != '\0'; i++)
+       for (int i = 0; buf[i] != '\0'; i++)
        {
                if (buf[i] == '.') open++;
                else if (buf[i] == '_') waiting++;
index 281bf98..cc20357 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * collectd - src/apcups.c
- * Copyright (C) 2006-2012  Florian octo Forster
+ * Copyright (C) 2006-2015  Florian octo Forster
  * Copyright (C) 2006       Anthony Gialluca <tonyabg at charter.net>
  * Copyright (C) 2000-2004  Kern Sibbald
  * Copyright (C) 1996-1999  Andre M. Hedrick <andre at suse.com>
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"      /* rrd_update_file */
 #include "plugin.h"      /* plugin_register, plugin_submit */
 #include "configfile.h"  /* cf_register */
@@ -32,9 +33,6 @@
 #if HAVE_SYS_TYPES_H
 # include <sys/types.h>
 #endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
 #if HAVE_NETDB_H
 # include <netdb.h>
 #endif
 # include <netinet/in.h>
 #endif
 
-#define NISPORT 3551
-#define MAXSTRING               256
-#define MODULE_NAME "apcups"
+#ifndef APCUPS_SERVER_TIMEOUT
+# define APCUPS_SERVER_TIMEOUT 15.0
+#endif
 
-#define APCUPS_DEFAULT_HOST "localhost"
+#ifndef APCUPS_DEFAULT_NODE
+# define APCUPS_DEFAULT_NODE "localhost"
+#endif
+
+#ifndef APCUPS_DEFAULT_SERVICE
+# define APCUPS_DEFAULT_SERVICE "3551"
+#endif
 
 /*
  * Private data types
@@ -68,24 +72,16 @@ struct apc_detail_s
  * Private variables
  */
 /* Default values for contacting daemon */
-static char *conf_host = NULL;
-static int   conf_port = NISPORT;
+static char *conf_node = NULL;
+static char *conf_service = NULL;
 /* Defaults to false for backwards compatibility. */
 static _Bool conf_report_seconds = 0;
+static _Bool conf_persistent_conn = 1;
 
 static int global_sockfd = -1;
 
 static int count_retries = 0;
 static int count_iterations = 0;
-static _Bool close_socket = 0;
-
-static const char *config_keys[] =
-{
-       "Host",
-       "Port",
-       "ReportSeconds"
-};
-static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
 static int net_shutdown (int *fd)
 {
@@ -94,7 +90,7 @@ static int net_shutdown (int *fd)
        if ((fd == NULL) || (*fd < 0))
                return (EINVAL);
 
-       swrite (*fd, (void *) &packet_size, sizeof (packet_size));
+       (void)swrite (*fd, (void *) &packet_size, sizeof (packet_size));
        close (*fd);
        *fd = -1;
 
@@ -116,26 +112,20 @@ static int apcups_shutdown (void)
  * Returns -1 on error
  * Returns socket file descriptor otherwise
  */
-static int net_open (char *host, int port)
+static int net_open (char const *node, char const *service)
 {
        int              sd;
        int              status;
-       char             port_str[8];
-       struct addrinfo  ai_hints;
        struct addrinfo *ai_return;
        struct addrinfo *ai_list;
 
-       assert ((port > 0x00000000) && (port <= 0x0000FFFF));
-
-       /* Convert the port to a string */
-       ssnprintf (port_str, sizeof (port_str), "%i", port);
+       /* TODO: Change this to `AF_UNSPEC' if apcupsd can handle IPv6 */
+       struct addrinfo ai_hints = {
+               .ai_family = AF_INET,
+               .ai_socktype = SOCK_STREAM
+       };
 
-       /* Resolve name */
-       memset ((void *) &ai_hints, '\0', sizeof (ai_hints));
-       ai_hints.ai_family   = AF_INET; /* XXX: Change this to `AF_UNSPEC' if apcupsd can handle IPv6 */
-       ai_hints.ai_socktype = SOCK_STREAM;
-
-       status = getaddrinfo (host, port_str, &ai_hints, &ai_return);
+       status = getaddrinfo (node, service, &ai_hints, &ai_return);
        if (status != 0)
        {
                char errbuf[1024];
@@ -179,7 +169,7 @@ static int net_open (char *host, int port)
        DEBUG ("apcups plugin: Done opening a socket %i", sd);
 
        return (sd);
-} /* int net_open (char *host, char *service, int port) */
+} /* int net_open */
 
 /*
  * Receive a message from the other end. Each message consists of
@@ -234,7 +224,7 @@ static int net_recv (int *sockfd, char *buf, int buflen)
  * Returns zero on success
  * Returns non-zero on error
  */
-static int net_send (int *sockfd, char *buff, int len)
+static int net_send (int *sockfd, const char *buff, int len)
 {
        uint16_t packet_size;
 
@@ -263,7 +253,7 @@ static int net_send (int *sockfd, char *buff, int len)
 }
 
 /* Get and print status from apcupsd NIS server */
-static int apc_query_server (char *host, int port,
+static int apc_query_server (char const *node, char const *service,
                struct apc_detail_s *apcups_detail)
 {
        int     n;
@@ -285,7 +275,7 @@ static int apc_query_server (char *host, int port,
        {
                if (global_sockfd < 0)
                {
-                       global_sockfd = net_open (host, port);
+                       global_sockfd = net_open (node, service);
                        if (global_sockfd < 0)
                        {
                                ERROR ("apcups plugin: Connecting to the "
@@ -325,13 +315,13 @@ static int apc_query_server (char *host, int port,
                                "first %i iterations. Will close the socket "
                                "in future iterations.",
                                count_retries, count_iterations);
-               close_socket = 1;
+               conf_persistent_conn = 0;
        }
 
        while ((n = net_recv (&global_sockfd, recvline, sizeof (recvline) - 1)) > 0)
        {
-               assert ((unsigned int)n < sizeof (recvline));
-               recvline[n] = '\0';
+               assert ((size_t)n < sizeof (recvline));
+               recvline[n] = 0;
 #if APCMAIN
                printf ("net_recv = `%s';\n", recvline);
 #endif /* if APCMAIN */
@@ -375,7 +365,7 @@ static int apc_query_server (char *host, int port,
        }
        status = errno; /* save errno, net_shutdown() may re-set it. */
 
-       if (close_socket)
+       if (!conf_persistent_conn)
                net_shutdown (&global_sockfd);
 
        if (n < 0)
@@ -389,43 +379,43 @@ static int apc_query_server (char *host, int port,
        return (0);
 }
 
-static int apcups_config (const char *key, const char *value)
+static int apcups_config (oconfig_item_t *ci)
 {
-       if (strcasecmp (key, "host") == 0)
-       {
-               if (conf_host != NULL)
-               {
-                       free (conf_host);
-                       conf_host = NULL;
-               }
-               if ((conf_host = strdup (value)) == NULL)
-                       return (1);
-       }
-       else if (strcasecmp (key, "Port") == 0)
+       _Bool persistent_conn_set = 0;
+
+       for (int i = 0; i < ci->children_num; i++)
        {
-               int port_tmp = atoi (value);
-               if (port_tmp < 1 || port_tmp > 65535)
-               {
-                       WARNING ("apcups plugin: Invalid port: %i", port_tmp);
-                       return (1);
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp (child->key, "Host") == 0)
+                       cf_util_get_string (child, &conf_node);
+               else if (strcasecmp (child->key, "Port") == 0)
+                       cf_util_get_service (child, &conf_service);
+               else if (strcasecmp (child->key, "ReportSeconds") == 0)
+                       cf_util_get_boolean (child, &conf_report_seconds);
+               else if (strcasecmp (child->key, "PersistentConnection") == 0) {
+                       cf_util_get_boolean (child, &conf_persistent_conn);
+                       persistent_conn_set = 1;
                }
-               conf_port = port_tmp;
-       }
-       else if (strcasecmp (key, "ReportSeconds") == 0)
-       {
-               if (IS_TRUE (value))
-                       conf_report_seconds = 1;
                else
-                       conf_report_seconds = 0;
+                       ERROR ("apcups plugin: Unknown config option \"%s\".", child->key);
        }
-       else
-       {
-               return (-1);
+
+       if (!persistent_conn_set) {
+               double interval = CDTIME_T_TO_DOUBLE(plugin_get_interval());
+               if (interval > APCUPS_SERVER_TIMEOUT) {
+                       NOTICE ("apcups plugin: Plugin poll interval set to %.3f seconds. "
+                               "Apcupsd NIS socket timeout is %.3f seconds, "
+                               "PersistentConnection disabled by default.",
+                               interval, APCUPS_SERVER_TIMEOUT);
+                       conf_persistent_conn = 0;
+               }
        }
+
        return (0);
-}
+} /* int apcups_config */
 
-static void apc_submit_generic (char *type, char *type_inst, double value)
+static void apc_submit_generic (const char *type, const char *type_inst, double value)
 {
        value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
@@ -469,10 +459,9 @@ static int apcups_read (void)
        apcups_detail.itemp    = -300.0;
        apcups_detail.linefreq =   -1.0;
 
-       status = apc_query_server (conf_host == NULL
-                       ? APCUPS_DEFAULT_HOST
-                       : conf_host,
-                       conf_port, &apcups_detail);
+       status = apc_query_server ((conf_node == NULL) ? APCUPS_DEFAULT_NODE : conf_node,
+                       (conf_service == NULL) ? APCUPS_DEFAULT_SERVICE : conf_service,
+                       &apcups_detail);
 
        /*
         * if we did not connect then do not bother submitting
@@ -480,11 +469,10 @@ static int apcups_read (void)
         */
        if (status != 0)
        {
-               DEBUG ("apcups plugin: apc_query_server (%s, %i) = %i",
-                               conf_host == NULL
-                               ? APCUPS_DEFAULT_HOST
-                               : conf_host,
-                               conf_port, status);
+               DEBUG ("apcups plugin: apc_query_server (%s, %s) = %i",
+                               (conf_node == NULL) ? APCUPS_DEFAULT_NODE : conf_node,
+                               (conf_service == NULL) ? APCUPS_DEFAULT_SERVICE : conf_service,
+                               status);
                return (-1);
        }
 
@@ -495,8 +483,7 @@ static int apcups_read (void)
 
 void module_register (void)
 {
-       plugin_register_config ("apcups", apcups_config, config_keys,
-                       config_keys_num);
+       plugin_register_complex_config ("apcups", apcups_config);
        plugin_register_read ("apcups", apcups_read);
        plugin_register_shutdown ("apcups", apcups_shutdown);
 } /* void module_register */
index 19d5a49..48fbcb9 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -59,7 +60,7 @@ static mach_port_t io_master_port = MACH_PORT_NULL;
 static int as_init (void)
 {
        kern_return_t status;
-       
+
        if (io_master_port != MACH_PORT_NULL)
        {
                mach_port_deallocate (mach_task_self (),
@@ -113,8 +114,6 @@ static int as_read (void)
        char   inst[128];
        int    value_int;
        double value_double;
-       int    i;
-
        if (!io_master_port || (io_master_port == MACH_PORT_NULL))
                return (-1);
 
@@ -169,7 +168,7 @@ static int as_read (void)
                                        kCFStringEncodingASCII))
                        continue;
                inst[sizeof (inst) - 1] = '\0';
-               for (i = 0; i < 128; i++)
+               for (int i = 0; i < 128; i++)
                {
                        if (inst[i] == '\0')
                                break;
index 5db988e..81a4efd 100644 (file)
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -33,9 +34,7 @@ static char *conf_device = NULL;
 
 static int aquaero_config (oconfig_item_t *ci)
 {
-       int i;
-
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
 
@@ -87,9 +86,8 @@ static void aquaero_submit_array (const char *type,
                const char *type_instance_prefix, double *value_array, int len)
 {
        char type_instance[DATA_MAX_NAME_LEN];
-       int i;
 
-       for (i = 0; i < len; i++)
+       for (int i = 0; i < len; i++)
        {
                if (value_array[i] == AQ5_FLOAT_UNDEF)
                        continue;
@@ -106,7 +104,6 @@ static int aquaero_read (void)
        aq5_settings_t aq_sett;
        char *err_msg = NULL;
        char type_instance[DATA_MAX_NAME_LEN];
-       int i;
 
        if (libaquaero5_poll(conf_device, &aq_data, &err_msg) < 0)
        {
@@ -147,7 +144,7 @@ static int aquaero_read (void)
                        AQ5_NUM_OTHER_SENSORS);
 
        /* Fans */
-       for (i = 0; i < AQ5_NUM_FAN; i++)
+       for (int i = 0; i < AQ5_NUM_FAN; i++)
        {
                if ((aq_sett.fan_data_source[i] == NONE)
                                || (aq_data.fan_vrm_temp[i] != AQ5_FLOAT_UNDEF))
index 11175af..20fef65 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -32,7 +33,7 @@
 #include <curl/curl.h>
 #include <libxml/parser.h>
 
-static char *races_list[] = /* {{{ */
+static const char *races_list[] = /* {{{ */
 {
   NULL,
   "Human",    /*  1 */
@@ -49,7 +50,7 @@ static char *races_list[] = /* {{{ */
 }; /* }}} */
 #define RACES_LIST_LENGTH STATIC_ARRAY_SIZE (races_list)
 
-static char *classes_list[] = /* {{{ */
+static const char *classes_list[] = /* {{{ */
 {
   NULL,
   "Warrior", /*  1 */
@@ -66,7 +67,7 @@ static char *classes_list[] = /* {{{ */
 }; /* }}} */
 #define CLASSES_LIST_LENGTH STATIC_ARRAY_SIZE (classes_list)
 
-static char *genders_list[] = /* {{{ */
+static const char *genders_list[] = /* {{{ */
 {
   "Male",
   "Female"
@@ -154,14 +155,14 @@ static size_t ascent_curl_callback (void *buf, size_t size, size_t nmemb, /* {{{
 {
   size_t len = size * nmemb;
 
-  if (len <= 0)
+  if (len == 0)
     return (len);
 
   if ((ascent_buffer_fill + len) >= ascent_buffer_size)
   {
     char *temp;
 
-    temp = (char *) realloc (ascent_buffer,
+    temp = realloc (ascent_buffer,
         ascent_buffer_fill + len + 1);
     if (temp == NULL)
     {
@@ -181,20 +182,19 @@ static size_t ascent_curl_callback (void *buf, size_t size, size_t nmemb, /* {{{
 
 static int ascent_submit_players (player_stats_t *ps) /* {{{ */
 {
-  size_t i;
   gauge_t value;
 
-  for (i = 0; i < RACES_LIST_LENGTH; i++)
+  for (size_t i = 0; i < RACES_LIST_LENGTH; i++)
     if (races_list[i] != NULL)
       ascent_submit_gauge ("by-race", "players", races_list[i],
           (gauge_t) ps->races[i]);
 
-  for (i = 0; i < CLASSES_LIST_LENGTH; i++)
+  for (size_t i = 0; i < CLASSES_LIST_LENGTH; i++)
     if (classes_list[i] != NULL)
       ascent_submit_gauge ("by-class", "players", classes_list[i],
           (gauge_t) ps->classes[i]);
 
-  for (i = 0; i < GENDERS_LIST_LENGTH; i++)
+  for (size_t i = 0; i < GENDERS_LIST_LENGTH; i++)
     if (genders_list[i] != NULL)
       ascent_submit_gauge ("by-gender", "players", genders_list[i],
           (gauge_t) ps->genders[i]);
@@ -328,9 +328,7 @@ static int ascent_xml_read_int (xmlDoc *doc, xmlNode *node, /* {{{ */
 static int ascent_xml_sessions_plr (xmlDoc *doc, xmlNode *node, /* {{{ */
     player_info_t *pi)
 {
-  xmlNode *child;
-
-  for (child = node->xmlChildrenNode; child != NULL; child = child->next)
+  for (xmlNode *child = node->xmlChildrenNode; child != NULL; child = child->next)
   {
     if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0)
         || (xmlStrcmp ((const xmlChar *) "text", child->name) == 0))
@@ -364,12 +362,11 @@ static int ascent_xml_sessions_plr (xmlDoc *doc, xmlNode *node, /* {{{ */
 
 static int ascent_xml_sessions (xmlDoc *doc, xmlNode *node) /* {{{ */
 {
-  xmlNode *child;
-  player_stats_t ps;
+  player_stats_t ps = {
+    .level_sum = 0
+  };
 
-  memset (&ps, 0, sizeof (ps));
-
-  for (child = node->xmlChildrenNode; child != NULL; child = child->next)
+  for (xmlNode *child = node->xmlChildrenNode; child != NULL; child = child->next)
   {
     if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0)
         || (xmlStrcmp ((const xmlChar *) "text", child->name) == 0))
@@ -396,9 +393,7 @@ static int ascent_xml_sessions (xmlDoc *doc, xmlNode *node) /* {{{ */
 
 static int ascent_xml_status (xmlDoc *doc, xmlNode *node) /* {{{ */
 {
-  xmlNode *child;
-
-  for (child = node->xmlChildrenNode; child != NULL; child = child->next)
+  for (xmlNode *child = node->xmlChildrenNode; child != NULL; child = child->next)
   {
     if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0)
         || (xmlStrcmp ((const xmlChar *) "text", child->name) == 0))
@@ -438,7 +433,6 @@ static int ascent_xml (const char *data) /* {{{ */
 {
   xmlDoc *doc;
   xmlNode *cur;
-  xmlNode *child;
 
 #if 0
   doc = xmlParseMemory (data, strlen (data),
@@ -469,7 +463,7 @@ static int ascent_xml (const char *data) /* {{{ */
     return (-1);
   }
 
-  for (child = cur->xmlChildrenNode; child != NULL; child = child->next)
+  for (xmlNode *child = cur->xmlChildrenNode; child != NULL; child = child->next)
   {
     if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0)
         || (xmlStrcmp ((const xmlChar *) "text", child->name) == 0))
@@ -594,8 +588,7 @@ static int ascent_init (void) /* {{{ */
   if (timeout != NULL)
     curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, atol(timeout));
   else
-    curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS,
-       CDTIME_T_TO_MS(plugin_get_interval()));
+    curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
 #endif
 
   return (0);
index aaedd70..fba3450 100644 (file)
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "utils_cache.h"
 #include "plugin.h"
@@ -343,9 +344,9 @@ static temperature_list_t * temp_list = NULL;
  */
 static int temp_list_add(temperature_list_t * list, const char * sensor)
 {
-    temperature_list_t * new_temp;
+    temperature_list_t *new_temp;
 
-    new_temp = (temperature_list_t *) malloc(sizeof(*new_temp));
+    new_temp = malloc(sizeof (*new_temp));
     if(new_temp == NULL)
         return -1;
 
@@ -407,7 +408,6 @@ static int get_reference_temperature(double * result)
 
     gauge_t * values = NULL;   /**< rate values */
     size_t    values_num = 0;  /**< number of rate values */
-    int i;
 
     gauge_t values_history[REF_TEMP_AVG_NUM];
 
@@ -445,11 +445,10 @@ static int get_reference_temperature(double * result)
             list->initialized = 1;
             list->num_values = values_num;
 
-            for(i=0; i<values_num; ++i)
+            for(size_t i=0; i<values_num; ++i)
             {
-                DEBUG ("barometer: get_reference_temperature - rate %d: %lf **",
-                       i,
-                       values[i]);
+                DEBUG ("barometer: get_reference_temperature - rate %zu: %lf **",
+                       i, values[i]);
                 if(!isnan(values[i]))
                 {
                     avg_sum += values[i];
@@ -475,11 +474,10 @@ static int get_reference_temperature(double * result)
             continue;
         }
 
-        for(i=0; i<REF_TEMP_AVG_NUM*list->num_values; ++i)
+        for(size_t i=0; i<REF_TEMP_AVG_NUM*list->num_values; ++i)
         {
-            DEBUG ("barometer: get_reference_temperature - history %d: %lf",
-                   i,
-                   values_history[i]);
+            DEBUG ("barometer: get_reference_temperature - history %zu: %lf",
+                   i, values_history[i]);
             if(!isnan(values_history[i]))
             {
                 avg_sum += values_history[i];
@@ -501,11 +499,10 @@ static int get_reference_temperature(double * result)
                 continue;
             }
 
-            for(i=0; i<values_num; ++i)
+            for(size_t i=0; i<values_num; ++i)
             {
-                DEBUG ("barometer: get_reference_temperature - rate last %d: %lf **",
-                       i,
-                       values[i]);
+                DEBUG ("barometer: get_reference_temperature - rate last %zu: %lf **",
+                       i, values[i]);
                 if(!isnan(values[i]))
                 {
                     avg_sum += values[i];
@@ -1583,8 +1580,7 @@ static int MPL115_collectd_barometer_read (void)
        already available. */
     if(!avg_initialized)
     {
-        int i;
-        for(i=0; i<config_oversample-1; ++i)
+        for(int i=0; i<config_oversample-1; ++i)
         {
             result = MPL115_read_averaged(&pressure, &temperature);
             if(result)
index c4c050d..a084319 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
-#include "utils_complain.h"
-
 #if HAVE_MACH_MACH_TYPES_H
 #  include <mach/mach_types.h>
 #endif
@@ -143,7 +142,7 @@ static void submit_capacity (char const *plugin_instance, /* {{{ */
 } /* }}} void submit_capacity */
 
 #if HAVE_IOKIT_PS_IOPOWERSOURCES_H || HAVE_IOKIT_IOKITLIB_H
-static double dict_get_double (CFDictionaryRef dict, char *key_string) /* {{{ */
+static double dict_get_double (CFDictionaryRef dict, const char *key_string) /* {{{ */
 {
        double      val_double;
        long long   val_int;
@@ -203,7 +202,6 @@ static void get_via_io_power_sources (double *ret_charge, /* {{{ */
        CFTypeRef       ps_obj;
 
        double temp_double;
-       int i;
 
        ps_raw       = IOPSCopyPowerSourcesInfo ();
        ps_array     = IOPSCopyPowerSourcesList (ps_raw);
@@ -211,7 +209,7 @@ static void get_via_io_power_sources (double *ret_charge, /* {{{ */
 
        DEBUG ("ps_array_len == %i", ps_array_len);
 
-       for (i = 0; i < ps_array_len; i++)
+       for (int i = 0; i < ps_array_len; i++)
        {
                ps_obj  = CFArrayGetValueAtIndex (ps_array, i);
                ps_dict = IOPSGetPowerSourceDescription (ps_raw, ps_obj);
@@ -276,7 +274,6 @@ static void get_via_generic_iokit (double *ret_capacity_full, /* {{{ */
        CFDictionaryRef bat_root_dict;
        CFArrayRef      bat_info_arry;
        CFIndex         bat_info_arry_len;
-       CFIndex         bat_info_arry_pos;
        CFDictionaryRef bat_info_dict;
 
        double temp_double;
@@ -311,7 +308,7 @@ static void get_via_generic_iokit (double *ret_capacity_full, /* {{{ */
                }
                bat_info_arry_len = CFArrayGetCount (bat_info_arry);
 
-               for (bat_info_arry_pos = 0;
+               for (CFIndex bat_info_arry_pos = 0;
                                bat_info_arry_pos < bat_info_arry_len;
                                bat_info_arry_pos++)
                {
@@ -341,7 +338,7 @@ static void get_via_generic_iokit (double *ret_capacity_full, /* {{{ */
                                *ret_voltage = temp_double / 1000.0;
                        }
                }
-               
+
                CFRelease (bat_root_dict);
        }
 
@@ -358,7 +355,7 @@ static int battery_read (void) /* {{{ */
         * IOPowerSources. IOKit, on the other hand, only reports the full
         * capacity. We use the two to calculate the current charged capacity. */
        gauge_t charge_rel = NAN; /* Current charge in percent */
-       gauge_t capacity_charged = NAN; /* Charged capacity */
+       gauge_t capacity_charged; /* Charged capacity */
        gauge_t capacity_full = NAN; /* Total capacity */
        gauge_t capacity_design = NAN; /* Full design capacity */
 
@@ -715,11 +712,10 @@ static int read_acpi (void) /* {{{ */
 
 static int read_pmu (void) /* {{{ */
 {
-       int i;
-
+       int i = 0;
        /* The upper limit here is just a safeguard. If there is a system with
         * more than 100 batteries, this can easily be increased. */
-       for (i = 0; i < 100; i++)
+       for (; i < 100; i++)
        {
                FILE *fh;
 
@@ -804,9 +800,7 @@ static int battery_read (void) /* {{{ */
 
 static int battery_config (oconfig_item_t *ci)
 {
-       int i;
-
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
 
index 6eac159..7fda034 100644 (file)
@@ -36,6 +36,7 @@
 #endif /* STRPTIME_NEEDS_STANDARDS */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -54,7 +55,7 @@
 # define BIND_DEFAULT_URL "http://localhost:8053/"
 #endif
 
-/* 
+/*
  * Some types used for the callback functions. `translation_table_ptr_t' and
  * `list_info_ptr_t' are passed to the callbacks in the `void *user_data'
  * pointer.
@@ -277,14 +278,14 @@ static size_t bind_curl_callback (void *buf, size_t size, /* {{{ */
 {
   size_t len = size * nmemb;
 
-  if (len <= 0)
+  if (len == 0)
     return (len);
 
   if ((bind_buffer_fill + len) >= bind_buffer_size)
   {
     char *temp;
 
-    temp = realloc(bind_buffer, bind_buffer_fill + len + 1);
+    temp = realloc (bind_buffer, bind_buffer_fill + len + 1);
     if (temp == NULL)
     {
       ERROR ("bind plugin: realloc failed.");
@@ -309,12 +310,11 @@ static int bind_xml_table_callback (const char *name, value_t value, /* {{{ */
     time_t current_time, void *user_data)
 {
   translation_table_ptr_t *table = (translation_table_ptr_t *) user_data;
-  size_t i;
 
   if (table == NULL)
     return (-1);
 
-  for (i = 0; i < table->table_length; i++)
+  for (size_t i = 0; i < table->table_length; i++)
   {
     if (strcmp (table->table[i].xml_name, name) != 0)
       continue;
@@ -417,7 +417,7 @@ static int bind_xml_read_timestamp (const char *xpath_expression, /* {{{ */
   xmlNode *node;
   char *str_ptr;
   char *tmp;
-  struct tm tm;
+  struct tm tm = { 0 };
 
   xpathObj = xmlXPathEvalExpression (BAD_CAST xpath_expression, xpathCtx);
   if (xpathObj == NULL)
@@ -458,7 +458,6 @@ static int bind_xml_read_timestamp (const char *xpath_expression, /* {{{ */
     return (-1);
   }
 
-  memset (&tm, 0, sizeof(tm));
   tmp = strptime (str_ptr, "%Y-%m-%dT%T", &tm);
   xmlFree(str_ptr);
   if (tmp == NULL)
@@ -474,7 +473,7 @@ static int bind_xml_read_timestamp (const char *xpath_expression, /* {{{ */
   return (0);
 } /* }}} int bind_xml_read_timestamp */
 
-/* 
+/*
  * bind_parse_generic_name_value
  *
  * Reads statistics in the form:
@@ -491,7 +490,6 @@ static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ *
 {
   xmlXPathObject *xpathObj = NULL;
   int num_entries;
-  int i;
 
   xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx);
   if (xpathObj == NULL)
@@ -503,19 +501,18 @@ static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ *
 
   num_entries = 0;
   /* Iterate over all matching nodes. */
-  for (i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
+  for (int i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
   {
     xmlNode *name_node = NULL;
     xmlNode *counter = NULL;
     xmlNode *parent;
-    xmlNode *child;
 
     parent = xpathObj->nodesetval->nodeTab[i];
     DEBUG ("bind plugin: bind_parse_generic_name_value: parent->name = %s;",
         (char *) parent->name);
 
     /* Iterate over all child nodes. */
-    for (child = parent->xmlChildrenNode;
+    for (xmlNode *child = parent->xmlChildrenNode;
         child != NULL;
         child = child->next)
     {
@@ -559,7 +556,7 @@ static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ *
   return (0);
 } /* }}} int bind_parse_generic_name_value */
 
-/* 
+/*
  * bind_parse_generic_value_list
  *
  * Reads statistics in the form:
@@ -578,7 +575,6 @@ static int bind_parse_generic_value_list (const char *xpath_expression, /* {{{ *
 {
   xmlXPathObject *xpathObj = NULL;
   int num_entries;
-  int i;
 
   xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx);
   if (xpathObj == NULL)
@@ -590,12 +586,10 @@ static int bind_parse_generic_value_list (const char *xpath_expression, /* {{{ *
 
   num_entries = 0;
   /* Iterate over all matching nodes. */
-  for (i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
+  for (int i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
   {
-    xmlNode *child;
-
     /* Iterate over all child nodes. */
-    for (child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
+    for (xmlNode *child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
         child != NULL;
         child = child->next)
     {
@@ -649,7 +643,6 @@ static int bind_parse_generic_name_attr_value_list (const char *xpath_expression
 {
   xmlXPathObject *xpathObj = NULL;
   int num_entries;
-  int i;
 
   xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx);
   if (xpathObj == NULL)
@@ -661,12 +654,10 @@ static int bind_parse_generic_name_attr_value_list (const char *xpath_expression
 
   num_entries = 0;
   /* Iterate over all matching nodes. */
-  for (i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
+  for (int i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
   {
-    xmlNode *child;
-
     /* Iterate over all child nodes. */
-    for (child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
+    for (xmlNode *child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
         child != NULL;
         child = child->next)
     {
@@ -714,7 +705,6 @@ static int bind_xml_stats_handle_zone (int version, xmlDoc *doc, /* {{{ */
 {
   xmlXPathObject *path_obj;
   char *zone_name = NULL;
-  int i;
   size_t j;
 
   if (version >= 3)
@@ -738,7 +728,7 @@ static int bind_xml_stats_handle_zone (int version, xmlDoc *doc, /* {{{ */
       return (-1);
     }
 
-    for (i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++)
+    for (int i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++)
     {
       zone_name = (char *) xmlNodeListGetString (doc,
           path_obj->nodesetval->nodeTab[i]->xmlChildrenNode, 1);
@@ -774,7 +764,7 @@ static int bind_xml_stats_handle_zone (int version, xmlDoc *doc, /* {{{ */
   { /* Parse the <counters> tag {{{ */
     char plugin_instance[DATA_MAX_NAME_LEN];
     translation_table_ptr_t table_ptr =
-    { 
+    {
       nsstats_translation_table,
       nsstats_translation_table_length,
       plugin_instance
@@ -817,7 +807,6 @@ static int bind_xml_stats_search_zones (int version, xmlDoc *doc, /* {{{ */
 {
   xmlXPathObject *zone_nodes = NULL;
   xmlXPathContext *zone_path_context;
-  int i;
 
   zone_path_context = xmlXPathNewContext (doc);
   if (zone_path_context == NULL)
@@ -834,7 +823,7 @@ static int bind_xml_stats_search_zones (int version, xmlDoc *doc, /* {{{ */
     return (-1);
   }
 
-  for (i = 0; i < zone_nodes->nodesetval->nodeNr; i++)
+  for (int i = 0; i < zone_nodes->nodesetval->nodeNr; i++)
   {
     node = zone_nodes->nodesetval->nodeTab[i];
     assert (node != NULL);
@@ -855,7 +844,6 @@ static int bind_xml_stats_handle_view (int version, xmlDoc *doc, /* {{{ */
 {
   char *view_name = NULL;
   cb_view_t *view;
-  int i;
   size_t j;
 
   if (version == 3)
@@ -887,7 +875,7 @@ static int bind_xml_stats_handle_view (int version, xmlDoc *doc, /* {{{ */
       return (-1);
     }
 
-    for (i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++)
+    for (int i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++)
     {
       view_name = (char *) xmlNodeListGetString (doc,
           path_obj->nodesetval->nodeTab[i]->xmlChildrenNode, 1);
@@ -955,7 +943,7 @@ static int bind_xml_stats_handle_view (int version, xmlDoc *doc, /* {{{ */
   {
     char plugin_instance[DATA_MAX_NAME_LEN];
     translation_table_ptr_t table_ptr =
-    { 
+    {
       resstats_translation_table,
       resstats_translation_table_length,
       plugin_instance
@@ -1010,7 +998,6 @@ static int bind_xml_stats_search_views (int version, xmlDoc *doc, /* {{{ */
 {
   xmlXPathObject *view_nodes = NULL;
   xmlXPathContext *view_path_context;
-  int i;
 
   view_path_context = xmlXPathNewContext (doc);
   if (view_path_context == NULL)
@@ -1027,7 +1014,7 @@ static int bind_xml_stats_search_views (int version, xmlDoc *doc, /* {{{ */
     return (-1);
   }
 
-  for (i = 0; i < view_nodes->nodesetval->nodeNr; i++)
+  for (int i = 0; i < view_nodes->nodesetval->nodeNr; i++)
   {
     xmlNode *node;
 
@@ -1441,7 +1428,6 @@ static int bind_xml (const char *data) /* {{{ */
   xmlXPathContext *xpathCtx = NULL;
   xmlXPathObject *xpathObj = NULL;
   int ret = -1;
-  int i;
 
   doc = xmlParseMemory (data, strlen (data));
   if (doc == NULL)
@@ -1471,7 +1457,7 @@ static int bind_xml (const char *data) /* {{{ */
   }
   else
   {
-    for (i = 0; i < xpathObj->nodesetval->nodeNr; i++)
+    for (int i = 0; i < xpathObj->nodesetval->nodeNr; i++)
     {
       xmlNode *node;
       char *attr_version;
@@ -1533,7 +1519,7 @@ static int bind_xml (const char *data) /* {{{ */
     return (-1);
   }
 
-  for (i = 0; i < xpathObj->nodesetval->nodeNr; i++)
+  for (int i = 0; i < xpathObj->nodesetval->nodeNr; i++)
   {
     xmlNode *node;
     char *attr_version;
@@ -1613,7 +1599,7 @@ static int bind_config_add_view_zone (cb_view_t *view, /* {{{ */
     return (-1);
   }
 
-  tmp = (char **) realloc (view->zones,
+  tmp = realloc (view->zones,
       sizeof (char *) * (view->zones_num + 1));
   if (tmp == NULL)
   {
@@ -1636,7 +1622,6 @@ static int bind_config_add_view_zone (cb_view_t *view, /* {{{ */
 static int bind_config_add_view (oconfig_item_t *ci) /* {{{ */
 {
   cb_view_t *tmp;
-  int i;
 
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
   {
@@ -1644,7 +1629,7 @@ static int bind_config_add_view (oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  tmp = (cb_view_t *) realloc (views, sizeof (*views) * (views_num + 1));
+  tmp = realloc (views, sizeof (*views) * (views_num + 1));
   if (tmp == NULL)
   {
     ERROR ("bind plugin: realloc failed.");
@@ -1668,7 +1653,7 @@ static int bind_config_add_view (oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -1693,9 +1678,7 @@ static int bind_config_add_view (oconfig_item_t *ci) /* {{{ */
 
 static int bind_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -1758,7 +1741,7 @@ static int bind_init (void) /* {{{ */
   curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 50L);
 #ifdef HAVE_CURLOPT_TIMEOUT_MS
   curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (timeout >= 0) ?
-      (long) timeout : CDTIME_T_TO_MS(plugin_get_interval()));
+      (long) timeout : (long) CDTIME_T_TO_MS(plugin_get_interval()));
 #endif
 
 
index 9c53a3e..5248a1a 100644 (file)
@@ -27,6 +27,7 @@
 #define _BSD_SOURCE
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -37,6 +38,9 @@
 #if HAVE_YAJL_YAJL_VERSION_H
 #include <yajl/yajl_version.h>
 #endif
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
 
 #include <limits.h>
 #include <poll.h>
@@ -45,7 +49,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <strings.h>
-#include <sys/socket.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/un.h>
@@ -97,7 +100,7 @@ enum ceph_dset_type_d
 };
 
 /** Valid types for ceph defined in types.db */
-const char * ceph_dset_types [CEPH_DSET_TYPES_NUM] =
+static const char * const ceph_dset_types [CEPH_DSET_TYPES_NUM] =
                                    {"ceph_latency", "ceph_bytes", "ceph_rate"};
 
 /******* ceph_daemon *******/
@@ -260,7 +263,7 @@ static int ceph_cb_boolean(void *ctx, int bool_val)
 #define BUFFER_ADD(dest, src) do { \
     size_t dest_size = sizeof (dest); \
     strncat ((dest), (src), dest_size - strlen (dest)); \
-    (dest)[dest_size - 1] = 0; \
+    (dest)[dest_size - 1] = '\0'; \
 } while (0)
 
 static int
@@ -270,14 +273,13 @@ ceph_cb_number(void *ctx, const char *number_val, yajl_len_t number_len)
     char buffer[number_len+1];
     char key[2 * DATA_MAX_NAME_LEN];
     _Bool latency_type = 0;
-    size_t i;
     int status;
 
+    key[0] = '\0';
     memcpy(buffer, number_val, number_len);
-    buffer[sizeof(buffer) - 1] = 0;
+    buffer[sizeof(buffer) - 1] = '\0';
 
-    memset (key, 0, sizeof (key));
-    for (i = 0; i < state->depth; i++)
+    for (size_t i = 0; i < state->depth; i++)
     {
         if (state->stack[i] == NULL)
             continue;
@@ -423,8 +425,7 @@ static void ceph_daemon_print(const struct ceph_daemon *d)
 
 static void ceph_daemons_print(void)
 {
-    int i;
-    for(i = 0; i < g_num_daemons; ++i)
+    for(int i = 0; i < g_num_daemons; ++i)
     {
         ceph_daemon_print(g_daemons[i]);
     }
@@ -432,15 +433,15 @@ static void ceph_daemons_print(void)
 
 static void ceph_daemon_free(struct ceph_daemon *d)
 {
-    int i = 0;
-    for(; i < d->last_idx; i++)
+    for(int i = 0; i < d->last_idx; i++)
     {
         sfree(d->last_poll_data[i]);
     }
     sfree(d->last_poll_data);
     d->last_poll_data = NULL;
     d->last_idx = 0;
-    for(i = 0; i < d->ds_num; i++)
+
+    for(int i = 0; i < d->ds_num; i++)
     {
         sfree(d->ds_names[i]);
     }
@@ -549,10 +550,9 @@ static _Bool has_suffix (char const *str, char const *suffix)
 /* count_parts returns the number of elements a "foo.bar.baz" style key has. */
 static size_t count_parts (char const *key)
 {
-    char const *ptr;
     size_t parts_num = 0;
 
-    for (ptr = key; ptr != NULL; ptr = strchr (ptr + 1, '.'))
+    for (const char *ptr = key; ptr != NULL; ptr = strchr (ptr + 1, '.'))
         parts_num++;
 
     return parts_num;
@@ -594,7 +594,6 @@ static int ceph_daemon_add_ds_entry(struct ceph_daemon *d, const char *name,
 {
     uint32_t type;
     char ds_name[DATA_MAX_NAME_LEN];
-    memset(ds_name, 0, sizeof(ds_name));
 
     if(convert_special_metrics)
     {
@@ -624,7 +623,7 @@ static int ceph_daemon_add_ds_entry(struct ceph_daemon *d, const char *name,
         return -ENOMEM;
     }
 
-    d->ds_names[d->ds_num] = malloc(sizeof(char) * DATA_MAX_NAME_LEN);
+    d->ds_names[d->ds_num] = malloc(DATA_MAX_NAME_LEN);
     if(!d->ds_names[d->ds_num])
     {
         return -ENOMEM;
@@ -685,10 +684,9 @@ static int cc_handle_bool(struct oconfig_item_s *item, int *dest)
 
 static int cc_add_daemon_config(oconfig_item_t *ci)
 {
-    int ret, i;
-    struct ceph_daemon *nd, cd;
+    int ret;
+    struct ceph_daemon *nd, cd = { 0 };
     struct ceph_daemon **tmp;
-    memset(&cd, 0, sizeof(struct ceph_daemon));
 
     if((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
     {
@@ -703,7 +701,7 @@ static int cc_add_daemon_config(oconfig_item_t *ci)
         return ret;
     }
 
-    for(i=0; i < ci->children_num; i++)
+    for(int i=0; i < ci->children_num; i++)
     {
         oconfig_item_t *child = ci->children + i;
 
@@ -748,7 +746,7 @@ static int cc_add_daemon_config(oconfig_item_t *ci)
     }
     g_daemons = tmp;
 
-    nd = malloc(sizeof(*nd));
+    nd = malloc(sizeof (*nd));
     if(!nd)
     {
         return ENOMEM;
@@ -760,9 +758,9 @@ static int cc_add_daemon_config(oconfig_item_t *ci)
 
 static int ceph_config(oconfig_item_t *ci)
 {
-    int ret, i;
+    int ret;
 
-    for(i = 0; i < ci->children_num; ++i)
+    for(int i = 0; i < ci->children_num; ++i)
     {
         oconfig_item_t *child = ci->children + i;
         if(strcasecmp("Daemon", child->key) == 0)
@@ -846,7 +844,7 @@ node_handler_define_schema(void *arg, const char *val, const char *key)
 static int add_last(struct ceph_daemon *d, const char *ds_n, double cur_sum,
         uint64_t cur_count)
 {
-    d->last_poll_data[d->last_idx] = malloc(1 * sizeof(struct last_data));
+    d->last_poll_data[d->last_idx] = malloc(sizeof (*d->last_poll_data[d->last_idx]));
     if(!d->last_poll_data[d->last_idx])
     {
         return -ENOMEM;
@@ -874,7 +872,7 @@ static int update_last(struct ceph_daemon *d, const char *ds_n, int index,
 
     if(!d->last_poll_data)
     {
-        d->last_poll_data = malloc(1 * sizeof(struct last_data *));
+        d->last_poll_data = malloc(sizeof (*d->last_poll_data));
         if(!d->last_poll_data)
         {
             return -ENOMEM;
@@ -899,8 +897,7 @@ static int update_last(struct ceph_daemon *d, const char *ds_n, int index,
  */
 static int backup_search_for_last_avg(struct ceph_daemon *d, const char *ds_n)
 {
-    int i = 0;
-    for(; i < d->last_idx; i++)
+    for(int i = 0; i < d->last_idx; i++)
     {
         if(strcmp(d->last_poll_data[i]->ds_name, ds_n) == 0)
         {
@@ -960,12 +957,11 @@ static double get_last_avg(struct ceph_daemon *d, const char *ds_n, int index,
  */
 static uint32_t backup_search_for_type(struct ceph_daemon *d, char *ds_name)
 {
-    int idx = 0;
-    for(; idx < d->ds_num; idx++)
+    for(int i = 0; i < d->ds_num; i++)
     {
-        if(strcmp(d->ds_names[idx], ds_name) == 0)
+        if(strcmp(d->ds_names[i], ds_name) == 0)
         {
-            return d->ds_types[idx];
+            return d->ds_types[i];
         }
     }
     return DSET_TYPE_UNFOUND;
@@ -984,7 +980,6 @@ static int node_handler_fetch_data(void *arg, const char *val, const char *key)
     int index = vtmp->index;
 
     char ds_name[DATA_MAX_NAME_LEN];
-    memset(ds_name, 0, sizeof(ds_name));
 
     if (parse_keys (ds_name, sizeof (ds_name), key))
     {
@@ -1087,7 +1082,7 @@ static int node_handler_fetch_data(void *arg, const char *val, const char *key)
 
 static int cconn_connect(struct cconn *io)
 {
-    struct sockaddr_un address;
+    struct sockaddr_un address = { 0 };
     int flags, fd, err;
     if(io->state != CSTATE_UNCONNECTED)
     {
@@ -1102,7 +1097,6 @@ static int cconn_connect(struct cconn *io)
             "failed: error %d", err);
         return err;
     }
-    memset(&address, 0, sizeof(struct sockaddr_un));
     address.sun_family = AF_UNIX;
     snprintf(address.sun_path, sizeof(address.sun_path), "%s",
             io->d->asok_path);
@@ -1462,7 +1456,7 @@ static int milli_diff(const struct timeval *t1, const struct timeval *t2)
  */
 static int cconn_main_loop(uint32_t request_type)
 {
-    int i, ret, some_unreachable = 0;
+    int ret, some_unreachable = 0;
     struct timeval end_tv;
     struct cconn io_array[g_num_daemons];
 
@@ -1470,7 +1464,7 @@ static int cconn_main_loop(uint32_t request_type)
 
     /* create cconn array */
     memset(io_array, 0, sizeof(io_array));
-    for(i = 0; i < g_num_daemons; ++i)
+    for(int i = 0; i < g_num_daemons; ++i)
     {
         io_array[i].d = g_daemons[i];
         io_array[i].request_type = request_type;
@@ -1489,7 +1483,7 @@ static int cconn_main_loop(uint32_t request_type)
         struct pollfd fds[g_num_daemons];
         memset(fds, 0, sizeof(fds));
         nfds = 0;
-        for(i = 0; i < g_num_daemons; ++i)
+        for(int i = 0; i < g_num_daemons; ++i)
         {
             struct cconn *io = io_array + i;
             ret = cconn_prepare(io, fds + nfds);
@@ -1527,7 +1521,7 @@ static int cconn_main_loop(uint32_t request_type)
             ERROR("ceph plugin: poll(2) error: %d", ret);
             goto done;
         }
-        for(i = 0; i < nfds; ++i)
+        for(int i = 0; i < nfds; ++i)
         {
             struct cconn *io = polled_io_array[i];
             int revents = fds[i].revents;
@@ -1558,7 +1552,7 @@ static int cconn_main_loop(uint32_t request_type)
             }
         }
     }
-    done: for(i = 0; i < g_num_daemons; ++i)
+    done: for(int i = 0; i < g_num_daemons; ++i)
     {
         cconn_close(io_array + i);
     }
@@ -1582,6 +1576,22 @@ static int ceph_read(void)
 static int ceph_init(void)
 {
     int ret;
+
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_DAC_OVERRIDE)
+  if (check_capability (CAP_DAC_OVERRIDE) != 0)
+  {
+    if (getuid () == 0)
+      WARNING ("ceph plugin: Running collectd as root, but the "
+          "CAP_DAC_OVERRIDE capability is missing. The plugin's read "
+          "function will probably fail. Is your init system dropping "
+          "capabilities?");
+    else
+      WARNING ("ceph plugin: collectd doesn't have the CAP_DAC_OVERRIDE "
+          "capability. If you don't want to run collectd as root, try running "
+          "\"setcap cap_dac_override=ep\" on the collectd binary.");
+  }
+#endif
+
     ceph_daemons_print();
 
     ret = cconn_main_loop(ASOK_REQ_VERSION);
@@ -1591,8 +1601,7 @@ static int ceph_init(void)
 
 static int ceph_shutdown(void)
 {
-    int i;
-    for(i = 0; i < g_num_daemons; ++i)
+    for(int i = 0; i < g_num_daemons; ++i)
     {
         ceph_daemon_free(g_daemons[i]);
     }
index ae67125..91f084f 100644 (file)
@@ -24,8 +24,8 @@
 
 struct case_s
 {
-  char *key;
-  char *value;
+  const char *key;
+  const char *value;
 };
 typedef struct case_s case_t;
 
@@ -136,22 +136,23 @@ DEF_TEST(traverse_json)
   yajl_handle hndl;
 #if HAVE_YAJL_V2
   hndl = yajl_alloc (&callbacks, NULL, &ctx);
-  CHECK_ZERO (traverse_json ((unsigned char *) json, (uint32_t) strlen (json), hndl));
+  CHECK_ZERO (traverse_json ((const unsigned char *) json, (uint32_t) strlen (json), hndl));
   CHECK_ZERO (yajl_complete_parse (hndl));
 #else
   hndl = yajl_alloc (&callbacks, NULL, NULL, &ctx);
-  CHECK_ZERO (traverse_json ((unsigned char *) json, (uint32_t) strlen (json), hndl));
+  CHECK_ZERO (traverse_json ((const unsigned char *) json, (uint32_t) strlen (json), hndl));
   CHECK_ZERO (yajl_parse_complete (hndl));
 #endif
 
+  yajl_free (hndl);
   return 0;
 }
 
 DEF_TEST(parse_keys)
 {
   struct {
-    char *str;
-    char *want;
+    const char *str;
+    const char *want;
   } cases[] = {
     {"WBThrottle.bytes_dirtied.description.bytes_wb.description.ios_dirtied.description.ios_wb.type", "WBThrottle.bytesDirtied.description.bytesWb.description.iosDirt"},
     {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
@@ -168,13 +169,10 @@ DEF_TEST(parse_keys)
 
   for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
   {
-    char got[DATA_MAX_NAME_LEN];
-
-    memset (got, 0, sizeof (got));
+    char got[64];
 
     CHECK_ZERO (parse_keys (got, sizeof (got), cases[i].str));
-
-    CHECK_ZERO (strcmp (got, cases[i].want));
+    EXPECT_EQ_STR (cases[i].want, got);
   }
 
   return 0;
index 6d41972..3a59ec4 100644 (file)
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -206,18 +207,16 @@ static int cgroups_config (const char *key, const char *value)
 
 static int cgroups_read (void)
 {
-       cu_mount_t *mnt_list;
-       cu_mount_t *mnt_ptr;
+       cu_mount_t *mnt_list = NULL;
        _Bool cgroup_found = 0;
 
-       mnt_list = NULL;
        if (cu_mount_getlist (&mnt_list) == NULL)
        {
                ERROR ("cgroups plugin: cu_mount_getlist failed.");
                return (-1);
        }
 
-       for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
+       for (cu_mount_t *mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
        {
                /* Find the cgroup mountpoint which contains the cpuacct
                 * controller. */
diff --git a/src/chrony.c b/src/chrony.c
new file mode 100644 (file)
index 0000000..f6294e4
--- /dev/null
@@ -0,0 +1,1123 @@
+/* chrony plugin for collectd (monitoring of chrony time server daemon)
+ **********************************************************************
+ * Copyright (C) Claudius M Zingerli, ZSeng, 2015-2016 
+ *
+ * Internals roughly based on the ntpd plugin
+ * Some functions copied from chronyd/web (as marked)
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * 
+ * TODO:
+ *     - More robust udp parsing (using offsets instead of structs?)
+ *       -> Currently chrony parses its data the same way as we do (using structs)
+ *     - Plausibility checks on values received
+ *       -> Done at higher levels
+ */
+
+#include "collectd.h"
+
+#include "common.h"             /* auxiliary functions */
+#include "plugin.h"             /* plugin_register_*, plugin_dispatch_values */
+
+#if HAVE_NETDB_H
+#  include <netdb.h>            /* struct addrinfo */
+#endif
+#if HAVE_ARPA_INET_H
+#  include <arpa/inet.h>        /* ntohs/ntohl */
+#endif
+
+
+#define CONFIG_KEY_HOST    "Host"
+#define CONFIG_KEY_PORT    "Port"
+#define CONFIG_KEY_TIMEOUT "Timeout"
+
+#define URAND_DEVICE_PATH  "/dev/urandom"       /* Used to initialize seq nr generator */
+#define RAND_DEVICE_PATH   "/dev/random"        /* Used to initialize seq nr generator (fall back) */
+
+static const char *g_config_keys[] = {
+  CONFIG_KEY_HOST,
+  CONFIG_KEY_PORT,
+  CONFIG_KEY_TIMEOUT
+};
+
+static int       g_config_keys_num = STATIC_ARRAY_SIZE(g_config_keys);
+static int       g_chrony_is_connected;
+static int       g_chrony_socket  = -1;
+static time_t    g_chrony_timeout = -1;
+static char     *g_chrony_plugin_instance;
+static char     *g_chrony_host;
+static char     *g_chrony_port;
+static uint32_t  g_chrony_rand    = 1;
+static uint32_t  g_chrony_seq_is_initialized;
+
+#define PLUGIN_NAME_SHORT "chrony"
+#define PLUGIN_NAME       PLUGIN_NAME_SHORT " plugin"
+#define DAEMON_NAME       PLUGIN_NAME_SHORT
+#define CHRONY_DEFAULT_HOST "localhost"
+#define CHRONY_DEFAULT_PORT "323"
+#define CHRONY_DEFAULT_TIMEOUT 2
+
+/* Return codes (collectd expects non-zero on errors) */
+#define CHRONY_RC_OK    0
+#define CHRONY_RC_FAIL  1
+
+/* Chronyd command packet variables adapted from chrony/candm.h (GPL2) */
+#define PROTO_VERSION_NUMBER 6
+#define IPADDR_UNSPEC 0
+#define IPADDR_INET4  1
+#define IPADDR_INET6  2
+#define IPV6_STR_MAX_SIZE (8*4+7+1)
+
+typedef enum
+{
+  PKT_TYPE_CMD_REQUEST = 1,
+  PKT_TYPE_CMD_REPLY   = 2
+} ePacketType;
+
+typedef enum
+{
+  REQ_N_SOURCES    = 14,
+  REQ_SOURCE_DATA  = 15,
+  REQ_TRACKING     = 33,
+  REQ_SOURCE_STATS = 34
+} eDaemonRequests;
+
+
+typedef enum
+{
+  RPY_NULL             = 1,
+  RPY_N_SOURCES        = 2,
+  RPY_SOURCE_DATA      = 3,
+  RPY_MANUAL_TIMESTAMP = 4,
+  RPY_TRACKING         = 5,
+  RPY_SOURCE_STATS     = 6,
+  RPY_RTC              = 7
+} eDaemonReplies;
+
+
+#if defined(__GNUC__) || defined (__SUNPRO_C) || defined(lint)
+#  /* extension to enforce struct packing. */
+#  define ATTRIB_PACKED __attribute__((packed))
+#else
+#  error Not defining packed attribute (unknown compiler)
+#  define ATTRIB_PACKED 
+#endif
+
+typedef struct ATTRIB_PACKED
+{
+  int32_t value;
+} tFloat;
+
+typedef struct ATTRIB_PACKED
+{
+  uint32_t tv_sec_high;
+  uint32_t tv_sec_low;
+  uint32_t tv_nsec;
+} tTimeval;
+
+typedef enum
+{
+  STT_SUCCESS        =  0,
+  STT_FAILED         =  1,
+  STT_UNAUTH         =  2,
+  STT_INVALID        =  3,
+  STT_NOSUCHSOURCE   =  4,
+  STT_INVALIDTS      =  5,
+  STT_NOTENABLED     =  6,
+  STT_BADSUBNET      =  7,
+  STT_ACCESSALLOWED  =  8,
+  STT_ACCESSDENIED   =  9,
+  STT_NOHOSTACCESS   = 10,
+  STT_SOURCEALREADYKNOWN = 11,
+  STT_TOOMANYSOURCES = 12,
+  STT_NORTC          = 13,
+  STT_BADRTCFILE     = 14,
+  STT_INACTIVE       = 15,
+  STT_BADSAMPLE      = 16,
+  STT_INVALIDAF      = 17,
+  STT_BADPKTVERSION  = 18,
+  STT_BADPKTLENGTH   = 19
+} eChrony_Status;
+
+/* Chrony client request packets */
+typedef struct ATTRIB_PACKED
+{
+  uint8_t f_dummy0[80];         /* Chrony expects 80bytes dummy data (Avoiding UDP Amplification) */
+} tChrony_Req_Tracking;
+
+typedef struct ATTRIB_PACKED
+{
+  uint32_t f_n_sources;
+} tChrony_Req_N_Sources;
+
+typedef struct ATTRIB_PACKED
+{
+  int32_t f_index;
+  uint8_t f_dummy0[44];
+} tChrony_Req_Source_data;
+
+typedef struct ATTRIB_PACKED
+{
+  int32_t f_index;
+  uint8_t f_dummy0[56];
+} tChrony_Req_Source_stats;
+
+typedef struct ATTRIB_PACKED
+{
+  struct
+  {
+    uint8_t f_version;
+    uint8_t f_type;
+    uint8_t f_dummy0;
+    uint8_t f_dummy1;
+    uint16_t f_cmd;
+    uint16_t f_cmd_try;
+    uint32_t f_seq;
+
+    uint32_t f_dummy2;
+    uint32_t f_dummy3;
+  } header;                     /* Packed: 20Bytes */
+  union
+  {
+    tChrony_Req_N_Sources n_sources;
+    tChrony_Req_Source_data source_data;
+    tChrony_Req_Source_stats source_stats;
+    tChrony_Req_Tracking tracking;
+  } body;
+  uint8_t padding[4 + 16];      /* Padding to match minimal response size */
+} tChrony_Request;
+
+/* Chrony daemon response packets */
+typedef struct ATTRIB_PACKED
+{
+  uint32_t f_n_sources;
+} tChrony_Resp_N_Sources;
+
+typedef struct ATTRIB_PACKED
+{
+  union
+  {
+    uint32_t ip4;
+    uint8_t ip6[16];
+  } addr;
+  uint16_t f_family;
+} tChrony_IPAddr;
+
+typedef struct ATTRIB_PACKED
+{
+  tChrony_IPAddr addr;
+  uint16_t dummy;               /* FIXME: Strange dummy space. Needed on gcc 4.8.3/clang 3.4.1 on x86_64 */
+  int16_t f_poll;               /* 2^f_poll = Time between polls (s) */
+  uint16_t f_stratum;           /* Remote clock stratum */
+  uint16_t f_state;             /* 0 = RPY_SD_ST_SYNC,    1 = RPY_SD_ST_UNREACH,   2 = RPY_SD_ST_FALSETICKER */
+                                /* 3 = RPY_SD_ST_JITTERY, 4 = RPY_SD_ST_CANDIDATE, 5 = RPY_SD_ST_OUTLIER     */
+  uint16_t f_mode;              /* 0 = RPY_SD_MD_CLIENT,  1 = RPY_SD_MD_PEER,      2 = RPY_SD_MD_REF         */
+  uint16_t f_flags;             /* unused */
+  uint16_t f_reachability;      /* Bit mask of successfull tries to reach the source */
+
+  uint32_t f_since_sample;      /* Time since last sample (s) */
+  tFloat f_origin_latest_meas;  /*  */
+  tFloat f_latest_meas;         /*  */
+  tFloat f_latest_meas_err;     /*  */
+} tChrony_Resp_Source_data;
+
+typedef struct ATTRIB_PACKED
+{
+  uint32_t f_ref_id;
+  tChrony_IPAddr addr;
+  uint16_t dummy;               /* FIXME: Strange dummy space. Needed on gcc 4.8.3/clang 3.4.1 on x86_64 */
+  uint32_t f_n_samples;         /* Number of measurements done   */
+  uint32_t f_n_runs;            /* How many measurements to come */
+  uint32_t f_span_seconds;      /* For how long we're measuring  */
+  tFloat f_rtc_seconds_fast;    /* ??? */
+  tFloat f_rtc_gain_rate_ppm;   /* Estimated relative frequency error */
+  tFloat f_skew_ppm;            /* Clock skew (ppm) (worst case freq est error (skew: peak2peak)) */
+  tFloat f_est_offset;          /* Estimated offset of source */
+  tFloat f_est_offset_err;      /* Error of estimation        */
+} tChrony_Resp_Source_stats;
+
+typedef struct ATTRIB_PACKED
+{
+  uint32_t f_ref_id;
+  tChrony_IPAddr addr;
+  uint16_t dummy;               /* FIXME: Strange dummy space. Needed on gcc 4.8.3/clang 3.4.1 on x86_64 */
+  uint16_t f_stratum;
+  uint16_t f_leap_status;
+  tTimeval f_ref_time;
+  tFloat f_current_correction;
+  tFloat f_last_offset;
+  tFloat f_rms_offset;
+  tFloat f_freq_ppm;
+  tFloat f_resid_freq_ppm;
+  tFloat f_skew_ppm;
+  tFloat f_root_delay;
+  tFloat f_root_dispersion;
+  tFloat f_last_update_interval;
+} tChrony_Resp_Tracking;
+
+typedef struct ATTRIB_PACKED
+{
+  struct
+  {
+    uint8_t f_version;
+    uint8_t f_type;
+    uint8_t f_dummy0;
+    uint8_t f_dummy1;
+    uint16_t f_cmd;
+    uint16_t f_reply;
+    uint16_t f_status;
+    uint16_t f_dummy2;
+    uint16_t f_dummy3;
+    uint16_t f_dummy4;
+    uint32_t f_seq;
+    uint32_t f_dummy5;
+    uint32_t f_dummy6;
+  } header;                     /* Packed: 28 Bytes */
+
+  union
+  {
+    tChrony_Resp_N_Sources n_sources;
+    tChrony_Resp_Source_data source_data;
+    tChrony_Resp_Source_stats source_stats;
+    tChrony_Resp_Tracking tracking;
+  } body;
+
+  uint8_t padding[1024];
+} tChrony_Response;
+
+
+/*****************************************************************************/
+/* Internal functions */
+/*****************************************************************************/
+
+/* connect_client code adapted from: http://long.ccaba.upc.edu/long/045Guidelines/eva/ipv6.html#daytimeClient6 */
+/* License granted by Eva M Castro via e-mail on 2016-02-18 under the terms of GPLv3 */
+static int
+connect_client(const char *p_hostname,
+               const char *p_service, int p_family, int p_socktype)
+{
+  struct addrinfo *res, *ressave;
+  int n, sockfd;
+
+  struct addrinfo ai_hints = {
+    .ai_family = p_family,
+    .ai_socktype = p_socktype
+  };
+
+  n = getaddrinfo(p_hostname, p_service, &ai_hints, &res);
+
+  if (n < 0)
+  {
+    ERROR(PLUGIN_NAME ": getaddrinfo error:: [%s]", gai_strerror(n));
+    return -1;
+  }
+
+  ressave = res;
+
+  sockfd = -1;
+  while (res)
+  {
+    sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+
+    if (!(sockfd < 0))
+    {
+      if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
+      {
+        /* Success */
+        break;
+      }
+
+      close(sockfd);
+      sockfd = -1;
+    }
+    res = res->ai_next;
+  }
+
+  freeaddrinfo(ressave);
+  return sockfd;
+}
+
+
+/* niptoha code originally from: git://git.tuxfamily.org/gitroot/chrony/chrony.git:util.c */
+/* Original code licensed as GPLv2, by Richard P. Purnow, Miroslav Lichvar */
+/* Original name: char * UTI_IPToString(IPAddr *addr)*/
+static char *
+niptoha(const tChrony_IPAddr * addr, char *p_buf, size_t p_buf_size)
+{
+  int rc = 1;
+  unsigned long a, b, c, d, ip;
+
+  switch (ntohs(addr->f_family))
+  {
+  case IPADDR_UNSPEC:
+    rc = snprintf(p_buf, p_buf_size, "[UNSPEC]");
+    break;
+  case IPADDR_INET4:
+    ip = ntohl(addr->addr.ip4);
+    a = (ip >> 24) & 0xff;
+    b = (ip >> 16) & 0xff;
+    c = (ip >> 8) & 0xff;
+    d = (ip >> 0) & 0xff;
+    rc = snprintf(p_buf, p_buf_size, "%ld.%ld.%ld.%ld", a, b, c, d);
+    break;
+  case IPADDR_INET6:
+  {
+    const char *rp = inet_ntop(AF_INET6, addr->addr.ip6, p_buf, p_buf_size);
+    if (rp == NULL)
+    {
+      ERROR(PLUGIN_NAME ": Error converting ipv6 address to string. Errno = %d", errno);
+      rc = snprintf(p_buf, p_buf_size, "[UNKNOWN]");
+    }
+    break;
+  }
+  default:
+    rc = snprintf(p_buf, p_buf_size, "[UNKNOWN]");
+  }
+  assert(rc > 0);
+  return p_buf;
+}
+
+
+static int
+chrony_set_timeout(void)
+{
+  /* Set the socket's  timeout to g_chrony_timeout; a value of 0 signals infinite timeout */
+  /* Returns 0 on success, !0 on error (check errno) */
+
+  struct timeval tv;
+  tv.tv_sec = g_chrony_timeout;
+  tv.tv_usec = 0;
+
+  assert(g_chrony_socket >= 0);
+  if (setsockopt(g_chrony_socket, SOL_SOCKET,
+      SO_RCVTIMEO, (char *) &tv, sizeof(struct timeval)) < 0)
+  {
+    return CHRONY_RC_FAIL;
+  }
+  return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_connect(void)
+{
+  /* Connects to the chrony daemon */
+  /* Returns 0 on success, !0 on error (check errno) */
+  int socket;
+
+  if (g_chrony_host == NULL)
+  {
+    g_chrony_host = strdup(CHRONY_DEFAULT_HOST);
+    if (g_chrony_host == NULL)
+    {
+      ERROR(PLUGIN_NAME ": Error duplicating chrony host name");
+      return CHRONY_RC_FAIL;
+    }
+  }
+  if (g_chrony_port == NULL)
+  {
+    g_chrony_port = strdup(CHRONY_DEFAULT_PORT);
+    if (g_chrony_port == NULL)
+    {
+      ERROR(PLUGIN_NAME ": Error duplicating chrony port string");
+      return CHRONY_RC_FAIL;
+    }
+  }
+  if (g_chrony_timeout < 0)
+  {
+    g_chrony_timeout = CHRONY_DEFAULT_TIMEOUT;
+    assert(g_chrony_timeout >= 0);
+  }
+
+  DEBUG(PLUGIN_NAME ": Connecting to %s:%s", g_chrony_host, g_chrony_port);
+  socket = connect_client(g_chrony_host, g_chrony_port, AF_UNSPEC, SOCK_DGRAM);
+  if (socket < 0)
+  {
+    ERROR(PLUGIN_NAME ": Error connecting to daemon. Errno = %d", errno);
+    return CHRONY_RC_FAIL;
+  }
+  DEBUG(PLUGIN_NAME ": Connected");
+  g_chrony_socket = socket;
+
+  if (chrony_set_timeout())
+  {
+    ERROR(PLUGIN_NAME ": Error setting timeout to %llds. Errno = %d",
+          (long long)g_chrony_timeout, errno);
+    return CHRONY_RC_FAIL;
+  }
+  return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_send_request(const tChrony_Request * p_req, size_t p_req_size)
+{
+  if (send(g_chrony_socket, p_req, p_req_size, 0) < 0)
+  {
+    ERROR(PLUGIN_NAME ": Error sending packet. Errno = %d", errno);
+    return CHRONY_RC_FAIL;
+  }
+  return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_recv_response(tChrony_Response * p_resp, size_t p_resp_max_size,
+                     size_t * p_resp_size)
+{
+  ssize_t rc = recv(g_chrony_socket, p_resp, p_resp_max_size, 0);
+  if (rc <= 0)
+  {
+    ERROR(PLUGIN_NAME ": Error receiving packet: %s (%d)", strerror(errno),
+          errno);
+    return CHRONY_RC_FAIL;
+  }
+  else
+  {
+    *p_resp_size = rc;
+    return CHRONY_RC_OK;
+  }
+}
+
+
+static int
+chrony_query(const int p_command, tChrony_Request * p_req,
+             tChrony_Response * p_resp, size_t * p_resp_size)
+{
+  /* Check connection. We simply perform one try as collectd already handles retries */
+  assert(p_req);
+  assert(p_resp);
+  assert(p_resp_size);
+
+  if (g_chrony_is_connected == 0)
+  {
+    if (chrony_connect() == CHRONY_RC_OK)
+    {
+      g_chrony_is_connected = 1;
+    }
+    else
+    {
+      ERROR(PLUGIN_NAME ": Unable to connect. Errno = %d", errno);
+      return CHRONY_RC_FAIL;
+    }
+  }
+
+  do
+  {
+    int valid_command = 0;
+    size_t req_size  = sizeof(p_req->header) + sizeof(p_req->padding);
+    size_t resp_size = sizeof(p_resp->header);
+    uint16_t resp_code = RPY_NULL;
+    switch (p_command)
+    {
+    case REQ_TRACKING:
+      req_size  += sizeof(p_req->body.tracking);
+      resp_size += sizeof(p_resp->body.tracking);
+      resp_code = RPY_TRACKING;
+      valid_command = 1;
+      break;
+    case REQ_N_SOURCES:
+      req_size  += sizeof(p_req->body.n_sources);
+      resp_size += sizeof(p_resp->body.n_sources);
+      resp_code = RPY_N_SOURCES;
+      valid_command = 1;
+      break;
+    case REQ_SOURCE_DATA:
+      req_size  += sizeof(p_req->body.source_data);
+      resp_size += sizeof(p_resp->body.source_data);
+      resp_code = RPY_SOURCE_DATA;
+      valid_command = 1;
+      break;
+    case REQ_SOURCE_STATS:
+      req_size  += sizeof(p_req->body.source_stats);
+      resp_size += sizeof(p_resp->body.source_stats);
+      resp_code = RPY_SOURCE_STATS;
+      valid_command = 1;
+      break;
+    default:
+      ERROR(PLUGIN_NAME ": Unknown request command (Was: %d)", p_command);
+      break;
+    }
+
+    if (valid_command == 0)
+      break;
+
+    uint32_t seq_nr = rand_r(&g_chrony_rand);
+    p_req->header.f_cmd = htons(p_command);
+    p_req->header.f_cmd_try = 0;
+    p_req->header.f_seq = seq_nr;
+
+    DEBUG(PLUGIN_NAME ": Sending request (.cmd = %d, .seq = %d)", p_command,
+          seq_nr);
+    if (chrony_send_request(p_req, req_size) != 0)
+      break;
+
+    DEBUG(PLUGIN_NAME ": Waiting for response");
+    if (chrony_recv_response(p_resp, resp_size, p_resp_size) != 0)
+      break;
+
+    DEBUG(PLUGIN_NAME
+          ": Received response: .version = %u, .type = %u, .cmd = %u, .reply = %u, .status = %u, .seq = %u",
+          p_resp->header.f_version, p_resp->header.f_type,
+          ntohs(p_resp->header.f_cmd), ntohs(p_resp->header.f_reply),
+          ntohs(p_resp->header.f_status), p_resp->header.f_seq);
+
+    if (p_resp->header.f_version != p_req->header.f_version)
+    {
+      ERROR(PLUGIN_NAME ": Wrong protocol version (Was: %d, expected: %d)",
+            p_resp->header.f_version, p_req->header.f_version);
+      return CHRONY_RC_FAIL;
+    }
+    if (p_resp->header.f_type != PKT_TYPE_CMD_REPLY)
+    {
+      ERROR(PLUGIN_NAME ": Wrong packet type (Was: %d, expected: %d)",
+            p_resp->header.f_type, PKT_TYPE_CMD_REPLY);
+      return CHRONY_RC_FAIL;
+    }
+    if (p_resp->header.f_seq != seq_nr)
+    {
+      /* FIXME: Implement sequence number handling */
+      ERROR(PLUGIN_NAME
+            ": Unexpected sequence number (Was: %d, expected: %d)",
+            p_resp->header.f_seq, p_req->header.f_seq);
+      return CHRONY_RC_FAIL;
+    }
+    if (p_resp->header.f_cmd != p_req->header.f_cmd)
+    {
+      ERROR(PLUGIN_NAME ": Wrong reply command (Was: %d, expected: %d)",
+            p_resp->header.f_cmd, p_req->header.f_cmd);
+      return CHRONY_RC_FAIL;
+    }
+
+    if (ntohs(p_resp->header.f_reply) != resp_code)
+    {
+      ERROR(PLUGIN_NAME ": Wrong reply code (Was: %d, expected: %d)",
+            ntohs(p_resp->header.f_reply), resp_code);
+      return CHRONY_RC_FAIL;
+    }
+
+    switch (p_resp->header.f_status)
+    {
+    case STT_SUCCESS:
+      DEBUG(PLUGIN_NAME ": Reply packet status STT_SUCCESS");
+      break;
+    default:
+      ERROR(PLUGIN_NAME
+            ": Reply packet contains error status: %d (expected: %d)",
+            p_resp->header.f_status, STT_SUCCESS);
+      return CHRONY_RC_FAIL;
+    }
+
+    /* Good result */
+    return CHRONY_RC_OK;
+  }
+  while (0);
+
+  /* Some error occured */
+  return CHRONY_RC_FAIL;
+}
+
+
+static void
+chrony_init_req(tChrony_Request * p_req)
+{
+  memset(p_req, 0, sizeof(*p_req));
+  p_req->header.f_version = PROTO_VERSION_NUMBER;
+  p_req->header.f_type    = PKT_TYPE_CMD_REQUEST;
+  p_req->header.f_dummy0  = 0;
+  p_req->header.f_dummy1  = 0;
+  p_req->header.f_dummy2  = 0;
+  p_req->header.f_dummy3  = 0;
+}
+
+
+/* ntohf code originally from: git://git.tuxfamily.org/gitroot/chrony/chrony.git:util.c */
+/* Original code licensed as GPLv2, by Richard P. Purnow, Miroslav Lichvar */
+/* Original name: double UTI_tFloatNetworkToHost(tFloat f) */
+static double
+ntohf(tFloat p_float)
+{
+  /* Convert tFloat in Network-bit-order to double in host-bit-order */
+
+#define FLOAT_EXP_BITS 7
+#define FLOAT_EXP_MIN (-(1 << (FLOAT_EXP_BITS - 1)))
+#define FLOAT_EXP_MAX (-FLOAT_EXP_MIN - 1)
+#define FLOAT_COEF_BITS ((int)sizeof (int32_t) * 8 - FLOAT_EXP_BITS)
+#define FLOAT_COEF_MIN (-(1 << (FLOAT_COEF_BITS - 1)))
+#define FLOAT_COEF_MAX (-FLOAT_COEF_MIN - 1)
+
+  int32_t exp, coef;
+  uint32_t uval;
+
+  uval = ntohl(p_float.value);
+  exp = (uval >> FLOAT_COEF_BITS) - FLOAT_COEF_BITS;
+  if (exp >= 1 << (FLOAT_EXP_BITS - 1))
+    exp -= 1 << FLOAT_EXP_BITS;
+
+  /* coef = (x << FLOAT_EXP_BITS) >> FLOAT_EXP_BITS; */
+  coef = uval % (1U << FLOAT_COEF_BITS);
+  if (coef >= 1 << (FLOAT_COEF_BITS - 1))
+    coef -= 1 << FLOAT_COEF_BITS;
+
+  return coef * pow(2.0, exp);
+}
+
+
+static void
+chrony_push_data(const char *p_type, const char *p_type_inst, double p_value)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = p_value;    /* TODO: Check type??? (counter, gauge, derive, absolute) */
+
+  vl.values = values;
+  vl.values_len = 1;
+
+  /* XXX: Shall g_chrony_host/g_chrony_port be reflected in the plugin's output? */
+  /* hostname_g is set in daemon/collectd.c (from config, via gethostname or by resolving localhost) */
+  /* defined as: char hostname_g[DATA_MAX_NAME_LEN]; (never NULL) */
+  sstrncpy(vl.host, hostname_g, sizeof(vl.host));
+  sstrncpy(vl.plugin, PLUGIN_NAME_SHORT, sizeof(vl.plugin));
+  if (g_chrony_plugin_instance != NULL)
+  {
+    sstrncpy(vl.plugin_instance, g_chrony_plugin_instance,
+             sizeof(vl.plugin_instance));
+  }
+  if (p_type != NULL)
+    sstrncpy(vl.type, p_type, sizeof(vl.type));
+
+  if (p_type_inst != NULL)
+    sstrncpy(vl.type_instance, p_type_inst, sizeof(vl.type_instance));
+
+  plugin_dispatch_values(&vl);
+}
+
+
+static void
+chrony_push_data_valid(const char *p_type, const char *p_type_inst, const int p_is_valid,
+                       double p_value)
+{
+  /* Push real value if p_is_valid is true, push NAN if p_is_valid is not true (idea from ntp plugin) */
+  if (p_is_valid == 0)
+    p_value = NAN;
+
+  chrony_push_data(p_type, p_type_inst, p_value);
+}
+
+
+static int
+chrony_init_seq(void)
+{
+  /* Initialize the sequence number generator from /dev/urandom */
+  /* Fallbacks: /dev/random and time(NULL) */
+
+  int fh;
+
+  /* Try urandom */
+  fh = open(URAND_DEVICE_PATH, O_RDONLY);
+  if (fh >= 0)
+  {
+    ssize_t rc = read(fh, &g_chrony_rand, sizeof(g_chrony_rand));
+    if (rc != sizeof(g_chrony_rand))
+    {
+      ERROR(PLUGIN_NAME ": Reading from random source \'%s\'failed: %s (%d)",
+            URAND_DEVICE_PATH, strerror(errno), errno);
+      close(fh);
+      return CHRONY_RC_FAIL;
+    }
+    close(fh);
+    DEBUG(PLUGIN_NAME ": Seeding RNG from " URAND_DEVICE_PATH);
+  }
+  else
+  {
+    if (errno == ENOENT)
+    {
+      /* URAND_DEVICE_PATH device not found. Try RAND_DEVICE_PATH as fall-back */
+      fh = open(RAND_DEVICE_PATH, O_RDONLY);
+      if (fh >= 0)
+      {
+        ssize_t rc = read(fh, &g_chrony_rand, sizeof(g_chrony_rand));
+        if (rc != sizeof(g_chrony_rand))
+        {
+          ERROR(PLUGIN_NAME
+                ": Reading from random source \'%s\'failed: %s (%d)",
+                RAND_DEVICE_PATH, strerror(errno), errno);
+          close(fh);
+          return CHRONY_RC_FAIL;
+        }
+        close(fh);
+        DEBUG(PLUGIN_NAME ": Seeding RNG from " RAND_DEVICE_PATH);
+      }
+      else
+      {
+        /* Error opening RAND_DEVICE_PATH. Try time(NULL) as fall-back */
+        DEBUG(PLUGIN_NAME ": Seeding RNG from time(NULL)");
+        g_chrony_rand = time(NULL) ^ getpid();
+      }
+    }
+    else
+    {
+      ERROR(PLUGIN_NAME ": Opening random source \'%s\' failed: %s (%d)",
+            URAND_DEVICE_PATH, strerror(errno), errno);
+      return CHRONY_RC_FAIL;
+    }
+  }
+
+  return CHRONY_RC_OK;
+}
+
+
+/*****************************************************************************/
+/* Exported functions */
+/*****************************************************************************/
+static int
+chrony_config(const char *p_key, const char *p_value)
+{
+  assert(p_key);
+  assert(p_value);
+
+  /* Parse config variables */
+  if (strcasecmp(p_key, CONFIG_KEY_HOST) == 0)
+  {
+    if (g_chrony_host != NULL)
+      free(g_chrony_host);
+
+    if ((g_chrony_host = strdup(p_value)) == NULL)
+    {
+      ERROR(PLUGIN_NAME ": Error duplicating host name");
+      return CHRONY_RC_FAIL;
+    }
+  }
+  else
+  {
+    if (strcasecmp(p_key, CONFIG_KEY_PORT) == 0)
+    {
+      if (g_chrony_port != NULL)
+        free(g_chrony_port);
+
+      if ((g_chrony_port = strdup(p_value)) == NULL)
+      {
+        ERROR(PLUGIN_NAME ": Error duplicating port name");
+        return CHRONY_RC_FAIL;
+      }
+    }
+    else
+    {
+      if (strcasecmp(p_key, CONFIG_KEY_TIMEOUT) == 0)
+      {
+        time_t tosec = strtol(p_value, NULL, 0);
+        g_chrony_timeout = tosec;
+      }
+      else
+      {
+        WARNING(PLUGIN_NAME ": Unknown configuration variable: %s %s", p_key, p_value);
+        return CHRONY_RC_FAIL;
+      }
+    }
+  }
+  /* XXX: We could set g_chrony_plugin_instance here to "g_chrony_host-g_chrony_port", but as multiple instances aren't yet supported, we skip this for now */
+
+  return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_request_daemon_stats(void)
+{
+  /* Perform Tracking request */
+  int rc;
+  size_t chrony_resp_size;
+  tChrony_Request chrony_req;
+  tChrony_Response chrony_resp;
+
+  chrony_init_req(&chrony_req);
+  rc =
+    chrony_query(REQ_TRACKING, &chrony_req, &chrony_resp, &chrony_resp_size);
+  if (rc != 0)
+  {
+    ERROR(PLUGIN_NAME ": chrony_query (REQ_TRACKING) failed with status %i",
+          rc);
+    return rc;
+  }
+#if COLLECT_DEBUG
+  {
+    char src_addr[IPV6_STR_MAX_SIZE] = { 0 };
+    niptoha(&chrony_resp.body.tracking.addr, src_addr, sizeof(src_addr));
+    DEBUG(PLUGIN_NAME ": Daemon stat: .addr = %s, .ref_id= %u, .stratum = %u, .leap_status = %u, .ref_time = %u:%u:%u, .current_correction = %f, .last_offset = %f, .rms_offset = %f, .freq_ppm = %f, .skew_ppm = %f, .root_delay = %f, .root_dispersion = %f, .last_update_interval = %f", src_addr, ntohs(chrony_resp.body.tracking.f_ref_id),  
+          ntohs(chrony_resp.body.tracking.f_stratum),
+          ntohs(chrony_resp.body.tracking.f_leap_status),
+          ntohl(chrony_resp.body.tracking.f_ref_time.tv_sec_high),
+          ntohl(chrony_resp.body.tracking.f_ref_time.tv_sec_low),
+          ntohl(chrony_resp.body.tracking.f_ref_time.tv_nsec),
+          ntohf(chrony_resp.body.tracking.f_current_correction),
+          ntohf(chrony_resp.body.tracking.f_last_offset),
+          ntohf(chrony_resp.body.tracking.f_rms_offset),
+          ntohf(chrony_resp.body.tracking.f_freq_ppm),
+          ntohf(chrony_resp.body.tracking.f_skew_ppm),
+          ntohf(chrony_resp.body.tracking.f_root_delay),
+          ntohf(chrony_resp.body.tracking.f_root_dispersion),
+          ntohf(chrony_resp.body.tracking.f_last_update_interval));
+  }
+#endif
+
+  double time_ref = ntohl(chrony_resp.body.tracking.f_ref_time.tv_nsec);
+  time_ref /= 1000000000.0;
+  time_ref += ntohl(chrony_resp.body.tracking.f_ref_time.tv_sec_low);
+  if (chrony_resp.body.tracking.f_ref_time.tv_sec_high)
+  {
+    double secs_high =
+      ntohl(chrony_resp.body.tracking.f_ref_time.tv_sec_high);
+    secs_high *= 4294967296.0;
+    time_ref += secs_high;
+  }
+
+  /* Forward results to collectd-daemon */
+  /* Type_instance is always 'chrony' to tag daemon-wide data */
+  /*                Type                Type_instan  Value */
+  chrony_push_data("clock_stratum",     DAEMON_NAME, ntohs(chrony_resp.body.tracking.f_stratum));
+  chrony_push_data("time_ref",          DAEMON_NAME, time_ref);  /* unit: s */
+  chrony_push_data("time_offset_ntp",   DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_current_correction));      /* Offset between system time and NTP, unit: s */
+  chrony_push_data("time_offset",       DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_last_offset)); /* Estimated Offset of the NTP time, unit: s */
+  chrony_push_data("time_offset_rms",   DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_rms_offset));  /* averaged value of the above, unit: s */
+  chrony_push_data("frequency_error",   DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_freq_ppm));    /* Frequency error of the local osc, unit: ppm */
+  chrony_push_data("clock_skew_ppm",    DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_skew_ppm));
+  chrony_push_data("root_delay",        DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_root_delay));  /* Network latency between local daemon and the current source */
+  chrony_push_data("root_dispersion",   DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_root_dispersion));
+  chrony_push_data("clock_last_update", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_last_update_interval));
+
+  return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_request_sources_count(unsigned int *p_count)
+{
+  /* Requests the number of time sources from the chrony daemon */
+  int rc;
+  size_t chrony_resp_size;
+  tChrony_Request chrony_req;
+  tChrony_Response chrony_resp;
+
+  DEBUG(PLUGIN_NAME ": Requesting data");
+  chrony_init_req(&chrony_req);
+  rc =
+    chrony_query(REQ_N_SOURCES, &chrony_req, &chrony_resp, &chrony_resp_size);
+  if (rc != 0)
+  {
+    ERROR(PLUGIN_NAME ": chrony_query (REQ_N_SOURCES) failed with status %i",
+          rc);
+    return rc;
+  }
+
+  *p_count = ntohl(chrony_resp.body.n_sources.f_n_sources);
+  DEBUG(PLUGIN_NAME ": Getting data of %d clock sources", *p_count);
+
+  return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_request_source_data(int p_src_idx, int *p_is_reachable)
+{
+  /* Perform Source data request for source #p_src_idx */
+  int rc;
+  size_t chrony_resp_size;
+  tChrony_Request chrony_req;
+  tChrony_Response chrony_resp;
+
+  char src_addr[IPV6_STR_MAX_SIZE] = { 0 };
+
+  chrony_init_req(&chrony_req);
+  chrony_req.body.source_data.f_index = htonl(p_src_idx);
+  rc =
+    chrony_query(REQ_SOURCE_DATA, &chrony_req, &chrony_resp,
+                 &chrony_resp_size);
+  if (rc != 0)
+  {
+    ERROR(PLUGIN_NAME
+          ": chrony_query (REQ_SOURCE_DATA) failed with status %i", rc);
+    return rc;
+  }
+
+  niptoha(&chrony_resp.body.source_data.addr, src_addr, sizeof(src_addr));
+  DEBUG(PLUGIN_NAME
+        ": Source[%d] data: .addr = %s, .poll = %u, .stratum = %u, .state = %u, .mode = %u, .flags = %u, .reach = %u, .latest_meas_ago = %u, .orig_latest_meas = %f, .latest_meas = %f, .latest_meas_err = %f",
+        p_src_idx, src_addr, ntohs(chrony_resp.body.source_data.f_poll),
+        ntohs(chrony_resp.body.source_data.f_stratum),
+        ntohs(chrony_resp.body.source_data.f_state),
+        ntohs(chrony_resp.body.source_data.f_mode),
+        ntohs(chrony_resp.body.source_data.f_flags),
+        ntohs(chrony_resp.body.source_data.f_reachability),
+        ntohl(chrony_resp.body.source_data.f_since_sample),
+        ntohf(chrony_resp.body.source_data.f_origin_latest_meas),
+        ntohf(chrony_resp.body.source_data.f_latest_meas),
+        ntohf(chrony_resp.body.source_data.f_latest_meas_err));
+
+  /* Push NaN if source is currently not reachable */
+  int is_reachable =
+    ntohs(chrony_resp.body.source_data.f_reachability) & 0x01;
+  *p_is_reachable = is_reachable;
+
+  /* Forward results to collectd-daemon */
+  chrony_push_data_valid("clock_stratum", src_addr, is_reachable,
+                         ntohs(chrony_resp.body.source_data.f_stratum));
+  chrony_push_data_valid("clock_state", src_addr, is_reachable,
+                         ntohs(chrony_resp.body.source_data.f_state));
+  chrony_push_data_valid("clock_mode", src_addr, is_reachable,
+                         ntohs(chrony_resp.body.source_data.f_mode));
+  chrony_push_data_valid("clock_reachability", src_addr, is_reachable,
+                         ntohs(chrony_resp.body.source_data.f_reachability));
+  chrony_push_data_valid("clock_last_meas", src_addr, is_reachable,
+                         ntohs(chrony_resp.body.source_data.f_since_sample));
+
+  return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_request_source_stats(int p_src_idx, const int *p_is_reachable)
+{
+  /* Perform Source stats request for source #p_src_idx */
+  int rc;
+  size_t chrony_resp_size;
+  tChrony_Request chrony_req;
+  tChrony_Response chrony_resp;
+  double skew_ppm, frequency_error, time_offset;
+
+  char src_addr[IPV6_STR_MAX_SIZE] = { 0 };
+
+  if (*p_is_reachable == 0)
+  {
+    skew_ppm = 0;
+    frequency_error = 0;
+    time_offset = 0;
+  }
+  else
+  {
+    chrony_init_req(&chrony_req);
+    chrony_req.body.source_stats.f_index = htonl(p_src_idx);
+    rc =
+      chrony_query(REQ_SOURCE_STATS, &chrony_req, &chrony_resp,
+                   &chrony_resp_size);
+    if (rc != 0)
+    {
+      ERROR(PLUGIN_NAME
+            ": chrony_query (REQ_SOURCE_STATS) failed with status %i", rc);
+      return rc;
+    }
+
+    skew_ppm = ntohf(chrony_resp.body.source_stats.f_skew_ppm);
+    frequency_error =
+      ntohf(chrony_resp.body.source_stats.f_rtc_gain_rate_ppm);
+    time_offset = ntohf(chrony_resp.body.source_stats.f_est_offset);
+
+    niptoha(&chrony_resp.body.source_stats.addr, src_addr, sizeof(src_addr));
+    DEBUG(PLUGIN_NAME
+          ": Source[%d] stat: .addr = %s, .ref_id= %u, .n_samples = %u, "
+          ".n_runs = %u, .span_seconds = %u, .rtc_seconds_fast = %f, "
+          ".rtc_gain_rate_ppm = %f, .skew_ppm= %f, .est_offset = %f, .est_offset_err = %f",
+          p_src_idx, src_addr,
+          ntohl(chrony_resp.body.source_stats.f_ref_id),
+          ntohl(chrony_resp.body.source_stats.f_n_samples),
+          ntohl(chrony_resp.body.source_stats.f_n_runs),
+          ntohl(chrony_resp.body.source_stats.f_span_seconds),
+          ntohf(chrony_resp.body.source_stats.f_rtc_seconds_fast),
+          frequency_error, skew_ppm, time_offset,
+          ntohf(chrony_resp.body.source_stats.f_est_offset_err));
+
+  } /* if (*is_reachable) */
+
+  /* Forward results to collectd-daemon */
+  chrony_push_data_valid("clock_skew_ppm", src_addr, *p_is_reachable, skew_ppm);
+  chrony_push_data_valid("frequency_error", src_addr, *p_is_reachable, frequency_error); /* unit: ppm */
+  chrony_push_data_valid("time_offset", src_addr, *p_is_reachable, time_offset);         /* unit: s */
+
+  return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_read(void)
+{
+  /* collectd read callback: Perform data acquisition */
+  int rc;
+  unsigned int n_sources;
+
+  if (g_chrony_seq_is_initialized == 0)
+  {
+    /* Seed RNG for sequence number generation */
+    rc = chrony_init_seq();
+    if (rc != CHRONY_RC_OK)
+      return rc;
+
+    g_chrony_seq_is_initialized = 1;
+  }
+
+  /* Get daemon stats */
+  rc = chrony_request_daemon_stats();
+  if (rc != CHRONY_RC_OK)
+    return rc;
+
+  /* Get number of time sources, then check every source for status */
+  rc = chrony_request_sources_count(&n_sources);
+  if (rc != CHRONY_RC_OK)
+    return rc;
+
+  for (unsigned int now_src = 0; now_src < n_sources; ++now_src)
+  {
+    int is_reachable;
+    rc = chrony_request_source_data(now_src, &is_reachable);
+    if (rc != CHRONY_RC_OK)
+      return rc;
+
+    rc = chrony_request_source_stats(now_src, &is_reachable);
+    if (rc != CHRONY_RC_OK)
+      return rc;
+
+  }
+  return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_shutdown(void)
+{
+  /* Collectd shutdown callback: Free mem */
+  if (g_chrony_is_connected != 0)
+  {
+    close(g_chrony_socket);
+    g_chrony_is_connected = 0;
+  }
+  if (g_chrony_host != NULL)
+    sfree(g_chrony_host);
+
+  if (g_chrony_port != NULL)
+    sfree(g_chrony_port);
+  
+  if (g_chrony_plugin_instance != NULL)
+    sfree(g_chrony_plugin_instance);
+  
+  return CHRONY_RC_OK;
+}
+
+
+void
+module_register(void)
+{
+  plugin_register_config(PLUGIN_NAME_SHORT, chrony_config, g_config_keys,
+                         g_config_keys_num);
+  plugin_register_read(PLUGIN_NAME_SHORT, chrony_read);
+  plugin_register_shutdown(PLUGIN_NAME_SHORT, chrony_shutdown);
+}
index aade08a..afa7e48 100644 (file)
@@ -620,6 +620,11 @@ sets the type instance instead. I<(optional)>
 Works like the option of the same name directly beneath the I<MBean> block, but
 sets the type instance instead. I<(optional)>
 
+=item B<PluginName> I<name>
+
+When set, overrides the default setting for the I<plugin> field
+(C<GenericJMX>).
+
 =item B<Table> B<true>|B<false>
 
 Set this to true if the returned attribute is a I<composite type>. If set to
index 8b0f867..12187f3 100644 (file)
@@ -104,7 +104,7 @@ static int consolitation_g = CON_NONE;
 static _Bool nan_is_error_g = 0;
 
 static char **match_ds_g = NULL;
-static int    match_ds_num_g = 0;
+static size_t match_ds_num_g = 0;
 
 /* `strdup' is an XSI extension. I don't want to pull in all of XSI just for
  * that, so here's an own implementation.. It's easy enough. The GCC attributes
@@ -128,27 +128,25 @@ static int filter_ds (size_t *values_num,
        gauge_t *new_values;
        char   **new_names;
 
-       size_t i;
-
        if (match_ds_g == NULL)
                return (RET_OKAY);
 
        new_values = (gauge_t *)calloc (match_ds_num_g, sizeof (*new_values));
        if (new_values == NULL)
        {
-               fprintf (stderr, "malloc failed: %s\n", strerror (errno));
+               fprintf (stderr, "calloc failed: %s\n", strerror (errno));
                return (RET_UNKNOWN);
        }
 
        new_names = (char **)calloc (match_ds_num_g, sizeof (*new_names));
        if (new_names == NULL)
        {
-               fprintf (stderr, "malloc failed: %s\n", strerror (errno));
+               fprintf (stderr, "calloc failed: %s\n", strerror (errno));
                free (new_values);
                return (RET_UNKNOWN);
        }
 
-       for (i = 0; i < (size_t) match_ds_num_g; i++)
+       for (size_t i = 0; i < match_ds_num_g; i++)
        {
                size_t j;
 
@@ -182,7 +180,7 @@ static int filter_ds (size_t *values_num,
        }
 
        free (*values);
-       for (i = 0; i < *values_num; i++)
+       for (size_t i = 0; i < *values_num; i++)
                free ((*values_names)[i]);
        free (*values_names);
 
@@ -245,6 +243,7 @@ static int match_range (range_t *range, double value)
        return (((ret - range->invert) == 0) ? 0 : 1);
 } /* int match_range */
 
+__attribute__((noreturn))
 static void usage (const char *name)
 {
        fprintf (stderr, "Usage: %s <-s socket> <-n value_spec> <-H hostname> [options]\n"
@@ -282,7 +281,6 @@ static int do_listval (lcc_connection_t *connection)
        char *hostname = NULL;
 
        int status;
-       size_t i;
 
        status = lcc_listval (connection, &ret_ident, &ret_ident_num);
        if (status != 0) {
@@ -300,7 +298,7 @@ static int do_listval (lcc_connection_t *connection)
                return (RET_UNKNOWN);
        }
 
-       for (i = 0; i < ret_ident_num; ++i) {
+       for (size_t i = 0; i < ret_ident_num; ++i) {
                char id[1024];
 
                if ((hostname_g != NULL) && (strcasecmp (hostname_g, ret_ident[i].host)))
@@ -344,9 +342,8 @@ static int do_check_con_none (size_t values_num,
        int num_okay = 0;
        const char *status_str = "UNKNOWN";
        int status_code = RET_UNKNOWN;
-       size_t i;
 
-       for (i = 0; i < values_num; i++)
+       for (size_t i = 0; i < values_num; i++)
        {
                if (isnan (values[i]))
                {
@@ -389,7 +386,7 @@ static int do_check_con_none (size_t values_num,
        if (values_num > 0)
        {
                printf (" |");
-               for (i = 0; i < values_num; i++)
+               for (size_t i = 0; i < values_num; i++)
                        printf (" %s=%f;;;;", values_names[i], values[i]);
        }
        printf ("\n");
@@ -400,7 +397,6 @@ static int do_check_con_none (size_t values_num,
 static int do_check_con_average (size_t values_num,
                double *values, char **values_names)
 {
-       size_t i;
        double total;
        int total_num;
        double average;
@@ -409,7 +405,7 @@ static int do_check_con_average (size_t values_num,
 
        total = 0.0;
        total_num = 0;
-       for (i = 0; i < values_num; i++)
+       for (size_t i = 0; i < values_num; i++)
        {
                if (isnan (values[i]))
                {
@@ -450,7 +446,7 @@ static int do_check_con_average (size_t values_num,
        }
 
        printf ("%s: %g average |", status_str, average);
-       for (i = 0; i < values_num; i++)
+       for (size_t i = 0; i < values_num; i++)
                printf (" %s=%f;;;;", values_names[i], values[i]);
        printf ("\n");
 
@@ -460,7 +456,6 @@ static int do_check_con_average (size_t values_num,
 static int do_check_con_sum (size_t values_num,
                double *values, char **values_names)
 {
-       size_t i;
        double total;
        int total_num;
        const char *status_str = "UNKNOWN";
@@ -468,7 +463,7 @@ static int do_check_con_sum (size_t values_num,
 
        total = 0.0;
        total_num = 0;
-       for (i = 0; i < values_num; i++)
+       for (size_t i = 0; i < values_num; i++)
        {
                if (isnan (values[i]))
                {
@@ -507,7 +502,7 @@ static int do_check_con_sum (size_t values_num,
        }
 
        printf ("%s: %g sum |", status_str, total);
-       for (i = 0; i < values_num; i++)
+       for (size_t i = 0; i < values_num; i++)
                printf (" %s=%f;;;;", values_names[i], values[i]);
        printf ("\n");
 
@@ -517,7 +512,6 @@ static int do_check_con_sum (size_t values_num,
 static int do_check_con_percentage (size_t values_num,
                double *values, char **values_names)
 {
-       size_t i;
        double sum = 0.0;
        double percentage;
 
@@ -530,7 +524,7 @@ static int do_check_con_percentage (size_t values_num,
                return (RET_WARNING);
        }
 
-       for (i = 0; i < values_num; i++)
+       for (size_t i = 0; i < values_num; i++)
        {
                if (isnan (values[i]))
                {
@@ -570,7 +564,7 @@ static int do_check_con_percentage (size_t values_num,
        }
 
        printf ("%s: %lf percent |", status_str, percentage);
-       for (i = 0; i < values_num; i++)
+       for (size_t i = 0; i < values_num; i++)
                printf (" %s=%lf;;;;", values_names[i], values[i]);
        return (status_code);
 } /* int do_check_con_percentage */
@@ -582,14 +576,12 @@ static int do_check (lcc_connection_t *connection)
        size_t   values_num;
        char ident_str[1024];
        lcc_identifier_t ident;
-       size_t i;
        int status;
 
        snprintf (ident_str, sizeof (ident_str), "%s/%s",
                        hostname_g, value_string_g);
        ident_str[sizeof (ident_str) - 1] = 0;
 
-       memset (&ident, 0, sizeof (ident));
        status = lcc_string_to_identifier (connection, &ident, ident_str);
        if (status != 0)
        {
@@ -617,9 +609,9 @@ static int do_check (lcc_connection_t *connection)
 
        status = RET_UNKNOWN;
        if (consolitation_g == CON_NONE)
-               status =  do_check_con_none (values_num, values, values_names);
+               status = do_check_con_none (values_num, values, values_names);
        else if (consolitation_g == CON_AVERAGE)
-               status =  do_check_con_average (values_num, values, values_names);
+               status = do_check_con_average (values_num, values, values_names);
        else if (consolitation_g == CON_SUM)
                status = do_check_con_sum (values_num, values, values_names);
        else if (consolitation_g == CON_PERCENTAGE)
@@ -627,7 +619,7 @@ static int do_check (lcc_connection_t *connection)
 
        free (values);
        if (values_names != NULL)
-               for (i = 0; i < values_num; i++)
+               for (size_t i = 0; i < values_num; i++)
                        free (values_names[i]);
        free (values_names);
 
@@ -693,7 +685,7 @@ int main (int argc, char **argv)
                        case 'd':
                        {
                                char **tmp;
-                               tmp = (char **) realloc (match_ds_g,
+                               tmp = realloc (match_ds_g,
                                                (match_ds_num_g + 1)
                                                * sizeof (char *));
                                if (tmp == NULL)
index 773a6cd..16b26af 100644 (file)
@@ -37,7 +37,7 @@ for collectd in Python. This is a lot more efficient than executing a
 Python-script every time you want to read a value with the C<exec plugin> (see
 L<collectd-exec(5)>) and provides a lot more functionality, too.
 
-The minimum required Python version is I<2.3>.
+The minimum required Python version is I<2.6>.
 
 =head1 CONFIGURATION
 
@@ -94,11 +94,12 @@ way of entering your commands. The daemonized collectd won't do that.
 
 =item *
 
-B<2.> collectd will block I<SIGINT>. Pressing I<Ctrl+C> will usually cause
+B<2.> Python will be handling I<SIGINT>. Pressing I<Ctrl+C> will usually cause
 collectd to shut down. This would be problematic in an interactive session,
-therefore this signal will be blocked. You can still use it to interrupt
-syscalls like sleep and pause but it won't generate a I<KeyboardInterrupt>
-exception either.
+therefore Python will be handling it in interactive sessions. This allows you
+to use I<Ctrl+C> to interrupt Python code without killing collectd. This also
+means you can catch I<KeyboardInterrupt> exceptions which does not work during
+normal operation.
 
 To quit collectd send I<EOF> (press I<Ctrl+D> at the beginning of a new line).
 
@@ -658,6 +659,8 @@ Any Python module will start similar to:
 
 A very simple read function might look like:
 
+  import random
+
   def read(data=None):
     vl = collectd.Values(type='gauge')
     vl.plugin='python.spam'
@@ -671,28 +674,12 @@ A very simple write function might look like:
 
 To register those functions with collectd:
 
-  collectd.register_read(read);
-  collectd.register_write(write);
+  collectd.register_read(read)
+  collectd.register_write(write)
 
 See the section L<"CLASSES"> above for a complete documentation of the data
 types used by the read, write and match functions.
 
-=head1 NOTES
-
-=over 4
-
-=item *
-
-Please feel free to send in new plugins to collectd's mailing list at
-E<lt>collectdE<nbsp>atE<nbsp>collectd.orgE<gt> for review and, possibly,
-inclusion in the main distribution. In the latter case, we will take care of
-keeping the plugin up to date and adapting it to new versions of collectd.
-
-Before submitting your plugin, please take a look at
-L<http://collectd.org/dev-info.shtml>.
-
-=back
-
 =head1 CAVEATS
 
 =over 4
index 71814a2..7db9fe7 100644 (file)
 #include <time.h>
 #include <signal.h>
 #include <errno.h>
+#include <math.h>
+#include <sys/time.h>
 
 #include "utils_heap.h"
 
 #include "libcollectdclient/collectd/client.h"
 #include "libcollectdclient/collectd/network.h"
-#include "libcollectdclient/collectd/network_buffer.h"
 
 #define DEF_NUM_HOSTS    1000
 #define DEF_NUM_PLUGINS    20
@@ -99,6 +100,29 @@ static void signal_handler (int signal) /* {{{ */
   loop = 0;
 } /* }}} void signal_handler */
 
+#if HAVE_CLOCK_GETTIME
+static double dtime (void) /* {{{ */
+{
+  struct timespec ts = { 0 };
+
+  if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0)
+    perror ("clock_gettime");
+
+  return ((double) ts.tv_sec) + (((double) ts.tv_nsec) / 1e9);
+} /* }}} double dtime */
+#else
+/* Work around for Mac OS X which doesn't have clock_gettime(2). *sigh* */
+static double dtime (void) /* {{{ */
+{
+  struct timeval tv = { 0 };
+
+  if (gettimeofday (&tv, /* timezone = */ NULL) != 0)
+    perror ("gettimeofday");
+
+  return ((double) tv.tv_sec) + (((double) tv.tv_usec) / 1e6);
+} /* }}} double dtime */
+#endif
+
 static int compare_time (const void *v0, const void *v1) /* {{{ */
 {
   const lcc_value_list_t *vl0 = v0;
@@ -131,13 +155,12 @@ static lcc_value_list_t *create_value_list (void) /* {{{ */
   lcc_value_list_t *vl;
   int host_num;
 
-  vl = malloc (sizeof (*vl));
+  vl = calloc (1, sizeof (*vl));
   if (vl == NULL)
   {
-    fprintf (stderr, "malloc failed.\n");
+    fprintf (stderr, "calloc failed.\n");
     return (NULL);
   }
-  memset (vl, 0, sizeof (*vl));
 
   vl->values = calloc (/* nmemb = */ 1, sizeof (*vl->values));
   if (vl->values == NULL)
@@ -161,7 +184,7 @@ static lcc_value_list_t *create_value_list (void) /* {{{ */
   host_num = get_boundet_random (0, conf_num_hosts);
 
   vl->interval = conf_interval;
-  vl->time = 1.0 + time (NULL)
+  vl->time = 1.0 + dtime ()
     + (host_num % (1 + (int) vl->interval));
 
   if (get_boundet_random (0, 2) == 0)
@@ -200,7 +223,7 @@ static int send_value (lcc_value_list_t *vl) /* {{{ */
   if (vl->values_types[0] == LCC_TYPE_GAUGE)
     vl->values[0].gauge = 100.0 * ((gauge_t) random ()) / (((gauge_t) RAND_MAX) + 1.0);
   else
-    vl->values[0].derive += get_boundet_random (0, 100);
+    vl->values[0].derive += (derive_t) get_boundet_random (0, 100);
 
   status = lcc_network_values_send (net, vl);
   if (status != 0)
@@ -314,8 +337,7 @@ static int read_options (int argc, char **argv) /* {{{ */
 
 int main (int argc, char **argv) /* {{{ */
 {
-  int i;
-  time_t last_time;
+  double last_time;
   int values_sent = 0;
 
   read_options (argc, argv);
@@ -343,7 +365,7 @@ int main (int argc, char **argv) /* {{{ */
   else
   {
     lcc_server_t *srv;
-    
+
     srv = lcc_server_create (net, conf_destination, conf_service);
     if (srv == NULL)
     {
@@ -360,7 +382,7 @@ int main (int argc, char **argv) /* {{{ */
 
   fprintf (stdout, "Creating %i values ... ", conf_num_values);
   fflush (stdout);
-  for (i = 0; i < conf_num_values; i++)
+  for (int i = 0; i < conf_num_values; i++)
   {
     lcc_value_list_t *vl;
 
@@ -388,14 +410,18 @@ int main (int argc, char **argv) /* {{{ */
       printf ("%i values have been sent.\n", values_sent);
 
       /* Check if we need to sleep */
-      time_t now = time (NULL);
+      double now = dtime ();
 
       while (now < vl->time)
       {
         /* 1 / 100 second */
         struct timespec ts = { 0, 10000000 };
+
+        ts.tv_sec = (time_t) now;
+        ts.tv_nsec = (long) ((now - ((double) ts.tv_sec)) * 1e9);
+
         nanosleep (&ts, /* remaining = */ NULL);
-        now = time (NULL);
+        now = dtime ();
 
         if (!loop)
           break;
@@ -423,7 +449,6 @@ int main (int argc, char **argv) /* {{{ */
 
   lcc_network_destroy (net);
   exit (EXIT_SUCCESS);
-  return (0);
 } /* }}} int main */
 
 /* vim: set sw=2 sts=2 et fdm=marker : */
index 64f1d11..8eb08a6 100644 (file)
 #@BUILD_PLUGIN_BIND_TRUE@LoadPlugin bind
 #@BUILD_PLUGIN_CEPH_TRUE@LoadPlugin ceph
 #@BUILD_PLUGIN_CGROUPS_TRUE@LoadPlugin cgroups
+#@BUILD_PLUGIN_CHRONY_TRUE@LoadPlugin chrony
 #@BUILD_PLUGIN_CONNTRACK_TRUE@LoadPlugin conntrack
 #@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@LoadPlugin contextswitch
 @BUILD_PLUGIN_CPU_TRUE@@BUILD_PLUGIN_CPU_TRUE@LoadPlugin cpu
 #@BUILD_PLUGIN_CPUFREQ_TRUE@LoadPlugin cpufreq
+#@BUILD_PLUGIN_CPUSLEEP_TRUE@LoadPlugin cpusleep
 @LOAD_PLUGIN_CSV@LoadPlugin csv
 #@BUILD_PLUGIN_CURL_TRUE@LoadPlugin curl
 #@BUILD_PLUGIN_CURL_JSON_TRUE@LoadPlugin curl_json
 #@BUILD_PLUGIN_FILECOUNT_TRUE@LoadPlugin filecount
 #@BUILD_PLUGIN_FSCACHE_TRUE@LoadPlugin fscache
 #@BUILD_PLUGIN_GMOND_TRUE@LoadPlugin gmond
+#@BUILD_PLUGIN_GPS_TRUE@LoadPlugin gps
+#@BUILD_PLUGIN_GRPC_TRUE@LoadPlugin grpc
 #@BUILD_PLUGIN_HDDTEMP_TRUE@LoadPlugin hddtemp
 @BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_PLUGIN_INTERFACE_TRUE@LoadPlugin interface
 #@BUILD_PLUGIN_IPC_TRUE@LoadPlugin ipc
 @BUILD_PLUGIN_MEMORY_TRUE@@BUILD_PLUGIN_MEMORY_TRUE@LoadPlugin memory
 #@BUILD_PLUGIN_MIC_TRUE@LoadPlugin mic
 #@BUILD_PLUGIN_MODBUS_TRUE@LoadPlugin modbus
+#@BUILD_PLUGIN_MQTT_TRUE@LoadPlugin mqtt
 #@BUILD_PLUGIN_MULTIMETER_TRUE@LoadPlugin multimeter
 #@BUILD_PLUGIN_MYSQL_TRUE@LoadPlugin mysql
 #@BUILD_PLUGIN_NETAPP_TRUE@LoadPlugin netapp
 #@BUILD_PLUGIN_NGINX_TRUE@LoadPlugin nginx
 #@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@LoadPlugin notify_desktop
 #@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@LoadPlugin notify_email
+#@BUILD_PLUGIN_NOTIFY_NAGIOS_TRUE@LoadPlugin notify_nagios
 #@BUILD_PLUGIN_NTPD_TRUE@LoadPlugin ntpd
 #@BUILD_PLUGIN_NUMA_TRUE@LoadPlugin numa
 #@BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut
 #@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@LoadPlugin write_riemann
 #@BUILD_PLUGIN_WRITE_SENSU_TRUE@LoadPlugin write_sensu
 #@BUILD_PLUGIN_WRITE_TSDB_TRUE@LoadPlugin write_tsdb
+#@BUILD_PLUGIN_XENCPU_TRUE@LoadPlugin xencpu
 #@BUILD_PLUGIN_XMMS_TRUE@LoadPlugin xmms
 #@BUILD_PLUGIN_ZFS_ARC_TRUE@LoadPlugin zfs_arc
+#@BUILD_PLUGIN_ZONE_TRUE@LoadPlugin zone
 #@BUILD_PLUGIN_ZOOKEEPER_TRUE@LoadPlugin zookeeper
 
 ##############################################################################
 #      Host "localhost"
 #      Port "3551"
 #      ReportSeconds true
+#      PersistentConnection true
 #</Plugin>
 
 #<Plugin aquaero>
 #  </Daemon>
 #</Plugin>
 
+#<Plugin chrony>
+#      Host    "localhost"
+#      Port    "323"
+#      Timeout "2"
+#</Plugin>
+
 #<Plugin cgroups>
 #  CGroup "libvirt"
 #  IgnoreSelected false
 #  </Metric>
 #</Plugin>
 
+#<Plugin gps>
+#  Host "127.0.0.1"
+#  Port "2947"
+#  Timeout 0.015
+#  PauseConnect 5
+#</Plugin>
+
+#<Plugin grpc>
+#      WorkerThreads 5
+#      <Listen "0.0.0.0" "50051">
+#              EnableSSL true
+#              SSLRootCerts "/path/to/root.pem"
+#              SSLServerCert "/path/to/server.pem"
+#              SSLServerKey "/path/to/server.key"
+#      </Listen>
+#</Plugin>
+
 #<Plugin hddtemp>
 #  Host "127.0.0.1"
 #  Port "7634"
 #<Plugin interface>
 #      Interface "eth0"
 #      IgnoreSelected false
+#      ReportInactive true
+#      UniqueName false
 #</Plugin>
 
 #<Plugin ipmi>
 #      </Host>
 #</Plugin>
 
+#<Plugin mqtt>
+#      <Publish "name">
+#              Host "localhost"
+#              Port 1883
+#              ClientId "localhost"
+#              User "user"
+#              Password "secret"
+#              QoS 0
+#              Prefix "collectd"
+#              StoreRates true
+#              Retain false
+#              CACert "/etc/ssl/ca.crt"
+#              CertificateFile "/etc/ssl/client.crt"
+#              CertificateKeyFile "/etc/ssl/client.pem"
+#              TLSProtocol "tlsv1.2"
+#              CipherSuite "ciphers"
+#      </Publish>
+#      <Subscribe "name">
+#              Host "localhost"
+#              Port 1883
+#              ClientId "localhost"
+#              User "user"
+#              Password "secret"
+#              QoS 2
+#              Topic "collectd/#"
+#              CleanSession true
+#      </Subscribe>
+#</Plugin>
+
 #<Plugin mysql>
 #      <Database db_name>
 #              Host "database.serv.er"
 #              User "db_user"
 #              Password "secret"
 #              Database "db_name"
+#              SSLKey "/path/to/key.pem"
+#              SSLCert "/path/to/cert.pem"
+#              SSLCA "/path/to/ca.pem"
+#              SSLCAPath "/path/to/cas/"
+#              SSLCipher "DHE-RSA-AES256-SHA"
 #              MasterStats true
 #              ConnectTimeout 10
 #              InnodbStats true
 #              SlaveStats true
 #              SlaveNotifications true
 #      </Database>
+#      <Database galera>
+#              Alias "galera"
+#              Host "localhost"
+#              Socket "/var/run/mysql/mysqld.sock"
+#              WsrepStats true
+#      </Database>
 #</Plugin>
 
 #<Plugin netapp>
 #      Recipient "email2@domain2.com"
 #</Plugin>
 
+#<Plugin notify_nagios>
+#      CommandFile "/usr/local/nagios/var/rw/nagios.cmd"
+#</Plugin>
+
 #<Plugin ntpd>
 #      Host "localhost"
 #      Port 123
 #  DeleteTimers   false
 #  DeleteGauges   false
 #  DeleteSets     false
+#  CounterSum     false
 #  TimerPercentile 90.0
 #  TimerPercentile 95.0
 #  TimerPercentile 99.0
 ##     None of the following option should be set manually
 ##     This plugin automatically detect most optimal options
 ##     Only set values here if:
-##     - The module ask you to
+##     - The module asks you to
 ##     - You want to disable the collection of some data
-##     - Your (intel) CPU is not supported (yet) by the module
-##     - The module generate a lot of errors 'MSR offset 0x... read failed'
+##     - Your (Intel) CPU is not supported (yet) by the module
+##     - The module generates a lot of errors 'MSR offset 0x... read failed'
 ##     In the last two cases, please open a bug request
 #
 #      TCCActivationTemp "100"
 #    Host "localhost"
 #    Port "2003"
 #    Protocol "tcp"
+#    ReconnectInterval 0
 #    LogSendErrors true
 #    Prefix "collectd"
 #    Postfix "collectd"
 #              ClientKey "/etc/ssl/client.pem"
 #              ClientCert "/etc/ssl/client.crt"
 #              ClientKeyPass "secret"
+#              Header "X-Custom-Header: custom_value"
 #              SSLVersion "TLSv1"
 #              Format "Command"
+#              Metrics true
+#              Notifications false
 #              StoreRates false
 #              BufferSize 4096
 #              LowSpeedLimit 0
 #              Host "localhost"
 #              Port "6379"
 #              Timeout 1000
+#              Prefix "collectd/"
 #      </Node>
 #</Plugin>
 
index e5a5c75..f3ff4bb 100644 (file)
@@ -38,7 +38,7 @@ i.e. a C<E<lt>PluginE<nbsp>...E<gt>> block.
 The syntax of this config file is similar to the config file of the famous
 I<Apache> webserver. Each line contains either an option (a key and a list of
 one or more values) or a section-start or -end. Empty lines and everything
-after a non-quoted hash-symbol (C<#>) is ignored. I<Keys> are unquoted
+after a non-quoted hash-symbol (C<#>) are ignored. I<Keys> are unquoted
 strings, consisting only of alphanumeric characters and the underscore (C<_>)
 character. Keys are handled case insensitive by I<collectd> itself and all
 plugins included with it. I<Values> can either be an I<unquoted string>, a
@@ -70,7 +70,7 @@ C<E<lt>B<Plugin> ...E<gt>> block.
 
 =item B<BaseDir> I<Directory>
 
-Sets the base directory. This is the directory beneath all RRD-files are
+Sets the base directory. This is the directory beneath which all RRD-files are
 created. Possibly more subdirectories are created. This is also the working
 directory for the daemon.
 
@@ -83,7 +83,7 @@ I<collectd> will be mostly useless.
 Only the first B<LoadPlugin> statement or block for a given plugin name has any
 effect. This is useful when you want to split up the configuration into smaller
 files and want each file to be "self contained", i.e. it contains a B<Plugin>
-block I<and> then appropriate B<LoadPlugin> statement. The downside is that if
+block I<and> the appropriate B<LoadPlugin> statement. The downside is that if
 you have multiple conflicting B<LoadPlugin> blocks, e.g. when they specify
 different intervals, only one of them (the first one encountered) will take
 effect and all others will be silently ignored.
@@ -127,8 +127,17 @@ the average user from ever having to deal with this low level linking stuff.
 =item B<Interval> I<Seconds>
 
 Sets a plugin-specific interval for collecting metrics. This overrides the
-global B<Interval> setting. If a plugin provides own support for specifying an
-interval, that setting will take precedence.
+global B<Interval> setting. If a plugin provides its own support for specifying
+an interval, that setting will take precedence.
+
+=item B<FlushInterval> I<Seconds>
+
+Specifies the interval, in seconds, to call the flush callback if it's
+defined in this plugin. By default, this is disabled.
+
+=item B<FlushTimeout> I<Seconds>
+
+Specifies the value of the timeout argument of the flush callback.
 
 =back
 
@@ -203,7 +212,7 @@ matching C<*.conf> in any subdirectory of C</etc/collectd.d>.
 
 =back
 
-If more than one files are included by a single B<Include> option, the files
+If more than one file is included by a single B<Include> option, the files
 will be included in lexicographical order (as defined by the C<strcmp>
 function). Thus, you can e.E<nbsp>g. use numbered prefixes to specify the
 order in which the files are loaded.
@@ -244,7 +253,7 @@ magic! (Assuming you're using the I<RRDtool> or I<RRDCacheD> plugin.)
 
 =item B<MaxReadInterval> I<Seconds>
 
-Read plugin doubles interval between queries after each failed attempt
+A read plugin doubles the interval between queries after each failed attempt
 to get data.
 
 This options limits the maximum value of the interval. The default value is
@@ -517,7 +526,9 @@ are disabled by default.
 The I<AMQP plugin> can be used to communicate with other instances of
 I<collectd> or third party applications using an AMQP message broker. Values
 are sent to or received from the broker, which handles routing, queueing and
-possibly filtering or messages.
+possibly filtering out messages.
+
+B<Synopsis:>
 
  <Plugin "amqp">
    # Send values to an AMQP broker
@@ -815,12 +826,24 @@ B<apcupsd> can handle it.
 
 TCP-Port to connect to. Defaults to B<3551>.
 
-=item B<ReportSeconds> B<true|false>
+=item B<ReportSeconds> B<true>|B<false>
 
 If set to B<true>, the time reported in the C<timeleft> metric will be
 converted to seconds. This is the recommended setting. If set to B<false>, the
 default for backwards compatibility, the time will be reported in minutes.
 
+=item B<PersistentConnection> B<true>|B<false>
+
+The plugin is designed to keep the connection to I<apcupsd> open between reads.
+If plugin poll interval is greater than 15 seconds (hardcoded socket close
+timeout in I<apcupsd> NIS), then this option is B<false> by default.
+
+You can instruct the plugin to close the connection after each read by setting
+this option to B<false> or force keeping the connection by setting it to B<true>.
+
+If I<apcupsd> appears to close the connection due to inactivity quite quickly,
+the plugin will try to detect this problem and switch to an open-read-close mode.
+
 =back
 
 =head2 Plugin C<aquaero>
@@ -1338,6 +1361,32 @@ at all, B<all> cgroups are selected.
 
 =back
 
+=head2 Plugin C<chrony>
+
+The C<chrony> plugin collects ntp data from a B<chronyd> server, such as clock
+skew and per-peer stratum.
+
+For talking to B<chronyd>, it mimics what the B<chronyc> control program does
+on the wire.
+
+Available configuration options for the C<chrony> plugin:
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname of the host running B<chronyd>. Defaults to B<localhost>.
+
+=item B<Port> I<Port>
+
+UDP-Port to connect to. Defaults to B<323>.
+
+=item B<Timeout> I<Timeout>
+
+Connection timeout in seconds. Defaults to B<2>.
+
+=back
+
 =head2 Plugin C<conntrack>
 
 This plugin collects IP conntrack statistics.
@@ -1408,6 +1457,16 @@ installed) to get the current CPU frequency. If this file does not exist make
 sure B<cpufreqd> (L<http://cpufreqd.sourceforge.net/>) or a similar tool is
 installed and an "cpu governor" (that's a kernel module) is loaded.
 
+=head2 Plugin C<cpusleep>
+
+This plugin doesn't have any options. It reads CLOCK_BOOTTIME and
+CLOCK_MONOTONIC and reports the difference between these clocks. Since
+BOOTTIME clock increments while device is suspended and MONOTONIC
+clock does not, the derivative of the difference between these clocks
+gives the relative amount of time the device has spent in suspend
+state. The recorded value is in milliseconds of sleep per seconds of
+wall clock.
+
 =head2 Plugin C<csv>
 
 =over 4
@@ -1428,6 +1487,92 @@ number.
 
 =back
 
+=head2 cURL Statistics
+
+All cURL-based plugins support collection of generic, request-based
+statistics. These are disabled by default and can be enabled selectively for
+each page or URL queried from the curl, curl_json, or curl_xml plugins. See
+the documentation of those plugins for specific information. This section
+describes the available metrics that can be configured for each plugin. All
+options are disabled by default.
+
+See L<http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html> for more details.
+
+=over 4
+
+=item B<TotalTime> B<true|false>
+
+Total time of the transfer, including name resolving, TCP connect, etc.
+
+=item B<NamelookupTime> B<true|false>
+
+Time it took from the start until name resolving was completed.
+
+=item B<ConnectTime> B<true|false>
+
+Time it took from the start until the connect to the remote host (or proxy)
+was completed.
+
+=item B<AppconnectTime> B<true|false>
+
+Time it took from the start until the SSL/SSH connect/handshake to the remote
+host was completed.
+
+=item B<PretransferTime> B<true|false>
+
+Time it took from the start until just before the transfer begins.
+
+=item B<StarttransferTime> B<true|false>
+
+Time it took from the start until the first byte was received.
+
+=item B<RedirectTime> B<true|false>
+
+Time it took for all redirection steps include name lookup, connect,
+pre-transfer and transfer before final transaction was started.
+
+=item B<RedirectCount> B<true|false>
+
+The total number of redirections that were actually followed.
+
+=item B<SizeUpload> B<true|false>
+
+The total amount of bytes that were uploaded.
+
+=item B<SizeDownload> B<true|false>
+
+The total amount of bytes that were downloaded.
+
+=item B<SpeedDownload> B<true|false>
+
+The average download speed that curl measured for the complete download.
+
+=item B<SpeedUpload> B<true|false>
+
+The average upload speed that curl measured for the complete upload.
+
+=item B<HeaderSize> B<true|false>
+
+The total size of all the headers received.
+
+=item B<RequestSize> B<true|false>
+
+The total size of the issued requests.
+
+=item B<ContentLengthDownload> B<true|false>
+
+The content-length of the download.
+
+=item B<ContentLengthUpload> B<true|false>
+
+The specified size of the upload.
+
+=item B<NumConnects> B<true|false>
+
+The number of new connections that were created to achieve the transfer.
+
+=back
+
 =head2 Plugin C<curl>
 
 The curl plugin uses the B<libcurl> (L<http://curl.haxx.se/>) to read web pages
@@ -1528,11 +1673,21 @@ Beware that requests will get aborted if they take too long to complete. Adjust
 B<Timeout> accordingly if you expect B<MeasureResponseTime> to report such slow
 requests.
 
+This option is similar to enabling the B<TotalTime> statistic but it's
+measured by collectd instead of cURL.
+
 =item B<MeasureResponseCode> B<true>|B<false>
 
 Measure response code for the request. If this setting is enabled, B<Match>
 blocks (see below) are optional. Disabled by default.
 
+=item B<E<lt>StatisticsE<gt>>
+
+One B<Statistics> block can be used to specify cURL statistics to be collected
+for each request to the remote web site. See the section "cURL Statistics"
+above for details. If this setting is enabled, B<Match> blocks (see below) are
+optional.
+
 =item B<E<lt>MatchE<gt>>
 
 One or more B<Match> blocks that define how to match information in the data
@@ -1645,6 +1800,12 @@ URL. By default the global B<Interval> setting will be used.
 These options behave exactly equivalent to the appropriate options of the
 I<cURL> plugin. Please see there for a detailed description.
 
+=item B<E<lt>StatisticsE<gt>>
+
+One B<Statistics> block can be used to specify cURL statistics to be collected
+for each request to the remote URL. See the section "cURL Statistics" above
+for details.
+
 =back
 
 The following options are valid within B<Key> blocks:
@@ -1747,6 +1908,12 @@ Examples:
 These options behave exactly equivalent to the appropriate options of the
 I<cURL plugin>. Please see there for a detailed description.
 
+=item B<E<lt>StatisticsE<gt>>
+
+One B<Statistics> block can be used to specify cURL statistics to be collected
+for each request to the remote URL. See the section "cURL Statistics" above
+for details.
+
 =item E<lt>B<XPath> I<XPath-expression>E<gt>
 
 Within each B<URL> block, there must be one or more B<XPath> blocks. Each
@@ -1819,6 +1986,7 @@ than those of other plugins. It usually looks something like this:
     </Query>
     <Database "product_information">
       Driver "mysql"
+      Interval 120
       DriverOption "host" "localhost"
       DriverOption "username" "collectd"
       DriverOption "password" "aZo6daiw"
@@ -1998,6 +2166,11 @@ the daemon. Other than that, that name is not used.
 
 =over 4
 
+=item B<Interval> I<Interval>
+
+Sets the interval (in seconds) in which the values will be collected from this
+database. By default the global B<Interval> setting will be used.
+
 =item B<Driver> I<Driver>
 
 Specifies the driver to use to connect to the database. In many cases those
@@ -2238,7 +2411,7 @@ I<TypeInstance> will be used.
 
 =item B<MappedOnly> B<true>|B<false>
 
-When set to B<true>, only metrics that can be mapped to to a I<type> will be
+When set to B<true>, only metrics that can be mapped to a I<type> will be
 collected, all other metrics will be ignored. Defaults to B<false>.
 
 =back
@@ -2468,6 +2641,123 @@ source, this is optional. Otherwise the option is required.
 
 =back
 
+=head2 Plugin C<gps>
+
+The C<gps plugin> connects to gpsd on the host machine.
+The host, port, timeout and pause are configurable.
+
+This is useful if you run an NTP server using a GPS for source and you want to
+monitor it.
+
+Mind your GPS must send $--GSA for having the data reported!
+
+The following elements are collected:
+
+=over 4
+
+=item B<satellites>
+
+Number of satellites used for fix (type instance "used") and in view (type
+instance "visible"). 0 means no GPS satellites are visible.
+
+=item B<dilution_of_precision>
+
+Vertical and horizontal dilution (type instance "horizontal" or "vertical").
+It should be between 0 and 3.
+Look at the documentation of your GPS to know more.
+
+=back
+
+Synopsis:
+
+ LoadPlugin gps
+ <Plugin "gps">
+   # Connect to localhost on gpsd regular port:
+   Host "127.0.0.1"
+   Port "2947"
+   # 15 ms timeout
+   Timeout 0.015
+   # PauseConnect of 5 sec. between connection attempts.
+   PauseConnect 5
+ </Plugin>
+
+Available configuration options:
+
+=over 4
+
+=item B<Host> I<Host>
+
+The host on which gpsd daemon runs. Defaults to B<localhost>.
+
+=item B<Port> I<Port>
+
+Port to connect to gpsd on the host machine. Defaults to B<2947>.
+
+=item B<Timeout> I<Seconds>
+
+Timeout in seconds (default 0.015 sec).
+
+The GPS data stream is fetch by the plugin form the daemon.
+It waits for data to be available, if none arrives it times out
+and loop for another reading.
+Mind to put a low value gpsd expects value in the micro-seconds area
+(recommended is 500 us) since the waiting function is blocking.
+Value must be between 500 us and 5 sec., if outside that range the
+default value is applied.
+
+This only applies from gpsd release-2.95.
+
+=item B<PauseConnect> I<Seconds>
+
+Pause to apply between attempts of connection to gpsd in seconds (default 5 sec).
+
+=back
+
+=head2 Plugin C<grpc>
+
+The I<grpc> plugin provides an RPC interface to submit values to or query
+values from collectd based on the open source gRPC framework. It exposes an
+end-point for dispatching values to the daemon.
+
+The B<gRPC> homepage can be found at L<https://grpc.io/>.
+
+=over 4
+
+=item B<Listen> I<Host> I<Port>
+
+The B<Listen> statement sets the network address to bind to. When multiple
+statements are specified, the daemon will bind to all of them. If none are
+specified, it defaults to B<0.0.0.0:50051>.
+
+The argument I<Host> may be a hostname, an IPv4 address, or an IPv6 address.
+
+Optionally, B<Listen> may be specified as a configuration block which
+supports the following options:
+
+=over 4
+
+=item B<EnableSSL> I<true>|I<false>
+
+Whether to enable SSL for incoming connections. Default: false.
+
+=item B<SSLRootCerts> I<Filename>
+
+=item B<SSLServerKey> I<Filename>
+
+=item B<SSLServerCert> I<Filename>
+
+Filenames specifying SSL certificate and key material to be used with SSL
+connections.
+
+=back
+
+=item B<WorkerThreads> I<Num>
+
+Number of threads to start for handling incoming connections. The default
+value is B<5>.
+
+=back
+
 =head2 Plugin C<hddtemp>
 
 To get values from B<hddtemp> collectd connects to B<localhost> (127.0.0.1),
@@ -2527,6 +2817,29 @@ This will ignore the loopback interface, all interfaces with names starting
 with I<veth> and all interfaces with names starting with I<tun> followed by
 at least one digit.
 
+=item B<ReportInactive> I<true>|I<false>
+
+When set to I<false>, only interfaces with non-zero traffic will be
+reported. Note that the check is done by looking into whether a
+package was sent at any time from boot and the corresponding counter
+is non-zero. So, if the interface has been sending data in the past
+since boot, but not during the reported time-interval, it will still
+be reported.
+
+The default value is I<true> and results in collection of the data
+from all interfaces that are selected by B<Interface> and
+B<IgnoreSelected> options.
+
+=item B<UniqueName> I<true>|I<false>
+
+Interface name is not unique on Solaris (KSTAT), interface name is unique
+only within a module/instance. Following tuple is considered unique:
+   (ks_module, ks_instance, ks_name)
+If this option is set to true, interface name contains above three fields
+separated by an underscore. For more info on KSTAT, visit
+L<http://docs.oracle.com/cd/E23824_01/html/821-1468/kstat-3kstat.html#REFMAN3Ekstat-3kstat>
+
+This option is only available on Solaris.
 
 =back
 
@@ -3248,6 +3561,146 @@ B<Collect> option is mandatory.
 
 =back
 
+=head2 Plugin C<mqtt>
+
+The I<MQTT plugin> can send metrics to MQTT (B<Publish> blocks) and receive
+values from MQTT (B<Subscribe> blocks).
+
+B<Synopsis:>
+
+ <Plugin mqtt>
+   <Publish "name">
+     Host "mqtt.example.com"
+     Prefix "collectd"
+   </Publish>
+   <Subscribe "name">
+     Host "mqtt.example.com"
+     Topic "collectd/#"
+   </Subscribe>
+ </Plugin>
+
+The plugin's configuration is in B<Publish> and/or B<Subscribe> blocks,
+configuring the sending and receiving direction respectively. The plugin will
+register a write callback named C<mqtt/I<name>> where I<name> is the string
+argument given to the B<Publish> block. Both types of blocks share many but not
+all of the following options. If an option is valid in only one of the blocks,
+it will be mentioned explicitly.
+
+B<Options:>
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname of the MQTT broker to connect to.
+
+=item B<Port> I<Service>
+
+Port number or service name of the MQTT broker to connect to.
+
+=item B<User> I<UserName>
+
+Username used when authenticating to the MQTT broker.
+
+=item B<Password> I<Password>
+
+Password used when authenticating to the MQTT broker.
+
+=item B<ClientId> I<ClientId>
+
+MQTT client ID to use. Defaults to the hostname used by I<collectd>.
+
+=item B<QoS> [B<0>-B<2>]
+
+Sets the I<Quality of Service>, with the values C<0>, C<1> and C<2> meaning:
+
+=over 4
+
+=item B<0>
+
+At most once
+
+=item B<1>
+
+At least once
+
+=item B<2>
+
+Exactly once
+
+=back
+
+In B<Publish> blocks, this option determines the QoS flag set on outgoing
+messages and defaults to B<0>. In B<Subscribe> blocks, determines the maximum
+QoS setting the client is going to accept and defaults to B<2>. If the QoS flag
+on a message is larger than the maximum accepted QoS of a subscriber, the
+message's QoS will be downgraded.
+
+=item B<Prefix> I<Prefix> (Publish only)
+
+This plugin will use one topic per I<value list> which will looks like a path.
+I<Prefix> is used as the first path element and defaults to B<collectd>.
+
+An example topic name would be:
+
+ collectd/cpu-0/cpu-user
+
+=item B<Retain> B<false>|B<true> (Publish only)
+
+Controls whether the MQTT broker will retain (keep a copy of) the last message
+sent to each topic and deliver it to new subscribers. Defaults to B<false>.
+
+=item B<StoreRates> B<true>|B<false> (Publish only)
+
+Controls whether C<DERIVE> and C<COUNTER> metrics are converted to a I<rate>
+before sending. Defaults to B<true>.
+
+=item B<CleanSession> B<true>|B<false> (Subscribe only)
+
+Controls whether the MQTT "cleans" the session up after the subscriber
+disconnects or if it maintains the subscriber's subscriptions and all messages
+that arrive while the subscriber is disconnected. Defaults to B<true>.
+
+=item B<Topic> I<TopicName> (Subscribe only)
+
+Configures the topic(s) to subscribe to. You can use the single level C<+> and
+multi level C<#> wildcards. Defaults to B<collectd/#>, i.e. all topics beneath
+the B<collectd> branch.
+
+=item B<CACert> I<file>
+
+Path to the PEM-encoded CA certificate file. Setting this option enables TLS
+communication with the MQTT broker, and as such, B<Port> should be the TLS-enabled
+port of the MQTT broker.
+A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+
+=item B<CertificateFile> I<file>
+
+Path to the PEM-encoded certificate file to use as client certificate when
+connecting to the MQTT broker.
+A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+
+=item B<CertificateKeyFile> I<file>
+
+Path to the unencrypted PEM-encoded key file corresponding to B<CertificateFile>.
+A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+
+=item B<TLSProtocol> I<protocol>
+
+If configured, this specifies the string protocol version (e.g. C<tlsv1>,
+C<tlsv1.2>) to use for the TLS connection to the broker. If not set a default
+version is used which depends on the version of OpenSSL the Mosquitto library
+was linked against.
+
+=item B<CipherSuite> I<ciphersuite>
+
+A string describing the ciphers available for use. See L<ciphers(1)> and the
+C<openssl ciphers> utility for more information. If unset, the default ciphers
+will be used.
+
+
+=back
+
 =head2 Plugin C<mysql>
 
 The C<mysql plugin> requires B<mysqlclient> to be installed. It connects to
@@ -3281,6 +3734,11 @@ Synopsis:
       Port "3306"
       MasterStats true
       ConnectTimeout 10
+      SSLKey "/path/to/key.pem"
+      SSLCert "/path/to/cert.pem"
+      SSLCA "/path/to/ca.pem"
+      SSLCAPath "/path/to/cas/"
+      SSLCipher "DHE-RSA-AES256-SHA"
     </Database>
 
     <Database bar>
@@ -3290,12 +3748,20 @@ Synopsis:
       SlaveStats true
       SlaveNotifications true
     </Database>
+
+   <Database galera>
+      Alias "galera"
+      Host "localhost"
+      Socket "/var/run/mysql/mysqld.sock"
+      WsrepStats true
+   </Database>
   </Plugin>
 
 A B<Database> block defines one connection to a MySQL database. It accepts a
 single argument which specifies the name of the database. None of the other
 options are required. MySQL will use default values as documented in the
-section "mysql_real_connect()" in the B<MySQL reference manual>.
+"mysql_real_connect()" and "mysql_ssl_set()" sections in the
+B<MySQL reference manual>.
 
 =over 4
 
@@ -3360,10 +3826,36 @@ privileges. See the B<User> documentation above. Defaults to B<false>.
 If enabled, the plugin sends a notification if the replication slave I/O and /
 or SQL threads are not running. Defaults to B<false>.
 
+=item B<WsrepStats> I<true|false>
+ Enable the collection of wsrep plugin statistics, used in Master-Master
+ replication setups like in MySQL Galera/Percona XtraDB Cluster.
+ User needs only privileges to execute 'SHOW GLOBAL STATUS'
 =item B<ConnectTimeout> I<Seconds>
 
 Sets the connect timeout for the MySQL client.
 
+=item B<SSLKey> I<Path>
+
+If provided, the X509 key in PEM format.
+
+=item B<SSLCert> I<Path>
+
+If provided, the X509 cert in PEM format.
+
+=item B<SSLCA> I<Path>
+
+If provided, the CA file in PEM format (check OpenSSL docs).
+
+=item B<SSLCAPath> I<Path>
+
+If provided, the CA directory (check OpenSSL docs).
+
+=item B<SSLCipher> I<String>
+
+If provided, the SSL cipher to use.
+
 =back
 
 =head2 Plugin C<netapp>
@@ -4303,6 +4795,21 @@ Default: C<Collectd notify: %s@%s>
 
 =back
 
+=head2 Plugin C<notify_nagios>
+
+The I<notify_nagios> plugin writes notifications to Nagios' I<command file> as
+a I<passive service check result>.
+
+Available configuration options:
+
+=over 4
+
+=item B<CommandFile> I<Path>
+
+Sets the I<command file> to write to. Defaults to F</usr/local/nagios/var/rw/nagios.cmd>.
+
+=back
+
 =head2 Plugin C<ntpd>
 
 The C<ntpd> plugin collects per-peer ntp data such as time offset and time
@@ -4540,6 +5047,16 @@ The following options are accepted within each B<Instance> block:
 Sets the URL to use to connect to the I<OpenLDAP> server. This option is
 I<mandatory>.
 
+=item B<BindDN> I<BindDN>
+
+Name in the form of an LDAP distinguished name intended to be used for
+authentication. Defaults to empty string to establish an anonymous authorization.
+
+=item B<Password> I<Password>
+
+Password for simple bind authentication. If this option is not set,
+unauthenticated bind operation is used.
+
 =item B<StartTLS> B<true|false>
 
 Defines whether TLS must be used when connecting to the I<OpenLDAP> server.
@@ -4561,8 +5078,9 @@ client configuration mechanisms. See ldap.conf(5) for the details.
 
 =item B<Timeout> I<Seconds>
 
-Sets the timeout value for ldap operations. Defaults to B<-1> which results in
-an infinite timeout.
+Sets the timeout value for ldap operations, in seconds. By default, the
+configured B<Interval> is used to set the timeout. Use B<-1> to disable
+(infinite timeout).
 
 =item B<Version> I<Version>
 
@@ -4811,6 +5329,13 @@ Default: B<0.9>
 
 Sets the Time-To-Live of generated ICMP packets.
 
+=item B<Size> I<size>
+
+Sets the size of the data payload in ICMP packet to specified I<size> (it
+will be filled with regular ASCII pattern). If not set, default 56 byte
+long string is used so that the packet size of an ICMPv4 packet is exactly
+64 bytes, similar to the behaviour of normal ping(1) command.
+
 =item B<SourceAddress> I<host>
 
 Sets the source address to use. I<host> may either be a numerical network
@@ -4918,13 +5443,12 @@ The B<Query> block defines one database query which may later be used by a
 database definition. It accepts a single mandatory argument which specifies
 the name of the query. The names of all queries have to be unique (see the
 B<MinVersion> and B<MaxVersion> options below for an exception to this
-rule). The following configuration options are available to define the query:
+rule).
+
+In each B<Query> block, there is one or more B<Result> blocks. Multiple
+B<Result> blocks may be used to extract multiple values from a single query.
 
-In each B<Query> block, there is one or more B<Result> blocks. B<Result>
-blocks define how to handle the values returned from the query. They define
-which column holds which value and how to dispatch that value to the daemon.
-Multiple B<Result> blocks may be used to extract multiple values from a single
-query.
+The following configuration options are available to define the query:
 
 =over 4
 
@@ -4942,7 +5466,7 @@ allowed as long as a single non-empty command has been specified only.
 
 The returned lines will be handled separately one after another.
 
-=item B<Param> I<hostname>|I<database>|I<username>|I<interval>
+=item B<Param> I<hostname>|I<database>|I<instance>|I<username>|I<interval>
 
 Specify the parameters which should be passed to the SQL query. The parameters
 are referred to in the SQL query as B<$1>, B<$2>, etc. in the same order as
@@ -4979,6 +5503,34 @@ specific or global B<Interval> options).
 Please note that parameters are only supported by PostgreSQL's protocol
 version 3 and above which was introduced in version 7.4 of PostgreSQL.
 
+=item B<PluginInstanceFrom> I<column>
+
+Specify how to create the "PluginInstance" for reporting this query results.
+Only one column is supported. You may concatenate fields and string values in
+the query statement to get the required results.
+
+=item B<MinVersion> I<version>
+
+=item B<MaxVersion> I<version>
+
+Specify the minimum or maximum version of PostgreSQL that this query should be
+used with. Some statistics might only be available with certain versions of
+PostgreSQL. This allows you to specify multiple queries with the same name but
+which apply to different versions, thus allowing you to use the same
+configuration in a heterogeneous environment.
+
+The I<version> has to be specified as the concatenation of the major, minor
+and patch-level versions, each represented as two-decimal-digit numbers. For
+example, version 8.2.3 will become 80203.
+
+=back
+
+The B<Result> block defines how to handle the values returned from the query.
+It defines which column holds which value and how to dispatch that value to
+the daemon.
+
+=over 4
+
 =item B<Type> I<type>
 
 The I<type> name to be used when dispatching the values. The type describes
@@ -4986,7 +5538,7 @@ how to handle the data and where to store it. See L<types.db(5)> for more
 details on types and their configuration. The number and type of values (as
 selected by the B<ValuesFrom> option) has to match the type of the given name.
 
-This option is required inside a B<Result> block.
+This option is mandatory.
 
 =item B<InstancePrefix> I<prefix>
 
@@ -5022,20 +5574,6 @@ This option is required inside a B<Result> block and may be specified multiple
 times. If multiple B<ValuesFrom> options are specified, the columns are read
 in the given order.
 
-=item B<MinVersion> I<version>
-
-=item B<MaxVersion> I<version>
-
-Specify the minimum or maximum version of PostgreSQL that this query should be
-used with. Some statistics might only be available with certain versions of
-PostgreSQL. This allows you to specify multiple queries with the same name but
-which apply to different versions, thus allowing you to use the same
-configuration in a heterogeneous environment.
-
-The I<version> has to be specified as the concatenation of the major, minor
-and patch-level versions, each represented as two-decimal-digit numbers. For
-example, version 8.2.3 will become 80203.
-
 =back
 
 The following predefined queries are available (the definitions can be found
@@ -5205,6 +5743,8 @@ Specify the plugin instance name that should be used instead of the database
 name (which is the default, if this option has not been specified). This
 allows to query multiple databases of the same name on the same host (e.g.
 when running multiple database server versions in parallel).
+The plugin instance name can also be set from the query result using
+the B<PluginInstanceFrom> option in B<Query> block.
 
 =item B<Host> I<hostname>
 
@@ -5471,6 +6011,10 @@ dispatched to the daemon using the specified I<name> as an identifier. This
 allows to "group" several processes together. I<name> must not contain
 slashes.
 
+=item B<CollectContextSwitch> I<Boolean>
+
+Collect context switch of the process.
+
 =back
 
 =head2 Plugin C<protocols>
@@ -5937,6 +6481,12 @@ few ones. This option enables you to do that: By setting B<IgnoreSelected> to
 I<true> the effect of B<Sensor> is inverted: All selected sensors are ignored
 and all other sensors are collected.
 
+=item B<UseLabels> I<true>|I<false>
+
+Configures how sensor readings are reported. When set to I<true>, sensor
+readings are reported using their descriptive label (e.g. "VCore"). When set to
+I<false> (the default) the sensor name is used ("in0").
+
 =back
 
 =head2 Plugin C<sigrok>
@@ -6039,6 +6589,22 @@ collected. If at least one B<Disk> option is given and no B<IgnoreSelected> or
 set to B<false>, B<only> matching disks will be collected. If B<IgnoreSelected>
 is set to B<true>, all disks are collected B<except> the ones matched.
 
+=item B<IgnoreSleepMode> B<true>|B<false>
+
+Normally, the C<smart> plugin will ignore disks that are reported to be asleep.
+This option disables the sleep mode check and allows the plugin to collect data
+from these disks anyway. This is useful in cases where libatasmart mistakenly
+reports disks as asleep because it has not been updated to incorporate support
+for newer idle states in the ATA spec.
+
+=item B<UseSerial> B<true>|B<false>
+
+A disk's kernel name (e.g., sda) can change from one boot to the next. If this
+option is enabled, the C<smart> plugin will use the disk's serial number (e.g.,
+HGST_HUH728080ALE600_2EJ8VH8X) instead of the kernel name as the key for
+storing data. This ensures that the data for a given disk will be kept together
+even if the kernel name changes.
+
 =back
 
 =head2 Plugin C<snmp>
@@ -6085,6 +6651,12 @@ rate of counters and size of sets will be zero, timers report C<NaN> and gauges
 are unchanged. If set to B<True>, the such metrics are not dispatched and
 removed from the internal cache.
 
+=item B<CounterSum> B<false>|B<true>
+
+When enabled, creates a C<count> metric which reports the change since the last
+read. This option primarily exists for compatibility with the I<statsd>
+implementation by Etsy.
+
 =item B<TimerPercentile> I<Percent>
 
 Calculate and dispatch the configured percentile, i.e. compute the latency, so
@@ -6598,7 +7170,7 @@ port in numeric form.
 =item B<AllPortsSummary> I<true>|I<false>
 
 If this option is set to I<true> a summary of statistics from all connections
-are collectd. This option defaults to I<false>.
+are collected. This option defaults to I<false>.
 
 =back
 
@@ -6693,13 +7265,13 @@ fails or if you want to disable this feature.
 =item B<DigitalTemperatureSensor> I<true>|I<false>
 
 Boolean enabling the collection of the temperature of each core.
-This option should only be used if the automated detectionfails or 
+This option should only be used if the automated detectionfails or
 if you want to disable this feature.
 
 =item B<DigitalTemperatureSensor> I<true>|I<false>
 
 Boolean enabling the collection of the temperature of each package.
-This option should only be used if the automated detectionfails or 
+This option should only be used if the automated detectionfails or
 if you want to disable this feature.
 
 =item B<TCCActivationTemp> I<Temperature>
@@ -7039,17 +7611,17 @@ setting B<name>.
 B<address> means use the interface's mac address. This is useful since the
 interface path might change between reboots of a guest or across migrations.
 
-=item B<PluginInstanceFormat> B<name|uuid>
+=item B<PluginInstanceFormat> B<name|uuid|none>
 
 When the virt plugin logs data, it sets the plugin_instance of the collected
-data according to this setting. The default is to use the guest name as provided
-by the hypervisor, which is equal to setting B<name>.
+data according to this setting. The default is to not set the plugin_instance.
 
+B<name> means use the guest's name as provided by the hypervisor.
 B<uuid> means use the guest's UUID.
 
-You can also specify combinations of these fields. For example B<name uuid>
-means to concatenate the guest name and UUID (with a literal colon character
-between, thus I<"foo:1234-1234-1234-1234">).
+You can also specify combinations of the B<name> and B<uuid> fields.
+For example B<name uuid> means to concatenate the guest name and UUID
+(with a literal colon character between, thus I<"foo:1234-1234-1234-1234">).
 
 =back
 
@@ -7124,6 +7696,14 @@ Service name or port number to connect to. Defaults to C<2003>.
 
 Protocol to use when connecting to I<Graphite>. Defaults to C<tcp>.
 
+=item B<ReconnectInterval> I<Seconds>
+
+When set to non-zero, forces the connection to the Graphite backend to be
+closed and re-opend periodically. This behavior is desirable in environments
+where the connection to the Graphite backend is done through load balancers,
+for example. When set to zero, the default, the connetion is kept open for as
+long as possible.
+
 =item B<LogSendErrors> B<false>|B<true>
 
 If set to B<true> (the default), logs errors when sending data to I<Graphite>.
@@ -7350,20 +7930,35 @@ authentication.
 
 Password required to load the private key in B<ClientKey>.
 
+=item B<Header> I<Header>
+
+A HTTP header to add to the request.  Multiple headers are added if this option is specified more than once.  Example:
+
+  Header "X-Custom-Header: custom_value"
+
 =item B<SSLVersion> B<SSLv2>|B<SSLv3>|B<TLSv1>|B<TLSv1_0>|B<TLSv1_1>|B<TLSv1_2>
 
 Define which SSL protocol version must be used. By default C<libcurl> will
 attempt to figure out the remote SSL protocol version. See
 L<curl_easy_setopt(3)> for more details.
 
-=item B<Format> B<Command>|B<JSON>
+=item B<Format> B<Command>|B<JSON>|B<KAIROSDB>
 
 Format of the output to generate. If set to B<Command>, will create output that
 is understood by the I<Exec> and I<UnixSock> plugins. When set to B<JSON>, will
-create output in the I<JavaScript Object Notation> (JSON).
+create output in the I<JavaScript Object Notation> (JSON). When set to KAIROSDB
+, will create output in the KairosDB format.
 
 Defaults to B<Command>.
 
+=item B<Metrics> B<true>|B<false>
+
+Controls whether I<metrics> are POSTed to this location. Defaults to B<true>.
+
+=item B<Notifications> B<false>|B<true>
+
+Controls whether I<notifications> are POSTed to this location. Defaults to B<false>.
+
 =item B<StoreRates> B<true|false>
 
 If set to B<true>, convert counter values to rates. If set to B<false> (the
@@ -7392,6 +7987,10 @@ complete. When this limit is reached, the POST operation will be aborted, and
 all the data in the current send buffer will probably be lost. Defaults to 0,
 which means the connection never times out.
 
+=item B<LogHttpError> B<false>|B<true>
+
+Enables printing of HTTP error code to log. Turned off by default.
+
 The C<write_http> plugin regularly submits the collected values to the HTTP
 server. How frequently this happens depends on how much data you are collecting
 and the size of B<BufferSize>. The optimal value to set B<Timeout> to is
@@ -7518,14 +8117,20 @@ Synopsis:
         Host "localhost"
         Port "6379"
         Timeout 1000
+        Prefix "collectd/"
+        Database 1
+        MaxSetSize -1
+        StoreRates true
     </Node>
   </Plugin>
 
 Values are submitted to I<Sorted Sets>, using the metric name as the key, and
 the timestamp as the score. Retrieving a date range can then be done using the
 C<ZRANGEBYSCORE> I<Redis> command. Additionally, all the identifiers of these
-I<Sorted Sets> are kept in a I<Set> called C<collectd/values> and can be
-retrieved using the C<SMEMBERS> I<Redis> command. See
+I<Sorted Sets> are kept in a I<Set> called C<collectd/values> (or
+C<${prefix}/values> if the B<Prefix> option was specified) and can be retrieved
+using the C<SMEMBERS> I<Redis> command. You can specify the database to use
+with the B<Database> parameter (default is C<0>). See
 L<http://redis.io/commands#sorted_set> and L<http://redis.io/commands#set> for
 details.
 
@@ -7560,6 +8165,28 @@ that numerical port numbers must be given as a string, too.
 
 The B<Timeout> option sets the socket connection timeout, in milliseconds.
 
+=item B<Prefix> I<Prefix>
+
+Prefix used when constructing the name of the I<Sorted Sets> and the I<Set>
+containing all metrics. Defaults to C<collectd/>, so metrics will have names
+like C<collectd/cpu-0/cpu-user>. When setting this to something different, it
+is recommended but not required to include a trailing slash in I<Prefix>.
+
+=item B<Database> I<Index>
+
+This index selects the redis database to use for writing operations. Defaults
+to C<0>.
+
+=item B<MaxSetSize> I<Items>
+
+The B<MaxSetSize> option limits the number of items that the I<Sorted Sets> can
+hold. Negative values for I<Items> sets no limit, which is the default behavior.
+
+=item B<StoreRates> B<true>|B<false>
+
+If set to B<true> (the default), convert counter values to rates. If set to
+B<false> counter values are stored as is, i.e. as an increasing integer number.
+
 =back
 
 =head2 Plugin C<write_riemann>
@@ -7604,11 +8231,26 @@ Hostname or address to connect to. Defaults to C<localhost>.
 
 Service name or port number to connect to. Defaults to C<5555>.
 
-=item B<Protocol> B<UDP>|B<TCP>
+=item B<Protocol> B<UDP>|B<TCP>|B<TLS>
 
 Specify the protocol to use when communicating with I<Riemann>. Defaults to
 B<TCP>.
 
+=item B<TLSCertFile> I<Path>
+
+When using the B<TLS> protocol, path to a PEM certificate to present
+to remote host.
+
+=item B<TLSCAFile> I<Path>
+
+When using the B<TLS> protocol, path to a PEM CA certificate to
+use to validate the remote hosts's identity.
+
+=item B<TLSKeyFile> I<Path>
+
+When using the B<TLS> protocol, path to a PEM private key associated
+with the certificate defined by B<TLSCertFile>.
+
 =item B<Batch> B<true>|B<false>
 
 If set to B<true> and B<Protocol> is set to B<TCP>,
@@ -7628,6 +8270,11 @@ Defaults to true
 
 Maximum payload size for a riemann packet. Defaults to 8192
 
+=item B<BatchFlushTimeout> I<seconds>
+
+Maximum amount of seconds to wait in between to batch flushes.
+No timeout by default.
+
 =item B<StoreRates> B<true>|B<false>
 
 If set to B<true> (the default), convert counter values to rates. If set to
@@ -7794,6 +8441,14 @@ attribute for each metric being sent out to I<Sensu>.
 
 =back
 
+=head2 Plugin C<xencpu>
+
+This plugin collects metrics of hardware CPU load for machine running Xen
+hypervisor. Load is calculated from 'idle time' value, provided by Xen.
+Result is reported using the C<percent> type, for each CPU (core).
+
+This plugin doesn't have any options (yet).
+
 =head2 Plugin C<zookeeper>
 
 The I<zookeeper plugin> will collect statistics from a I<Zookeeper> server
@@ -8691,6 +9346,8 @@ Available options:
 
 =item B<TypeInstance> I<String>
 
+=item B<MetaDataSet> I<String> I<String>
+
 Set the appropriate field to the given string. The strings for plugin instance
 and type instance may be empty, the strings for host and plugin may not be
 empty. It's currently not possible to set the type of a value this way.
index d019d27..31183b1 100644 (file)
@@ -72,6 +72,7 @@
 extern char *optarg;
 extern int   optind;
 
+__attribute__((noreturn))
 static void exit_usage (const char *name, int status) {
   fprintf ((status == 0) ? stdout : stderr,
       "Usage: %s [options] <command> [cmd options]\n\n"
@@ -120,7 +121,7 @@ static int count_chars (const char *str, char chr) {
   return count;
 } /* count_chars */
 
-static int array_grow (void **array, int *array_len, size_t elem_size)
+static int array_grow (void **array, size_t *array_len, size_t elem_size)
 {
   void *tmp;
 
@@ -184,7 +185,6 @@ static int getval (lcc_connection_t *c, int argc, char **argv)
   char   **ret_values_names = NULL;
 
   int status;
-  size_t i;
 
   assert (strcasecmp (argv[0], "getval") == 0);
 
@@ -193,7 +193,6 @@ static int getval (lcc_connection_t *c, int argc, char **argv)
     return (-1);
   }
 
-  memset (&ident, 0, sizeof (ident));
   status = parse_identifier (c, argv[1], &ident);
   if (status != 0)
     return (status);
@@ -203,7 +202,7 @@ static int getval (lcc_connection_t *c, int argc, char **argv)
     if (ret_values != NULL) \
       free (ret_values); \
     if (ret_values_names != NULL) { \
-      for (i = 0; i < ret_values_num; ++i) \
+      for (size_t i = 0; i < ret_values_num; ++i) \
         free (ret_values_names[i]); \
       free (ret_values_names); \
     } \
@@ -218,7 +217,7 @@ static int getval (lcc_connection_t *c, int argc, char **argv)
     BAIL_OUT (-1);
   }
 
-  for (i = 0; i < ret_values_num; ++i)
+  for (size_t i = 0; i < ret_values_num; ++i)
     printf ("%s=%e\n", ret_values_names[i], ret_values[i]);
   BAIL_OUT (0);
 #undef BAIL_OUT
@@ -229,13 +228,12 @@ static int flush (lcc_connection_t *c, int argc, char **argv)
   int timeout = -1;
 
   lcc_identifier_t *identifiers = NULL;
-  int identifiers_num = 0;
+  size_t identifiers_num = 0;
 
   char **plugins = NULL;
-  int plugins_num = 0;
+  size_t plugins_num = 0;
 
   int status;
-  int i;
 
   assert (strcasecmp (argv[0], "flush") == 0);
 
@@ -250,7 +248,7 @@ static int flush (lcc_connection_t *c, int argc, char **argv)
     return (s); \
   } while (0)
 
-  for (i = 1; i < argc; ++i) {
+  for (int i = 1; i < argc; ++i) {
     char *key, *value;
 
     key   = argv[i];
@@ -314,7 +312,7 @@ static int flush (lcc_connection_t *c, int argc, char **argv)
     plugins[0] = NULL;
   }
 
-  for (i = 0; i < plugins_num; ++i) {
+  for (size_t i = 0; i < plugins_num; ++i) {
     if (identifiers_num == 0) {
       status = lcc_flush (c, plugins[i], NULL, timeout);
       if (status != 0)
@@ -322,9 +320,7 @@ static int flush (lcc_connection_t *c, int argc, char **argv)
             (plugins[i] == NULL) ? "(all)" : plugins[i], lcc_strerror (c));
     }
     else {
-      int j;
-
-      for (j = 0; j < identifiers_num; ++j) {
+      for (size_t j = 0; j < identifiers_num; ++j) {
         status = lcc_flush (c, plugins[i], identifiers + j, timeout);
         if (status != 0) {
           char id[1024];
@@ -349,7 +345,6 @@ static int listval (lcc_connection_t *c, int argc, char **argv)
   size_t            ret_ident_num = 0;
 
   int status;
-  size_t i;
 
   assert (strcasecmp (argv[0], "listval") == 0);
 
@@ -372,7 +367,7 @@ static int listval (lcc_connection_t *c, int argc, char **argv)
     BAIL_OUT (status);
   }
 
-  for (i = 0; i < ret_ident_num; ++i) {
+  for (size_t i = 0; i < ret_ident_num; ++i) {
     char id[1024];
 
     status = lcc_identifier_to_string (c, id, sizeof (id), ret_ident + i);
@@ -398,7 +393,6 @@ static int putval (lcc_connection_t *c, int argc, char **argv)
   size_t  values_len = 0;
 
   int status;
-  int i;
 
   assert (strcasecmp (argv[0], "putval") == 0);
 
@@ -415,7 +409,7 @@ static int putval (lcc_connection_t *c, int argc, char **argv)
   if (status != 0)
     return (status);
 
-  for (i = 2; i < argc; ++i) {
+  for (int i = 2; i < argc; ++i) {
     char *tmp;
 
     tmp = strchr (argv[i], (int)'=');
@@ -482,7 +476,7 @@ static int putval (lcc_connection_t *c, int argc, char **argv)
 
       values_len = 0;
       value = tmp;
-      while (value != 0) {
+      while (value != NULL) {
         char *dot, *endptr;
 
         tmp = strchr (value, (int)':');
@@ -507,7 +501,7 @@ static int putval (lcc_connection_t *c, int argc, char **argv)
           values_types[values_len] = LCC_TYPE_GAUGE;
         }
         else { /* integer */
-          values[values_len].counter = strtol (value, &endptr, 0);
+          values[values_len].counter = (counter_t) strtoull (value, &endptr, 0);
           values_types[values_len] = LCC_TYPE_COUNTER;
         }
         ++values_len;
@@ -551,21 +545,20 @@ int main (int argc, char **argv) {
   int status;
 
   while (42) {
-    int n;
+    int opt;
 
-    n = getopt (argc, argv, "s:h");
+    opt = getopt (argc, argv, "s:h");
 
-    if (n == -1)
+    if (opt == -1)
       break;
 
-    switch (n) {
+    switch (opt) {
       case 's':
         snprintf (address, sizeof (address), "unix:%s", optarg);
         address[sizeof (address) - 1] = '\0';
         break;
       case 'h':
         exit_usage (argv[0], 0);
-        break;
       default:
         exit_usage (argv[0], 1);
     }
index 33f02b4..13304f2 100644 (file)
 static int loop    = 0;
 static int restart = 0;
 
-static char  *pidfile      = NULL;
-static pid_t  collectd_pid = 0;
+static const char *pidfile      = NULL;
+static pid_t       collectd_pid = 0;
 
-static void exit_usage (char *name)
+__attribute__((noreturn))
+static void exit_usage (const char *name)
 {
        printf ("Usage: %s <options> [-- <collectd options>]\n"
 
@@ -119,6 +120,7 @@ static int pidfile_delete (void)
 static int daemonize (void)
 {
        struct rlimit rl;
+       int dev_null;
 
        pid_t pid = 0;
        int   i   = 0;
@@ -152,26 +154,33 @@ static int daemonize (void)
        for (i = 0; i < (int)rl.rlim_max; ++i)
                close (i);
 
-       errno = 0;
-       if (open ("/dev/null", O_RDWR) != 0) {
-               syslog (LOG_ERR, "Error: couldn't connect STDIN to /dev/null: %s",
-                               strerror (errno));
+       dev_null = open ("/dev/null", O_RDWR);
+       if (dev_null == -1) {
+               syslog (LOG_ERR, "Error: couldn't open /dev/null: %s", strerror (errno));
                return -1;
        }
 
-       errno = 0;
-       if (dup (0) != 1) {
-               syslog (LOG_ERR, "Error: couldn't connect STDOUT to /dev/null: %s",
-                               strerror (errno));
+       if (dup2 (dev_null, STDIN_FILENO) == -1) {
+               close (dev_null);
+               syslog (LOG_ERR, "Error: couldn't connect STDIN to /dev/null: %s", strerror (errno));
                return -1;
        }
 
-       errno = 0;
-       if (dup (0) != 2) {
-               syslog (LOG_ERR, "Error: couldn't connect STDERR to /dev/null: %s",
-                               strerror (errno));
+       if (dup2 (dev_null, STDOUT_FILENO) == -1) {
+               close (dev_null);
+               syslog (LOG_ERR, "Error: couldn't connect STDOUT to /dev/null: %s", strerror (errno));
                return -1;
        }
+
+       if (dup2 (dev_null, STDERR_FILENO) == -1) {
+               close (dev_null);
+               syslog (LOG_ERR, "Error: couldn't connect STDERR to /dev/null: %s", strerror (errno));
+               return -1;
+       }
+
+       if ((dev_null != STDIN_FILENO) && (dev_null != STDOUT_FILENO) && (dev_null != STDERR_FILENO))
+               close (dev_null);
+
        return 0;
 } /* daemonize */
 
index 49a3355..ce90ede 100644 (file)
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -74,14 +75,13 @@ static int conntrack_read (void)
 {
        value_t conntrack, conntrack_max, conntrack_pct;
        FILE *fh;
-       char buffer[64];
+       char buffer[64] = { 0 };
        size_t buffer_len;
 
        fh = fopen (old_files?CONNTRACK_FILE_OLD:CONNTRACK_FILE, "r");
        if (fh == NULL)
                return (-1);
 
-       memset (buffer, 0, sizeof (buffer));
        if (fgets (buffer, sizeof (buffer), fh) == NULL)
        {
                fclose (fh);
@@ -135,7 +135,7 @@ static int conntrack_read (void)
 
 void module_register (void)
 {
-    plugin_register_config ("conntrack", conntrack_config,
+       plugin_register_config ("conntrack", conntrack_config,
                             config_keys, config_keys_num);
        plugin_register_read ("conntrack", conntrack_read);
 } /* void module_register */
index 344f76e..76e2a6c 100644 (file)
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
index c946250..8002966 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -28,6 +28,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -405,19 +406,16 @@ static cpu_state_t *get_cpu_state (size_t cpu_num, size_t state) /* {{{ */
  * array. */
 static void aggregate (gauge_t *sum_by_state) /* {{{ */
 {
-       size_t cpu_num;
-       size_t state;
-
-       for (state = 0; state < COLLECTD_CPU_STATE_MAX; state++)
+       for (size_t state = 0; state < COLLECTD_CPU_STATE_MAX; state++)
                sum_by_state[state] = NAN;
 
-       for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+       for (size_t cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
        {
                cpu_state_t *this_cpu_states = get_cpu_state (cpu_num, 0);
 
                this_cpu_states[COLLECTD_CPU_STATE_ACTIVE].rate = NAN;
 
-               for (state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
+               for (size_t state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
                {
                        if (!this_cpu_states[state].has_value)
                                continue;
@@ -442,7 +440,6 @@ static void aggregate (gauge_t *sum_by_state) /* {{{ */
 static void cpu_commit_one (int cpu_num, /* {{{ */
                gauge_t rates[static COLLECTD_CPU_STATE_MAX])
 {
-       size_t state;
        gauge_t sum;
 
        sum = rates[COLLECTD_CPU_STATE_ACTIVE];
@@ -455,7 +452,7 @@ static void cpu_commit_one (int cpu_num, /* {{{ */
                return;
        }
 
-       for (state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
+       for (size_t state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
        {
                gauge_t percent = 100.0 * rates[state] / sum;
                submit_percent (cpu_num, state, percent);
@@ -466,9 +463,7 @@ static void cpu_commit_one (int cpu_num, /* {{{ */
  * each iteration / after each call to cpu_commit(). */
 static void cpu_reset (void) /* {{{ */
 {
-       size_t i;
-
-       for (i = 0; i < cpu_states_num; i++)
+       for (size_t i = 0; i < cpu_states_num; i++)
                cpu_states[i].has_value = 0;
 
        global_cpu_num = 0;
@@ -477,13 +472,9 @@ static void cpu_reset (void) /* {{{ */
 /* Legacy behavior: Dispatches the raw derive values without any aggregation. */
 static void cpu_commit_without_aggregation (void) /* {{{ */
 {
-       int state;
-
-       for (state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
+       for (int state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
        {
-               size_t cpu_num;
-
-               for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+               for (size_t cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
                {
                        cpu_state_t *s = get_cpu_state (cpu_num, state);
 
@@ -501,7 +492,6 @@ static void cpu_commit (void) /* {{{ */
        gauge_t global_rates[COLLECTD_CPU_STATE_MAX] = {
                NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN /* Batman! */
        };
-       size_t cpu_num;
 
        if (report_by_state && report_by_cpu && !report_percent)
        {
@@ -517,15 +507,14 @@ static void cpu_commit (void) /* {{{ */
                return;
        }
 
-       for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+       for (size_t cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
        {
                cpu_state_t *this_cpu_states = get_cpu_state (cpu_num, 0);
                gauge_t local_rates[COLLECTD_CPU_STATE_MAX] = {
                        NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN
                };
-               size_t state;
 
-               for (state = 0; state < COLLECTD_CPU_STATE_MAX; state++)
+               for (size_t state = 0; state < COLLECTD_CPU_STATE_MAX; state++)
                        if (this_cpu_states[state].has_value)
                                local_rates[state] = this_cpu_states[state].rate;
 
@@ -536,11 +525,12 @@ static void cpu_commit (void) /* {{{ */
 /* Adds a derive value to the internal state. This should be used by each read
  * function for each state. At the end of the iteration, the read function
  * should call cpu_commit(). */
-static int cpu_stage (size_t cpu_num, size_t state, derive_t value, cdtime_t now) /* {{{ */
+static int cpu_stage (size_t cpu_num, size_t state, derive_t d, cdtime_t now) /* {{{ */
 {
        int status;
        cpu_state_t *s;
-       value_t v;
+       gauge_t rate = NAN;
+       value_t val = {.derive = d};
 
        if (state >= COLLECTD_CPU_STATE_ACTIVE)
                return (EINVAL);
@@ -554,12 +544,11 @@ static int cpu_stage (size_t cpu_num, size_t state, derive_t value, cdtime_t now
 
        s = get_cpu_state (cpu_num, state);
 
-       v.gauge = NAN;
-       status = value_to_rate (&v, value, &s->conv, DS_TYPE_DERIVE, now);
+       status = value_to_rate (&rate, val, DS_TYPE_DERIVE, now, &s->conv);
        if (status != 0)
                return (status);
 
-       s->rate = v.gauge;
+       s->rate = rate;
        s->has_value = 1;
        return (0);
 } /* }}} int cpu_stage */
@@ -569,8 +558,6 @@ static int cpu_read (void)
        cdtime_t now = cdtime ();
 
 #if PROCESSOR_CPU_LOAD_INFO /* {{{ */
-       int cpu;
-
        kern_return_t status;
 
        processor_cpu_load_info_data_t cpu_info;
@@ -578,7 +565,7 @@ static int cpu_read (void)
 
        host_t cpu_host;
 
-       for (cpu = 0; cpu < cpu_list_len; cpu++)
+       for (int cpu = 0; cpu < cpu_list_len; cpu++)
        {
                cpu_host = 0;
                cpu_info_len = PROCESSOR_BASIC_INFO_COUNT;
@@ -653,13 +640,12 @@ static int cpu_read (void)
 /* }}} #endif defined(KERNEL_LINUX) */
 
 #elif defined(HAVE_LIBKSTAT) /* {{{ */
-       int cpu;
        static cpu_stat_t cs;
 
        if (kc == NULL)
                return (-1);
 
-       for (cpu = 0; cpu < numcpu; cpu++)
+       for (int cpu = 0; cpu < numcpu; cpu++)
        {
                if (kstat_read (kc, ksp[cpu], &cs) == -1)
                        continue; /* error message? */
@@ -675,7 +661,6 @@ static int cpu_read (void)
        uint64_t cpuinfo[numcpu][CPUSTATES];
        size_t cpuinfo_size;
        int status;
-       int i;
 
        if (numcpu < 1)
        {
@@ -688,7 +673,7 @@ static int cpu_read (void)
 
 #if defined(KERN_CPTIME2)
        if (numcpu > 1) {
-               for (i = 0; i < numcpu; i++) {
+               for (int i = 0; i < numcpu; i++) {
                        int mib[] = {CTL_KERN, KERN_CPTIME2, i};
 
                        cpuinfo_size = sizeof (cpuinfo[0]);
@@ -721,12 +706,12 @@ static int cpu_read (void)
                        return (-1);
                }
 
-               for(i = 0; i < CPUSTATES; i++) {
+               for(int i = 0; i < CPUSTATES; i++) {
                        cpuinfo[0][i] = cpuinfo_tmp[i];
                }
        }
 
-       for (i = 0; i < numcpu; i++) {
+       for (int i = 0; i < numcpu; i++) {
                cpu_stage (i, COLLECTD_CPU_STATE_USER,      (derive_t) cpuinfo[i][CP_USER], now);
                cpu_stage (i, COLLECTD_CPU_STATE_NICE,      (derive_t) cpuinfo[i][CP_NICE], now);
                cpu_stage (i, COLLECTD_CPU_STATE_SYSTEM,    (derive_t) cpuinfo[i][CP_SYS], now);
@@ -738,7 +723,6 @@ static int cpu_read (void)
 #elif defined(HAVE_SYSCTLBYNAME) && defined(HAVE_SYSCTL_KERN_CP_TIMES) /* {{{ */
        long cpuinfo[maxcpu][CPUSTATES];
        size_t cpuinfo_size;
-       int i;
 
        memset (cpuinfo, 0, sizeof (cpuinfo));
 
@@ -751,7 +735,7 @@ static int cpu_read (void)
                return (-1);
        }
 
-       for (i = 0; i < numcpu; i++) {
+       for (int i = 0; i < numcpu; i++) {
                cpu_stage (i, COLLECTD_CPU_STATE_USER,      (derive_t) cpuinfo[i][CP_USER], now);
                cpu_stage (i, COLLECTD_CPU_STATE_NICE,      (derive_t) cpuinfo[i][CP_NICE], now);
                cpu_stage (i, COLLECTD_CPU_STATE_SYSTEM,    (derive_t) cpuinfo[i][CP_SYS], now);
@@ -801,7 +785,7 @@ static int cpu_read (void)
 
 #elif defined(HAVE_PERFSTAT) /* {{{ */
        perfstat_id_t id;
-       int i, cpus;
+       int cpus;
 
        numcpu =  perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);
        if(numcpu == -1)
@@ -814,8 +798,7 @@ static int cpu_read (void)
 
        if (pnumcpu != numcpu || perfcpu == NULL)
        {
-               if (perfcpu != NULL)
-                       free(perfcpu);
+               free(perfcpu);
                perfcpu = malloc(numcpu * sizeof(perfstat_cpu_t));
        }
        pnumcpu = numcpu;
@@ -829,7 +812,7 @@ static int cpu_read (void)
                return (-1);
        }
 
-       for (i = 0; i < cpus; i++)
+       for (int i = 0; i < cpus; i++)
        {
                cpu_stage (i, COLLECTD_CPU_STATE_IDLE,   (derive_t) perfcpu[i].idle, now);
                cpu_stage (i, COLLECTD_CPU_STATE_SYSTEM, (derive_t) perfcpu[i].sys,  now);
index b92b1d0..1e9e857 100644 (file)
@@ -21,6 +21,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -80,12 +81,11 @@ static int cpufreq_read (void)
 {
         int status;
        unsigned long long val;
-       int i = 0;
        FILE *fp;
        char filename[256];
        char buffer[16];
 
-       for (i = 0; i < num_cpu; i++)
+       for (int i = 0; i < num_cpu; i++)
        {
                status = ssnprintf (filename, sizeof (filename),
                                "/sys/devices/system/cpu/cpu%d/cpufreq/"
diff --git a/src/cpusleep.c b/src/cpusleep.c
new file mode 100644 (file)
index 0000000..326c29c
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ * collectd - src/cpusleep.c
+ * Copyright (C) 2016 rinigus
+ *
+ * The MIT License (MIT)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *      rinigus <http://github.com/rinigus>
+ *
+ * CPU sleep is reported in milliseconds of sleep per second of wall
+ * time. For that, the time difference between BOOT and MONOTONIC clocks
+ * is reported using derive type.
+**/
+
+#include "collectd.h"
+
+#include "common.h"
+#include "plugin.h"
+#include <time.h>
+
+static void cpusleep_submit(derive_t cpu_sleep) {
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].derive = cpu_sleep;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy(vl.host, hostname_g, sizeof(vl.host));
+  sstrncpy(vl.plugin, "cpusleep", sizeof(vl.plugin));
+  sstrncpy(vl.type, "total_time_in_ms", sizeof(vl.type));
+
+  plugin_dispatch_values(&vl);
+}
+
+static int cpusleep_read(void) {
+  struct timespec b, m;
+  if (clock_gettime(CLOCK_BOOTTIME, &b) < 0) {
+    ERROR("cpusleep plugin: clock_boottime failed");
+    return (-1);
+  }
+
+  if (clock_gettime(CLOCK_MONOTONIC, &m) < 0) {
+    ERROR("cpusleep plugin: clock_monotonic failed");
+    return (-1);
+  }
+
+  // to avoid false positives in counter overflow due to reboot,
+  // derive is used. Sleep is calculated in milliseconds
+  derive_t diffsec = b.tv_sec - m.tv_sec;
+  derive_t diffnsec = b.tv_nsec - m.tv_nsec;
+  derive_t sleep = diffsec * 1000 + diffnsec / 1000000;
+
+  cpusleep_submit(sleep);
+
+  return (0);
+}
+
+void module_register(void) {
+  plugin_register_read("cpusleep", cpusleep_read);
+} /* void module_register */
index 81e580d..070d33a 100644 (file)
@@ -21,7 +21,7 @@
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *   Sven Trenkel <collectd at semidefinite.de>  
+ *   Sven Trenkel <collectd at semidefinite.de>
  **/
 
 /* Some python versions don't include this by default. */
        PyGILState_Release(gil_state);\
 }
 
-/* Python 2.4 has this macro, older versions do not. */
-#ifndef Py_VISIT
-#define Py_VISIT(o) do {\
-       int _vret;\
-       if ((o) != NULL) {\
-               _vret = visit((o), arg);\
-               if (_vret != 0)\
-               return _vret;\
-       }\
-} while (0)
-#endif
-
-/* Python 2.4 has this macro, older versions do not. */
-#ifndef Py_CLEAR
-#define Py_CLEAR(o) do {\
-       PyObject *tmp = o;\
-       (o) = NULL;\
-       Py_XDECREF(tmp);\
-} while (0)
-#endif
-
-/* Python 2.4 has this macro, older versions do not. */
-#ifndef Py_RETURN_NONE
-# define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
-#endif
-
 /* This macro is a shortcut for calls like
  * x = PyObject_Repr(x);
  * This can't be done like this example because this would leak
 } while (0)
 static inline void CPY_STRCAT(PyObject **a, PyObject *b) {
        PyObject *ret;
-       
+
        if (!a || !*a)
                return;
-       
+
        ret = PyUnicode_Concat(*a, b);
        Py_DECREF(*a);
        *a = ret;
@@ -156,7 +130,7 @@ static inline PyObject *cpy_string_to_unicode_or_bytes(const char *buf) {
        return PyBytes_FromString(buf);
 #else
        return PyString_FromString(buf);
-#endif 
+#endif
 }
 
 void cpy_log_exception(const char *context);
@@ -170,7 +144,7 @@ typedef struct {
        PyObject *values;    /* Sequence */
        PyObject *children;  /* Sequence */
 } Config;
-PyTypeObject ConfigType;
+extern PyTypeObject ConfigType;
 
 typedef struct {
        PyObject_HEAD        /* No semicolon! */
@@ -181,7 +155,7 @@ typedef struct {
        char type[DATA_MAX_NAME_LEN];
        char type_instance[DATA_MAX_NAME_LEN];
 } PluginData;
-PyTypeObject PluginDataType;
+extern PyTypeObject PluginDataType;
 #define PluginData_New() PyObject_CallFunctionObjArgs((PyObject *) &PluginDataType, (void *) 0)
 
 typedef struct {
@@ -190,7 +164,7 @@ typedef struct {
        PyObject *meta;      /* dict */
        double interval;
 } Values;
-PyTypeObject ValuesType;
+extern PyTypeObject ValuesType;
 #define Values_New() PyObject_CallFunctionObjArgs((PyObject *) &ValuesType, (void *) 0)
 
 typedef struct {
@@ -198,12 +172,12 @@ typedef struct {
        int severity;
        char message[NOTIF_MAX_MSG_LEN];
 } Notification;
-PyTypeObject NotificationType;
+extern PyTypeObject NotificationType;
 #define Notification_New() PyObject_CallFunctionObjArgs((PyObject *) &NotificationType, (void *) 0)
 
 typedef PyLongObject Signed;
-PyTypeObject SignedType;
+extern PyTypeObject SignedType;
 
 typedef PyLongObject Unsigned;
-PyTypeObject UnsignedType;
+extern PyTypeObject UnsignedType;
 
index 0772873..e008ecf 100644 (file)
--- a/src/csv.c
+++ b/src/csv.c
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "utils_cache.h"
@@ -45,7 +46,6 @@ static int value_list_to_string (char *buffer, int buffer_len,
 {
        int offset;
        int status;
-       int i;
        gauge_t *rates = NULL;
 
        assert (0 == strcmp (ds->type, vl->type));
@@ -58,7 +58,7 @@ static int value_list_to_string (char *buffer, int buffer_len,
                return (-1);
        offset = status;
 
-       for (i = 0; i < ds->ds_num; i++)
+       for (size_t i = 0; i < ds->ds_num; i++)
        {
                if ((ds->ds[i].type != DS_TYPE_COUNTER)
                                && (ds->ds[i].type != DS_TYPE_GAUGE)
@@ -187,7 +187,6 @@ static int value_list_to_filename (char *buffer, size_t buffer_size,
 static int csv_create_file (const char *filename, const data_set_t *ds)
 {
        FILE *csv;
-       int i;
 
        if (check_create_dir (filename))
                return (-1);
@@ -203,7 +202,7 @@ static int csv_create_file (const char *filename, const data_set_t *ds)
        }
 
        fprintf (csv, "epoch");
-       for (i = 0; i < ds->ds_num; i++)
+       for (size_t i = 0; i < ds->ds_num; i++)
                fprintf (csv, ",%s", ds->ds[i].name);
 
        fprintf (csv, "\n");
@@ -269,7 +268,7 @@ static int csv_write (const data_set_t *ds, const value_list_t *vl,
        char         values[4096];
        FILE        *csv;
        int          csv_fd;
-       struct flock fl;
+       struct flock fl = { 0 };
        int          status;
 
        if (0 != strcmp (ds->type, vl->type)) {
@@ -288,12 +287,10 @@ static int csv_write (const data_set_t *ds, const value_list_t *vl,
 
        if (use_stdio)
        {
-               size_t i;
-
                escape_string (filename, sizeof (filename));
 
                /* Replace commas by colons for PUTVAL compatible output. */
-               for (i = 0; i < sizeof (values); i++)
+               for (size_t i = 0; i < sizeof (values); i++)
                {
                        if (values[i] == 0)
                                break;
@@ -342,9 +339,6 @@ static int csv_write (const data_set_t *ds, const value_list_t *vl,
        }
        csv_fd = fileno (csv);
 
-       memset (&fl, '\0', sizeof (fl));
-       fl.l_start  = 0;
-       fl.l_len    = 0; /* till end of file */
        fl.l_pid    = getpid ();
        fl.l_type   = F_WRLCK;
        fl.l_whence = SEEK_SET;
index 470f25d..8d7baa5 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
+#include "utils_curl_stats.h"
 #include "utils_match.h"
 #include "utils_time.h"
 
@@ -67,6 +69,7 @@ struct web_page_s /* {{{ */
   _Bool response_time;
   _Bool response_code;
   int timeout;
+  curl_stats_t *stats;
 
   CURL *curl;
   char curl_errbuf[CURL_ERROR_SIZE];
@@ -95,7 +98,7 @@ static size_t cc_curl_callback (void *buf, /* {{{ */
   size_t len;
 
   len = size * nmemb;
-  if (len <= 0)
+  if (len == 0)
     return (len);
 
   wp = user_data;
@@ -108,7 +111,7 @@ static size_t cc_curl_callback (void *buf, /* {{{ */
     size_t temp_size;
 
     temp_size = wp->buffer_fill + len + 1;
-    temp = (char *) realloc (wp->buffer, temp_size);
+    temp = realloc (wp->buffer, temp_size);
     if (temp == NULL)
     {
       ERROR ("curl plugin: realloc failed.");
@@ -156,6 +159,7 @@ static void cc_web_page_free (web_page_t *wp) /* {{{ */
   sfree (wp->cacert);
   sfree (wp->post_body);
   curl_slist_free_all (wp->headers);
+  curl_stats_destroy (wp->stats);
 
   sfree (wp->buffer);
 
@@ -266,23 +270,21 @@ static int cc_config_add_match (web_page_t *page, /* {{{ */
 {
   web_match_t *match;
   int status;
-  int i;
 
   if (ci->values_num != 0)
   {
     WARNING ("curl plugin: Ignoring arguments for the `Match' block.");
   }
 
-  match = (web_match_t *) malloc (sizeof (*match));
+  match = calloc (1, sizeof (*match));
   if (match == NULL)
   {
-    ERROR ("curl plugin: malloc failed.");
+    ERROR ("curl plugin: calloc failed.");
     return (-1);
   }
-  memset (match, 0, sizeof (*match));
 
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -339,7 +341,7 @@ static int cc_config_add_match (web_page_t *page, /* {{{ */
       match->dstype);
   if (match->match == NULL)
   {
-    ERROR ("curl plugin: tail_match_add_match_simple failed.");
+    ERROR ("curl plugin: match_create_simple failed.");
     cc_web_match_free (match);
     return (-1);
   }
@@ -391,7 +393,7 @@ static int cc_page_init_curl (web_page_t *wp) /* {{{ */
     if (wp->pass != NULL)
       credentials_size += strlen (wp->pass);
 
-    wp->credentials = (char *) malloc (credentials_size);
+    wp->credentials = malloc (credentials_size);
     if (wp->credentials == NULL)
     {
       ERROR ("curl plugin: malloc failed.");
@@ -421,8 +423,7 @@ static int cc_page_init_curl (web_page_t *wp) /* {{{ */
   if (wp->timeout >= 0)
     curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS, (long) wp->timeout);
   else
-    curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS,
-       CDTIME_T_TO_MS(plugin_get_interval()));
+    curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
 #endif
 
   return (0);
@@ -432,7 +433,6 @@ static int cc_config_add_page (oconfig_item_t *ci) /* {{{ */
 {
   web_page_t *page;
   int status;
-  int i;
 
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
   {
@@ -440,13 +440,12 @@ static int cc_config_add_page (oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  page = (web_page_t *) malloc (sizeof (*page));
+  page = calloc (1, sizeof (*page));
   if (page == NULL)
   {
-    ERROR ("curl plugin: malloc failed.");
+    ERROR ("curl plugin: calloc failed.");
     return (-1);
   }
-  memset (page, 0, sizeof (*page));
   page->url = NULL;
   page->user = NULL;
   page->pass = NULL;
@@ -456,6 +455,7 @@ static int cc_config_add_page (oconfig_item_t *ci) /* {{{ */
   page->response_time = 0;
   page->response_code = 0;
   page->timeout = -1;
+  page->stats = NULL;
 
   page->instance = strdup (ci->values[0].value.string);
   if (page->instance == NULL)
@@ -467,7 +467,7 @@ static int cc_config_add_page (oconfig_item_t *ci) /* {{{ */
 
   /* Process all children */
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -498,6 +498,11 @@ static int cc_config_add_page (oconfig_item_t *ci) /* {{{ */
       status = cf_util_get_string (child, &page->post_body);
     else if (strcasecmp ("Timeout", child->key) == 0)
       status = cf_util_get_int (child, &page->timeout);
+    else if (strcasecmp ("Statistics", child->key) == 0) {
+      page->stats = curl_stats_from_config (child);
+      if (page->stats == NULL)
+        status = -1;
+    }
     else
     {
       WARNING ("curl plugin: Option `%s' not allowed here.", child->key);
@@ -517,12 +522,13 @@ static int cc_config_add_page (oconfig_item_t *ci) /* {{{ */
       status = -1;
     }
 
-    if (page->matches == NULL && !page->response_time && !page->response_code)
+    if (page->matches == NULL && page->stats == NULL
+        && !page->response_time && !page->response_code)
     {
       assert (page->instance != NULL);
       WARNING ("curl plugin: No (valid) `Match' block "
-          "or MeasureResponseTime or MeasureResponseCode within "
-          "`Page' block `%s'.", page->instance);
+          "or Statistics or MeasureResponseTime or MeasureResponseCode "
+          "within `Page' block `%s'.", page->instance);
       status = -1;
     }
 
@@ -546,7 +552,7 @@ static int cc_config_add_page (oconfig_item_t *ci) /* {{{ */
     web_page_t *prev;
 
     prev = pages_g;
-    while ((prev != NULL) && (prev->next != NULL))
+    while (prev->next != NULL)
       prev = prev->next;
     prev->next = page;
   }
@@ -559,12 +565,11 @@ static int cc_config (oconfig_item_t *ci) /* {{{ */
   int success;
   int errors;
   int status;
-  int i;
 
   success = 0;
   errors = 0;
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -660,7 +665,6 @@ static void cc_submit_response_time (const web_page_t *wp, /* {{{ */
 
 static int cc_read_page (web_page_t *wp) /* {{{ */
 {
-  web_match_t *wm;
   int status;
   cdtime_t start = 0;
 
@@ -678,6 +682,8 @@ static int cc_read_page (web_page_t *wp) /* {{{ */
 
   if (wp->response_time)
     cc_submit_response_time (wp, cdtime() - start);
+  if (wp->stats != NULL)
+    curl_stats_dispatch (wp->stats, wp->curl, hostname_g, "curl", wp->instance);
 
   if(wp->response_code)
   {
@@ -691,7 +697,7 @@ static int cc_read_page (web_page_t *wp) /* {{{ */
     }
   }
 
-  for (wm = wp->matches; wm != NULL; wm = wm->next)
+  for (web_match_t *wm = wp->matches; wm != NULL; wm = wm->next)
   {
     cu_match_value_t *mv;
 
@@ -718,9 +724,7 @@ static int cc_read_page (web_page_t *wp) /* {{{ */
 
 static int cc_read (void) /* {{{ */
 {
-  web_page_t *wp;
-
-  for (wp = pages_g; wp != NULL; wp = wp->next)
+  for (web_page_t *wp = pages_g; wp != NULL; wp = wp->next)
     cc_read_page (wp);
 
   return (0);
index 4188f37..d4e7803 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 #include "utils_avltree.h"
 #include "utils_complain.h"
+#include "utils_curl_stats.h"
 
-#include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
 
@@ -79,6 +80,7 @@ struct cj_s /* {{{ */
   char *post_body;
   cdtime_t interval;
   int timeout;
+  curl_stats_t *stats;
 
   CURL *curl;
   char curl_errbuf[CURL_ERROR_SIZE];
@@ -117,7 +119,7 @@ static size_t cj_curl_callback (void *buf, /* {{{ */
 
   len = size * nmemb;
 
-  if (len <= 0)
+  if (len == 0)
     return (len);
 
   db = user_data;
@@ -433,6 +435,7 @@ static void cj_free (void *arg) /* {{{ */
   sfree (db->cacert);
   sfree (db->post_body);
   curl_slist_free_all (db->headers);
+  curl_stats_destroy (db->stats);
 
   sfree (db);
 } /* }}} void cj_free */
@@ -468,7 +471,6 @@ static int cj_config_add_key (cj_t *db, /* {{{ */
 {
   cj_key_t *key;
   int status;
-  int i;
 
   if ((ci->values_num != 1)
       || (ci->values[0].type != OCONFIG_TYPE_STRING))
@@ -478,13 +480,12 @@ static int cj_config_add_key (cj_t *db, /* {{{ */
     return (-1);
   }
 
-  key = (cj_key_t *) malloc (sizeof (*key));
+  key = calloc (1, sizeof (*key));
   if (key == NULL)
   {
-    ERROR ("curl_json plugin: malloc failed.");
+    ERROR ("curl_json plugin: calloc failed.");
     return (-1);
   }
-  memset (key, 0, sizeof (*key));
   key->magic = CJ_KEY_MAGIC;
 
   if (strcasecmp ("Key", ci->key) == 0)
@@ -505,7 +506,7 @@ static int cj_config_add_key (cj_t *db, /* {{{ */
   }
 
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -619,7 +620,7 @@ static int cj_init_curl (cj_t *db) /* {{{ */
     if (db->pass != NULL)
       credentials_size += strlen (db->pass);
 
-    db->credentials = (char *) malloc (credentials_size);
+    db->credentials = malloc (credentials_size);
     if (db->credentials == NULL)
     {
       ERROR ("curl_json plugin: malloc failed.");
@@ -649,11 +650,9 @@ static int cj_init_curl (cj_t *db) /* {{{ */
   if (db->timeout >= 0)
     curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) db->timeout);
   else if (db->interval > 0)
-    curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
-        CDTIME_T_TO_MS(db->timeout));
+    curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(db->timeout));
   else
-    curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
-        CDTIME_T_TO_MS(plugin_get_interval()));
+    curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
 #endif
 
   return (0);
@@ -663,7 +662,6 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
 {
   cj_t *db;
   int status = 0;
-  int i;
 
   if ((ci->values_num != 1)
       || (ci->values[0].type != OCONFIG_TYPE_STRING))
@@ -673,13 +671,12 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  db = (cj_t *) malloc (sizeof (*db));
+  db = calloc (1, sizeof (*db));
   if (db == NULL)
   {
-    ERROR ("curl_json plugin: malloc failed.");
+    ERROR ("curl_json plugin: calloc failed.");
     return (-1);
   }
-  memset (db, 0, sizeof (*db));
 
   db->timeout = -1;
 
@@ -701,7 +698,7 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
   }
 
   /* Fill the `cj_t' structure.. */
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -731,6 +728,12 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
       status = cf_util_get_cdtime(child, &db->interval);
     else if (strcasecmp ("Timeout", child->key) == 0)
       status = cf_util_get_int (child, &db->timeout);
+    else if (strcasecmp ("Statistics", child->key) == 0)
+    {
+      db->stats = curl_stats_from_config (child);
+      if (db->stats == NULL)
+        status = -1;
+    }
     else
     {
       WARNING ("curl_json plugin: Option `%s' not allowed here.", child->key);
@@ -756,11 +759,8 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
   /* If all went well, register this database for reading */
   if (status == 0)
   {
-    user_data_t ud;
+    user_data_t ud = { 0 };
     char *cb_name;
-    struct timespec interval = { 0, 0 };
-
-    CDTIME_T_TO_TIMESPEC (db->interval, &interval);
 
     if (db->instance == NULL)
       db->instance = strdup("default");
@@ -768,7 +768,6 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
     DEBUG ("curl_json plugin: Registering new read callback: %s",
            db->instance);
 
-    memset (&ud, 0, sizeof (ud));
     ud.data = (void *) db;
     ud.free_func = cj_free;
 
@@ -776,7 +775,7 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
                db->instance, db->url ? db->url : db->sock);
 
     plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read,
-                                  /* interval = */ (db->interval > 0) ? &interval : NULL,
+                                  /* interval = */ db->interval,
                                   &ud);
     sfree (cb_name);
   }
@@ -795,12 +794,11 @@ static int cj_config (oconfig_item_t *ci) /* {{{ */
   int success;
   int errors;
   int status;
-  int i;
 
   success = 0;
   errors = 0;
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -831,32 +829,33 @@ static int cj_config (oconfig_item_t *ci) /* {{{ */
 
 /* }}} End of configuration handling functions */
 
+static const char *cj_host (cj_t *db) /* {{{ */
+{
+  if ((db->host == NULL)
+      || (strcmp ("", db->host) == 0)
+      || (strcmp (CJ_DEFAULT_HOST, db->host) == 0))
+    return hostname_g;
+  return db->host;
+} /* }}} cj_host */
+
 static void cj_submit (cj_t *db, cj_key_t *key, value_t *value) /* {{{ */
 {
   value_list_t vl = VALUE_LIST_INIT;
-  char *host;
 
   vl.values     = value;
   vl.values_len = 1;
 
-  if ((db->host == NULL)
-      || (strcmp ("", db->host) == 0)
-      || (strcmp (CJ_DEFAULT_HOST, db->host) == 0))
-    host = hostname_g;
-  else
-    host = db->host;
-
   if (key->instance == NULL)
   {
-    int i, len = 0;
-    for (i = 0; i < db->depth; i++)
+    int len = 0;
+    for (int i = 0; i < db->depth; i++)
       len += ssnprintf(vl.type_instance+len, sizeof(vl.type_instance)-len,
                        i ? "-%s" : "%s", db->state[i+1].name);
   }
   else
     sstrncpy (vl.type_instance, key->instance, sizeof (vl.type_instance));
 
-  sstrncpy (vl.host, host, sizeof (vl.host));
+  sstrncpy (vl.host, cj_host (db), sizeof (vl.host));
   sstrncpy (vl.plugin, "curl_json", sizeof (vl.plugin));
   sstrncpy (vl.plugin_instance, db->instance, sizeof (vl.plugin_instance));
   sstrncpy (vl.type, key->type, sizeof (vl.type));
@@ -870,7 +869,7 @@ static void cj_submit (cj_t *db, cj_key_t *key, value_t *value) /* {{{ */
 static int cj_sock_perform (cj_t *db) /* {{{ */
 {
   char errbuf[1024];
-  struct sockaddr_un sa_unix = {};
+  struct sockaddr_un sa_unix = { 0 };
   sa_unix.sun_family = AF_UNIX;
   sstrncpy (sa_unix.sun_path, db->sock, sizeof (sa_unix.sun_path));
 
@@ -919,6 +918,8 @@ static int cj_curl_perform(cj_t *db) /* {{{ */
            status, db->curl_errbuf, url);
     return (-1);
   }
+  if (db->stats != NULL)
+    curl_stats_dispatch (db->stats, db->curl, cj_host (db), "curl_json", db->instance);
 
   curl_easy_getinfo(db->curl, CURLINFO_EFFECTIVE_URL, &url);
   curl_easy_getinfo(db->curl, CURLINFO_RESPONSE_CODE, &rc);
@@ -964,9 +965,9 @@ static int cj_perform (cj_t *db) /* {{{ */
   }
 
 #if HAVE_YAJL_V2
-    status = yajl_complete_parse(db->yajl);
+  status = yajl_complete_parse(db->yajl);
 #else
-    status = yajl_parse_complete(db->yajl);
+  status = yajl_parse_complete(db->yajl);
 #endif
   if (status != yajl_status_ok)
   {
index c33ec1f..f3aa2d9 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
+#include "utils_curl_stats.h"
 #include "utils_llist.h"
 
 #include <libxml/parser.h>
@@ -50,7 +52,7 @@ struct cx_xpath_s /* {{{ */
   char *path;
   char *type;
   cx_values_t *values;
-  int values_len;
+  size_t values_len;
   char *instance_prefix;
   char *instance;
   int is_table;
@@ -83,6 +85,7 @@ struct cx_s /* {{{ */
   char *post_body;
   int timeout;
   struct curl_slist *headers;
+  curl_stats_t *stats;
 
   cx_namespace_t *namespaces;
   size_t namespaces_num;
@@ -114,14 +117,14 @@ static size_t cx_curl_callback (void *buf, /* {{{ */
     return (0);
   }
 
-   if (len <= 0)
+  if (len == 0)
     return (len);
 
   if ((db->buffer_fill + len) >= db->buffer_size)
   {
     char *temp;
 
-    temp = (char *) realloc (db->buffer,
+    temp = realloc (db->buffer,
                     db->buffer_fill + len + 1);
     if (temp == NULL)
     {
@@ -170,13 +173,11 @@ static void cx_list_free (llist_t *list) /* {{{ */
   }
 
   llist_destroy (list);
-  list = NULL;
 } /* }}} void cx_list_free */
 
 static void cx_free (void *arg) /* {{{ */
 {
   cx_t *db;
-  size_t i;
 
   DEBUG ("curl_xml plugin: cx_free (arg = %p);", arg);
 
@@ -203,8 +204,9 @@ static void cx_free (void *arg) /* {{{ */
   sfree (db->cacert);
   sfree (db->post_body);
   curl_slist_free_all (db->headers);
+  curl_stats_destroy (db->stats);
 
-  for (i = 0; i < db->namespaces_num; i++)
+  for (size_t i = 0; i < db->namespaces_num; i++)
   {
     sfree (db->namespaces[i].prefix);
     sfree (db->namespaces[i].url);
@@ -214,6 +216,13 @@ static void cx_free (void *arg) /* {{{ */
   sfree (db);
 } /* }}} void cx_free */
 
+static const char *cx_host (cx_t *db) /* {{{ */
+{
+  if (db->host == NULL)
+    return hostname_g;
+  return db->host;
+} /* }}} cx_host */
+
 static int cx_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
     oconfig_item_t *ci)
 {
@@ -243,7 +252,7 @@ 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 %i values, but config talks about %i",
+    WARNING ("curl_xml plugin: DataSet `%s' requires %zu values, but config talks about %zu",
         xpath->type, ds->ds_num, xpath->values_len);
     return (-1);
   }
@@ -251,7 +260,7 @@ static int cx_check_type (const data_set_t *ds, cx_xpath_t *xpath) /* {{{ */
   return (0);
 } /* }}} cx_check_type */
 
-static xmlXPathObjectPtr cx_evaluate_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */ 
+static xmlXPathObjectPtr cx_evaluate_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */
            xmlChar *expr)
 {
   xmlXPathObjectPtr xpath_obj;
@@ -318,7 +327,7 @@ static int cx_handle_single_value_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */
   {
     WARNING ("curl_xml plugin: "
         "relative xpath expression \"%s\" is expected to return "
-        "only text/attribute node which is not the case. Skipping...", 
+        "only text/attribute node which is not the case. Skipping...",
         xpath->values[index].path);
     xmlXPathFreeObject (values_node_obj);
     return (-1);
@@ -339,7 +348,7 @@ static int cx_handle_single_value_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */
       vl->values[index].absolute = (absolute_t) strtoull (node_value,
           /* endptr = */ NULL, /* base = */ 0);
       break;
-    case DS_TYPE_GAUGE: 
+    case DS_TYPE_GAUGE:
       vl->values[index].gauge = (gauge_t) strtod (node_value,
           /* endptr = */ NULL);
   }
@@ -359,14 +368,13 @@ static int cx_handle_all_value_xpaths (xmlXPathContextPtr xpath_ctx, /* {{{ */
 {
   value_t values[xpath->values_len];
   int status;
-  int i;
 
   assert (xpath->values_len > 0);
   assert (xpath->values_len == vl->values_len);
   assert (xpath->values_len == ds->ds_num);
   vl->values = values;
 
-  for (i = 0; i < xpath->values_len; i++)
+  for (size_t i = 0; i < xpath->values_len; i++)
   {
     status = cx_handle_single_value_xpath (xpath_ctx, xpath, ds, vl, i);
     if (status != 0)
@@ -475,18 +483,17 @@ static int cx_handle_instance_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */
 
 static int  cx_handle_base_xpath (char const *plugin_instance, /* {{{ */
     char const *host,
-    xmlXPathContextPtr xpath_ctx, const data_set_t *ds, 
+    xmlXPathContextPtr xpath_ctx, const data_set_t *ds,
     char *base_xpath, cx_xpath_t *xpath)
 {
   int total_nodes;
-  int i;
 
   xmlXPathObjectPtr base_node_obj = NULL;
   xmlNodeSetPtr base_nodes = NULL;
 
   value_list_t vl = VALUE_LIST_INIT;
 
-  base_node_obj = cx_evaluate_xpath (xpath_ctx, BAD_CAST base_xpath); 
+  base_node_obj = cx_evaluate_xpath (xpath_ctx, BAD_CAST base_xpath);
   if (base_node_obj == NULL)
     return -1; /* error is logged already */
 
@@ -503,7 +510,7 @@ static int  cx_handle_base_xpath (char const *plugin_instance, /* {{{ */
   }
 
   /* If base_xpath returned multiple results, then */
-  /* Instance in the xpath block is required */ 
+  /* Instance in the xpath block is required */
   if (total_nodes > 1 && xpath->instance == NULL)
   {
     ERROR ("curl_xml plugin: "
@@ -516,11 +523,11 @@ static int  cx_handle_base_xpath (char const *plugin_instance, /* {{{ */
   vl.values_len = ds->ds_num;
   sstrncpy (vl.type, xpath->type, sizeof (vl.type));
   sstrncpy (vl.plugin, "curl_xml", sizeof (vl.plugin));
-  sstrncpy (vl.host, (host != NULL) ? host : hostname_g, sizeof (vl.host));
+  sstrncpy (vl.host, host, sizeof (vl.host));
   if (plugin_instance != NULL)
-    sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); 
+    sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
 
-  for (i = 0; i < total_nodes; i++)
+  for (int i = 0; i < total_nodes; i++)
   {
     int status;
 
@@ -537,19 +544,19 @@ static int  cx_handle_base_xpath (char const *plugin_instance, /* {{{ */
   } /* for (i = 0; i < total_nodes; i++) */
 
   /* free up the allocated memory */
-  xmlXPathFreeObject (base_node_obj); 
+  xmlXPathFreeObject (base_node_obj);
 
-  return (0); 
+  return (0);
 } /* }}} cx_handle_base_xpath */
 
-static int cx_handle_parsed_xml(xmlDocPtr doc, /* {{{ */ 
+static int cx_handle_parsed_xml(xmlDocPtr doc, /* {{{ */
                        xmlXPathContextPtr xpath_ctx, cx_t *db)
 {
   llentry_t *le;
   const data_set_t *ds;
   cx_xpath_t *xpath;
   int status=-1;
-  
+
 
   le = llist_head (db->list);
   while (le != NULL)
@@ -559,7 +566,7 @@ static int cx_handle_parsed_xml(xmlDocPtr doc, /* {{{ */
     ds = plugin_get_ds (xpath->type);
 
     if ( (cx_check_type(ds, xpath) == 0) &&
-         (cx_handle_base_xpath(db->instance, db->host,
+         (cx_handle_base_xpath(db->instance, cx_host (db),
                                xpath_ctx, ds, le->key, xpath) == 0) )
       status = 0; /* we got atleast one success */
 
@@ -574,7 +581,6 @@ static int cx_parse_stats_xml(xmlChar* xml, cx_t *db) /* {{{ */
   int status;
   xmlDocPtr doc;
   xmlXPathContextPtr xpath_ctx;
-  size_t i;
 
   /* Load the XML */
   doc = xmlParseDoc(xml);
@@ -592,7 +598,7 @@ static int cx_parse_stats_xml(xmlChar* xml, cx_t *db) /* {{{ */
     return (-1);
   }
 
-  for (i = 0; i < db->namespaces_num; i++)
+  for (size_t i = 0; i < db->namespaces_num; i++)
   {
     cx_namespace_t const *ns = db->namespaces + i;
     status = xmlXPathRegisterNs (xpath_ctx,
@@ -623,7 +629,7 @@ static int cx_curl_perform (cx_t *db, CURL *curl) /* {{{ */
   char *url;
   url = db->url;
 
-  db->buffer_fill = 0; 
+  db->buffer_fill = 0;
   status = curl_easy_perform (curl);
   if (status != CURLE_OK)
   {
@@ -631,6 +637,8 @@ static int cx_curl_perform (cx_t *db, CURL *curl) /* {{{ */
            status, db->curl_errbuf, url);
     return (-1);
   }
+  if (db->stats != NULL)
+    curl_stats_dispatch (db->stats, db->curl, cx_host (db), "curl_xml", db->instance);
 
   curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
   curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rc);
@@ -671,15 +679,13 @@ static int cx_read (user_data_t *ud) /* {{{ */
 static int cx_config_add_values (const char *name, cx_xpath_t *xpath, /* {{{ */
                                       oconfig_item_t *ci)
 {
-  int i;
-
   if (ci->values_num < 1)
   {
     WARNING ("curl_xml plugin: `ValuesFrom' needs at least one argument.");
     return (-1);
   }
 
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
     if (ci->values[i].type != OCONFIG_TYPE_STRING)
     {
       WARNING ("curl_xml plugin: `ValuesFrom' needs only string argument.");
@@ -689,13 +695,13 @@ static int cx_config_add_values (const char *name, cx_xpath_t *xpath, /* {{{ */
   sfree (xpath->values);
 
   xpath->values_len = 0;
-  xpath->values = (cx_values_t *) malloc (sizeof (cx_values_t) * ci->values_num);
+  xpath->values = malloc (sizeof (cx_values_t) * ci->values_num);
   if (xpath->values == NULL)
     return (-1);
-  xpath->values_len = ci->values_num;
+  xpath->values_len = (size_t) ci->values_num;
 
   /* populate cx_values_t structure */
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
   {
     xpath->values[i].path_len = sizeof (ci->values[i].value.string);
     sstrncpy (xpath->values[i].path, ci->values[i].value.string, sizeof (xpath->values[i].path));
@@ -710,15 +716,13 @@ static int cx_config_add_xpath (cx_t *db, oconfig_item_t *ci) /* {{{ */
   char *name;
   llentry_t *le;
   int status;
-  int i;
 
-  xpath = malloc (sizeof (*xpath));
+  xpath = calloc (1, sizeof (*xpath));
   if (xpath == NULL)
   {
-    ERROR ("curl_xml plugin: malloc failed.");
+    ERROR ("curl_xml plugin: calloc failed.");
     return (-1);
   }
-  memset (xpath, 0, sizeof (*xpath));
 
   status = cf_util_get_string (ci, &xpath->path);
   if (status != 0)
@@ -737,7 +741,7 @@ static int cx_config_add_xpath (cx_t *db, oconfig_item_t *ci) /* {{{ */
   }
 
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -876,7 +880,7 @@ static int cx_init_curl (cx_t *db) /* {{{ */
     if (db->pass != NULL)
       credentials_size += strlen (db->pass);
 
-    db->credentials = (char *) malloc (credentials_size);
+    db->credentials = malloc (credentials_size);
     if (db->credentials == NULL)
     {
       ERROR ("curl_xml plugin: malloc failed.");
@@ -906,8 +910,7 @@ static int cx_init_curl (cx_t *db) /* {{{ */
   if (db->timeout >= 0)
     curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) db->timeout);
   else
-    curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
-       CDTIME_T_TO_MS(plugin_get_interval()));
+    curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
 #endif
 
   return (0);
@@ -917,7 +920,6 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */
 {
   cx_t *db;
   int status = 0;
-  int i;
 
   if ((ci->values_num != 1)
       || (ci->values[0].type != OCONFIG_TYPE_STRING))
@@ -927,13 +929,12 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  db = (cx_t *) malloc (sizeof (*db));
+  db = calloc (1, sizeof (*db));
   if (db == NULL)
   {
-    ERROR ("curl_xml plugin: malloc failed.");
+    ERROR ("curl_xml plugin: calloc failed.");
     return (-1);
   }
-  memset (db, 0, sizeof (*db));
 
   db->timeout = -1;
 
@@ -955,7 +956,7 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */
   }
 
   /* Fill the `cx_t' structure.. */
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -985,6 +986,12 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */
       status = cx_config_add_namespace (db, child);
     else if (strcasecmp ("Timeout", child->key) == 0)
       status = cf_util_get_int (child, &db->timeout);
+    else if (strcasecmp ("Statistics", child->key) == 0)
+    {
+      db->stats = curl_stats_from_config (child);
+      if (db->stats == NULL)
+        status = -1;
+    }
     else
     {
       WARNING ("curl_xml plugin: Option `%s' not allowed here.", child->key);
@@ -1010,7 +1017,7 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */
   /* If all went well, register this database for reading */
   if (status == 0)
   {
-    user_data_t ud;
+    user_data_t ud = { 0 };
     char *cb_name;
 
     if (db->instance == NULL)
@@ -1019,13 +1026,12 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */
     DEBUG ("curl_xml plugin: Registering new read callback: %s",
            db->instance);
 
-    memset (&ud, 0, sizeof (ud));
     ud.data = (void *) db;
     ud.free_func = cx_free;
 
     cb_name = ssnprintf_alloc ("curl_xml-%s-%s", db->instance, db->url);
     plugin_register_complex_read (/* group = */ "curl_xml", cb_name, cx_read,
-                                  /* interval = */ NULL, &ud);
+                                  /* interval = */ 0, &ud);
     sfree (cb_name);
   }
   else
@@ -1044,12 +1050,11 @@ static int cx_config (oconfig_item_t *ci) /* {{{ */
   int success;
   int errors;
   int status;
-  int i;
 
   success = 0;
   errors = 0;
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
index 88fc712..632872a 100644 (file)
@@ -1,7 +1,3 @@
-if COMPILER_IS_GCC
-AM_CFLAGS = -Wall -Werror
-endif
-
 AM_CPPFLAGS = -I$(top_srcdir)/src
 AM_CPPFLAGS += -DPREFIX='"${prefix}"'
 AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
@@ -14,7 +10,7 @@ AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"'
 AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
 
 # Link to these libraries..
-COMMON_LIBS =
+COMMON_LIBS = $(PTHREAD_LIBS)
 if BUILD_WITH_LIBRT
 COMMON_LIBS += -lrt
 endif
@@ -27,9 +23,6 @@ endif
 if BUILD_WITH_LIBRESOLV
 COMMON_LIBS += -lresolv
 endif
-if BUILD_WITH_LIBPTHREAD
-COMMON_LIBS += -lpthread
-endif
 if BUILD_WITH_LIBKSTAT
 COMMON_LIBS += -lkstat
 endif
@@ -37,11 +30,9 @@ if BUILD_WITH_LIBDEVINFO
 COMMON_LIBS += -ldevinfo
 endif
 
-AUTOMAKE_OPTIONS = subdir-objects
-
 sbin_PROGRAMS = collectd
 
-noinst_LTLIBRARIES = libavltree.la libcommon.la libheap.la libplugin_mock.la
+noinst_LTLIBRARIES = libavltree.la libcommon.la libheap.la libmetadata.la libplugin_mock.la
 
 libavltree_la_SOURCES = utils_avltree.c utils_avltree.h
 
@@ -50,8 +41,12 @@ libcommon_la_LIBADD = $(COMMON_LIBS)
 
 libheap_la_SOURCES = utils_heap.c utils_heap.h
 
-libplugin_mock_la_SOURCES = plugin_mock.c utils_cache_mock.c utils_time_mock.c
-libplugin_mock_la_LIBADD = $(COMMON_LIBS)
+libmetadata_la_SOURCES = meta_data.c meta_data.h
+
+libplugin_mock_la_SOURCES = plugin_mock.c utils_cache_mock.c \
+                           utils_time.c utils_time.h
+libplugin_mock_la_CPPFLAGS = $(AM_CPPFLAGS) -DMOCK_TIME
+libplugin_mock_la_LIBADD = $(COMMON_LIBS) libcommon.la
 
 collectd_SOURCES = collectd.c collectd.h \
                   configfile.c configfile.h \
@@ -76,7 +71,7 @@ collectd_CPPFLAGS =  $(AM_CPPFLAGS) $(LTDLINCL)
 collectd_CFLAGS = $(AM_CFLAGS)
 collectd_LDFLAGS = -export-dynamic
 collectd_LDADD = libavltree.la libcommon.la libheap.la -lm $(COMMON_LIBS)
-collectd_DEPENDENCIES = libavltree.la libcommon.la libheap.la
+collectd_DEPENDENCIES = libavltree.la libcommon.la libheap.la libmetadata.la
 
 # The daemon needs to call sg_init, so we need to link it against libstatgrab,
 # too. -octo
@@ -92,14 +87,25 @@ else
 collectd_LDADD += -loconfig
 endif
 
-check_PROGRAMS = test_common test_utils_avltree test_utils_heap
-TESTS = test_common test_utils_avltree test_utils_heap
+LOG_COMPILER = env VALGRIND="@VALGRIND@" $(abs_top_srcdir)/testwrapper.sh
+
+check_PROGRAMS = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_time test_utils_subst
+TESTS          = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_time test_utils_subst
 
 test_common_SOURCES = common_test.c ../testing.h
-test_common_LDADD = libcommon.la libplugin_mock.la $(COMMON_LIBS)
+test_common_LDADD = libplugin_mock.la
+
+test_meta_data_SOURCES = meta_data_test.c ../testing.h
+test_meta_data_LDADD = libmetadata.la libplugin_mock.la
 
 test_utils_avltree_SOURCES = utils_avltree_test.c ../testing.h
 test_utils_avltree_LDADD = libavltree.la $(COMMON_LIBS)
 
 test_utils_heap_SOURCES = utils_heap_test.c ../testing.h
 test_utils_heap_LDADD = libheap.la $(COMMON_LIBS)
+
+test_utils_time_SOURCES = utils_time_test.c ../testing.h
+
+test_utils_subst_SOURCES = utils_subst_test.c ../testing.h \
+                          utils_subst.c utils_subst.h
+test_utils_subst_LDADD = libplugin_mock.la
index 6e625bb..8573579 100644 (file)
  **/
 
 #include "collectd.h"
-#include "common.h"
 
+#include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
 #include <sys/types.h>
-#include <sys/socket.h>
 #include <sys/un.h>
 #include <netdb.h>
 
-#include <pthread.h>
-
 #if HAVE_LOCALE_H
 # include <locale.h>
 #endif
@@ -55,7 +52,6 @@
  */
 char hostname_g[DATA_MAX_NAME_LEN];
 cdtime_t interval_g;
-int  pidfile_from_cli = 0;
 int  timeout_g;
 #if HAVE_LIBKSTAT
 kstat_ctl_t *kc;
@@ -101,9 +97,7 @@ static int init_hostname (void)
 {
        const char *str;
 
-       struct addrinfo  ai_hints;
        struct addrinfo *ai_list;
-       struct addrinfo *ai_ptr;
        int status;
 
        str = global_option_get ("Hostname");
@@ -124,8 +118,9 @@ static int init_hostname (void)
        if (IS_FALSE (str))
                return (0);
 
-       memset (&ai_hints, '\0', sizeof (ai_hints));
-       ai_hints.ai_flags = AI_CANONNAME;
+       struct addrinfo ai_hints = {
+               .ai_flags = AI_CANONNAME
+       };
 
        status = getaddrinfo (hostname_g, NULL, &ai_hints, &ai_list);
        if (status != 0)
@@ -138,7 +133,7 @@ static int init_hostname (void)
                return (-1);
        }
 
-       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
        {
                if (ai_ptr->ai_canonname == NULL)
                        continue;
@@ -197,7 +192,7 @@ static int change_basedir (const char *orig_dir)
        while ((dirlen > 0) && (dir[dirlen - 1] == '/'))
                dir[--dirlen] = '\0';
 
-       if (dirlen <= 0) {
+       if (dirlen == 0) {
                free (dir);
                return (-1);
        }
@@ -270,6 +265,7 @@ static void update_kstat (void)
 /* TODO
  * Remove all settings but `-f' and `-C'
  */
+__attribute__((noreturn))
 static void exit_usage (int status)
 {
        printf ("Usage: "PACKAGE_NAME" [OPTIONS]\n\n"
@@ -332,9 +328,7 @@ static int do_init (void)
        }
 #endif
 
-       plugin_init_all ();
-
-       return (0);
+       return plugin_init_all ();
 } /* int do_init () */
 
 
@@ -388,8 +382,7 @@ static int do_loop (void)
 
 static int do_shutdown (void)
 {
-       plugin_shutdown_all ();
-       return (0);
+       return plugin_shutdown_all ();
 } /* int do_shutdown */
 
 #if COLLECT_DAEMON
@@ -425,15 +418,18 @@ static int pidfile_remove (void)
 #ifdef KERNEL_LINUX
 static int notify_upstart (void)
 {
-    const char  *upstart_job = getenv("UPSTART_JOB");
+    char const *upstart_job = getenv("UPSTART_JOB");
 
     if (upstart_job == NULL)
         return 0;
 
     if (strcmp(upstart_job, "collectd") != 0)
+    {
+        WARNING ("Environment specifies unexpected UPSTART_JOB=\"%s\", expected \"collectd\". Ignoring the variable.", upstart_job);
         return 0;
+    }
 
-    WARNING ("supervised by upstart, will stop to signal readyness");
+    NOTICE("Upstart detected, stopping now to signal readyness.");
     raise(SIGSTOP);
     unsetenv("UPSTART_JOB");
 
@@ -442,49 +438,68 @@ static int notify_upstart (void)
 
 static int notify_systemd (void)
 {
-    int                  fd = -1;
-    const char          *notifysocket = getenv("NOTIFY_SOCKET");
-    struct sockaddr_un   su;
-    struct iovec         iov;
-    struct msghdr        hdr;
+    int                  fd;
+    const char          *notifysocket;
+    struct sockaddr_un   su = { 0 };
+    size_t               su_size;
+    char                 buffer[] = "READY=1\n";
 
+    notifysocket = getenv ("NOTIFY_SOCKET");
     if (notifysocket == NULL)
         return 0;
 
-    if ((strchr("@/", notifysocket[0])) == NULL ||
-        strlen(notifysocket) < 2)
+    if ((strlen (notifysocket) < 2)
+        || ((notifysocket[0] != '@') && (notifysocket[0] != '/')))
+    {
+        ERROR ("invalid notification socket NOTIFY_SOCKET=\"%s\": path must be absolute", notifysocket);
         return 0;
+    }
+    NOTICE ("Systemd detected, trying to signal readyness.");
 
-    WARNING ("supervised by systemd, will signal readyness");
-    if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
-        WARNING ("cannot contact systemd socket %s", notifysocket);
+    unsetenv ("NOTIFY_SOCKET");
+
+#if defined(SOCK_CLOEXEC)
+    fd = socket (AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, /* protocol = */ 0);
+#else
+    fd = socket (AF_UNIX, SOCK_DGRAM, /* protocol = */ 0);
+#endif
+    if (fd < 0) {
+        char errbuf[1024];
+        ERROR ("creating UNIX socket failed: %s",
+                 sstrerror (errno, errbuf, sizeof (errbuf)));
         return 0;
     }
 
-    bzero(&su, sizeof(su));
     su.sun_family = AF_UNIX;
-    sstrncpy (su.sun_path, notifysocket, sizeof(su.sun_path));
-
-    if (notifysocket[0] == '@')
+    if (notifysocket[0] != '@')
+    {
+        /* regular UNIX socket */
+        sstrncpy (su.sun_path, notifysocket, sizeof (su.sun_path));
+        su_size = sizeof (su);
+    }
+    else
+    {
+        /* Linux abstract namespace socket: specify address as "\0foo", i.e.
+         * start with a null byte. Since null bytes have no special meaning in
+         * that case, we have to set su_size correctly to cover only the bytes
+         * that are part of the address. */
+        sstrncpy (su.sun_path, notifysocket, sizeof (su.sun_path));
         su.sun_path[0] = 0;
+        su_size = sizeof (sa_family_t) + strlen (notifysocket);
+        if (su_size > sizeof (su))
+            su_size = sizeof (su);
+    }
 
-    bzero(&iov, sizeof(iov));
-    iov.iov_base = "READY=1";
-    iov.iov_len = strlen("READY=1");
-
-    bzero(&hdr, sizeof(hdr));
-    hdr.msg_name = &su;
-    hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) +
-        strlen(notifysocket);
-    hdr.msg_iov = &iov;
-    hdr.msg_iovlen = 1;
-
-    unsetenv("NOTIFY_SOCKET");
-    if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) {
-        WARNING ("cannot send notification to systemd");
+    if (sendto (fd, buffer, strlen (buffer), MSG_NOSIGNAL, (void *) &su, (socklen_t) su_size) < 0)
+    {
+        char errbuf[1024];
+        ERROR ("sendto(\"%s\") failed: %s", notifysocket,
+                 sstrerror (errno, errbuf, sizeof (errbuf)));
         close(fd);
         return 0;
     }
+
+    unsetenv ("NOTIFY_SOCKET");
     close(fd);
     return 1;
 }
@@ -492,16 +507,11 @@ static int notify_systemd (void)
 
 int main (int argc, char **argv)
 {
-       struct sigaction sig_int_action;
-       struct sigaction sig_term_action;
-       struct sigaction sig_usr1_action;
-       struct sigaction sig_pipe_action;
-       char *configfile = CONFIGFILE;
+       const char *configfile = CONFIGFILE;
        int test_config  = 0;
        int test_readall = 0;
        const char *basedir;
 #if COLLECT_DAEMON
-       struct sigaction sig_chld_action;
        pid_t pid;
        int daemonize    = 1;
 #endif
@@ -531,15 +541,14 @@ int main (int argc, char **argv)
                                break;
                        case 'T':
                                test_readall = 1;
-                               global_option_set ("ReadThreads", "-1");
+                               global_option_set ("ReadThreads", "-1", 1);
 #if COLLECT_DAEMON
                                daemonize = 0;
 #endif /* COLLECT_DAEMON */
                                break;
 #if COLLECT_DAEMON
                        case 'P':
-                               global_option_set ("PIDFile", optarg);
-                               pidfile_from_cli = 1;
+                               global_option_set ("PIDFile", optarg, 1);
                                break;
                        case 'f':
                                daemonize = 0;
@@ -602,8 +611,10 @@ int main (int argc, char **argv)
        /*
         * fork off child
         */
-       memset (&sig_chld_action, '\0', sizeof (sig_chld_action));
-       sig_chld_action.sa_handler = SIG_IGN;
+       struct sigaction sig_chld_action = {
+               .sa_handler = SIG_IGN
+       };
+
        sigaction (SIGCHLD, &sig_chld_action, NULL);
 
     /*
@@ -616,6 +627,8 @@ int main (int argc, char **argv)
 #endif
        )
        {
+               int status;
+
                if ((pid = fork ()) == -1)
                {
                        /* error */
@@ -644,33 +657,42 @@ int main (int argc, char **argv)
                close (1);
                close (0);
 
-               if (open ("/dev/null", O_RDWR) != 0)
+               status = open ("/dev/null", O_RDWR);
+               if (status != 0)
                {
-                       ERROR ("Error: Could not connect `STDIN' to `/dev/null'");
+                       ERROR ("Error: Could not connect `STDIN' to `/dev/null' (status %d)", status);
                        return (1);
                }
-               if (dup (0) != 1)
+
+               status = dup (0);
+               if (status != 1)
                {
-                       ERROR ("Error: Could not connect `STDOUT' to `/dev/null'");
+                       ERROR ("Error: Could not connect `STDOUT' to `/dev/null' (status %d)", status);
                        return (1);
                }
-               if (dup (0) != 2)
+
+               status = dup (0);
+               if (status != 2)
                {
-                       ERROR ("Error: Could not connect `STDERR' to `/dev/null'");
+                       ERROR ("Error: Could not connect `STDERR' to `/dev/null', (status %d)", status);
                        return (1);
                }
        } /* if (daemonize) */
 #endif /* COLLECT_DAEMON */
 
-       memset (&sig_pipe_action, '\0', sizeof (sig_pipe_action));
-       sig_pipe_action.sa_handler = SIG_IGN;
+       struct sigaction sig_pipe_action = {
+               .sa_handler = SIG_IGN
+       };
+
        sigaction (SIGPIPE, &sig_pipe_action, NULL);
 
        /*
         * install signal handlers
         */
-       memset (&sig_int_action, '\0', sizeof (sig_int_action));
-       sig_int_action.sa_handler = sig_int_handler;
+       struct sigaction sig_int_action = {
+               .sa_handler = sig_int_handler
+       };
+
        if (0 != sigaction (SIGINT, &sig_int_action, NULL)) {
                char errbuf[1024];
                ERROR ("Error: Failed to install a signal handler for signal INT: %s",
@@ -678,8 +700,10 @@ int main (int argc, char **argv)
                return (1);
        }
 
-       memset (&sig_term_action, '\0', sizeof (sig_term_action));
-       sig_term_action.sa_handler = sig_term_handler;
+       struct sigaction sig_term_action = {
+               .sa_handler = sig_term_handler
+       };
+
        if (0 != sigaction (SIGTERM, &sig_term_action, NULL)) {
                char errbuf[1024];
                ERROR ("Error: Failed to install a signal handler for signal TERM: %s",
@@ -687,8 +711,10 @@ int main (int argc, char **argv)
                return (1);
        }
 
-       memset (&sig_usr1_action, '\0', sizeof (sig_usr1_action));
-       sig_usr1_action.sa_handler = sig_usr1_handler;
+       struct sigaction sig_usr1_action = {
+               .sa_handler = sig_usr1_handler
+       };
+
        if (0 != sigaction (SIGUSR1, &sig_usr1_action, NULL)) {
                char errbuf[1024];
                ERROR ("Error: Failed to install a signal handler for signal USR1: %s",
@@ -699,12 +725,19 @@ int main (int argc, char **argv)
        /*
         * run the actual loops
         */
-       do_init ();
+       if (do_init () != 0)
+       {
+               ERROR ("Error: one or more plugin init callbacks failed.");
+               exit_status = 1;
+       }
 
        if (test_readall)
        {
                if (plugin_read_all_once () != 0)
+               {
+                       ERROR ("Error: one or more plugin read callbacks failed.");
                        exit_status = 1;
+               }
        }
        else
        {
@@ -715,7 +748,11 @@ int main (int argc, char **argv)
        /* close syslog */
        INFO ("Exiting normally.");
 
-       do_shutdown ();
+       if (do_shutdown () != 0)
+       {
+               ERROR ("Error: one or more plugin shutdown callbacks failed.");
+               exit_status = 1;
+       }
 
 #if COLLECT_DAEMON
        if (daemonize)
index 80b753c..3cb0c1b 100644 (file)
@@ -95,6 +95,9 @@
 #  include <time.h>
 # endif
 #endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
 
 #if HAVE_ASSERT_H
 # include <assert.h>
@@ -224,39 +227,39 @@ typedef int _Bool;
 #endif
 
 #ifndef PACKAGE_NAME
-#define PACKAGE_NAME "collectd"
+# define PACKAGE_NAME "collectd"
 #endif
 
 #ifndef PREFIX
-#define PREFIX "/opt/" PACKAGE_NAME
+# define PREFIX "/opt/" PACKAGE_NAME
 #endif
 
 #ifndef SYSCONFDIR
-#define SYSCONFDIR PREFIX "/etc"
+# define SYSCONFDIR PREFIX "/etc"
 #endif
 
 #ifndef CONFIGFILE
-#define CONFIGFILE SYSCONFDIR"/collectd.conf"
+# define CONFIGFILE SYSCONFDIR"/collectd.conf"
 #endif
 
 #ifndef LOCALSTATEDIR
-#define LOCALSTATEDIR PREFIX "/var"
+# define LOCALSTATEDIR PREFIX "/var"
 #endif
 
 #ifndef PKGLOCALSTATEDIR
-#define PKGLOCALSTATEDIR PREFIX "/var/lib/" PACKAGE_NAME
+# define PKGLOCALSTATEDIR PREFIX "/var/lib/" PACKAGE_NAME
 #endif
 
 #ifndef PIDFILE
-#define PIDFILE PREFIX "/var/run/" PACKAGE_NAME ".pid"
+# define PIDFILE PREFIX "/var/run/" PACKAGE_NAME ".pid"
 #endif
 
 #ifndef PLUGINDIR
-#define PLUGINDIR PREFIX "/lib/" PACKAGE_NAME
+# define PLUGINDIR PREFIX "/lib/" PACKAGE_NAME
 #endif
 
 #ifndef PKGDATADIR
-#define PKGDATADIR PREFIX "/share/" PACKAGE_NAME
+# define PKGDATADIR PREFIX "/share/" PACKAGE_NAME
 #endif
 
 #ifndef COLLECTD_GRP_NAME
@@ -267,21 +270,15 @@ typedef int _Bool;
 # define COLLECTD_DEFAULT_INTERVAL 10.0
 #endif
 
- #ifndef COLLECTD_USERAGENT
- # define COLLECTD_USERAGENT PACKAGE_NAME"/"PACKAGE_VERSION
- #endif
+#ifndef COLLECTD_USERAGENT
+# define COLLECTD_USERAGENT PACKAGE_NAME "/" PACKAGE_VERSION
+#endif
 
 /* Only enable __attribute__() for compilers known to support it. */
-#if defined(__clang__)
-# define clang_attr(x) __attribute__(x)
-# define gcc_attr(x) /**/
-#elif __GNUC__
-# define clang_attr(x) /**/
-# define gcc_attr(x) __attribute__(x)
-#else
-# define clang_attr(x) /**/
-# define gcc_attr(x) /**/
-# define __attribute__(x) /**/
+#if !defined(__clang__) && !defined(__GNUC__)
+# if !defined(__attribute__)
+#  define __attribute__(x) /**/
+# endif
 #endif
 
 #if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__
@@ -291,7 +288,7 @@ typedef int _Bool;
 # pragma GCC poison strcpy strcat strtok
 #endif
 
-/* 
+/*
  * Special hack for the perl plugin: Because the later included perl.h defines
  * a macro which is never used, but contains `sprintf', we cannot poison that
  * identifies just yet. The parl plugin will do that itself once perl.h is
@@ -313,7 +310,6 @@ typedef uint64_t cdtime_t;
 
 extern char     hostname_g[];
 extern cdtime_t interval_g;
-extern int      pidfile_from_cli;
 extern int      timeout_g;
 
 #endif /* COLLECTD_H */
index fba51ef..05b1199 100644 (file)
 #endif
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_cache.h"
 
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-
 #ifdef HAVE_MATH_H
 # include <math.h>
 #endif
 
 /* for getaddrinfo */
 #include <sys/types.h>
-#include <sys/socket.h>
 #include <netdb.h>
 
 #include <poll.h>
 # include <netinet/in.h>
 #endif
 
+#if HAVE_NETINET_TCP_H
+# include <netinet/tcp.h>
+#endif
+
 /* for ntohl and htonl */
 #if HAVE_ARPA_INET_H
 # include <arpa/inet.h>
 #endif
 
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
+
 #ifdef HAVE_LIBKSTAT
 extern kstat_ctl_t *kc;
 #endif
@@ -116,10 +120,9 @@ char *ssnprintf_alloc (char const *format, ...) /* {{{ */
                return (strdup (static_buffer));
 
        /* Allocate a buffer large enough to hold the string. */
-       alloc_buffer = malloc (alloc_buffer_size);
+       alloc_buffer = calloc (1, alloc_buffer_size);
        if (alloc_buffer == NULL)
                return (NULL);
-       memset (alloc_buffer, 0, alloc_buffer_size);
 
        /* Print again into this new buffer. */
        va_start (ap, format);
@@ -145,7 +148,7 @@ char *sstrdup (const char *s)
        /* Do not use `strdup' here, because it's not specified in POSIX. It's
         * ``only'' an XSI extension. */
        sz = strlen (s) + 1;
-       r = (char *) malloc (sizeof (char) * sz);
+       r = malloc (sz);
        if (r == NULL)
        {
                ERROR ("sstrdup: Out of memory.");
@@ -259,8 +262,8 @@ ssize_t sread (int fd, void *buf, size_t count)
 
                assert ((0 > status) || (nleft >= (size_t)status));
 
-               nleft = nleft - status;
-               ptr   = ptr   + status;
+               nleft = nleft - ((size_t) status);
+               ptr   = ptr   + ((size_t) status);
        }
 
        return (0);
@@ -277,6 +280,9 @@ ssize_t swrite (int fd, const void *buf, size_t count)
        ptr   = (const char *) buf;
        nleft = count;
        
+       if (fd < 0)
+               return (-1);
+
        /* checking for closed peer connection */
        pfd.fd = fd;
        pfd.events = POLLIN | POLLHUP;
@@ -300,8 +306,8 @@ ssize_t swrite (int fd, const void *buf, size_t count)
                if (status < 0)
                        return (status);
 
-               nleft = nleft - status;
-               ptr   = ptr   + status;
+               nleft = nleft - ((size_t) status);
+               ptr   = ptr   + ((size_t) status);
        }
 
        return (0);
@@ -335,9 +341,8 @@ int strjoin (char *buffer, size_t buffer_size,
        size_t avail;
        char *ptr;
        size_t sep_len;
-       size_t i;
 
-       if ((buffer_size < 1) || (fields_num <= 0))
+       if ((buffer_size < 1) || (fields_num == 0))
                return (-1);
 
        memset (buffer, 0, buffer_size);
@@ -348,7 +353,7 @@ int strjoin (char *buffer, size_t buffer_size,
        if (sep != NULL)
                sep_len = strlen (sep);
 
-       for (i = 0; i < fields_num; i++)
+       for (size_t i = 0; i < fields_num; i++)
        {
                size_t field_len;
 
@@ -372,34 +377,12 @@ int strjoin (char *buffer, size_t buffer_size,
        }
 
        assert (buffer[buffer_size - 1] == 0);
-       return (strlen (buffer));
+       return ((int) strlen (buffer));
 }
 
-int strsubstitute (char *str, char c_from, char c_to)
-{
-       int ret;
-
-       if (str == NULL)
-               return (-1);
-
-       ret = 0;
-       while (*str != '\0')
-       {
-               if (*str == c_from)
-               {
-                       *str = c_to;
-                       ret++;
-               }
-               str++;
-       }
-
-       return (ret);
-} /* int strsubstitute */
-
 int escape_string (char *buffer, size_t buffer_size)
 {
   char *temp;
-  size_t i;
   size_t j;
 
   /* Check if we need to escape at all first */
@@ -410,15 +393,14 @@ int escape_string (char *buffer, size_t buffer_size)
   if (buffer_size < 3)
     return (EINVAL);
 
-  temp = (char *) malloc (buffer_size);
+  temp = calloc (1, buffer_size);
   if (temp == NULL)
     return (ENOMEM);
-  memset (temp, 0, buffer_size);
 
   temp[0] = '"';
   j = 1;
 
-  for (i = 0; i < buffer_size; i++)
+  for (size_t i = 0; i < buffer_size; i++)
   {
     if (buffer[i] == 0)
     {
@@ -452,9 +434,7 @@ int escape_string (char *buffer, size_t buffer_size)
 
 int strunescape (char *buf, size_t buf_len)
 {
-       size_t i;
-
-       for (i = 0; (i < buf_len) && (buf[i] != '\0'); ++i)
+       for (size_t i = 0; (i < buf_len) && (buf[i] != '\0'); ++i)
        {
                if (buf[i] != '\\')
                        continue;
@@ -507,7 +487,6 @@ size_t strstripnewline (char *buffer)
 
 int escape_slashes (char *buffer, size_t buffer_size)
 {
-       int i;
        size_t buffer_len;
 
        buffer_len = strlen (buffer);
@@ -530,7 +509,7 @@ int escape_slashes (char *buffer, size_t buffer_size)
                buffer_len--;
        }
 
-       for (i = 0; i < buffer_len; i++)
+       for (size_t i = 0; i < buffer_len; i++)
        {
                if (buffer[i] == '/')
                        buffer[i] = '_';
@@ -541,9 +520,7 @@ int escape_slashes (char *buffer, size_t buffer_size)
 
 void replace_special (char *buffer, size_t buffer_size)
 {
-       size_t i;
-
-       for (i = 0; i < buffer_size; i++)
+       for (size_t i = 0; i < buffer_size; i++)
        {
                if (buffer[i] == 0)
                        return;
@@ -617,7 +594,6 @@ int check_create_dir (const char *file_orig)
        int   last_is_file = 1;
        int   path_is_absolute = 0;
        size_t len;
-       int   i;
 
        /*
         * Sanity checks first
@@ -663,7 +639,7 @@ int check_create_dir (const char *file_orig)
        /*
         * For each component, do..
         */
-       for (i = 0; i < (fields_num - last_is_file); i++)
+       for (int i = 0; i < (fields_num - last_is_file); i++)
        {
                /*
                 * Do not create directories that start with a dot. This
@@ -681,8 +657,8 @@ int check_create_dir (const char *file_orig)
                 * Join the components together again
                 */
                dir[0] = '/';
-               if (strjoin (dir + path_is_absolute, dir_len - path_is_absolute,
-                                       fields, i + 1, "/") < 0)
+               if (strjoin (dir + path_is_absolute, (size_t) (dir_len - path_is_absolute),
+                                       fields, (size_t) (i + 1), "/") < 0)
                {
                        ERROR ("strjoin failed: `%s', component #%i", file_orig, i);
                        return (-1);
@@ -962,7 +938,6 @@ int format_values (char *ret, size_t ret_len, /* {{{ */
 {
         size_t offset = 0;
         int status;
-        int i;
         gauge_t *rates = NULL;
 
         assert (0 == strcmp (ds->type, vl->type));
@@ -988,7 +963,7 @@ int format_values (char *ret, size_t ret_len, /* {{{ */
 
         BUFFER_ADD ("%.3f", CDTIME_T_TO_DOUBLE (vl->time));
 
-        for (i = 0; i < ds->ds_num; i++)
+        for (size_t i = 0; i < ds->ds_num; i++)
         {
                 if (ds->ds[i].type == DS_TYPE_GAUGE)
                         BUFFER_ADD (":"GAUGE_FORMAT, vl->values[i].gauge);
@@ -1165,7 +1140,7 @@ int parse_value (const char *value_orig, value_t *ret_value, int ds_type)
 
 int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
 {
-       int i;
+       size_t i;
        char *dummy;
        char *ptr;
        char *saveptr;
@@ -1173,9 +1148,10 @@ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
        if ((buffer == NULL) || (vl == NULL) || (ds == NULL))
                return EINVAL;
 
-       i = -1;
+       i = 0;
        dummy = buffer;
        saveptr = NULL;
+       vl->time = 0;
        while ((ptr = strtok_r (dummy, ":", &saveptr)) != NULL)
        {
                dummy = NULL;
@@ -1183,11 +1159,11 @@ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
                if (i >= vl->values_len)
                {
                        /* Make sure i is invalid. */
-                       i = vl->values_len + 1;
+                       i = 0;
                        break;
                }
 
-               if (i == -1)
+               if (vl->time == 0)
                {
                        if (strcmp ("N", ptr) == 0)
                                vl->time = cdtime ();
@@ -1206,19 +1182,19 @@ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
 
                                vl->time = DOUBLE_TO_CDTIME_T (tmp);
                        }
+
+                       continue;
                }
-               else
-               {
-                       if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
-                               vl->values[i].gauge = NAN;
-                       else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
-                               return -1;
-               }
+
+               if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
+                       vl->values[i].gauge = NAN;
+               else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
+                       return -1;
 
                i++;
        } /* while (strtok_r) */
 
-       if ((ptr != NULL) || (i != vl->values_len))
+       if ((ptr != NULL) || (i == 0))
                return (-1);
        return (0);
 } /* int parse_values */
@@ -1380,10 +1356,9 @@ counter_t counter_diff (counter_t old_value, counter_t new_value)
        if (old_value > new_value)
        {
                if (old_value <= 4294967295U)
-                       diff = (4294967295U - old_value) + new_value;
+                       diff = (4294967295U - old_value) + new_value + 1;
                else
-                       diff = (18446744073709551615ULL - old_value)
-                               + new_value;
+                       diff = (18446744073709551615ULL - old_value) + new_value + 1;
        }
        else
        {
@@ -1488,11 +1463,10 @@ int rate_to_value (value_t *ret_value, gauge_t rate, /* {{{ */
        return (0);
 } /* }}} value_t rate_to_value */
 
-int value_to_rate (value_t *ret_rate, derive_t value, /* {{{ */
-               value_to_rate_state_t *state,
-               int ds_type, cdtime_t t)
+int value_to_rate (gauge_t *ret_rate, /* {{{ */
+               value_t value, int ds_type, cdtime_t t, value_to_rate_state_t *state)
 {
-       double interval;
+       gauge_t interval;
 
        /* Another invalid state: The time is not increasing. */
        if (t <= state->last_time)
@@ -1504,67 +1478,54 @@ int value_to_rate (value_t *ret_rate, derive_t value, /* {{{ */
        interval = CDTIME_T_TO_DOUBLE(t - state->last_time);
 
        /* Previous value is invalid. */
-       if (state->last_time == 0) /* {{{ */
+       if (state->last_time == 0)
        {
-               if (ds_type == DS_TYPE_DERIVE)
-               {
-                       state->last_value.derive = value;
-               }
-               else if (ds_type == DS_TYPE_COUNTER)
-               {
-                       state->last_value.counter = (counter_t) value;
-               }
-               else if (ds_type == DS_TYPE_ABSOLUTE)
-               {
-                       state->last_value.absolute = (absolute_t) value;
-               }
-               else
-               {
-                       assert (23 == 42);
-               }
-
+               state->last_value = value;
                state->last_time = t;
                return (EAGAIN);
-       } /* }}} */
+       }
 
-       if (ds_type == DS_TYPE_DERIVE)
-       {
-               ret_rate->gauge = (value - state->last_value.derive) / interval;
-               state->last_value.derive = value;
+       switch (ds_type) {
+       case DS_TYPE_DERIVE: {
+               derive_t diff = value.derive - state->last_value.derive;
+               *ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
+               break;
        }
-       else if (ds_type == DS_TYPE_COUNTER)
-       {
-               ret_rate->gauge = (((counter_t)value) - state->last_value.counter) / interval;
-               state->last_value.counter = (counter_t) value;
+       case DS_TYPE_GAUGE: {
+               *ret_rate = value.gauge;
+               break;
        }
-       else if (ds_type == DS_TYPE_ABSOLUTE)
-       {
-               ret_rate->gauge = (((absolute_t)value) - state->last_value.absolute) / interval;
-               state->last_value.absolute = (absolute_t) value;
+       case DS_TYPE_COUNTER: {
+               counter_t diff = counter_diff (state->last_value.counter, value.counter);
+               *ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
+               break;
        }
-       else
-       {
-               assert (23 == 42);
+       case DS_TYPE_ABSOLUTE: {
+               absolute_t diff = value.absolute;
+               *ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
+               break;
+       }
+       default:
+               return EINVAL;
        }
 
-        state->last_time = t;
+       state->last_value = value;
+       state->last_time = t;
        return (0);
 } /* }}} value_t rate_to_value */
 
 int service_name_to_port_number (const char *service_name)
 {
        struct addrinfo *ai_list;
-       struct addrinfo *ai_ptr;
-       struct addrinfo ai_hints;
        int status;
        int service_number;
 
        if (service_name == NULL)
                return (-1);
 
-       ai_list = NULL;
-       memset (&ai_hints, 0, sizeof (ai_hints));
-       ai_hints.ai_family = AF_UNSPEC;
+       struct addrinfo ai_hints = {
+               .ai_family = AF_UNSPEC
+       };
 
        status = getaddrinfo (/* node = */ NULL, service_name,
                        &ai_hints, &ai_list);
@@ -1576,7 +1537,7 @@ int service_name_to_port_number (const char *service_name)
        }
 
        service_number = -1;
-       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
        {
                if (ai_ptr->ai_family == AF_INET)
                {
@@ -1604,6 +1565,46 @@ int service_name_to_port_number (const char *service_name)
        return (-1);
 } /* int service_name_to_port_number */
 
+void set_sock_opts (int sockfd) /* {{{ */
+{
+       int status;
+       int socktype;
+
+       socklen_t socklen = sizeof (socklen_t);
+       int so_keepalive = 1;
+
+       status = getsockopt (sockfd, SOL_SOCKET, SO_TYPE, &socktype, &socklen);
+       if (status != 0)
+       {
+               WARNING ("set_sock_opts: failed to determine socket type");
+               return;
+       }
+
+       if (socktype == SOCK_STREAM)
+       {
+               status = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
+                               &so_keepalive, sizeof (so_keepalive));
+               if (status != 0)
+                       WARNING ("set_sock_opts: failed to set socket keepalive flag");
+
+#ifdef TCP_KEEPIDLE
+               int tcp_keepidle = ((CDTIME_T_TO_MS(plugin_get_interval()) - 1) / 100 + 1);
+               status = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
+                               &tcp_keepidle, sizeof (tcp_keepidle));
+               if (status != 0)
+                       WARNING ("set_sock_opts: failed to set socket tcp keepalive time");
+#endif
+
+#ifdef TCP_KEEPINTVL
+               int tcp_keepintvl = ((CDTIME_T_TO_MS(plugin_get_interval()) - 1) / 1000 + 1);
+               status = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
+                               &tcp_keepintvl, sizeof (tcp_keepintvl));
+               if (status != 0)
+                       WARNING ("set_sock_opts: failed to set socket tcp keepalive interval");
+#endif
+       }
+} /* }}} void set_sock_opts */
+
 int strtoderive (const char *string, derive_t *ret_value) /* {{{ */
 {
        derive_t tmp;
@@ -1667,9 +1668,56 @@ int strarray_add (char ***ret_array, size_t *ret_array_len, char const *str) /*
 
 void strarray_free (char **array, size_t array_len) /* {{{ */
 {
-       size_t i;
-
-       for (i = 0; i < array_len; i++)
+       for (size_t i = 0; i < array_len; i++)
                sfree (array[i]);
        sfree (array);
 } /* }}} void strarray_free */
+
+#ifdef HAVE_SYS_CAPABILITY_H
+int check_capability (int capability) /* {{{ */
+{
+#ifdef _LINUX_CAPABILITY_VERSION_3
+       cap_user_header_t cap_header = calloc(1, sizeof (*cap_header));
+       if (cap_header == NULL)
+       {
+               ERROR("check_capability: calloc failed");
+               return (-1);
+       }
+
+       cap_user_data_t cap_data = calloc(1, sizeof (*cap_data));
+       if (cap_data == NULL)
+       {
+               ERROR("check_capability: calloc failed");
+               sfree(cap_header);
+               return (-1);
+       }
+
+       cap_header->pid = getpid();
+       cap_header->version = _LINUX_CAPABILITY_VERSION;
+       if (capget(cap_header, cap_data) < 0)
+       {
+               ERROR("check_capability: capget failed");
+               sfree(cap_header);
+               sfree(cap_data);
+               return (-1);
+       }
+
+       if ((cap_data->effective & (1 << capability)) == 0)
+       {
+               sfree(cap_header);
+               sfree(cap_data);
+               return (-1);
+       }
+       else
+       {
+               sfree(cap_header);
+               sfree(cap_data);
+               return (0);
+       }
+#else
+       WARNING ("check_capability: unsupported capability implementation. "
+           "Some plugin(s) may require elevated privileges to work properly.");
+       return (0);
+#endif /* _LINUX_CAPABILITY_VERSION_3 */
+} /* }}} int check_capability */
+#endif /* HAVE_SYS_CAPABILITY_H */
index da21cad..720e5f1 100644 (file)
@@ -29,6 +29,7 @@
 #define COMMON_H
 
 #include "collectd.h"
+
 #include "plugin.h"
 
 #if HAVE_PWD_H
@@ -37,9 +38,7 @@
 
 #define sfree(ptr) \
        do { \
-               if((ptr) != NULL) { \
-                       free(ptr); \
-               } \
+               free(ptr); \
                (ptr) = NULL; \
        } while (0)
 
@@ -224,8 +223,6 @@ int escape_string (char *buffer, size_t buffer_size);
  */
 void replace_special (char *buffer, size_t buffer_size);
 
-int strsubstitute (char *str, char c_from, char c_to);
-
 /*
  * NAME
  *   strunescape
@@ -357,13 +354,16 @@ counter_t counter_diff (counter_t old_value, counter_t new_value);
 int rate_to_value (value_t *ret_value, gauge_t rate,
                rate_to_value_state_t *state, int ds_type, cdtime_t t);
 
-int value_to_rate (value_t *ret_rate, derive_t value,
-               value_to_rate_state_t *state, int ds_type, cdtime_t t);
+int value_to_rate (gauge_t *ret_rate, value_t value, int ds_type, cdtime_t t,
+               value_to_rate_state_t *state);
 
 /* Converts a service name (a string) to a port number
  * (in the range [1-65535]). Returns less than zero on error. */
 int service_name_to_port_number (const char *service_name);
 
+/* Sets various, non-default, socket options */
+void set_sock_opts (int sockfd);
+
 /** Parse a string to a derive_t value. Returns zero on success or non-zero on
  * failure. If failure is returned, ret_value is not touched. */
 int strtoderive (const char *string, derive_t *ret_value);
@@ -375,4 +375,12 @@ int strtogauge (const char *string, gauge_t *ret_value);
 int strarray_add (char ***ret_array, size_t *ret_array_len, char const *str);
 void strarray_free (char **array, size_t array_len);
 
+#ifdef HAVE_SYS_CAPABILITY_H
+/** Check if the current process benefits from the capability passed in
+ * argument. Returns zero if it does, less than zero if it doesn't or on error.
+ * See capabilities(7) for the list of possible capabilities.
+ * */
+int check_capability (int capability);
+#endif /* HAVE_SYS_CAPABILITY_H */
+
 #endif /* COMMON_H */
index 39ea577..202ddf6 100644 (file)
@@ -24,8 +24,8 @@
  *   Florian octo Forster <octo at collectd.org>
  */
 
-#include "testing.h"
 #include "common.h"
+#include "testing.h"
 
 #if HAVE_LIBKSTAT
 kstat_ctl_t *kc;
@@ -42,18 +42,18 @@ DEF_TEST(sstrncpy)
 
   ret = sstrncpy (ptr, "foobar", 8);
   OK(ret == ptr);
-  STREQ ("foobar", ptr);
+  EXPECT_EQ_STR ("foobar", ptr);
   OK(buffer[3] == buffer[12]);
 
   ret = sstrncpy (ptr, "abc", 8);
   OK(ret == ptr);
-  STREQ ("abc", ptr);
+  EXPECT_EQ_STR ("abc", ptr);
   OK(buffer[3] == buffer[12]);
 
   ret = sstrncpy (ptr, "collectd", 8);
   OK(ret == ptr);
   OK(ptr[7] == 0);
-  STREQ ("collect", ptr);
+  EXPECT_EQ_STR ("collect", ptr);
   OK(buffer[3] == buffer[12]);
 
   return (0);
@@ -70,12 +70,12 @@ DEF_TEST(ssnprintf)
 
   status = ssnprintf (ptr, 8, "%i", 1337);
   OK(status == 4);
-  STREQ ("1337", ptr);
+  EXPECT_EQ_STR ("1337", ptr);
 
   status = ssnprintf (ptr, 8, "%s", "collectd");
   OK(status == 8);
   OK(ptr[7] == 0);
-  STREQ ("collect", ptr);
+  EXPECT_EQ_STR ("collect", ptr);
   OK(buffer[3] == buffer[12]);
 
   return (0);
@@ -87,10 +87,9 @@ DEF_TEST(sstrdup)
 
   ptr = sstrdup ("collectd");
   OK(ptr != NULL);
-  STREQ ("collectd", ptr);
+  EXPECT_EQ_STR ("collectd", ptr);
 
   sfree(ptr);
-  OK(ptr == NULL);
 
   ptr = sstrdup (NULL);
   OK(ptr == NULL);
@@ -107,40 +106,40 @@ DEF_TEST(strsplit)
   strncpy (buffer, "foo bar", sizeof (buffer));
   status = strsplit (buffer, fields, 8);
   OK(status == 2);
-  STREQ ("foo", fields[0]);
-  STREQ ("bar", fields[1]);
+  EXPECT_EQ_STR ("foo", fields[0]);
+  EXPECT_EQ_STR ("bar", fields[1]);
 
   strncpy (buffer, "foo \t bar", sizeof (buffer));
   status = strsplit (buffer, fields, 8);
   OK(status == 2);
-  STREQ ("foo", fields[0]);
-  STREQ ("bar", fields[1]);
+  EXPECT_EQ_STR ("foo", fields[0]);
+  EXPECT_EQ_STR ("bar", fields[1]);
 
   strncpy (buffer, "one two\tthree\rfour\nfive", sizeof (buffer));
   status = strsplit (buffer, fields, 8);
   OK(status == 5);
-  STREQ ("one", fields[0]);
-  STREQ ("two", fields[1]);
-  STREQ ("three", fields[2]);
-  STREQ ("four", fields[3]);
-  STREQ ("five", fields[4]);
+  EXPECT_EQ_STR ("one", fields[0]);
+  EXPECT_EQ_STR ("two", fields[1]);
+  EXPECT_EQ_STR ("three", fields[2]);
+  EXPECT_EQ_STR ("four", fields[3]);
+  EXPECT_EQ_STR ("five", fields[4]);
 
   strncpy (buffer, "\twith trailing\n", sizeof (buffer));
   status = strsplit (buffer, fields, 8);
   OK(status == 2);
-  STREQ ("with", fields[0]);
-  STREQ ("trailing", fields[1]);
+  EXPECT_EQ_STR ("with", fields[0]);
+  EXPECT_EQ_STR ("trailing", fields[1]);
 
   strncpy (buffer, "1 2 3 4 5 6 7 8 9 10 11 12 13", sizeof (buffer));
   status = strsplit (buffer, fields, 8);
   OK(status == 8);
-  STREQ ("7", fields[6]);
-  STREQ ("8", fields[7]);
+  EXPECT_EQ_STR ("7", fields[6]);
+  EXPECT_EQ_STR ("8", fields[7]);
 
   strncpy (buffer, "single", sizeof (buffer));
   status = strsplit (buffer, fields, 8);
   OK(status == 1);
-  STREQ ("single", fields[0]);
+  EXPECT_EQ_STR ("single", fields[0]);
 
   strncpy (buffer, "", sizeof (buffer));
   status = strsplit (buffer, fields, 8);
@@ -162,26 +161,26 @@ DEF_TEST(strjoin)
 
   status = strjoin (buffer, sizeof (buffer), fields, 2, "!");
   OK(status == 7);
-  STREQ ("foo!bar", buffer);
+  EXPECT_EQ_STR ("foo!bar", buffer);
 
   status = strjoin (buffer, sizeof (buffer), fields, 1, "!");
   OK(status == 3);
-  STREQ ("foo", buffer);
+  EXPECT_EQ_STR ("foo", buffer);
 
   status = strjoin (buffer, sizeof (buffer), fields, 0, "!");
   OK(status < 0);
 
   status = strjoin (buffer, sizeof (buffer), fields, 2, "rcht");
   OK(status == 10);
-  STREQ ("foorchtbar", buffer);
+  EXPECT_EQ_STR ("foorchtbar", buffer);
 
   status = strjoin (buffer, sizeof (buffer), fields, 4, "");
   OK(status == 12);
-  STREQ ("foobarbazqux", buffer);
+  EXPECT_EQ_STR ("foobarbazqux", buffer);
 
   status = strjoin (buffer, sizeof (buffer), fields, 4, "!");
   OK(status == 15);
-  STREQ ("foo!bar!baz!qux", buffer);
+  EXPECT_EQ_STR ("foo!bar!baz!qux", buffer);
 
   fields[0] = "0123";
   fields[1] = "4567";
@@ -193,6 +192,55 @@ DEF_TEST(strjoin)
   return (0);
 }
 
+DEF_TEST(escape_slashes)
+{
+  struct {
+    char *str;
+    char *want;
+  } cases[] = {
+    {"foo/bar/baz", "foo_bar_baz"},
+    {"/like/a/path", "like_a_path"},
+    {"trailing/slash/", "trailing_slash_"},
+    {"foo//bar", "foo__bar"},
+  };
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+    char buffer[32];
+
+    strncpy (buffer, cases[i].str, sizeof (buffer));
+    OK(escape_slashes (buffer, sizeof (buffer)) == 0);
+    EXPECT_EQ_STR(cases[i].want, buffer);
+  }
+
+  return 0;
+}
+
+DEF_TEST(escape_string)
+{
+  struct {
+    char *str;
+    char *want;
+  } cases[] = {
+    {"foobar", "foobar"},
+    {"f00bar", "f00bar"},
+    {"foo bar", "\"foo bar\""},
+    {"foo \"bar\"", "\"foo \\\"bar\\\"\""},
+    {"012345678901234", "012345678901234"},
+    {"012345 78901234", "\"012345 789012\""},
+    {"012345 78901\"34", "\"012345 78901\""},
+  };
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+    char buffer[16];
+
+    strncpy (buffer, cases[i].str, sizeof (buffer));
+    OK(escape_string (buffer, sizeof (buffer)) == 0);
+    EXPECT_EQ_STR(cases[i].want, buffer);
+  }
+
+  return 0;
+}
+
 DEF_TEST(strunescape)
 {
   char buffer[16];
@@ -201,23 +249,23 @@ DEF_TEST(strunescape)
   strncpy (buffer, "foo\\tbar", sizeof (buffer));
   status = strunescape (buffer, sizeof (buffer));
   OK(status == 0);
-  STREQ ("foo\tbar", buffer);
+  EXPECT_EQ_STR ("foo\tbar", buffer);
 
   strncpy (buffer, "\\tfoo\\r\\n", sizeof (buffer));
   status = strunescape (buffer, sizeof (buffer));
   OK(status == 0);
-  STREQ ("\tfoo\r\n", buffer);
+  EXPECT_EQ_STR ("\tfoo\r\n", buffer);
 
   strncpy (buffer, "With \\\"quotes\\\"", sizeof (buffer));
   status = strunescape (buffer, sizeof (buffer));
   OK(status == 0);
-  STREQ ("With \"quotes\"", buffer);
+  EXPECT_EQ_STR ("With \"quotes\"", buffer);
 
   /* Backslash before null byte */
   strncpy (buffer, "\\tbackslash end\\", sizeof (buffer));
   status = strunescape (buffer, sizeof (buffer));
   OK(status != 0);
-  STREQ ("\tbackslash end", buffer);
+  EXPECT_EQ_STR ("\tbackslash end", buffer);
   return (0);
 
   /* Backslash at buffer end */
@@ -235,6 +283,98 @@ DEF_TEST(strunescape)
   return (0);
 }
 
+DEF_TEST(parse_values)
+{
+  struct {
+    char buffer[64];
+    int status;
+    gauge_t value;
+  } cases[] = {
+    {"1435044576:42",     0, 42.0},
+    {"1435044576:42:23", -1,  NAN},
+    {"1435044576:U",      0,  NAN},
+    {"N:12.3",            0, 12.3},
+    {"N:42.0:23",        -1,  NAN},
+    {"N:U",               0,  NAN},
+    {"T:42.0",           -1,  NAN},
+  };
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+  {
+    data_source_t dsrc = {
+      .name = "value",
+      .type = DS_TYPE_GAUGE,
+      .min = 0.0,
+      .max = NAN,
+    };
+    data_set_t ds = {
+      .type = "example",
+      .ds_num = 1,
+      .ds = &dsrc,
+    };
+
+    value_t v = {
+      .gauge = NAN,
+    };
+    value_list_t vl = {
+      .values = &v,
+      .values_len = 1,
+      .time = 0,
+      .interval = 0,
+      .host = "example.com",
+      .plugin = "common_test",
+      .type = "example",
+      .meta = NULL,
+    };
+
+    int status = parse_values (cases[i].buffer, &vl, &ds);
+    EXPECT_EQ_INT (cases[i].status, status);
+    if (status != 0)
+      continue;
+
+    EXPECT_EQ_DOUBLE (cases[i].value, vl.values[0].gauge);
+  }
+
+  return (0);
+}
+
+DEF_TEST(value_to_rate)
+{
+  struct {
+    time_t t0;
+    time_t t1;
+    int ds_type;
+    value_t v0;
+    value_t v1;
+    gauge_t want;
+  } cases[] = {
+    { 0, 10, DS_TYPE_DERIVE,  {.derive  =    0}, {.derive = 1000},   NAN},
+    {10, 20, DS_TYPE_DERIVE,  {.derive  = 1000}, {.derive = 2000}, 100.0},
+    {20, 30, DS_TYPE_DERIVE,  {.derive  = 2000}, {.derive = 1800}, -20.0},
+    { 0, 10, DS_TYPE_COUNTER, {.counter =    0}, {.counter = 1000},   NAN},
+    {10, 20, DS_TYPE_COUNTER, {.counter = 1000}, {.counter = 5000}, 400.0},
+    /* 32bit wrap-around. */
+    {20, 30, DS_TYPE_COUNTER, {.counter = 4294967238ULL}, {.counter =   42}, 10.0},
+    /* 64bit wrap-around. */
+    {30, 40, DS_TYPE_COUNTER, {.counter = 18446744073709551558ULL}, {.counter =   42}, 10.0},
+  };
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+    value_to_rate_state_t state = { cases[i].v0, TIME_T_TO_CDTIME_T (cases[i].t0) };
+    gauge_t got;
+
+    if (cases[i].t0 == 0) {
+      OK(value_to_rate (&got, cases[i].v1, cases[i].ds_type, TIME_T_TO_CDTIME_T(cases[i].t1), &state) == EAGAIN);
+      continue;
+    }
+
+    OK(value_to_rate (&got, cases[i].v1, cases[i].ds_type, TIME_T_TO_CDTIME_T(cases[i].t1), &state) == 0);
+    EXPECT_EQ_DOUBLE(cases[i].want, got);
+  }
+
+  return 0;
+}
+
 int main (void)
 {
   RUN_TEST(sstrncpy);
@@ -242,7 +382,11 @@ int main (void)
   RUN_TEST(sstrdup);
   RUN_TEST(strsplit);
   RUN_TEST(strjoin);
+  RUN_TEST(escape_slashes);
+  RUN_TEST(escape_string);
   RUN_TEST(strunescape);
+  RUN_TEST(parse_values);
+  RUN_TEST(value_to_rate);
 
   END_TEST;
 }
index 16e0724..a31fb64 100644 (file)
@@ -72,15 +72,16 @@ typedef struct cf_complex_callback_s
 
 typedef struct cf_value_map_s
 {
-       char *key;
+       const char *key;
        int (*func) (oconfig_item_t *);
 } cf_value_map_t;
 
 typedef struct cf_global_option_s
 {
-       char *key;
+       const char *key;
        char *value;
-       char *def;
+       _Bool from_cli; /* value set from CLI */
+       const char *def;
 } cf_global_option_t;
 
 /*
@@ -108,21 +109,21 @@ static int cf_value_map_num = STATIC_ARRAY_SIZE (cf_value_map);
 
 static cf_global_option_t cf_global_options[] =
 {
-       {"BaseDir",     NULL, PKGLOCALSTATEDIR},
-       {"PIDFile",     NULL, PIDFILE},
-       {"Hostname",    NULL, NULL},
-       {"FQDNLookup",  NULL, "true"},
-       {"Interval",    NULL, NULL},
-       {"ReadThreads", NULL, "5"},
-       {"WriteThreads", NULL, "5"},
-       {"WriteQueueLimitHigh", NULL, NULL},
-       {"WriteQueueLimitLow", NULL, NULL},
-       {"Timeout",     NULL, "2"},
-       {"AutoLoadPlugin", NULL, "false"},
-       {"CollectInternalStats", NULL, "false"},
-       {"PreCacheChain",  NULL, "PreCache"},
-       {"PostCacheChain", NULL, "PostCache"},
-       {"MaxReadInterval", NULL, "86400"}
+       {"BaseDir",              NULL, 0, PKGLOCALSTATEDIR},
+       {"PIDFile",              NULL, 0, PIDFILE},
+       {"Hostname",             NULL, 0, NULL},
+       {"FQDNLookup",           NULL, 0, "true"},
+       {"Interval",             NULL, 0, NULL},
+       {"ReadThreads",          NULL, 0, "5"},
+       {"WriteThreads",         NULL, 0, "5"},
+       {"WriteQueueLimitHigh",  NULL, 0, NULL},
+       {"WriteQueueLimitLow",   NULL, 0, NULL},
+       {"Timeout",              NULL, 0, "2"},
+       {"AutoLoadPlugin",       NULL, 0, "false"},
+       {"CollectInternalStats", NULL, 0, "false"},
+       {"PreCacheChain",        NULL, 0, "PreCache"},
+       {"PostCacheChain",       NULL, 0, "PostCache"},
+       {"MaxReadInterval",      NULL, 0, "86400"}
 };
 static int cf_global_options_num = STATIC_ARRAY_SIZE (cf_global_options);
 
@@ -154,7 +155,7 @@ static int cf_dispatch (const char *type, const char *orig_key,
        char *key;
        char *value;
        int ret;
-       int i;
+       int i = 0;
 
        if (orig_key == NULL)
                return (EINVAL);
@@ -210,19 +211,19 @@ static int dispatch_global_option (const oconfig_item_t *ci)
        if (ci->values_num != 1)
                return (-1);
        if (ci->values[0].type == OCONFIG_TYPE_STRING)
-               return (global_option_set (ci->key, ci->values[0].value.string));
+               return (global_option_set (ci->key, ci->values[0].value.string, 0));
        else if (ci->values[0].type == OCONFIG_TYPE_NUMBER)
        {
                char tmp[128];
                ssnprintf (tmp, sizeof (tmp), "%lf", ci->values[0].value.number);
-               return (global_option_set (ci->key, tmp));
+               return (global_option_set (ci->key, tmp, 0));
        }
        else if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
        {
                if (ci->values[0].value.boolean)
-                       return (global_option_set (ci->key, "true"));
+                       return (global_option_set (ci->key, "true", 0));
                else
-                       return (global_option_set (ci->key, "false"));
+                       return (global_option_set (ci->key, "false", 0));
        }
 
        return (-1);
@@ -230,8 +231,6 @@ static int dispatch_global_option (const oconfig_item_t *ci)
 
 static int dispatch_value_typesdb (oconfig_item_t *ci)
 {
-       int i = 0;
-
        assert (strcasecmp (ci->key, "TypesDB") == 0);
 
        cf_default_typesdb = 0;
@@ -241,7 +240,7 @@ static int dispatch_value_typesdb (oconfig_item_t *ci)
                return (-1);
        }
 
-       for (i = 0; i < ci->values_num; ++i)
+       for (int i = 0; i < ci->values_num; ++i)
        {
                if (OCONFIG_TYPE_STRING != ci->values[i].type) {
                        WARNING ("configfile: TypesDB: Skipping %i. argument which "
@@ -257,7 +256,7 @@ static int dispatch_value_typesdb (oconfig_item_t *ci)
 static int dispatch_value_plugindir (oconfig_item_t *ci)
 {
        assert (strcasecmp (ci->key, "PluginDir") == 0);
-       
+
        if (ci->values_num != 1)
                return (-1);
        if (ci->values[0].type != OCONFIG_TYPE_STRING)
@@ -269,10 +268,9 @@ static int dispatch_value_plugindir (oconfig_item_t *ci)
 
 static int dispatch_loadplugin (oconfig_item_t *ci)
 {
-       int i;
        const char *name;
        unsigned int flags = 0;
-       plugin_ctx_t ctx;
+       plugin_ctx_t ctx = { 0 };
        plugin_ctx_t old_ctx;
        int ret_val;
 
@@ -288,22 +286,26 @@ static int dispatch_loadplugin (oconfig_item_t *ci)
                name = "virt";
 
        /* default to the global interval set before loading this plugin */
-       memset (&ctx, 0, sizeof (ctx));
        ctx.interval = cf_get_default_interval ();
+       ctx.flush_interval = 0;
+       ctx.flush_timeout = 0;
 
-       for (i = 0; i < ci->children_num; ++i) {
-               if (strcasecmp("Globals", ci->children[i].key) == 0)
-                       cf_util_get_flag (ci->children + i, &flags, PLUGIN_FLAGS_GLOBAL);
-               else if (strcasecmp ("Interval", ci->children[i].key) == 0) {
-                       if (cf_util_get_cdtime (ci->children + i, &ctx.interval) != 0) {
-                               /* cf_util_get_cdtime will log an error */
-                               continue;
-                       }
-               }
+       for (int i = 0; i < ci->children_num; ++i)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp("Globals", child->key) == 0)
+                       cf_util_get_flag (child, &flags, PLUGIN_FLAGS_GLOBAL);
+               else if (strcasecmp ("Interval", child->key) == 0)
+                       cf_util_get_cdtime (child, &ctx.interval);
+               else if (strcasecmp ("FlushInterval", child->key) == 0)
+                       cf_util_get_cdtime (child, &ctx.flush_interval);
+               else if (strcasecmp ("FlushTimeout", child->key) == 0)
+                       cf_util_get_cdtime (child, &ctx.flush_timeout);
                else {
                        WARNING("Ignoring unknown LoadPlugin option \"%s\" "
                                        "for plugin \"%s\"",
-                                       ci->children[i].key, ci->values[0].value.string);
+                                       child->key, ci->values[0].value.string);
                }
        }
 
@@ -320,12 +322,11 @@ static int dispatch_value_plugin (const char *plugin, oconfig_item_t *ci)
        char  buffer[4096];
        char *buffer_ptr;
        int   buffer_free;
-       int i;
 
        buffer_ptr = buffer;
        buffer_free = sizeof (buffer);
 
-       for (i = 0; i < ci->values_num; i++)
+       for (int i = 0; i < ci->values_num; i++)
        {
                int status = -1;
 
@@ -353,17 +354,16 @@ static int dispatch_value_plugin (const char *plugin, oconfig_item_t *ci)
 
 static int dispatch_value (oconfig_item_t *ci)
 {
-       int ret = -2;
-       int i;
+       int ret = 0;
 
-       for (i = 0; i < cf_value_map_num; i++)
+       for (int i = 0; i < cf_value_map_num; i++)
                if (strcasecmp (cf_value_map[i].key, ci->key) == 0)
                {
                        ret = cf_value_map[i].func (ci);
                        break;
                }
 
-       for (i = 0; i < cf_global_options_num; i++)
+       for (int i = 0; i < cf_global_options_num; i++)
                if (strcasecmp (cf_global_options[i].key, ci->key) == 0)
                {
                        ret = dispatch_global_option (ci);
@@ -375,10 +375,7 @@ static int dispatch_value (oconfig_item_t *ci)
 
 static int dispatch_block_plugin (oconfig_item_t *ci)
 {
-       int i;
-       char *name;
-
-       cf_complex_callback_t *cb;
+       const char *name;
 
        if (strcasecmp (ci->key, "Plugin") != 0)
                return (-1);
@@ -400,12 +397,11 @@ static int dispatch_block_plugin (oconfig_item_t *ci)
 
        if (IS_TRUE (global_option_get ("AutoLoadPlugin")))
        {
-               plugin_ctx_t ctx;
+               plugin_ctx_t ctx = { 0 };
                plugin_ctx_t old_ctx;
                int status;
 
                /* default to the global interval set before loading this plugin */
-               memset (&ctx, 0, sizeof (ctx));
                ctx.interval = cf_get_default_interval ();
 
                old_ctx = plugin_set_ctx (ctx);
@@ -422,7 +418,7 @@ static int dispatch_block_plugin (oconfig_item_t *ci)
        }
 
        /* Check for a complex callback first */
-       for (cb = complex_callback_head; cb != NULL; cb = cb->next)
+       for (cf_complex_callback_t *cb = complex_callback_head; cb != NULL; cb = cb->next)
        {
                if (strcasecmp (name, cb->type) == 0)
                {
@@ -437,7 +433,7 @@ static int dispatch_block_plugin (oconfig_item_t *ci)
        }
 
        /* Hm, no complex plugin found. Dispatch the values one by one */
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                if (ci->children[i].children == NULL)
                        dispatch_value_plugin (name, ci->children + i);
@@ -473,7 +469,6 @@ static int cf_ci_replace_child (oconfig_item_t *dst, oconfig_item_t *src,
                int offset)
 {
        oconfig_item_t *temp;
-       int i;
 
        assert (offset >= 0);
        assert (dst->children_num > offset);
@@ -481,7 +476,7 @@ static int cf_ci_replace_child (oconfig_item_t *dst, oconfig_item_t *src,
        /* Free the memory used by the replaced child. Usually that's the
         * `Include "blah"' statement. */
        temp = dst->children + offset;
-       for (i = 0; i < temp->values_num; i++)
+       for (int i = 0; i < temp->values_num; i++)
        {
                if (temp->values[i].type == OCONFIG_TYPE_STRING)
                {
@@ -509,7 +504,7 @@ static int cf_ci_replace_child (oconfig_item_t *dst, oconfig_item_t *src,
                return (0);
        }
 
-       temp = (oconfig_item_t *) realloc (dst->children,
+       temp = realloc (dst->children,
                        sizeof (oconfig_item_t)
                        * (dst->children_num + src->children_num - 1));
        if (temp == NULL)
@@ -557,7 +552,7 @@ static int cf_ci_append_children (oconfig_item_t *dst, oconfig_item_t *src)
        if ((src == NULL) || (src->children_num == 0))
                return (0);
 
-       temp = (oconfig_item_t *) realloc (dst->children,
+       temp = realloc (dst->children,
                        sizeof (oconfig_item_t)
                        * (dst->children_num + src->children_num));
        if (temp == NULL)
@@ -582,17 +577,13 @@ static oconfig_item_t *cf_read_generic (const char *path,
 
 static int cf_include_all (oconfig_item_t *root, int depth)
 {
-       int i;
-
-       for (i = 0; i < root->children_num; i++)
+       for (int i = 0; i < root->children_num; i++)
        {
                oconfig_item_t *new;
                oconfig_item_t *old;
 
                char *pattern = NULL;
 
-               int j;
-
                if (strcasecmp (root->children[i].key, "Include") != 0)
                        continue;
 
@@ -605,7 +596,7 @@ static int cf_include_all (oconfig_item_t *root, int depth)
                        continue;
                }
 
-               for (j = 0; j < old->children_num; ++j)
+               for (int j = 0; j < old->children_num; ++j)
                {
                        oconfig_item_t *child = old->children + j;
 
@@ -699,7 +690,6 @@ static oconfig_item_t *cf_read_dir (const char *dir,
        char **filenames = NULL;
        int filenames_num = 0;
        int status;
-       int i;
 
        assert (depth < CF_MAX_DEPTH);
 
@@ -712,14 +702,13 @@ static oconfig_item_t *cf_read_dir (const char *dir,
                return (NULL);
        }
 
-       root = (oconfig_item_t *) malloc (sizeof (oconfig_item_t));
+       root = calloc (1, sizeof (*root));
        if (root == NULL)
        {
-               ERROR ("configfile: malloc failed.");
+               ERROR ("configfile: calloc failed.");
                closedir (dh);
                return (NULL);
        }
-       memset (root, 0, sizeof (oconfig_item_t));
 
        while ((de = readdir (dh)) != NULL)
        {
@@ -737,7 +726,7 @@ static oconfig_item_t *cf_read_dir (const char *dir,
                                        " name is too long.",
                                        dir, de->d_name);
                        closedir (dh);
-                       for (i = 0; i < filenames_num; ++i)
+                       for (int i = 0; i < filenames_num; ++i)
                                free (filenames[i]);
                        free (filenames);
                        free (root);
@@ -745,12 +734,12 @@ static oconfig_item_t *cf_read_dir (const char *dir,
                }
 
                ++filenames_num;
-               tmp = (char **) realloc (filenames,
+               tmp = realloc (filenames,
                                filenames_num * sizeof (*filenames));
                if (tmp == NULL) {
                        ERROR ("configfile: realloc failed.");
                        closedir (dh);
-                       for (i = 0; i < filenames_num - 1; ++i)
+                       for (int i = 0; i < filenames_num - 1; ++i)
                                free (filenames[i]);
                        free (filenames);
                        free (root);
@@ -770,7 +759,7 @@ static oconfig_item_t *cf_read_dir (const char *dir,
        qsort ((void *) filenames, filenames_num, sizeof (*filenames),
                        cf_compare_string);
 
-       for (i = 0; i < filenames_num; ++i)
+       for (int i = 0; i < filenames_num; ++i)
        {
                oconfig_item_t *temp;
                char *name = filenames[i];
@@ -803,7 +792,7 @@ static oconfig_item_t *cf_read_dir (const char *dir,
  *
  * There are two versions of this function: If `wordexp' exists shell wildcards
  * will be expanded and the function will include all matches found. If
- * `wordexp' (or, more precisely, it's header file) is not available the
+ * `wordexp' (or, more precisely, its header file) is not available the
  * simpler function is used which does not do any such expansion.
  */
 #if HAVE_WORDEXP_H
@@ -814,7 +803,6 @@ static oconfig_item_t *cf_read_generic (const char *path,
        int status;
        const char *path_ptr;
        wordexp_t we;
-       size_t i;
 
        if (depth >= CF_MAX_DEPTH)
        {
@@ -830,20 +818,19 @@ static oconfig_item_t *cf_read_generic (const char *path,
                return (NULL);
        }
 
-       root = (oconfig_item_t *) malloc (sizeof (oconfig_item_t));
+       root = calloc (1, sizeof (*root));
        if (root == NULL)
        {
-               ERROR ("configfile: malloc failed.");
+               ERROR ("configfile: calloc failed.");
                return (NULL);
        }
-       memset (root, '\0', sizeof (oconfig_item_t));
 
        /* wordexp() might return a sorted list already. That's not
         * documented though, so let's make sure we get what we want. */
        qsort ((void *) we.we_wordv, we.we_wordc, sizeof (*we.we_wordv),
                        cf_compare_string);
 
-       for (i = 0; i < we.we_wordc; i++)
+       for (size_t i = 0; i < we.we_wordc; i++)
        {
                oconfig_item_t *temp;
                struct stat statbuf;
@@ -921,13 +908,12 @@ static oconfig_item_t *cf_read_generic (const char *path,
 } /* oconfig_item_t *cf_read_generic */
 #endif /* !HAVE_WORDEXP_H */
 
-/* 
+/*
  * Public functions
  */
-int global_option_set (const char *option, const char *value)
+int global_option_set (const char *option, const char *value, _Bool from_cli)
 {
        int i;
-
        DEBUG ("option = %s; value = %s;", option, value);
 
        for (i = 0; i < cf_global_options_num; i++)
@@ -935,12 +921,16 @@ int global_option_set (const char *option, const char *value)
                        break;
 
        if (i >= cf_global_options_num)
+       {
+               ERROR ("configfile: Cannot set unknown global option `%s'.", option);
                return (-1);
+       }
 
-       if (strcasecmp (option, "PIDFile") == 0 && pidfile_from_cli == 1)
+       if (cf_global_options[i].from_cli && (! from_cli))
        {
-               DEBUG ("Configfile: Ignoring `PIDFILE' option because "
-                       "command-line option `-P' take precedence.");
+               DEBUG ("configfile: Ignoring %s `%s' option because "
+                               "it was overriden by a command-line option.",
+                               option, value);
                return (0);
        }
 
@@ -951,20 +941,24 @@ int global_option_set (const char *option, const char *value)
        else
                cf_global_options[i].value = NULL;
 
+       cf_global_options[i].from_cli = from_cli;
+
        return (0);
 }
 
 const char *global_option_get (const char *option)
 {
        int i;
-
        for (i = 0; i < cf_global_options_num; i++)
                if (strcasecmp (cf_global_options[i].key, option) == 0)
                        break;
 
        if (i >= cf_global_options_num)
+       {
+               ERROR ("configfile: Cannot get unknown global option `%s'.", option);
                return (NULL);
-       
+       }
+
        return ((cf_global_options[i].value != NULL)
                        ? cf_global_options[i].value
                        : cf_global_options[i].def);
@@ -1015,9 +1009,7 @@ cdtime_t cf_get_default_interval (void)
 
 void cf_unregister (const char *type)
 {
-       cf_callback_t *this, *prev;
-
-       for (prev = NULL, this = first_callback;
+       for (cf_callback_t *prev = NULL, *this = first_callback;
                        this != NULL;
                        prev = this, this = this->next)
                if (strcasecmp (this->type, type) == 0)
@@ -1034,9 +1026,7 @@ void cf_unregister (const char *type)
 
 void cf_unregister_complex (const char *type)
 {
-       cf_complex_callback_t *this, *prev;
-
-       for (prev = NULL, this = complex_callback_head;
+       for (cf_complex_callback_t *prev = NULL, *this = complex_callback_head;
                        this != NULL;
                        prev = this, this = this->next)
                if (strcasecmp (this->type, type) == 0)
@@ -1062,7 +1052,7 @@ void cf_register (const char *type,
        cf_unregister (type);
 
        /* This pointer will be free'd in `cf_unregister' */
-       if ((cf_cb = (cf_callback_t *) malloc (sizeof (cf_callback_t))) == NULL)
+       if ((cf_cb = malloc (sizeof (*cf_cb))) == NULL)
                return;
 
        cf_cb->type     = type;
@@ -1079,7 +1069,7 @@ int cf_register_complex (const char *type, int (*callback) (oconfig_item_t *))
 {
        cf_complex_callback_t *new;
 
-       new = (cf_complex_callback_t *) malloc (sizeof (cf_complex_callback_t));
+       new = malloc (sizeof (*new));
        if (new == NULL)
                return (-1);
 
@@ -1110,10 +1100,10 @@ int cf_register_complex (const char *type, int (*callback) (oconfig_item_t *))
        return (0);
 } /* int cf_register_complex */
 
-int cf_read (char *filename)
+int cf_read (const char *filename)
 {
        oconfig_item_t *conf;
-       int i;
+       int ret = 0;
 
        conf = cf_read_generic (filename, /* pattern = */ NULL, /* depth = */ 0);
        if (conf == NULL)
@@ -1128,21 +1118,30 @@ int cf_read (char *filename)
                return (-1);
        }
 
-       for (i = 0; i < conf->children_num; i++)
+       for (int i = 0; i < conf->children_num; i++)
        {
                if (conf->children[i].children == NULL)
-                       dispatch_value (conf->children + i);
+               {
+                       if (dispatch_value (conf->children + i) != 0)
+                               ret = -1;
+               }
                else
-                       dispatch_block (conf->children + i);
+               {
+                       if (dispatch_block (conf->children + i) != 0)
+                               ret = -1;
+               }
        }
 
        oconfig_free (conf);
 
        /* Read the default types.db if no `TypesDB' option was given. */
        if (cf_default_typesdb)
-               read_types_list (PKGDATADIR"/types.db");
+       {
+               if (read_types_list (PKGDATADIR"/types.db") != 0)
+                       ret = -1;
+       }
 
-       return (0);
+       return ret;
 } /* int cf_read */
 
 /* Assures the config option is a string, duplicates it and returns the copy in
index 5bc9b30..ae2c6c0 100644 (file)
 #define CONFIGFILE_H
 
 #include "collectd.h"
+
 #include "utils_time.h"
 #include "liboconfig/oconfig.h"
 
 /*
  * DESCRIPTION
  *  Remove a registered plugin from the internal data structures.
- * 
+ *
  * PARAMETERS
  *  `type'      Name of the plugin (must be the same as passed to
  *              `plugin_register'
@@ -87,9 +88,9 @@ int cf_register_complex (const char *type, int (*callback) (oconfig_item_t *));
  *  Returns zero upon success and non-zero otherwise. A error-message will have
  *  been printed in this case.
  */
-int cf_read (char *filename);
+int cf_read (const char *filename);
 
-int global_option_set (const char *option, const char *value);
+int global_option_set (const char *option, const char *value, _Bool from_cli);
 const char *global_option_get (const char *option);
 long global_option_get_long (const char *option, long default_value);
 long global_option_get_long_in_range (const char *option, long default_value, long min, long max);
index ecc7f16..cee479a 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "configfile.h"
 #include "plugin.h"
 #include "utils_complain.h"
@@ -174,7 +175,7 @@ static char *fc_strdup (const char *orig) /* {{{ */
     return (NULL);
 
   sz = strlen (orig) + 1;
-  dest = (char *) malloc (sz);
+  dest = malloc (sz);
   if (dest == NULL)
     return (NULL);
 
@@ -235,13 +236,12 @@ static int fc_config_add_match (fc_match_t **matches_head, /* {{{ */
     return (-1);
   }
 
-  m = (fc_match_t *) malloc (sizeof (*m));
+  m = calloc (1, sizeof (*m));
   if (m == NULL)
   {
-    ERROR ("fc_config_add_match: malloc failed.");
+    ERROR ("fc_config_add_match: calloc failed.");
     return (-1);
   }
-  memset (m, 0, sizeof (*m));
 
   sstrncpy (m->name, ptr->name, sizeof (m->name));
   memcpy (&m->proc, &ptr->proc, sizeof (m->proc));
@@ -307,13 +307,12 @@ static int fc_config_add_target (fc_target_t **targets_head, /* {{{ */
     return (-1);
   }
 
-  t = (fc_target_t *) malloc (sizeof (*t));
+  t = calloc (1, sizeof (*t));
   if (t == NULL)
   {
-    ERROR ("fc_config_add_target: malloc failed.");
+    ERROR ("fc_config_add_target: calloc failed.");
     return (-1);
   }
-  memset (t, 0, sizeof (*t));
 
   sstrncpy (t->name, ptr->name, sizeof (t->name));
   memcpy (&t->proc, &ptr->proc, sizeof (t->proc));
@@ -335,7 +334,7 @@ static int fc_config_add_target (fc_target_t **targets_head, /* {{{ */
   {
     t->user_data = NULL;
   }
-  
+
   if (*targets_head != NULL)
   {
     ptr = *targets_head;
@@ -358,7 +357,6 @@ static int fc_config_add_rule (fc_chain_t *chain, /* {{{ */
   fc_rule_t *rule;
   char rule_name[2*DATA_MAX_NAME_LEN] = "Unnamed rule";
   int status = 0;
-  int i;
 
   if (ci->values_num > 1)
   {
@@ -373,14 +371,12 @@ static int fc_config_add_rule (fc_chain_t *chain, /* {{{ */
     return (-1);
   }
 
-  rule = (fc_rule_t *) malloc (sizeof (*rule));
+  rule = calloc (1, sizeof (*rule));
   if (rule == NULL)
   {
-    ERROR ("fc_config_add_rule: malloc failed.");
+    ERROR ("fc_config_add_rule: calloc failed.");
     return (-1);
   }
-  memset (rule, 0, sizeof (*rule));
-  rule->next = NULL;
 
   if (ci->values_num == 1)
   {
@@ -389,7 +385,7 @@ static int fc_config_add_rule (fc_chain_t *chain, /* {{{ */
         ci->values[0].value.string);
   }
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
@@ -450,7 +446,6 @@ static int fc_config_add_chain (const oconfig_item_t *ci) /* {{{ */
 {
   fc_chain_t *chain = NULL;
   int status = 0;
-  int i;
   int new_chain = 1;
 
   if ((ci->values_num != 1)
@@ -469,20 +464,16 @@ static int fc_config_add_chain (const oconfig_item_t *ci) /* {{{ */
 
   if (chain == NULL)
   {
-    chain = (fc_chain_t *) malloc (sizeof (*chain));
+    chain = calloc (1, sizeof (*chain));
     if (chain == NULL)
     {
-      ERROR ("fc_config_add_chain: malloc failed.");
+      ERROR ("fc_config_add_chain: calloc failed.");
       return (-1);
     }
-    memset (chain, 0, sizeof (*chain));
     sstrncpy (chain->name, ci->values[0].value.string, sizeof (chain->name));
-    chain->rules = NULL;
-    chain->targets = NULL;
-    chain->next = NULL;
   }
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
@@ -632,16 +623,13 @@ static int fc_bit_return_invoke (const data_set_t __attribute__((unused)) *ds, /
 static int fc_bit_write_create (const oconfig_item_t *ci, /* {{{ */
     void **user_data)
 {
-  int i;
-
   fc_writer_t *plugin_list = NULL;
   size_t plugin_list_len = 0;
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
     fc_writer_t *temp;
-    int j;
 
     if (strcasecmp ("Plugin", child->key) != 0)
     {
@@ -651,7 +639,7 @@ static int fc_bit_write_create (const oconfig_item_t *ci, /* {{{ */
       continue;
     }
 
-    for (j = 0; j < child->values_num; j++)
+    for (int j = 0; j < child->values_num; j++)
     {
       char *plugin;
 
@@ -663,7 +651,7 @@ static int fc_bit_write_create (const oconfig_item_t *ci, /* {{{ */
       }
       plugin = child->values[j].value.string;
 
-      temp = (fc_writer_t *) realloc (plugin_list, (plugin_list_len + 2)
+      temp = realloc (plugin_list, (plugin_list_len + 2)
           * (sizeof (*plugin_list)));
       if (temp == NULL)
       {
@@ -692,14 +680,13 @@ static int fc_bit_write_create (const oconfig_item_t *ci, /* {{{ */
 static int fc_bit_write_destroy (void **user_data) /* {{{ */
 {
   fc_writer_t *plugin_list;
-  size_t i;
 
   if ((user_data == NULL) || (*user_data == NULL))
     return (0);
 
   plugin_list = *user_data;
 
-  for (i = 0; plugin_list[i].plugin != NULL; i++)
+  for (size_t i = 0; plugin_list[i].plugin != NULL; i++)
     free (plugin_list[i].plugin);
   free (plugin_list);
 
@@ -752,9 +739,7 @@ static int fc_bit_write_invoke (const data_set_t *ds, /* {{{ */
   }
   else
   {
-    size_t i;
-
-    for (i = 0; plugin_list[i].plugin != NULL; i++)
+    for (size_t i = 0; plugin_list[i].plugin != NULL; i++)
     {
       status = plugin_write (plugin_list[i].plugin, ds, vl);
       if (status != 0)
@@ -781,12 +766,11 @@ static int fc_bit_write_invoke (const data_set_t *ds, /* {{{ */
 static int fc_init_once (void) /* {{{ */
 {
   static int done = 0;
-  target_proc_t tproc;
+  target_proc_t tproc = { 0 };
 
   if (done != 0)
     return (0);
 
-  memset (&tproc, 0, sizeof (tproc));
   tproc.create  = fc_bit_jump_create;
   tproc.destroy = fc_bit_jump_destroy;
   tproc.invoke  = fc_bit_jump_invoke;
@@ -824,14 +808,12 @@ int fc_register_match (const char *name, match_proc_t proc) /* {{{ */
 
   DEBUG ("fc_register_match (%s);", name);
 
-  m = (fc_match_t *) malloc (sizeof (*m));
+  m = calloc (1, sizeof (*m));
   if (m == NULL)
     return (-ENOMEM);
-  memset (m, 0, sizeof (*m));
 
   sstrncpy (m->name, name, sizeof (m->name));
   memcpy (&m->proc, &proc, sizeof (m->proc));
-  m->next = NULL;
 
   if (match_list_head == NULL)
   {
@@ -858,14 +840,12 @@ int fc_register_target (const char *name, target_proc_t proc) /* {{{ */
 
   DEBUG ("fc_register_target (%s);", name);
 
-  t = (fc_target_t *) malloc (sizeof (*t));
+  t = calloc (1, sizeof (*t));
   if (t == NULL)
     return (-ENOMEM);
-  memset (t, 0, sizeof (*t));
 
   sstrncpy (t->name, name, sizeof (t->name));
   memcpy (&t->proc, &proc, sizeof (t->proc));
-  t->next = NULL;
 
   if (target_list_head == NULL)
   {
@@ -887,12 +867,10 @@ int fc_register_target (const char *name, target_proc_t proc) /* {{{ */
 
 fc_chain_t *fc_chain_get_by_name (const char *chain_name) /* {{{ */
 {
-  fc_chain_t *chain;
-
   if (chain_name == NULL)
     return (NULL);
 
-  for (chain = chain_list_head; chain != NULL; chain = chain->next)
+  for (fc_chain_t *chain = chain_list_head; chain != NULL; chain = chain->next)
     if (strcasecmp (chain_name, chain->name) == 0)
       return (chain);
 
@@ -902,7 +880,6 @@ fc_chain_t *fc_chain_get_by_name (const char *chain_name) /* {{{ */
 int fc_process_chain (const data_set_t *ds, value_list_t *vl, /* {{{ */
     fc_chain_t *chain)
 {
-  fc_rule_t *rule;
   fc_target_t *target;
   int status = FC_TARGET_CONTINUE;
 
@@ -911,7 +888,7 @@ int fc_process_chain (const data_set_t *ds, value_list_t *vl, /* {{{ */
 
   DEBUG ("fc_process_chain (chain = %s);", chain->name);
 
-  for (rule = chain->rules; rule != NULL; rule = rule->next)
+  for (fc_rule_t *rule = chain->rules; rule != NULL; rule = rule->next)
   {
     fc_match_t *match;
     status = FC_TARGET_CONTINUE;
index 2db90db..2d280f8 100644 (file)
@@ -28,6 +28,7 @@
 #define FILTER_CHAIN_H 1
 
 #include "collectd.h"
+
 #include "plugin.h"
 
 #define FC_MATCH_NO_MATCH  0
@@ -97,7 +98,7 @@ int fc_process_chain (const data_set_t *ds, value_list_t *vl,
 
 int fc_default_action (const data_set_t *ds, value_list_t *vl);
 
-/* 
+/*
  * Shortcut for global configuration
  */
 int fc_configure (const oconfig_item_t *ci);
index 29236e2..9e4fd07 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "meta_data.h"
 
-#include <pthread.h>
-
 /*
  * Data types
  */
@@ -71,7 +70,7 @@ static char *md_strdup (const char *orig) /* {{{ */
     return (NULL);
 
   sz = strlen (orig) + 1;
-  dest = (char *) malloc (sz);
+  dest = malloc (sz);
   if (dest == NULL)
     return (NULL);
 
@@ -84,13 +83,12 @@ static meta_entry_t *md_entry_alloc (const char *key) /* {{{ */
 {
   meta_entry_t *e;
 
-  e = (meta_entry_t *) malloc (sizeof (*e));
+  e = calloc (1, sizeof (*e));
   if (e == NULL)
   {
-    ERROR ("md_entry_alloc: malloc failed.");
+    ERROR ("md_entry_alloc: calloc failed.");
     return (NULL);
   }
-  memset (e, 0, sizeof (*e));
 
   e->key = md_strdup (key);
   if (e->key == NULL)
@@ -106,12 +104,15 @@ static meta_entry_t *md_entry_alloc (const char *key) /* {{{ */
   return (e);
 } /* }}} meta_entry_t *md_entry_alloc */
 
-static meta_entry_t *md_entry_clone (const meta_entry_t *orig) /* {{{ */
+/* XXX: The lock on md must be held while calling this function! */
+static meta_entry_t *md_entry_clone_contents (const meta_entry_t *orig) /* {{{ */
 {
   meta_entry_t *copy;
 
-  if (orig == NULL)
-    return (NULL);
+  /* WARNINGS :
+   *  - we do not check that orig != NULL here. You should have done it before.
+   *  - we do not set copy->next. DO NOT FORGET TO SET copy->next IN YOUR FUNCTION
+   */
 
   copy = md_entry_alloc (orig->key);
   if (copy == NULL)
@@ -122,6 +123,18 @@ static meta_entry_t *md_entry_clone (const meta_entry_t *orig) /* {{{ */
   else
     copy->value = orig->value;
 
+  return (copy);
+} /* }}} meta_entry_t *md_entry_clone_contents */
+
+static meta_entry_t *md_entry_clone (const meta_entry_t *orig) /* {{{ */
+{
+  meta_entry_t *copy;
+
+  if (orig == NULL)
+    return (NULL);
+
+  copy = md_entry_clone_contents(orig);
+
   copy->next = md_entry_clone (orig->next);
   return (copy);
 } /* }}} meta_entry_t *md_entry_clone */
@@ -198,6 +211,63 @@ static int md_entry_insert (meta_data_t *md, meta_entry_t *e) /* {{{ */
 } /* }}} int md_entry_insert */
 
 /* XXX: The lock on md must be held while calling this function! */
+static int md_entry_insert_clone (meta_data_t *md, meta_entry_t *orig) /* {{{ */
+{
+  meta_entry_t *e;
+  meta_entry_t *this;
+  meta_entry_t *prev;
+
+  /* WARNINGS :
+   *  - we do not check that md and e != NULL here. You should have done it before.
+   *  - we do not use the lock. You should have set it before.
+   */
+
+  e = md_entry_clone_contents(orig);
+
+  prev = NULL;
+  this = md->head;
+  while (this != NULL)
+  {
+    if (strcasecmp (e->key, this->key) == 0)
+      break;
+
+    prev = this;
+    this = this->next;
+  }
+
+  if (this == NULL)
+  {
+    /* This key does not exist yet. */
+    if (md->head == NULL)
+      md->head = e;
+    else
+    {
+      assert (prev != NULL);
+      prev->next = e;
+    }
+
+    e->next = NULL;
+  }
+  else /* (this != NULL) */
+  {
+    if (prev == NULL)
+      md->head = e;
+    else
+      prev->next = e;
+
+    e->next = this->next;
+  }
+
+  if (this != NULL)
+  {
+    this->next = NULL;
+    md_entry_free (this);
+  }
+
+  return (0);
+} /* }}} int md_entry_insert_clone */
+
+/* XXX: The lock on md must be held while calling this function! */
 static meta_entry_t *md_entry_lookup (meta_data_t *md, /* {{{ */
     const char *key)
 {
@@ -231,15 +301,13 @@ meta_data_t *meta_data_create (void) /* {{{ */
 {
   meta_data_t *md;
 
-  md = (meta_data_t *) malloc (sizeof (*md));
+  md = calloc (1, sizeof (*md));
   if (md == NULL)
   {
-    ERROR ("meta_data_create: malloc failed.");
+    ERROR ("meta_data_create: calloc failed.");
     return (NULL);
   }
-  memset (md, 0, sizeof (*md));
 
-  md->head = NULL;
   pthread_mutex_init (&md->lock, /* attr = */ NULL);
 
   return (md);
@@ -263,6 +331,26 @@ meta_data_t *meta_data_clone (meta_data_t *orig) /* {{{ */
   return (copy);
 } /* }}} meta_data_t *meta_data_clone */
 
+int meta_data_clone_merge (meta_data_t **dest, meta_data_t *orig) /* {{{ */
+{
+  if (orig == NULL)
+    return (0);
+
+  if (*dest == NULL) {
+    *dest = meta_data_clone(orig);
+    return(0);
+  }
+
+  pthread_mutex_lock (&orig->lock);
+  for (meta_entry_t *e=orig->head; e != NULL; e = e->next)
+  {
+    md_entry_insert_clone((*dest), e);
+  }
+  pthread_mutex_unlock (&orig->lock);
+
+  return (0);
+} /* }}} int meta_data_clone_merge */
+
 void meta_data_destroy (meta_data_t *md) /* {{{ */
 {
   if (md == NULL)
@@ -275,14 +363,12 @@ void meta_data_destroy (meta_data_t *md) /* {{{ */
 
 int meta_data_exists (meta_data_t *md, const char *key) /* {{{ */
 {
-  meta_entry_t *e;
-
   if ((md == NULL) || (key == NULL))
     return (-EINVAL);
 
   pthread_mutex_lock (&md->lock);
 
-  for (e = md->head; e != NULL; e = e->next)
+  for (meta_entry_t *e = md->head; e != NULL; e = e->next)
   {
     if (strcasecmp (key, e->key) == 0)
     {
@@ -297,14 +383,12 @@ int meta_data_exists (meta_data_t *md, const char *key) /* {{{ */
 
 int meta_data_type (meta_data_t *md, const char *key) /* {{{ */
 {
-  meta_entry_t *e;
-
   if ((md == NULL) || (key == NULL))
     return -EINVAL;
 
   pthread_mutex_lock (&md->lock);
 
-  for (e = md->head; e != NULL; e = e->next)
+  for (meta_entry_t *e = md->head; e != NULL; e = e->next)
   {
     if (strcasecmp (key, e->key) == 0)
     {
@@ -320,15 +404,14 @@ int meta_data_type (meta_data_t *md, const char *key) /* {{{ */
 int meta_data_toc (meta_data_t *md, char ***toc) /* {{{ */
 {
   int i = 0, count = 0;
-  meta_entry_t *e;
 
   if ((md == NULL) || (toc == NULL))
     return -EINVAL;
 
   pthread_mutex_lock (&md->lock);
 
-  for (e = md->head; e != NULL; e = e->next)
-    ++count;    
+  for (meta_entry_t *e = md->head; e != NULL; e = e->next)
+    ++count;
 
   if (count == 0)
   {
@@ -337,9 +420,9 @@ int meta_data_toc (meta_data_t *md, char ***toc) /* {{{ */
   }
 
   *toc = calloc(count, sizeof(**toc));
-  for (e = md->head; e != NULL; e = e->next)
+  for (meta_entry_t *e = md->head; e != NULL; e = e->next)
     (*toc)[i++] = strdup(e->key);
-  
+
   pthread_mutex_unlock (&md->lock);
   return count;
 } /* }}} int meta_data_toc */
@@ -518,7 +601,7 @@ int meta_data_get_string (meta_data_t *md, /* {{{ */
     ERROR ("meta_data_get_string: md_strdup failed.");
     return (-ENOMEM);
   }
+
   pthread_mutex_unlock (&md->lock);
 
   *value = temp;
index fa48df3..0398c54 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "collectd.h"
 
+
 /*
  * Defines
  */
@@ -43,6 +44,7 @@ typedef struct meta_data_s meta_data_t;
 
 meta_data_t *meta_data_create (void);
 meta_data_t *meta_data_clone (meta_data_t *orig);
+int meta_data_clone_merge (meta_data_t **dest, meta_data_t *orig);
 void meta_data_destroy (meta_data_t *md);
 
 int meta_data_exists (meta_data_t *md, const char *key);
diff --git a/src/daemon/meta_data_test.c b/src/daemon/meta_data_test.c
new file mode 100644 (file)
index 0000000..35cfe71
--- /dev/null
@@ -0,0 +1,120 @@
+/**
+ * collectd - src/daemon/meta_data_test.c
+ * Copyright (C) 2015       Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "collectd.h"
+
+#include "testing.h"
+#include "meta_data.h"
+
+DEF_TEST(base)
+{
+  meta_data_t *m;
+
+  char *s;
+  int64_t si;
+  uint64_t ui;
+  double d;
+  _Bool b;
+
+  CHECK_NOT_NULL (m = meta_data_create ());
+
+  /* all of these are absent */
+  OK(meta_data_get_string (m, "string", &s) != 0);
+  OK(meta_data_get_signed_int (m, "signed_int", &si) != 0);
+  OK(meta_data_get_unsigned_int (m, "unsigned_int", &ui) != 0);
+  OK(meta_data_get_double (m, "double", &d) != 0);
+  OK(meta_data_get_boolean (m, "boolean", &b) != 0);
+
+  /* populate structure */
+  CHECK_ZERO (meta_data_add_string (m, "string", "foobar"));
+  OK(meta_data_exists (m, "string"));
+  OK(meta_data_type (m, "string") == MD_TYPE_STRING);
+
+  CHECK_ZERO (meta_data_add_signed_int (m, "signed_int", -1));
+  OK(meta_data_exists (m, "signed_int"));
+  OK(meta_data_type (m, "signed_int") == MD_TYPE_SIGNED_INT);
+
+  CHECK_ZERO (meta_data_add_unsigned_int (m, "unsigned_int", 1));
+  OK(meta_data_exists (m, "unsigned_int"));
+  OK(meta_data_type (m, "unsigned_int") == MD_TYPE_UNSIGNED_INT);
+
+  CHECK_ZERO (meta_data_add_double (m, "double", 47.11));
+  OK(meta_data_exists (m, "double"));
+  OK(meta_data_type (m, "double") == MD_TYPE_DOUBLE);
+
+  CHECK_ZERO (meta_data_add_boolean (m, "boolean", 1));
+  OK(meta_data_exists (m, "boolean"));
+  OK(meta_data_type (m, "boolean") == MD_TYPE_BOOLEAN);
+
+  /* retrieve and check all values */
+  CHECK_ZERO (meta_data_get_string (m, "string", &s));
+  EXPECT_EQ_STR ("foobar", s);
+  sfree (s);
+
+  CHECK_ZERO (meta_data_get_signed_int (m, "signed_int", &si));
+  EXPECT_EQ_INT (-1, (int) si);
+
+  CHECK_ZERO (meta_data_get_unsigned_int (m, "unsigned_int", &ui));
+  EXPECT_EQ_INT (1, (int) ui);
+
+  CHECK_ZERO (meta_data_get_double (m, "double", &d));
+  EXPECT_EQ_DOUBLE (47.11, d);
+
+  CHECK_ZERO (meta_data_get_boolean (m, "boolean", &b));
+  OK1 (b, "b evaluates to true");
+
+  /* retrieving the wrong type always fails */
+  EXPECT_EQ_INT (-2, meta_data_get_boolean (m, "string", &b));
+  EXPECT_EQ_INT (-2, meta_data_get_string (m, "signed_int", &s));
+  EXPECT_EQ_INT (-2, meta_data_get_string (m, "unsigned_int", &s));
+  EXPECT_EQ_INT (-2, meta_data_get_string (m, "double", &s));
+  EXPECT_EQ_INT (-2, meta_data_get_string (m, "boolean", &s));
+
+  /* replace existing keys */
+  CHECK_ZERO (meta_data_add_signed_int (m, "string", 666));
+  OK(meta_data_type (m, "string") == MD_TYPE_SIGNED_INT);
+
+  CHECK_ZERO (meta_data_add_signed_int (m, "signed_int", 666));
+  CHECK_ZERO (meta_data_get_signed_int (m, "signed_int", &si));
+  EXPECT_EQ_INT (666, (int) si);
+
+  /* deleting keys */
+  CHECK_ZERO (meta_data_delete (m, "signed_int"));
+  EXPECT_EQ_INT (-2, meta_data_delete (m, "doesnt exist"));
+
+  meta_data_destroy (m);
+  return 0;
+}
+
+int main (void)
+{
+  RUN_TEST(base);
+
+  END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
index 1deabba..1bee8cd 100644 (file)
@@ -26,6 +26,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -80,6 +81,12 @@ struct write_queue_s
        write_queue_t *next;
 };
 
+struct flush_callback_s {
+       char *name;
+       cdtime_t timeout;
+};
+typedef struct flush_callback_s flush_callback_t;
+
 /*
  * Private variables
  */
@@ -282,7 +289,7 @@ static int register_callback (llist_t **list, /* {{{ */
                {
                        ERROR ("plugin: register_callback: "
                                        "llentry_create failed.");
-                       free (key);
+                       sfree (key);
                        destroy_callback (cf);
                        return (-1);
                }
@@ -312,8 +319,8 @@ static void log_list_callbacks (llist_t **list, /* {{{ */
 {
        char *str;
        int len;
-       llentry_t *le;
        int i;
+       llentry_t *le;
        int n;
        char **keys;
 
@@ -352,9 +359,9 @@ static void log_list_callbacks (llist_t **list, /* {{{ */
                *str = '\0';
                strjoin(str, len, keys, n, "', '");
                INFO("%s ['%s']", comment, str);
-               free(str);
+               sfree (str);
        }
-       free(keys);
+       sfree (keys);
 } /* }}} void log_list_callbacks */
 
 static int create_register_callback (llist_t **list, /* {{{ */
@@ -362,13 +369,12 @@ static int create_register_callback (llist_t **list, /* {{{ */
 {
        callback_func_t *cf;
 
-       cf = (callback_func_t *) malloc (sizeof (*cf));
+       cf = calloc (1, sizeof (*cf));
        if (cf == NULL)
        {
-               ERROR ("plugin: create_register_callback: malloc failed.");
+               ERROR ("plugin: create_register_callback: calloc failed.");
                return (-1);
        }
-       memset (cf, 0, sizeof (*cf));
 
        cf->cf_callback = callback;
        if (ud == NULL)
@@ -477,7 +483,9 @@ static void *plugin_read_thread (void __attribute__((unused)) *args)
        {
                read_func_t *rf;
                plugin_ctx_t old_ctx;
+               cdtime_t start;
                cdtime_t now;
+               cdtime_t elapsed;
                int status;
                int rf_type;
                int rc;
@@ -556,6 +564,8 @@ static void *plugin_read_thread (void __attribute__((unused)) *args)
 
                DEBUG ("plugin_read_thread: Handling `%s'.", rf->rf_name);
 
+               start = cdtime ();
+
                old_ctx = plugin_set_ctx (rf->rf_ctx);
 
                if (rf_type == RF_SIMPLE)
@@ -599,8 +609,22 @@ static void *plugin_read_thread (void __attribute__((unused)) *args)
                /* update the ``next read due'' field */
                now = cdtime ();
 
+               /* calculate the time spent in the read function */
+               elapsed = (now - start);
+
+               if (elapsed > rf->rf_effective_interval)
+                       WARNING ("plugin_read_thread: read-function of the `%s' plugin took %.3f "
+                               "seconds, which is above its read interval (%.3f seconds). You might "
+                               "want to adjust the `Interval' or `ReadThreads' settings.",
+                               rf->rf_name, CDTIME_T_TO_DOUBLE(elapsed),
+                               CDTIME_T_TO_DOUBLE(rf->rf_effective_interval));
+
+               DEBUG ("plugin_read_thread: read-function of the `%s' plugin took "
+                               "%.6f seconds.",
+                               rf->rf_name, CDTIME_T_TO_DOUBLE(elapsed));
+
                DEBUG ("plugin_read_thread: Effective interval of the "
-                               "%s plugin is %.3f seconds.",
+                               "`%s' plugin is %.3f seconds.",
                                rf->rf_name,
                                CDTIME_T_TO_DOUBLE (rf->rf_effective_interval));
 
@@ -617,7 +641,7 @@ static void *plugin_read_thread (void __attribute__((unused)) *args)
                        rf->rf_next_read = now;
                }
 
-               DEBUG ("plugin_read_thread: Next read of the %s plugin at %.3f.",
+               DEBUG ("plugin_read_thread: Next read of the `%s' plugin at %.3f.",
                                rf->rf_name,
                                CDTIME_T_TO_DOUBLE (rf->rf_next_read));
 
@@ -631,8 +655,6 @@ static void *plugin_read_thread (void __attribute__((unused)) *args)
 
 static void start_read_threads (int num)
 {
-       int i;
-
        if (read_threads != NULL)
                return;
 
@@ -644,7 +666,7 @@ static void start_read_threads (int num)
        }
 
        read_threads_num = 0;
-       for (i = 0; i < num; i++)
+       for (int i = 0; i < num; i++)
        {
                if (pthread_create (read_threads + read_threads_num, NULL,
                                        plugin_read_thread, NULL) == 0)
@@ -661,8 +683,6 @@ static void start_read_threads (int num)
 
 static void stop_read_threads (void)
 {
-       int i;
-
        if (read_threads == NULL)
                return;
 
@@ -674,7 +694,7 @@ static void stop_read_threads (void)
        pthread_cond_broadcast (&read_cond);
        pthread_mutex_unlock (&read_lock);
 
-       for (i = 0; i < read_threads_num; i++)
+       for (int i = 0; i < read_threads_num; i++)
        {
                if (pthread_join (read_threads[i], NULL) != 0)
                {
@@ -846,8 +866,6 @@ static void *plugin_write_thread (void __attribute__((unused)) *args) /* {{{ */
 
 static void start_write_threads (size_t num) /* {{{ */
 {
-       size_t i;
-
        if (write_threads != NULL)
                return;
 
@@ -859,7 +877,7 @@ static void start_write_threads (size_t num) /* {{{ */
        }
 
        write_threads_num = 0;
-       for (i = 0; i < num; i++)
+       for (size_t i = 0; i < num; i++)
        {
                int status;
 
@@ -883,7 +901,7 @@ static void start_write_threads (size_t num) /* {{{ */
 static void stop_write_threads (void) /* {{{ */
 {
        write_queue_t *q;
-       int i;
+       size_t i;
 
        if (write_threads == NULL)
                return;
@@ -924,7 +942,7 @@ static void stop_write_threads (void) /* {{{ */
 
        if (i > 0)
        {
-               WARNING ("plugin: %i value list%s left after shutting down "
+               WARNING ("plugin: %zu value list%s left after shutting down "
                                "the write threads.",
                                i, (i == 1) ? " was" : "s were");
        }
@@ -935,17 +953,17 @@ static void stop_write_threads (void) /* {{{ */
  */
 void plugin_set_dir (const char *dir)
 {
-       if (plugindir != NULL)
-               free (plugindir);
+       sfree (plugindir);
 
        if (dir == NULL)
-               plugindir = NULL;
-       else if ((plugindir = strdup (dir)) == NULL)
        {
-               char errbuf[1024];
-               ERROR ("strdup failed: %s",
-                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               plugindir = NULL;
+               return;
        }
+
+       plugindir = strdup (dir);
+       if (plugindir == NULL)
+               ERROR ("plugin_set_dir: strdup(\"%s\") failed", dir);
 }
 
 static _Bool plugin_is_loaded (char const *name)
@@ -953,7 +971,7 @@ static _Bool plugin_is_loaded (char const *name)
        int status;
 
        if (plugins_loaded == NULL)
-               plugins_loaded = c_avl_create ((void *) strcasecmp);
+               plugins_loaded = c_avl_create ((int (*) (const void *, const void *)) strcasecmp);
        assert (plugins_loaded != NULL);
 
        status = c_avl_get (plugins_loaded, name, /* ret_value = */ NULL);
@@ -1083,6 +1101,7 @@ int plugin_load (char const *plugin_name, uint32_t flags)
                        /* success */
                        plugin_mark_loaded (plugin_name);
                        ret = 0;
+                       INFO ("plugin_load: plugin \"%s\" successfully loaded.", plugin_name);
                        break;
                }
                else
@@ -1219,14 +1238,13 @@ int plugin_register_read (const char *name,
        read_func_t *rf;
        int status;
 
-       rf = malloc (sizeof (*rf));
+       rf = calloc (1, sizeof (*rf));
        if (rf == NULL)
        {
-               ERROR ("plugin_register_read: malloc failed.");
+               ERROR ("plugin_register_read: calloc failed.");
                return (ENOMEM);
        }
 
-       memset (rf, 0, sizeof (read_func_t));
        rf->rf_callback = (void *) callback;
        rf->rf_udata.data = NULL;
        rf->rf_udata.free_func = NULL;
@@ -1247,20 +1265,19 @@ int plugin_register_read (const char *name,
 
 int plugin_register_complex_read (const char *group, const char *name,
                plugin_read_cb callback,
-               const struct timespec *interval,
+               cdtime_t interval,
                user_data_t *user_data)
 {
        read_func_t *rf;
        int status;
 
-       rf = malloc (sizeof (*rf));
+       rf = calloc (1,sizeof (*rf));
        if (rf == NULL)
        {
-               ERROR ("plugin_register_complex_read: malloc failed.");
+               ERROR ("plugin_register_complex_read: calloc failed.");
                return (ENOMEM);
        }
 
-       memset (rf, 0, sizeof (read_func_t));
        rf->rf_callback = (void *) callback;
        if (group != NULL)
                sstrncpy (rf->rf_group, group, sizeof (rf->rf_group));
@@ -1268,10 +1285,7 @@ int plugin_register_complex_read (const char *group, const char *name,
                rf->rf_group[0] = '\0';
        rf->rf_name = strdup (name);
        rf->rf_type = RF_COMPLEX;
-       if (interval != NULL)
-               rf->rf_interval = TIMESPEC_TO_CDTIME_T (interval);
-       else
-               rf->rf_interval = plugin_get_interval ();
+       rf->rf_interval = (interval != 0) ? interval : plugin_get_interval ();
 
        /* Set user data */
        if (user_data == NULL)
@@ -1302,11 +1316,104 @@ int plugin_register_write (const char *name,
                                (void *) callback, ud));
 } /* int plugin_register_write */
 
+static int plugin_flush_timeout_callback (user_data_t *ud)
+{
+       flush_callback_t *cb = ud->data;
+
+       return plugin_flush (cb->name, cb->timeout, /* identifier = */ NULL);
+} /* static int plugin_flush_callback */
+
+static void plugin_flush_timeout_callback_free (void *data)
+{
+       flush_callback_t *cb = data;
+
+       if (cb == NULL) return;
+
+       sfree (cb->name);
+       sfree (cb);
+} /* static void plugin_flush_callback_free */
+
+static char *plugin_flush_callback_name (const char *name)
+{
+       const char *flush_prefix = "flush/";
+       size_t prefix_size;
+       char *flush_name;
+       size_t name_size;
+
+       prefix_size = strlen(flush_prefix);
+       name_size = strlen(name);
+
+       flush_name = malloc (name_size + prefix_size + 1);
+       if (flush_name == NULL)
+       {
+               ERROR ("plugin_flush_callback_name: malloc failed.");
+               return (NULL);
+       }
+
+       sstrncpy (flush_name, flush_prefix, prefix_size + 1);
+       sstrncpy (flush_name + prefix_size, name, name_size + 1);
+
+       return flush_name;
+} /* static char *plugin_flush_callback_name */
+
 int plugin_register_flush (const char *name,
                plugin_flush_cb callback, user_data_t *ud)
 {
-       return (create_register_callback (&list_flush, name,
-                               (void *) callback, ud));
+       int status;
+       plugin_ctx_t ctx = plugin_get_ctx ();
+
+       status = create_register_callback (&list_flush, name,
+               (void *) callback, ud);
+       if (status != 0)
+               return status;
+
+       if (ctx.flush_interval != 0)
+       {
+               char *flush_name;
+               flush_callback_t *cb;
+
+               flush_name = plugin_flush_callback_name (name);
+               if (flush_name == NULL)
+                       return (-1);
+
+               cb = malloc(sizeof (*cb));
+               if (cb == NULL)
+               {
+                       ERROR ("plugin_register_flush: malloc failed.");
+                       sfree (flush_name);
+                       return (-1);
+               }
+
+               cb->name = strdup (name);
+               if (cb->name == NULL)
+               {
+                       ERROR ("plugin_register_flush: strdup failed.");
+                       sfree (cb);
+                       sfree (flush_name);
+                       return (-1);
+               }
+               cb->timeout = ctx.flush_timeout;
+
+               ud->data = cb;
+               ud->free_func = plugin_flush_timeout_callback_free;
+
+               status = plugin_register_complex_read (
+                       /* group     = */ "flush",
+                       /* name      = */ flush_name,
+                       /* callback  = */ plugin_flush_timeout_callback,
+                       /* interval  = */ ctx.flush_interval,
+                       /* user data = */ ud);
+
+               sfree (flush_name);
+               if (status != 0)
+               {
+                       sfree (cb->name);
+                       sfree (cb);
+                       return status;
+               }
+       }
+
+       return 0;
 } /* int plugin_register_flush */
 
 int plugin_register_missing (const char *name,
@@ -1347,7 +1454,6 @@ static void plugin_free_data_sets (void)
 int plugin_register_data_set (const data_set_t *ds)
 {
        data_set_t *ds_copy;
-       int i;
 
        if ((data_sets != NULL)
                        && (c_avl_get (data_sets, ds->type, NULL) == 0))
@@ -1362,20 +1468,20 @@ int plugin_register_data_set (const data_set_t *ds)
                        return (-1);
        }
 
-       ds_copy = (data_set_t *) malloc (sizeof (data_set_t));
+       ds_copy = malloc (sizeof (*ds_copy));
        if (ds_copy == NULL)
                return (-1);
        memcpy(ds_copy, ds, sizeof (data_set_t));
 
-       ds_copy->ds = (data_source_t *) malloc (sizeof (data_source_t)
+       ds_copy->ds = malloc (sizeof (*ds_copy->ds)
                        * ds->ds_num);
        if (ds_copy->ds == NULL)
        {
-               free (ds_copy);
+               sfree (ds_copy);
                return (-1);
        }
 
-       for (i = 0; i < ds->ds_num; i++)
+       for (size_t i = 0; i < ds->ds_num; i++)
                memcpy (ds_copy->ds + i, ds->ds + i, sizeof (data_source_t));
 
        return (c_avl_insert (data_sets, (void *) ds_copy->type, (void *) ds_copy));
@@ -1525,7 +1631,21 @@ int plugin_unregister_write (const char *name)
 
 int plugin_unregister_flush (const char *name)
 {
-       return (plugin_unregister (list_flush, name));
+       plugin_ctx_t ctx = plugin_get_ctx ();
+
+       if (ctx.flush_interval != 0)
+       {
+               char *flush_name;
+
+               flush_name = plugin_flush_callback_name (name);
+               if (flush_name != NULL)
+               {
+                       plugin_unregister_read(flush_name);
+                       sfree (flush_name);
+               }
+       }
+
+       return plugin_unregister (list_flush, name);
 }
 
 int plugin_unregister_missing (const char *name)
@@ -1564,11 +1684,12 @@ int plugin_unregister_notification (const char *name)
        return (plugin_unregister (list_notification, name));
 }
 
-void plugin_init_all (void)
+int plugin_init_all (void)
 {
        char const *chain_name;
        llentry_t *le;
        int status;
+       int ret = 0;
 
        /* Init the value cache */
        uc_init ();
@@ -1613,7 +1734,7 @@ void plugin_init_all (void)
        }
 
        if ((list_init == NULL) && (read_heap == NULL))
-               return;
+               return ret;
 
        /* Calling all init callbacks before checking if read callbacks
         * are available allows the init callbacks to register the read
@@ -1642,6 +1763,7 @@ void plugin_init_all (void)
                         * handling themselves. */
                        /* FIXME: Unload _all_ functions */
                        plugin_unregister_read (le->key);
+                       ret = -1;
                }
 
                le = le->next;
@@ -1663,6 +1785,7 @@ void plugin_init_all (void)
                if (num != -1)
                        start_read_threads ((num > 0) ? num : 5);
        }
+       return ret;
 } /* void plugin_init_all */
 
 /* TODO: Rename this function. */
@@ -1846,9 +1969,10 @@ int plugin_flush (const char *plugin, cdtime_t timeout, const char *identifier)
   return (0);
 } /* int plugin_flush */
 
-void plugin_shutdown_all (void)
+int plugin_shutdown_all (void)
 {
        llentry_t *le;
+       int ret = 0;  // Assume success.
 
        destroy_all_callbacks (&list_init);
 
@@ -1889,7 +2013,8 @@ void plugin_shutdown_all (void)
                 * after callback returns. */
                le = le->next;
 
-               (*callback) ();
+               if ((*callback) () != 0)
+                       ret = -1;
 
                plugin_set_ctx (old_ctx);
        }
@@ -1909,6 +2034,7 @@ void plugin_shutdown_all (void)
 
        plugin_free_loaded ();
        plugin_free_data_sets ();
+       return (ret);
 } /* void plugin_shutdown_all */
 
 int plugin_dispatch_missing (const value_list_t *vl) /* {{{ */
@@ -1964,8 +2090,10 @@ static int plugin_dispatch_values_internal (value_list_t *vl)
 
        int free_meta_data = 0;
 
-       if ((vl == NULL) || (vl->type[0] == 0)
-                       || (vl->values == NULL) || (vl->values_len < 1))
+       assert(vl);
+       assert(vl->plugin);
+
+       if (vl->type[0] == 0 || vl->values == NULL || vl->values_len < 1)
        {
                ERROR ("plugin_dispatch_values: Invalid value list "
                                "from plugin %s.", vl->plugin);
@@ -2032,8 +2160,8 @@ static int plugin_dispatch_values_internal (value_list_t *vl)
        if (ds->ds_num != vl->values_len)
        {
                ERROR ("plugin_dispatch_values: ds->type = %s: "
-                               "(ds->ds_num = %i) != "
-                               "(vl->values_len = %i)",
+                               "(ds->ds_num = %zu) != "
+                               "(vl->values_len = %zu)",
                                ds->type, ds->ds_num, vl->values_len);
                return (-1);
        }
@@ -2086,7 +2214,7 @@ static int plugin_dispatch_values_internal (value_list_t *vl)
                         * don't get confused.. */
                        if (saved_values != NULL)
                        {
-                               free (vl->values);
+                               sfree (vl->values);
                                vl->values     = saved_values;
                                vl->values_len = saved_values_len;
                        }
@@ -2115,7 +2243,7 @@ static int plugin_dispatch_values_internal (value_list_t *vl)
         * confused.. */
        if (saved_values != NULL)
        {
-               free (vl->values);
+               sfree (vl->values);
                vl->values     = saved_values;
                vl->values_len = saved_values_len;
        }
@@ -2230,7 +2358,7 @@ int plugin_dispatch_multivalue (value_list_t const *template, /* {{{ */
 
        assert (template->values_len == 1);
 
-  /* Calculate sum for Gauge to calculate percent if needed */
+       /* Calculate sum for Gauge to calculate percent if needed */
        if (DS_TYPE_GAUGE == store_type)        {
                va_start (ap, store_type);
                while (42)
@@ -2451,13 +2579,12 @@ static int plugin_notification_meta_add (notification_t *n,
     return (-1);
   }
 
-  meta = (notification_meta_t *) malloc (sizeof (notification_meta_t));
+  meta = calloc (1, sizeof (*meta));
   if (meta == NULL)
   {
-    ERROR ("plugin_notification_meta_add: malloc failed.");
+    ERROR ("plugin_notification_meta_add: calloc failed.");
     return (-1);
   }
-  memset (meta, 0, sizeof (notification_meta_t));
 
   sstrncpy (meta->name, name, sizeof (meta->name));
   meta->type = type;
@@ -2554,14 +2681,12 @@ int plugin_notification_meta_add_boolean (notification_t *n,
 int plugin_notification_meta_copy (notification_t *dst,
     const notification_t *src)
 {
-  notification_meta_t *meta;
-
   assert (dst != NULL);
   assert (src != NULL);
   assert (dst != src);
   assert ((src->meta == NULL) || (src->meta != dst->meta));
 
-  for (meta = src->meta; meta != NULL; meta = meta->next)
+  for (notification_meta_t *meta = src->meta; meta != NULL; meta = meta->next)
   {
     if (meta->type == NM_TYPE_STRING)
       plugin_notification_meta_add_string (dst, meta->name,
@@ -2601,7 +2726,11 @@ int plugin_notification_meta_free (notification_meta_t *n)
 
     if (this->type == NM_TYPE_STRING)
     {
-      free ((char *)this->nm_value.nm_string);
+      /* Assign to a temporary variable to work around nm_string's const
+       * modifier. */
+      void *tmp = (void *) this->nm_value.nm_string;
+
+      sfree (tmp);
       this->nm_value.nm_string = NULL;
     }
     sfree (this);
@@ -2708,7 +2837,7 @@ static void *plugin_thread_start (void *arg)
 
        plugin_set_ctx (plugin_thread->ctx);
 
-       free (plugin_thread);
+       sfree (plugin_thread);
 
        return start_routine (plugin_arg);
 } /* void *plugin_thread_start */
index cba298c..49edba2 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * collectd - src/plugin.h
+ * collectd - src/daemon/plugin.h
  * Copyright (C) 2005-2014  Florian octo Forster
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
 #define PLUGIN_H
 
 #include "collectd.h"
+
 #include "configfile.h"
 #include "meta_data.h"
 #include "utils_time.h"
 
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
+#include <pthread.h>
 
 #define PLUGIN_FLAGS_GLOBAL 0x0001
 
-#define DATA_MAX_NAME_LEN 64
+#ifndef DATA_MAX_NAME_LEN
+# define DATA_MAX_NAME_LEN 128
+#endif
 
 #define DS_TYPE_COUNTER  0
 #define DS_TYPE_GAUGE    1
@@ -97,7 +98,7 @@ typedef union value_u value_t;
 struct value_list_s
 {
        value_t *values;
-       int      values_len;
+       size_t   values_len;
        cdtime_t time;
        cdtime_t interval;
        char     host[DATA_MAX_NAME_LEN];
@@ -125,7 +126,7 @@ typedef struct data_source_s data_source_t;
 struct data_set_s
 {
        char           type[DATA_MAX_NAME_LEN];
-       int            ds_num;
+       size_t         ds_num;
        data_source_t *ds;
 };
 typedef struct data_set_s data_set_t;
@@ -177,6 +178,8 @@ typedef struct user_data_s user_data_t;
 struct plugin_ctx_s
 {
        cdtime_t interval;
+       cdtime_t flush_interval;
+       cdtime_t flush_timeout;
 };
 typedef struct plugin_ctx_s plugin_ctx_t;
 
@@ -238,10 +241,10 @@ void plugin_set_dir (const char *dir);
  */
 int plugin_load (const char *name, uint32_t flags);
 
-void plugin_init_all (void);
+int plugin_init_all (void);
 void plugin_read_all (void);
 int plugin_read_all_once (void);
-void plugin_shutdown_all (void);
+int plugin_shutdown_all (void);
 
 /*
  * NAME
@@ -293,7 +296,7 @@ int plugin_register_read (const char *name,
  * "plugin_register_complex_read" returns an error (non-zero). */
 int plugin_register_complex_read (const char *group, const char *name,
                plugin_read_cb callback,
-               const struct timespec *interval,
+               cdtime_t interval,
                user_data_t *user_data);
 int plugin_register_write (const char *name,
                plugin_write_cb callback, user_data_t *user_data);
index 4023a8f..34c222c 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 
 #include "plugin.h"
@@ -102,7 +103,6 @@ static void parse_line (char *buf)
   char  *fields[64];
   size_t fields_num;
   data_set_t *ds;
-  int i;
 
   fields_num = strsplit (buf, fields, 64);
   if (fields_num < 2)
@@ -112,25 +112,27 @@ static void parse_line (char *buf)
   if (fields[0][0] == '#')
     return;
 
-  ds = (data_set_t *) malloc (sizeof (data_set_t));
+  ds = calloc (1, sizeof (*ds));
   if (ds == NULL)
     return;
 
-  memset (ds, '\0', sizeof (data_set_t));
-
   sstrncpy (ds->type, fields[0], sizeof (ds->type));
 
   ds->ds_num = fields_num - 1;
   ds->ds = (data_source_t *) calloc (ds->ds_num, sizeof (data_source_t));
   if (ds->ds == NULL)
+  {
+    sfree (ds);
     return;
+  }
 
-  for (i = 0; i < ds->ds_num; i++)
+  for (size_t i = 0; i < ds->ds_num; i++)
     if (parse_ds (ds->ds + i, fields[i + 1], strlen (fields[i + 1])) != 0)
     {
-      sfree (ds->ds);
-      ERROR ("types_list: parse_line: Cannot parse data source #%i "
+      ERROR ("types_list: parse_line: Cannot parse data source #%zu "
          "of data set %s", i, ds->type);
+      sfree (ds->ds);
+      sfree (ds);
       return;
     }
 
index fcfbb94..e1c41ec 100644 (file)
  *   Florian octo Forster <octo at collectd.org>
  **/
 
-#include "config.h"
-
 #include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
 #include <assert.h>
 
 #include "utils_avltree.h"
@@ -485,7 +481,7 @@ c_avl_tree_t *c_avl_create (int (*compare) (const void *, const void *))
        if (compare == NULL)
                return (NULL);
 
-       if ((t = (c_avl_tree_t *) malloc (sizeof (c_avl_tree_t))) == NULL)
+       if ((t = malloc (sizeof (*t))) == NULL)
                return (NULL);
 
        t->root = NULL;
@@ -509,7 +505,7 @@ int c_avl_insert (c_avl_tree_t *t, void *key, void *value)
        c_avl_node_t *nptr;
        int cmp;
 
-       if ((new = (c_avl_node_t *) malloc (sizeof (c_avl_node_t))) == NULL)
+       if ((new = malloc (sizeof (*new))) == NULL)
                return (-1);
 
        new->key = key;
@@ -665,10 +661,9 @@ c_avl_iterator_t *c_avl_get_iterator (c_avl_tree_t *t)
        if (t == NULL)
                return (NULL);
 
-       iter = (c_avl_iterator_t *) malloc (sizeof (c_avl_iterator_t));
+       iter = calloc (1, sizeof (*iter));
        if (iter == NULL)
                return (NULL);
-       memset (iter, '\0', sizeof (c_avl_iterator_t));
        iter->tree = t;
 
        return (iter);
index 1e0f271..43e94cf 100644 (file)
@@ -42,7 +42,7 @@ typedef struct c_avl_iterator_s c_avl_iterator_t;
  *
  * PARAMETERS
  *   `compare'  The function-pointer `compare' is used to compare two keys. It
- *              has to return less than zero if it's first argument is smaller
+ *              has to return less than zero if its first argument is smaller
  *              then the second argument, more than zero if the first argument
  *              is bigger than the second argument and zero if they are equal.
  *              If your keys are char-pointers, you can use the `strcmp'
@@ -131,7 +131,7 @@ int c_avl_get (c_avl_tree_t *t, const void *key, void **value);
  *   c_avl_pick
  *
  * DESCRIPTION
- *   Remove a (pseudo-)random element from the tree and return it's `key' and
+ *   Remove a (pseudo-)random element from the tree and return its `key' and
  *   `value'. Entries are not returned in any particular order. This function
  *   is intended for cache-flushes that don't care about the order but simply
  *   want to remove all elements, one at a time.
index 2a8244c..150dd1b 100644 (file)
  *   Florian octo Forster <octo at collectd.org>
  */
 
-#include "testing.h"
+#include "common.h" /* STATIC_ARRAY_SIZE */
 #include "collectd.h"
+
+#include "testing.h"
 #include "utils_avltree.h"
 
 static int compare_total_count = 0;
@@ -42,30 +44,98 @@ static int compare_callback (void const *v0, void const *v1)
 
 DEF_TEST(success)
 {
+  struct {
+    char *key;
+    char *value;
+  } cases[] = {
+    {"Eeph7chu", "vai1reiV"},
+    {"igh3Paiz", "teegh1Ee"},
+    {"caip6Uu8", "ooteQu8n"},
+    {"Aech6vah", "AijeeT0l"},
+    {"Xah0et2L", "gah8Taep"},
+    {"BocaeB8n", "oGaig8io"},
+    {"thai8AhM", "ohjeFo3f"},
+    {"ohth6ieC", "hoo8ieWo"},
+    {"aej7Woow", "phahuC2s"},
+    {"Hai8ier2", "Yie6eimi"},
+    {"phuXi3Li", "JaiF7ieb"},
+    {"Shaig5ef", "aihi5Zai"},
+    {"voh6Aith", "Oozaeto0"},
+    {"zaiP5kie", "seep5veM"},
+    {"pae7ba7D", "chie8Ojo"},
+    {"Gou2ril3", "ouVoo0ha"},
+    {"lo3Thee3", "ahDu4Zuj"},
+    {"Rah8kohv", "ieShoc7E"},
+    {"ieN5engi", "Aevou1ah"},
+    {"ooTe4OhP", "aingai5Y"},
+  };
+
   c_avl_tree_t *t;
-  char key_orig[] = "foo";
-  char value_orig[] = "bar";
-  char *key_ret = NULL;
-  char *value_ret = NULL;
 
   RESET_COUNTS ();
-  t = c_avl_create (compare_callback);
-  OK (t != NULL);
+  CHECK_NOT_NULL (t = c_avl_create (compare_callback));
+
+  /* insert */
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+  {
+    char *key;
+    char *value;
 
-  OK (c_avl_insert (t, key_orig, value_orig) == 0);
-  OK (c_avl_size (t) == 1);
+    CHECK_NOT_NULL (key = strdup (cases[i].key));
+    CHECK_NOT_NULL (value = strdup (cases[i].value));
+
+    CHECK_ZERO (c_avl_insert (t, key, value));
+    EXPECT_EQ_INT ((int) (i + 1), c_avl_size (t));
+  }
 
   /* Key already exists. */
-  OK (c_avl_insert (t, "foo", "qux") > 0);
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+    EXPECT_EQ_INT (1, c_avl_insert (t, cases[i].key, cases[i].value));
+
+  /* get */
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+  {
+    char *value_ret = NULL;
+
+    CHECK_ZERO (c_avl_get (t, cases[i].key, (void *) &value_ret));
+    EXPECT_EQ_STR (cases[i].value, value_ret);
+  }
+
+  /* remove half */
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases) / 2; i++)
+  {
+    char *key = NULL;
+    char *value = NULL;
+
+    int expected_size = (int) (STATIC_ARRAY_SIZE (cases) - (i + 1));
+
+    CHECK_ZERO (c_avl_remove (t, cases[i].key, (void *) &key, (void *) &value));
+
+    EXPECT_EQ_STR (cases[i].key, key);
+    EXPECT_EQ_STR (cases[i].value, value);
+
+    free (key);
+    free (value);
+
+    EXPECT_EQ_INT (expected_size, c_avl_size (t));
+  }
+
+  /* pick the other half */
+  for (size_t i = STATIC_ARRAY_SIZE (cases) / 2; i < STATIC_ARRAY_SIZE (cases); i++)
+  {
+    char *key = NULL;
+    char *value = NULL;
+
+    int expected_size = (int) (STATIC_ARRAY_SIZE (cases) - (i + 1));
+
+    EXPECT_EQ_INT (expected_size + 1, c_avl_size (t));
+    EXPECT_EQ_INT (0, c_avl_pick (t, (void *) &key, (void *) &value));
 
-  OK (c_avl_get (t, "foo", (void *) &value_ret) == 0);
-  OK (value_ret == &value_orig[0]);
+    free (key);
+    free (value);
 
-  key_ret = value_ret = NULL;
-  OK (c_avl_remove (t, "foo", (void *) &key_ret, (void *) &value_ret) == 0);
-  OK (key_ret == &key_orig[0]);
-  OK (value_ret == &value_orig[0]);
-  OK (c_avl_size (t) == 0);
+    EXPECT_EQ_INT (expected_size, c_avl_size (t));
+  }
 
   c_avl_destroy (t);
 
index c4cef28..7c1fa41 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * collectd - src/utils_cache.c
  * Copyright (C) 2007-2010  Florian octo Forster
+ * Copyright (C) 2016       Sebastian tokkee Harl
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  *
  * Authors:
  *   Florian octo Forster <octo at collectd.org>
+ *   Sebastian tokkee Harl <sh at tokkee.org>
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_avltree.h"
 #include "meta_data.h"
 
 #include <assert.h>
-#include <pthread.h>
 
 typedef struct cache_entry_s
 {
        char name[6 * DATA_MAX_NAME_LEN];
-       int        values_num;
+       size_t     values_num;
        gauge_t   *values_gauge;
        value_t   *values_raw;
        /* Time contained in the package
@@ -47,7 +49,7 @@ typedef struct cache_entry_s
         * (for purging old entries) */
        cdtime_t last_update;
        /* Interval in which the data is collected
-        * (for purding old entries) */
+        * (for purging old entries) */
        cdtime_t interval;
        int state;
        int hits;
@@ -68,6 +70,13 @@ typedef struct cache_entry_s
        meta_data_t *meta;
 } cache_entry_t;
 
+struct uc_iter_s {
+  c_avl_iterator_t *iter;
+
+  char *name;
+  cache_entry_t *entry;
+};
+
 static c_avl_tree_t   *cache_tree = NULL;
 static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
 
@@ -79,17 +88,16 @@ static int cache_compare (const cache_entry_t *a, const cache_entry_t *b)
   return (strcmp (a->name, b->name));
 } /* int cache_compare */
 
-static cache_entry_t *cache_alloc (int values_num)
+static cache_entry_t *cache_alloc (size_t values_num)
 {
   cache_entry_t *ce;
 
-  ce = (cache_entry_t *) malloc (sizeof (cache_entry_t));
+  ce = calloc (1, sizeof (*ce));
   if (ce == NULL)
   {
-    ERROR ("utils_cache: cache_alloc: malloc failed.");
+    ERROR ("utils_cache: cache_alloc: calloc failed.");
     return (NULL);
   }
-  memset (ce, '\0', sizeof (cache_entry_t));
   ce->values_num = values_num;
 
   ce->values_gauge = calloc (values_num, sizeof (*ce->values_gauge));
@@ -128,9 +136,7 @@ static void cache_free (cache_entry_t *ce)
 
 static void uc_check_range (const data_set_t *ds, cache_entry_t *ce)
 {
-  int i;
-
-  for (i = 0; i < ds->ds_num; i++)
+  for (size_t i = 0; i < ds->ds_num; i++)
   {
     if (isnan (ce->values_gauge[i]))
       continue;
@@ -144,7 +150,6 @@ static void uc_check_range (const data_set_t *ds, cache_entry_t *ce)
 static int uc_insert (const data_set_t *ds, const value_list_t *vl,
     const char *key)
 {
-  int i;
   char *key_copy;
   cache_entry_t *ce;
 
@@ -161,13 +166,13 @@ static int uc_insert (const data_set_t *ds, const value_list_t *vl,
   if (ce == NULL)
   {
     sfree (key_copy);
-    ERROR ("uc_insert: cache_alloc (%i) failed.", ds->ds_num);
+    ERROR ("uc_insert: cache_alloc (%zu) failed.", ds->ds_num);
     return (-1);
   }
 
   sstrncpy (ce->name, key, sizeof (ce->name));
 
-  for (i = 0; i < ds->ds_num; i++)
+  for (size_t i = 0; i < ds->ds_num; i++)
   {
     switch (ds->ds[i].type)
     {
@@ -246,8 +251,7 @@ int uc_check_timeout (void)
   c_avl_iterator_t *iter;
 
   int status;
-  int i;
-  
+
   pthread_mutex_lock (&cache_lock);
 
   now = cdtime ();
@@ -264,7 +268,7 @@ int uc_check_timeout (void)
       continue;
 
     /* If entry has not been updated, add to `keys' array */
-    tmp = (char **) realloc ((void *) keys,
+    tmp = realloc ((void *) keys,
        (keys_len + 1) * sizeof (char *));
     if (tmp == NULL)
     {
@@ -318,7 +322,7 @@ int uc_check_timeout (void)
    * including plugin specific meta data, rates, history, …. This must be done
    * without holding the lock, otherwise we will run into a deadlock if a
    * plugin calls the cache interface. */
-  for (i = 0; i < keys_len; i++)
+  for (int i = 0; i < keys_len; i++)
   {
     value_list_t vl = VALUE_LIST_INIT;
 
@@ -343,7 +347,7 @@ int uc_check_timeout (void)
    * the timestamp again, so in theory it is possible we remove a value after
    * it is updated here. */
   pthread_mutex_lock (&cache_lock);
-  for (i = 0; i < keys_len; i++)
+  for (int i = 0; i < keys_len; i++)
   {
     key = NULL;
     ce = NULL;
@@ -375,7 +379,6 @@ int uc_update (const data_set_t *ds, const value_list_t *vl)
   char name[6 * DATA_MAX_NAME_LEN];
   cache_entry_t *ce = NULL;
   int status;
-  int i;
 
   if (FORMAT_VL (name, sizeof (name), vl) != 0)
   {
@@ -407,29 +410,13 @@ int uc_update (const data_set_t *ds, const value_list_t *vl)
     return (-1);
   }
 
-  for (i = 0; i < ds->ds_num; i++)
+  for (size_t i = 0; i < ds->ds_num; i++)
   {
     switch (ds->ds[i].type)
     {
       case DS_TYPE_COUNTER:
        {
-         counter_t diff;
-
-         /* check if the counter has wrapped around */
-         if (vl->values[i].counter < ce->values_raw[i].counter)
-         {
-           if (ce->values_raw[i].counter <= 4294967295U)
-             diff = (4294967295U - ce->values_raw[i].counter)
-               + vl->values[i].counter;
-           else
-             diff = (18446744073709551615ULL - ce->values_raw[i].counter)
-               + vl->values[i].counter;
-         }
-         else /* counter has NOT wrapped around */
-         {
-           diff = vl->values[i].counter - ce->values_raw[i].counter;
-         }
-
+         counter_t diff = counter_diff (ce->values_raw[i].counter, vl->values[i].counter);
          ce->values_gauge[i] = ((double) diff)
            / (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
          ce->values_raw[i].counter = vl->values[i].counter;
@@ -443,9 +430,7 @@ int uc_update (const data_set_t *ds, const value_list_t *vl)
 
       case DS_TYPE_DERIVE:
        {
-         derive_t diff;
-
-         diff = vl->values[i].derive - ce->values_raw[i].derive;
+         derive_t diff = vl->values[i].derive - ce->values_raw[i].derive;
 
          ce->values_gauge[i] = ((double) diff)
            / (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
@@ -467,14 +452,14 @@ 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[%i] = %lf", name, i, ce->values_gauge[i]);
+    DEBUG ("uc_update: %s: ds[%zu] = %lf", name, i, ce->values_gauge[i]);
   } /* for (i) */
 
   /* Update the history if it exists. */
   if (ce->history != NULL)
   {
     assert (ce->history_index < ce->history_length);
-    for (i = 0; i < ce->values_num; i++)
+    for (size_t i = 0; i < ce->values_num; i++)
     {
       size_t hist_idx = (ce->values_num * ce->history_index) + i;
       ce->history[hist_idx] = ce->values_gauge[i];
@@ -517,7 +502,7 @@ int uc_get_rate_by_name (const char *name, gauge_t **ret_values, size_t *ret_val
     else
     {
       ret_num = ce->values_num;
-      ret = (gauge_t *) malloc (ret_num * sizeof (gauge_t));
+      ret = malloc (ret_num * sizeof (*ret));
       if (ret == NULL)
       {
         ERROR ("utils_cache: uc_get_rate_by_name: malloc failed.");
@@ -567,7 +552,7 @@ gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl)
    * values are returned. */
   if (ret_num != (size_t) ds->ds_num)
   {
-    ERROR ("utils_cache: uc_get_rate: ds[%s] has %i values, "
+    ERROR ("utils_cache: uc_get_rate: ds[%s] has %zu values, "
        "but uc_get_rate_by_name returned %zu.",
        ds->type, ds->ds_num, ret_num);
     sfree (ret);
@@ -654,9 +639,7 @@ int uc_get_names (char ***ret_names, cdtime_t **ret_times, size_t *ret_number)
 
   if (status != 0)
   {
-    size_t i;
-
-    for (i = 0; i < number; i++)
+    for (size_t i = 0; i < number; i++)
     {
       sfree (names[i]);
     }
@@ -731,7 +714,6 @@ int uc_get_history_by_name (const char *name,
     gauge_t *ret_history, size_t num_steps, size_t num_ds)
 {
   cache_entry_t *ce = NULL;
-  size_t i;
   int status = 0;
 
   pthread_mutex_lock (&cache_lock);
@@ -763,7 +745,7 @@ int uc_get_history_by_name (const char *name,
       return (-ENOMEM);
     }
 
-    for (i = ce->history_length * ce->values_num;
+    for (size_t i = ce->history_length * ce->values_num;
        i < (num_steps * ce->values_num);
        i++)
       tmp[i] = NAN;
@@ -773,7 +755,7 @@ int uc_get_history_by_name (const char *name,
   } /* if (ce->history_length < num_steps) */
 
   /* Copy the values to the output buffer. */
-  for (i = 0; i < num_steps; i++)
+  for (size_t i = 0; i < num_steps; i++)
   {
     size_t src_index;
     size_t dst_index;
@@ -887,6 +869,102 @@ int uc_inc_hits (const data_set_t *ds, const value_list_t *vl, int step)
 } /* int uc_inc_hits */
 
 /*
+ * Iterator interface
+ */
+uc_iter_t *uc_get_iterator (void)
+{
+  uc_iter_t *iter;
+
+  iter = (uc_iter_t *) calloc(1, sizeof (*iter));
+  if (iter == NULL)
+    return (NULL);
+
+  pthread_mutex_lock (&cache_lock);
+
+  iter->iter = c_avl_get_iterator (cache_tree);
+  if (iter->iter == NULL)
+  {
+    free (iter);
+    return (NULL);
+  }
+
+  return (iter);
+} /* uc_iter_t *uc_get_iterator */
+
+int uc_iterator_next (uc_iter_t *iter, char **ret_name)
+{
+  int status;
+
+  if (iter == NULL)
+    return (-1);
+
+  while ((status = c_avl_iterator_next (iter->iter,
+         (void *) &iter->name, (void *) &iter->entry)) == 0)
+  {
+    if (iter->entry->state == STATE_MISSING)
+      continue;
+
+    break;
+  }
+  if (status != 0) {
+    iter->name = NULL;
+    iter->entry = NULL;
+    return (-1);
+  }
+
+  if (ret_name != NULL)
+    *ret_name = iter->name;
+
+  return (0);
+} /* int uc_iterator_next */
+
+void uc_iterator_destroy (uc_iter_t *iter)
+{
+  if (iter == NULL)
+    return;
+
+  c_avl_iterator_destroy (iter->iter);
+  pthread_mutex_unlock (&cache_lock);
+
+  free (iter);
+} /* void uc_iterator_destroy */
+
+int uc_iterator_get_time (uc_iter_t *iter, cdtime_t *ret_time)
+{
+  if ((iter == NULL) || (iter->entry == NULL) || (ret_time == NULL))
+    return (-1);
+
+  *ret_time = iter->entry->last_time;
+  return (0);
+} /* int uc_iterator_get_name */
+
+int uc_iterator_get_values (uc_iter_t *iter, value_t **ret_values, size_t *ret_num)
+{
+  if ((iter == NULL) || (iter->entry == NULL)
+      || (ret_values == NULL) || (ret_num == NULL))
+    return (-1);
+
+  *ret_values = calloc (iter->entry->values_num, sizeof(*iter->entry->values_raw));
+  if (*ret_values == NULL)
+    return (-1);
+  for (size_t i = 0; i < iter->entry->values_num; ++i)
+    *ret_values[i] = iter->entry->values_raw[i];
+
+  *ret_num = iter->entry->values_num;
+
+  return (0);
+} /* int uc_iterator_get_values */
+
+int uc_iterator_get_interval (uc_iter_t *iter, cdtime_t *ret_interval)
+{
+  if ((iter == NULL) || (iter->entry == NULL) || (ret_interval == NULL))
+    return (-1);
+
+  *ret_interval = iter->entry->interval;
+  return (0);
+} /* int uc_iterator_get_name */
+
+/*
  * Meta data interface
  */
 /* XXX: This function will acquire `cache_lock' but will not free it! */
index 75bfc42..93c2519 100644 (file)
@@ -1,6 +1,7 @@
 /**
- * collectd - src/utils_cache.h
+ * collectd - utils_cache.h
  * Copyright (C) 2007       Florian octo Forster
+ * Copyright (C) 2016       Sebastian tokkee Harl
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -22,6 +23,7 @@
  *
  * Authors:
  *   Florian octo Forster <octo at collectd.org>
+ *   Sebastian tokkee Harl <sh at tokkee.org>
  **/
 
 #ifndef UTILS_CACHE_H
@@ -55,6 +57,53 @@ int uc_get_history_by_name (const char *name,
     gauge_t *ret_history, size_t num_steps, size_t num_ds);
 
 /*
+ * Iterator interface
+ */
+struct uc_iter_s;
+typedef struct uc_iter_s uc_iter_t;
+
+/*
+ * NAME
+ *   uc_get_iterator
+ *
+ * DESCRIPTION
+ *   Create an iterator for the cache. It will hold the cache lock until it's
+ *   destroyed.
+ *
+ * RETURN VALUE
+ *   An iterator object on success or NULL else.
+ */
+uc_iter_t *uc_get_iterator (void);
+
+/*
+ * NAME
+ *   uc_iterator_next
+ *
+ * DESCRIPTION
+ *   Advance the iterator to the next positiion and (optionally) returns the
+ *   name of the entry.
+ *
+ * PARAMETERS
+ *   `iter'     The iterator object to advance.
+ *   `ret_name' Pointer to a string where to store the name. The returned
+ *              value is a copy of the value and has to be freed by the
+ *              caller.
+ *
+ * RETURN VALUE
+ *   Zero upon success or non-zero if the iterator ie NULL or no further
+ *   values are available.
+ */
+int uc_iterator_next (uc_iter_t *iter, char **ret_name);
+void uc_iterator_destroy (uc_iter_t *iter);
+
+/* Return the timestamp of the value at the current position. */
+int uc_iterator_get_time (uc_iter_t *iter, cdtime_t *ret_time);
+/* Return the (raw) value at the current position. */
+int uc_iterator_get_values (uc_iter_t *iter, value_t **ret_values, size_t *ret_num);
+/* Return the interval of the value at the current position. */
+int uc_iterator_get_interval (uc_iter_t *iter, cdtime_t *ret_interval);
+
+/*
  * Meta data interface
  */
 int uc_meta_data_exists (const value_list_t *vl, const char *key);
index 6c78d64..1080c80 100644 (file)
@@ -26,7 +26,8 @@
 
 #include "utils_cache.h"
 
-gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl)
+gauge_t *uc_get_rate (__attribute__((unused)) data_set_t const *ds,
+                      __attribute__((unused)) value_list_t const *vl)
 {
   return (NULL);
 }
index 6193614..d028c06 100644 (file)
@@ -27,6 +27,7 @@
  **/
 
 #include "collectd.h"
+
 #include "utils_complain.h"
 #include "plugin.h"
 
@@ -102,4 +103,3 @@ void c_do_release (int level, c_complain_t *c, const char *format, ...)
 } /* c_release */
 
 /* vim: set sw=4 ts=4 tw=78 noexpandtab : */
-
index 390f961..9d96d35 100644 (file)
@@ -66,6 +66,7 @@ typedef struct
  *   `c'      Identifier for the complaint.
  *   `format' Message format - see the documentation of printf(3).
  */
+__attribute__ ((format(printf,3,4)))
 void c_complain (int level, c_complain_t *c, const char *format, ...);
 
 /*
@@ -80,6 +81,7 @@ void c_complain (int level, c_complain_t *c, const char *format, ...);
  *
  *   See `c_complain' for further details and a description of the parameters.
  */
+__attribute__ ((format(printf,3,4)))
 void c_complain_once (int level, c_complain_t *c, const char *format, ...);
 
 /*
@@ -101,6 +103,7 @@ void c_complain_once (int level, c_complain_t *c, const char *format, ...);
  *
  *   See `c_complain' for a description of the parameters.
  */
+__attribute__ ((format(printf,3,4)))
 void c_do_release (int level, c_complain_t *c, const char *format, ...);
 #define c_release(level, c, ...) \
        do { \
index 1b5dca7..8637581 100644 (file)
@@ -25,7 +25,6 @@
  **/
 
 #include <stdlib.h>
-#include <string.h>
 #include <errno.h>
 #include <assert.h>
 #include <pthread.h>
@@ -112,14 +111,13 @@ c_heap_t *c_heap_create (int (*compare) (const void *, const void *))
   if (compare == NULL)
     return (NULL);
 
-  h = malloc (sizeof (*h));
+  h = calloc (1, sizeof (*h));
   if (h == NULL)
     return (NULL);
 
-  memset (h, 0, sizeof (*h));
   pthread_mutex_init (&h->lock, /* attr = */ NULL);
   h->compare = compare;
-  
+
   h->list = NULL;
   h->list_len = 0;
   h->list_size = 0;
@@ -174,7 +172,7 @@ int c_heap_insert (c_heap_t *h, void *ptr)
 
   /* Reorganize the heap from bottom up. */
   reheap (h, /* parent of this node = */ (index - 1) / 2, DIR_UP);
-  
+
   pthread_mutex_unlock (&h->lock);
   return (0);
 } /* int c_heap_insert */
index 6d71c43..243554c 100644 (file)
@@ -39,7 +39,7 @@ typedef struct c_heap_s c_heap_t;
  *
  * PARAMETERS
  *   `compare'  The function-pointer `compare' is used to compare two keys. It
- *              has to return less than zero if it's first argument is smaller
+ *              has to return less than zero if its first argument is smaller
  *              then the second argument, more than zero if the first argument
  *              is bigger than the second argument and zero if they are equal.
  *              If your keys are char-pointers, you can use the `strcmp'
index 53d0fba..54a9613 100644 (file)
@@ -24,8 +24,9 @@
  *   Florian octo Forster <octo at collectd.org>
  */
 
-#include "testing.h"
 #include "collectd.h"
+
+#include "testing.h"
 #include "utils_heap.h"
 
 static int compare (void const *v0, void const *v1)
@@ -44,14 +45,13 @@ static int compare (void const *v0, void const *v1)
 DEF_TEST(simple)
 {
   int values[] = { 9, 5, 6, 1, 3, 4, 0, 8, 2, 7 };
-  int i;
   c_heap_t *h;
 
   CHECK_NOT_NULL(h = c_heap_create (compare));
-  for (i = 0; i < 10; i++)
+  for (int i = 0; i < 10; i++)
     CHECK_ZERO(c_heap_insert (h, &values[i]));
 
-  for (i = 0; i < 5; i++)
+  for (int i = 0; i < 5; i++)
   {
     int *ret = NULL;
     CHECK_NOT_NULL(ret = c_heap_get_root(h));
@@ -64,7 +64,7 @@ DEF_TEST(simple)
   CHECK_ZERO(c_heap_insert (h, &values[4] /* = 3 */));
   CHECK_ZERO(c_heap_insert (h, &values[5] /* = 4 */));
 
-  for (i = 0; i < 10; i++)
+  for (int i = 0; i < 10; i++)
   {
     int *ret = NULL;
     CHECK_NOT_NULL(ret = c_heap_get_root(h));
index 692a1e5..ff73ad7 100644 (file)
@@ -27,7 +27,7 @@
  **/
 /**
  * Usage:
- * 
+ *
  * Define plugin's global pointer variable of type ignorelist_t:
  *   ignorelist_t *myconfig_ignore;
  * If you know the state of the global ignore (IgnoreSelected),
@@ -88,50 +88,43 @@ static inline void ignorelist_append (ignorelist_t *il, ignorelist_item_t *item)
 }
 
 #if HAVE_REGEX_H
-static int ignorelist_append_regex(ignorelist_t *il, const char *entry)
+static int ignorelist_append_regex(ignorelist_t *il, const char *re_str)
 {
        regex_t *re;
-       ignorelist_item_t *item;
+       ignorelist_item_t *entry;
        int status;
 
-       /* create buffer */
-       re = malloc (sizeof (*re));
+       re = calloc (1, sizeof (*re));
        if (re == NULL)
        {
-               ERROR ("ignorelist_append_regex: malloc failed.");
-               return ENOMEM;
+               ERROR ("ignorelist_append_regex: calloc failed.");
+               return (ENOMEM);
        }
-       memset (re, 0, sizeof (*re));
 
-       /* compile regex */
-       status = regcomp (re, entry, REG_EXTENDED);
+       status = regcomp (re, re_str, REG_EXTENDED);
        if (status != 0)
        {
                char errbuf[1024];
-
                (void) regerror (status, re, errbuf, sizeof (errbuf));
-               ERROR ("ignorelist_append_regex: Compiling regular expression \"%s\" failed: %s", entry, errbuf);
+               ERROR ("utils_ignorelist: regcomp failed: %s", errbuf);
+               ERROR ("ignorelist_append_regex: Compiling regular expression \"%s\" failed: %s", re_str, errbuf);
                sfree (re);
-               return status;
+               return (status);
        }
 
-       /* create new entry */
-       item = malloc (sizeof (*item));
-       if (item == NULL)
+       entry = calloc (1, sizeof (*entry));
+       if (entry == NULL)
        {
-               ERROR ("ignorelist_append_regex: malloc failed.");
+               ERROR ("ignorelist_append_regex: calloc failed.");
                regfree (re);
                sfree (re);
-               return ENOMEM;
+               return (ENOMEM);
        }
-       memset (item, 0, sizeof (*item));
-       item->rmatch = re;
-
-       /* append new entry */
-       ignorelist_append (il, item);
+       entry->rmatch = re;
 
+       ignorelist_append (il, entry);
        return (0);
-} /* int ignorelist_append_regex(ignorelist_t *il, const char *entry) */
+} /* int ignorelist_append_regex */
 #endif
 
 static int ignorelist_append_string(ignorelist_t *il, const char *entry)
@@ -139,12 +132,11 @@ static int ignorelist_append_string(ignorelist_t *il, const char *entry)
        ignorelist_item_t *new;
 
        /* create new entry */
-       if ((new = malloc(sizeof(ignorelist_item_t))) == NULL )
+       if ((new = calloc(1, sizeof (*new))) == NULL )
        {
                ERROR ("cannot allocate new entry");
                return (1);
        }
-       memset (new, '\0', sizeof(ignorelist_item_t));
        new->smatch = sstrdup(entry);
 
        /* append new entry */
@@ -199,10 +191,9 @@ ignorelist_t *ignorelist_create (int invert)
 {
        ignorelist_t *il;
 
-       il = malloc (sizeof (*il));
+       il = calloc (1, sizeof (*il));
        if (il == NULL)
                return NULL;
-       memset (il, 0, sizeof (*il));
 
        /*
         * ->ignore == 0  =>  collect
@@ -244,7 +235,6 @@ void ignorelist_free (ignorelist_t *il)
        }
 
        sfree (il);
-       il = NULL;
 } /* void ignorelist_destroy (ignorelist_t *il) */
 
 /*
@@ -263,7 +253,7 @@ void ignorelist_set_invert (ignorelist_t *il, int invert)
 
 /*
  * append entry into ignorelist_t
- * return 1 for success
+ * return 0 for success
  */
 int ignorelist_add (ignorelist_t *il, const char *entry)
 {
@@ -314,8 +304,6 @@ int ignorelist_add (ignorelist_t *il, const char *entry)
  */
 int ignorelist_match (ignorelist_t *il, const char *entry)
 {
-       ignorelist_item_t *traverse;
-
        /* if no entries, collect all */
        if ((il == NULL) || (il->head == NULL))
                return (0);
@@ -324,7 +312,7 @@ int ignorelist_match (ignorelist_t *il, const char *entry)
                return (0);
 
        /* traverse list and check entries */
-       for (traverse = il->head; traverse != NULL; traverse = traverse->next)
+       for (ignorelist_item_t *traverse = il->head; traverse != NULL; traverse = traverse->next)
        {
 #if HAVE_REGEX_H
                if (traverse->rmatch != NULL)
index 4265286..6027338 100644 (file)
@@ -24,8 +24,6 @@
  *   Florian Forster <octo at collectd.org>
  */
 
-#include "config.h"
-
 #include <stdlib.h>
 #include <string.h>
 
@@ -48,12 +46,10 @@ llist_t *llist_create (void)
 {
        llist_t *ret;
 
-       ret = (llist_t *) malloc (sizeof (llist_t));
+       ret = calloc (1, sizeof (*ret));
        if (ret == NULL)
                return (NULL);
 
-       memset (ret, '\0', sizeof (llist_t));
-
        return (ret);
 }
 
@@ -78,7 +74,7 @@ llentry_t *llentry_create (char *key, void *value)
 {
        llentry_t *e;
 
-       e = (llentry_t *) malloc (sizeof (llentry_t));
+       e = malloc (sizeof (*e));
        if (e)
        {
                e->key   = key;
index 3847284..914b6e2 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -63,7 +64,7 @@ static char *match_substr (const char *str, int begin, int end)
   }
 
   ret_len = end - begin;
-  ret = (char *) malloc (sizeof (char) * (ret_len + 1));
+  ret = malloc (ret_len + 1);
   if (ret == NULL)
   {
     ERROR ("utils_match: match_substr: malloc failed.");
@@ -238,10 +239,9 @@ cu_match_t *match_create_callback (const char *regex, const char *excluderegex,
   DEBUG ("utils_match: match_create_callback: regex = %s, excluderegex = %s",
         regex, excluderegex);
 
-  obj = (cu_match_t *) malloc (sizeof (cu_match_t));
+  obj = calloc (1, sizeof (*obj));
   if (obj == NULL)
     return (NULL);
-  memset (obj, '\0', sizeof (cu_match_t));
 
   status = regcomp (&obj->regex, regex, REG_EXTENDED | REG_NEWLINE);
   if (status != 0)
@@ -275,10 +275,9 @@ cu_match_t *match_create_simple (const char *regex,
   cu_match_value_t *user_data;
   cu_match_t *obj;
 
-  user_data = (cu_match_value_t *) malloc (sizeof (cu_match_value_t));
+  user_data = calloc (1, sizeof (*user_data));
   if (user_data == NULL)
     return (NULL);
-  memset (user_data, '\0', sizeof (cu_match_value_t));
   user_data->ds_type = match_ds_type;
 
   obj = match_create_callback (regex, excluderegex,
@@ -323,9 +322,8 @@ int match_apply (cu_match_t *obj, const char *str)
 {
   int status;
   regmatch_t re_match[32];
-  char *matches[32];
+  char *matches[32] = { 0 };
   size_t matches_num;
-  size_t i;
 
   if ((obj == NULL) || (str == NULL))
     return (-1);
@@ -349,7 +347,6 @@ int match_apply (cu_match_t *obj, const char *str)
   if (status != 0)
     return (0);
 
-  memset (matches, '\0', sizeof (matches));
   for (matches_num = 0; matches_num < STATIC_ARRAY_SIZE (matches); matches_num++)
   {
     if ((re_match[matches_num].rm_so < 0)
@@ -378,7 +375,7 @@ int match_apply (cu_match_t *obj, const char *str)
     }
   }
 
-  for (i = 0; i < matches_num; i++)
+  for (size_t i = 0; i < matches_num; i++)
   {
     sfree (matches[i]);
   }
index fee0871..0488f91 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "utils_time.h"
 #include "utils_random.h"
 
index 3e55497..1bc28f7 100644 (file)
  */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "utils_subst.h"
 
-char *subst (char *buf, size_t buflen, const char *string, int off1, int off2,
+char *subst (char *buf, size_t buflen, const char *string, size_t off1, size_t off2,
                const char *replacement)
 {
-       char  *buf_ptr = buf;
-       size_t len     = buflen;
+       char *out = buf;
+
+       char const *front;
+       char const *back;
+       size_t front_len;
+       size_t replacement_len;
+       size_t back_len;
+
+       if ((NULL == buf) || (0 == buflen) || (NULL == string) || (NULL == replacement))
+               return NULL;
 
-       if ((NULL == buf) || (0 >= buflen) || (NULL == string)
-                       || (0 > off1) || (0 > off2) || (off1 > off2)
-                       || (NULL == replacement))
+       size_t string_len = strlen (string);
+       if ((off1 > string_len) || (off2 > string_len) || (off1 > off2))
                return NULL;
 
-       sstrncpy (buf_ptr, string,
-                       ((size_t)off1 + 1 > buflen) ? buflen : (size_t)off1 + 1);
-       buf_ptr += off1;
-       len     -= off1;
+       front = string;
+       back = string + off2;
+       front_len = off1;
+       replacement_len = strlen (replacement);
+       back_len = strlen (back);
+
+       if (front_len >= buflen) {
+               front_len = buflen - 1;
+               replacement_len = 0;
+               back_len = 0;
+       } else if ((front_len + replacement_len) >= buflen) {
+               replacement_len = buflen - (front_len + 1);
+               back_len = 0;
+       } else if ((front_len + replacement_len + back_len) >= buflen) {
+               back_len = buflen - (front_len + replacement_len + 1);
+       } else {
+               buflen = front_len + replacement_len + back_len + 1;
+       }
+       assert ((front_len + replacement_len + back_len) == (buflen - 1));
 
-       if (0 >= len)
-               return buf;
+       if (front_len != 0) {
+               sstrncpy (out, front, front_len + 1);
+               out += front_len;
+       }
 
-       sstrncpy (buf_ptr, replacement, len);
-       buf_ptr += strlen (replacement);
-       len     -= strlen (replacement);
+       if (replacement_len != 0) {
+               sstrncpy (out, replacement, replacement_len + 1);
+               out += replacement_len;
+       }
 
-       if (0 >= len)
-               return buf;
+       if (back_len != 0) {
+               sstrncpy (out, back, back_len + 1);
+               out += back_len;
+       }
 
-       sstrncpy (buf_ptr, string + off2, len);
+       out[0] = 0;
        return buf;
 } /* subst */
 
@@ -75,7 +103,7 @@ char *asubst (const char *string, int off1, int off2, const char *replacement)
 
        len = off1 + strlen (replacement) + strlen (string) - off2 + 1;
 
-       buf = (char *)malloc (len);
+       buf = malloc (len);
        if (NULL == buf)
                return NULL;
 
@@ -88,7 +116,6 @@ char *asubst (const char *string, int off1, int off2, const char *replacement)
 char *subst_string (char *buf, size_t buflen, const char *string,
                const char *needle, const char *replacement)
 {
-       char *temp;
        size_t needle_len;
        size_t i;
 
@@ -96,19 +123,13 @@ char *subst_string (char *buf, size_t buflen, const char *string,
                        || (needle == NULL) || (replacement == NULL))
                return (NULL);
 
-       temp = (char *) malloc (buflen);
-       if (temp == NULL)
-       {
-               ERROR ("subst_string: malloc failed.");
-               return (NULL);
-       }
-
        needle_len = strlen (needle);
-       strncpy (buf, string, buflen);
+       sstrncpy (buf, string, buflen);
 
        /* Limit the loop to prevent endless loops. */
        for (i = 0; i < buflen; i++)
        {
+               char temp[buflen];
                char *begin_ptr;
                size_t begin;
 
@@ -142,7 +163,6 @@ char *subst_string (char *buf, size_t buflen, const char *string,
                                i, string, needle, replacement);
        }
 
-       sfree (temp);
        return (buf);
 } /* char *subst_string */
 
index 9085286..50df9c7 100644 (file)
@@ -66,7 +66,7 @@
  *
  * The function returns 'buf' on success, NULL else.
  */
-char *subst (char *buf, size_t buflen, const char *string, int off1, int off2,
+char *subst (char *buf, size_t buflen, const char *string, size_t off1, size_t off2,
                const char *replacement);
 
 /*
diff --git a/src/daemon/utils_subst_test.c b/src/daemon/utils_subst_test.c
new file mode 100644 (file)
index 0000000..c6caba2
--- /dev/null
@@ -0,0 +1,135 @@
+/**
+ * collectd - src/daemon/utils_subst_test.c
+ * Copyright (C) 2015       Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "collectd.h"
+
+#include "testing.h"
+#include "utils_subst.h"
+
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc;
+#endif /* HAVE_LIBKSTAT */
+
+DEF_TEST(subst)
+{
+  struct {
+    const char *str;
+    int off1;
+    int off2;
+    const char *rplmt;
+    const char *want;
+  } cases[] = {
+    {"foo_____bar", 3, 8, " - ", "foo - bar"}, /* documentation example */
+    {"foo bar", 0, 2, "m",     "mo bar"},    /* beginning, shorten */
+    {"foo bar", 0, 1, "m",     "moo bar"},   /* beginning, same length */
+    {"foo bar", 0, 3, "milk",  "milk bar"},  /* beginning, extend */
+    {"foo bar", 3, 6, "de",    "fooder"},    /* center, shorten */
+    {"foo bar", 2, 6, "rste",  "forster"},   /* center, same length */
+    {"foo bar", 1, 3, "ish",   "fish bar"},  /* center, extend */
+    {"foo bar", 2, 7, "ul",    "foul"},      /* end, shorten */
+    {"foo bar", 3, 7, "lish",  "foolish"},   /* end, same length */
+    {"foo bar", 3, 7, "dwear", "foodwear"},  /* end, extend */
+    /* truncation (buffer is 16 chars) */
+    {"01234567890123",        8, 8,    "", "01234567890123"},
+    {"01234567890123",        8, 8,   "*", "01234567*890123"},
+    {"01234567890123",        8, 8,  "**", "01234567**89012"},
+    /* input > buffer */
+    {"012345678901234----",   0,  0,   "", "012345678901234"},
+    {"012345678901234----",  17, 18,   "", "012345678901234"},
+    {"012345678901234----",   0,  3,   "", "345678901234---"},
+    {"012345678901234----",   0,  4,   "", "45678901234----"},
+    {"012345678901234----",   0,  5,   "", "5678901234----"},
+    {"012345678901234----",   8,  8,  "#", "01234567#890123"},
+    {"012345678901234----",  12, 12, "##", "012345678901##2"},
+    {"012345678901234----",  13, 13, "##", "0123456789012##"},
+    {"012345678901234----",  14, 14, "##", "01234567890123#"},
+    {"012345678901234----",  15, 15, "##", "012345678901234"},
+    {"012345678901234----",  16, 16, "##", "012345678901234"},
+    /* error cases */
+    {NULL,       3,  4, "_",  NULL}, /* no input */
+    {"foo bar",  3, 10, "_",  NULL}, /* offset exceeds input */
+    {"foo bar", 10, 13, "_",  NULL}, /* offset exceeds input */
+    {"foo bar",  4,  3, "_",  NULL}, /* off1 > off2 */
+    {"foo bar",  3,  4, NULL, NULL}, /* no replacement */
+  };
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+    char buffer[16] = "!!!!!!!!!!!!!!!";
+
+    if (cases[i].want == NULL) {
+      OK(subst (buffer, sizeof (buffer), cases[i].str, cases[i].off1, cases[i].off2, cases[i].rplmt) == NULL);
+      continue;
+    }
+
+    OK(subst (buffer, sizeof (buffer), cases[i].str, cases[i].off1, cases[i].off2, cases[i].rplmt) == &buffer[0]);
+    EXPECT_EQ_STR(cases[i].want, buffer);
+  }
+
+  return 0;
+}
+
+DEF_TEST(subst_string)
+{
+  struct {
+    const char *str;
+    const char *srch;
+    const char *rplmt;
+    const char *want;
+  } cases[] = {
+    {"Hello %{name}",    "%{name}", "world", "Hello world"},
+    {"abcccccc",         "abc",     "cab",   "ccccccab"},
+    {"(((()(())))())",   "()",      "",      ""},
+    {"food booth",       "oo",      "ee",    "feed beeth"},
+    {"foo bar",          "baz",     "qux",   "foo bar"},
+    {"foo bar",          "oo",      "oo",    "foo bar"},
+    {"sixteen chars",    "chars",   "characters", "sixteen charact"},
+  };
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+    char buffer[16];
+
+    if (cases[i].want == NULL) {
+      OK(subst_string (buffer, sizeof (buffer), cases[i].str, cases[i].srch, cases[i].rplmt) == NULL);
+      continue;
+    }
+
+    OK(subst_string (buffer, sizeof (buffer), cases[i].str, cases[i].srch, cases[i].rplmt) == buffer);
+    EXPECT_EQ_STR(cases[i].want, buffer);
+  }
+
+  return 0;
+}
+
+int main (void)
+{
+  RUN_TEST(subst);
+  RUN_TEST(subst_string);
+
+  END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
index fe5dca8..0d8ed7c 100644 (file)
@@ -31,6 +31,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "utils_tail.h"
 
@@ -45,10 +46,9 @@ static int cu_tail_reopen (cu_tail_t *obj)
 {
   int seek_end = 0;
   FILE *fh;
-  struct stat stat_buf;
+  struct stat stat_buf = { 0 };
   int status;
 
-  memset (&stat_buf, 0, sizeof (stat_buf));
   status = stat (obj->file, &stat_buf);
   if (status != 0)
   {
@@ -119,10 +119,9 @@ cu_tail_t *cu_tail_create (const char *file)
 {
        cu_tail_t *obj;
 
-       obj = (cu_tail_t *) malloc (sizeof (cu_tail_t));
+       obj = calloc (1, sizeof (*obj));
        if (obj == NULL)
                return (NULL);
-       memset (obj, '\0', sizeof (cu_tail_t));
 
        obj->file = strdup (file);
        if (obj->file == NULL)
index 8776ad1..ffcaa90 100644 (file)
@@ -30,6 +30,7 @@
  */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_match.h"
@@ -111,9 +112,8 @@ static int tail_callback (void *data, char *buf,
     int __attribute__((unused)) buflen)
 {
   cu_tail_match_t *obj = (cu_tail_match_t *) data;
-  size_t i;
 
-  for (i = 0; i < obj->matches_num; i++)
+  for (size_t i = 0; i < obj->matches_num; i++)
     match_apply (obj->matches[i].match, buf);
 
   return (0);
@@ -126,10 +126,9 @@ cu_tail_match_t *tail_match_create (const char *filename)
 {
   cu_tail_match_t *obj;
 
-  obj = (cu_tail_match_t *) malloc (sizeof (cu_tail_match_t));
+  obj = calloc (1, sizeof (*obj));
   if (obj == NULL)
     return (NULL);
-  memset (obj, '\0', sizeof (cu_tail_match_t));
 
   obj->tail = cu_tail_create (filename);
   if (obj->tail == NULL)
@@ -143,8 +142,6 @@ cu_tail_match_t *tail_match_create (const char *filename)
 
 void tail_match_destroy (cu_tail_match_t *obj)
 {
-  size_t i;
-
   if (obj == NULL)
     return;
 
@@ -154,7 +151,7 @@ void tail_match_destroy (cu_tail_match_t *obj)
     obj->tail = NULL;
   }
 
-  for (i = 0; i < obj->matches_num; i++)
+  for (size_t i = 0; i < obj->matches_num; i++)
   {
     cu_tail_match_match_t *match = obj->matches + i;
     if (match->match != NULL)
@@ -180,7 +177,7 @@ int tail_match_add_match (cu_tail_match_t *obj, cu_match_t *match,
 {
   cu_tail_match_match_t *temp;
 
-  temp = (cu_tail_match_match_t *) realloc (obj->matches,
+  temp = realloc (obj->matches,
       sizeof (cu_tail_match_match_t) * (obj->matches_num + 1));
   if (temp == NULL)
     return (-1);
@@ -212,13 +209,12 @@ int tail_match_add_match_simple (cu_tail_match_t *obj,
   if (match == NULL)
     return (-1);
 
-  user_data = (cu_tail_match_simple_t *) malloc (sizeof (cu_tail_match_simple_t));
+  user_data = calloc (1, sizeof (*user_data));
   if (user_data == NULL)
   {
     match_destroy (match);
     return (-1);
   }
-  memset (user_data, '\0', sizeof (cu_tail_match_simple_t));
 
   sstrncpy (user_data->plugin, plugin, sizeof (user_data->plugin));
   if (plugin_instance != NULL)
@@ -248,7 +244,6 @@ int tail_match_read (cu_tail_match_t *obj)
 {
   char buffer[4096];
   int status;
-  size_t i;
 
   status = cu_tail_read (obj->tail, buffer, sizeof (buffer), tail_callback,
       (void *) obj);
@@ -258,7 +253,7 @@ int tail_match_read (cu_tail_match_t *obj)
     return (status);
   }
 
-  for (i = 0; i < obj->matches_num; i++)
+  for (size_t i = 0; i < obj->matches_num; i++)
   {
     cu_tail_match_match_t *lt_match = obj->matches + i;
 
index 4a8df89..784e109 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "utils_avltree.h"
 #include "utils_threshold.h"
@@ -124,16 +125,16 @@ int ut_search_threshold (const value_list_t *vl, /* {{{ */
   if (vl == NULL)
     return (EINVAL);
 
-       /* Is this lock really necessary? */
-       pthread_mutex_lock (&threshold_lock);
+  /* Is this lock really necessary? */
+  pthread_mutex_lock (&threshold_lock);
   t = threshold_search (vl);
   if (t == NULL) {
-               pthread_mutex_unlock (&threshold_lock);
+    pthread_mutex_unlock (&threshold_lock);
     return (ENOENT);
-       }
+  }
 
   memcpy (ret_threshold, t, sizeof (*ret_threshold));
-       pthread_mutex_unlock (&threshold_lock);
+  pthread_mutex_unlock (&threshold_lock);
 
   ret_threshold->next = NULL;
 
index bf097fa..a5c3373 100644 (file)
@@ -59,7 +59,7 @@ threshold_t *threshold_get (const char *hostname,
 
 threshold_t *threshold_search (const value_list_t *vl);
 
-int ut_search_threshold (const value_list_t *vl, 
+int ut_search_threshold (const value_list_t *vl,
   threshold_t *ret_threshold);
 
 #endif /* UTILS_THRESHOLD_H */
index 6603c15..86476ea 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/utils_time.c
- * Copyright (C) 2010       Florian octo Forster
+ * Copyright (C) 2010-2015  Florian octo Forster
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *   Florian octo Forster <ff at octo.it>
+ *   Florian octo Forster <octo at collectd.org>
  **/
 
 #include "collectd.h"
+
 #include "utils_time.h"
 #include "plugin.h"
 #include "common.h"
 
-#if HAVE_CLOCK_GETTIME
+#ifndef DEFAULT_MOCK_TIME
+# define DEFAULT_MOCK_TIME 1542455354518929408ULL
+#endif
+
+#ifdef MOCK_TIME
+cdtime_t cdtime_mock = (cdtime_t) MOCK_TIME;
+
+cdtime_t cdtime (void)
+{
+  return cdtime_mock;
+}
+#else /* !MOCK_TIME */
+# if HAVE_CLOCK_GETTIME
 cdtime_t cdtime (void) /* {{{ */
 {
   int status;
@@ -46,7 +59,7 @@ cdtime_t cdtime (void) /* {{{ */
 
   return (TIMESPEC_TO_CDTIME_T (&ts));
 } /* }}} cdtime_t cdtime */
-#else
+# else /* !HAVE_CLOCK_GETTIME */
 /* Work around for Mac OS X which doesn't have clock_gettime(2). *sigh* */
 cdtime_t cdtime (void) /* {{{ */
 {
@@ -64,41 +77,95 @@ cdtime_t cdtime (void) /* {{{ */
 
   return (TIMEVAL_TO_CDTIME_T (&tv));
 } /* }}} cdtime_t cdtime */
+# endif
 #endif
 
-size_t cdtime_to_iso8601 (char *s, size_t max, cdtime_t t) /* {{{ */
+/* format_zone reads time zone information from "extern long timezone", exported
+ * by <time.h>, and formats it according to RFC 3339. This differs from
+ * strftime()'s "%z" format by including a colon between hour and minute. */
+static int format_zone (char *buffer, size_t buffer_size, struct tm const *tm) /* {{{ */
+{
+  char tmp[7];
+  size_t sz;
+
+  if ((buffer == NULL) || (buffer_size < 7))
+    return EINVAL;
+
+  sz = strftime (tmp, sizeof (tmp), "%z", tm);
+  if (sz == 0)
+    return ENOMEM;
+  if (sz != 5)
+  {
+    DEBUG ("format_zone: strftime(\"%%z\") = \"%s\", want \"+hhmm\"", tmp);
+    sstrncpy (buffer, tmp, buffer_size);
+    return 0;
+  }
+
+  buffer[0] = tmp[0];
+  buffer[1] = tmp[1];
+  buffer[2] = tmp[2];
+  buffer[3] = ':';
+  buffer[4] = tmp[3];
+  buffer[5] = tmp[4];
+  buffer[6] = 0;
+
+  return 0;
+} /* }}} int format_zone */
+
+static int format_rfc3339 (char *buffer, size_t buffer_size, cdtime_t t, _Bool print_nano) /* {{{ */
 {
   struct timespec t_spec;
   struct tm t_tm;
-
+  char base[20]; /* 2006-01-02T15:04:05 */
+  char nano[11]; /* .999999999 */
+  char zone[7];  /* +00:00 */
+  char *fields[] = {base, nano, zone};
   size_t len;
+  int status;
 
   CDTIME_T_TO_TIMESPEC (t, &t_spec);
   NORMALIZE_TIMESPEC (t_spec);
 
-  if (localtime_r ((time_t *)&t_spec.tv_sec, &t_tm) == NULL) {
+  if (localtime_r (&t_spec.tv_sec, &t_tm) == NULL) {
     char errbuf[1024];
-    ERROR ("cdtime_to_iso8601: localtime_r failed: %s",
-        sstrerror (errno, errbuf, sizeof (errbuf)));
-    return (0);
+    status = errno;
+    ERROR ("format_rfc3339: localtime_r failed: %s",
+        sstrerror (status, errbuf, sizeof (errbuf)));
+    return (status);
   }
 
-  len = strftime (s, max, "%Y-%m-%dT%H:%M:%S", &t_tm);
+  len = strftime (base, sizeof (base), "%Y-%m-%dT%H:%M:%S", &t_tm);
   if (len == 0)
-    return 0;
+    return ENOMEM;
 
-  if (max - len > 2) {
-    int n = snprintf (s + len, max - len, ".%09i", (int)t_spec.tv_nsec);
-    len += (n < max - len) ? n : max - len;
-  }
+  if (print_nano)
+    ssnprintf (nano, sizeof (nano), ".%09ld", (long) t_spec.tv_nsec);
+  else
+    sstrncpy (nano, "", sizeof (nano));
 
-  if (max - len > 3) {
-    int n = strftime (s + len, max - len, "%z", &t_tm);
-    len += (n < max - len) ? n : max - len;
-  }
+  status = format_zone (zone, sizeof (zone), &t_tm);
+  if (status != 0)
+    return status;
+
+  if (strjoin (buffer, buffer_size, fields, STATIC_ARRAY_SIZE (fields), "") < 0)
+    return ENOMEM;
+  return 0;
+} /* }}} int format_rfc3339 */
+
+int rfc3339 (char *buffer, size_t buffer_size, cdtime_t t) /* {{{ */
+{
+  if (buffer_size < RFC3339_SIZE)
+    return ENOMEM;
+
+  return format_rfc3339 (buffer, buffer_size, t, 0);
+} /* }}} size_t cdtime_to_rfc3339 */
+
+int rfc3339nano (char *buffer, size_t buffer_size, cdtime_t t) /* {{{ */
+{
+  if (buffer_size < RFC3339NANO_SIZE)
+    return ENOMEM;
 
-  s[max - 1] = '\0';
-  return len;
-} /* }}} size_t cdtime_to_iso8601 */
+  return format_rfc3339 (buffer, buffer_size, t, 1);
+} /* }}} size_t cdtime_to_rfc3339nano */
 
 /* vim: set sw=2 sts=2 et fdm=marker : */
index 9b08e8e..4d88dcc 100644 (file)
@@ -1,6 +1,6 @@
 /**
- * collectd - src/utils_time.h
- * Copyright (C) 2010       Florian octo Forster
+ * collectd - src/daemon/utils_time.h
+ * Copyright (C) 2010-2015  Florian octo Forster
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -21,7 +21,7 @@
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *   Florian octo Forster <ff at octo.it>
+ *   Florian octo Forster <octo at collectd.org>
  **/
 
 #ifndef UTILS_TIME_H
 
 #include "collectd.h"
 
+#ifdef TESTING_H
+/* cdtime_mock is the time returned by cdtime() when build with
+ * -DMOCK_TIME */
+extern cdtime_t cdtime_mock;
+#endif
+
 /*
  * "cdtime_t" is a 64bit unsigned integer. The time is stored at a 2^-30 second
  * resolution, i.e. the most significant 34 bit are used to store the time in
  * manner is that comparing times and calculating differences is as simple as
  * it is with "time_t", i.e. a simple integer comparison / subtraction works.
  */
-/* 
+/*
  * cdtime_t is defined in "collectd.h" */
 /* typedef uint64_t cdtime_t; */
 
 /* 2^30 = 1073741824 */
-#define TIME_T_TO_CDTIME_T(t) (((cdtime_t) (t)) * 1073741824)
-#define CDTIME_T_TO_TIME_T(t) ((time_t) ((t) / 1073741824))
+#define TIME_T_TO_CDTIME_T(t) (((cdtime_t) (t)) << 30)
+
+#define MS_TO_CDTIME_T(ms) (((((cdtime_t) (ms)) / 1000) << 30) | \
+    ((((((cdtime_t) (ms)) % 1000) << 30) + 500) / 1000))
+#define US_TO_CDTIME_T(us) (((((cdtime_t) (us)) / 1000000) << 30) | \
+    ((((((cdtime_t) (us)) % 1000000) << 30) + 500000) / 1000000))
+#define NS_TO_CDTIME_T(ns) (((((cdtime_t) (ns)) / 1000000000) << 30) | \
+    ((((((cdtime_t) (ns)) % 1000000000) << 30) + 500000000) / 1000000000))
+
+#define CDTIME_T_TO_TIME_T(t) ((time_t) (((t) + (1 << 29)) >> 30))
+#define CDTIME_T_TO_MS(t)  ((uint64_t) ((((t) >> 30) * 1000) + \
+  ((((t) & 0x3fffffff) * 1000 + (1 << 29)) >> 30)))
+#define CDTIME_T_TO_US(t)  ((uint64_t) ((((t) >> 30) * 1000000) + \
+  ((((t) & 0x3fffffff) * 1000000 + (1 << 29)) >> 30)))
+#define CDTIME_T_TO_NS(t)  ((uint64_t) ((((t) >> 30) * 1000000000) + \
+  ((((t) & 0x3fffffff) * 1000000000 + (1 << 29)) >> 30)))
 
 #define CDTIME_T_TO_DOUBLE(t) (((double) (t)) / 1073741824.0)
 #define DOUBLE_TO_CDTIME_T(d) ((cdtime_t) ((d) * 1073741824.0))
 
-#define MS_TO_CDTIME_T(ms) ((cdtime_t)    (((double) (ms)) * 1073741.824))
-#define CDTIME_T_TO_MS(t)  ((long)        (((double) (t))  / 1073741.824))
-#define US_TO_CDTIME_T(us) ((cdtime_t)    (((double) (us)) * 1073.741824))
-#define CDTIME_T_TO_US(t)  ((suseconds_t) (((double) (t))  / 1073.741824))
-#define NS_TO_CDTIME_T(ns) ((cdtime_t)    (((double) (ns)) * 1.073741824))
-#define CDTIME_T_TO_NS(t)  ((long)        (((double) (t))  / 1.073741824))
-
-#define CDTIME_T_TO_TIMEVAL(cdt,tvp) do {                                    \
-        (tvp)->tv_sec = CDTIME_T_TO_TIME_T (cdt);                            \
-        (tvp)->tv_usec = CDTIME_T_TO_US ((cdt) % 1073741824);                \
+#define CDTIME_T_TO_TIMEVAL(cdt,tvp) do { \
+  (tvp)->tv_sec = (time_t) ((cdt) >> 30); \
+  (tvp)->tv_usec = (suseconds_t) ((((cdt) & 0x3fffffff) * 1000000 + (1 << 29)) >> 30); \
 } while (0)
-#define TIMEVAL_TO_CDTIME_T(tv) (TIME_T_TO_CDTIME_T ((tv)->tv_sec)           \
-    + US_TO_CDTIME_T ((tv)->tv_usec))
+#define TIMEVAL_TO_CDTIME_T(tv) US_TO_CDTIME_T(1000000 * (tv)->tv_sec + (tv)->tv_usec)
 
-#define CDTIME_T_TO_TIMESPEC(cdt,tsp) do {                                   \
-  (tsp)->tv_sec = CDTIME_T_TO_TIME_T (cdt);                                  \
-  (tsp)->tv_nsec = CDTIME_T_TO_NS ((cdt) % 1073741824);                      \
+#define CDTIME_T_TO_TIMESPEC(cdt,tsp) do { \
+  (tsp)->tv_sec = (time_t) ((cdt) >> 30); \
+  (tsp)->tv_nsec = (long) ((((cdt) & 0x3fffffff) * 1000000000 + (1 << 29)) >> 30); \
 } while (0)
-#define TIMESPEC_TO_CDTIME_T(ts) (TIME_T_TO_CDTIME_T ((ts)->tv_sec)           \
-    + NS_TO_CDTIME_T ((ts)->tv_nsec))
+#define TIMESPEC_TO_CDTIME_T(ts) NS_TO_CDTIME_T(1000000000ULL * (ts)->tv_sec + (ts)->tv_nsec)
 
 cdtime_t cdtime (void);
 
-/* format a cdtime_t value in ISO 8601 format:
- * returns the number of characters written to the string (not including the
- * terminating null byte or 0 on error; the function ensures that the string
- * is null terminated */
-size_t cdtime_to_iso8601 (char *s, size_t max, cdtime_t t);
+#define RFC3339_SIZE     26
+#define RFC3339NANO_SIZE 36
+
+/* rfc3339 formats a cdtime_t time in RFC 3339 format with second precision. */
+int rfc3339 (char *buffer, size_t buffer_size, cdtime_t t);
+
+/* rfc3339nano formats a cdtime_t time in RFC 3339 format with nanosecond
+ * precision. */
+int rfc3339nano (char *buffer, size_t buffer_size, cdtime_t t);
 
 #endif /* UTILS_TIME_H */
 /* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/utils_time_mock.c b/src/daemon/utils_time_mock.c
deleted file mode 100644 (file)
index 5edfe6f..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * collectd - src/tests/mock/utils_time.c
- * Copyright (C) 2013       Florian octo Forster
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *   Florian octo Forster <octo at collectd.org>
- */
-
-#include "utils_time.h"
-
-cdtime_t cdtime (void)
-{
-  return (0);
-}
-
diff --git a/src/daemon/utils_time_test.c b/src/daemon/utils_time_test.c
new file mode 100644 (file)
index 0000000..9f04368
--- /dev/null
@@ -0,0 +1,126 @@
+/**
+ * collectd - src/daemon/utils_time_test.c
+ * Copyright (C) 2015       Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#define DBL_PRECISION 1e-3
+
+#include "collectd.h"
+
+#include "testing.h"
+#include "utils_time.h"
+
+DEF_TEST(conversion)
+{
+  struct {
+    cdtime_t t;
+    double d;
+    time_t tt;
+    uint64_t ms;
+    struct timeval tv;
+    struct timespec ts;
+  } cases[] = {
+  /*              cdtime          double      time_t   milliseconds               timeval                 timespec */
+    {                     0,          0.0  ,          0,                0, {         0,      0}, {         0,         0}},
+    {        10737418240ULL,         10.0  ,         10,            10000, {        10,      0}, {        10,         0}},
+    {1542908534771941376ULL, 1436945549.0  , 1436945549, 1436945549000ULL, {1436945549,      0}, {1436945549,         0}},
+    {1542908535540740522ULL, 1436945549.716, 1436945550, 1436945549716ULL, {1436945549, 716000}, {1436945549, 716000000}},
+    // 1426076671.123 * 2^30 = 1531238166015458148.352
+    {1531238166015458148ULL, 1426076671.123, 1426076671, 1426076671123ULL, {1426076671, 123000}, {1426076671, 123000000}},
+    // 1426076681.234 * 2^30 = 1531238176872061730.816
+    {1531238176872061731ULL, 1426076681.234, 1426076681, 1426076681234ULL, {1426076681, 234000}, {1426076681, 234000000}},
+    // 1426083986.314 * 2^30 = 1531246020641985396.736
+    {1531246020641985397ULL, 1426083986.314, 1426083986, 1426083986314ULL, {1426083986, 314000}, {1426083986, 314000000}},
+    // 1426083986.494142531 * 2^30 = 1531246020835411966.5
+    {1531246020835411967ULL, 1426083986.494, 1426083986, 1426083986494ULL, {1426083986, 494143}, {1426083986, 494142531}},
+    // 1426083986.987410814 * 2^30 = 1531246021365054752.4
+    {1531246021365054752ULL, 1426083986.987, 1426083987, 1426083986987ULL, {1426083986, 987411}, {1426083986, 987410814}},
+
+    /* These cases test the cdtime_t -> ns conversion rounds correctly. */
+    // 1546167635576736987 / 2^30 = 1439980823.1524536265...
+    {1546167635576736987ULL, 1439980823.152, 1439980823, 1439980823152ULL, {1439980823, 152454}, {1439980823, 152453627}},
+    // 1546167831554815222 / 2^30 = 1439981005.6712620165...
+    {1546167831554815222ULL, 1439981005.671, 1439981006, 1439981005671ULL, {1439981005, 671262}, {1439981005, 671262017}},
+    // 1546167986577716567 / 2^30 = 1439981150.0475896215...
+    {1546167986577716567ULL, 1439981150.048, 1439981150, 1439981150048ULL, {1439981150,  47590}, {1439981150,  47589622}},
+  };
+
+  for (size_t i = 0; i < (sizeof (cases) / sizeof (cases[0])); i++) {
+    struct timeval tv;
+    struct timespec ts;
+
+    // cdtime -> s
+    EXPECT_EQ_UINT64 (cases[i].tt, CDTIME_T_TO_TIME_T (cases[i].t));
+
+    // cdtime -> ms
+    EXPECT_EQ_UINT64(cases[i].ms, CDTIME_T_TO_MS (cases[i].t));
+
+    // cdtime -> us
+    CDTIME_T_TO_TIMEVAL (cases[i].t, &tv);
+    EXPECT_EQ_UINT64 (cases[i].tv.tv_sec, tv.tv_sec);
+    EXPECT_EQ_UINT64 (cases[i].tv.tv_usec, tv.tv_usec);
+
+    // cdtime -> ns
+    CDTIME_T_TO_TIMESPEC (cases[i].t, &ts);
+    EXPECT_EQ_UINT64 (cases[i].ts.tv_sec, ts.tv_sec);
+    EXPECT_EQ_UINT64 (cases[i].ts.tv_nsec, ts.tv_nsec);
+
+    // cdtime -> double
+    EXPECT_EQ_DOUBLE (cases[i].d, CDTIME_T_TO_DOUBLE (cases[i].t));
+  }
+
+  return 0;
+}
+
+/* These cases test the ns -> cdtime_t conversion rounds correctly. */
+DEF_TEST(ns_to_cdtime)
+{
+  struct {
+    uint64_t ns;
+    cdtime_t want;
+  } cases[] = {
+    // 1439981652801860766 * 2^30 / 10^9 = 1546168526406004689.4
+    {1439981652801860766ULL, 1546168526406004689ULL},
+    // 1439981836985281914 * 2^30 / 10^9 = 1546168724171447263.4
+    {1439981836985281914ULL, 1546168724171447263ULL},
+    // 1439981880053705608 * 2^30 / 10^9 = 1546168770415815077.4
+    {1439981880053705608ULL, 1546168770415815077ULL},
+  };
+
+  for (size_t i = 0; i < (sizeof (cases) / sizeof (cases[0])); i++) {
+    EXPECT_EQ_UINT64 (cases[i].want, NS_TO_CDTIME_T (cases[i].ns));
+  }
+
+  return 0;
+}
+
+int main (void)
+{
+  RUN_TEST(conversion);
+  RUN_TEST(ns_to_cdtime);
+
+  END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
index a7963ea..b93aa51 100644 (file)
--- a/src/dbi.c
+++ b/src/dbi.c
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -64,6 +65,8 @@ struct cdbi_database_s /* {{{ */
   char *name;
   char *select_db;
 
+  cdtime_t interval;
+
   char *driver;
   char *host;
   cdbi_driver_option_t *driver_options;
@@ -146,7 +149,7 @@ static int cdbi_result_get_field (dbi_result res, /* {{{ */
   else if (src_type == DBI_TYPE_STRING)
   {
     const char *value;
-    
+
     value = dbi_result_get_string_idx (res, index);
     if (value == NULL)
       sstrncpy (buffer, "", buffer_size);
@@ -176,15 +179,13 @@ static int cdbi_result_get_field (dbi_result res, /* {{{ */
 
 static void cdbi_database_free (cdbi_database_t *db) /* {{{ */
 {
-  size_t i;
-
   if (db == NULL)
     return;
 
   sfree (db->name);
   sfree (db->driver);
 
-  for (i = 0; i < db->driver_options_num; i++)
+  for (size_t i = 0; i < db->driver_options_num; i++)
   {
     sfree (db->driver_options[i].key);
     if (!db->driver_options[i].is_numeric)
@@ -193,7 +194,7 @@ static void cdbi_database_free (cdbi_database_t *db) /* {{{ */
   sfree (db->driver_options);
 
   if (db->q_prep_areas)
-    for (i = 0; i < db->queries_num; ++i)
+    for (size_t i = 0; i < db->queries_num; ++i)
       udb_query_delete_preparation_area (db->q_prep_areas[i]);
   free (db->q_prep_areas);
 
@@ -212,9 +213,10 @@ static void cdbi_database_free (cdbi_database_t *db) /* {{{ */
  *     </Result>
  *     ...
  *   </Query>
- *     
+ *
  *   <Database "plugin_instance1">
  *     Driver "mysql"
+ *     Interval 120
  *     DriverOption "hostname" "localhost"
  *     ...
  *     Query "plugin_instance0"
@@ -237,7 +239,7 @@ static int cdbi_config_add_database_driver_option (cdbi_database_t *db, /* {{{ *
     return (-1);
   }
 
-  option = (cdbi_driver_option_t *) realloc (db->driver_options,
+  option = realloc (db->driver_options,
       sizeof (*option) * (db->driver_options_num + 1));
   if (option == NULL)
   {
@@ -281,7 +283,6 @@ static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
 {
   cdbi_database_t *db;
   int status;
-  int i;
 
   if ((ci->values_num != 1)
       || (ci->values[0].type != OCONFIG_TYPE_STRING))
@@ -291,13 +292,12 @@ static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  db = (cdbi_database_t *) malloc (sizeof (*db));
+  db = calloc (1, sizeof (*db));
   if (db == NULL)
   {
-    ERROR ("dbi plugin: malloc failed.");
+    ERROR ("dbi plugin: calloc failed.");
     return (-1);
   }
-  memset (db, 0, sizeof (*db));
 
   status = cf_util_get_string (ci, &db->name);
   if (status != 0)
@@ -307,7 +307,7 @@ static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
   }
 
   /* Fill the `cdbi_database_t' structure.. */
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -322,6 +322,8 @@ static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
           &db->queries, &db->queries_num);
     else if (strcasecmp ("Host", child->key) == 0)
       status = cf_util_get_string (child, &db->host);
+    else if (strcasecmp ("Interval", child->key) == 0)
+      status = cf_util_get_cdtime(child, &db->interval);
     else
     {
       WARNING ("dbi plugin: Option `%s' not allowed here.", child->key);
@@ -351,17 +353,15 @@ static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
 
   while ((status == 0) && (db->queries_num > 0))
   {
-    db->q_prep_areas = (udb_query_preparation_area_t **) calloc (
-        db->queries_num, sizeof (*db->q_prep_areas));
-
+    db->q_prep_areas = calloc (db->queries_num, sizeof (*db->q_prep_areas));
     if (db->q_prep_areas == NULL)
     {
-      WARNING ("dbi plugin: malloc failed");
+      WARNING ("dbi plugin: calloc failed");
       status = -1;
       break;
     }
 
-    for (i = 0; i < db->queries_num; ++i)
+    for (size_t i = 0; i < db->queries_num; ++i)
     {
       db->q_prep_areas[i]
         = udb_query_allocate_preparation_area (db->queries[i]);
@@ -382,7 +382,7 @@ static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
   {
     cdbi_database_t **temp;
 
-    temp = (cdbi_database_t **) realloc (databases,
+    temp = realloc (databases,
         sizeof (*databases) * (databases_num + 1));
     if (temp == NULL)
     {
@@ -391,14 +391,13 @@ static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
     }
     else
     {
-      user_data_t ud;
+      user_data_t ud = { 0 };
       char *name = NULL;
 
       databases = temp;
       databases[databases_num] = db;
       databases_num++;
 
-      memset (&ud, 0, sizeof (ud));
       ud.data = (void *) db;
       ud.free_func = NULL;
       name = ssnprintf_alloc("dbi:%s", db->name);
@@ -406,7 +405,7 @@ static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
       plugin_register_complex_read (/* group = */ NULL,
           /* name = */ name ? name : db->name,
           /* callback = */ cdbi_read_database,
-          /* interval = */ NULL,
+          /* interval = */ (db->interval > 0) ? db->interval : 0,
           /* user_data = */ &ud);
       free (name);
     }
@@ -423,9 +422,7 @@ static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
 
 static int cdbi_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
     if (strcasecmp ("Query", child->key) == 0)
@@ -494,7 +491,6 @@ static int cdbi_read_database_query (cdbi_database_t *db, /* {{{ */
   char **column_names;
   char **column_values;
   int status;
-  size_t i;
 
   /* Macro that cleans up dynamically allocated memory and returns the
    * specified status. */
@@ -506,7 +502,6 @@ static int cdbi_read_database_query (cdbi_database_t *db, /* {{{ */
 
   column_names = NULL;
   column_values = NULL;
-  res = NULL;
 
   statement = udb_query_get_statement (q);
   assert (statement != NULL);
@@ -542,43 +537,41 @@ static int cdbi_read_database_query (cdbi_database_t *db, /* {{{ */
   }
 
   /* Allocate `column_names' and `column_values'. {{{ */
-  column_names = (char **) calloc (column_num, sizeof (char *));
+  column_names = calloc (column_num, sizeof (*column_names));
   if (column_names == NULL)
   {
-    ERROR ("dbi plugin: malloc failed.");
+    ERROR ("dbi plugin: calloc failed.");
     BAIL_OUT (-1);
   }
 
-  column_names[0] = (char *) calloc (column_num,
-      DATA_MAX_NAME_LEN * sizeof (char));
+  column_names[0] = calloc (column_num, DATA_MAX_NAME_LEN);
   if (column_names[0] == NULL)
   {
-    ERROR ("dbi plugin: malloc failed.");
+    ERROR ("dbi plugin: calloc failed.");
     BAIL_OUT (-1);
   }
-  for (i = 1; i < column_num; i++)
+  for (size_t i = 1; i < column_num; i++)
     column_names[i] = column_names[i - 1] + DATA_MAX_NAME_LEN;
 
-  column_values = (char **) calloc (column_num, sizeof (char *));
+  column_values = calloc (column_num, sizeof (*column_values));
   if (column_values == NULL)
   {
-    ERROR ("dbi plugin: malloc failed.");
+    ERROR ("dbi plugin: calloc failed.");
     BAIL_OUT (-1);
   }
 
-  column_values[0] = (char *) calloc (column_num,
-      DATA_MAX_NAME_LEN * sizeof (char));
+  column_values[0] = calloc (column_num, DATA_MAX_NAME_LEN);
   if (column_values[0] == NULL)
   {
-    ERROR ("dbi plugin: malloc failed.");
+    ERROR ("dbi plugin: calloc failed.");
     BAIL_OUT (-1);
   }
-  for (i = 1; i < column_num; i++)
+  for (size_t i = 1; i < column_num; i++)
     column_values[i] = column_values[i - 1] + DATA_MAX_NAME_LEN;
   /* }}} */
 
   /* Copy the field names to `column_names' */
-  for (i = 0; i < column_num; i++) /* {{{ */
+  for (size_t i = 0; i < column_num; i++) /* {{{ */
   {
     const char *column_name;
 
@@ -596,7 +589,7 @@ static int cdbi_read_database_query (cdbi_database_t *db, /* {{{ */
 
   udb_query_prepare_result (q, prep_area, (db->host ? db->host : hostname_g),
       /* plugin = */ "dbi", db->name,
-      column_names, column_num, /* interval = */ 0);
+      column_names, column_num, /* interval = */ (db->interval > 0) ? db->interval : 0);
 
   /* 0 = error; 1 = success; */
   status = dbi_result_first_row (res); /* {{{ */
@@ -618,7 +611,7 @@ static int cdbi_read_database_query (cdbi_database_t *db, /* {{{ */
   {
     status = 0;
     /* Copy the value of the columns to `column_values' */
-    for (i = 0; i < column_num; i++) /* {{{ */
+    for (size_t i = 0; i < column_num; i++) /* {{{ */
     {
       status = cdbi_result_get_field (res, (unsigned int) (i + 1),
           column_values[i], DATA_MAX_NAME_LEN);
@@ -674,7 +667,6 @@ static int cdbi_connect_database (cdbi_database_t *db) /* {{{ */
 {
   dbi_driver driver;
   dbi_conn connection;
-  size_t i;
   int status;
 
   if (db->connection != NULL)
@@ -716,7 +708,7 @@ static int cdbi_connect_database (cdbi_database_t *db) /* {{{ */
    * encountered, it will get a list of options understood by the driver and
    * report that as `INFO'. This way, users hopefully don't have too much
    * trouble finding out how to configure the plugin correctly.. */
-  for (i = 0; i < db->driver_options_num; i++)
+  for (size_t i = 0; i < db->driver_options_num; i++)
   {
     if (db->driver_options[i].is_numeric)
     {
@@ -749,11 +741,9 @@ static int cdbi_connect_database (cdbi_database_t *db) /* {{{ */
 
     if (status != 0)
     {
-      char const *opt;
-
       INFO ("dbi plugin: This is a list of all options understood "
           "by the `%s' driver:", db->driver);
-      for (opt = dbi_conn_get_option_list (connection, NULL);
+      for (const char *opt = dbi_conn_get_option_list (connection, NULL);
           opt != NULL;
           opt = dbi_conn_get_option_list (connection, opt))
       {
@@ -798,7 +788,6 @@ static int cdbi_connect_database (cdbi_database_t *db) /* {{{ */
 static int cdbi_read_database (user_data_t *ud) /* {{{ */
 {
   cdbi_database_t *db = (cdbi_database_t *) ud->data;
-  size_t i;
   int success;
   int status;
 
@@ -813,7 +802,7 @@ static int cdbi_read_database (user_data_t *ud) /* {{{ */
   /* TODO: Complain if `db_version == 0' */
 
   success = 0;
-  for (i = 0; i < db->queries_num; i++)
+  for (size_t i = 0; i < db->queries_num; i++)
   {
     /* Check if we know the database's version and if so, if this query applies
      * to that version. */
@@ -838,9 +827,7 @@ static int cdbi_read_database (user_data_t *ud) /* {{{ */
 
 static int cdbi_shutdown (void) /* {{{ */
 {
-  size_t i;
-
-  for (i = 0; i < databases_num; i++)
+  for (size_t i = 0; i < databases_num; i++)
   {
     if (databases[i]->connection != NULL)
     {
index ff70172..83be176 100644 (file)
--- a/src/df.c
+++ b/src/df.c
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -190,7 +191,6 @@ static int df_read (void)
 #endif
        /* struct STATANYFS statbuf; */
        cu_mount_t *mnt_list;
-       cu_mount_t *mnt_ptr;
 
        mnt_list = NULL;
        if (cu_mount_getlist (&mnt_list) == NULL)
@@ -199,7 +199,7 @@ static int df_read (void)
                return (-1);
        }
 
-       for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
+       for (cu_mount_t *mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
        {
                unsigned long long blocksize;
                char disk_name[256];
@@ -273,12 +273,12 @@ static int df_read (void)
                                sstrncpy (disk_name, "root", sizeof (disk_name));
                        else
                        {
-                               int i, len;
+                               int len;
 
                                sstrncpy (disk_name, mnt_ptr->dir + 1, sizeof (disk_name));
                                len = strlen (disk_name);
 
-                               for (i = 0; i < len; i++)
+                               for (int i = 0; i < len; i++)
                                        if (disk_name[i] == '/')
                                                disk_name[i] = '-';
                        }
index 1c3dd98..d7eb0a5 100644 (file)
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_ignorelist.h"
 #if HAVE_IOKIT_IOBSD_H
 #  include <IOKit/IOBSD.h>
 #endif
+#if KERNEL_FREEBSD
+#include <devstat.h>
+#include <libgeom.h>
+#endif
 
 #if HAVE_LIMITS_H
 # include <limits.h>
@@ -102,11 +107,18 @@ typedef struct diskstats
        derive_t avg_read_time;
        derive_t avg_write_time;
 
+       _Bool has_merged;
+       _Bool has_in_progress;
+       _Bool has_io_time;
+
        struct diskstats *next;
 } diskstats_t;
 
 static diskstats_t *disklist;
 /* #endif KERNEL_LINUX */
+#elif KERNEL_FREEBSD
+static struct gmesh geom_tree;
+/* #endif KERNEL_FREEBSD */
 
 #elif HAVE_LIBKSTAT
 #define MAX_NUMDISK 1024
@@ -219,9 +231,33 @@ static int disk_init (void)
 /* #endif HAVE_IOKIT_IOKITLIB_H */
 
 #elif KERNEL_LINUX
-       /* do nothing */
+#if HAVE_LIBUDEV
+       if (conf_udev_name_attr != NULL)
+       {
+               handle_udev = udev_new();
+               if (handle_udev == NULL) {
+                       ERROR ("disk plugin: udev_new() failed!");
+                       return (-1);
+               }
+       }
+#endif /* HAVE_LIBUDEV */
 /* #endif KERNEL_LINUX */
 
+#elif KERNEL_FREEBSD
+       int rv;
+
+       rv = geom_gettree(&geom_tree);
+       if (rv != 0) {
+               ERROR ("geom_gettree() failed, returned %d", rv);
+               return (-1);
+       }
+       rv = geom_stats_open();
+       if (rv != 0) {
+               ERROR ("geom_stats_open() failed, returned %d", rv);
+               return (-1);
+       }
+/* #endif KERNEL_FREEBSD */
+
 #elif HAVE_LIBKSTAT
        kstat_t *ksp_chain;
 
@@ -246,6 +282,17 @@ static int disk_init (void)
        return (0);
 } /* int disk_init */
 
+static int disk_shutdown (void)
+{
+#if KERNEL_LINUX
+#if HAVE_LIBUDEV
+       if (handle_udev != NULL)
+               udev_unref(handle_udev);
+#endif /* HAVE_LIBUDEV */
+#endif /* KERNEL_LINUX */
+       return (0);
+} /* int disk_shutdown */
+
 static void disk_submit (const char *plugin_instance,
                const char *type,
                derive_t read, derive_t write)
@@ -253,10 +300,6 @@ static void disk_submit (const char *plugin_instance,
        value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
 
-       /* Both `ignorelist' and `plugin_instance' may be NULL. */
-       if (ignorelist_match (ignorelist, plugin_instance) != 0)
-         return;
-
        values[0].derive = read;
        values[1].derive = write;
 
@@ -271,44 +314,40 @@ static void disk_submit (const char *plugin_instance,
        plugin_dispatch_values (&vl);
 } /* void disk_submit */
 
-#if KERNEL_LINUX
-static void submit_in_progress (char const *disk_name, gauge_t in_progress)
+#if KERNEL_FREEBSD || KERNEL_LINUX
+static void submit_io_time (char const *plugin_instance, derive_t io_time, derive_t weighted_time)
 {
-       value_t v;
+       value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
 
-       if (ignorelist_match (ignorelist, disk_name) != 0)
-         return;
-
-       v.gauge = in_progress;
+       values[0].derive = io_time;
+       values[1].derive = weighted_time;
 
-       vl.values = &v;
-       vl.values_len = 1;
+       vl.values = values;
+       vl.values_len = 2;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "disk", sizeof (vl.plugin));
-       sstrncpy (vl.plugin_instance, disk_name, sizeof (vl.plugin_instance));
-       sstrncpy (vl.type, "pending_operations", sizeof (vl.type));
+       sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "disk_io_time", sizeof (vl.type));
 
        plugin_dispatch_values (&vl);
-}
+} /* void submit_io_time */
+#endif /* KERNEL_FREEBSD || KERNEL_LINUX */
 
-static void submit_io_time (char const *plugin_instance, derive_t io_time, derive_t weighted_time)
+#if KERNEL_LINUX
+static void submit_in_progress (char const *disk_name, gauge_t in_progress)
 {
-       value_t values[2];
+       value_t v;
        value_list_t vl = VALUE_LIST_INIT;
 
-       if (ignorelist_match (ignorelist, plugin_instance) != 0)
-         return;
-
-       values[0].derive = io_time;
-       values[1].derive = weighted_time;
+       v.gauge = in_progress;
 
-       vl.values = values;
-       vl.values_len = 2;
+       vl.values = &v;
+       vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "disk", sizeof (vl.plugin));
-       sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
-       sstrncpy (vl.type, "disk_io_time", sizeof (vl.type));
+       sstrncpy (vl.plugin_instance, disk_name, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "pending_operations", sizeof (vl.type));
 
        plugin_dispatch_values (&vl);
 }
@@ -367,7 +406,7 @@ static signed long long dict_get_value (CFDictionaryRef dict, const char *key)
                DEBUG ("CFStringCreateWithCString (%s) failed.", key);
                return (-1LL);
        }
-       
+
        /* get => we don't need to release (== free) the object */
        val_obj = (CFNumberRef) CFDictionaryGetValue (dict, key_obj);
 
@@ -482,6 +521,15 @@ static int disk_read (void)
                else
                        ssnprintf (disk_name, sizeof (disk_name), "%i-%i", disk_major, disk_minor);
 
+               DEBUG ("disk plugin: disk_name = \"%s\"", disk_name);
+
+               /* check the name against ignore list */
+               if (ignorelist_match (ignorelist, disk_name) != 0) {
+                       CFRelease (props_dict);
+                       IOObjectRelease (disk);
+                       continue;
+               }
+
                /* extract the stats */
                read_ops  = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsReadsKey);
                read_byt  = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsBytesReadKey);
@@ -493,7 +541,6 @@ static int disk_read (void)
                IOObjectRelease (disk);
 
                /* and submit */
-               DEBUG ("disk plugin: disk_name = \"%s\"", disk_name);
                if ((read_byt != -1LL) || (write_byt != -1LL))
                        disk_submit (disk_name, "disk_octets", read_byt, write_byt);
                if ((read_ops != -1LL) || (write_ops != -1LL))
@@ -505,10 +552,130 @@ static int disk_read (void)
        IOObjectRelease (disk_list);
 /* #endif HAVE_IOKIT_IOKITLIB_H */
 
+#elif KERNEL_FREEBSD
+       int retry, dirty;
+
+       void *snap = NULL;
+       struct devstat *snap_iter;
+
+       struct gident *geom_id;
+
+       const char *disk_name;
+       long double read_time, write_time, busy_time, total_duration;
+
+       for (retry = 0, dirty = 1; retry < 5 && dirty == 1; retry++) {
+               if (snap != NULL)
+                       geom_stats_snapshot_free(snap);
+
+               /* Get a fresh copy of stats snapshot */
+               snap = geom_stats_snapshot_get();
+               if (snap == NULL) {
+                       ERROR("disk plugin: geom_stats_snapshot_get() failed.");
+                       return (-1);
+               }
+
+               /* Check if we have dirty read from this snapshot */
+               dirty = 0;
+               geom_stats_snapshot_reset(snap);
+               while ((snap_iter = geom_stats_snapshot_next(snap)) != NULL) {
+                       if (snap_iter->id == NULL)
+                               continue;
+                       geom_id = geom_lookupid(&geom_tree, snap_iter->id);
+
+                       /* New device? refresh GEOM tree */
+                       if (geom_id == NULL) {
+                               geom_deletetree(&geom_tree);
+                               if (geom_gettree(&geom_tree) != 0) {
+                                       ERROR("disk plugin: geom_gettree() failed");
+                                       geom_stats_snapshot_free(snap);
+                                       return (-1);
+                               }
+                               geom_id = geom_lookupid(&geom_tree, snap_iter->id);
+                       }
+                       /*
+                        * This should be rare: the device come right before we take the
+                        * snapshot and went away right after it.  We will handle this
+                        * case later, so don't mark dirty but silently ignore it.
+                        */
+                       if (geom_id == NULL)
+                               continue;
+
+                       /* Only collect PROVIDER data */
+                       if (geom_id->lg_what != ISPROVIDER)
+                               continue;
+
+                       /* Only collect data when rank is 1 (physical devices) */
+                       if (((struct gprovider *)(geom_id->lg_ptr))->lg_geom->lg_rank != 1)
+                               continue;
+
+                       /* Check if this is a dirty read quit for another try */
+                       if (snap_iter->sequence0 != snap_iter->sequence1) {
+                               dirty = 1;
+                               break;
+                       }
+               }
+       }
+
+       /* Reset iterator */
+       geom_stats_snapshot_reset(snap);
+       for (;;) {
+               snap_iter = geom_stats_snapshot_next(snap);
+               if (snap_iter == NULL)
+                       break;
+
+               if (snap_iter->id == NULL)
+                       continue;
+               geom_id = geom_lookupid(&geom_tree, snap_iter->id);
+               if (geom_id == NULL)
+                       continue;
+               if (geom_id->lg_what != ISPROVIDER)
+                       continue;
+               if (((struct gprovider *)(geom_id->lg_ptr))->lg_geom->lg_rank != 1)
+                       continue;
+               /* Skip dirty reads, if present */
+               if (dirty && (snap_iter->sequence0 != snap_iter->sequence1))
+                       continue;
+
+               disk_name = ((struct gprovider *)geom_id->lg_ptr)->lg_name;
+
+               if (ignorelist_match (ignorelist, disk_name) != 0)
+                       continue;
+
+               if ((snap_iter->bytes[DEVSTAT_READ] != 0) || (snap_iter->bytes[DEVSTAT_WRITE] != 0)) {
+                       disk_submit(disk_name, "disk_octets",
+                                       (derive_t)snap_iter->bytes[DEVSTAT_READ],
+                                       (derive_t)snap_iter->bytes[DEVSTAT_WRITE]);
+               }
+
+               if ((snap_iter->operations[DEVSTAT_READ] != 0) || (snap_iter->operations[DEVSTAT_WRITE] != 0)) {
+                       disk_submit(disk_name, "disk_ops",
+                                       (derive_t)snap_iter->operations[DEVSTAT_READ],
+                                       (derive_t)snap_iter->operations[DEVSTAT_WRITE]);
+               }
+
+               read_time = devstat_compute_etime(&snap_iter->duration[DEVSTAT_READ], NULL);
+               write_time = devstat_compute_etime(&snap_iter->duration[DEVSTAT_WRITE], NULL);
+               if ((read_time != 0) || (write_time != 0)) {
+                       disk_submit (disk_name, "disk_time",
+                                       (derive_t)(read_time*1000), (derive_t)(write_time*1000));
+               }
+               if (devstat_compute_statistics(snap_iter, NULL, 1.0,
+                   DSM_TOTAL_BUSY_TIME, &busy_time,
+                   DSM_TOTAL_DURATION, &total_duration,
+                   DSM_NONE) != 0) {
+                       WARNING("%s", devstat_errbuf);
+               }
+               else
+               {
+                       submit_io_time(disk_name, busy_time, total_duration);
+               }
+       }
+       geom_stats_snapshot_free(snap);
+
 #elif KERNEL_LINUX
        FILE *fh;
        char buffer[1024];
-       
+
        char *fields[32];
        int numfields;
        int fieldshift = 0;
@@ -544,15 +711,10 @@ static int disk_read (void)
                fieldshift = 1;
        }
 
-#if HAVE_LIBUDEV
-       handle_udev = udev_new();
-#endif
-
        while (fgets (buffer, sizeof (buffer), fh) != NULL)
        {
                char *disk_name;
                char *output_name;
-               char *alt_name;
 
                numfields = strsplit (buffer, fields, 32);
 
@@ -690,6 +852,16 @@ static int disk_read (void)
                        ds->read_time = read_time;
                        ds->write_ops = write_ops;
                        ds->write_time = write_time;
+
+                       if (read_merged || write_merged)
+                               ds->has_merged = 1;
+
+                       if (in_progress)
+                               ds->has_in_progress = 1;
+
+                       if (io_time)
+                               ds->has_io_time = 1;
+               
                } /* if (is_disk) */
 
                /* Don't write to the RRDs if we've just started.. */
@@ -712,13 +884,23 @@ static int disk_read (void)
                output_name = disk_name;
 
 #if HAVE_LIBUDEV
-               alt_name = disk_udev_attr_name (handle_udev, disk_name,
-                               conf_udev_name_attr);
-#else
-               alt_name = NULL;
+               char *alt_name = NULL;
+               if (conf_udev_name_attr != NULL)
+               {
+                       alt_name = disk_udev_attr_name (handle_udev, disk_name, conf_udev_name_attr);
+                       if (alt_name != NULL)
+                               output_name = alt_name;
+               }
 #endif
-               if (alt_name != NULL)
-                       output_name = alt_name;
+
+               if (ignorelist_match (ignorelist, output_name) != 0)
+               {
+#if HAVE_LIBUDEV
+                       /* release udev-based alternate name, if allocated */
+                       sfree (alt_name);
+#endif
+                       continue;
+               }
 
                if ((ds->read_bytes != 0) || (ds->write_bytes != 0))
                        disk_submit (output_name, "disk_octets",
@@ -734,19 +916,21 @@ static int disk_read (void)
 
                if (is_disk)
                {
-                       disk_submit (output_name, "disk_merged",
+                       if (ds->has_merged)
+                               disk_submit (output_name, "disk_merged",
                                        read_merged, write_merged);
-                       submit_in_progress (output_name, in_progress);
-                       submit_io_time (output_name, io_time, weighted_time);
+                       if (ds->has_in_progress)
+                               submit_in_progress (output_name, in_progress);
+                       if (ds->has_io_time)
+                               submit_io_time (output_name, io_time, weighted_time);
                } /* if (is_disk) */
 
+#if HAVE_LIBUDEV
                /* release udev-based alternate name, if allocated */
-               free(alt_name);
+               sfree (alt_name);
+#endif
        } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
 
-#if HAVE_LIBUDEV
-       udev_unref(handle_udev);
-#endif
 
        fclose (fh);
 /* #endif defined(KERNEL_LINUX) */
@@ -770,18 +954,20 @@ static int disk_read (void)
 #  error "kstat_io_t does not have the required members"
 # endif
        static kstat_io_t kio;
-       int i;
 
        if (kc == NULL)
                return (-1);
 
-       for (i = 0; i < numdisk; i++)
+       for (int i = 0; i < numdisk; i++)
        {
                if (kstat_read (kc, ksp[i], &kio) == -1)
                        continue;
 
                if (strncmp (ksp[i]->ks_class, "disk", 4) == 0)
                {
+                       if (ignorelist_match (ignorelist, ksp[i]->ks_name) != 0)
+                               continue;
+
                        disk_submit (ksp[i]->ks_name, "disk_octets",
                                        kio.KIO_ROCTETS, kio.KIO_WOCTETS);
                        disk_submit (ksp[i]->ks_name, "disk_ops",
@@ -792,6 +978,9 @@ static int disk_read (void)
                }
                else if (strncmp (ksp[i]->ks_class, "partition", 9) == 0)
                {
+                       if (ignorelist_match (ignorelist, ksp[i]->ks_name) != 0)
+                               continue;
+
                        disk_submit (ksp[i]->ks_name, "disk_octets",
                                        kio.KIO_ROCTETS, kio.KIO_WOCTETS);
                        disk_submit (ksp[i]->ks_name, "disk_ops",
@@ -807,15 +996,20 @@ static int disk_read (void)
 # else
        int disks;
 #endif
-       int counter;
        char name[DATA_MAX_NAME_LEN];
-       
+
        if ((ds = sg_get_disk_io_stats(&disks)) == NULL)
                return (0);
-               
-       for (counter=0; counter < disks; counter++) {
+
+       for (int counter = 0; counter < disks; counter++) {
                strncpy(name, ds->disk_name, sizeof(name));
                name[sizeof(name)-1] = '\0'; /* strncpy doesn't terminate longer strings */
+
+               if (ignorelist_match (ignorelist, name) != 0) {
+                       ds++;
+                       continue;
+               }
+
                disk_submit (name, "disk_octets", ds->read_bytes, ds->write_bytes);
                ds++;
        }
@@ -830,9 +1024,8 @@ static int disk_read (void)
        derive_t write_ops;
        perfstat_id_t firstpath;
        int rnumdisk;
-       int i;
 
-       if ((numdisk = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0)) < 0) 
+       if ((numdisk = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0)) < 0)
        {
                char errbuf[1024];
                WARNING ("disk plugin: perfstat_disk: %s",
@@ -841,14 +1034,14 @@ static int disk_read (void)
        }
 
        if (numdisk != pnumdisk || stat_disk==NULL) {
-               if (stat_disk!=NULL) 
+               if (stat_disk!=NULL)
                        free(stat_disk);
                stat_disk = (perfstat_disk_t *)calloc(numdisk, sizeof(perfstat_disk_t));
-       } 
+       }
        pnumdisk = numdisk;
 
        firstpath.name[0]='\0';
-       if ((rnumdisk = perfstat_disk(&firstpath, stat_disk, sizeof(perfstat_disk_t), numdisk)) < 0) 
+       if ((rnumdisk = perfstat_disk(&firstpath, stat_disk, sizeof(perfstat_disk_t), numdisk)) < 0)
        {
                char errbuf[1024];
                WARNING ("disk plugin: perfstat_disk : %s",
@@ -856,8 +1049,11 @@ static int disk_read (void)
                return (-1);
        }
 
-       for (i = 0; i < rnumdisk; i++) 
+       for (int i = 0; i < rnumdisk; i++)
        {
+               if (ignorelist_match (ignorelist, stat_disk[i].name) != 0)
+                       continue;
+
                read_sectors = stat_disk[i].rblks*stat_disk[i].bsize;
                write_sectors = stat_disk[i].wblks*stat_disk[i].bsize;
                disk_submit (stat_disk[i].name, "disk_octets", read_sectors, write_sectors);
@@ -882,5 +1078,6 @@ void module_register (void)
   plugin_register_config ("disk", disk_config,
       config_keys, config_keys_num);
   plugin_register_init ("disk", disk_init);
+  plugin_register_shutdown ("disk", disk_shutdown);
   plugin_register_read ("disk", disk_read);
 } /* void module_register */
index 3421c47..a2a4667 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
 #define _BSD_SOURCE
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
 #include "utils_dns.h"
-#include <pthread.h>
 #include <poll.h>
 
 #include <pcap.h>
 
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
+
 /*
  * Private data types
  */
@@ -94,11 +98,10 @@ static counter_list_t *counter_list_create (counter_list_t **list,
 {
        counter_list_t *entry;
 
-       entry = (counter_list_t *) malloc (sizeof (counter_list_t));
+       entry = calloc (1, sizeof (*entry));
        if (entry == NULL)
                return (NULL);
 
-       memset (entry, 0, sizeof (counter_list_t));
        entry->key = key;
        entry->value = value;
 
@@ -212,7 +215,7 @@ static int dns_run_pcap_loop (void)
 {
        pcap_t *pcap_obj;
        char    pcap_error[PCAP_ERRBUF_SIZE];
-       struct  bpf_program fp;
+       struct  bpf_program fp = { 0 };
 
        int status;
 
@@ -239,7 +242,6 @@ static int dns_run_pcap_loop (void)
                return (PCAP_ERROR);
        }
 
-       memset (&fp, 0, sizeof (fp));
        status = pcap_compile (pcap_obj, &fp, "udp port 53", 1, 0);
        if (status < 0)
        {
@@ -349,6 +351,20 @@ static int dns_init (void)
 
        listen_thread_init = 1;
 
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_NET_RAW)
+       if (check_capability (CAP_NET_RAW) != 0)
+       {
+               if (getuid () == 0)
+                       WARNING ("dns plugin: Running collectd as root, but the CAP_NET_RAW "
+                                       "capability is missing. The plugin's read function will probably "
+                                       "fail. Is your init system dropping capabilities?");
+               else
+                       WARNING ("dns plugin: collectd doesn't have the CAP_NET_RAW capability. "
+                                       "If you don't want to run collectd as root, try running \"setcap "
+                                       "cap_net_raw=ep\" on the collectd binary.");
+       }
+#endif
+
        return (0);
 } /* int dns_init */
 
@@ -392,7 +408,6 @@ static int dns_read (void)
        unsigned int keys[T_MAX];
        unsigned int values[T_MAX];
        int len;
-       int i;
 
        counter_list_t *ptr;
 
@@ -414,7 +429,7 @@ static int dns_read (void)
        }
        pthread_mutex_unlock (&qtype_mutex);
 
-       for (i = 0; i < len; i++)
+       for (int i = 0; i < len; i++)
        {
                DEBUG ("dns plugin: qtype = %u; counter = %u;", keys[i], values[i]);
                submit_derive ("dns_qtype", qtype_str (keys[i]), values[i]);
@@ -430,7 +445,7 @@ static int dns_read (void)
        }
        pthread_mutex_unlock (&opcode_mutex);
 
-       for (i = 0; i < len; i++)
+       for (int i = 0; i < len; i++)
        {
                DEBUG ("dns plugin: opcode = %u; counter = %u;", keys[i], values[i]);
                submit_derive ("dns_opcode", opcode_str (keys[i]), values[i]);
@@ -446,7 +461,7 @@ static int dns_read (void)
        }
        pthread_mutex_unlock (&rcode_mutex);
 
-       for (i = 0; i < len; i++)
+       for (int i = 0; i < len; i++)
        {
                DEBUG ("dns plugin: rcode = %u; counter = %u;", keys[i], values[i]);
                submit_derive ("dns_rcode", rcode_str (keys[i]), values[i]);
index d46bb02..70f03ca 100644 (file)
  See: http://www.drbd.org/users-guide/ch-admin.html#s-performance-indicators
 
  version: 8.3.11 (api:88/proto:86-96)
- srcversion: 71955441799F513ACA6DA60 
+ srcversion: 71955441799F513ACA6DA60
   0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate B r-----
         ns:64363752 nr:0 dw:357799284 dr:846902273 al:34987022 bm:18062 lo:0 \
                                                pe:0 ua:0 ap:0 ep:1 wo:f oos:0
  */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -69,7 +70,6 @@ static int drbd_submit_fields (long int resource,
        char plugin_instance[DATA_MAX_NAME_LEN];
        value_t values[fields_num];
        value_list_t vl = VALUE_LIST_INIT;
-       size_t i;
 
        if (resource < 0)
        {
@@ -88,7 +88,7 @@ static int drbd_submit_fields (long int resource,
        ssnprintf (plugin_instance, sizeof (plugin_instance), "r%ld",
                        resource);
 
-       for (i = 0; i < drbd_names_num; i++)
+       for (size_t i = 0; i < drbd_names_num; i++)
        {
                char *data;
                /* skip non numeric wo */
@@ -107,7 +107,7 @@ static int drbd_submit_fields (long int resource,
                        sizeof (vl.plugin_instance));
        sstrncpy (vl.type, "drbd_resource", sizeof (vl.type));
 
-       for (i = 0; i < fields_num; i++)
+       for (size_t i = 0; i < fields_num; i++)
        {
                if (drbd_names[i] == NULL)
                        continue;
index 6a0c0a4..9dce34c 100644 (file)
@@ -39,6 +39,7 @@
  */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
 
 #include <stddef.h>
 
-#if HAVE_LIBPTHREAD
-# include <pthread.h>
-#endif
-
-#include <sys/socket.h>
 #include <sys/un.h>
 #include <sys/select.h>
 
@@ -220,7 +216,7 @@ static int email_config (const char *key, const char *value)
 static void type_list_incr (type_list_t *list, char *name, int incr)
 {
        if (NULL == list->head) {
-               list->head = (type_t *)smalloc (sizeof (type_t));
+               list->head = smalloc (sizeof (*list->head));
 
                list->head->name  = sstrdup (name);
                list->head->value = incr;
@@ -237,7 +233,7 @@ static void type_list_incr (type_list_t *list, char *name, int incr)
                }
 
                if (NULL == ptr) {
-                       list->tail->next = (type_t *)smalloc (sizeof (type_t));
+                       list->tail->next = smalloc (sizeof (*list->tail->next));
                        list->tail = list->tail->next;
 
                        list->tail->name  = sstrdup (name);
@@ -390,8 +386,8 @@ static void *open_connection (void __attribute__((unused)) *arg)
 {
        struct sockaddr_un addr;
 
-       char *path  = (NULL == sock_file) ? SOCK_PATH : sock_file;
-       char *group = (NULL == sock_group) ? COLLECTD_GRP_NAME : sock_group;
+       const char *path  = (NULL == sock_file) ? SOCK_PATH : sock_file;
+       const char *group = (NULL == sock_group) ? COLLECTD_GRP_NAME : sock_group;
 
        /* create UNIX socket */
        errno = 0;
@@ -469,9 +465,6 @@ static void *open_connection (void __attribute__((unused)) *arg)
        }
 
        { /* initialize collector threads */
-               int i   = 0;
-               int err = 0;
-
                pthread_attr_t ptattr;
 
                conns.head = NULL;
@@ -483,16 +476,16 @@ static void *open_connection (void __attribute__((unused)) *arg)
                available_collectors = max_conns;
 
                collectors =
-                       (collector_t **)smalloc (max_conns * sizeof (collector_t *));
+                       smalloc (max_conns * sizeof (*collectors));
 
-               for (i = 0; i < max_conns; ++i) {
-                       collectors[i] = (collector_t *)smalloc (sizeof (collector_t));
+               for (int i = 0; i < max_conns; ++i) {
+                       collectors[i] = smalloc (sizeof (*collectors[i]));
                        collectors[i]->socket = NULL;
 
-                       if (0 != (err = plugin_thread_create (&collectors[i]->thread,
-                                                       &ptattr, collect, collectors[i]))) {
+                       if (plugin_thread_create (&collectors[i]->thread,
+                                                       &ptattr, collect, collectors[i]) != 0) {
                                char errbuf[1024];
-                               log_err ("pthread_create() failed: %s",
+                               log_err ("plugin_thread_create() failed: %s",
                                                sstrerror (errno, errbuf, sizeof (errbuf)));
                                collectors[i]->thread = (pthread_t) 0;
                        }
@@ -538,13 +531,12 @@ static void *open_connection (void __attribute__((unused)) *arg)
                        break;
                }
 
-               connection = malloc (sizeof (*connection));
+               connection = calloc (1, sizeof (*connection));
                if (connection == NULL)
                {
                        close (remote);
                        continue;
                }
-               memset (connection, 0, sizeof (*connection));
 
                connection->socket = fdopen (remote, "r");
                connection->next   = NULL;
@@ -577,13 +569,11 @@ static void *open_connection (void __attribute__((unused)) *arg)
 
 static int email_init (void)
 {
-       int err = 0;
-
-       if (0 != (err = plugin_thread_create (&connector, NULL,
-                               open_connection, NULL))) {
+       if (plugin_thread_create (&connector, NULL,
+                               open_connection, NULL) != 0) {
                char errbuf[1024];
                disabled = 1;
-               log_err ("pthread_create() failed: %s",
+               log_err ("plugin_thread_create() failed: %s",
                                sstrerror (errno, errbuf, sizeof (errbuf)));
                return (-1);
        }
@@ -612,8 +602,6 @@ static void type_list_free (type_list_t *t)
 
 static int email_shutdown (void)
 {
-       int i = 0;
-
        if (connector != ((pthread_t) 0)) {
                pthread_kill (connector, SIGTERM);
                connector = (pthread_t) 0;
@@ -630,7 +618,7 @@ static int email_shutdown (void)
        available_collectors = 0;
 
        if (collectors != NULL) {
-               for (i = 0; i < max_conns; ++i) {
+               for (int i = 0; i < max_conns; ++i) {
                        if (collectors[i] == NULL)
                                continue;
 
@@ -688,15 +676,12 @@ static void email_submit (const char *type, const char *type_instance, gauge_t v
  * after they have been copied to l2. */
 static void copy_type_list (type_list_t *l1, type_list_t *l2)
 {
-       type_t *ptr1;
-       type_t *ptr2;
-
        type_t *last = NULL;
 
-       for (ptr1 = l1->head, ptr2 = l2->head; NULL != ptr1;
+       for (type_t *ptr1 = l1->head, *ptr2 = l2->head; NULL != ptr1;
                        ptr1 = ptr1->next, last = ptr2, ptr2 = ptr2->next) {
                if (NULL == ptr2) {
-                       ptr2 = (type_t *)smalloc (sizeof (type_t));
+                       ptr2 = smalloc (sizeof (*ptr2));
                        ptr2->name = NULL;
                        ptr2->next = NULL;
 
@@ -722,8 +707,6 @@ static void copy_type_list (type_list_t *l1, type_list_t *l2)
 
 static int email_read (void)
 {
-       type_t *ptr;
-
        double score_old;
        int score_count_old;
 
@@ -737,7 +720,7 @@ static int email_read (void)
 
        pthread_mutex_unlock (&count_mutex);
 
-       for (ptr = list_count_copy.head; NULL != ptr; ptr = ptr->next) {
+       for (type_t *ptr = list_count_copy.head; NULL != ptr; ptr = ptr->next) {
                email_submit ("email_count", ptr->name, ptr->value);
        }
 
@@ -748,7 +731,7 @@ static int email_read (void)
 
        pthread_mutex_unlock (&size_mutex);
 
-       for (ptr = list_size_copy.head; NULL != ptr; ptr = ptr->next) {
+       for (type_t *ptr = list_size_copy.head; NULL != ptr; ptr = ptr->next) {
                email_submit ("email_size", ptr->name, ptr->value);
        }
 
@@ -772,7 +755,7 @@ static int email_read (void)
 
        pthread_mutex_unlock (&check_mutex);
 
-       for (ptr = list_check_copy.head; NULL != ptr; ptr = ptr->next)
+       for (type_t *ptr = list_check_copy.head; NULL != ptr; ptr = ptr->next)
                email_submit ("spam_check", ptr->name, ptr->value);
 
        return (0);
index 03de9ef..f4f4ac4 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
index a30a5d1..a213b60 100644 (file)
@@ -23,6 +23,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -104,14 +105,13 @@ static int ethstat_add_map (const oconfig_item_t *ci) /* {{{ */
     return (ENOMEM);
   }
 
-  map = malloc (sizeof (*map));
+  map = calloc (1, sizeof (*map));
   if (map == NULL)
   {
     sfree (key);
-    ERROR ("ethstat plugin: malloc(3) failed.");
+    ERROR ("ethstat plugin: calloc failed.");
     return (ENOMEM);
   }
-  memset (map, 0, sizeof (*map));
 
   sstrncpy (map->type, ci->values[1].value.string, sizeof (map->type));
   if (ci->values_num == 3)
@@ -120,7 +120,7 @@ static int ethstat_add_map (const oconfig_item_t *ci) /* {{{ */
 
   if (value_map == NULL)
   {
-    value_map = c_avl_create ((void *) strcmp);
+    value_map = c_avl_create ((int (*) (const void *, const void *)) strcmp);
     if (value_map == NULL)
     {
       sfree (map);
@@ -150,9 +150,7 @@ static int ethstat_add_map (const oconfig_item_t *ci) /* {{{ */
 
 static int ethstat_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -217,19 +215,13 @@ static void ethstat_submit_value (const char *device,
 static int ethstat_read_interface (char *device)
 {
   int fd;
-  struct ifreq req;
-  struct ethtool_drvinfo drvinfo;
   struct ethtool_gstrings *strings;
   struct ethtool_stats *stats;
   size_t n_stats;
   size_t strings_size;
   size_t stats_size;
-  size_t i;
   int status;
 
-  memset (&req, 0, sizeof (req));
-  sstrncpy(req.ifr_name, device, sizeof (req.ifr_name));
-
   fd = socket(AF_INET, SOCK_DGRAM, /* protocol = */ 0);
   if (fd < 0)
   {
@@ -239,9 +231,16 @@ static int ethstat_read_interface (char *device)
     return 1;
   }
 
-  memset (&drvinfo, 0, sizeof (drvinfo));
-  drvinfo.cmd = ETHTOOL_GDRVINFO;
-  req.ifr_data = (void *) &drvinfo;
+  struct ethtool_drvinfo drvinfo = {
+    .cmd = ETHTOOL_GDRVINFO
+  };
+
+  struct ifreq req = {
+    .ifr_data = (void *) &drvinfo
+  };
+
+  sstrncpy(req.ifr_name, device, sizeof (req.ifr_name));
+
   status = ioctl (fd, SIOCETHTOOL, &req);
   if (status < 0)
   {
@@ -273,7 +272,7 @@ static int ethstat_read_interface (char *device)
     close (fd);
     sfree (strings);
     sfree (stats);
-    ERROR("ethstat plugin: malloc(3) failed.");
+    ERROR("ethstat plugin: malloc failed.");
     return (-1);
   }
 
@@ -310,7 +309,7 @@ static int ethstat_read_interface (char *device)
     return (-1);
   }
 
-  for (i = 0; i < n_stats; i++)
+  for (size_t i = 0; i < n_stats; i++)
   {
     char *stat_name;
 
@@ -334,9 +333,7 @@ static int ethstat_read_interface (char *device)
 
 static int ethstat_read(void)
 {
-  size_t i;
-
-  for (i = 0; i < interfaces_num; i++)
+  for (size_t i = 0; i < interfaces_num; i++)
     ethstat_read_interface (interfaces[i]);
 
   return 0;
index 699be61..dfd4b05 100644 (file)
@@ -27,6 +27,7 @@
 #define _BSD_SOURCE /* For setgroups */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -38,7 +39,9 @@
 #include <grp.h>
 #include <signal.h>
 
-#include <pthread.h>
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
 
 #define PL_NORMAL        0x01
 #define PL_NOTIF_ACTION  0x02
@@ -126,13 +129,12 @@ static int exec_config_exec (oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  pl = (program_list_t *) malloc (sizeof (program_list_t));
+  pl = calloc (1, sizeof (*pl));
   if (pl == NULL)
   {
-    ERROR ("exec plugin: malloc failed.");
+    ERROR ("exec plugin: calloc failed.");
     return (-1);
   }
-  memset (pl, '\0', sizeof (program_list_t));
 
   if (strcasecmp ("NotificationExec", ci->key) == 0)
     pl->flags |= PL_NOTIF_ACTION;
@@ -163,16 +165,15 @@ static int exec_config_exec (oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  pl->argv = (char **) malloc (ci->values_num * sizeof (char *));
+  pl->argv = calloc (ci->values_num, sizeof (*pl->argv));
   if (pl->argv == NULL)
   {
-    ERROR ("exec plugin: malloc failed.");
+    ERROR ("exec plugin: calloc failed.");
     sfree (pl->exec);
     sfree (pl->user);
     sfree (pl);
     return (-1);
   }
-  memset (pl->argv, '\0', ci->values_num * sizeof (char *));
 
   {
     char *tmp = strrchr (ci->values[1].value.string, '/');
@@ -184,7 +185,7 @@ static int exec_config_exec (oconfig_item_t *ci) /* {{{ */
   pl->argv[0] = strdup (buffer);
   if (pl->argv[0] == NULL)
   {
-    ERROR ("exec plugin: malloc failed.");
+    ERROR ("exec plugin: strdup failed.");
     sfree (pl->argv);
     sfree (pl->exec);
     sfree (pl->user);
@@ -249,9 +250,7 @@ static int exec_config_exec (oconfig_item_t *ci) /* {{{ */
 
 static int exec_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
     if ((strcasecmp ("Exec", child->key) == 0)
@@ -350,7 +349,6 @@ static void reset_signal_mask (void) /* {{{ */
 {
   sigset_t ss;
 
-  memset (&ss, 0, sizeof (ss));
   sigemptyset (&ss);
   sigprocmask (SIG_SETMASK, &ss, /* old mask = */ NULL);
 } /* }}} void reset_signal_mask */
@@ -475,11 +473,10 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err)
   else if (pid == 0)
   {
     int fd_num;
-    int fd;
 
     /* Close all file descriptors but the pipe end we need. */
     fd_num = getdtablesize ();
-    for (fd = 0; fd < fd_num; fd++)
+    for (int fd = 0; fd < fd_num; fd++)
     {
       if ((fd == fd_pipe_in[0])
           || (fd == fd_pipe_out[1])
@@ -725,7 +722,6 @@ static void *exec_notification_one (void *arg) /* {{{ */
 {
   program_list_t *pl = ((program_list_and_notification_t *) arg)->pl;
   notification_t *n = &((program_list_and_notification_t *) arg)->n;
-  notification_meta_t *meta;
   int fd;
   FILE *fh;
   int pid;
@@ -773,7 +769,7 @@ static void *exec_notification_one (void *arg) /* {{{ */
   if (strlen (n->type_instance) > 0)
     fprintf (fh, "TypeInstance: %s\n", n->type_instance);
 
-  for (meta = n->meta; meta != NULL; meta = meta->next)
+  for (notification_meta_t *meta = n->meta; meta != NULL; meta = meta->next)
   {
     if (meta->type == NM_TYPE_STRING)
       fprintf (fh, "%s: %s\n", meta->name, meta->nm_value.nm_string);
@@ -808,20 +804,34 @@ static void *exec_notification_one (void *arg) /* {{{ */
 
 static int exec_init (void) /* {{{ */
 {
-  struct sigaction sa;
+  struct sigaction sa = {
+    .sa_handler = sigchld_handler
+  };
 
-  memset (&sa, '\0', sizeof (sa));
-  sa.sa_handler = sigchld_handler;
   sigaction (SIGCHLD, &sa, NULL);
 
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SETUID) && defined(CAP_SETGID)
+  if ((check_capability (CAP_SETUID) != 0) ||
+      (check_capability (CAP_SETGID) != 0))
+  {
+    if (getuid () == 0)
+      WARNING ("exec plugin: Running collectd as root, but the CAP_SETUID "
+          "or CAP_SETGID capabilities are missing. The plugin's read function "
+          "will probably fail. Is your init system dropping capabilities?");
+    else
+      WARNING ("exec plugin: collectd doesn't have the CAP_SETUID or "
+          "CAP_SETGID capabilities. If you don't want to run collectd as root, "
+          "try running \"setcap 'cap_setuid=ep cap_setgid=ep'\" on the "
+          "collectd binary.");
+  }
+#endif
+
   return (0);
 } /* int exec_init }}} */
 
 static int exec_read (void) /* {{{ */
 {
-  program_list_t *pl;
-
-  for (pl = pl_head; pl != NULL; pl = pl->next)
+  for (program_list_t *pl = pl_head; pl != NULL; pl = pl->next)
   {
     pthread_t t;
     pthread_attr_t attr;
@@ -852,10 +862,9 @@ static int exec_read (void) /* {{{ */
 static int exec_notification (const notification_t *n, /* {{{ */
     user_data_t __attribute__((unused)) *user_data)
 {
-  program_list_t *pl;
   program_list_and_notification_t *pln;
 
-  for (pl = pl_head; pl != NULL; pl = pl->next)
+  for (program_list_t *pl = pl_head; pl != NULL; pl = pl->next)
   {
     pthread_t t;
     pthread_attr_t attr;
@@ -868,8 +877,7 @@ static int exec_notification (const notification_t *n, /* {{{ */
     if (pl->pid != 0)
       continue;
 
-    pln = (program_list_and_notification_t *) malloc (sizeof
-        (program_list_and_notification_t));
+    pln = malloc (sizeof (*pln));
     if (pln == NULL)
     {
       ERROR ("exec plugin: malloc failed.");
index 666dacc..c7603c7 100644 (file)
@@ -18,6 +18,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
index 9ea8af7..9de9e6c 100644 (file)
@@ -22,8 +22,9 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
-#include "plugin.h"       
+#include "plugin.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -334,7 +335,6 @@ static int fc_config_add_dir (oconfig_item_t *ci)
 {
   fc_directory_conf_t *dir;
   int status;
-  int i;
 
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
   {
@@ -344,13 +344,12 @@ static int fc_config_add_dir (oconfig_item_t *ci)
   }
 
   /* Initialize `dir' */
-  dir = (fc_directory_conf_t *) malloc (sizeof (*dir));
+  dir = calloc (1, sizeof (*dir));
   if (dir == NULL)
   {
-    ERROR ("filecount plugin: malloc failed.");
+    ERROR ("filecount plugin: calloc failed.");
     return (-1);
   }
-  memset (dir, 0, sizeof (*dir));
 
   dir->path = strdup (ci->values[0].value.string);
   if (dir->path == NULL)
@@ -369,7 +368,7 @@ static int fc_config_add_dir (oconfig_item_t *ci)
   dir->size = 0;
 
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
@@ -400,7 +399,7 @@ static int fc_config_add_dir (oconfig_item_t *ci)
   {
     fc_directory_conf_t **temp;
 
-    temp = (fc_directory_conf_t **) realloc (directories,
+    temp = realloc (directories,
         sizeof (*directories) * (directories_num + 1));
     if (temp == NULL)
     {
@@ -429,9 +428,7 @@ static int fc_config_add_dir (oconfig_item_t *ci)
 
 static int fc_config (oconfig_item_t *ci)
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
     if (strcasecmp ("Directory", child->key) == 0)
@@ -542,7 +539,7 @@ static int fc_read_dir (fc_directory_conf_t *dir)
 
   if (dir->mtime != 0)
     dir->now = time (NULL);
-    
+
   status = walk_directory (dir->path, fc_read_dir_callback, dir,
       /* include hidden */ (dir->options & FC_HIDDEN) ? 1 : 0);
   if (status != 0)
@@ -558,9 +555,7 @@ static int fc_read_dir (fc_directory_conf_t *dir)
 
 static int fc_read (void)
 {
-  size_t i;
-
-  for (i = 0; i < directories_num; i++)
+  for (size_t i = 0; i < directories_num; i++)
     fc_read_dir (directories[i]);
 
   return (0);
index 8fbd271..33633d6 100644 (file)
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include <stdio.h>  /* a header needed for FILE */
@@ -158,7 +159,6 @@ static void fscache_read_stats_file (FILE *fh)
         char *lineptr;
         char *fields[32];
         int fields_num;
-        int i;
 
         /* Find the colon and replace it with a null byte */
         lineptr = strchr (linebuffer, ':');
@@ -175,14 +175,14 @@ static void fscache_read_stats_file (FILE *fh)
             section_len--;
             section[section_len] = 0;
         }
-        if (section_len <= 0)
+        if (section_len == 0)
             continue;
 
         fields_num = strsplit (lineptr, fields, STATIC_ARRAY_SIZE (fields));
         if (fields_num <= 0)
             continue;
 
-        for (i = 0; i < fields_num; i++)
+        for (int i = 0; i < fields_num; i++)
         {
             char *field_name;
             char *field_value_str;
index 2ac9f25..2b299ca 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "configfile.h"
 #include "utils_avltree.h"
 
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
 #if HAVE_NETDB_H
 # include <netdb.h>
 #endif
@@ -83,12 +78,12 @@ typedef struct staging_entry_s staging_entry_t;
 
 struct metric_map_s
 {
-  char *ganglia_name;
-  char *type;
-  char *type_instance;
-  char *ds_name;
-  int   ds_type;
-  int   ds_index;
+  char  *ganglia_name;
+  char  *type;
+  char  *type_instance;
+  char  *ds_name;
+  int    ds_type;
+  size_t ds_index;
 };
 typedef struct metric_map_s metric_map_t;
 
@@ -166,7 +161,7 @@ static metric_map_t *metric_lookup (const char *key) /* {{{ */
     return (NULL);
 
   /* Look up the DS type and ds_index. */
-  if ((map[i].ds_type < 0) || (map[i].ds_index < 0)) /* {{{ */
+  if (map[i].ds_type < 0) /* {{{ */
   {
     const data_set_t *ds;
 
@@ -191,7 +186,7 @@ static metric_map_t *metric_lookup (const char *key) /* {{{ */
     }
     else
     {
-      int j;
+      size_t j;
 
       for (j = 0; j < ds->ds_num; j++)
         if (strcasecmp (ds->ds[j].name, map[i].ds_name) == 0)
@@ -217,9 +212,7 @@ static int create_sockets (socket_entry_t **ret_sockets, /* {{{ */
     size_t *ret_sockets_num,
     const char *node, const char *service, int listen)
 {
-  struct addrinfo  ai_hints;
   struct addrinfo *ai_list;
-  struct addrinfo *ai_ptr;
   int              ai_return;
 
   socket_entry_t *sockets = NULL;
@@ -230,17 +223,12 @@ static int create_sockets (socket_entry_t **ret_sockets, /* {{{ */
   if (*ret_sockets != NULL)
     return (EINVAL);
 
-  memset (&ai_hints, 0, sizeof (ai_hints));
-  ai_hints.ai_flags    = 0;
-#ifdef AI_PASSIVE
-  ai_hints.ai_flags |= AI_PASSIVE;
-#endif
-#ifdef AI_ADDRCONFIG
-  ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
-  ai_hints.ai_family   = AF_UNSPEC;
-  ai_hints.ai_socktype = SOCK_DGRAM;
-  ai_hints.ai_protocol = IPPROTO_UDP;
+  struct addrinfo ai_hints = {
+    .ai_family = AF_UNSPEC,
+    .ai_flags = AI_ADDRCONFIG | AI_PASSIVE,
+    .ai_protocol = IPPROTO_UDP,
+    .ai_socktype = SOCK_DGRAM
+  };
 
   ai_return = getaddrinfo (node, service, &ai_hints, &ai_list);
   if (ai_return != 0)
@@ -255,7 +243,7 @@ static int create_sockets (socket_entry_t **ret_sockets, /* {{{ */
     return (-1);
   }
 
-  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) /* {{{ */
+  for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) /* {{{ */
   {
     socket_entry_t *tmp;
 
@@ -314,7 +302,6 @@ static int create_sockets (socket_entry_t **ret_sockets, /* {{{ */
     if (ai_ptr->ai_family == AF_INET)
     {
       struct sockaddr_in *addr;
-      struct ip_mreq mreq;
       int loop;
 
       addr = (struct sockaddr_in *) ai_ptr->ai_addr;
@@ -326,19 +313,32 @@ static int create_sockets (socket_entry_t **ret_sockets, /* {{{ */
       }
 
       loop = 1;
-      setsockopt (sockets[sockets_num].fd, IPPROTO_IP, IP_MULTICAST_LOOP,
+      status = setsockopt (sockets[sockets_num].fd, IPPROTO_IP, IP_MULTICAST_LOOP,
           (void *) &loop, sizeof (loop));
+      if (status != 0)
+      {
+        char errbuf[1024];
+        WARNING ("gmond plugin: setsockopt(2) failed: %s",
+                 sstrerror (errno, errbuf, sizeof (errbuf)));
+      }
+
+      struct ip_mreq mreq = {
+        .imr_multiaddr.s_addr = addr->sin_addr.s_addr,
+        .imr_interface.s_addr = htonl (INADDR_ANY)
+      };
 
-      memset (&mreq, 0, sizeof (mreq));
-      mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
-      mreq.imr_interface.s_addr = htonl (INADDR_ANY);
-      setsockopt (sockets[sockets_num].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+      status = setsockopt (sockets[sockets_num].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
           (void *) &mreq, sizeof (mreq));
+      if (status != 0)
+      {
+        char errbuf[1024];
+        WARNING ("gmond plugin: setsockopt(2) failed: %s",
+                 sstrerror (errno, errbuf, sizeof (errbuf)));
+      }
     } /* if (ai_ptr->ai_family == AF_INET) */
     else if (ai_ptr->ai_family == AF_INET6)
     {
       struct sockaddr_in6 *addr;
-      struct ipv6_mreq mreq;
       int loop;
 
       addr = (struct sockaddr_in6 *) ai_ptr->ai_addr;
@@ -350,15 +350,29 @@ static int create_sockets (socket_entry_t **ret_sockets, /* {{{ */
       }
 
       loop = 1;
-      setsockopt (sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
+      status = setsockopt (sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
           (void *) &loop, sizeof (loop));
+      if (status != 0)
+      {
+        char errbuf[1024];
+        WARNING ("gmond plugin: setsockopt(2) failed: %s",
+                 sstrerror (errno, errbuf, sizeof (errbuf)));
+      }
+
+      struct ipv6_mreq mreq = {
+        .ipv6mr_interface = 0 /* any */
+      };
 
-      memset (&mreq, 0, sizeof (mreq));
       memcpy (&mreq.ipv6mr_multiaddr,
           &addr->sin6_addr, sizeof (addr->sin6_addr));
-      mreq.ipv6mr_interface = 0; /* any */
-      setsockopt (sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
+      status = setsockopt (sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
           (void *) &mreq, sizeof (mreq));
+      if (status != 0)
+      {
+        char errbuf[1024];
+        WARNING ("gmond plugin: setsockopt(2) failed: %s",
+                 sstrerror (errno, errbuf, sizeof (errbuf)));
+      }
     } /* if (ai_ptr->ai_family == AF_INET6) */
 
     sockets_num++;
@@ -379,13 +393,10 @@ static int create_sockets (socket_entry_t **ret_sockets, /* {{{ */
 
 static int request_meta_data (const char *host, const char *name) /* {{{ */
 {
-  Ganglia_metadata_msg msg;
-  char buffer[BUFF_SIZE];
+  Ganglia_metadata_msg msg = { 0 };
+  char buffer[BUFF_SIZE] = { 0 };
   unsigned int buffer_size;
   XDR xdr;
-  size_t i;
-
-  memset (&msg, 0, sizeof (msg));
 
   msg.id = gmetadata_request;
   msg.Ganglia_metadata_msg_u.grequest.metric_id.host = strdup (host);
@@ -399,7 +410,6 @@ static int request_meta_data (const char *host, const char *name) /* {{{ */
     return (-1);
   }
 
-  memset (buffer, 0, sizeof (buffer));
   xdrmem_create (&xdr, buffer, sizeof (buffer), XDR_ENCODE);
 
   if (!xdr_Ganglia_metadata_msg (&xdr, &msg))
@@ -415,7 +425,7 @@ static int request_meta_data (const char *host, const char *name) /* {{{ */
       host, name);
 
   pthread_mutex_lock (&mc_send_sockets_lock);
-  for (i = 0; i < mc_send_sockets_num; i++)
+  for (size_t i = 0; i < mc_send_sockets_num; i++)
   {
     ssize_t status = sendto (mc_send_sockets[i].fd, buffer, (size_t) buffer_size,
         /* flags = */ 0,
@@ -457,10 +467,9 @@ static staging_entry_t *staging_entry_get (const char *host, /* {{{ */
     return (se);
 
   /* insert new entry */
-  se = (staging_entry_t *) malloc (sizeof (*se));
+  se = calloc (1, sizeof (*se));
   if (se == NULL)
     return (NULL);
-  memset (se, 0, sizeof (*se));
 
   sstrncpy (se->key, key, sizeof (se->key));
   se->flags = 0;
@@ -496,7 +505,7 @@ static staging_entry_t *staging_entry_get (const char *host, /* {{{ */
 
 static int staging_entry_update (const char *host, const char *name, /* {{{ */
     const char *type, const char *type_instance,
-    int ds_index, int ds_type, value_t value)
+    size_t ds_index, int ds_type, value_t value)
 {
   const data_set_t *ds;
   staging_entry_t *se;
@@ -510,7 +519,7 @@ static int staging_entry_update (const char *host, const char *name, /* {{{ */
 
   if (ds->ds_num <= ds_index)
   {
-    ERROR ("gmond plugin: Invalid index %i: %s has only %i data source(s).",
+    ERROR ("gmond plugin: Invalid index %zu: %s has only %zu data source(s).",
         ds_index, ds->type, ds->ds_num);
     return (-1);
   }
@@ -696,7 +705,7 @@ static int mc_handle_metadata_msg (Ganglia_metadata_msg *msg) /* {{{ */
 
       msg_meta = msg->Ganglia_metadata_msg_u.gfull;
 
-      if (msg_meta.metric.tmax <= 0)
+      if (msg_meta.metric.tmax == 0)
         return (-1);
 
       map = metric_lookup (msg_meta.metric_id.name);
@@ -764,9 +773,8 @@ static int mc_handle_metric (void *buffer, size_t buffer_size) /* {{{ */
     case gmetric_float:
     case gmetric_double:
     {
-      Ganglia_value_msg msg;
+      Ganglia_value_msg msg = { 0 };
 
-      memset (&msg, 0, sizeof (msg));
       if (xdr_Ganglia_value_msg (&xdr, &msg))
         mc_handle_value_msg (&msg);
       break;
@@ -775,8 +783,7 @@ static int mc_handle_metric (void *buffer, size_t buffer_size) /* {{{ */
     case gmetadata_full:
     case gmetadata_request:
     {
-      Ganglia_metadata_msg msg;
-      memset (&msg, 0, sizeof (msg));
+      Ganglia_metadata_msg msg = { 0 };
       if (xdr_Ganglia_metadata_msg (&xdr, &msg))
         mc_handle_metadata_msg (&msg);
       break;
@@ -820,7 +827,6 @@ static void *mc_receive_thread (void *arg) /* {{{ */
 {
   socket_entry_t *mc_receive_socket_entries;
   int status;
-  size_t i;
 
   mc_receive_socket_entries = NULL;
   status = create_sockets (&mc_receive_socket_entries, &mc_receive_sockets_num,
@@ -838,7 +844,7 @@ static void *mc_receive_thread (void *arg) /* {{{ */
   if (mc_receive_sockets == NULL)
   {
     ERROR ("gmond plugin: calloc failed.");
-    for (i = 0; i < mc_receive_sockets_num; i++)
+    for (size_t i = 0; i < mc_receive_sockets_num; i++)
       close (mc_receive_socket_entries[i].fd);
     free (mc_receive_socket_entries);
     mc_receive_socket_entries = NULL;
@@ -846,7 +852,7 @@ static void *mc_receive_thread (void *arg) /* {{{ */
     return ((void *) -1);
   }
 
-  for (i = 0; i < mc_receive_sockets_num; i++)
+  for (size_t i = 0; i < mc_receive_sockets_num; i++)
   {
     mc_receive_sockets[i].fd = mc_receive_socket_entries[i].fd;
     mc_receive_sockets[i].events = POLLIN | POLLPRI;
@@ -866,7 +872,7 @@ static void *mc_receive_thread (void *arg) /* {{{ */
       break;
     }
 
-    for (i = 0; i < mc_receive_sockets_num; i++)
+    for (size_t i = 0; i < mc_receive_sockets_num; i++)
     {
       if (mc_receive_sockets[i].revents != 0)
         mc_handle_socket (mc_receive_sockets + i);
@@ -916,7 +922,7 @@ static int mc_receive_thread_stop (void) /* {{{ */
   return (0);
 } /* }}} int mc_receive_thread_stop */
 
-/* 
+/*
  * Config:
  *
  * <Plugin gmond>
@@ -954,7 +960,6 @@ static int gmond_config_set_string (oconfig_item_t *ci, char **str) /* {{{ */
 static int gmond_config_add_metric (oconfig_item_t *ci) /* {{{ */
 {
   metric_map_t *map;
-  int i;
 
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
   {
@@ -986,7 +991,7 @@ static int gmond_config_add_metric (oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
     if (strcasecmp ("Type", child->key) == 0)
@@ -1063,9 +1068,7 @@ static int gmond_config_set_address (oconfig_item_t *ci, /* {{{ */
 
 static int gmond_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
     if (strcasecmp ("MCReceiveFrom", child->key) == 0)
@@ -1089,7 +1092,7 @@ static int gmond_init (void) /* {{{ */
       (mc_receive_port != NULL) ? mc_receive_port : MC_RECEIVE_PORT_DEFAULT,
       /* listen = */ 0);
 
-  staging_tree = c_avl_create ((void *) strcmp);
+  staging_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
   if (staging_tree == NULL)
   {
     ERROR ("gmond plugin: c_avl_create failed.");
@@ -1103,12 +1106,10 @@ static int gmond_init (void) /* {{{ */
 
 static int gmond_shutdown (void) /* {{{ */
 {
-  size_t i;
-
   mc_receive_thread_stop ();
 
   pthread_mutex_lock (&mc_send_sockets_lock);
-  for (i = 0; i < mc_send_sockets_num; i++)
+  for (size_t i = 0; i < mc_send_sockets_num; i++)
   {
     close (mc_send_sockets[i].fd);
     mc_send_sockets[i].fd = -1;
diff --git a/src/gps.c b/src/gps.c
new file mode 100644 (file)
index 0000000..19f317c
--- /dev/null
+++ b/src/gps.c
@@ -0,0 +1,368 @@
+/**
+ * collectd - src/gps.c
+ * Copyright (C) 2015  Nicolas JOURDEN
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Nicolas JOURDEN <nicolas.jourden at laposte.net>
+ *   Florian octo Forster <octo at collectd.org>
+ *   Marc Fournier <marc.fournier at camptocamp.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_time.h"
+#include "configfile.h"
+
+#define CGPS_TRUE                  1
+#define CGPS_FALSE                 0
+#define CGPS_DEFAULT_HOST          "localhost"
+#define CGPS_DEFAULT_PORT          "2947" /* DEFAULT_GPSD_PORT */
+#define CGPS_DEFAULT_TIMEOUT       MS_TO_CDTIME_T (15)
+#define CGPS_DEFAULT_PAUSE_CONNECT TIME_T_TO_CDTIME_T (5)
+#define CGPS_MAX_ERROR             100
+#define CGPS_CONFIG                "?WATCH={\"enable\":true,\"json\":true,\"nmea\":false}\r\n"
+
+#include <gps.h>
+#include <pthread.h>
+
+typedef struct {
+  char *host;
+  char *port;
+  cdtime_t timeout;
+  cdtime_t pause_connect;
+} cgps_config_t;
+
+typedef struct {
+  gauge_t sats_used;
+  gauge_t sats_visible;
+  gauge_t hdop;
+  gauge_t vdop;
+} cgps_data_t;
+
+static cgps_config_t cgps_config_data;
+
+static cgps_data_t cgps_data = {NAN, NAN, NAN, NAN};
+
+static pthread_t cgps_thread_id;
+static pthread_mutex_t  cgps_data_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t  cgps_thread_lock = PTHREAD_MUTEX_INITIALIZER;
+static int cgps_thread_shutdown = CGPS_FALSE;
+static int cgps_thread_running = CGPS_FALSE;
+
+/**
+ * Non blocking pause for the thread.
+ */
+static int cgps_thread_pause(cdtime_t pTime)
+{
+  cdtime_t now;
+  now = cdtime ();
+  struct timespec pause_th;
+  CDTIME_T_TO_TIMESPEC (MS_TO_CDTIME_T(10), &pause_th);
+  while (CGPS_TRUE)
+  {
+    if ( (cdtime () - now) > pTime )
+    {
+      break;
+    }
+
+    pthread_mutex_lock (&cgps_thread_lock);
+    if (cgps_thread_shutdown == CGPS_TRUE)
+    {
+      return CGPS_FALSE;
+    }
+    pthread_mutex_unlock (&cgps_thread_lock);
+    nanosleep (&pause_th, NULL);
+ }
+
+ return CGPS_TRUE;
+}
+
+/**
+ * Thread reading from gpsd.
+ */
+static void * cgps_thread (void * pData)
+{
+  struct gps_data_t gpsd_conn;
+  unsigned int err_count;
+  cgps_thread_running = CGPS_TRUE;
+
+  while (CGPS_TRUE)
+  {
+    pthread_mutex_lock (&cgps_thread_lock);
+    if (cgps_thread_shutdown == CGPS_TRUE)
+    {
+      goto quit;
+    }
+    pthread_mutex_unlock (&cgps_thread_lock);
+
+    err_count = 0;
+
+#if GPSD_API_MAJOR_VERSION > 4
+    int status = gps_open (cgps_config_data.host, cgps_config_data.port, &gpsd_conn);
+#else
+    int status = gps_open_r (cgps_config_data.host, cgps_config_data.port, &gpsd_conn);
+#endif
+    if (status < 0)
+    {
+      WARNING ("gps plugin: connecting to %s:%s failed: %s",
+               cgps_config_data.host, cgps_config_data.port, gps_errstr (status));
+
+      // Here we make a pause until a new tentative to connect, we check also if
+      // the thread does not need to stop.
+      if (cgps_thread_pause(cgps_config_data.pause_connect) == CGPS_FALSE)
+      {
+        goto quit;
+      }
+
+      continue;
+    }
+
+    gps_stream (&gpsd_conn, WATCH_ENABLE | WATCH_JSON | WATCH_NEWSTYLE, NULL);
+    gps_send (&gpsd_conn, CGPS_CONFIG);
+
+    while (CGPS_TRUE)
+    {
+      pthread_mutex_lock (&cgps_thread_lock);
+      if (cgps_thread_shutdown == CGPS_TRUE)
+      {
+        goto stop;
+      }
+      pthread_mutex_unlock (&cgps_thread_lock);
+
+#if GPSD_API_MAJOR_VERSION > 4
+      long timeout_us = CDTIME_T_TO_US (cgps_config_data.timeout);
+      if (!gps_waiting (&gpsd_conn, (int) timeout_us ))
+#else
+      if (!gps_waiting (&gpsd_conn))
+#endif
+      {
+        continue;
+      }
+
+      if (gps_read (&gpsd_conn) == -1)
+      {
+        WARNING ("gps plugin: incorrect data! (err_count: %d)", err_count);
+        err_count++;
+
+        if (err_count > CGPS_MAX_ERROR)
+        {
+          // Server is not responding ...
+          if (gps_send (&gpsd_conn, CGPS_CONFIG) == -1)
+          {
+            WARNING ("gps plugin: gpsd seems to be down, reconnecting");
+            gps_close (&gpsd_conn);
+            break;
+          }
+          // Server is responding ...
+          else
+          {
+            err_count = 0;
+          }
+        }
+
+        continue;
+      }
+
+      pthread_mutex_lock (&cgps_data_lock);
+
+      // Number of sats in view:
+      cgps_data.sats_used = (gauge_t) gpsd_conn.satellites_used;
+      cgps_data.sats_visible = (gauge_t) gpsd_conn.satellites_visible;
+
+      // dilution of precision:
+      cgps_data.vdop = NAN;
+      cgps_data.hdop = NAN;
+      if (cgps_data.sats_used > 0)
+      {
+        cgps_data.hdop = gpsd_conn.dop.hdop;
+        cgps_data.vdop = gpsd_conn.dop.vdop;
+      }
+
+      DEBUG ("gps plugin: %.0f sats used (of %.0f visible), hdop = %.3f, vdop = %.3f",
+             cgps_data.sats_used, cgps_data.sats_visible, cgps_data.hdop, cgps_data.vdop);
+
+      pthread_mutex_unlock (&cgps_data_lock);
+    }
+  }
+
+stop:
+  DEBUG ("gps plugin: thread closing gpsd connection ... ");
+  gps_stream (&gpsd_conn, WATCH_DISABLE, NULL);
+  gps_close (&gpsd_conn);
+quit:
+  DEBUG ("gps plugin: thread shutting down ... ");
+  cgps_thread_running = CGPS_FALSE;
+  pthread_mutex_unlock (&cgps_thread_lock);
+  pthread_exit (NULL);
+}
+
+
+/**
+ * Submit a piece of the data.
+ */
+static void cgps_submit (const char *type, gauge_t value, const char *type_instance)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "gps", sizeof (vl.plugin));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+  sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+}
+
+/**
+ * Read the data and submit by piece.
+ */
+static int cgps_read (void)
+{
+  cgps_data_t data_copy;
+
+  pthread_mutex_lock (&cgps_data_lock);
+  data_copy = cgps_data;
+  pthread_mutex_unlock (&cgps_data_lock);
+
+  cgps_submit ("dilution_of_precision", data_copy.hdop, "horizontal");
+  cgps_submit ("dilution_of_precision", data_copy.vdop, "vertical");
+  cgps_submit ("satellites", data_copy.sats_used, "used");
+  cgps_submit ("satellites", data_copy.sats_visible, "visible");
+
+  return (0);
+}
+
+/**
+ * Read configuration.
+ */
+static int cgps_config (oconfig_item_t *ci)
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Host", child->key) == 0)
+      cf_util_get_string (child, &cgps_config_data.host);
+    else if (strcasecmp ("Port", child->key) == 0)
+      cf_util_get_service (child, &cgps_config_data.port);
+    else if (strcasecmp ("Timeout", child->key) == 0)
+      cf_util_get_cdtime (child, &cgps_config_data.timeout);
+    else if (strcasecmp ("PauseConnect", child->key) == 0)
+      cf_util_get_cdtime (child, &cgps_config_data.pause_connect);
+    else
+      WARNING ("gps plugin: Ignoring unknown config option \"%s\".", child->key);
+  }
+
+  // Controlling the value for timeout:
+  // If set too high it blocks the reading (> 5 s), too low it gets not reading (< 500 us).
+  // To avoid any issues we replace "out of range" value by the default value.
+  if (
+    cgps_config_data.timeout > TIME_T_TO_CDTIME_T(5)
+    ||
+    cgps_config_data.timeout < US_TO_CDTIME_T(500)
+  )
+  {
+    WARNING ("gps plugin: timeout set to %.6f sec. setting to default (%.6f).",
+      CDTIME_T_TO_DOUBLE(cgps_config_data.timeout),
+      CDTIME_T_TO_DOUBLE(CGPS_DEFAULT_TIMEOUT)
+    );
+    cgps_config_data.timeout = CGPS_DEFAULT_TIMEOUT;
+  }
+
+  return (0);
+}
+
+/**
+ * Init.
+ */
+static int cgps_init (void)
+{
+  int status;
+
+  if (cgps_thread_running == CGPS_TRUE)
+  {
+    DEBUG ("gps plugin: error gps thread already running ... ");
+    return 0;
+  }
+
+  DEBUG ("gps plugin: config{host: \"%s\", port: \"%s\", timeout: %.6f sec., pause connect: %.3f sec.}",
+         cgps_config_data.host, cgps_config_data.port,
+         CDTIME_T_TO_DOUBLE (cgps_config_data.timeout),
+         CDTIME_T_TO_DOUBLE (cgps_config_data.pause_connect));
+
+  status = plugin_thread_create (&cgps_thread_id, NULL, cgps_thread, NULL);
+  if (status != 0)
+  {
+    ERROR ("gps plugin: pthread_create() failed.");
+    return (-1);
+  }
+
+  return (0);
+}
+
+/**
+ * Shutdown.
+ */
+static int cgps_shutdown (void)
+{
+  void * res;
+
+  pthread_mutex_lock (&cgps_thread_lock);
+  cgps_thread_shutdown = CGPS_TRUE;
+  pthread_mutex_unlock (&cgps_thread_lock);
+
+  pthread_join(cgps_thread_id, &res);
+  free(res);
+
+  // Clean mutex:
+  pthread_mutex_unlock(&cgps_thread_lock);
+  pthread_mutex_destroy(&cgps_thread_lock);
+  pthread_mutex_unlock(&cgps_data_lock);
+  pthread_mutex_destroy(&cgps_data_lock);
+
+  sfree (cgps_config_data.port);
+  sfree (cgps_config_data.host);
+
+  return (0);
+}
+
+/**
+ * Register the module.
+ */
+void module_register (void)
+{
+  cgps_config_data.host = sstrdup (CGPS_DEFAULT_HOST);
+  cgps_config_data.port = sstrdup (CGPS_DEFAULT_PORT);
+  cgps_config_data.timeout = CGPS_DEFAULT_TIMEOUT;
+  cgps_config_data.pause_connect = CGPS_DEFAULT_PAUSE_CONNECT;
+
+  plugin_register_complex_config ("gps", cgps_config);
+  plugin_register_init ("gps", cgps_init);
+  plugin_register_read ("gps", cgps_read);
+  plugin_register_shutdown ("gps", cgps_shutdown);
+}
diff --git a/src/grpc.cc b/src/grpc.cc
new file mode 100644 (file)
index 0000000..ae3dab2
--- /dev/null
@@ -0,0 +1,661 @@
+/**
+ * collectd - src/grpc.cc
+ * Copyright (C) 2015-2016 Sebastian Harl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Sebastian Harl <sh at tokkee.org>
+ **/
+
+#include <grpc++/grpc++.h>
+#include <google/protobuf/util/time_util.h>
+
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include "collectd.grpc.pb.h"
+
+extern "C" {
+#include <fnmatch.h>
+#include <stdbool.h>
+
+#include "collectd.h"
+#include "common.h"
+#include "configfile.h"
+#include "plugin.h"
+
+#include "daemon/utils_cache.h"
+}
+
+using collectd::Collectd;
+
+using collectd::DispatchValuesRequest;
+using collectd::DispatchValuesReply;
+using collectd::QueryValuesRequest;
+using collectd::QueryValuesReply;
+
+using google::protobuf::util::TimeUtil;
+
+/*
+ * private types
+ */
+
+struct Listener {
+       grpc::string addr;
+       grpc::string port;
+
+       grpc::SslServerCredentialsOptions *ssl;
+};
+static std::vector<Listener> listeners;
+static grpc::string default_addr("0.0.0.0:50051");
+
+/*
+ * helper functions
+ */
+
+static bool ident_matches(const value_list_t *vl, const value_list_t *matcher)
+{
+       if (fnmatch(matcher->host, vl->host, 0))
+               return false;
+
+       if (fnmatch(matcher->plugin, vl->plugin, 0))
+               return false;
+       if (fnmatch(matcher->plugin_instance, vl->plugin_instance, 0))
+               return false;
+
+       if (fnmatch(matcher->type, vl->type, 0))
+               return false;
+       if (fnmatch(matcher->type_instance, vl->type_instance, 0))
+               return false;
+
+       return true;
+} /* ident_matches */
+
+static grpc::string read_file(const char *filename)
+{
+       std::ifstream f;
+       grpc::string s, content;
+
+       f.open(filename);
+       if (!f.is_open()) {
+               ERROR("grpc: Failed to open '%s'", filename);
+               return "";
+       }
+
+       while (std::getline(f, s)) {
+               content += s;
+               content.push_back('\n');
+       }
+       f.close();
+       return content;
+} /* read_file */
+
+/*
+ * proto conversion
+ */
+
+static void marshal_ident(const value_list_t *vl, collectd::types::Identifier *msg)
+{
+       msg->set_host(vl->host);
+       msg->set_plugin(vl->plugin);
+       if (vl->plugin_instance[0] != '\0')
+               msg->set_plugin_instance(vl->plugin_instance);
+       msg->set_type(vl->type);
+       if (vl->type_instance[0] != '\0')
+               msg->set_type_instance(vl->type_instance);
+} /* marshal_ident */
+
+static grpc::Status unmarshal_ident(const collectd::types::Identifier &msg, value_list_t *vl,
+               bool require_fields)
+{
+       std::string s;
+
+       s = msg.host();
+       if (!s.length() && require_fields)
+               return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+                               grpc::string("missing host name"));
+       sstrncpy(vl->host, s.c_str(), sizeof(vl->host));
+
+       s = msg.plugin();
+       if (!s.length() && require_fields)
+               return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+                               grpc::string("missing plugin name"));
+       sstrncpy(vl->plugin, s.c_str(), sizeof(vl->plugin));
+
+       s = msg.type();
+       if (!s.length() && require_fields)
+               return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+                               grpc::string("missing type name"));
+       sstrncpy(vl->type, s.c_str(), sizeof(vl->type));
+
+       s = msg.plugin_instance();
+       sstrncpy(vl->plugin_instance, s.c_str(), sizeof(vl->plugin_instance));
+
+       s = msg.type_instance();
+       sstrncpy(vl->type_instance, s.c_str(), sizeof(vl->type_instance));
+
+       return grpc::Status::OK;
+} /* unmarshal_ident() */
+
+static grpc::Status marshal_value_list(const value_list_t *vl, collectd::types::ValueList *msg)
+{
+       auto id = msg->mutable_identifier();
+       marshal_ident(vl, id);
+
+       auto ds = plugin_get_ds(vl->type);
+       if ((ds == NULL) || (ds->ds_num != vl->values_len)) {
+               return grpc::Status(grpc::StatusCode::INTERNAL,
+                               grpc::string("failed to retrieve data-set for values"));
+       }
+
+       auto t = TimeUtil::NanosecondsToTimestamp(CDTIME_T_TO_NS(vl->time));
+       auto d = TimeUtil::NanosecondsToDuration(CDTIME_T_TO_NS(vl->interval));
+       msg->set_allocated_time(new google::protobuf::Timestamp(t));
+       msg->set_allocated_interval(new google::protobuf::Duration(d));
+
+       for (size_t i = 0; i < vl->values_len; ++i) {
+               auto v = msg->add_value();
+               switch (ds->ds[i].type) {
+                       case DS_TYPE_COUNTER:
+                               v->set_counter(vl->values[i].counter);
+                               break;
+                       case DS_TYPE_GAUGE:
+                               v->set_gauge(vl->values[i].gauge);
+                               break;
+                       case DS_TYPE_DERIVE:
+                               v->set_derive(vl->values[i].derive);
+                               break;
+                       case DS_TYPE_ABSOLUTE:
+                               v->set_absolute(vl->values[i].absolute);
+                               break;
+                       default:
+                               return grpc::Status(grpc::StatusCode::INTERNAL,
+                                               grpc::string("unknown value type"));
+               }
+       }
+
+       return grpc::Status::OK;
+} /* marshal_value_list */
+
+static grpc::Status unmarshal_value_list(const collectd::types::ValueList &msg, value_list_t *vl)
+{
+       vl->time = NS_TO_CDTIME_T(TimeUtil::TimestampToNanoseconds(msg.time()));
+       vl->interval = NS_TO_CDTIME_T(TimeUtil::DurationToNanoseconds(msg.interval()));
+
+       auto status = unmarshal_ident(msg.identifier(), vl, true);
+       if (!status.ok())
+               return status;
+
+       value_t *values = NULL;
+       size_t values_len = 0;
+
+       status = grpc::Status::OK;
+       for (auto v : msg.value()) {
+               value_t *val = (value_t *)realloc(values, (values_len + 1) * sizeof(*values));
+               if (!val) {
+                       status = grpc::Status(grpc::StatusCode::RESOURCE_EXHAUSTED,
+                                       grpc::string("failed to allocate values array"));
+                       break;
+               }
+
+               values = val;
+               val = values + values_len;
+               values_len++;
+
+               switch (v.value_case()) {
+               case collectd::types::Value::ValueCase::kCounter:
+                       val->counter = counter_t(v.counter());
+                       break;
+               case collectd::types::Value::ValueCase::kGauge:
+                       val->gauge = gauge_t(v.gauge());
+                       break;
+               case collectd::types::Value::ValueCase::kDerive:
+                       val->derive = derive_t(v.derive());
+                       break;
+               case collectd::types::Value::ValueCase::kAbsolute:
+                       val->absolute = absolute_t(v.absolute());
+                       break;
+               default:
+                       status = grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+                                       grpc::string("unknown value type"));
+                       break;
+               }
+
+               if (!status.ok())
+                       break;
+       }
+       if (status.ok()) {
+               vl->values = values;
+               vl->values_len = values_len;
+       }
+       else if (values) {
+               free(values);
+       }
+
+       return status;
+} /* unmarshal_value_list() */
+
+/*
+ * request call-backs and call objects
+ */
+
+static grpc::Status Process(grpc::ServerContext *ctx,
+               DispatchValuesRequest request, DispatchValuesReply *reply)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+       auto status = unmarshal_value_list(request.values(), &vl);
+       if (!status.ok())
+               return status;
+
+       if (plugin_dispatch_values(&vl))
+               status = grpc::Status(grpc::StatusCode::INTERNAL,
+                               grpc::string("failed to enqueue values for writing"));
+       return status;
+} /* Process(): DispatchValues */
+
+static grpc::Status Process(grpc::ServerContext *ctx,
+               QueryValuesRequest request, QueryValuesReply *reply)
+{
+       uc_iter_t *iter;
+       char *name = NULL;
+
+       value_list_t matcher;
+       auto status = unmarshal_ident(request.identifier(), &matcher, false);
+       if (!status.ok())
+               return status;
+
+       if ((iter = uc_get_iterator()) == NULL) {
+               return grpc::Status(grpc::StatusCode::INTERNAL,
+                               grpc::string("failed to query values: cannot create iterator"));
+       }
+
+       status = grpc::Status::OK;
+       while (uc_iterator_next(iter, &name) == 0) {
+               value_list_t res;
+               if (parse_identifier_vl(name, &res) != 0) {
+                       status = grpc::Status(grpc::StatusCode::INTERNAL,
+                                       grpc::string("failed to parse identifier"));
+                       break;
+               }
+
+               if (!ident_matches(&res, &matcher))
+                       continue;
+
+               if (uc_iterator_get_time(iter, &res.time) < 0) {
+                       status = grpc::Status(grpc::StatusCode::INTERNAL,
+                                       grpc::string("failed to retrieve value timestamp"));
+                       break;
+               }
+               if (uc_iterator_get_interval(iter, &res.interval) < 0) {
+                       status = grpc::Status(grpc::StatusCode::INTERNAL,
+                                       grpc::string("failed to retrieve value interval"));
+                       break;
+               }
+               if (uc_iterator_get_values(iter, &res.values, &res.values_len) < 0) {
+                       status = grpc::Status(grpc::StatusCode::INTERNAL,
+                                       grpc::string("failed to retrieve values"));
+                       break;
+               }
+
+               auto vl = reply->add_values();
+               status = marshal_value_list(&res, vl);
+               free(res.values);
+               if (!status.ok())
+                       break;
+       }
+
+       uc_iterator_destroy(iter);
+
+       return status;
+} /* Process(): QueryValues */
+
+class Call
+{
+public:
+       Call(Collectd::AsyncService *service, grpc::ServerCompletionQueue *cq)
+               : service_(service), cq_(cq), status_(CREATE)
+       { }
+
+       virtual ~Call()
+       { }
+
+       void Handle()
+       {
+               if (status_ == CREATE) {
+                       Create();
+                       status_ = PROCESS;
+               }
+               else if (status_ == PROCESS) {
+                       Process();
+                       status_ = FINISH;
+               }
+               else {
+                       GPR_ASSERT(status_ == FINISH);
+                       Finish();
+               }
+       } /* Handle() */
+
+protected:
+       virtual void Create() = 0;
+       virtual void Process() = 0;
+       virtual void Finish() = 0;
+
+       Collectd::AsyncService *service_;
+       grpc::ServerCompletionQueue *cq_;
+       grpc::ServerContext ctx_;
+
+private:
+       enum CallStatus { CREATE, PROCESS, FINISH };
+       CallStatus status_;
+}; /* class Call */
+
+template<typename RequestT, typename ReplyT>
+class RpcCall final : public Call
+{
+       typedef void (Collectd::AsyncService::*CreatorT)(grpc::ServerContext *,
+                       RequestT *, grpc::ServerAsyncResponseWriter<ReplyT> *,
+                       grpc::CompletionQueue *, grpc::ServerCompletionQueue *, void *);
+
+public:
+       RpcCall(Collectd::AsyncService *service,
+                       CreatorT creator, grpc::ServerCompletionQueue *cq)
+               : Call(service, cq), creator_(creator), responder_(&ctx_)
+       {
+               Handle();
+       } /* RpcCall() */
+
+       virtual ~RpcCall()
+       { }
+
+private:
+       void Create()
+       {
+               (service_->*creator_)(&ctx_, &request_, &responder_, cq_, cq_, this);
+       } /* Create() */
+
+       void Process()
+       {
+               // Add a new request object to the queue.
+               new RpcCall<RequestT, ReplyT>(service_, creator_, cq_);
+               grpc::Status status = ::Process(&ctx_, request_, &reply_);
+               responder_.Finish(reply_, status, this);
+       } /* Process() */
+
+       void Finish()
+       {
+               delete this;
+       } /* Finish() */
+
+       CreatorT creator_;
+
+       RequestT request_;
+       ReplyT reply_;
+
+       grpc::ServerAsyncResponseWriter<ReplyT> responder_;
+}; /* class RpcCall */
+
+/*
+ * gRPC server implementation
+ */
+
+class CollectdServer final
+{
+public:
+       void Start()
+       {
+               auto auth = grpc::InsecureServerCredentials();
+
+               grpc::ServerBuilder builder;
+
+               if (listeners.empty()) {
+                       builder.AddListeningPort(default_addr, auth);
+                       INFO("grpc: Listening on %s", default_addr.c_str());
+               }
+               else {
+                       for (auto l : listeners) {
+                               grpc::string addr = l.addr + ":" + l.port;
+
+                               auto use_ssl = grpc::string("");
+                               auto a = auth;
+                               if (l.ssl != nullptr) {
+                                       use_ssl = grpc::string(" (SSL enabled)");
+                                       a = grpc::SslServerCredentials(*l.ssl);
+                               }
+
+                               builder.AddListeningPort(addr, a);
+                               INFO("grpc: Listening on %s%s", addr.c_str(), use_ssl.c_str());
+                       }
+               }
+
+               builder.RegisterService(&service_);
+               cq_ = builder.AddCompletionQueue();
+               server_ = builder.BuildAndStart();
+       } /* Start() */
+
+       void Shutdown()
+       {
+               server_->Shutdown();
+               cq_->Shutdown();
+       } /* Shutdown() */
+
+       void Mainloop()
+       {
+               // Register request types.
+               new RpcCall<DispatchValuesRequest, DispatchValuesReply>(&service_,
+                               &Collectd::AsyncService::RequestDispatchValues, cq_.get());
+               new RpcCall<QueryValuesRequest, QueryValuesReply>(&service_,
+                               &Collectd::AsyncService::RequestQueryValues, cq_.get());
+
+               while (true) {
+                       void *req = NULL;
+                       bool ok = false;
+
+                       if (!cq_->Next(&req, &ok))
+                               break; // Queue shut down.
+                       if (!ok) {
+                               ERROR("grpc: Failed to read from queue");
+                               break;
+                       }
+
+                       static_cast<Call *>(req)->Handle();
+               }
+       } /* Mainloop() */
+
+private:
+       Collectd::AsyncService service_;
+
+       std::unique_ptr<grpc::Server> server_;
+       std::unique_ptr<grpc::ServerCompletionQueue> cq_;
+}; /* class CollectdServer */
+
+static CollectdServer *server = nullptr;
+
+/*
+ * collectd plugin interface
+ */
+
+extern "C" {
+       static pthread_t *workers;
+       static size_t workers_num = 5;
+
+       static void *worker_thread(void *arg)
+       {
+               CollectdServer *s = (CollectdServer *)arg;
+               s->Mainloop();
+               return NULL;
+       } /* worker_thread() */
+
+       static int c_grpc_config_listen(oconfig_item_t *ci)
+       {
+               if ((ci->values_num != 2)
+                               || (ci->values[0].type != OCONFIG_TYPE_STRING)
+                               || (ci->values[1].type != OCONFIG_TYPE_STRING)) {
+                       ERROR("grpc: The `%s` config option needs exactly "
+                                       "two string argument (address and port).", ci->key);
+                       return -1;
+               }
+
+               auto listener = Listener();
+               listener.addr = grpc::string(ci->values[0].value.string);
+               listener.port = grpc::string(ci->values[1].value.string);
+               listener.ssl = nullptr;
+
+               auto ssl_opts = new(grpc::SslServerCredentialsOptions);
+               grpc::SslServerCredentialsOptions::PemKeyCertPair pkcp = {};
+               bool use_ssl = false;
+
+               for (int i = 0; i < ci->children_num; i++) {
+                       oconfig_item_t *child = ci->children + i;
+
+                       if (!strcasecmp("EnableSSL", child->key)) {
+                               if (cf_util_get_boolean(child, &use_ssl)) {
+                                       ERROR("grpc: Option `%s` expects a boolean value",
+                                                       child->key);
+                                       return -1;
+                               }
+                       }
+                       else if (!strcasecmp("SSLRootCerts", child->key)) {
+                               char *certs = NULL;
+                               if (cf_util_get_string(child, &certs)) {
+                                       ERROR("grpc: Option `%s` expects a string value",
+                                                       child->key);
+                                       return -1;
+                               }
+                               ssl_opts->pem_root_certs = read_file(certs);
+                       }
+                       else if (!strcasecmp("SSLServerKey", child->key)) {
+                               char *key = NULL;
+                               if (cf_util_get_string(child, &key)) {
+                                       ERROR("grpc: Option `%s` expects a string value",
+                                                       child->key);
+                                       return -1;
+                               }
+                               pkcp.private_key = read_file(key);
+                       }
+                       else if (!strcasecmp("SSLServerCert", child->key)) {
+                               char *cert = NULL;
+                               if (cf_util_get_string(child, &cert)) {
+                                       ERROR("grpc: Option `%s` expects a string value",
+                                                       child->key);
+                                       return -1;
+                               }
+                               pkcp.cert_chain = read_file(cert);
+                       }
+                       else {
+                               WARNING("grpc: Option `%s` not allowed in <%s> block.",
+                                               child->key, ci->key);
+                       }
+               }
+
+               ssl_opts->pem_key_cert_pairs.push_back(pkcp);
+               if (use_ssl)
+                       listener.ssl = ssl_opts;
+               else
+                       delete(ssl_opts);
+
+               listeners.push_back(listener);
+               return 0;
+       } /* c_grpc_config_listen() */
+
+       static int c_grpc_config(oconfig_item_t *ci)
+       {
+               int i;
+
+               for (i = 0; i < ci->children_num; i++) {
+                       oconfig_item_t *child = ci->children + i;
+
+                       if (!strcasecmp("Listen", child->key)) {
+                               if (c_grpc_config_listen(child))
+                                       return -1;
+                       }
+                       else if (!strcasecmp("WorkerThreads", child->key)) {
+                               int n;
+                               if (cf_util_get_int(child, &n))
+                                       return -1;
+                               workers_num = (size_t)n;
+                       }
+                       else {
+                               WARNING("grpc: Option `%s` not allowed here.", child->key);
+                       }
+               }
+
+               return 0;
+       } /* c_grpc_config() */
+
+       static int c_grpc_init(void)
+       {
+               server = new CollectdServer();
+               size_t i;
+
+               if (! server) {
+                       ERROR("grpc: Failed to create server");
+                       return -1;
+               }
+
+               workers = (pthread_t *)calloc(workers_num, sizeof(*workers));
+               if (! workers) {
+                       delete server;
+                       server = nullptr;
+
+                       ERROR("grpc: Failed to allocate worker threads");
+                       return -1;
+               }
+
+               server->Start();
+               for (i = 0; i < workers_num; i++) {
+                       plugin_thread_create(&workers[i], /* attr = */ NULL,
+                                       worker_thread, server);
+               }
+               INFO("grpc: Started %zu workers", workers_num);
+               return 0;
+       } /* c_grpc_init() */
+
+       static int c_grpc_shutdown(void)
+       {
+               size_t i;
+
+               if (!server)
+                       return -1;
+
+               server->Shutdown();
+
+               INFO("grpc: Waiting for %zu workers to terminate", workers_num);
+               for (i = 0; i < workers_num; i++)
+                       pthread_join(workers[i], NULL);
+               free(workers);
+               workers = NULL;
+               workers_num = 0;
+
+               delete server;
+               server = nullptr;
+
+               return 0;
+       } /* c_grpc_shutdown() */
+
+       void module_register(void)
+       {
+               plugin_register_complex_config("grpc", c_grpc_config);
+               plugin_register_init("grpc", c_grpc_init);
+               plugin_register_shutdown("grpc", c_grpc_shutdown);
+       } /* module_register() */
+} /* extern "C" */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
index 82c158c..8213e97 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
 # include <netdb.h>
-# include <sys/socket.h>
 # include <netinet/in.h>
 # include <netinet/tcp.h>
 # include <libgen.h> /* for basename */
@@ -89,19 +89,9 @@ static int hddtemp_query_daemon (char *buffer, int buffer_size)
        const char *host;
        const char *port;
 
-       struct addrinfo  ai_hints;
-       struct addrinfo *ai_list, *ai_ptr;
+       struct addrinfo *ai_list;
        int              ai_return;
 
-       memset (&ai_hints, '\0', sizeof (ai_hints));
-       ai_hints.ai_flags    = 0;
-#ifdef AI_ADDRCONFIG
-       ai_hints.ai_flags   |= AI_ADDRCONFIG;
-#endif
-       ai_hints.ai_family   = PF_UNSPEC;
-       ai_hints.ai_socktype = SOCK_STREAM;
-       ai_hints.ai_protocol = IPPROTO_TCP;
-
        host = hddtemp_host;
        if (host == NULL)
                host = HDDTEMP_DEF_HOST;
@@ -110,6 +100,13 @@ static int hddtemp_query_daemon (char *buffer, int buffer_size)
        if (strlen (port) == 0)
                port = HDDTEMP_DEF_PORT;
 
+       struct addrinfo ai_hints = {
+               .ai_flags = AI_ADDRCONFIG,
+               .ai_family = AF_UNSPEC,
+               .ai_protocol = IPPROTO_TCP,
+               .ai_socktype = SOCK_STREAM
+       };
+
        if ((ai_return = getaddrinfo (host, port, &ai_hints, &ai_list)) != 0)
        {
                char errbuf[1024];
@@ -122,7 +119,7 @@ static int hddtemp_query_daemon (char *buffer, int buffer_size)
        }
 
        fd = -1;
-       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
        {
                /* create our socket descriptor */
                fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype,
@@ -253,7 +250,6 @@ static int hddtemp_read (void)
        char *saveptr;
        int num_fields;
        int num_disks;
-       int i;
 
        /* get data from daemon */
        if (hddtemp_query_daemon (buf, sizeof (buf)) < 0)
@@ -274,7 +270,7 @@ static int hddtemp_read (void)
 
        num_disks = num_fields / 4;
 
-       for (i = 0; i < num_disks; i++)
+       for (int i = 0; i < num_disks; i++)
        {
                char *name;
                double temperature;
index df8ffb4..a74699e 100644 (file)
@@ -23,6 +23,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -31,9 +32,6 @@
 #if HAVE_SYS_TYPES_H
 #  include <sys/types.h>
 #endif
-#if HAVE_SYS_SOCKET_H
-#  include <sys/socket.h>
-#endif
 
 /* One cannot include both. This sucks. */
 #if HAVE_LINUX_IF_H
@@ -87,17 +85,20 @@ static const char *config_keys[] =
 {
        "Interface",
        "IgnoreSelected",
-       NULL
+       "ReportInactive",
 };
-static int config_keys_num = 2;
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
 static ignorelist_t *ignorelist = NULL;
 
+static _Bool report_inactive = 1;
+
 #ifdef HAVE_LIBKSTAT
 #define MAX_NUMIF 256
 extern kstat_ctl_t *kc;
 static kstat_t *ksp[MAX_NUMIF];
 static int numif = 0;
+static _Bool unique_name = 0;
 #endif /* HAVE_LIBKSTAT */
 
 static int interface_config (const char *key, const char *value)
@@ -116,6 +117,17 @@ static int interface_config (const char *key, const char *value)
                        invert = 0;
                ignorelist_set_invert (ignorelist, invert);
        }
+       else if (strcasecmp (key, "ReportInactive") == 0)
+               report_inactive = IS_TRUE (value);
+       else if (strcasecmp (key, "UniqueName") == 0)
+       {
+               #ifdef HAVE_LIBKSTAT
+               if (IS_TRUE (value))
+                       unique_name = 1;
+               #else
+                       WARNING ("interface plugin: the \"UniqueName\" option is only valid on Solaris.");
+               #endif /* HAVE_LIBKSTAT */
+       }
        else
        {
                return (-1);
@@ -128,7 +140,6 @@ static int interface_config (const char *key, const char *value)
 static int interface_init (void)
 {
        kstat_t *ksp_chain;
-       derive_t val;
 
        numif = 0;
 
@@ -145,7 +156,7 @@ static int interface_init (void)
                        continue;
                if (kstat_read (kc, ksp_chain, NULL) == -1)
                        continue;
-               if ((val = get_kstat_value (ksp_chain, "obytes")) == -1LL)
+               if (get_kstat_value (ksp_chain, "obytes") == -1LL)
                        continue;
                ksp[numif++] = ksp_chain;
        }
@@ -181,9 +192,8 @@ static int interface_read (void)
 {
 #if HAVE_GETIFADDRS
        struct ifaddrs *if_list;
-       struct ifaddrs *if_ptr;
 
-/* Darin/Mac OS X and possible other *BSDs */
+/* Darwin/Mac OS X and possible other *BSDs */
 #if HAVE_STRUCT_IF_DATA
 #  define IFA_DATA if_data
 #  define IFA_RX_BYTES ifi_ibytes
@@ -211,11 +221,14 @@ static int interface_read (void)
        if (getifaddrs (&if_list) != 0)
                return (-1);
 
-       for (if_ptr = if_list; if_ptr != NULL; if_ptr = if_ptr->ifa_next)
+       for (struct ifaddrs *if_ptr = if_list; if_ptr != NULL; if_ptr = if_ptr->ifa_next)
        {
                if (if_ptr->ifa_addr != NULL && if_ptr->ifa_addr->sa_family == AF_LINK) {
                        if_data = (struct IFA_DATA *) if_ptr->ifa_data;
 
+                       if (!report_inactive && if_data->IFA_RX_PACKT == 0 && if_data->IFA_TX_PACKT == 0)
+                               continue;
+
                        if_submit (if_ptr->ifa_name, "if_octets",
                                if_data->IFA_RX_BYTES,
                                if_data->IFA_TX_BYTES);
@@ -268,78 +281,95 @@ static int interface_read (void)
                if (numfields < 11)
                        continue;
 
-               incoming = atoll (fields[0]);
-               outgoing = atoll (fields[8]);
-               if_submit (device, "if_octets", incoming, outgoing);
-
                incoming = atoll (fields[1]);
                outgoing = atoll (fields[9]);
+               if (!report_inactive && incoming == 0 && outgoing == 0)
+                       continue;
+
                if_submit (device, "if_packets", incoming, outgoing);
 
+               incoming = atoll (fields[0]);
+               outgoing = atoll (fields[8]);
+               if_submit (device, "if_octets", incoming, outgoing);
+
                incoming = atoll (fields[2]);
                outgoing = atoll (fields[10]);
                if_submit (device, "if_errors", incoming, outgoing);
+
+               incoming = atoll (fields[3]);
+               outgoing = atoll (fields[11]);
+               if_submit (device, "if_dropped", incoming, outgoing);
        }
 
        fclose (fh);
 /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKSTAT
-       int i;
        derive_t rx;
        derive_t tx;
+       char iname[DATA_MAX_NAME_LEN];
 
        if (kc == NULL)
                return (-1);
 
-       for (i = 0; i < numif; i++)
+       for (int i = 0; i < numif; i++)
        {
                if (kstat_read (kc, ksp[i], NULL) == -1)
                        continue;
 
+               if (unique_name)
+                       ssnprintf(iname, sizeof(iname), "%s_%d_%s", ksp[i]->ks_module, ksp[i]->ks_instance, ksp[i]->ks_name);
+               else
+                       sstrncpy(iname, ksp[i]->ks_name, sizeof(iname));
+
                /* try to get 64bit counters */
-               rx = get_kstat_value (ksp[i], "rbytes64");
-               tx = get_kstat_value (ksp[i], "obytes64");
+               rx = get_kstat_value (ksp[i], "ipackets64");
+               tx = get_kstat_value (ksp[i], "opackets64");
                /* or fallback to 32bit */
                if (rx == -1LL)
-                       rx = get_kstat_value (ksp[i], "rbytes");
+                       rx = get_kstat_value (ksp[i], "ipackets");
                if (tx == -1LL)
-                       tx = get_kstat_value (ksp[i], "obytes");
+                       tx = get_kstat_value (ksp[i], "opackets");
+               if (!report_inactive && rx == 0 && tx == 0)
+                       continue;
                if ((rx != -1LL) || (tx != -1LL))
-                       if_submit (ksp[i]->ks_name, "if_octets", rx, tx);
+                       if_submit (iname, "if_packets", rx, tx);
 
                /* try to get 64bit counters */
-               rx = get_kstat_value (ksp[i], "ipackets64");
-               tx = get_kstat_value (ksp[i], "opackets64");
+               rx = get_kstat_value (ksp[i], "rbytes64");
+               tx = get_kstat_value (ksp[i], "obytes64");
                /* or fallback to 32bit */
                if (rx == -1LL)
-                       rx = get_kstat_value (ksp[i], "ipackets");
+                       rx = get_kstat_value (ksp[i], "rbytes");
                if (tx == -1LL)
-                       tx = get_kstat_value (ksp[i], "opackets");
+                       tx = get_kstat_value (ksp[i], "obytes");
                if ((rx != -1LL) || (tx != -1LL))
-                       if_submit (ksp[i]->ks_name, "if_packets", rx, tx);
+                       if_submit (iname, "if_octets", rx, tx);
 
                /* no 64bit error counters yet */
                rx = get_kstat_value (ksp[i], "ierrors");
                tx = get_kstat_value (ksp[i], "oerrors");
                if ((rx != -1LL) || (tx != -1LL))
-                       if_submit (ksp[i]->ks_name, "if_errors", rx, tx);
+                       if_submit (iname, "if_errors", rx, tx);
        }
 /* #endif HAVE_LIBKSTAT */
 
 #elif defined(HAVE_LIBSTATGRAB)
        sg_network_io_stats *ios;
-       int i, num;
+       int num;
 
        ios = sg_get_network_io_stats (&num);
 
-       for (i = 0; i < num; i++)
+       for (int i = 0; i < num; i++) {
+               if (!report_inactive && ios[i].rx == 0 && ios[i].tx == 0)
+                       continue;
                if_submit (ios[i].interface_name, "if_octets", ios[i].rx, ios[i].tx);
+       }
 /* #endif HAVE_LIBSTATGRAB */
 
 #elif defined(HAVE_PERFSTAT)
        perfstat_id_t id;
-       int i, ifs;
+       int ifs;
 
        if ((nif =  perfstat_netinterface(NULL, NULL, sizeof(perfstat_netinterface_t), 0)) < 0)
        {
@@ -351,9 +381,8 @@ static int interface_read (void)
 
        if (pnif != nif || ifstat == NULL)
        {
-               if (ifstat != NULL)
-                       free(ifstat);
-               ifstat = malloc(nif * sizeof(perfstat_netinterface_t));
+               free(ifstat);
+               ifstat = malloc(nif * sizeof (*ifstat));
        }
        pnif = nif;
 
@@ -366,8 +395,11 @@ static int interface_read (void)
                return (-1);
        }
 
-       for (i = 0; i < ifs; i++)
+       for (int i = 0; i < ifs; i++)
        {
+               if (!report_inactive && ifstat[i].ipackets == 0 && ifstat[i].opackets == 0)
+                       continue;
+
                if_submit (ifstat[i].name, "if_octets", ifstat[i].ibytes, ifstat[i].obytes);
                if_submit (ifstat[i].name, "if_packets", ifstat[i].ipackets ,ifstat[i].opackets);
                if_submit (ifstat[i].name, "if_errors", ifstat[i].ierrors, ifstat[i].oerrors );
@@ -386,3 +418,4 @@ void module_register (void)
 #endif
        plugin_register_read ("interface", interface_read);
 } /* void module_register */
+
index b403847..70c55dc 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -27,6 +27,7 @@
  */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -213,7 +214,7 @@ static caddr_t ipc_get_info (cid_t cid, int cmd, int version, int stsize, int *n
 
   *nmemb = size / stsize;
 
-  buff = (caddr_t)malloc (size);
+  buff = malloc (size);
   if (buff == NULL)  {
     ERROR ("ipc plugin: ipc_get_info malloc failed.");
     return (NULL);
@@ -236,14 +237,14 @@ static int ipc_read_sem (void) /* {{{ */
   ipcinfo_sem_t *ipcinfo_sem;
   unsigned short sem_nsems=0;
   unsigned short sems=0;
-  int i,n;
+  int n;
 
   ipcinfo_sem = (ipcinfo_sem_t *)ipc_get_info(0,
     GET_IPCINFO_SEM_ALL, IPCINFO_SEM_VERSION, sizeof(ipcinfo_sem_t), &n);
   if (ipcinfo_sem == NULL)
     return -1;
 
-  for (i=0; i<n; i++) {
+  for (int i=0; i<n; i++) {
     sem_nsems += ipcinfo_sem[i].sem_nsems;
     sems++;
   }
@@ -261,14 +262,14 @@ static int ipc_read_shm (void) /* {{{ */
   ipcinfo_shm_t *pshm;
   unsigned int shm_segments=0;
   size64_t shm_bytes=0;
-  int i,n;
+  int n;
 
   ipcinfo_shm = (ipcinfo_shm_t *)ipc_get_info(0,
     GET_IPCINFO_SHM_ALL, IPCINFO_SHM_VERSION, sizeof(ipcinfo_shm_t), &n);
   if (ipcinfo_shm == NULL)
     return -1;
 
-  for (i=0, pshm=ipcinfo_shm; i<n; i++, pshm++) {
+  for (int i=0, pshm=ipcinfo_shm; i<n; i++, pshm++) {
     shm_segments++;
     shm_bytes += pshm->shm_segsz;
   }
@@ -287,18 +288,18 @@ static int ipc_read_msg (void) /* {{{ */
   uint32_t msg_used_space=0;
   uint32_t msg_alloc_queues=0;
   msgqnum32_t msg_qnum=0;
-  int i,n;
+  int n;
 
   ipcinfo_msg = (ipcinfo_msg_t *)ipc_get_info(0,
     GET_IPCINFO_MSG_ALL, IPCINFO_MSG_VERSION, sizeof(ipcinfo_msg_t), &n);
   if (ipcinfo_msg == NULL)
     return -1;
 
-  for (i=0; i<n; i++) {
+  for (int i=0; i<n; i++) {
     msg_alloc_queues++;
     msg_used_space += ipcinfo_msg[i].msg_cbytes;
     msg_qnum += ipcinfo_msg[i].msg_qnum;
-
+  }
   free(ipcinfo_msg);
 
   ipc_submit_g("msg", "count", "queues", msg_alloc_queues);
index 51d33dc..ad62299 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_ignorelist.h"
 
-#include <pthread.h>
-
 #include <OpenIPMI/ipmiif.h>
 #include <OpenIPMI/ipmi_err.h>
 #include <OpenIPMI/ipmi_posix.h>
@@ -82,9 +81,7 @@ static int c_ipmi_nofiy_notpresent = 0;
  */
 static void c_ipmi_error (const char *func, int status)
 {
-  char errbuf[4096];
-
-  memset (errbuf, 0, sizeof (errbuf));
+  char errbuf[4096] = { 0 };
 
   if (IPMI_IS_OS_ERR (status))
   {
@@ -236,7 +233,7 @@ static int sensor_list_add (ipmi_sensor_t *sensor)
   c_ipmi_sensor_list_t *list_item;
   c_ipmi_sensor_list_t *list_prev;
 
-  char buffer[DATA_MAX_NAME_LEN];
+  char buffer[DATA_MAX_NAME_LEN] = { 0 };
   const char *entity_id_string;
   char sensor_name[DATA_MAX_NAME_LEN];
   char *sensor_name_ptr;
@@ -246,7 +243,6 @@ static int sensor_list_add (ipmi_sensor_t *sensor)
 
   sensor_id = ipmi_sensor_convert_to_id (sensor);
 
-  memset (buffer, 0, sizeof (buffer));
   ipmi_sensor_get_name (sensor, buffer, sizeof (buffer));
   buffer[sizeof (buffer) - 1] = 0;
 
@@ -279,7 +275,7 @@ static int sensor_list_add (ipmi_sensor_t *sensor)
     {
       /* `sensor_id_ptr' now points to "(123)". */
       ssnprintf (sensor_name, sizeof (sensor_name),
-          "%s %s", sensor_name_ptr, sensor_id_ptr); 
+          "%s %s", sensor_name_ptr, sensor_id_ptr);
     }
     /* else: don't touch sensor_name. */
   }
@@ -436,11 +432,9 @@ static int sensor_list_remove (ipmi_sensor_t *sensor)
 
 static int sensor_list_read_all (void)
 {
-  c_ipmi_sensor_list_t *list_item;
-
   pthread_mutex_lock (&sensor_list_lock);
 
-  for (list_item = sensor_list;
+  for (c_ipmi_sensor_list_t *list_item = sensor_list;
       list_item != NULL;
       list_item = list_item->next)
   {
@@ -552,7 +546,6 @@ static void domain_connection_change_handler (ipmi_domain_t *domain,
 static int thread_init (os_handler_t **ret_os_handler)
 {
   os_handler_t *os_handler;
-  ipmi_open_option_t open_option[1];
   ipmi_con_t *smi_connection = NULL;
   ipmi_domain_id_t domain_id;
   int status;
@@ -576,9 +569,12 @@ static int thread_init (os_handler_t **ret_os_handler)
     return (-1);
   }
 
-  memset (open_option, 0, sizeof (open_option));
-  open_option[0].option = IPMI_OPEN_OPTION_ALL;
-  open_option[0].ival = 1;
+  ipmi_open_option_t open_option[1] = {
+    [0] = {
+      .option = IPMI_OPEN_OPTION_ALL,
+      { .ival = 1 }
+    }
+  };
 
   status = ipmi_open_domain ("mydomain", &smi_connection, /* num_con = */ 1,
       domain_connection_change_handler, /* user data = */ NULL,
index 590b693..35c93f4 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
-#include <sys/socket.h>
-
 #include <libiptc/libiptc.h>
 #include <libiptc/libip6tc.h>
 
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
+
 /*
  * iptc_handle_t was available before libiptc was officially available as a
  * shared library. Note, that when the shared lib was introduced, the API and
@@ -63,14 +66,10 @@ typedef struct ip6tc_handle ip6tc_handle_t;
  */
 static const char *config_keys[] =
 {
-       "Chain",
-       "Chain6"
+    "Chain",
+    "Chain6"
 };
 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
-/*
-    Each table/chain combo that will be queried goes into this list
-*/
-
 enum protocol_version_e
 {
     IPV4,
@@ -78,6 +77,9 @@ enum protocol_version_e
 };
 typedef enum protocol_version_e protocol_version_t;
 
+/*
+ * Each table/chain combo that will be queried goes into this list
+ */
 #ifndef XT_TABLE_MAXNAMELEN
 # define XT_TABLE_MAXNAMELEN 32
 #endif
@@ -87,14 +89,14 @@ typedef struct {
     char chain[XT_TABLE_MAXNAMELEN];
     union
     {
-       int   num;
-       char *comment;
+        int   num;
+        char *comment;
     } rule;
     enum
     {
-       RTYPE_NUM,
-       RTYPE_COMMENT,
-       RTYPE_COMMENT_ALL
+        RTYPE_NUM,
+        RTYPE_COMMENT,
+        RTYPE_COMMENT_ALL
     } rule_type;
     char name[64];
 } ip_chain_t;
@@ -104,142 +106,141 @@ static int chain_num = 0;
 
 static int iptables_config (const char *key, const char *value)
 {
-       /* int ip_value; */
-       protocol_version_t ip_version = 0;
-
-       if (strcasecmp (key, "Chain") == 0)
-               ip_version = IPV4;
-       else if (strcasecmp (key, "Chain6") == 0)
-               ip_version = IPV6;
-       else
-               return (1);
-
-       ip_chain_t temp, *final, **list;
-       char *table;
-       int   table_len;
-       char *chain;
-       int   chain_len;
-
-       char *value_copy;
-       char *fields[4];
-       int   fields_num;
-
-       memset (&temp, 0, sizeof (temp));
-
-       value_copy = strdup (value);
-       if (value_copy == NULL)
-       {
-           char errbuf[1024];
-           ERROR ("strdup failed: %s",
-                   sstrerror (errno, errbuf, sizeof (errbuf)));
-           return (1);
-       }
-
-       /*
-        *  Time to fill the temp element
-        *  Examine value string, it should look like:
-        *  Chain[6] <table> <chain> [<comment|num> [name]]
-        */
-
-       /* set IPv4 or IPv6 */
-       temp.ip_version = ip_version;
-
-       /* Chain <table> <chain> [<comment|num> [name]] */
-       fields_num = strsplit (value_copy, fields, 4);
-       if (fields_num < 2)
-       {
-           free (value_copy);
-           return (1);
-       }
-
-       table = fields[0];
-       chain = fields[1];
-
-       table_len = strlen (table) + 1;
-       if ((unsigned int)table_len > sizeof(temp.table))
-       {
-               ERROR ("Table `%s' too long.", table);
-               free (value_copy);
-               return (1);
-       }
-       sstrncpy (temp.table, table, table_len);
-
-       chain_len = strlen (chain) + 1;
-       if ((unsigned int)chain_len > sizeof(temp.chain))
-       {
-               ERROR ("Chain `%s' too long.", chain);
-               free (value_copy);
-               return (1);
-       }
-       sstrncpy (temp.chain, chain, chain_len);
-
-       if (fields_num >= 3)
-       {
-           char *comment = fields[2];
-           int   rule = atoi (comment);
-
-           if (rule)
-           {
-               temp.rule.num = rule;
-               temp.rule_type = RTYPE_NUM;
-           }
-           else
-           {
-               temp.rule.comment = strdup (comment);
-               if (temp.rule.comment == NULL)
-               {
-                   free (value_copy);
-                   return (1);
-               }
-               temp.rule_type = RTYPE_COMMENT;
-           }
-       }
-       else
-       {
-           temp.rule_type = RTYPE_COMMENT_ALL;
-       }
-
-       if (fields_num >= 4)
-           sstrncpy (temp.name, fields[3], sizeof (temp.name));
-
-       free (value_copy);
-       value_copy = NULL;
-       table = NULL;
-       chain = NULL;
-
-       list = (ip_chain_t **) realloc (chain_list, (chain_num + 1) * sizeof (ip_chain_t *));
-       if (list == NULL)
-       {
-           char errbuf[1024];
-           ERROR ("realloc failed: %s",
-                   sstrerror (errno, errbuf, sizeof (errbuf)));
-           sfree (temp.rule.comment);
-           return (1);
-       }
-
-       chain_list = list;
-       final = (ip_chain_t *) malloc( sizeof(temp) );
-       if (final == NULL)
-       {
-           char errbuf[1024];
-           ERROR ("malloc failed: %s",
-                   sstrerror (errno, errbuf, sizeof (errbuf)));
-           sfree (temp.rule.comment);
-           return (1);
-       }
-       memcpy (final, &temp, sizeof (temp));
-       chain_list[chain_num] = final;
-       chain_num++;
-
-       DEBUG ("Chain #%i: table = %s; chain = %s;", chain_num, final->table, final->chain);
-
-       return (0);
+    /* int ip_value; */
+    protocol_version_t ip_version = 0;
+
+    if (strcasecmp (key, "Chain") == 0)
+        ip_version = IPV4;
+    else if (strcasecmp (key, "Chain6") == 0)
+        ip_version = IPV6;
+    else
+        return (1);
+
+    ip_chain_t  temp = { 0 };
+    ip_chain_t *final, **list;
+    char *table;
+    int   table_len;
+    char *chain;
+    int   chain_len;
+
+    char *value_copy;
+    char *fields[4];
+    int   fields_num;
+
+    value_copy = strdup (value);
+    if (value_copy == NULL)
+    {
+        char errbuf[1024];
+        ERROR ("strdup failed: %s",
+                sstrerror (errno, errbuf, sizeof (errbuf)));
+        return (1);
+    }
+
+    /*
+     *  Time to fill the temp element
+     *  Examine value string, it should look like:
+     *  Chain[6] <table> <chain> [<comment|num> [name]]
+     */
+
+    /* set IPv4 or IPv6 */
+    temp.ip_version = ip_version;
+
+    /* Chain <table> <chain> [<comment|num> [name]] */
+    fields_num = strsplit (value_copy, fields, 4);
+    if (fields_num < 2)
+    {
+        free (value_copy);
+        return (1);
+    }
+
+    table = fields[0];
+    chain = fields[1];
+
+    table_len = strlen (table) + 1;
+    if ((unsigned int)table_len > sizeof(temp.table))
+    {
+        ERROR ("Table `%s' too long.", table);
+        free (value_copy);
+        return (1);
+    }
+    sstrncpy (temp.table, table, table_len);
+
+    chain_len = strlen (chain) + 1;
+    if ((unsigned int)chain_len > sizeof(temp.chain))
+    {
+        ERROR ("Chain `%s' too long.", chain);
+        free (value_copy);
+        return (1);
+    }
+    sstrncpy (temp.chain, chain, chain_len);
+
+    if (fields_num >= 3)
+    {
+        char *comment = fields[2];
+        int   rule = atoi (comment);
+
+        if (rule)
+        {
+            temp.rule.num = rule;
+            temp.rule_type = RTYPE_NUM;
+        }
+        else
+        {
+            temp.rule.comment = strdup (comment);
+            if (temp.rule.comment == NULL)
+            {
+                free (value_copy);
+                return (1);
+            }
+            temp.rule_type = RTYPE_COMMENT;
+        }
+    }
+    else
+    {
+        temp.rule_type = RTYPE_COMMENT_ALL;
+    }
+
+    if (fields_num >= 4)
+        sstrncpy (temp.name, fields[3], sizeof (temp.name));
+
+    free (value_copy);
+    value_copy = NULL;
+    table = NULL;
+    chain = NULL;
+
+    list = realloc (chain_list, (chain_num + 1) * sizeof (ip_chain_t *));
+    if (list == NULL)
+    {
+        char errbuf[1024];
+        ERROR ("realloc failed: %s",
+                sstrerror (errno, errbuf, sizeof (errbuf)));
+        sfree (temp.rule.comment);
+        return (1);
+    }
+
+    chain_list = list;
+    final = malloc(sizeof (*final));
+    if (final == NULL)
+    {
+        char errbuf[1024];
+        ERROR ("malloc failed: %s",
+                sstrerror (errno, errbuf, sizeof (errbuf)));
+        sfree (temp.rule.comment);
+        return (1);
+    }
+    memcpy (final, &temp, sizeof (temp));
+    chain_list[chain_num] = final;
+    chain_num++;
+
+    DEBUG ("Chain #%i: table = %s; chain = %s;", chain_num, final->table, final->chain);
+
+    return (0);
 } /* int iptables_config */
 
 static int submit6_match (const struct ip6t_entry_match *match,
-                const struct ip6t_entry *entry,
-                const ip_chain_t *chain,
-                int rule_num)
+                          const struct ip6t_entry *entry,
+                          const ip_chain_t *chain,
+                          int rule_num)
 {
     int status;
     value_t values[1];
@@ -256,7 +257,7 @@ static int submit6_match (const struct ip6t_entry_match *match,
         if (strcmp (match->u.user.name, "comment") != 0)
             return (0);
         if ((chain->rule_type == RTYPE_COMMENT)
-                && (strcmp (chain->rule.comment, (char *) match->data) != 0))
+             && (strcmp (chain->rule.comment, (char *) match->data) != 0))
             return (0);
     }
 
@@ -266,7 +267,7 @@ static int submit6_match (const struct ip6t_entry_match *match,
     sstrncpy (vl.plugin, "ip6tables", sizeof (vl.plugin));
 
     status = ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
-            "%s-%s", chain->table, chain->chain);
+                        "%s-%s", chain->table, chain->chain);
     if ((status < 1) || ((unsigned int)status >= sizeof (vl.plugin_instance)))
         return (0);
 
@@ -278,10 +279,10 @@ static int submit6_match (const struct ip6t_entry_match *match,
     {
         if (chain->rule_type == RTYPE_NUM)
             ssnprintf (vl.type_instance, sizeof (vl.type_instance),
-                    "%i", chain->rule.num);
+                       "%i", chain->rule.num);
         else
             sstrncpy (vl.type_instance, (char *) match->data,
-                    sizeof (vl.type_instance));
+                      sizeof (vl.type_instance));
     }
 
     sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
@@ -298,9 +299,9 @@ static int submit6_match (const struct ip6t_entry_match *match,
 
 /* This needs to return `int' for IPT_MATCH_ITERATE to work. */
 static int submit_match (const struct ipt_entry_match *match,
-               const struct ipt_entry *entry,
-               const ip_chain_t *chain,
-               int rule_num) 
+                         const struct ipt_entry *entry,
+                         const ip_chain_t *chain,
+                         int rule_num)
 {
     int status;
     value_t values[1];
@@ -309,16 +310,16 @@ static int submit_match (const struct ipt_entry_match *match,
     /* Select the rules to collect */
     if (chain->rule_type == RTYPE_NUM)
     {
-       if (chain->rule.num != rule_num)
-           return (0);
+        if (chain->rule.num != rule_num)
+            return (0);
     }
     else
     {
-       if (strcmp (match->u.user.name, "comment") != 0)
-           return (0);
-       if ((chain->rule_type == RTYPE_COMMENT)
-               && (strcmp (chain->rule.comment, (char *) match->data) != 0))
-           return (0);
+        if (strcmp (match->u.user.name, "comment") != 0)
+            return (0);
+        if ((chain->rule_type == RTYPE_COMMENT)
+             && (strcmp (chain->rule.comment, (char *) match->data) != 0))
+            return (0);
     }
 
     vl.values = values;
@@ -327,22 +328,22 @@ static int submit_match (const struct ipt_entry_match *match,
     sstrncpy (vl.plugin, "iptables", sizeof (vl.plugin));
 
     status = ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
-           "%s-%s", chain->table, chain->chain);
+                        "%s-%s", chain->table, chain->chain);
     if ((status < 1) || ((unsigned int)status >= sizeof (vl.plugin_instance)))
-       return (0);
+        return (0);
 
     if (chain->name[0] != '\0')
     {
-       sstrncpy (vl.type_instance, chain->name, sizeof (vl.type_instance));
+        sstrncpy (vl.type_instance, chain->name, sizeof (vl.type_instance));
     }
     else
     {
-       if (chain->rule_type == RTYPE_NUM)
-           ssnprintf (vl.type_instance, sizeof (vl.type_instance),
-                   "%i", chain->rule.num);
-       else
-           sstrncpy (vl.type_instance, (char *) match->data,
-                   sizeof (vl.type_instance));
+        if (chain->rule_type == RTYPE_NUM)
+            ssnprintf (vl.type_instance, sizeof (vl.type_instance),
+                       "%i", chain->rule.num);
+        else
+            sstrncpy (vl.type_instance, (char *) match->data,
+                      sizeof (vl.type_instance));
     }
 
     sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
@@ -358,7 +359,7 @@ static int submit_match (const struct ipt_entry_match *match,
 
 
 /* ipv6 submit_chain */
-static void submit6_chain( ip6tc_handle_t *handle, ip_chain_t *chain )
+static void submit6_chain (ip6tc_handle_t *handle, ip_chain_t *chain)
 {
     const struct ip6t_entry *entry;
     int rule_num;
@@ -390,102 +391,100 @@ static void submit6_chain( ip6tc_handle_t *handle, ip_chain_t *chain )
 
 
 /* ipv4 submit_chain */
-static void submit_chain( iptc_handle_t *handle, ip_chain_t *chain )
+static void submit_chain (iptc_handle_t *handle, ip_chain_t *chain)
 {
     const struct ipt_entry *entry;
     int rule_num;
 
-    /* Find first rule for chain and use the iterate macro */    
+    /* Find first rule for chain and use the iterate macro */
     entry = iptc_first_rule( chain->chain, handle );
     if (entry == NULL)
     {
-       DEBUG ("iptc_first_rule failed: %s", iptc_strerror (errno));
-       return;
+        DEBUG ("iptc_first_rule failed: %s", iptc_strerror (errno));
+        return;
     }
 
     rule_num = 1;
     while (entry)
     {
-       if (chain->rule_type == RTYPE_NUM)
-       {
-           submit_match (NULL, entry, chain, rule_num);
-       }
-       else
-       {
-           IPT_MATCH_ITERATE( entry, submit_match, entry, chain, rule_num );
-       }
-
-       entry = iptc_next_rule( entry, handle );
-       rule_num++;
+        if (chain->rule_type == RTYPE_NUM)
+        {
+            submit_match (NULL, entry, chain, rule_num);
+        }
+        else
+        {
+            IPT_MATCH_ITERATE( entry, submit_match, entry, chain, rule_num );
+        }
+
+        entry = iptc_next_rule( entry, handle );
+        rule_num++;
     } /* while (entry) */
 }
 
 
 static int iptables_read (void)
 {
-    int i;
     int num_failures = 0;
     ip_chain_t *chain;
 
-    /* Init the iptc handle structure and query the correct table */    
-    for (i = 0; i < chain_num; i++)
+    /* Init the iptc handle structure and query the correct table */
+    for (int i = 0; i < chain_num; i++)
     {
-       chain = chain_list[i];
-       
-       if (!chain)
-       {
-           DEBUG ("iptables plugin: chain == NULL");
-           continue;
-       }
-
-       if ( chain->ip_version == IPV4 )
+        chain = chain_list[i];
+
+        if (!chain)
+        {
+            DEBUG ("iptables plugin: chain == NULL");
+            continue;
+        }
+
+        if ( chain->ip_version == IPV4 )
         {
 #ifdef HAVE_IPTC_HANDLE_T
-               iptc_handle_t _handle;
-               iptc_handle_t *handle = &_handle;
+            iptc_handle_t _handle;
+            iptc_handle_t *handle = &_handle;
 
-               *handle = iptc_init (chain->table);
+            *handle = iptc_init (chain->table);
 #else
-               iptc_handle_t *handle;
-                handle = iptc_init (chain->table);
+            iptc_handle_t *handle;
+            handle = iptc_init (chain->table);
 #endif
 
-                if (!handle)
-                {
-                        ERROR ("iptables plugin: iptc_init (%s) failed: %s",
-                                chain->table, iptc_strerror (errno));
-                        num_failures++;
-                        continue;
-                }
+            if (!handle)
+            {
+                ERROR ("iptables plugin: iptc_init (%s) failed: %s",
+                        chain->table, iptc_strerror (errno));
+                num_failures++;
+                continue;
+            }
 
-                submit_chain (handle, chain);
-                iptc_free (handle);
+            submit_chain (handle, chain);
+            iptc_free (handle);
         }
         else if ( chain->ip_version == IPV6 )
         {
 #ifdef HAVE_IP6TC_HANDLE_T
-               ip6tc_handle_t _handle;
-               ip6tc_handle_t *handle = &_handle;
+            ip6tc_handle_t _handle;
+            ip6tc_handle_t *handle = &_handle;
 
-               *handle = ip6tc_init (chain->table);
+            *handle = ip6tc_init (chain->table);
 #else
-                ip6tc_handle_t *handle;
-                handle = ip6tc_init (chain->table);
+            ip6tc_handle_t *handle;
+            handle = ip6tc_init (chain->table);
 #endif
-
-                if (!handle)
-                {
-                        ERROR ("iptables plugin: ip6tc_init (%s) failed: %s",
-                                chain->table, ip6tc_strerror (errno));
-                        num_failures++;
-                        continue;
-                }
-
-                submit6_chain (handle, chain);
-                ip6tc_free (handle);
+            if (!handle)
+            {
+                ERROR ("iptables plugin: ip6tc_init (%s) failed: %s",
+                        chain->table, ip6tc_strerror (errno));
+                num_failures++;
+                continue;
+            }
+
+            submit6_chain (handle, chain);
+            ip6tc_free (handle);
         }
-        else num_failures++;
-
+        else
+            num_failures++;
     } /* for (i = 0 .. chain_num) */
 
     return ((num_failures < chain_num) ? 0 : -1);
@@ -493,29 +492,42 @@ static int iptables_read (void)
 
 static int iptables_shutdown (void)
 {
-    int i;
-
-    for (i = 0; i < chain_num; i++)
+    for (int i = 0; i < chain_num; i++)
     {
-       if ((chain_list[i] != NULL) && (chain_list[i]->rule_type == RTYPE_COMMENT))
-       {
-           sfree (chain_list[i]->rule.comment);
-       }
-       sfree (chain_list[i]);
+        if ((chain_list[i] != NULL) && (chain_list[i]->rule_type == RTYPE_COMMENT))
+            sfree (chain_list[i]->rule.comment);
+        sfree (chain_list[i]);
     }
     sfree (chain_list);
 
     return (0);
 } /* int iptables_shutdown */
 
+static int iptables_init (void)
+{
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_NET_ADMIN)
+    if (check_capability (CAP_NET_ADMIN) != 0)
+    {
+        if (getuid () == 0)
+            WARNING ("iptables plugin: Running collectd as root, but the "
+                  "CAP_NET_ADMIN capability is missing. The plugin's read "
+                  "function will probably fail. Is your init system dropping "
+                  "capabilities?");
+        else
+            WARNING ("iptables plugin: collectd doesn't have the CAP_NET_ADMIN "
+                  "capability. If you don't want to run collectd as root, try "
+                  "running \"setcap cap_net_admin=ep\" on the collectd binary.");
+    }
+#endif
+    return (0);
+} /* int iptables_init */
+
 void module_register (void)
 {
     plugin_register_config ("iptables", iptables_config,
-           config_keys, config_keys_num);
+                             config_keys, config_keys_num);
+    plugin_register_init ("iptables", iptables_init);
     plugin_register_read ("iptables", iptables_read);
     plugin_register_shutdown ("iptables", iptables_shutdown);
 } /* void module_register */
 
-/*
- * vim:shiftwidth=4:softtabstop=4:tabstop=8
- */
index cbb5542..92690e8 100644 (file)
  */
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 
 #if HAVE_ARPA_INET_H
 # include <arpa/inet.h>
 #endif /* HAVE_ARPA_INET_H */
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif /* HAVE_SYS_SOCKET_H */
 #if HAVE_NETINET_IN_H
 # include <netinet/in.h>
 #endif /* HAVE_NETINET_IN_H */
@@ -197,7 +195,7 @@ static int get_pi (struct ip_vs_service_entry *se, char *pi, size_t size)
                        (se->protocol == IPPROTO_TCP) ? "TCP" : "UDP",
                        ntohs (se->port));
 
-       if ((0 > len) || (size <= len)) {
+       if ((0 > len) || (size <= ((size_t) len))) {
                log_err ("plugin instance truncated: %s", pi);
                return -1;
        }
@@ -220,14 +218,15 @@ static int get_ti (struct ip_vs_dest_entry *de, char *ti, size_t size)
        len = ssnprintf (ti, size, "%s_%u", inet_ntoa (addr),
                        ntohs (de->port));
 
-       if ((0 > len) || (size <= len)) {
+       if ((0 > len) || (size <= ((size_t) len))) {
                log_err ("type instance truncated: %s", ti);
                return -1;
        }
        return 0;
 } /* get_ti */
 
-static void cipvs_submit_connections (char *pi, char *ti, derive_t value)
+static void cipvs_submit_connections (const char *pi, const char *ti,
+               derive_t value)
 {
        value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
@@ -248,7 +247,7 @@ static void cipvs_submit_connections (char *pi, char *ti, derive_t value)
        return;
 } /* cipvs_submit_connections */
 
-static void cipvs_submit_if (char *pi, char *t, char *ti,
+static void cipvs_submit_if (const char *pi, const char *t, const char *ti,
                derive_t rx, derive_t tx)
 {
        value_t values[2];
@@ -271,7 +270,8 @@ static void cipvs_submit_if (char *pi, char *t, char *ti,
        return;
 } /* cipvs_submit_if */
 
-static void cipvs_submit_dest (char *pi, struct ip_vs_dest_entry *de) {
+static void cipvs_submit_dest (const char *pi, struct ip_vs_dest_entry *de)
+{
        struct ip_vs_stats_user stats = de->stats;
 
        char ti[DATA_MAX_NAME_LEN];
@@ -292,8 +292,6 @@ static void cipvs_submit_service (struct ip_vs_service_entry *se)
 
        char pi[DATA_MAX_NAME_LEN];
 
-       int i = 0;
-
        if (0 != get_pi (se, pi, sizeof (pi)))
        {
                free (dests);
@@ -304,7 +302,7 @@ static void cipvs_submit_service (struct ip_vs_service_entry *se)
        cipvs_submit_if (pi, "if_packets", NULL, stats.inpkts, stats.outpkts);
        cipvs_submit_if (pi, "if_octets", NULL, stats.inbytes, stats.outbytes);
 
-       for (i = 0; i < dests->num_dests; ++i)
+       for (size_t i = 0; i < dests->num_dests; ++i)
                cipvs_submit_dest (pi, &dests->entrytable[i]);
 
        free (dests);
@@ -314,7 +312,6 @@ static void cipvs_submit_service (struct ip_vs_service_entry *se)
 static int cipvs_read (void)
 {
        struct ip_vs_get_services *services = NULL;
-       int i = 0;
 
        if (sockfd < 0)
                return (-1);
@@ -322,7 +319,7 @@ static int cipvs_read (void)
        if (NULL == (services = ipvs_get_services ()))
                return -1;
 
-       for (i = 0; i < services->num_services; ++i)
+       for (size_t i = 0; i < services->num_services; ++i)
                cipvs_submit_service (&services->entrytable[i]);
 
        free (services);
index 93f3f53..0c36379 100644 (file)
--- a/src/irq.c
+++ b/src/irq.c
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
index c74fe6c..47f4cd3 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "filter_chain.h"
 
-#include <pthread.h>
 #include <jni.h>
 
 #if !defined(JNI_VERSION_1_2)
@@ -507,7 +507,6 @@ static jobject ctoj_oconfig_item (JNIEnv *jvm_env, /* {{{ */
   jmethodID m_addchild;
   jobject o_key;
   jobject o_ocitem;
-  int i;
 
   c_ocitem = (*jvm_env)->FindClass (jvm_env, "org/collectd/api/OConfigItem");
   if (c_ocitem == NULL)
@@ -572,7 +571,7 @@ static jobject ctoj_oconfig_item (JNIEnv *jvm_env, /* {{{ */
   (*jvm_env)->DeleteLocalRef (jvm_env, o_key);
 
   /* Call OConfigItem.addValue for each value */
-  for (i = 0; i < ci->values_num; i++) /* {{{ */
+  for (int i = 0; i < ci->values_num; i++) /* {{{ */
   {
     jobject o_value;
 
@@ -590,7 +589,7 @@ static jobject ctoj_oconfig_item (JNIEnv *jvm_env, /* {{{ */
   } /* }}} for (i = 0; i < ci->values_num; i++) */
 
   /* Call OConfigItem.addChild for each child */
-  for (i = 0; i < ci->children_num; i++) /* {{{ */
+  for (int i = 0; i < ci->children_num; i++) /* {{{ */
   {
     jobject o_child;
 
@@ -618,7 +617,6 @@ static jobject ctoj_data_set (JNIEnv *jvm_env, const data_set_t *ds) /* {{{ */
   jmethodID m_add;
   jobject o_type;
   jobject o_dataset;
-  int i;
 
   /* Look up the org/collectd/api/DataSet class */
   c_dataset = (*jvm_env)->FindClass (jvm_env, "org/collectd/api/DataSet");
@@ -668,7 +666,7 @@ static jobject ctoj_data_set (JNIEnv *jvm_env, const data_set_t *ds) /* {{{ */
   /* Decrease reference counter on the java.lang.String object. */
   (*jvm_env)->DeleteLocalRef (jvm_env, o_type);
 
-  for (i = 0; i < ds->ds_num; i++)
+  for (size_t i = 0; i < ds->ds_num; i++)
   {
     jobject o_datasource;
 
@@ -763,7 +761,6 @@ static jobject ctoj_value_list (JNIEnv *jvm_env, /* {{{ */
   jmethodID m_valuelist_constructor;
   jobject o_valuelist;
   int status;
-  int i;
 
   /* First, create a new ValueList instance..
    * Look up the class.. */
@@ -846,7 +843,7 @@ static jobject ctoj_value_list (JNIEnv *jvm_env, /* {{{ */
     return (NULL);
   }
 
-  for (i = 0; i < vl->values_len; i++)
+  for (size_t i = 0; i < vl->values_len; i++)
   {
     status = ctoj_value_list_add_value (jvm_env, vl->values[i], ds->ds[i].type,
         c_valuelist, o_valuelist);
@@ -1117,7 +1114,6 @@ static int jtoc_values_array (JNIEnv *jvm_env, /* {{{ */
 
   value_t *values;
   int values_num;
-  int i;
 
   values_num = ds->ds_num;
 
@@ -1177,7 +1173,7 @@ static int jtoc_values_array (JNIEnv *jvm_env, /* {{{ */
     BAIL_OUT (-1);
   }
 
-  for (i = 0; i < values_num; i++)
+  for (int i = 0; i < values_num; i++)
   {
     jobject o_number;
     int status;
@@ -1364,12 +1360,9 @@ static jint JNICALL cjni_api_dispatch_values (JNIEnv *jvm_env, /* {{{ */
 static jint JNICALL cjni_api_dispatch_notification (JNIEnv *jvm_env, /* {{{ */
     jobject this, jobject o_notification)
 {
-  notification_t n;
+  notification_t n = { 0 };
   int status;
 
-  memset (&n, 0, sizeof (n));
-  n.meta = NULL;
-
   status = jtoc_notification (jvm_env, &n, o_notification);
   if (status != 0)
   {
@@ -1424,7 +1417,7 @@ static jint JNICALL cjni_api_register_init (JNIEnv *jvm_env, /* {{{ */
 static jint JNICALL cjni_api_register_read (JNIEnv *jvm_env, /* {{{ */
     jobject this, jobject o_name, jobject o_read)
 {
-  user_data_t ud;
+  user_data_t ud = { 0 };
   cjni_callback_info_t *cbi;
 
   cbi = cjni_callback_info_create (jvm_env, o_name, o_read, CB_TYPE_READ);
@@ -1433,12 +1426,11 @@ static jint JNICALL cjni_api_register_read (JNIEnv *jvm_env, /* {{{ */
 
   DEBUG ("java plugin: Registering new read callback: %s", cbi->name);
 
-  memset (&ud, 0, sizeof (ud));
   ud.data = (void *) cbi;
   ud.free_func = cjni_callback_info_destroy;
 
   plugin_register_complex_read (/* group = */ NULL, cbi->name, cjni_read,
-      /* interval = */ NULL, &ud);
+      /* interval = */ 0, &ud);
 
   (*jvm_env)->DeleteLocalRef (jvm_env, o_read);
 
@@ -1448,7 +1440,7 @@ static jint JNICALL cjni_api_register_read (JNIEnv *jvm_env, /* {{{ */
 static jint JNICALL cjni_api_register_write (JNIEnv *jvm_env, /* {{{ */
     jobject this, jobject o_name, jobject o_write)
 {
-  user_data_t ud;
+  user_data_t ud = { 0 };
   cjni_callback_info_t *cbi;
 
   cbi = cjni_callback_info_create (jvm_env, o_name, o_write, CB_TYPE_WRITE);
@@ -1457,7 +1449,6 @@ static jint JNICALL cjni_api_register_write (JNIEnv *jvm_env, /* {{{ */
 
   DEBUG ("java plugin: Registering new write callback: %s", cbi->name);
 
-  memset (&ud, 0, sizeof (ud));
   ud.data = (void *) cbi;
   ud.free_func = cjni_callback_info_destroy;
 
@@ -1471,7 +1462,7 @@ static jint JNICALL cjni_api_register_write (JNIEnv *jvm_env, /* {{{ */
 static jint JNICALL cjni_api_register_flush (JNIEnv *jvm_env, /* {{{ */
     jobject this, jobject o_name, jobject o_flush)
 {
-  user_data_t ud;
+  user_data_t ud = { 0 };
   cjni_callback_info_t *cbi;
 
   cbi = cjni_callback_info_create (jvm_env, o_name, o_flush, CB_TYPE_FLUSH);
@@ -1480,7 +1471,6 @@ static jint JNICALL cjni_api_register_flush (JNIEnv *jvm_env, /* {{{ */
 
   DEBUG ("java plugin: Registering new flush callback: %s", cbi->name);
 
-  memset (&ud, 0, sizeof (ud));
   ud.data = (void *) cbi;
   ud.free_func = cjni_callback_info_destroy;
 
@@ -1501,7 +1491,7 @@ static jint JNICALL cjni_api_register_shutdown (JNIEnv *jvm_env, /* {{{ */
 static jint JNICALL cjni_api_register_log (JNIEnv *jvm_env, /* {{{ */
     jobject this, jobject o_name, jobject o_log)
 {
-  user_data_t ud;
+  user_data_t ud = { 0 };
   cjni_callback_info_t *cbi;
 
   cbi = cjni_callback_info_create (jvm_env, o_name, o_log, CB_TYPE_LOG);
@@ -1510,7 +1500,6 @@ static jint JNICALL cjni_api_register_log (JNIEnv *jvm_env, /* {{{ */
 
   DEBUG ("java plugin: Registering new log callback: %s", cbi->name);
 
-  memset (&ud, 0, sizeof (ud));
   ud.data = (void *) cbi;
   ud.free_func = cjni_callback_info_destroy;
 
@@ -1524,7 +1513,7 @@ static jint JNICALL cjni_api_register_log (JNIEnv *jvm_env, /* {{{ */
 static jint JNICALL cjni_api_register_notification (JNIEnv *jvm_env, /* {{{ */
     jobject this, jobject o_name, jobject o_notification)
 {
-  user_data_t ud;
+  user_data_t ud = { 0 };
   cjni_callback_info_t *cbi;
 
   cbi = cjni_callback_info_create (jvm_env, o_name, o_notification,
@@ -1534,7 +1523,6 @@ static jint JNICALL cjni_api_register_notification (JNIEnv *jvm_env, /* {{{ */
 
   DEBUG ("java plugin: Registering new notification callback: %s", cbi->name);
 
-  memset (&ud, 0, sizeof (ud));
   ud.data = (void *) cbi;
   ud.free_func = cjni_callback_info_destroy;
 
@@ -1568,9 +1556,8 @@ static jint JNICALL cjni_api_register_match_target (JNIEnv *jvm_env, /* {{{ */
 
   if (type == CB_TYPE_MATCH)
   {
-    match_proc_t m_proc;
+    match_proc_t m_proc = { 0 };
 
-    memset (&m_proc, 0, sizeof (m_proc));
     m_proc.create  = cjni_match_target_create;
     m_proc.destroy = cjni_match_target_destroy;
     m_proc.match   = (void *) cjni_match_target_invoke;
@@ -1579,9 +1566,8 @@ static jint JNICALL cjni_api_register_match_target (JNIEnv *jvm_env, /* {{{ */
   }
   else if (type == CB_TYPE_TARGET)
   {
-    target_proc_t t_proc;
+    target_proc_t t_proc = { 0 };
 
-    memset (&t_proc, 0, sizeof (t_proc));
     t_proc.create  = cjni_match_target_create;
     t_proc.destroy = cjni_match_target_destroy;
     t_proc.invoke  = cjni_match_target_invoke;
@@ -1801,14 +1787,13 @@ static cjni_callback_info_t *cjni_callback_info_create (JNIEnv *jvm_env, /* {{{
     return (NULL);
   }
 
-  cbi = (cjni_callback_info_t *) malloc (sizeof (*cbi));
+  cbi = calloc (1, sizeof (*cbi));
   if (cbi == NULL)
   {
-    ERROR ("java plugin: cjni_callback_info_create: malloc failed.");
+    ERROR ("java plugin: cjni_callback_info_create: calloc failed.");
     (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
     return (NULL);
   }
-  memset (cbi, 0, sizeof (*cbi));
   cbi->type = type;
 
   cbi->name = strdup (c_name);
@@ -1906,7 +1891,7 @@ static int cjni_callback_register (JNIEnv *jvm_env, /* {{{ */
 
   pthread_mutex_lock (&java_callbacks_lock);
 
-  tmp = (cjni_callback_info_t *) realloc (java_callbacks,
+  tmp = realloc (java_callbacks,
       (java_callbacks_num + 1) * sizeof (*java_callbacks));
   if (tmp == NULL)
   {
@@ -1987,11 +1972,10 @@ static int cjni_init_native (JNIEnv *jvm_env) /* {{{ */
 static int cjni_create_jvm (void) /* {{{ */
 {
   JNIEnv *jvm_env;
-  JavaVMInitArgs vm_args;
+  JavaVMInitArgs vm_args = { 0 };
   JavaVMOption vm_options[jvm_argc];
 
   int status;
-  size_t i;
 
   if (jvm != NULL)
     return (0);
@@ -2006,12 +1990,11 @@ static int cjni_create_jvm (void) /* {{{ */
 
   jvm_env = NULL;
 
-  memset (&vm_args, 0, sizeof (vm_args));
   vm_args.version = JNI_VERSION_1_2;
   vm_args.options = vm_options;
   vm_args.nOptions = (jint) jvm_argc;
 
-  for (i = 0; i < jvm_argc; i++)
+  for (size_t i = 0; i < jvm_argc; i++)
   {
     DEBUG ("java plugin: cjni_create_jvm: jvm_argv[%zu] = %s",
         i, jvm_argv[i]);
@@ -2067,13 +2050,12 @@ static JNIEnv *cjni_thread_attach (void) /* {{{ */
   if (cjni_env == NULL)
   {
     /* This pointer is free'd in `cjni_jvm_env_destroy'. */
-    cjni_env = (cjni_jvm_env_t *) malloc (sizeof (*cjni_env));
+    cjni_env = calloc (1, sizeof (*cjni_env));
     if (cjni_env == NULL)
     {
-      ERROR ("java plugin: cjni_thread_attach: malloc failed.");
+      ERROR ("java plugin: cjni_thread_attach: calloc failed.");
       return (NULL);
     }
-    memset (cjni_env, 0, sizeof (*cjni_env));
     cjni_env->reference_counter = 0;
     cjni_env->jvm_env = NULL;
 
@@ -2088,11 +2070,10 @@ static JNIEnv *cjni_thread_attach (void) /* {{{ */
   else
   {
     int status;
-    JavaVMAttachArgs args;
+    JavaVMAttachArgs args = { 0 };
 
     assert (cjni_env->jvm_env == NULL);
 
-    memset (&args, 0, sizeof (args));
     args.version = JNI_VERSION_1_2;
 
     status = (*jvm)->AttachCurrentThread (jvm, (void *) &jvm_env, (void *) &args);
@@ -2169,7 +2150,7 @@ static int cjni_config_add_jvm_arg (oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  tmp = (char **) realloc (jvm_argv, sizeof (char *) * (jvm_argc + 1));
+  tmp = realloc (jvm_argv, sizeof (char *) * (jvm_argc + 1));
   if (tmp == NULL)
   {
     ERROR ("java plugin: realloc failed.");
@@ -2205,7 +2186,7 @@ static int cjni_config_load_plugin (oconfig_item_t *ci) /* {{{ */
   if (jvm_env == NULL)
     return (-1);
 
-  class = (java_plugin_class_t *) realloc (java_classes_list,
+  class = realloc (java_classes_list,
       (java_classes_list_len + 1) * sizeof (*java_classes_list));
   if (class == NULL)
   {
@@ -2230,8 +2211,7 @@ static int cjni_config_load_plugin (oconfig_item_t *ci) /* {{{ */
   { /* Replace all dots ('.') with slashes ('/'). Dots are usually used
        thorough the Java community, but (Sun's) `FindClass' and friends need
        slashes. */
-    size_t i;
-    for (i = 0; class->name[i] != 0; i++)
+    for (size_t i = 0; class->name[i] != 0; i++)
       if (class->name[i] == '.')
         class->name[i] = '/';
   }
@@ -2289,7 +2269,6 @@ static int cjni_config_plugin_block (oconfig_item_t *ci) /* {{{ */
   cjni_callback_info_t *cbi;
   jobject o_ocitem;
   const char *name;
-  size_t i;
 
   jclass class;
   jmethodID method;
@@ -2304,7 +2283,7 @@ static int cjni_config_plugin_block (oconfig_item_t *ci) /* {{{ */
   name = ci->values[0].value.string;
 
   cbi = NULL;
-  for (i = 0; i < java_callbacks_num; i++)
+  for (size_t i = 0; i < java_callbacks_num; i++)
   {
     if (java_callbacks[i].type != CB_TYPE_CONFIG)
       continue;
@@ -2356,12 +2335,11 @@ static int cjni_config_perform (oconfig_item_t *ci) /* {{{ */
   int success;
   int errors;
   int status;
-  int i;
 
   success = 0;
   errors = 0;
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -2724,7 +2702,6 @@ static int cjni_match_target_create (const oconfig_item_t *ci, /* {{{ */
   jobject o_ci;
   jobject o_tmp;
   int type;
-  size_t i;
 
   cbi_ret = NULL;
   o_ci = NULL;
@@ -2769,7 +2746,7 @@ static int cjni_match_target_create (const oconfig_item_t *ci, /* {{{ */
 
   /* Lets see if we have a matching factory here.. */
   cbi_factory = NULL;
-  for (i = 0; i < java_callbacks_num; i++)
+  for (size_t i = 0; i < java_callbacks_num; i++)
   {
     if (java_callbacks[i].type != type)
       continue;
@@ -2801,13 +2778,13 @@ static int cjni_match_target_create (const oconfig_item_t *ci, /* {{{ */
 
   /* Allocate a new callback info structure. This is going to be our user_data
    * pointer. */
-  cbi_ret = (cjni_callback_info_t *) malloc (sizeof (*cbi_ret));
+  cbi_ret = calloc (1, sizeof (*cbi_ret));
   if (cbi_ret == NULL)
   {
-    ERROR ("java plugin: cjni_match_target_create: malloc failed.");
+    ERROR ("java plugin: cjni_match_target_create: calloc failed.");
     BAIL_OUT (-1);
   }
-  memset (cbi_ret, 0, sizeof (*cbi_ret));
+
   cbi_ret->object = NULL;
   cbi_ret->type = type;
 
@@ -2923,9 +2900,8 @@ static int cjni_match_target_invoke (const data_set_t *ds, /* {{{ */
    * `value_list_t'. */
   if (cbi->type == CB_TYPE_TARGET)
   {
-    value_list_t new_vl;
+    value_list_t new_vl = { 0 };
 
-    memset (&new_vl, 0, sizeof (new_vl));
     status = jtoc_value_list (jvm_env, &new_vl, o_vl);
     if (status != 0)
     {
@@ -2952,9 +2928,8 @@ static int cjni_match_target_invoke (const data_set_t *ds, /* {{{ */
 static int cjni_init_plugins (JNIEnv *jvm_env) /* {{{ */
 {
   int status;
-  size_t i;
 
-  for (i = 0; i < java_callbacks_num; i++)
+  for (size_t i = 0; i < java_callbacks_num; i++)
   {
     if (java_callbacks[i].type != CB_TYPE_INIT)
       continue;
@@ -2979,9 +2954,8 @@ static int cjni_init_plugins (JNIEnv *jvm_env) /* {{{ */
 static int cjni_shutdown_plugins (JNIEnv *jvm_env) /* {{{ */
 {
   int status;
-  size_t i;
 
-  for (i = 0; i < java_callbacks_num; i++)
+  for (size_t i = 0; i < java_callbacks_num; i++)
   {
     if (java_callbacks[i].type != CB_TYPE_SHUTDOWN)
       continue;
@@ -3004,15 +2978,13 @@ static int cjni_shutdown_plugins (JNIEnv *jvm_env) /* {{{ */
 static int cjni_shutdown (void) /* {{{ */
 {
   JNIEnv *jvm_env;
-  JavaVMAttachArgs args;
+  JavaVMAttachArgs args = { 0 };
   int status;
-  size_t i;
 
   if (jvm == NULL)
     return (0);
 
   jvm_env = NULL;
-  memset (&args, 0, sizeof (args));
   args.version = JNI_VERSION_1_2;
 
   status = (*jvm)->AttachCurrentThread (jvm, (void *) &jvm_env, &args);
@@ -3027,7 +2999,7 @@ static int cjni_shutdown (void) /* {{{ */
   cjni_shutdown_plugins (jvm_env);
 
   /* Release all the global references to callback functions */
-  for (i = 0; i < java_callbacks_num; i++)
+  for (size_t i = 0; i < java_callbacks_num; i++)
   {
     if (java_callbacks[i].object != NULL)
     {
@@ -3040,7 +3012,7 @@ static int cjni_shutdown (void) /* {{{ */
   sfree (java_callbacks);
 
   /* Release all the global references to directly loaded classes. */
-  for (i = 0; i < java_classes_list_len; i++)
+  for (size_t i = 0; i < java_classes_list_len; i++)
   {
     if (java_classes_list[i].object != NULL)
     {
@@ -3061,7 +3033,7 @@ static int cjni_shutdown (void) /* {{{ */
   pthread_key_delete (jvm_env_key);
 
   /* Free the JVM argument list */
-  for (i = 0; i < jvm_argc; i++)
+  for (size_t i = 0; i < jvm_argc; i++)
     sfree (jvm_argv[i]);
   jvm_argc = 0;
   sfree (jvm_argv);
index 5abee2f..e81a594 100644 (file)
@@ -1,9 +1,5 @@
 AUTOMAKE_OPTIONS = foreign no-dependencies
 
-if COMPILER_IS_GCC
-AM_CFLAGS = -Wall -Werror
-endif
-
 pkginclude_HEADERS = collectd/client.h collectd/network.h collectd/network_buffer.h collectd/lcc_features.h
 lib_LTLIBRARIES = libcollectdclient.la
 nodist_pkgconfig_DATA = libcollectdclient.pc
index bdb21f6..a15e0aa 100644 (file)
@@ -246,12 +246,10 @@ static void lcc_chomp (char *str) /* {{{ */
 
 static void lcc_response_free (lcc_response_t *res) /* {{{ */
 {
-  size_t i;
-
   if (res == NULL)
     return;
 
-  for (i = 0; i < res->lines_num; i++)
+  for (size_t i = 0; i < res->lines_num; i++)
     free (res->lines[i]);
   free (res->lines);
   res->lines = NULL;
@@ -277,13 +275,11 @@ static int lcc_send (lcc_connection_t *c, const char *command) /* {{{ */
 static int lcc_receive (lcc_connection_t *c, /* {{{ */
     lcc_response_t *ret_res)
 {
-  lcc_response_t res;
+  lcc_response_t res = { 0 };
   char *ptr;
   char buffer[4096];
   size_t i;
 
-  memset (&res, 0, sizeof (res));
-
   /* Read the first line, containing the status and a message */
   ptr = fgets (buffer, sizeof (buffer), c->fh);
   if (ptr == NULL)
@@ -298,7 +294,7 @@ static int lcc_receive (lcc_connection_t *c, /* {{{ */
    * beginning of the message. */
   ptr = NULL;
   errno = 0;
-  res.status = strtol (buffer, &ptr, 0);
+  res.status = (int) strtol (buffer, &ptr, 0);
   if ((errno != 0) || (ptr == &buffer[0]))
   {
     lcc_set_errno (c, errno);
@@ -323,7 +319,7 @@ static int lcc_receive (lcc_connection_t *c, /* {{{ */
   /* Allocate space for the char-pointers */
   res.lines_num = (size_t) res.status;
   res.status = 0;
-  res.lines = (char **) malloc (res.lines_num * sizeof (char *));
+  res.lines = malloc (res.lines_num * sizeof (*res.lines));
   if (res.lines == NULL)
   {
     lcc_set_errno (c, ENOMEM);
@@ -369,7 +365,7 @@ static int lcc_receive (lcc_connection_t *c, /* {{{ */
 static int lcc_sendreceive (lcc_connection_t *c, /* {{{ */
     const char *command, lcc_response_t *ret_res)
 {
-  lcc_response_t res;
+  lcc_response_t res = { 0 };
   int status;
 
   if (c->fh == NULL)
@@ -382,7 +378,6 @@ static int lcc_sendreceive (lcc_connection_t *c, /* {{{ */
   if (status != 0)
     return (status);
 
-  memset (&res, 0, sizeof (res));
   status = lcc_receive (c, &res);
   if (status == 0)
     memcpy (ret_res, &res, sizeof (*ret_res));
@@ -392,7 +387,7 @@ static int lcc_sendreceive (lcc_connection_t *c, /* {{{ */
 
 static int lcc_open_unixsocket (lcc_connection_t *c, const char *path) /* {{{ */
 {
-  struct sockaddr_un sa;
+  struct sockaddr_un sa = { 0 };
   int fd;
   int status;
 
@@ -409,7 +404,6 @@ static int lcc_open_unixsocket (lcc_connection_t *c, const char *path) /* {{{ */
     return (-1);
   }
 
-  memset (&sa, 0, sizeof (sa));
   sa.sun_family = AF_UNIX;
   strncpy (sa.sun_path, path, sizeof (sa.sun_path) - 1);
 
@@ -435,9 +429,7 @@ static int lcc_open_unixsocket (lcc_connection_t *c, const char *path) /* {{{ */
 static int lcc_open_netsocket (lcc_connection_t *c, /* {{{ */
     const char *addr_orig)
 {
-  struct addrinfo ai_hints;
   struct addrinfo *ai_res;
-  struct addrinfo *ai_ptr;
   char addr_copy[NI_MAXHOST];
   char *addr;
   char *port;
@@ -452,14 +444,6 @@ static int lcc_open_netsocket (lcc_connection_t *c, /* {{{ */
   addr_copy[sizeof(addr_copy) - 1] = '\0';
   addr = addr_copy;
 
-  memset (&ai_hints, 0, sizeof (ai_hints));
-  ai_hints.ai_flags = 0;
-#ifdef AI_ADDRCONFIG
-  ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
-  ai_hints.ai_family = AF_UNSPEC;
-  ai_hints.ai_socktype = SOCK_STREAM;
-
   port = NULL;
   if (*addr == '[') /* IPv6+port format */
   {
@@ -495,7 +479,12 @@ static int lcc_open_netsocket (lcc_connection_t *c, /* {{{ */
     }
   }
 
-  ai_res = NULL;
+  struct addrinfo ai_hints = {
+    .ai_family = AF_UNSPEC,
+    .ai_flags = AI_ADDRCONFIG,
+    .ai_socktype = SOCK_STREAM
+  };
+
   status = getaddrinfo (addr,
                         port == NULL ? LCC_DEFAULT_PORT : port,
                         &ai_hints, &ai_res);
@@ -505,7 +494,7 @@ static int lcc_open_netsocket (lcc_connection_t *c, /* {{{ */
     return (-1);
   }
 
-  for (ai_ptr = ai_res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  for (struct addrinfo *ai_ptr = ai_res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
   {
     fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
     if (fd < 0)
@@ -595,10 +584,9 @@ int lcc_connect (const char *address, lcc_connection_t **ret_con) /* {{{ */
   if (ret_con == NULL)
     return (-1);
 
-  c = (lcc_connection_t *) malloc (sizeof (*c));
+  c = calloc (1, sizeof (*c));
   if (c == NULL)
     return (-1);
-  memset (c, 0, sizeof (*c));
 
   status = lcc_open_socket (c, address);
   if (status != 0)
@@ -698,14 +686,14 @@ int lcc_getval (lcc_connection_t *c, lcc_identifier_t *ident, /* {{{ */
   /* Allocate space for the values */
   if (ret_values != NULL)
   {
-    values = (gauge_t *) malloc (values_num * sizeof (*values));
+    values = malloc (values_num * sizeof (*values));
     if (values == NULL)
       BAIL_OUT (ENOMEM);
   }
 
   if (ret_values_names != NULL)
   {
-    values_names = (char **) calloc (values_num, sizeof (*values_names));
+    values_names = calloc (values_num, sizeof (*values_names));
     if (values_names == NULL)
       BAIL_OUT (ENOMEM);
   }
@@ -761,7 +749,6 @@ int lcc_putval (lcc_connection_t *c, const lcc_value_list_t *vl) /* {{{ */
   char command[1024] = "";
   lcc_response_t res;
   int status;
-  size_t i;
 
   if ((c == NULL) || (vl == NULL) || (vl->values_len < 1)
       || (vl->values == NULL) || (vl->values_types == NULL))
@@ -786,7 +773,7 @@ int lcc_putval (lcc_connection_t *c, const lcc_value_list_t *vl) /* {{{ */
   else
     SSTRCAT (command, " N");
 
-  for (i = 0; i < vl->values_len; i++)
+  for (size_t i = 0; i < vl->values_len; i++)
   {
     if (vl->values_types[i] == LCC_TYPE_COUNTER)
       SSTRCATF (command, ":%"PRIu64, vl->values[i].counter);
@@ -878,7 +865,6 @@ int lcc_listval (lcc_connection_t *c, /* {{{ */
     lcc_identifier_t **ret_ident, size_t *ret_ident_num)
 {
   lcc_response_t res;
-  size_t i;
   int status;
 
   lcc_identifier_t *ident;
@@ -905,7 +891,7 @@ int lcc_listval (lcc_connection_t *c, /* {{{ */
   }
 
   ident_num = res.lines_num;
-  ident = (lcc_identifier_t *) malloc (ident_num * sizeof (*ident));
+  ident = malloc (ident_num * sizeof (*ident));
   if (ident == NULL)
   {
     lcc_response_free (&res);
@@ -913,7 +899,7 @@ int lcc_listval (lcc_connection_t *c, /* {{{ */
     return (-1);
   }
 
-  for (i = 0; i < res.lines_num; i++)
+  for (size_t i = 0; i < res.lines_num; i++)
   {
     char *time_str;
     char *ident_str;
@@ -1074,9 +1060,11 @@ int lcc_string_to_identifier (lcc_connection_t *c, /* {{{ */
   return (0);
 } /* }}} int lcc_string_to_identifier */
 
-int lcc_identifier_compare (const lcc_identifier_t *i0, /* {{{ */
-    const lcc_identifier_t *i1)
+int lcc_identifier_compare (const void *a, /* {{{ */
+    const void *b)
 {
+  const lcc_identifier_t *i0 = a;
+  const lcc_identifier_t *i1 = b;
   int status;
 
   if ((i0 == NULL) && (i1 == NULL))
@@ -1113,7 +1101,7 @@ int lcc_sort_identifiers (lcc_connection_t *c, /* {{{ */
   }
 
   qsort (idents, idents_num, sizeof (*idents),
-      (void *) lcc_identifier_compare);
+      lcc_identifier_compare);
   return (0);
 } /* }}} int lcc_sort_identifiers */
 
index 8e7f4b6..47462a6 100644 (file)
@@ -131,8 +131,8 @@ int lcc_string_to_identifier (lcc_connection_t *c,
 /* Compares the identifiers "i0" and "i1" and returns less than zero or greater
  * than zero if "i0" is smaller than or greater than "i1", respectively. If
  * "i0" and "i1" are identical, zero is returned. */
-int lcc_identifier_compare (const lcc_identifier_t *i0,
-    const lcc_identifier_t *i1);
+int lcc_identifier_compare (const void *i0,
+    const void *i1);
 int lcc_sort_identifiers (lcc_connection_t *c,
     lcc_identifier_t *idents, size_t idents_num);
 
index 049f7f0..64cf9c9 100644 (file)
@@ -56,7 +56,7 @@ typedef enum lcc_security_level_e lcc_security_level_t;
 lcc_network_t *lcc_network_create (void);
 void lcc_network_destroy (lcc_network_t *net);
 
-/* 
+/*
  * Add servers
  */
 lcc_server_t *lcc_server_create (lcc_network_t *net,
index 420471d..16293ca 100644 (file)
@@ -119,9 +119,7 @@ static void int_server_destroy (lcc_server_t *srv) /* {{{ */
 
 static int server_open_socket (lcc_server_t *srv) /* {{{ */
 {
-  struct addrinfo ai_hints = { 0 };
-  struct addrinfo *ai_list = NULL;
-  struct addrinfo *ai_ptr;
+  struct addrinfo *ai_list;
   int status;
 
   if (srv == NULL)
@@ -130,18 +128,18 @@ static int server_open_socket (lcc_server_t *srv) /* {{{ */
   if (srv->fd >= 0)
     server_close_socket (srv);
 
-#ifdef AI_ADDRCONFIG
-  ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
-  ai_hints.ai_family   = AF_UNSPEC;
-  ai_hints.ai_socktype = SOCK_DGRAM;
+  struct addrinfo ai_hints = {
+    .ai_family = AF_UNSPEC,
+    .ai_flags = AI_ADDRCONFIG,
+    .ai_socktype = SOCK_DGRAM
+  };
 
   status = getaddrinfo (srv->node, srv->service, &ai_hints, &ai_list);
   if (status != 0)
     return (status);
   assert (ai_list != NULL);
 
-  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
   {
     srv->fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
     if (srv->fd < 0)
@@ -204,7 +202,7 @@ static int server_open_socket (lcc_server_t *srv) /* {{{ */
 
 static int server_send_buffer (lcc_server_t *srv) /* {{{ */
 {
-  char buffer[LCC_NETWORK_BUFFER_SIZE_DEFAULT];
+  char buffer[LCC_NETWORK_BUFFER_SIZE_DEFAULT] = { 0 };
   size_t buffer_size;
   int status;
 
@@ -215,7 +213,6 @@ static int server_send_buffer (lcc_server_t *srv) /* {{{ */
       return (status);
   }
 
-  memset (buffer, 0, sizeof (buffer));
   buffer_size = sizeof (buffer);
 
   status = lcc_network_buffer_finalize (srv->buffer);
@@ -271,10 +268,9 @@ lcc_network_t *lcc_network_create (void) /* {{{ */
 {
   lcc_network_t *net;
 
-  net = malloc (sizeof (*net));
+  net = calloc (1, sizeof (*net));
   if (net == NULL)
     return (NULL);
-  memset (net, 0, sizeof (*net));
 
   net->servers = NULL;
 
@@ -299,10 +295,9 @@ lcc_server_t *lcc_server_create (lcc_network_t *net, /* {{{ */
   if (service == NULL)
     service = NET_DEFAULT_PORT;
 
-  srv = malloc (sizeof (*srv));
+  srv = calloc (1, sizeof (*srv));
   if (srv == NULL)
     return (NULL);
-  memset (srv, 0, sizeof (*srv));
 
   srv->fd = -1;
   srv->security_level = NONE;
@@ -392,7 +387,7 @@ int lcc_server_set_ttl (lcc_server_t *srv, uint8_t ttl) /* {{{ */
 
 int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ */
 {
-  int if_index;
+  unsigned int if_index;
   int status;
 
   if ((srv == NULL) || (interface == NULL))
@@ -415,18 +410,16 @@ int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ *
        * index is preferred here, because of its similarity
        * to the way IPv6 handles this. Unfortunately, it
        * appears not to be portable. */
-      struct ip_mreqn mreq;
-
-      memset (&mreq, 0, sizeof (mreq));
-      mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
-      mreq.imr_address.s_addr = ntohl (INADDR_ANY);
-      mreq.imr_ifindex = if_index;
+      struct ip_mreqn mreq = {
+        .imr_multiaddr.s_addr = addr->sin_addr.s_addr,
+        .imr_address.s_addr = ntohl (INADDR_ANY),
+        .imr_ifindex = (int) if_index
+      };
 #else
-      struct ip_mreq mreq;
-
-      memset (&mreq, 0, sizeof (mreq));
-      mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
-      mreq.imr_interface.s_addr = ntohl (INADDR_ANY);
+      struct ip_mreq mreq = {
+        .imr_multiaddr.s_addr = addr->sin_addr.s_addr,
+        .imr_interface.s_addr = ntohl (INADDR_ANY)
+      };
 #endif
 
       status = setsockopt (srv->fd, IPPROTO_IP, IP_MULTICAST_IF,
@@ -456,8 +449,8 @@ int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ *
 
   /* else: Not a multicast interface. */
 #if defined(SO_BINDTODEVICE)
-  status = setsockopt (srv->fd, SOL_SOCKET, SO_BINDTODEVICE,
-      interface, strlen (interface) + 1);
+  status = setsockopt (srv->fd, SOL_SOCKET, SO_BINDTODEVICE, interface,
+      (socklen_t) (strlen (interface) + 1));
   if (status != 0)
     return (-1);
 #endif
@@ -476,12 +469,10 @@ int lcc_server_set_security_level (lcc_server_t *srv, /* {{{ */
 int lcc_network_values_send (lcc_network_t *net, /* {{{ */
     const lcc_value_list_t *vl)
 {
-  lcc_server_t *srv;
-
   if ((net == NULL) || (vl == NULL))
     return (EINVAL);
 
-  for (srv = net->servers; srv != NULL; srv = srv->next)
+  for (lcc_server_t *srv = net->servers; srv != NULL; srv = srv->next)
     server_value_add (srv, vl);
 
   return (0);
index 8d35d20..2c6277c 100644 (file)
@@ -36,7 +36,6 @@
 #include <pthread.h>
 
 #if HAVE_LIBGCRYPT
-# include <pthread.h>
 # if defined __APPLE__
 /* default xcode compiler throws warnings even when deprecated functionality
  * is not used. -Werror breaks the build because of erroneous warnings.
@@ -275,7 +274,6 @@ static int nb_add_values (char **ret_buffer, /* {{{ */
   value_t       pkg_values[vl->values_len];
 
   size_t offset;
-  size_t i;
 
   packet_len = sizeof (pkg_type) + sizeof (pkg_length)
     + sizeof (pkg_num_values)
@@ -289,7 +287,7 @@ static int nb_add_values (char **ret_buffer, /* {{{ */
   pkg_length = htons ((uint16_t) packet_len);
   pkg_num_values = htons ((uint16_t) vl->values_len);
 
-  for (i = 0; i < vl->values_len; i++)
+  for (size_t i = 0; i < vl->values_len; i++)
   {
     pkg_values_types[i] = (uint8_t) vl->values_types[i];
     switch (vl->values_types[i])
@@ -654,19 +652,17 @@ lcc_network_buffer_t *lcc_network_buffer_create (size_t size) /* {{{ */
     return (NULL);
   }
 
-  nb = malloc (sizeof (*nb));
+  nb = calloc (1, sizeof (*nb));
   if (nb == NULL)
     return (NULL);
-  memset (nb, 0, sizeof (*nb));
 
   nb->size = size;
-  nb->buffer = malloc (nb->size);
+  nb->buffer = calloc (1, nb->size);
   if (nb->buffer == NULL)
   {
     free (nb);
     return (NULL);
   }
-  memset (nb->buffer, 0, nb->size);
 
   nb->ptr = nb->buffer;
   nb->free = nb->size;
@@ -764,7 +760,8 @@ int lcc_network_buffer_initialize (lcc_network_buffer_t *nb) /* {{{ */
     uint16_t pkg_type = htons (TYPE_ENCR_AES256);
     uint16_t pkg_length = 0; /* Filled in in finalize. */
     uint16_t pkg_user_len = htons ((uint16_t) username_length);
-    char hash[20];
+    /* Filled in in finalize. */
+    char hash[20] = { 0 };
 
     nb->encr_header_len = username_length;
     nb->encr_header_len += PART_ENCRYPTION_AES256_SIZE;
@@ -772,9 +769,6 @@ int lcc_network_buffer_initialize (lcc_network_buffer_t *nb) /* {{{ */
     gcry_randomize ((void *) &nb->encr_iv, sizeof (nb->encr_iv),
         GCRY_STRONG_RANDOM);
 
-    /* Filled in in finalize. */
-    memset (hash, 0, sizeof (hash));
-
     ADD_STATIC (nb, pkg_type);
     ADD_STATIC (nb, pkg_length);
     ADD_STATIC (nb, pkg_user_len);
index b5162cc..5ac0ef3 100644 (file)
@@ -1,5 +1,3 @@
-AUTOMAKE_OPTIONS = foreign no-dependencies
-
 BUILT_SOURCES = parser.h
 #CLEANFILES = parser.[ch] scanner.c
 AM_YFLAGS = -d
index 5d2c5b2..319aae8 100644 (file)
@@ -55,7 +55,7 @@ oconfig_item_t *oconfig_parse_fh (FILE *fh)
   if (NULL == c_file) {
     status = snprintf (file, sizeof (file), "<fd#%d>", fileno (fh));
 
-    if ((status < 0) || (status >= sizeof (file))) {
+    if ((status < 0) || (((size_t) status) >= sizeof (file))) {
       c_file = "<unknown>";
     }
     else {
@@ -106,13 +106,12 @@ oconfig_item_t *oconfig_clone (const oconfig_item_t *ci_orig)
 {
   oconfig_item_t *ci_copy;
 
-  ci_copy = (oconfig_item_t *) malloc (sizeof (*ci_copy));
+  ci_copy = calloc (1, sizeof (*ci_copy));
   if (ci_copy == NULL)
   {
-    fprintf (stderr, "malloc failed.\n");
+    fprintf (stderr, "calloc failed.\n");
     return (NULL);
   }
-  memset (ci_copy, 0, sizeof (*ci_copy));
   ci_copy->values = NULL;
   ci_copy->parent = NULL;
   ci_copy->children = NULL;
@@ -127,10 +126,8 @@ oconfig_item_t *oconfig_clone (const oconfig_item_t *ci_orig)
 
   if (ci_orig->values_num > 0) /* {{{ */
   {
-    int i;
-
-    ci_copy->values = (oconfig_value_t *) calloc (ci_orig->values_num,
-       sizeof (*ci_copy->values));
+    ci_copy->values = (oconfig_value_t *) calloc ((size_t) ci_orig->values_num,
+        sizeof (*ci_copy->values));
     if (ci_copy->values == NULL)
     {
       fprintf (stderr, "calloc failed.\n");
@@ -140,33 +137,30 @@ oconfig_item_t *oconfig_clone (const oconfig_item_t *ci_orig)
     }
     ci_copy->values_num = ci_orig->values_num;
 
-    for (i = 0; i < ci_copy->values_num; i++)
+    for (int i = 0; i < ci_copy->values_num; i++)
     {
        ci_copy->values[i].type = ci_orig->values[i].type;
        if (ci_copy->values[i].type == OCONFIG_TYPE_STRING)
        {
-        ci_copy->values[i].value.string
-          = strdup (ci_orig->values[i].value.string);
-        if (ci_copy->values[i].value.string == NULL)
-        {
-          fprintf (stderr, "strdup failed.\n");
-          oconfig_free (ci_copy);
-          return (NULL);
-        }
+         ci_copy->values[i].value.string = strdup (ci_orig->values[i].value.string);
+         if (ci_copy->values[i].value.string == NULL)
+         {
+           fprintf (stderr, "strdup failed.\n");
+           oconfig_free (ci_copy);
+           return (NULL);
+         }
        }
        else /* ci_copy->values[i].type != OCONFIG_TYPE_STRING) */
        {
-        ci_copy->values[i].value = ci_orig->values[i].value;
+         ci_copy->values[i].value = ci_orig->values[i].value;
        }
     }
   } /* }}} if (ci_orig->values_num > 0) */
 
   if (ci_orig->children_num > 0) /* {{{ */
   {
-    int i;
-
-    ci_copy->children = (oconfig_item_t *) calloc (ci_orig->children_num,
-       sizeof (*ci_copy->children));
+    ci_copy->children = (oconfig_item_t *) calloc ((size_t) ci_orig->children_num,
+        sizeof (*ci_copy->children));
     if (ci_copy->children == NULL)
     {
       fprintf (stderr, "calloc failed.\n");
@@ -175,10 +169,10 @@ oconfig_item_t *oconfig_clone (const oconfig_item_t *ci_orig)
     }
     ci_copy->children_num = ci_orig->children_num;
 
-    for (i = 0; i < ci_copy->children_num; i++)
+    for (int i = 0; i < ci_copy->children_num; i++)
     {
       oconfig_item_t *child;
-      
+
       child = oconfig_clone (ci_orig->children + i);
       if (child == NULL)
       {
@@ -196,15 +190,13 @@ oconfig_item_t *oconfig_clone (const oconfig_item_t *ci_orig)
 
 static void oconfig_free_all (oconfig_item_t *ci)
 {
-  int i;
-
   if (ci == NULL)
     return;
 
   if (ci->key != NULL)
     free (ci->key);
 
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
     if ((ci->values[i].type == OCONFIG_TYPE_STRING)
         && (NULL != ci->values[i].value.string))
       free (ci->values[i].value.string);
@@ -212,7 +204,7 @@ static void oconfig_free_all (oconfig_item_t *ci)
   if (ci->values != NULL)
     free (ci->values);
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
     oconfig_free_all (ci->children + i);
 
   if (ci->children != NULL)
@@ -223,7 +215,6 @@ void oconfig_free (oconfig_item_t *ci)
 {
   oconfig_free_all (ci);
   free (ci);
-  ci = NULL;
 }
 
 /*
index f0e886c..4a550b3 100644 (file)
@@ -208,15 +208,13 @@ statement_list:
 entire_file:
        statement_list
        {
-        ci_root = malloc (sizeof (oconfig_item_t));
-        memset (ci_root, '\0', sizeof (oconfig_item_t));
+        ci_root = calloc (1, sizeof (*ci_root));
         ci_root->children = $1.statement;
         ci_root->children_num = $1.statement_num;
        }
        | /* epsilon */
        {
-        ci_root = malloc (sizeof (oconfig_item_t));
-        memset (ci_root, '\0', sizeof (oconfig_item_t));
+        ci_root = calloc (1, sizeof (*ci_root));
         ci_root->children = NULL;
         ci_root->children_num = 0;
        }
@@ -225,7 +223,7 @@ entire_file:
 %%
 static int yyerror (const char *s)
 {
-       char *text;
+       const char *text;
 
        if (*yytext == '\n')
                text = "<newline>";
@@ -241,7 +239,6 @@ static char *unquote (const char *orig)
 {
        char *ret = strdup (orig);
        int len;
-       int i;
 
        if (ret == NULL)
                return (NULL);
@@ -255,7 +252,7 @@ static char *unquote (const char *orig)
        memmove (ret, ret + 1, len);
        ret[len] = '\0';
 
-       for (i = 0; i < len; i++)
+       for (int i = 0; i < len; i++)
        {
                if (ret[i] == '\\')
                {
index 41d6643..7a831c2 100644 (file)
@@ -146,7 +146,7 @@ static void ml_append (char *string)
 
        if (ml_free <= len) {
                ml_len += len - ml_free + 1;
-               ml_buffer = (char *)realloc (ml_buffer, ml_len);
+               ml_buffer = realloc (ml_buffer, ml_len);
                if (NULL == ml_buffer)
                        YY_FATAL_ERROR ("out of dynamic memory in ml_append");
        }
index 18b5f8e..cc3be37 100644 (file)
@@ -27,6 +27,7 @@
 #define _BSD_SOURCE
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
index 2d5f620..0886840 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
 #include <sys/types.h>
-#include <pthread.h>
 #include <yajl/yajl_common.h>
 #include <yajl/yajl_gen.h>
 #if HAVE_YAJL_YAJL_VERSION_H
@@ -65,12 +65,12 @@ static int log_logstash_config (const char *key, const char *value)
 
        if (0 == strcasecmp (key, "LogLevel")) {
                log_level = parse_log_severity(value);
-        if (log_level < 0) {
-            log_level = LOG_INFO;
-            ERROR("log_logstash: invalid loglevel [%s] defaulting to 'info'",
-                  value);
-            return 1;
-        }
+               if (log_level < 0) {
+                       log_level = LOG_INFO;
+                       ERROR("log_logstash: invalid loglevel [%s] defaulting to 'info'",
+                               value);
+                       return 1;
+               }
        }
        else if (0 == strcasecmp (key, "File")) {
                sfree (log_file);
index 1179718..d18a536 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
-#include <pthread.h>
-
 #define DEFAULT_LOGFILE LOCALSTATEDIR"/log/collectd.log"
 
 #if COLLECT_DEBUG
index 4d53447..5b0bd13 100644 (file)
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
index 9e24542..6b9a031 100644 (file)
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -24,6 +24,7 @@
 #include <lvm2app.h>
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
index 7987378..728fcd8 100644 (file)
@@ -23,7 +23,7 @@
 
 
 /**
- * There are several data streams provided by Madwifi plugin, some are 
+ * There are several data streams provided by Madwifi plugin, some are
  * connected to network interface, some are connected to each node
  * associated to that interface. Nodes represents other sides in
  * wireless communication, for example on network interface in AP mode,
  *     node_stat       Node statistic counters
  *
  * Both statistic counters have type instances for each counter returned
- * by Madwifi. See madwifi.h for content of ieee80211_nodestats, 
+ * by Madwifi. See madwifi.h for content of ieee80211_nodestats,
  * ieee80211_stats and ath_stats structures. Type instances use the same
  * name as fields in these structures (like ns_rx_dup). Some fields are
  * not reported, because they are not counters (like ns_tx_deauth_code
  * or ast_tx_rssi). Fields ns_rx_bytes and ns_tx_bytes are reported as
  * node_octets data stream instead of type instance of node_stat.
  * Statistics are not logged when they are zero.
- * 
+ *
  * There are two sets of these counters - the first 'WatchList' is a
  * set of counters that are individually logged. The second 'MiscList'
  * is a set of counters that are summed together and the sum is logged.
- * By default, the most important statistics are in the WatchList and 
+ * By default, the most important statistics are in the WatchList and
  * many error statistics are in MiscList. There are also many statistics
  * that are not in any of these sets, so they are not monitored by default.
  * It is possible to alter these lists using configuration options:
@@ -89,6 +89,7 @@
 
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -96,7 +97,6 @@
 
 #include <dirent.h>
 #include <sys/ioctl.h>
-#include <sys/socket.h>
 
 #if !KERNEL_LINUX
 # error "No applicable input method."
@@ -368,35 +368,34 @@ static int init_state = 0;
 static inline int item_watched(int i)
 {
        assert (i >= 0);
-       assert (i < ((STATIC_ARRAY_SIZE (watch_items) + 1) * 32));
+       assert ((size_t) i < (STATIC_ARRAY_SIZE (watch_items) * 32));
        return watch_items[i / 32] & FLAG (i);
 }
 
 static inline int item_summed(int i)
 {
        assert (i >= 0);
-       assert (i < ((STATIC_ARRAY_SIZE (misc_items) + 1) * 32));
+       assert ((size_t) i < (STATIC_ARRAY_SIZE (misc_items) * 32));
        return misc_items[i / 32] & FLAG (i);
 }
 
 static inline void watchlist_add (uint32_t *wl, int item)
 {
        assert (item >= 0);
-       assert (item < ((WL_LEN + 1) * 32));
+       assert (item < WL_LEN * 32);
        wl[item / 32] |= FLAG (item);
 }
 
 static inline void watchlist_remove (uint32_t *wl, int item)
 {
        assert (item >= 0);
-       assert (item < ((WL_LEN + 1) * 32));
+       assert (item < WL_LEN * 32);
        wl[item / 32] &= ~FLAG (item);
 }
 
 static inline void watchlist_set (uint32_t *wl, uint32_t val)
 {
-       int i;
-       for (i = 0; i < WL_LEN; i++)
+       for (int i = 0; i < WL_LEN; i++)
                wl[i] = val;
 }
 
@@ -404,9 +403,8 @@ static inline void watchlist_set (uint32_t *wl, uint32_t val)
 static int watchitem_find (const char *name)
 {
        int max = STATIC_ARRAY_SIZE (specs);
-       int i;
 
-       for (i = 0; i < max; i++)
+       for (int i = 0; i < max; i++)
                if (strcasecmp (name, specs[i].name) == 0)
                        return i;
 
@@ -420,16 +418,15 @@ static int watchitem_find (const char *name)
 
 static int madwifi_real_init (void)
 {
-       int max = STATIC_ARRAY_SIZE (specs);
-       int i;
+       size_t max = STATIC_ARRAY_SIZE (specs);
 
-       for (i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
+       for (size_t i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
                bounds[i] = 0;
 
        watchlist_set(watch_items, 0);
        watchlist_set(misc_items, 0);
 
-       for (i = 0; i < max; i++)
+       for (size_t i = 0; i < max; i++)
        {
                bounds[specs[i].flags & SRC_MASK] = i;
 
@@ -440,7 +437,7 @@ static int madwifi_real_init (void)
                        misc_items[i / 32] |= FLAG (i);
        }
 
-       for (i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
+       for (size_t i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
                bounds[i]++;
 
        return (0);
@@ -590,9 +587,8 @@ static void submit_antx (const char *dev, const char *name,
                u_int32_t *vals, int vals_num)
 {
        char ti2[16];
-       int i;
 
-       for (i = 0; i < vals_num; i++)
+       for (int i = 0; i < vals_num; i++)
        {
                if (vals[i] == 0)
                        continue;
@@ -615,12 +611,11 @@ process_stat_struct (int which, const void *ptr, const char *dev, const char *ma
                         const char *type_name, const char *misc_name)
 {
        uint32_t misc = 0;
-       int i;
 
        assert (which >= 1);
-       assert (which < STATIC_ARRAY_SIZE (bounds));
+       assert (((size_t) which) < STATIC_ARRAY_SIZE (bounds));
 
-       for (i = bounds[which - 1]; i < bounds[which]; i++)
+       for (int i = bounds[which - 1]; i < bounds[which]; i++)
        {
                uint32_t val = *(uint32_t *)(((char *) ptr) + specs[i].offset) ;
 
@@ -630,7 +625,7 @@ process_stat_struct (int which, const void *ptr, const char *dev, const char *ma
                if (item_summed (i))
                        misc += val;
        }
-       
+
        if (misc != 0)
                submit_derive (dev, type_name, misc_name, mac, misc);
 
@@ -700,7 +695,6 @@ process_80211stats (int sk, const char *dev)
 static int
 process_station (int sk, const char *dev, struct ieee80211req_sta_info *si)
 {
-       struct iwreq iwr;
        static char mac[DATA_MAX_NAME_LEN];
        struct ieee80211req_sta_stats stats;
        const struct ieee80211_nodestats *ns = &stats.is_stats;
@@ -715,10 +709,12 @@ process_station (int sk, const char *dev, struct ieee80211req_sta_info *si)
        if (item_watched (STAT_NODE_RSSI))
                submit_gauge (dev, "node_rssi", mac, NULL, si->isi_rssi);
 
-       memset (&iwr, 0, sizeof (iwr));
+       struct iwreq iwr = {
+               .u.data.pointer = (void *) &stats,
+               .u.data.length = sizeof (stats)
+       };
        sstrncpy(iwr.ifr_name, dev, sizeof (iwr.ifr_name));
-       iwr.u.data.pointer = (void *) &stats;
-       iwr.u.data.length = sizeof (stats);
+
        memcpy(stats.is_u.macaddr, si->isi_macaddr, IEEE80211_ADDR_LEN);
        status = ioctl(sk, IEEE80211_IOCTL_STA_STATS, &iwr);
        if (status < 0)
@@ -751,16 +747,17 @@ process_station (int sk, const char *dev, struct ieee80211req_sta_info *si)
 static int
 process_stations (int sk, const char *dev)
 {
-       uint8_t buf[24*1024];
-       struct iwreq iwr;
+       uint8_t buf[24*1024] = { 0 };
        uint8_t *cp;
-       int len, nodes;
+       int nodes;
+       size_t len;
        int status;
 
-       memset (&iwr, 0, sizeof (iwr));
+       struct iwreq iwr = {
+               .u.data.pointer = (void *) buf,
+               .u.data.length = sizeof (buf)
+       };
        sstrncpy (iwr.ifr_name, dev, sizeof (iwr.ifr_name));
-       iwr.u.data.pointer = (void *) buf;
-       iwr.u.data.length = sizeof (buf);
 
        status = ioctl (sk, IEEE80211_IOCTL_STA_INFO, &iwr);
        if (status < 0)
@@ -891,7 +888,7 @@ procfs_iterate(int sk)
        int status;
        int num_success;
        int num_fail;
-       
+
        if ((fh = fopen ("/proc/net/dev", "r")) == NULL)
        {
                WARNING ("madwifi plugin: opening /proc/net/dev failed");
@@ -953,7 +950,7 @@ static int madwifi_read (void)
 
 /* procfs iteration is not safe because it does not check whether given
    interface is madwifi interface and there are private ioctls used, which
-   may do something completely different on non-madwifi devices.   
+   may do something completely different on non-madwifi devices.
    Therefore, it is not used unless explicitly enabled (and should be used
    together with ignorelist). */
 
index abde2b3..80a29ac 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/match_empty_counter.c
- * Copyright (C) 2009       Florian Forster
+ * Copyright (C) 2009-2016  Florian Forster
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  **/
 
 #include "collectd.h"
+
 #include "common.h"
-#include "utils_cache.h"
 #include "filter_chain.h"
 
 /*
- * private data types
- */
-struct mec_match_s;
-typedef struct mec_match_s mec_match_t;
-struct mec_match_s
-{
-  int dummy;
-};
-
-/*
  * internal helper functions
  */
 static int mec_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
 {
-  mec_match_t *m;
-
-  m = (mec_match_t *) malloc (sizeof (*m));
-  if (m == NULL)
-  {
-    ERROR ("mec_create: malloc failed.");
-    return (-ENOMEM);
-  }
-  memset (m, 0, sizeof (*m));
-
   if (ci->children_num != 0)
   {
     ERROR ("empty_counter match: This match does not take any additional "
         "configuration.");
   }
 
-  *user_data = m;
+  *user_data = NULL;
   return (0);
 } /* }}} int mec_create */
 
-static int mec_destroy (void **user_data) /* {{{ */
+static int mec_destroy (__attribute__((unused)) void **user_data) /* {{{ */
 {
-  if (user_data != NULL)
-  {
-    sfree (*user_data);
-  }
-
   return (0);
 } /* }}} int mec_destroy */
 
-static int mec_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
+static int mec_match (__attribute__((unused)) const data_set_t *ds, /* {{{ */
     const value_list_t *vl,
-    notification_meta_t __attribute__((unused)) **meta, void **user_data)
+    __attribute__((unused)) notification_meta_t **meta,
+    __attribute__((unused)) void **user_data)
 {
-  int num_counters;
-  int num_empty;
-  int i;
-
-  if ((user_data == NULL) || (*user_data == NULL))
-    return (-1);
+  int num_counters = 0;
+  int num_empty = 0;
 
-
-  num_counters = 0;
-  num_empty = 0;
-
-  for (i = 0; i < ds->ds_num; i++)
+  for (size_t i = 0; i < ds->ds_num; i++)
   {
-    if (ds->ds[i].type != DS_TYPE_COUNTER)
+    if ((ds->ds[i].type != DS_TYPE_DERIVE)
+        && (ds->ds[i].type != DS_TYPE_COUNTER))
       continue;
 
     num_counters++;
-    if (vl->values[i].counter == 0)
+    if (((ds->ds[i].type == DS_TYPE_DERIVE) && (vl->values[i].derive == 0))
+        || ((ds->ds[i].type == DS_TYPE_COUNTER) && (vl->values[i].counter == 0)))
       num_empty++;
   }
 
-  if (num_counters == 0)
-    return (FC_MATCH_NO_MATCH);
-  else if (num_counters == num_empty)
+  if ((num_counters != 0) && (num_counters == num_empty))
     return (FC_MATCH_MATCHES);
-  else
-    return (FC_MATCH_NO_MATCH);
+
+  return (FC_MATCH_NO_MATCH);
 } /* }}} int mec_match */
 
 void module_register (void)
 {
-  match_proc_t mproc;
-
-  memset (&mproc, 0, sizeof (mproc));
-  mproc.create  = mec_create;
-  mproc.destroy = mec_destroy;
-  mproc.match   = mec_match;
-  fc_register_match ("empty_counter", mproc);
+  fc_register_match ("empty_counter", (match_proc_t) {
+    .create  = mec_create,
+    .destroy = mec_destroy,
+    .match   = mec_match,
+  });
 } /* module_register */
 
 /* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
index ba0c47c..c4983c2 100644 (file)
@@ -25,8 +25,8 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
-#include "utils_cache.h"
 #include "filter_chain.h"
 
 /*
@@ -99,17 +99,15 @@ static int mh_config_match (const oconfig_item_t *ci, /* {{{ */
 static int mh_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
 {
   mh_match_t *m;
-  int i;
 
-  m = (mh_match_t *) malloc (sizeof (*m));
+  m = calloc (1, sizeof (*m));
   if (m == NULL)
   {
-    ERROR ("mh_create: malloc failed.");
+    ERROR ("mh_create: calloc failed.");
     return (-ENOMEM);
   }
-  memset (m, 0, sizeof (*m));
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -151,8 +149,6 @@ static int mh_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
 {
   mh_match_t *m;
   uint32_t hash_val;
-  const char *host_ptr;
-  size_t i;
 
   if ((user_data == NULL) || (*user_data == NULL))
     return (-1);
@@ -161,14 +157,14 @@ static int mh_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
 
   hash_val = 0;
 
-  for (host_ptr = vl->host; *host_ptr != 0; host_ptr++)
+  for (const char *host_ptr = vl->host; *host_ptr != 0; host_ptr++)
   {
     /* 2184401929 is some appropriately sized prime number. */
     hash_val = (hash_val * UINT32_C (2184401929)) + ((uint32_t) *host_ptr);
   }
   DEBUG ("hashed match: host = %s; hash_val = %"PRIu32";", vl->host, hash_val);
 
-  for (i = 0; i < m->matches_num; i++)
+  for (size_t i = 0; i < m->matches_num; i++)
     if ((hash_val % m->matches[i].total) == m->matches[i].match)
       return (FC_MATCH_MATCHES);
 
@@ -177,9 +173,8 @@ static int mh_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
 
 void module_register (void)
 {
-  match_proc_t mproc;
+  match_proc_t mproc = { 0 };
 
-  memset (&mproc, 0, sizeof (mproc));
   mproc.create  = mh_create;
   mproc.destroy = mh_destroy;
   mproc.match   = mh_match;
index 4fa6ce7..cd63016 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include "collectd.h"
+
 #include "filter_chain.h"
 
 #include <sys/types.h>
@@ -99,12 +100,10 @@ static void mr_free_match (mr_match_t *m) /* {{{ */
 static int mr_match_regexen (mr_regex_t *re_head, /* {{{ */
                const char *string)
 {
-       mr_regex_t *re;
-
        if (re_head == NULL)
                return (FC_MATCH_MATCHES);
 
-       for (re = re_head; re != NULL; re = re->next)
+       for (mr_regex_t *re = re_head; re != NULL; re = re->next)
        {
                int status;
 
@@ -140,13 +139,12 @@ static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */
                return (-1);
        }
 
-       re = (mr_regex_t *) malloc (sizeof (*re));
+       re = calloc (1, sizeof (*re));
        if (re == NULL)
        {
-               log_err ("mr_config_add_regex: malloc failed.");
+               log_err ("mr_config_add_regex: calloc failed.");
                return (-1);
        }
-       memset (re, 0, sizeof (*re));
        re->next = NULL;
 
        re->re_str = strdup (ci->values[0].value.string);
@@ -163,7 +161,7 @@ static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */
                char errmsg[1024];
                regerror (status, &re->re, errmsg, sizeof (errmsg));
                errmsg[sizeof (errmsg) - 1] = 0;
-               log_err ("Compiling regex `%s' for `%s' failed: %s.", 
+               log_err ("Compiling regex `%s' for `%s' failed: %s.",
                                re->re_str, ci->key, errmsg);
                free (re->re_str);
                free (re);
@@ -192,20 +190,18 @@ static int mr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
 {
        mr_match_t *m;
        int status;
-       int i;
 
-       m = (mr_match_t *) malloc (sizeof (*m));
+       m = calloc (1, sizeof (*m));
        if (m == NULL)
        {
-               log_err ("mr_create: malloc failed.");
+               log_err ("mr_create: calloc failed.");
                return (-ENOMEM);
        }
-       memset (m, 0, sizeof (*m));
-       
+
        m->invert = 0;
 
        status = 0;
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
 
@@ -305,9 +301,8 @@ static int mr_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
 
 void module_register (void)
 {
-       match_proc_t mproc;
+       match_proc_t mproc = { 0 };
 
-       memset (&mproc, 0, sizeof (mproc));
        mproc.create  = mr_create;
        mproc.destroy = mr_destroy;
        mproc.match   = mr_match;
index 996201a..00fdd0c 100644 (file)
@@ -25,8 +25,8 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
-#include "utils_cache.h"
 #include "filter_chain.h"
 
 #define SATISFY_ALL 0
@@ -50,21 +50,19 @@ static int mt_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
 {
   mt_match_t *m;
   int status;
-  int i;
 
-  m = (mt_match_t *) malloc (sizeof (*m));
+  m = calloc (1, sizeof (*m));
   if (m == NULL)
   {
-    ERROR ("mt_create: malloc failed.");
+    ERROR ("mt_create: calloc failed.");
     return (-ENOMEM);
   }
-  memset (m, 0, sizeof (*m));
 
   m->future = 0;
   m->past = 0;
 
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -146,9 +144,8 @@ static int mt_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
 
 void module_register (void)
 {
-  match_proc_t mproc;
+  match_proc_t mproc = { 0 };
 
-  memset (&mproc, 0, sizeof (mproc));
   mproc.create  = mt_create;
   mproc.destroy = mt_destroy;
   mproc.match   = mt_match;
index 4d49984..54ddba2 100644 (file)
@@ -30,6 +30,7 @@
  */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "utils_cache.h"
 #include "filter_chain.h"
@@ -58,18 +59,16 @@ struct mv_match_s
  */
 static void mv_free_match (mv_match_t *m) /* {{{ */
 {
-  int i;
-  
   if (m == NULL)
     return;
 
   if (m->data_sources != NULL)
   {
-    for (i = 0; i < m->data_sources_num; ++i)
+    for (size_t i = 0; i < m->data_sources_num; ++i)
       free(m->data_sources[i]);
     free(m->data_sources);
   }
-  
+
   free (m);
 } /* }}} void mv_free_match */
 
@@ -103,7 +102,6 @@ static int mv_config_add_data_source (mv_match_t *m, /* {{{ */
 {
   size_t new_data_sources_num;
   char **temp;
-  int i;
 
   /* Check number of arbuments. */
   if (ci->values_num < 1)
@@ -114,7 +112,7 @@ static int mv_config_add_data_source (mv_match_t *m, /* {{{ */
   }
 
   /* Check type of arguments */
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
   {
     if (ci->values[i].type == OCONFIG_TYPE_STRING)
       continue;
@@ -129,7 +127,7 @@ static int mv_config_add_data_source (mv_match_t *m, /* {{{ */
 
   /* Allocate space for the char pointers */
   new_data_sources_num = m->data_sources_num + ((size_t) ci->values_num);
-  temp = (char **) realloc (m->data_sources,
+  temp = realloc (m->data_sources,
       new_data_sources_num * sizeof (char *));
   if (temp == NULL)
   {
@@ -139,14 +137,12 @@ static int mv_config_add_data_source (mv_match_t *m, /* {{{ */
   m->data_sources = temp;
 
   /* Copy the strings, allocating memory as needed. */
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
   {
-    size_t j;
-
     /* If we get here, there better be memory for us to write to. */
     assert (m->data_sources_num < new_data_sources_num);
 
-    j = m->data_sources_num;
+    size_t j = m->data_sources_num;
     m->data_sources[j] = sstrdup (ci->values[i].value.string);
     if (m->data_sources[j] == NULL)
     {
@@ -198,15 +194,13 @@ static int mv_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
 {
   mv_match_t *m;
   int status;
-  int i;
 
-  m = (mv_match_t *) malloc (sizeof (*m));
+  m = calloc (1, sizeof (*m));
   if (m == NULL)
   {
-    ERROR ("mv_create: malloc failed.");
+    ERROR ("mv_create: calloc failed.");
     return (-ENOMEM);
   }
-  memset (m, 0, sizeof (*m));
 
   m->min = NAN;
   m->max = NAN;
@@ -216,7 +210,7 @@ static int mv_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
   m->data_sources_num = 0;
 
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -277,7 +271,6 @@ static int mv_match (const data_set_t *ds, const value_list_t *vl, /* {{{ */
   mv_match_t *m;
   gauge_t *values;
   int status;
-  int i;
 
   if ((user_data == NULL) || (*user_data == NULL))
     return (-1);
@@ -294,7 +287,7 @@ static int mv_match (const data_set_t *ds, const value_list_t *vl, /* {{{ */
 
   status = FC_MATCH_NO_MATCH;
 
-  for (i = 0; i < ds->ds_num; i++)
+  for (size_t i = 0; i < ds->ds_num; i++)
   {
     int value_matches = 0;
 
@@ -336,7 +329,7 @@ static int mv_match (const data_set_t *ds, const value_list_t *vl, /* {{{ */
       if (m->satisfy == SATISFY_ANY)
         break;
     }
-    else if (value_matches == 0)
+    else
     {
       status = FC_MATCH_NO_MATCH;
       if (m->satisfy == SATISFY_ALL)
@@ -350,9 +343,8 @@ static int mv_match (const data_set_t *ds, const value_list_t *vl, /* {{{ */
 
 void module_register (void)
 {
-  match_proc_t mproc;
+  match_proc_t mproc = { 0 };
 
-  memset (&mproc, 0, sizeof (mproc));
   mproc.create  = mv_create;
   mproc.destroy = mv_destroy;
   mproc.match   = mv_match;
index d23062d..184bb99 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
 #include <netdb.h>
-#include <sys/socket.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 
@@ -85,19 +85,9 @@ static int mbmon_query_daemon (char *buffer, int buffer_size)
        const char *host;
        const char *port;
 
-       struct addrinfo  ai_hints;
-       struct addrinfo *ai_list, *ai_ptr;
+       struct addrinfo *ai_list;
        int              ai_return;
 
-       memset (&ai_hints, '\0', sizeof (ai_hints));
-       ai_hints.ai_flags    = 0;
-#ifdef AI_ADDRCONFIG
-       ai_hints.ai_flags   |= AI_ADDRCONFIG;
-#endif
-       ai_hints.ai_family   = PF_UNSPEC;
-       ai_hints.ai_socktype = SOCK_STREAM;
-       ai_hints.ai_protocol = IPPROTO_TCP;
-
        host = mbmon_host;
        if (host == NULL)
                host = MBMON_DEF_HOST;
@@ -106,6 +96,13 @@ static int mbmon_query_daemon (char *buffer, int buffer_size)
        if (port == NULL)
                port = MBMON_DEF_PORT;
 
+       struct addrinfo ai_hints = {
+               .ai_family = AF_UNSPEC,
+               .ai_flags = AI_ADDRCONFIG,
+               .ai_protocol = IPPROTO_TCP,
+               .ai_socktype = SOCK_STREAM
+       };
+
        if ((ai_return = getaddrinfo (host, port, &ai_hints, &ai_list)) != 0)
        {
                char errbuf[1024];
@@ -118,7 +115,7 @@ static int mbmon_query_daemon (char *buffer, int buffer_size)
        }
 
        fd = -1;
-       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
        {
                /* create our socket descriptor */
                if ((fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol)) < 0)
@@ -240,9 +237,7 @@ static void mbmon_submit (const char *type, const char *type_instance,
 /* Trim trailing whitespace from a string. */
 static void trim_spaces (char *s)
 {
-       size_t l;
-
-       for (l = strlen (s) - 1; (l > 0) && isspace ((int) s[l]); l--)
+       for (size_t l = strlen (s) - 1; (l > 0) && isspace ((int) s[l]); l--)
                s[l] = '\0';
 }
 
@@ -261,8 +256,8 @@ static int mbmon_read (void)
                double value;
                char *nextc;
 
-               char *type;
-               char *inst;
+               const char *type;
+               const char *inst;
 
                *t++ = '\0';
                trim_spaces (s);
index b34cc97..44cad2e 100644 (file)
--- a/src/md.c
+++ b/src/md.c
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_ignorelist.h"
index 013b6c4..1b6ab67 100644 (file)
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -199,23 +200,21 @@ static int cmc_config_add_match (web_page_t *page, /* {{{ */
 {
   web_match_t *match;
   int status;
-  int i;
 
   if (ci->values_num != 0)
   {
     WARNING ("memcachec plugin: Ignoring arguments for the `Match' block.");
   }
 
-  match = (web_match_t *) malloc (sizeof (*match));
+  match = calloc (1, sizeof (*match));
   if (match == NULL)
   {
-    ERROR ("memcachec plugin: malloc failed.");
+    ERROR ("memcachec plugin: calloc failed.");
     return (-1);
   }
-  memset (match, 0, sizeof (*match));
 
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -272,7 +271,7 @@ static int cmc_config_add_match (web_page_t *page, /* {{{ */
       match->dstype);
   if (match->match == NULL)
   {
-    ERROR ("memcachec plugin: tail_match_add_match_simple failed.");
+    ERROR ("memcachec plugin: match_create_simple failed.");
     cmc_web_match_free (match);
     return (-1);
   }
@@ -297,7 +296,6 @@ static int cmc_config_add_page (oconfig_item_t *ci) /* {{{ */
 {
   web_page_t *page;
   int status;
-  int i;
 
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
   {
@@ -305,13 +303,12 @@ static int cmc_config_add_page (oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  page = (web_page_t *) malloc (sizeof (*page));
+  page = calloc (1, sizeof (*page));
   if (page == NULL)
   {
-    ERROR ("memcachec plugin: malloc failed.");
+    ERROR ("memcachec plugin: calloc failed.");
     return (-1);
   }
-  memset (page, 0, sizeof (*page));
   page->server = NULL;
   page->key = NULL;
 
@@ -325,7 +322,7 @@ static int cmc_config_add_page (oconfig_item_t *ci) /* {{{ */
 
   /* Process all children */
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -389,7 +386,7 @@ static int cmc_config_add_page (oconfig_item_t *ci) /* {{{ */
     web_page_t *prev;
 
     prev = pages_g;
-    while ((prev != NULL) && (prev->next != NULL))
+    while (prev->next != NULL)
       prev = prev->next;
     prev->next = page;
   }
@@ -402,12 +399,11 @@ static int cmc_config (oconfig_item_t *ci) /* {{{ */
   int success;
   int errors;
   int status;
-  int i;
 
   success = 0;
   errors = 0;
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -466,7 +462,6 @@ static void cmc_submit (const web_page_t *wp, const web_match_t *wm, /* {{{ */
 
 static int cmc_read_page (web_page_t *wp) /* {{{ */
 {
-  web_match_t *wm;
   memcached_return rc;
   size_t string_length;
   uint32_t flags;
@@ -484,7 +479,7 @@ static int cmc_read_page (web_page_t *wp) /* {{{ */
     return (-1);
   }
 
-  for (wm = wp->matches; wm != NULL; wm = wm->next)
+  for (web_match_t *wm = wp->matches; wm != NULL; wm = wm->next)
   {
     cu_match_value_t *mv;
 
@@ -513,9 +508,7 @@ static int cmc_read_page (web_page_t *wp) /* {{{ */
 
 static int cmc_read (void) /* {{{ */
 {
-  web_page_t *wp;
-
-  for (wp = pages_g; wp != NULL; wp = wp->next)
+  for (web_page_t *wp = pages_g; wp != NULL; wp = wp->next)
     cmc_read_page (wp);
 
   return (0);
index d650f02..42882ae 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
 #include <netdb.h>
-#include <sys/socket.h>
 #include <sys/un.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
@@ -53,8 +53,9 @@ typedef struct memcached_s memcached_t;
 
 static _Bool memcached_have_instances = 0;
 
-static void memcached_free (memcached_t *st)
+static void memcached_free (void *arg)
 {
+  memcached_t *st = arg;
   if (st == NULL)
     return;
 
@@ -67,10 +68,9 @@ static void memcached_free (memcached_t *st)
 
 static int memcached_connect_unix (memcached_t *st)
 {
-  struct sockaddr_un serv_addr;
+  struct sockaddr_un serv_addr = { 0 };
   int fd;
 
-  memset (&serv_addr, 0, sizeof (serv_addr));
   serv_addr.sun_family = AF_UNIX;
   sstrncpy (serv_addr.sun_path, st->socket,
       sizeof (serv_addr.sun_path));
@@ -99,27 +99,22 @@ static int memcached_connect_unix (memcached_t *st)
 
 static int memcached_connect_inet (memcached_t *st)
 {
-  char *host;
-  char *port;
+  const char *host;
+  const char *port;
 
-  struct addrinfo  ai_hints;
-  struct addrinfo *ai_list, *ai_ptr;
+  struct addrinfo *ai_list;
   int status;
   int fd = -1;
 
-  memset (&ai_hints, 0, sizeof (ai_hints));
-  ai_hints.ai_flags    = 0;
-#ifdef AI_ADDRCONFIG
-  ai_hints.ai_flags   |= AI_ADDRCONFIG;
-#endif
-  ai_hints.ai_family   = AF_UNSPEC;
-  ai_hints.ai_socktype = SOCK_STREAM;
-  ai_hints.ai_protocol = 0;
-
   host = (st->host != NULL) ? st->host : MEMCACHED_DEF_HOST;
   port = (st->port != NULL) ? st->port : MEMCACHED_DEF_PORT;
 
-  ai_list = NULL;
+  struct addrinfo ai_hints = {
+    .ai_family = AF_UNSPEC,
+    .ai_flags = AI_ADDRCONFIG,
+    .ai_socktype = SOCK_STREAM
+  };
+
   status = getaddrinfo (host, port, &ai_hints, &ai_list);
   if (status != 0)
   {
@@ -133,7 +128,7 @@ static int memcached_connect_inet (memcached_t *st)
     return (-1);
   }
 
-  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
   {
     /* create our socket descriptor */
     fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
@@ -174,8 +169,7 @@ static int memcached_connect (memcached_t *st)
 
 static int memcached_query_daemon (char *buffer, size_t buffer_size, memcached_t *st)
 {
-  int fd = -1;
-  int status;
+  int fd, status;
   size_t buffer_fill;
 
   fd = memcached_connect (st);
@@ -246,21 +240,24 @@ static int memcached_query_daemon (char *buffer, size_t buffer_size, memcached_t
 
 static void memcached_init_vl (value_list_t *vl, memcached_t const *st)
 {
+  char const *host = st->host;
+
+  /* Set vl->host to hostname_g, if:
+   * - Legacy mode is used.
+   * - "Socket" option is given (doc: "Host option is ignored").
+   * - "Host" option is not provided.
+   * - "Host" option is set to "localhost" or "127.0.0.1". */
+  if ((strcmp (st->name, "__legacy__") == 0)
+      || (st->socket != NULL)
+      || (st->host == NULL)
+      || (strcmp ("127.0.0.1", st->host) == 0)
+      || (strcmp ("localhost", st->host) == 0))
+    host = hostname_g;
+
   sstrncpy (vl->plugin, "memcached", sizeof (vl->plugin));
-  if (strcmp (st->name, "__legacy__") == 0) /* legacy mode */
-  {
-    sstrncpy (vl->host, hostname_g, sizeof (vl->host));
-  }
-  else
-  {
-    if (st->socket != NULL)
-      sstrncpy (vl->host, hostname_g, sizeof (vl->host));
-    else
-      sstrncpy (vl->host,
-          (st->host != NULL) ? st->host : MEMCACHED_DEF_HOST,
-          sizeof (vl->host));
+  sstrncpy (vl->host, host, sizeof (vl->host));
+  if (strcmp (st->name, "__legacy__") != 0)
     sstrncpy (vl->plugin_instance, st->name, sizeof (vl->plugin_instance));
-  }
 }
 
 static void submit_derive (const char *type, const char *type_inst,
@@ -552,13 +549,12 @@ static int memcached_read (user_data_t *user_data)
 
 static int memcached_add_read_callback (memcached_t *st)
 {
-  user_data_t ud;
+  user_data_t ud = { 0 };
   char callback_name[3*DATA_MAX_NAME_LEN];
   int status;
 
-  memset (&ud, 0, sizeof (ud));
   ud.data = st;
-  ud.free_func = (void *) memcached_free;
+  ud.free_func = memcached_free;
 
   assert (st->name != NULL);
   ssnprintf (callback_name, sizeof (callback_name), "memcached/%s", st->name);
@@ -566,7 +562,7 @@ static int memcached_add_read_callback (memcached_t *st)
   status = plugin_register_complex_read (/* group = */ "memcached",
       /* name      = */ callback_name,
       /* callback  = */ memcached_read,
-      /* interval  = */ NULL,
+      /* interval  = */ 0,
       /* user_data = */ &ud);
   return (status);
 } /* int memcached_add_read_callback */
@@ -582,20 +578,18 @@ static int memcached_add_read_callback (memcached_t *st)
 static int config_add_instance(oconfig_item_t *ci)
 {
   memcached_t *st;
-  int i;
   int status = 0;
 
   /* Disable automatic generation of default instance in the init callback. */
   memcached_have_instances = 1;
 
-  st = malloc (sizeof (*st));
+  st = calloc (1, sizeof (*st));
   if (st == NULL)
   {
-    ERROR ("memcached plugin: malloc failed.");
+    ERROR ("memcached plugin: calloc failed.");
     return (-1);
   }
 
-  memset (st, 0, sizeof (*st));
   st->name = NULL;
   st->socket = NULL;
   st->host = NULL;
@@ -612,7 +606,7 @@ static int config_add_instance(oconfig_item_t *ci)
   }
   assert (st->name != NULL);
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -649,9 +643,8 @@ static int memcached_config (oconfig_item_t *ci)
 {
   int status = 0;
   _Bool have_instance_block = 0;
-  int i;
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -686,10 +679,9 @@ static int memcached_init (void)
     return (0);
 
   /* No instances were configured, lets start a default instance. */
-  st = malloc (sizeof (*st));
+  st = calloc (1, sizeof (*st));
   if (st == NULL)
     return (ENOMEM);
-  memset (st, 0, sizeof (*st));
   st->name = sstrdup ("__legacy__");
   st->socket = NULL;
   st->host = NULL;
index fb2f3d3..16b8e09 100644 (file)
@@ -24,6 +24,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -76,6 +77,7 @@ static vm_size_t pagesize;
 #elif HAVE_LIBKSTAT
 static int pagesize;
 static kstat_t *ksp;
+static kstat_t *ksz;
 /* #endif HAVE_LIBKSTAT */
 
 #elif HAVE_SYSCTL
@@ -97,9 +99,7 @@ static _Bool values_percentage = 0;
 
 static int memory_config (oconfig_item_t *ci) /* {{{ */
 {
-       int i;
-
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
                if (strcasecmp ("ValuesAbsolute", child->key) == 0)
@@ -137,6 +137,12 @@ static int memory_init (void)
                ksp = NULL;
                return (-1);
        }
+       if (get_kstat (&ksz, "zfs", 0, "arcstats") != 0)
+       {
+               ksz = NULL;
+               return (-1);
+       }
+
 /* #endif HAVE_LIBKSTAT */
 
 #elif HAVE_SYSCTL
@@ -230,7 +236,7 @@ static int memory_read_internal (value_list_t *vl)
         * vm.stats.vm.v_inactive_count: 113730
         * vm.stats.vm.v_cache_count: 10809
         */
-       char *sysctl_keys[8] =
+       const char *sysctl_keys[8] =
        {
                "vm.stats.vm.v_page_size",
                "vm.stats.vm.v_page_count",
@@ -243,9 +249,7 @@ static int memory_read_internal (value_list_t *vl)
        };
        double sysctl_vals[8];
 
-       int    i;
-
-       for (i = 0; sysctl_keys[i] != NULL; i++)
+       for (int i = 0; sysctl_keys[i] != NULL; i++)
        {
                int value;
                size_t value_len = sizeof (value);
@@ -263,7 +267,7 @@ static int memory_read_internal (value_list_t *vl)
        } /* for (sysctl_keys) */
 
        /* multiply all all page counts with the pagesize */
-       for (i = 1; sysctl_keys[i] != NULL; i++)
+       for (int i = 1; sysctl_keys[i] != NULL; i++)
                if (!isnan (sysctl_vals[i]))
                        sysctl_vals[i] *= sysctl_vals[0];
 
@@ -371,6 +375,8 @@ static int memory_read_internal (value_list_t *vl)
        long long mem_lock;
        long long mem_kern;
        long long mem_unus;
+       long long arcsize;
+
 
        long long pp_kernel;
        long long physmem;
@@ -378,17 +384,20 @@ static int memory_read_internal (value_list_t *vl)
 
        if (ksp == NULL)
                return (-1);
+       if (ksz == NULL)
+               return (-1);
 
        mem_used = get_kstat_value (ksp, "pagestotal");
        mem_free = get_kstat_value (ksp, "pagesfree");
        mem_lock = get_kstat_value (ksp, "pageslocked");
-       mem_kern = 0;
-       mem_unus = 0;
-
+       arcsize = get_kstat_value (ksz, "size");
        pp_kernel = get_kstat_value (ksp, "pp_kernel");
        physmem = get_kstat_value (ksp, "physmem");
        availrmem = get_kstat_value (ksp, "availrmem");
 
+       mem_kern = 0;
+       mem_unus = 0;
+
        if ((mem_used < 0LL) || (mem_free < 0LL) || (mem_lock < 0LL))
        {
                WARNING ("memory plugin: one of used, free or locked is negative.");
@@ -431,23 +440,25 @@ static int memory_read_internal (value_list_t *vl)
        mem_lock *= pagesize; /* some? ;) */
        mem_kern *= pagesize; /* it's 2011 RAM is cheap */
        mem_unus *= pagesize;
+       mem_kern -= arcsize;
+
 
        MEMORY_SUBMIT ("used",     (gauge_t) mem_used,
                       "free",     (gauge_t) mem_free,
                       "locked",   (gauge_t) mem_lock,
                       "kernel",   (gauge_t) mem_kern,
+                      "arc",      (gauge_t) arcsize,
                       "unusable", (gauge_t) mem_unus);
 /* #endif HAVE_LIBKSTAT */
 
 #elif HAVE_SYSCTL
        int mib[] = {CTL_VM, VM_METER};
-       struct vmtotal vmtotal;
+       struct vmtotal vmtotal = { 0 };
        gauge_t mem_active;
        gauge_t mem_inactive;
        gauge_t mem_free;
        size_t size;
 
-       memset (&vmtotal, 0, sizeof (vmtotal));
        size = sizeof (vmtotal);
 
        if (sysctl (mib, 2, &vmtotal, &size, NULL, 0) < 0) {
@@ -480,9 +491,8 @@ static int memory_read_internal (value_list_t *vl)
 /* #endif HAVE_LIBSTATGRAB */
 
 #elif HAVE_PERFSTAT
-       perfstat_memory_total_t pmemory;
+       perfstat_memory_total_t pmemory = { 0 };
 
-       memset (&pmemory, 0, sizeof (pmemory));
        if (perfstat_memory_total(NULL, &pmemory, sizeof(pmemory), 1) < 0)
        {
                char errbuf[1024];
index 570da51..3e31889 100644 (file)
--- a/src/mic.c
+++ b/src/mic.c
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "utils_ignorelist.h"
@@ -213,9 +214,8 @@ static void mic_submit_temp(int micnumber, const char *type, gauge_t val)
 static int mic_read_temps(int mic)
 {
        size_t num_therms = STATIC_ARRAY_SIZE(therm_ids);
-       size_t j;
 
-       for (j = 0; j < num_therms; j++) {
+       for (size_t j = 0; j < num_therms; j++) {
                U32 status;
                U32 temp_buffer;
                U32 buffer_size = (U32)sizeof(temp_buffer);
@@ -286,8 +286,7 @@ static int mic_read_cpu(int mic)
        }
 
        if (show_cpu_cores) {
-               int j;
-               for (j = 0; j < core_util.core; j++) {
+               for (int j = 0; j < core_util.core; j++) {
                        mic_submit_cpu(mic, "user", j, core_jiffs[j].user);
                        mic_submit_cpu(mic, "sys", j, core_jiffs[j].sys);
                        mic_submit_cpu(mic, "nice", j, core_jiffs[j].nice);
@@ -356,12 +355,11 @@ static int mic_read_power(int mic)
 
 static int mic_read (void)
 {
-       int i;
        U32 ret;
        int error;
 
        error=0;
-       for (i=0;i<num_mics;i++) {
+       for (int i=0;i<num_mics;i++) {
                ret = MicInitAdapter(&mic_handle,&mics[i]);
                if (ret != MIC_ACCESS_API_SUCCESS) {
                        ERROR("mic plugin: Problem initializing MicAdapter: %s",
index c04b308..db7d033 100644 (file)
@@ -21,6 +21,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -80,7 +81,7 @@ enum mb_register_type_e /* {{{ */
   REG_TYPE_UINT32,
   REG_TYPE_FLOAT
 }; /* }}} */
-enum mb_mreg_type_e /* {{{ */ 
+enum mb_mreg_type_e /* {{{ */
 {
   MREG_HOLDING,
   MREG_INPUT
@@ -161,12 +162,10 @@ static mb_data_t *data_definitions = NULL;
 static mb_data_t *data_get_by_name (mb_data_t *src, /* {{{ */
     const char *name)
 {
-  mb_data_t *ptr;
-
   if (name == NULL)
     return (NULL);
 
-  for (ptr = src; ptr != NULL; ptr = ptr->next)
+  for (mb_data_t *ptr = src; ptr != NULL; ptr = ptr->next)
     if (strcasecmp (ptr->name, name) == 0)
       return (ptr);
 
@@ -257,7 +256,7 @@ static int mb_submit (mb_host_t *host, mb_slave_t *slave, /* {{{ */
   if ((host == NULL) || (slave == NULL) || (data == NULL))
     return (EINVAL);
 
-  if (host->interval <= 0)
+  if (host->interval == 0)
     host->interval = plugin_get_interval ();
 
   if (slave->instance[0] == 0)
@@ -427,7 +426,7 @@ static int mb_init_connection (mb_host_t *host) /* {{{ */
 static int mb_read_data (mb_host_t *host, mb_slave_t *slave, /* {{{ */
     mb_data_t *data)
 {
-  uint16_t values[2];
+  uint16_t values[2] = { 0 };
   int values_num;
   const data_set_t *ds;
   int status = 0;
@@ -444,7 +443,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 %i data sources. "
+    ERROR ("Modbus plugin: The type \"%s\" has %zu data sources. "
         "I can only handle data sets with only one data source.",
         data->type, ds->ds_num);
     return (-1);
@@ -459,7 +458,6 @@ static int mb_read_data (mb_host_t *host, mb_slave_t *slave, /* {{{ */
         "is not UINT32.", data->type, DS_TYPE_TO_STRING (ds->ds[0].type));
   }
 
-  memset (values, 0, sizeof (values));
   if ((data->register_type == REG_TYPE_INT32)
       || (data->register_type == REG_TYPE_UINT32)
       || (data->register_type == REG_TYPE_FLOAT))
@@ -503,7 +501,7 @@ static int mb_read_data (mb_host_t *host, mb_slave_t *slave, /* {{{ */
     modbus_free (host->connection);
 #endif
   }
+
 #if LEGACY_LIBMODBUS
   /* Version 2.0.3: Pass the connection struct as a pointer and pass the slave
    * id to each call of "read_holding_registers". */
@@ -622,7 +620,6 @@ static int mb_read_data (mb_host_t *host, mb_slave_t *slave, /* {{{ */
 
 static int mb_read_slave (mb_host_t *host, mb_slave_t *slave) /* {{{ */
 {
-  mb_data_t *data;
   int success;
   int status;
 
@@ -630,7 +627,7 @@ static int mb_read_slave (mb_host_t *host, mb_slave_t *slave) /* {{{ */
     return (EINVAL);
 
   success = 0;
-  for (data = slave->collect; data != NULL; data = data->next)
+  for (mb_data_t *data = slave->collect; data != NULL; data = data->next)
   {
     status = mb_read_data (host, slave, data);
     if (status == 0)
@@ -646,7 +643,6 @@ static int mb_read_slave (mb_host_t *host, mb_slave_t *slave) /* {{{ */
 static int mb_read (user_data_t *user_data) /* {{{ */
 {
   mb_host_t *host;
-  size_t i;
   int success;
   int status;
 
@@ -656,7 +652,7 @@ static int mb_read (user_data_t *user_data) /* {{{ */
   host = user_data->data;
 
   success = 0;
-  for (i = 0; i < host->slaves_num; i++)
+  for (size_t i = 0; i < host->slaves_num; i++)
   {
     status = mb_read_slave (host, host->slaves + i);
     if (status == 0)
@@ -695,12 +691,10 @@ static void data_free_all (mb_data_t *data) /* {{{ */
 
 static void slaves_free_all (mb_slave_t *slaves, size_t slaves_num) /* {{{ */
 {
-  size_t i;
-
   if (slaves == NULL)
     return;
 
-  for (i = 0; i < slaves_num; i++)
+  for (size_t i = 0; i < slaves_num; i++)
     data_free_all (slaves[i].collect);
   sfree (slaves);
 } /* }}} void slaves_free_all */
@@ -720,11 +714,9 @@ static void host_free (void *void_host) /* {{{ */
 
 static int mb_config_add_data (oconfig_item_t *ci) /* {{{ */
 {
-  mb_data_t data;
+  mb_data_t data = { 0 };
   int status;
-  int i;
 
-  memset (&data, 0, sizeof (data));
   data.name = NULL;
   data.register_type = REG_TYPE_UINT16;
   data.next = NULL;
@@ -733,7 +725,7 @@ static int mb_config_add_data (oconfig_item_t *ci) /* {{{ */
   if (status != 0)
     return (status);
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -819,24 +811,17 @@ static int mb_config_set_host_address (mb_host_t *host, /* {{{ */
     const char *address)
 {
   struct addrinfo *ai_list;
-  struct addrinfo *ai_ptr;
-  struct addrinfo  ai_hints;
   int status;
 
   if ((host == NULL) || (address == NULL))
     return (EINVAL);
 
-  memset (&ai_hints, 0, sizeof (ai_hints));
-#if AI_ADDRCONFIG
-  ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
-  /* XXX: libmodbus can only handle IPv4 addresses. */
-  ai_hints.ai_family = AF_INET;
-  ai_hints.ai_addr = NULL;
-  ai_hints.ai_canonname = NULL;
-  ai_hints.ai_next = NULL;
+  struct addrinfo  ai_hints = {
+    /* XXX: libmodbus can only handle IPv4 addresses. */
+    .ai_family = AF_INET,
+    .ai_flags = AI_ADDRCONFIG
+  };
 
-  ai_list = NULL;
   status = getaddrinfo (address, /* service = */ NULL,
       &ai_hints, &ai_list);
   if (status != 0)
@@ -849,7 +834,7 @@ static int mb_config_set_host_address (mb_host_t *host, /* {{{ */
     return (status);
   }
 
-  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
   {
     status = getnameinfo (ai_ptr->ai_addr, ai_ptr->ai_addrlen,
         host->node, sizeof (host->node),
@@ -876,7 +861,6 @@ static int mb_config_add_slave (mb_host_t *host, oconfig_item_t *ci) /* {{{ */
 {
   mb_slave_t *slave;
   int status;
-  int i;
 
   if ((host == NULL) || (ci == NULL))
     return (EINVAL);
@@ -893,7 +877,7 @@ static int mb_config_add_slave (mb_host_t *host, oconfig_item_t *ci) /* {{{ */
   if (status != 0)
     return (status);
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -936,12 +920,10 @@ static int mb_config_add_host (oconfig_item_t *ci) /* {{{ */
 {
   mb_host_t *host;
   int status;
-  int i;
 
-  host = malloc (sizeof (*host));
+  host = calloc (1, sizeof (*host));
   if (host == NULL)
     return (ENOMEM);
-  memset (host, 0, sizeof (*host));
   host->slaves = NULL;
 
   status = cf_util_get_string_buffer (ci, host->host, sizeof (host->host));
@@ -956,7 +938,7 @@ static int mb_config_add_host (oconfig_item_t *ci) /* {{{ */
     return (EINVAL);
   }
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
     status = 0;
@@ -1024,18 +1006,15 @@ static int mb_config_add_host (oconfig_item_t *ci) /* {{{ */
   {
     user_data_t ud;
     char name[1024];
-    struct timespec interval = { 0, 0 };
 
     ud.data = host;
     ud.free_func = host_free;
 
     ssnprintf (name, sizeof (name), "modbus-%s", host->host);
 
-    CDTIME_T_TO_TIMESPEC (host->interval, &interval);
-
     plugin_register_complex_read (/* group = */ NULL, name,
         /* callback = */ mb_read,
-        /* interval = */ (host->interval > 0) ? &interval : NULL,
+        /* interval = */ host->interval,
         &ud);
   }
   else
@@ -1048,12 +1027,10 @@ static int mb_config_add_host (oconfig_item_t *ci) /* {{{ */
 
 static int mb_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
   if (ci == NULL)
     return (EINVAL);
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
diff --git a/src/mqtt.c b/src/mqtt.c
new file mode 100644 (file)
index 0000000..a7a0b86
--- /dev/null
@@ -0,0 +1,799 @@
+/**
+ * collectd - src/mqtt.c
+ * Copyright (C) 2014       Marc Falzon
+ * Copyright (C) 2014,2015  Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Marc Falzon <marc at baha dot mu>
+ *   Florian octo Forster <octo at collectd.org>
+ *   Jan-Piet Mens <jpmens at gmail.com>
+ **/
+
+// Reference: http://mosquitto.org/api/files/mosquitto-h.html
+
+
+#include "collectd.h"
+
+#include "common.h"
+#include "plugin.h"
+#include "utils_complain.h"
+
+#include <mosquitto.h>
+
+#define MQTT_MAX_TOPIC_SIZE         1024
+#define MQTT_MAX_MESSAGE_SIZE       MQTT_MAX_TOPIC_SIZE + 1024
+#define MQTT_DEFAULT_HOST           "localhost"
+#define MQTT_DEFAULT_PORT           1883
+#define MQTT_DEFAULT_TOPIC_PREFIX   "collectd"
+#define MQTT_DEFAULT_TOPIC          "collectd/#"
+#ifndef MQTT_KEEPALIVE
+# define MQTT_KEEPALIVE 60
+#endif
+#ifndef SSL_VERIFY_PEER
+# define SSL_VERIFY_PEER  1
+#endif
+
+
+/*
+ * Data types
+ */
+struct mqtt_client_conf
+{
+    _Bool               publish;
+    char               *name;
+
+    struct mosquitto   *mosq;
+    _Bool               connected;
+
+    char               *host;
+    int                 port;
+    char               *client_id;
+    char               *username;
+    char               *password;
+    int                 qos;
+    char                *cacertificatefile;
+    char                *certificatefile;
+    char                *certificatekeyfile;
+    char                *tlsprotocol;
+    char                *ciphersuite;
+
+    /* For publishing */
+    char               *topic_prefix;
+    _Bool               store_rates;
+    _Bool               retain;
+
+    /* For subscribing */
+    pthread_t           thread;
+    _Bool               loop;
+    char               *topic;
+    _Bool               clean_session;
+
+    c_complain_t        complaint_cantpublish;
+    pthread_mutex_t     lock;
+};
+typedef struct mqtt_client_conf mqtt_client_conf_t;
+
+static mqtt_client_conf_t **subscribers = NULL;
+static size_t subscribers_num = 0;
+
+/*
+ * Functions
+ */
+#if LIBMOSQUITTO_MAJOR == 0
+static char const *mosquitto_strerror (int code)
+{
+    switch (code)
+    {
+        case MOSQ_ERR_SUCCESS: return "MOSQ_ERR_SUCCESS";
+        case MOSQ_ERR_NOMEM: return "MOSQ_ERR_NOMEM";
+        case MOSQ_ERR_PROTOCOL: return "MOSQ_ERR_PROTOCOL";
+        case MOSQ_ERR_INVAL: return "MOSQ_ERR_INVAL";
+        case MOSQ_ERR_NO_CONN: return "MOSQ_ERR_NO_CONN";
+        case MOSQ_ERR_CONN_REFUSED: return "MOSQ_ERR_CONN_REFUSED";
+        case MOSQ_ERR_NOT_FOUND: return "MOSQ_ERR_NOT_FOUND";
+        case MOSQ_ERR_CONN_LOST: return "MOSQ_ERR_CONN_LOST";
+        case MOSQ_ERR_SSL: return "MOSQ_ERR_SSL";
+        case MOSQ_ERR_PAYLOAD_SIZE: return "MOSQ_ERR_PAYLOAD_SIZE";
+        case MOSQ_ERR_NOT_SUPPORTED: return "MOSQ_ERR_NOT_SUPPORTED";
+        case MOSQ_ERR_AUTH: return "MOSQ_ERR_AUTH";
+        case MOSQ_ERR_ACL_DENIED: return "MOSQ_ERR_ACL_DENIED";
+        case MOSQ_ERR_UNKNOWN: return "MOSQ_ERR_UNKNOWN";
+        case MOSQ_ERR_ERRNO: return "MOSQ_ERR_ERRNO";
+    }
+
+    return "UNKNOWN ERROR CODE";
+}
+#else
+/* provided by libmosquitto */
+#endif
+
+static void mqtt_free (mqtt_client_conf_t *conf)
+{
+    if (conf == NULL)
+        return;
+
+    if (conf->connected)
+        (void) mosquitto_disconnect (conf->mosq);
+    conf->connected = 0;
+    (void) mosquitto_destroy (conf->mosq);
+
+    sfree (conf->host);
+    sfree (conf->username);
+    sfree (conf->password);
+    sfree (conf->client_id);
+    sfree (conf->topic_prefix);
+    sfree (conf);
+}
+
+static char *strip_prefix (char *topic)
+{
+    size_t num = 0;
+
+    for (size_t i = 0; topic[i] != 0; i++)
+        if (topic[i] == '/')
+            num++;
+
+    if (num < 2)
+        return (NULL);
+
+    while (num > 2)
+    {
+        char *tmp = strchr (topic, '/');
+        if (tmp == NULL)
+            return (NULL);
+        topic = tmp + 1;
+        num--;
+    }
+
+    return (topic);
+}
+
+static void on_message (
+#if LIBMOSQUITTO_MAJOR == 0
+#else
+        __attribute__((unused)) struct mosquitto *m,
+#endif
+        __attribute__((unused)) void *arg,
+        const struct mosquitto_message *msg)
+{
+    value_list_t vl = VALUE_LIST_INIT;
+    data_set_t const *ds;
+    char *topic;
+    char *name;
+    char *payload;
+    int status;
+
+    if (msg->payloadlen <= 0) {
+        DEBUG ("mqtt plugin: message has empty payload");
+        return;
+    }
+
+    topic = strdup (msg->topic);
+    name = strip_prefix (topic);
+
+    status = parse_identifier_vl (name, &vl);
+    if (status != 0)
+    {
+        ERROR ("mqtt plugin: Unable to parse topic \"%s\".", topic);
+        sfree (topic);
+        return;
+    }
+    sfree (topic);
+
+    ds = plugin_get_ds (vl.type);
+    if (ds == NULL)
+    {
+        ERROR ("mqtt plugin: Unknown type: \"%s\".", vl.type);
+        return;
+    }
+
+    vl.values = calloc (ds->ds_num, sizeof (*vl.values));
+    if (vl.values == NULL)
+    {
+        ERROR ("mqtt plugin: calloc failed.");
+        return;
+    }
+    vl.values_len = ds->ds_num;
+
+    payload = malloc (msg->payloadlen+1);
+    if (payload == NULL)
+    {
+        ERROR ("mqtt plugin: malloc for payload buffer failed.");
+        sfree (vl.values);
+        return;
+    }
+    memmove (payload, msg->payload, msg->payloadlen);
+    payload[msg->payloadlen] = 0;
+
+    DEBUG ("mqtt plugin: payload = \"%s\"", payload);
+    status = parse_values (payload, &vl, ds);
+    if (status != 0)
+    {
+        ERROR ("mqtt plugin: Unable to parse payload \"%s\".", payload);
+        sfree (payload);
+        sfree (vl.values);
+        return;
+    }
+    sfree (payload);
+
+    plugin_dispatch_values (&vl);
+    sfree (vl.values);
+} /* void on_message */
+
+/* must hold conf->lock when calling. */
+static int mqtt_reconnect (mqtt_client_conf_t *conf)
+{
+    int status;
+
+    if (conf->connected)
+        return (0);
+
+    status = mosquitto_reconnect (conf->mosq);
+    if (status != MOSQ_ERR_SUCCESS)
+    {
+        char errbuf[1024];
+        ERROR ("mqtt_connect_broker: mosquitto_connect failed: %s",
+                (status == MOSQ_ERR_ERRNO)
+                ? sstrerror(errno, errbuf, sizeof (errbuf))
+                : mosquitto_strerror (status));
+        return (-1);
+    }
+
+    conf->connected = 1;
+
+    c_release (LOG_INFO,
+            &conf->complaint_cantpublish,
+            "mqtt plugin: successfully reconnected to broker \"%s:%d\"",
+            conf->host, conf->port);
+
+    return (0);
+} /* mqtt_reconnect */
+
+/* must hold conf->lock when calling. */
+static int mqtt_connect (mqtt_client_conf_t *conf)
+{
+    char const *client_id;
+    int status;
+
+    if (conf->mosq != NULL)
+        return mqtt_reconnect (conf);
+
+    if (conf->client_id)
+        client_id = conf->client_id;
+    else
+        client_id = hostname_g;
+
+#if LIBMOSQUITTO_MAJOR == 0
+    conf->mosq = mosquitto_new (client_id, /* user data = */ conf);
+#else
+    conf->mosq = mosquitto_new (client_id, conf->clean_session, /* user data = */ conf);
+#endif
+    if (conf->mosq == NULL)
+    {
+        ERROR ("mqtt plugin: mosquitto_new failed");
+        return (-1);
+    }
+
+#if LIBMOSQUITTO_MAJOR != 0
+    if (conf->cacertificatefile) {
+        status = mosquitto_tls_set(conf->mosq, conf->cacertificatefile, NULL,
+                                  conf->certificatefile, conf->certificatekeyfile, /* pw_callback */NULL);
+        if (status != MOSQ_ERR_SUCCESS) {
+            ERROR ("mqtt plugin: cannot mosquitto_tls_set: %s", mosquitto_strerror(status));
+            mosquitto_destroy (conf->mosq);
+            conf->mosq = NULL;
+            return (-1);
+        }
+
+        status = mosquitto_tls_opts_set(conf->mosq, SSL_VERIFY_PEER, conf->tlsprotocol, conf->ciphersuite);
+        if (status != MOSQ_ERR_SUCCESS) {
+            ERROR ("mqtt plugin: cannot mosquitto_tls_opts_set: %s", mosquitto_strerror(status));
+            mosquitto_destroy (conf->mosq);
+            conf->mosq = NULL;
+            return (-1);
+        }
+
+        status = mosquitto_tls_insecure_set(conf->mosq, false);
+        if (status != MOSQ_ERR_SUCCESS) {
+            ERROR ("mqtt plugin: cannot mosquitto_tls_insecure_set: %s", mosquitto_strerror(status));
+            mosquitto_destroy (conf->mosq);
+            conf->mosq = NULL;
+            return (-1);
+        }
+    }
+#endif
+
+    if (conf->username && conf->password)
+    {
+        status = mosquitto_username_pw_set (conf->mosq, conf->username, conf->password);
+        if (status != MOSQ_ERR_SUCCESS)
+        {
+            char errbuf[1024];
+            ERROR ("mqtt plugin: mosquitto_username_pw_set failed: %s",
+                    (status == MOSQ_ERR_ERRNO)
+                    ? sstrerror (errno, errbuf, sizeof (errbuf))
+                    : mosquitto_strerror (status));
+
+            mosquitto_destroy (conf->mosq);
+            conf->mosq = NULL;
+            return (-1);
+        }
+    }
+
+#if LIBMOSQUITTO_MAJOR == 0
+    status = mosquitto_connect (conf->mosq, conf->host, conf->port,
+            /* keepalive = */ MQTT_KEEPALIVE, /* clean session = */ conf->clean_session);
+#else
+    status = mosquitto_connect (conf->mosq, conf->host, conf->port, MQTT_KEEPALIVE);
+#endif
+    if (status != MOSQ_ERR_SUCCESS)
+    {
+        char errbuf[1024];
+        ERROR ("mqtt plugin: mosquitto_connect failed: %s",
+                (status == MOSQ_ERR_ERRNO)
+                ? sstrerror (errno, errbuf, sizeof (errbuf))
+                : mosquitto_strerror (status));
+
+        mosquitto_destroy (conf->mosq);
+        conf->mosq = NULL;
+        return (-1);
+    }
+
+    if (!conf->publish)
+    {
+        mosquitto_message_callback_set (conf->mosq, on_message);
+
+        status = mosquitto_subscribe (conf->mosq,
+                /* message_id = */ NULL,
+                conf->topic, conf->qos);
+        if (status != MOSQ_ERR_SUCCESS)
+        {
+            ERROR ("mqtt plugin: Subscribing to \"%s\" failed: %s",
+                    conf->topic, mosquitto_strerror (status));
+
+            mosquitto_disconnect (conf->mosq);
+            mosquitto_destroy (conf->mosq);
+            conf->mosq = NULL;
+            return (-1);
+        }
+    }
+
+    conf->connected = 1;
+    return (0);
+} /* mqtt_connect */
+
+static void *subscribers_thread (void *arg)
+{
+    mqtt_client_conf_t *conf = arg;
+    int status;
+
+    conf->loop = 1;
+
+    while (conf->loop)
+    {
+        status = mqtt_connect (conf);
+        if (status != 0)
+        {
+            sleep (1);
+            continue;
+        }
+
+        /* The documentation says "0" would map to the default (1000ms), but
+         * that does not work on some versions. */
+#if LIBMOSQUITTO_MAJOR == 0
+        status = mosquitto_loop (conf->mosq, /* timeout = */ 1000 /* ms */);
+#else
+        status = mosquitto_loop (conf->mosq,
+                /* timeout[ms] = */ 1000,
+                /* max_packets = */  100);
+#endif
+        if (status == MOSQ_ERR_CONN_LOST)
+        {
+            conf->connected = 0;
+            continue;
+        }
+        else if (status != MOSQ_ERR_SUCCESS)
+        {
+            ERROR ("mqtt plugin: mosquitto_loop failed: %s",
+                    mosquitto_strerror (status));
+            mosquitto_destroy (conf->mosq);
+            conf->mosq = NULL;
+            conf->connected = 0;
+            continue;
+        }
+
+        DEBUG ("mqtt plugin: mosquitto_loop succeeded.");
+    } /* while (conf->loop) */
+
+    pthread_exit (0);
+} /* void *subscribers_thread */
+
+static int publish (mqtt_client_conf_t *conf, char const *topic,
+    void const *payload, size_t payload_len)
+{
+    int status;
+
+    pthread_mutex_lock (&conf->lock);
+
+    status = mqtt_connect (conf);
+    if (status != 0) {
+        pthread_mutex_unlock (&conf->lock);
+        ERROR ("mqtt plugin: unable to reconnect to broker");
+        return (status);
+    }
+
+    status = mosquitto_publish(conf->mosq, /* message_id */ NULL, topic,
+#if LIBMOSQUITTO_MAJOR == 0
+            (uint32_t) payload_len, payload,
+#else
+            (int) payload_len, payload,
+#endif
+            conf->qos, conf->retain);
+    if (status != MOSQ_ERR_SUCCESS)
+    {
+        char errbuf[1024];
+        c_complain (LOG_ERR,
+            &conf->complaint_cantpublish,
+            "mqtt plugin: mosquitto_publish failed: %s",
+            (status == MOSQ_ERR_ERRNO)
+            ? sstrerror(errno, errbuf, sizeof (errbuf))
+            : mosquitto_strerror(status));
+        /* Mark our connection "down" regardless of the error as a safety
+         * measure; we will try to reconnect the next time we have to publish a
+         * message */
+        conf->connected = 0;
+
+        pthread_mutex_unlock (&conf->lock);
+        return (-1);
+    }
+
+    pthread_mutex_unlock (&conf->lock);
+    return (0);
+} /* int publish */
+
+static int format_topic (char *buf, size_t buf_len,
+    data_set_t const *ds, value_list_t const *vl,
+    mqtt_client_conf_t *conf)
+{
+    char name[MQTT_MAX_TOPIC_SIZE];
+    int status;
+
+    if ((conf->topic_prefix == NULL) || (conf->topic_prefix[0] == 0))
+        return (FORMAT_VL (buf, buf_len, vl));
+
+    status = FORMAT_VL (name, sizeof (name), vl);
+    if (status != 0)
+        return (status);
+
+    status = ssnprintf (buf, buf_len, "%s/%s", conf->topic_prefix, name);
+    if ((status < 0) || (((size_t) status) >= buf_len))
+        return (ENOMEM);
+
+    return (0);
+} /* int format_topic */
+
+static int mqtt_write (const data_set_t *ds, const value_list_t *vl,
+    user_data_t *user_data)
+{
+    mqtt_client_conf_t *conf;
+    char topic[MQTT_MAX_TOPIC_SIZE];
+    char payload[MQTT_MAX_MESSAGE_SIZE];
+    int status = 0;
+
+    if ((user_data == NULL) || (user_data->data == NULL))
+        return (EINVAL);
+    conf = user_data->data;
+
+    status = format_topic (topic, sizeof (topic), ds, vl, conf);
+    if (status != 0)
+    {
+        ERROR ("mqtt plugin: format_topic failed with status %d.", status);
+        return (status);
+    }
+
+    status = format_values (payload, sizeof (payload),
+            ds, vl, conf->store_rates);
+    if (status != 0)
+    {
+        ERROR ("mqtt plugin: format_values failed with status %d.", status);
+        return (status);
+    }
+
+    status = publish (conf, topic, payload, strlen (payload) + 1);
+    if (status != 0)
+    {
+        ERROR ("mqtt plugin: publish failed: %s", mosquitto_strerror (status));
+        return (status);
+    }
+
+    return (status);
+} /* mqtt_write */
+
+/*
+ * <Publish "name">
+ *   Host "example.com"
+ *   Port 1883
+ *   ClientId "collectd"
+ *   User "guest"
+ *   Password "secret"
+ *   Prefix "collectd"
+ *   StoreRates true
+ *   Retain false
+ *   QoS 0
+ *   CACert "ca.pem"                   Enables TLS if set
+ *   CertificateFile "client-cert.pem"         optional
+ *   CertificateKeyFile "client-key.pem"               optional
+ *   TLSProtocol "tlsv1.2"             optional
+ * </Publish>
+ */
+static int mqtt_config_publisher (oconfig_item_t *ci)
+{
+    mqtt_client_conf_t *conf;
+    char cb_name[1024];
+    user_data_t user_data = { 0 };
+    int status;
+
+    conf = calloc (1, sizeof (*conf));
+    if (conf == NULL)
+    {
+        ERROR ("mqtt plugin: calloc failed.");
+        return (-1);
+    }
+    conf->publish = 1;
+
+    conf->name = NULL;
+    status = cf_util_get_string (ci, &conf->name);
+    if (status != 0)
+    {
+        mqtt_free (conf);
+        return (status);
+    }
+
+    conf->host = strdup (MQTT_DEFAULT_HOST);
+    conf->port = MQTT_DEFAULT_PORT;
+    conf->client_id = NULL;
+    conf->qos = 0;
+    conf->topic_prefix = strdup (MQTT_DEFAULT_TOPIC_PREFIX);
+    conf->store_rates = 1;
+
+    status = pthread_mutex_init (&conf->lock, NULL);
+    if (status != 0)
+    {
+      mqtt_free (conf);
+      return (status);
+    }
+
+    C_COMPLAIN_INIT (&conf->complaint_cantpublish);
+
+    for (int i = 0; i < ci->children_num; i++)
+    {
+        oconfig_item_t *child = ci->children + i;
+        if (strcasecmp ("Host", child->key) == 0)
+            cf_util_get_string (child, &conf->host);
+        else if (strcasecmp ("Port", child->key) == 0)
+        {
+            int tmp = cf_util_get_port_number (child);
+            if (tmp < 0)
+                ERROR ("mqtt plugin: Invalid port number.");
+            else
+                conf->port = tmp;
+        }
+        else if (strcasecmp ("ClientId", child->key) == 0)
+            cf_util_get_string (child, &conf->client_id);
+        else if (strcasecmp ("User", child->key) == 0)
+            cf_util_get_string (child, &conf->username);
+        else if (strcasecmp ("Password", child->key) == 0)
+            cf_util_get_string (child, &conf->password);
+        else if (strcasecmp ("QoS", child->key) == 0)
+        {
+            int tmp = -1;
+            status = cf_util_get_int (child, &tmp);
+            if ((status != 0) || (tmp < 0) || (tmp > 2))
+                ERROR ("mqtt plugin: Not a valid QoS setting.");
+            else
+                conf->qos = tmp;
+        }
+        else if (strcasecmp ("Prefix", child->key) == 0)
+            cf_util_get_string (child, &conf->topic_prefix);
+        else if (strcasecmp ("StoreRates", child->key) == 0)
+            cf_util_get_boolean (child, &conf->store_rates);
+        else if (strcasecmp ("Retain", child->key) == 0)
+            cf_util_get_boolean (child, &conf->retain);
+        else if (strcasecmp ("CACert", child->key) == 0)
+            cf_util_get_string (child, &conf->cacertificatefile);
+        else if (strcasecmp ("CertificateFile", child->key) == 0)
+            cf_util_get_string (child, &conf->certificatefile);
+        else if (strcasecmp ("CertificateKeyFile", child->key) == 0)
+            cf_util_get_string (child, &conf->certificatekeyfile);
+        else if (strcasecmp ("TLSProtocol", child->key) == 0)
+            cf_util_get_string (child, &conf->tlsprotocol);
+        else if (strcasecmp ("CipherSuite", child->key) == 0)
+            cf_util_get_string (child, &conf->ciphersuite);
+        else
+            ERROR ("mqtt plugin: Unknown config option: %s", child->key);
+    }
+
+    ssnprintf (cb_name, sizeof (cb_name), "mqtt/%s", conf->name);
+    user_data.data = conf;
+
+    plugin_register_write (cb_name, mqtt_write, &user_data);
+    return (0);
+} /* mqtt_config_publisher */
+
+/*
+ * <Subscribe "name">
+ *   Host "example.com"
+ *   Port 1883
+ *   ClientId "collectd"
+ *   User "guest"
+ *   Password "secret"
+ *   Topic "collectd/#"
+ * </Subscribe>
+ */
+static int mqtt_config_subscriber (oconfig_item_t *ci)
+{
+    mqtt_client_conf_t **tmp;
+    mqtt_client_conf_t *conf;
+    int status;
+
+    conf = calloc (1, sizeof (*conf));
+    if (conf == NULL)
+    {
+        ERROR ("mqtt plugin: calloc failed.");
+        return (-1);
+    }
+    conf->publish = 0;
+
+    conf->name = NULL;
+    status = cf_util_get_string (ci, &conf->name);
+    if (status != 0)
+    {
+        mqtt_free (conf);
+        return (status);
+    }
+
+    conf->host = strdup (MQTT_DEFAULT_HOST);
+    conf->port = MQTT_DEFAULT_PORT;
+    conf->client_id = NULL;
+    conf->qos = 2;
+    conf->topic = strdup (MQTT_DEFAULT_TOPIC);
+    conf->clean_session = 1;
+
+    status = pthread_mutex_init (&conf->lock, NULL);
+    if (status != 0)
+    {
+      mqtt_free (conf);
+      return (status);
+    }
+
+    C_COMPLAIN_INIT (&conf->complaint_cantpublish);
+
+    for (int i = 0; i < ci->children_num; i++)
+    {
+        oconfig_item_t *child = ci->children + i;
+        if (strcasecmp ("Host", child->key) == 0)
+            cf_util_get_string (child, &conf->host);
+        else if (strcasecmp ("Port", child->key) == 0)
+        {
+            status = cf_util_get_port_number (child);
+            if (status < 0)
+                ERROR ("mqtt plugin: Invalid port number.");
+            else
+                conf->port = status;
+        }
+        else if (strcasecmp ("ClientId", child->key) == 0)
+            cf_util_get_string (child, &conf->client_id);
+        else if (strcasecmp ("User", child->key) == 0)
+            cf_util_get_string (child, &conf->username);
+        else if (strcasecmp ("Password", child->key) == 0)
+            cf_util_get_string (child, &conf->password);
+        else if (strcasecmp ("QoS", child->key) == 0)
+        {
+            int qos = -1;
+            status = cf_util_get_int (child, &qos);
+            if ((status != 0) || (qos < 0) || (qos > 2))
+                ERROR ("mqtt plugin: Not a valid QoS setting.");
+            else
+                conf->qos = qos;
+        }
+        else if (strcasecmp ("Topic", child->key) == 0)
+            cf_util_get_string (child, &conf->topic);
+        else if (strcasecmp ("CleanSession", child->key) == 0)
+            cf_util_get_boolean (child, &conf->clean_session);
+        else
+            ERROR ("mqtt plugin: Unknown config option: %s", child->key);
+    }
+
+    tmp = realloc (subscribers, sizeof (*subscribers) * (subscribers_num + 1) );
+    if (tmp == NULL)
+    {
+        ERROR ("mqtt plugin: realloc failed.");
+        mqtt_free (conf);
+        return (-1);
+    }
+    subscribers = tmp;
+    subscribers[subscribers_num] = conf;
+    subscribers_num++;
+
+    return (0);
+} /* mqtt_config_subscriber */
+
+/*
+ * <Plugin mqtt>
+ *   <Publish "name">
+ *     # ...
+ *   </Publish>
+ *   <Subscribe "name">
+ *     # ...
+ *   </Subscribe>
+ * </Plugin>
+ */
+static int mqtt_config (oconfig_item_t *ci)
+{
+    for (int i = 0; i < ci->children_num; i++)
+    {
+        oconfig_item_t *child = ci->children + i;
+
+        if (strcasecmp ("Publish", child->key) == 0)
+            mqtt_config_publisher (child);
+        else if (strcasecmp ("Subscribe", child->key) == 0)
+            mqtt_config_subscriber (child);
+        else
+            ERROR ("mqtt plugin: Unknown config option: %s", child->key);
+    }
+
+    return (0);
+} /* int mqtt_config */
+
+static int mqtt_init (void)
+{
+    mosquitto_lib_init ();
+
+    for (size_t i = 0; i < subscribers_num; i++)
+    {
+        int status;
+
+        if (subscribers[i]->loop)
+            continue;
+
+        status = plugin_thread_create (&subscribers[i]->thread,
+                /* attrs = */ NULL,
+                /* func  = */ subscribers_thread,
+                /* args  = */ subscribers[i]);
+        if (status != 0)
+        {
+            char errbuf[1024];
+            ERROR ("mqtt plugin: pthread_create failed: %s",
+                    sstrerror (errno, errbuf, sizeof (errbuf)));
+            continue;
+        }
+    }
+
+    return (0);
+} /* mqtt_init */
+
+void module_register (void)
+{
+    plugin_register_complex_config ("mqtt", mqtt_config);
+    plugin_register_init ("mqtt", mqtt_init);
+} /* void module_register */
+
+/* vim: set sw=4 sts=4 et fdm=marker : */
index 6953750..02fe1ad 100644 (file)
@@ -23,6 +23,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -148,20 +149,18 @@ static int multimeter_read_value(double *value)
 
 static int multimeter_init (void)
 {
-       int i;
        char device[] = "/dev/ttyS ";
 
-       for (i = 0; i < 10; i++)
+       for (int i = 0; i < 10; i++)
        {
                device[strlen(device)-1] = i + '0';
 
                if ((fd = open(device, O_RDWR | O_NOCTTY)) != -1)
                {
-                       struct termios tios;
+                       struct termios tios = { 0 };
                        int rts = TIOCM_RTS;
                        double value;
 
-                       memset (&tios, 0, sizeof (tios));
                        tios.c_cflag = B1200 | CS7 | CSTOPB | CREAD | CLOCAL;
                        tios.c_iflag = IGNBRK | IGNPAR;
                        tios.c_oflag = 0;
index f6c710c..ff6c0a7 100644 (file)
@@ -28,6 +28,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -46,6 +47,14 @@ struct mysql_database_s /* {{{ */
        char *user;
        char *pass;
        char *database;
+
+       /* mysql_ssl_set params */
+       char *key;
+       char *cert;
+       char *ca;
+       char *capath;
+       char *cipher;
+
        char *socket;
        int   port;
        int   timeout;
@@ -53,6 +62,7 @@ struct mysql_database_s /* {{{ */
        _Bool master_stats;
        _Bool slave_stats;
        _Bool innodb_stats;
+       _Bool wsrep_stats;
 
        _Bool slave_notif;
        _Bool slave_io_running;
@@ -71,7 +81,7 @@ static void mysql_database_free (void *arg) /* {{{ */
 
        DEBUG ("mysql plugin: mysql_database_free (arg = %p);", arg);
 
-       db = (mysql_database_t *) arg;
+       db = arg;
 
        if (db == NULL)
                return;
@@ -86,6 +96,11 @@ static void mysql_database_free (void *arg) /* {{{ */
        sfree (db->socket);
        sfree (db->instance);
        sfree (db->database);
+       sfree (db->key);
+       sfree (db->cert);
+       sfree (db->ca);
+       sfree (db->capath);
+       sfree (db->cipher);
        sfree (db);
 } /* }}} void mysql_database_free */
 
@@ -103,7 +118,6 @@ static int mysql_config_database (oconfig_item_t *ci) /* {{{ */
 {
        mysql_database_t *db;
        int status = 0;
-       int i;
 
        if ((ci->values_num != 1)
            || (ci->values[0].type != OCONFIG_TYPE_STRING))
@@ -113,13 +127,12 @@ static int mysql_config_database (oconfig_item_t *ci) /* {{{ */
                return (-1);
        }
 
-       db = (mysql_database_t *) malloc (sizeof (*db));
+       db = calloc (1, sizeof (*db));
        if (db == NULL)
        {
-               ERROR ("mysql plugin: malloc failed.");
+               ERROR ("mysql plugin: calloc failed.");
                return (-1);
        }
-       memset (db, 0, sizeof (*db));
 
        /* initialize all the pointers */
        db->alias    = NULL;
@@ -127,6 +140,12 @@ static int mysql_config_database (oconfig_item_t *ci) /* {{{ */
        db->user     = NULL;
        db->pass     = NULL;
        db->database = NULL;
+       db->key      = NULL;
+       db->cert     = NULL;
+       db->ca       = NULL;
+       db->capath   = NULL;
+       db->cipher   = NULL;
+
        db->socket   = NULL;
        db->con      = NULL;
        db->timeout  = 0;
@@ -144,7 +163,7 @@ static int mysql_config_database (oconfig_item_t *ci) /* {{{ */
        assert (db->instance != NULL);
 
        /* Fill the `mysql_database_t' structure.. */
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
 
@@ -169,6 +188,16 @@ static int mysql_config_database (oconfig_item_t *ci) /* {{{ */
                        status = cf_util_get_string (child, &db->socket);
                else if (strcasecmp ("Database", child->key) == 0)
                        status = cf_util_get_string (child, &db->database);
+               else if (strcasecmp ("SSLKey", child->key) == 0)
+                       status = cf_util_get_string (child, &db->key);
+               else if (strcasecmp ("SSLCert", child->key) == 0)
+                       status = cf_util_get_string (child, &db->cert);
+               else if (strcasecmp ("SSLCA", child->key) == 0)
+                       status = cf_util_get_string (child, &db->ca);
+               else if (strcasecmp ("SSLCAPath", child->key) == 0)
+                       status = cf_util_get_string (child, &db->capath);
+               else if (strcasecmp ("SSLCipher", child->key) == 0)
+                       status = cf_util_get_string (child, &db->cipher);
                else if (strcasecmp ("ConnectTimeout", child->key) == 0)
                        status = cf_util_get_int (child, &db->timeout);
                else if (strcasecmp ("MasterStats", child->key) == 0)
@@ -179,6 +208,8 @@ static int mysql_config_database (oconfig_item_t *ci) /* {{{ */
                        status = cf_util_get_boolean (child, &db->slave_notif);
                else if (strcasecmp ("InnodbStats", child->key) == 0)
                        status = cf_util_get_boolean (child, &db->innodb_stats);
+               else if (strcasecmp ("WsrepStats", child->key) == 0)
+                       status = cf_util_get_boolean (child, &db->wsrep_stats);
                else
                {
                        WARNING ("mysql plugin: Option `%s' not allowed here.", child->key);
@@ -192,13 +223,12 @@ static int mysql_config_database (oconfig_item_t *ci) /* {{{ */
        /* If all went well, register this database for reading */
        if (status == 0)
        {
-               user_data_t ud;
+               user_data_t ud = { 0 };
                char cb_name[DATA_MAX_NAME_LEN];
 
                DEBUG ("mysql plugin: Registering new read callback: %s",
                                (db->database != NULL) ? db->database : "<default>");
 
-               memset (&ud, 0, sizeof (ud));
                ud.data = (void *) db;
                ud.free_func = mysql_database_free;
 
@@ -210,7 +240,7 @@ static int mysql_config_database (oconfig_item_t *ci) /* {{{ */
 
                plugin_register_complex_read (/* group = */ NULL, cb_name,
                                              mysql_read,
-                                             /* interval = */ NULL, &ud);
+                                             /* interval = */ 0, &ud);
        }
        else
        {
@@ -223,13 +253,11 @@ static int mysql_config_database (oconfig_item_t *ci) /* {{{ */
 
 static int mysql_config (oconfig_item_t *ci) /* {{{ */
 {
-       int i;
-
        if (ci == NULL)
                return (EINVAL);
 
        /* Fill the `mysql_database_t' structure.. */
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
 
@@ -247,6 +275,8 @@ static int mysql_config (oconfig_item_t *ci) /* {{{ */
 
 static MYSQL *getconnection (mysql_database_t *db)
 {
+       const char *cipher;
+
        if (db->is_connected)
        {
                int status;
@@ -274,6 +304,8 @@ static MYSQL *getconnection (mysql_database_t *db)
        /* Configure TCP connect timeout (default: 0) */
        db->con->options.connect_timeout = db->timeout;
 
+       mysql_ssl_set (db->con, db->key, db->cert, db->ca, db->capath, db->cipher);
+
        if (mysql_real_connect (db->con, db->host, db->user, db->pass,
                                db->database, db->port, db->socket, 0) == NULL)
        {
@@ -285,10 +317,14 @@ static MYSQL *getconnection (mysql_database_t *db)
                return (NULL);
        }
 
+       cipher = mysql_get_ssl_cipher (db->con);
+
        INFO ("mysql plugin: Successfully connected to database %s "
-                       "at server %s (server version: %s, protocol version: %d)",
+                       "at server %s with cipher %s "
+                       "(server version: %s, protocol version: %d) ",
                        (db->database != NULL) ? db->database : "<none>",
                        mysql_get_host_info (db->con),
+                       (cipher != NULL) ?  cipher : "<none>",
                        mysql_get_server_info (db->con),
                        mysql_get_proto_info (db->con));
 
@@ -400,8 +436,8 @@ static int mysql_read_master_stats (mysql_database_t *db, MYSQL *con)
        MYSQL_RES *res;
        MYSQL_ROW  row;
 
-       char *query;
-       int   field_num;
+       const char *query;
+       int         field_num;
        unsigned long long position;
 
        query = "SHOW MASTER STATUS";
@@ -446,8 +482,8 @@ static int mysql_read_slave_stats (mysql_database_t *db, MYSQL *con)
        MYSQL_RES *res;
        MYSQL_ROW  row;
 
-       char *query;
-       int   field_num;
+       const char *query;
+       int         field_num;
 
        /* WTF? libmysqlclient does not seem to provide any means to
         * translate a column name to a column index ... :-/ */
@@ -569,84 +605,53 @@ static int mysql_read_innodb_stats (mysql_database_t *db, MYSQL *con)
        MYSQL_RES *res;
        MYSQL_ROW  row;
 
-       char *query;
-    struct {
-        char *key;
-        char *type;
-        int ds_type;
-    } metrics[] = {
-        { "metadata_mem_pool_size",         "bytes",        DS_TYPE_GAUGE },
-        { "lock_deadlocks",                 "mysql_locks",  DS_TYPE_DERIVE },
-        { "lock_timeouts",                  "mysql_locks",  DS_TYPE_DERIVE },
-        { "lock_row_lock_current_waits",    "mysql_locks",  DS_TYPE_DERIVE },
-        { "buffer_pool_size",               "bytes",        DS_TYPE_GAUGE },
-
-        { "buffer_pool_reads",              "operations",   DS_TYPE_DERIVE },
-        { "buffer_pool_read_requests",      "operations",   DS_TYPE_DERIVE },
-        { "buffer_pool_write_requests",     "operations",   DS_TYPE_DERIVE },
-        { "buffer_pool_wait_free",          "operations",   DS_TYPE_DERIVE },
-        { "buffer_pool_read_ahead",         "operations",   DS_TYPE_DERIVE },
-        { "buffer_pool_read_ahead_evicted", "operations",   DS_TYPE_DERIVE },
-
-        { "buffer_pool_pages_total",        "gauge",        DS_TYPE_GAUGE },
-        { "buffer_pool_pages_misc",         "gauge",        DS_TYPE_GAUGE },
-        { "buffer_pool_pages_data",         "gauge",        DS_TYPE_GAUGE },
-        { "buffer_pool_bytes_data",         "gauge",        DS_TYPE_GAUGE },
-        { "buffer_pool_pages_dirty",        "gauge",        DS_TYPE_GAUGE },
-        { "buffer_pool_bytes_dirty",        "gauge",        DS_TYPE_GAUGE },
-        { "buffer_pool_pages_free",         "gauge",        DS_TYPE_GAUGE },
-
-        { "buffer_pages_created",           "operations",   DS_TYPE_DERIVE },
-        { "buffer_pages_written",           "operations",   DS_TYPE_DERIVE },
-        { "buffer_pages_read",              "operations",   DS_TYPE_DERIVE },
-        { "buffer_data_reads",              "operations",   DS_TYPE_DERIVE },
-        { "buffer_data_written",            "operations",   DS_TYPE_DERIVE },
-
-        { "os_data_reads",                  "operations",   DS_TYPE_DERIVE },
-        { "os_data_writes",                 "operations",   DS_TYPE_DERIVE },
-        { "os_data_fsyncs",                 "operations",   DS_TYPE_DERIVE },
-        { "os_log_bytes_written",           "operations",   DS_TYPE_DERIVE },
-        { "os_log_fsyncs",                  "operations",   DS_TYPE_DERIVE },
-        { "os_log_pending_fsyncs",          "operations",   DS_TYPE_DERIVE },
-        { "os_log_pending_writes",          "operations",   DS_TYPE_DERIVE },
-
-        { "trx_rseg_history_len",           "gauge",        DS_TYPE_GAUGE },
-
-        { "log_waits",                      "operations",   DS_TYPE_DERIVE },
-        { "log_write_requests",             "operations",   DS_TYPE_DERIVE },
-        { "log_writes",                     "operations",   DS_TYPE_DERIVE },
-        { "adaptive_hash_searches",         "operations",   DS_TYPE_DERIVE },
-
-        { "file_num_open_files",            "gauge",        DS_TYPE_GAUGE },
-
-        { "ibuf_merges_insert",             "operations",   DS_TYPE_DERIVE },
-        { "ibuf_merges_delete_mark",        "operations",   DS_TYPE_DERIVE },
-        { "ibuf_merges_delete",             "operations",   DS_TYPE_DERIVE },
-        { "ibuf_merges_discard_insert",     "operations",   DS_TYPE_DERIVE },
-        { "ibuf_merges_discard_delete_mark","operations",   DS_TYPE_DERIVE },
-        { "ibuf_merges_discard_delete",     "operations",   DS_TYPE_DERIVE },
-        { "ibuf_merges_discard_merges",     "operations",   DS_TYPE_DERIVE },
-        { "ibuf_size",                      "bytes",        DS_TYPE_GAUGE },
-
-        { "innodb_activity_count",          "gauge",        DS_TYPE_GAUGE },
-        { "innodb_dblwr_writes",            "operations",   DS_TYPE_DERIVE },
-        { "innodb_dblwr_pages_written",     "operations",   DS_TYPE_DERIVE },
-        { "innodb_dblwr_page_size",         "gauge",        DS_TYPE_GAUGE },
-
-        { "innodb_rwlock_s_spin_waits",     "operations",   DS_TYPE_DERIVE },
-        { "innodb_rwlock_x_spin_waits",     "operations",   DS_TYPE_DERIVE },
-        { "innodb_rwlock_s_spin_rounds",    "operations",   DS_TYPE_DERIVE },
-        { "innodb_rwlock_x_spin_rounds",    "operations",   DS_TYPE_DERIVE },
-        { "innodb_rwlock_s_os_waits",       "operations",   DS_TYPE_DERIVE },
-        { "innodb_rwlock_x_os_waits",       "operations",   DS_TYPE_DERIVE },
-
-        { "dml_reads",                      "operations",   DS_TYPE_DERIVE },
-        { "dml_inserts",                    "operations",   DS_TYPE_DERIVE },
-        { "dml_deletes",                    "operations",   DS_TYPE_DERIVE },
-        { "dml_updates",                    "operations",   DS_TYPE_DERIVE },
-
-        { NULL,                     NULL,           0}
-    };
+       const char *query;
+       struct {
+               const char *key;
+               const char *type;
+               int ds_type;
+       } metrics[] = {
+               { "metadata_mem_pool_size",          "bytes",        DS_TYPE_GAUGE },
+               { "lock_deadlocks",                  "mysql_locks",  DS_TYPE_DERIVE },
+               { "lock_timeouts",                   "mysql_locks",  DS_TYPE_DERIVE },
+               { "lock_row_lock_current_waits",     "mysql_locks",  DS_TYPE_DERIVE },
+               { "buffer_pool_size",                "bytes",        DS_TYPE_GAUGE },
+
+               { "os_log_bytes_written",            "operations",   DS_TYPE_DERIVE },
+               { "os_log_pending_fsyncs",           "operations",   DS_TYPE_DERIVE },
+               { "os_log_pending_writes",           "operations",   DS_TYPE_DERIVE },
+
+               { "trx_rseg_history_len",            "gauge",        DS_TYPE_GAUGE },
+
+               { "adaptive_hash_searches",          "operations",   DS_TYPE_DERIVE },
+
+               { "file_num_open_files",             "gauge",        DS_TYPE_GAUGE },
+
+               { "ibuf_merges_insert",              "operations",   DS_TYPE_DERIVE },
+               { "ibuf_merges_delete_mark",         "operations",   DS_TYPE_DERIVE },
+               { "ibuf_merges_delete",              "operations",   DS_TYPE_DERIVE },
+               { "ibuf_merges_discard_insert",      "operations",   DS_TYPE_DERIVE },
+               { "ibuf_merges_discard_delete_mark", "operations",   DS_TYPE_DERIVE },
+               { "ibuf_merges_discard_delete",      "operations",   DS_TYPE_DERIVE },
+               { "ibuf_merges_discard_merges",      "operations",   DS_TYPE_DERIVE },
+               { "ibuf_size",                       "bytes",        DS_TYPE_GAUGE },
+
+               { "innodb_activity_count",           "gauge",        DS_TYPE_GAUGE },
+
+               { "innodb_rwlock_s_spin_waits",      "operations",   DS_TYPE_DERIVE },
+               { "innodb_rwlock_x_spin_waits",      "operations",   DS_TYPE_DERIVE },
+               { "innodb_rwlock_s_spin_rounds",     "operations",   DS_TYPE_DERIVE },
+               { "innodb_rwlock_x_spin_rounds",     "operations",   DS_TYPE_DERIVE },
+               { "innodb_rwlock_s_os_waits",        "operations",   DS_TYPE_DERIVE },
+               { "innodb_rwlock_x_os_waits",        "operations",   DS_TYPE_DERIVE },
+
+               { "dml_reads",                       "operations",   DS_TYPE_DERIVE },
+               { "dml_inserts",                     "operations",   DS_TYPE_DERIVE },
+               { "dml_deletes",                     "operations",   DS_TYPE_DERIVE },
+               { "dml_updates",                     "operations",   DS_TYPE_DERIVE },
+
+               { NULL,                              NULL,           0}
+       };
 
        query = "SELECT name, count, type FROM information_schema.innodb_metrics WHERE status = 'enabled'";
 
@@ -656,45 +661,130 @@ static int mysql_read_innodb_stats (mysql_database_t *db, MYSQL *con)
 
        while ((row = mysql_fetch_row (res)))
        {
-        int i;
+               int i;
                char *key;
                unsigned long long val;
 
                key = row[0];
                val = atoll (row[1]);
 
-        for (i = 0;
-             metrics[i].key != NULL && strcmp(metrics[i].key, key) != 0;
-             i++)
-            ;
-
-        if (metrics[i].key == NULL)
-            continue;
-
-        switch (metrics[i].ds_type) {
-        case DS_TYPE_COUNTER:
-            counter_submit(metrics[i].type, key, (counter_t)val, db);
-            break;
-        case DS_TYPE_GAUGE:
-            gauge_submit(metrics[i].type, key, (gauge_t)val, db);
-            break;
-        case DS_TYPE_DERIVE:
-            derive_submit(metrics[i].type, key, (derive_t)val, db);
-            break;
-        }
-    }
-
-    mysql_free_result(res);
-    return (0);
+               for (i = 0; metrics[i].key != NULL && strcmp(metrics[i].key, key) != 0; i++)
+                       ;
+
+               if (metrics[i].key == NULL)
+                       continue;
+
+               switch (metrics[i].ds_type) {
+                       case DS_TYPE_COUNTER:
+                               counter_submit(metrics[i].type, key, (counter_t)val, db);
+                               break;
+                       case DS_TYPE_GAUGE:
+                               gauge_submit(metrics[i].type, key, (gauge_t)val, db);
+                               break;
+                       case DS_TYPE_DERIVE:
+                               derive_submit(metrics[i].type, key, (derive_t)val, db);
+                               break;
+               }
+       }
+
+       mysql_free_result(res);
+       return (0);
 }
 
-static int mysql_read (user_data_t *ud)
+static int mysql_read_wsrep_stats (mysql_database_t *db, MYSQL *con)
 {
-       mysql_database_t *db;
-       MYSQL     *con;
        MYSQL_RES *res;
        MYSQL_ROW  row;
-       char      *query;
+
+       const char *query;
+       struct {
+               const char *key;
+               const char *type;
+               int ds_type;
+       } metrics[] = {
+
+               { "wsrep_apply_oooe",                "operations",   DS_TYPE_DERIVE },
+               { "wsrep_apply_oool",                "operations",   DS_TYPE_DERIVE },
+               { "wsrep_causal_reads",              "operations",   DS_TYPE_DERIVE },
+               { "wsrep_commit_oooe",               "operations",   DS_TYPE_DERIVE },
+               { "wsrep_commit_oool",               "operations",   DS_TYPE_DERIVE },
+               { "wsrep_flow_control_recv",         "operations",   DS_TYPE_DERIVE },
+               { "wsrep_flow_control_sent",         "operations",   DS_TYPE_DERIVE },
+               { "wsrep_flow_control_paused",       "operations",   DS_TYPE_DERIVE },
+               { "wsrep_local_bf_aborts",           "operations",   DS_TYPE_DERIVE },
+               { "wsrep_local_cert_failures",       "operations",   DS_TYPE_DERIVE },
+               { "wsrep_local_commits",             "operations",   DS_TYPE_DERIVE },
+               { "wsrep_local_replays",             "operations",   DS_TYPE_DERIVE },
+               { "wsrep_received",                  "operations",   DS_TYPE_DERIVE },
+               { "wsrep_replicated",                "operations",   DS_TYPE_DERIVE },
+
+               { "wsrep_received_bytes",            "total_bytes",  DS_TYPE_DERIVE },
+               { "wsrep_replicated_bytes",          "total_bytes",  DS_TYPE_DERIVE },
+
+               { "wsrep_apply_window",              "gauge",        DS_TYPE_GAUGE },
+               { "wsrep_commit_window",             "gauge",        DS_TYPE_GAUGE },
+
+               { "wsrep_cluster_size",              "gauge",        DS_TYPE_GAUGE },
+               { "wsrep_cert_deps_distance",        "gauge",        DS_TYPE_GAUGE },
+
+               { "wsrep_local_recv_queue",          "queue_length", DS_TYPE_GAUGE },
+               { "wsrep_local_send_queue",          "queue_length", DS_TYPE_GAUGE },
+
+               { NULL,                              NULL,           0}
+
+       };
+
+       query = "SHOW GLOBAL STATUS LIKE 'wsrep_%'";
+
+       res = exec_query (con, query);
+       if (res == NULL)
+               return (-1);
+
+       row = mysql_fetch_row (res);
+       if (row == NULL)
+       {
+               ERROR ("mysql plugin: Failed to get wsrep statistics: "
+                       "`%s' did not return any rows.", query);
+               mysql_free_result (res);
+               return (-1);
+       }
+
+       while ((row = mysql_fetch_row (res)))
+       {
+               int i;
+               char *key;
+               unsigned long long val;
+
+               key = row[0];
+               val = atoll (row[1]);
+
+               for (i = 0; metrics[i].key != NULL && strcmp(metrics[i].key, key) != 0; i++)
+                       ;
+
+               if (metrics[i].key == NULL)
+                       continue;
+
+               switch (metrics[i].ds_type) {
+                       case DS_TYPE_GAUGE:
+                               gauge_submit(metrics[i].type, key, (gauge_t)val, db);
+                               break;
+                       case DS_TYPE_DERIVE:
+                               derive_submit(metrics[i].type, key, (derive_t)val, db);
+                               break;
+               }
+       }
+
+       mysql_free_result(res);
+       return (0);
+} /* mysql_read_wsrep_stats */
+
+static int mysql_read (user_data_t *ud)
+{
+       mysql_database_t *db;
+       MYSQL      *con;
+       MYSQL_RES  *res;
+       MYSQL_ROW   row;
+       const char *query;
 
        derive_t qcache_hits          = 0;
        derive_t qcache_inserts       = 0;
@@ -709,7 +799,7 @@ static int mysql_read (user_data_t *ud)
 
        unsigned long long traffic_incoming = 0ULL;
        unsigned long long traffic_outgoing = 0ULL;
-    unsigned long mysql_version = 0ULL;
+       unsigned long mysql_version = 0ULL;
 
        if ((ud == NULL) || (ud->data == NULL))
        {
@@ -723,7 +813,7 @@ static int mysql_read (user_data_t *ud)
        if ((con = getconnection (db)) == NULL)
                return (-1);
 
-  mysql_version = mysql_get_server_version(con);
+       mysql_version = mysql_get_server_version(con);
 
        query = "SHOW STATUS";
        if (mysql_version >= 50002)
@@ -741,7 +831,7 @@ static int mysql_read (user_data_t *ud)
                key = row[0];
                val = atoll (row[1]);
 
-               if (strncmp (key, "Com_", 
+               if (strncmp (key, "Com_",
                                  strlen ("Com_")) == 0)
                {
                        if (val == 0ULL)
@@ -749,18 +839,18 @@ static int mysql_read (user_data_t *ud)
 
                        /* Ignore `prepared statements' */
                        if (strncmp (key, "Com_stmt_", strlen ("Com_stmt_")) != 0)
-                               counter_submit ("mysql_commands", 
-                                               key + strlen ("Com_"), 
+                               counter_submit ("mysql_commands",
+                                               key + strlen ("Com_"),
                                                val, db);
                }
-               else if (strncmp (key, "Handler_", 
+               else if (strncmp (key, "Handler_",
                                        strlen ("Handler_")) == 0)
                {
                        if (val == 0ULL)
                                continue;
 
-                       counter_submit ("mysql_handler", 
-                                       key + strlen ("Handler_"), 
+                       counter_submit ("mysql_handler",
+                                       key + strlen ("Handler_"),
                                        val, db);
                }
                else if (strncmp (key, "Qcache_",
@@ -777,7 +867,7 @@ static int mysql_read (user_data_t *ud)
                        else if (strcmp (key, "Qcache_queries_in_cache") == 0)
                                qcache_queries_in_cache = (gauge_t) val;
                }
-               else if (strncmp (key, "Bytes_", 
+               else if (strncmp (key, "Bytes_",
                                        strlen ("Bytes_")) == 0)
                {
                        if (strcmp (key, "Bytes_received") == 0)
@@ -785,7 +875,7 @@ static int mysql_read (user_data_t *ud)
                        else if (strcmp (key, "Bytes_sent") == 0)
                                traffic_outgoing += val;
                }
-               else if (strncmp (key, "Threads_", 
+               else if (strncmp (key, "Threads_",
                                                strlen ("Threads_")) == 0)
                {
                        if (strcmp (key, "Threads_running") == 0)
@@ -829,6 +919,8 @@ static int mysql_read (user_data_t *ud)
                                counter_submit ("mysql_bpool_counters", "read_requests", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_reads") == 0)
                                counter_submit ("mysql_bpool_counters", "reads", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_wait_free") == 0)
+                               counter_submit ("mysql_bpool_counters", "wait_free", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_write_requests") == 0)
                                counter_submit ("mysql_bpool_counters", "write_requests", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_bytes_data") == 0)
@@ -853,6 +945,8 @@ static int mysql_read (user_data_t *ud)
                                counter_submit ("mysql_innodb_dblwr", "writes", val, db);
                        else if (strcmp (key, "Innodb_dblwr_pages_written") == 0)
                                counter_submit ("mysql_innodb_dblwr", "written", val, db);
+                       else if (strcmp (key, "Innodb_dblwr_page_size") == 0)
+                               gauge_submit ("mysql_innodb_dblwr", "page_size", val, db);
 
                        /* log */
                        else if (strcmp (key, "Innodb_log_waits") == 0)
@@ -897,8 +991,19 @@ static int mysql_read (user_data_t *ud)
                }
                else if (strncmp (key, "Sort_", strlen ("Sort_")) == 0)
                {
-                       counter_submit ("mysql_sort", key + strlen ("Sort_"),
-                                       val, db);
+                       if (strcmp (key, "Sort_merge_passes") == 0)
+                               counter_submit ("mysql_sort_merge_passes", NULL, val, db);
+                       else if (strcmp (key, "Sort_rows") == 0)
+                               counter_submit ("mysql_sort_rows", NULL, val, db);
+                       else if (strcmp (key, "Sort_range") == 0)
+                               counter_submit ("mysql_sort", "range", val, db);
+                       else if (strcmp (key, "Sort_scan") == 0)
+                               counter_submit ("mysql_sort", "scan", val, db);
+
+               }
+               else if (strncmp (key, "Slow_queries", strlen ("Slow_queries")) == 0)
+               {
+                       counter_submit ("mysql_slow_queries", NULL , val, db);
                }
        }
        mysql_free_result (res); res = NULL;
@@ -937,7 +1042,7 @@ static int mysql_read (user_data_t *ud)
        traffic_submit  (traffic_incoming, traffic_outgoing, db);
 
        if (mysql_version >= 50600 && db->innodb_stats)
-        mysql_read_innodb_stats (db, con);
+               mysql_read_innodb_stats (db, con);
 
        if (db->master_stats)
                mysql_read_master_stats (db, con);
@@ -945,6 +1050,9 @@ static int mysql_read (user_data_t *ud)
        if ((db->slave_stats) || (db->slave_notif))
                mysql_read_slave_stats (db, con);
 
+       if (db->wsrep_stats)
+               mysql_read_wsrep_stats (db, con);
+
        return (0);
 } /* int mysql_read */
 
index f761e29..26577da 100644 (file)
@@ -27,6 +27,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "utils_ignorelist.h"
 
@@ -464,10 +465,9 @@ static disk_t *get_disk(cfg_disk_t *cd, const char *name) /* {{{ */
                        return d;
        }
 
-       d = malloc(sizeof(*d));
+       d = calloc (1, sizeof (*d));
        if (d == NULL)
                return (NULL);
-       memset (d, 0, sizeof (*d));
        d->next = NULL;
 
        d->name = strdup(name);
@@ -513,10 +513,9 @@ static data_volume_usage_t *get_volume_usage (cfg_volume_usage_t *cvu, /* {{{ */
                return (NULL);
 
        /* Not found: allocate. */
-       new = malloc (sizeof (*new));
+       new = calloc (1, sizeof (*new));
        if (new == NULL)
                return (NULL);
-       memset (new, 0, sizeof (*new));
        new->next = NULL;
 
        new->name = strdup (name);
@@ -581,10 +580,9 @@ static data_volume_perf_t *get_volume_perf (cfg_volume_perf_t *cvp, /* {{{ */
                return (NULL);
 
        /* Not found: allocate. */
-       new = malloc (sizeof (*new));
+       new = calloc (1, sizeof (*new));
        if (new == NULL)
                return (NULL);
-       memset (new, 0, sizeof (*new));
        new->next = NULL;
 
        new->name = strdup (name);
@@ -882,7 +880,7 @@ static cdtime_t cna_child_get_cdtime (na_elem_t *data) /* {{{ */
 } /* }}} cdtime_t cna_child_get_cdtime */
 
 
-/* 
+/*
  * Query functions
  *
  * These functions are called with appropriate data returned by the libnetapp
@@ -892,15 +890,12 @@ static cdtime_t cna_child_get_cdtime (na_elem_t *data) /* {{{ */
 static int cna_handle_wafl_data (const char *hostname, cfg_wafl_t *cfg_wafl, /* {{{ */
                na_elem_t *data, cdtime_t interval)
 {
-       cfg_wafl_t perf_data;
+       cfg_wafl_t perf_data = { 0 };
        const char *plugin_inst;
 
        na_elem_t *instances;
-       na_elem_t *counter;
        na_elem_iter_t counter_iter;
 
-       memset (&perf_data, 0, sizeof (perf_data));
-       
        perf_data.timestamp = cna_child_get_cdtime (data);
 
        instances = na_elem_child(na_elem_child (data, "instances"), "instance-data");
@@ -923,7 +918,7 @@ static int cna_handle_wafl_data (const char *hostname, cfg_wafl_t *cfg_wafl, /*
 
        /* Iterate over all counters */
        counter_iter = na_child_iterator (na_elem_child (instances, "counters"));
-       for (counter = na_iterator_next (&counter_iter);
+       for (na_elem_t *counter = na_iterator_next (&counter_iter);
                        counter != NULL;
                        counter = na_iterator_next (&counter_iter))
        {
@@ -1059,13 +1054,12 @@ static int cna_handle_disk_data (const char *hostname, /* {{{ */
 {
        cdtime_t timestamp;
        na_elem_t *instances;
-       na_elem_t *instance;
        na_elem_iter_t instance_iter;
        disk_t *worst_disk = NULL;
 
        if ((cfg_disk == NULL) || (data == NULL))
                return (EINVAL);
-       
+
        timestamp = cna_child_get_cdtime (data);
 
        instances = na_elem_child (data, "instances");
@@ -1079,17 +1073,15 @@ static int cna_handle_disk_data (const char *hostname, /* {{{ */
 
        /* Iterate over all children */
        instance_iter = na_child_iterator (instances);
-       for (instance = na_iterator_next (&instance_iter);
+       for (na_elem_t *instance = na_iterator_next (&instance_iter);
                        instance != NULL;
                        instance = na_iterator_next(&instance_iter))
        {
                disk_t *old_data;
-               disk_t  new_data;
+               disk_t  new_data = { 0 };
 
                na_elem_iter_t counter_iterator;
-               na_elem_t *counter;
 
-               memset (&new_data, 0, sizeof (new_data));
                new_data.timestamp = timestamp;
                new_data.disk_busy_percent = NAN;
 
@@ -1099,7 +1091,7 @@ static int cna_handle_disk_data (const char *hostname, /* {{{ */
 
                /* Look for the "disk_busy" and "base_for_disk_busy" counters */
                counter_iterator = na_child_iterator(na_elem_child(instance, "counters"));
-               for (counter = na_iterator_next(&counter_iterator);
+               for (na_elem_t *counter = na_iterator_next(&counter_iterator);
                                counter != NULL;
                                counter = na_iterator_next(&counter_iterator))
                {
@@ -1256,8 +1248,7 @@ static int cna_handle_volume_perf_data (const char *hostname, /* {{{ */
        cdtime_t timestamp;
        na_elem_t *elem_instances;
        na_elem_iter_t iter_instances;
-       na_elem_t *elem_instance;
-       
+
        timestamp = cna_child_get_cdtime (data);
 
        elem_instances = na_elem_child(data, "instances");
@@ -1270,20 +1261,18 @@ static int cna_handle_volume_perf_data (const char *hostname, /* {{{ */
        }
 
        iter_instances = na_child_iterator (elem_instances);
-       for (elem_instance = na_iterator_next(&iter_instances);
+       for (na_elem_t *elem_instance = na_iterator_next(&iter_instances);
                        elem_instance != NULL;
                        elem_instance = na_iterator_next(&iter_instances))
        {
                const char *name;
 
-               data_volume_perf_t perf_data;
+               data_volume_perf_t perf_data = { 0 };
                data_volume_perf_t *v;
 
                na_elem_t *elem_counters;
                na_elem_iter_t iter_counters;
-               na_elem_t *elem_counter;
 
-               memset (&perf_data, 0, sizeof (perf_data));
                perf_data.timestamp = timestamp;
 
                name = na_child_get_string (elem_instance, "name");
@@ -1300,7 +1289,7 @@ static int cna_handle_volume_perf_data (const char *hostname, /* {{{ */
                        continue;
 
                iter_counters = na_child_iterator (elem_counters);
-               for (elem_counter = na_iterator_next(&iter_counters);
+               for (na_elem_t *elem_counter = na_iterator_next(&iter_counters);
                                elem_counter != NULL;
                                elem_counter = na_iterator_next(&iter_counters))
                {
@@ -1425,9 +1414,7 @@ static int cna_query_volume_perf (host_config_t *host) /* {{{ */
 static int cna_submit_volume_usage_data (const char *hostname, /* {{{ */
                cfg_volume_usage_t *cfg_volume, int interval)
 {
-       data_volume_usage_t *v;
-
-       for (v = cfg_volume->volumes; v != NULL; v = v->next)
+       for (data_volume_usage_t *v = cfg_volume->volumes; v != NULL; v = v->next)
        {
                char plugin_instance[DATA_MAX_NAME_LEN];
 
@@ -1522,9 +1509,8 @@ static int cna_submit_volume_usage_data (const char *hostname, /* {{{ */
 static int cna_change_volume_status (const char *hostname, /* {{{ */
                data_volume_usage_t *v)
 {
-       notification_t n;
+       notification_t n = { 0 };
 
-       memset (&n, 0, sizeof (n));
        n.time = cdtime ();
        sstrncpy (n.host, hostname, sizeof (n.host));
        sstrncpy (n.plugin, "netapp", sizeof (n.plugin));
@@ -1549,7 +1535,7 @@ static void cna_handle_volume_snap_usage(const host_config_t *host, /* {{{ */
                data_volume_usage_t *v)
 {
        uint64_t snap_used = 0, value;
-       na_elem_t *data, *elem_snap, *elem_snapshots;
+       na_elem_t *data, *elem_snapshots;
        na_elem_iter_t iter_snap;
 
        data = na_server_invoke_elem(host->srv, v->snap_query);
@@ -1581,7 +1567,7 @@ static void cna_handle_volume_snap_usage(const host_config_t *host, /* {{{ */
        }
 
        iter_snap = na_child_iterator (elem_snapshots);
-       for (elem_snap = na_iterator_next (&iter_snap);
+       for (na_elem_t *elem_snap = na_iterator_next (&iter_snap);
                        elem_snap != NULL;
                        elem_snap = na_iterator_next (&iter_snap))
        {
@@ -1696,7 +1682,6 @@ static void cna_handle_volume_sis_saved (const host_config_t *host, /* {{{ */
 static int cna_handle_volume_usage_data (const host_config_t *host, /* {{{ */
                cfg_volume_usage_t *cfg_volume, na_elem_t *data)
 {
-       na_elem_t *elem_volume;
        na_elem_t *elem_volumes;
        na_elem_iter_t iter_volume;
 
@@ -1710,7 +1695,7 @@ static int cna_handle_volume_usage_data (const host_config_t *host, /* {{{ */
        }
 
        iter_volume = na_child_iterator (elem_volumes);
-       for (elem_volume = na_iterator_next (&iter_volume);
+       for (na_elem_t *elem_volume = na_iterator_next (&iter_volume);
                        elem_volume != NULL;
                        elem_volume = na_iterator_next (&iter_volume))
        {
@@ -1736,7 +1721,7 @@ static int cna_handle_volume_usage_data (const host_config_t *host, /* {{{ */
 
                if ((v->flags & CFG_VOLUME_USAGE_SNAP) != 0)
                        cna_handle_volume_snap_usage(host, v);
-               
+
                if ((v->flags & CFG_VOLUME_USAGE_DF) == 0)
                        continue;
 
@@ -1834,7 +1819,6 @@ static int cna_query_volume_usage (host_config_t *host) /* {{{ */
 static int cna_handle_quota_data (const host_config_t *host, /* {{{ */
                cfg_quota_t *cfg_quota, na_elem_t *data)
 {
-       na_elem_t *elem_quota;
        na_elem_t *elem_quotas;
        na_elem_iter_t iter_quota;
 
@@ -1848,7 +1832,7 @@ static int cna_handle_quota_data (const host_config_t *host, /* {{{ */
        }
 
        iter_quota = na_child_iterator (elem_quotas);
-       for (elem_quota = na_iterator_next (&iter_quota);
+       for (na_elem_t *elem_quota = na_iterator_next (&iter_quota);
                        elem_quota != NULL;
                        elem_quota = na_iterator_next (&iter_quota))
        {
@@ -1960,7 +1944,6 @@ static int cna_query_quota (host_config_t *host) /* {{{ */
 static int cna_handle_snapvault_data (const char *hostname, /* {{{ */
                cfg_snapvault_t *cfg_snapvault, na_elem_t *data, cdtime_t interval)
 {
-       na_elem_t *status;
        na_elem_iter_t status_iter;
 
        status = na_elem_child (data, "status-list");
@@ -1970,7 +1953,7 @@ static int cna_handle_snapvault_data (const char *hostname, /* {{{ */
        }
 
        status_iter = na_child_iterator (status);
-       for (status = na_iterator_next (&status_iter);
+       for (na_elem_t *status = na_iterator_next (&status_iter);
                        status != NULL;
                        status = na_iterator_next (&status_iter))
        {
@@ -2020,7 +2003,6 @@ static int cna_handle_snapvault_iter (host_config_t *host, /* {{{ */
        const char *tag;
 
        uint32_t records_count;
-       uint32_t i;
 
        records_count = na_child_get_uint32 (data, "records", UINT32_MAX);
        if (records_count == UINT32_MAX)
@@ -2032,7 +2014,7 @@ static int cna_handle_snapvault_iter (host_config_t *host, /* {{{ */
 
        DEBUG ("netapp plugin: Iterating %u SV records (tag = %s)", records_count, tag);
 
-       for (i = 0; i < records_count; ++i) {
+       for (uint32_t i = 0; i < records_count; ++i) {
                na_elem_t *elem;
 
                elem = na_server_invoke (host->srv,
@@ -2121,7 +2103,6 @@ static int cna_handle_system_data (const char *hostname, /* {{{ */
                cfg_system_t *cfg_system, na_elem_t *data, int interval)
 {
        na_elem_t *instances;
-       na_elem_t *counter;
        na_elem_iter_t counter_iter;
 
        derive_t disk_read = 0, disk_written = 0;
@@ -2131,7 +2112,7 @@ static int cna_handle_system_data (const char *hostname, /* {{{ */
 
        const char *instance;
        cdtime_t timestamp;
-       
+
        timestamp = cna_child_get_cdtime (data);
 
        instances = na_elem_child(na_elem_child (data, "instances"), "instance-data");
@@ -2153,7 +2134,7 @@ static int cna_handle_system_data (const char *hostname, /* {{{ */
        }
 
        counter_iter = na_child_iterator (na_elem_child (instances, "counters"));
-       for (counter = na_iterator_next (&counter_iter);
+       for (na_elem_t *counter = na_iterator_next (&counter_iter);
                        counter != NULL;
                        counter = na_iterator_next (&counter_iter))
        {
@@ -2198,7 +2179,7 @@ static int cna_handle_system_data (const char *hostname, /* {{{ */
                        && (HAS_ALL_FLAGS (counter_flags, 0x01 | 0x02)))
                submit_two_derive (hostname, instance, "disk_octets", NULL,
                                disk_read, disk_written, timestamp, interval);
-                               
+
        if ((cfg_system->flags & CFG_SYSTEM_NET)
                        && (HAS_ALL_FLAGS (counter_flags, 0x04 | 0x08)))
                submit_two_derive (hostname, instance, "if_octets", NULL,
@@ -2398,17 +2379,15 @@ static int cna_config_volume_performance (host_config_t *host, /* {{{ */
                const oconfig_item_t *ci)
 {
        cfg_volume_perf_t *cfg_volume_perf;
-       int i;
 
        if ((host == NULL) || (ci == NULL))
                return (EINVAL);
 
        if (host->cfg_volume_perf == NULL)
        {
-               cfg_volume_perf = malloc (sizeof (*cfg_volume_perf));
+               cfg_volume_perf = calloc (1, sizeof (*cfg_volume_perf));
                if (cfg_volume_perf == NULL)
                        return (ENOMEM);
-               memset (cfg_volume_perf, 0, sizeof (*cfg_volume_perf));
 
                /* Set default flags */
                cfg_volume_perf->query = NULL;
@@ -2441,10 +2420,10 @@ static int cna_config_volume_performance (host_config_t *host, /* {{{ */
                host->cfg_volume_perf = cfg_volume_perf;
        }
        cfg_volume_perf = host->cfg_volume_perf;
-       
-       for (i = 0; i < ci->children_num; ++i) {
+
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *item = ci->children + i;
-               
+
                /* if (!item || !item->key || !*item->key) continue; */
                if (strcasecmp(item->key, "Interval") == 0)
                        cna_config_get_interval (item, &cfg_volume_perf->interval);
@@ -2526,24 +2505,22 @@ static void cna_config_volume_usage_default (cfg_volume_usage_t *cvu, /* {{{ */
 static int cna_config_quota (host_config_t *host, oconfig_item_t *ci) /* {{{ */
 {
        cfg_quota_t *cfg_quota;
-       int i;
 
        if ((host == NULL) || (ci == NULL))
                return (EINVAL);
 
        if (host->cfg_quota == NULL)
        {
-               cfg_quota = malloc (sizeof (*cfg_quota));
+               cfg_quota = calloc (1, sizeof (*cfg_quota));
                if (cfg_quota == NULL)
                        return (ENOMEM);
-               memset (cfg_quota, 0, sizeof (*cfg_quota));
                cfg_quota->query = NULL;
 
                host->cfg_quota = cfg_quota;
        }
        cfg_quota = host->cfg_quota;
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *item = ci->children + i;
 
                if (strcasecmp (item->key, "Interval") == 0)
@@ -2559,17 +2536,15 @@ static int cna_config_quota (host_config_t *host, oconfig_item_t *ci) /* {{{ */
 /* Corresponds to a <Disks /> block */
 static int cna_config_disk(host_config_t *host, oconfig_item_t *ci) { /* {{{ */
        cfg_disk_t *cfg_disk;
-       int i;
 
        if ((host == NULL) || (ci == NULL))
                return (EINVAL);
 
        if (host->cfg_disk == NULL)
        {
-               cfg_disk = malloc (sizeof (*cfg_disk));
+               cfg_disk = calloc (1, sizeof (*cfg_disk));
                if (cfg_disk == NULL)
                        return (ENOMEM);
-               memset (cfg_disk, 0, sizeof (*cfg_disk));
 
                /* Set default flags */
                cfg_disk->flags = CFG_DISK_ALL;
@@ -2579,10 +2554,10 @@ static int cna_config_disk(host_config_t *host, oconfig_item_t *ci) { /* {{{ */
                host->cfg_disk = cfg_disk;
        }
        cfg_disk = host->cfg_disk;
-       
-       for (i = 0; i < ci->children_num; ++i) {
+
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *item = ci->children + i;
-               
+
                /* if (!item || !item->key || !*item->key) continue; */
                if (strcasecmp(item->key, "Interval") == 0)
                        cna_config_get_interval (item, &cfg_disk->interval);
@@ -2605,17 +2580,15 @@ static int cna_config_disk(host_config_t *host, oconfig_item_t *ci) { /* {{{ */
 static int cna_config_wafl(host_config_t *host, oconfig_item_t *ci) /* {{{ */
 {
        cfg_wafl_t *cfg_wafl;
-       int i;
 
        if ((host == NULL) || (ci == NULL))
                return (EINVAL);
 
        if (host->cfg_wafl == NULL)
        {
-               cfg_wafl = malloc (sizeof (*cfg_wafl));
+               cfg_wafl = calloc (1, sizeof (*cfg_wafl));
                if (cfg_wafl == NULL)
                        return (ENOMEM);
-               memset (cfg_wafl, 0, sizeof (*cfg_wafl));
 
                /* Set default flags */
                cfg_wafl->flags = CFG_WAFL_ALL;
@@ -2624,9 +2597,9 @@ static int cna_config_wafl(host_config_t *host, oconfig_item_t *ci) /* {{{ */
        }
        cfg_wafl = host->cfg_wafl;
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *item = ci->children + i;
-               
+
                if (strcasecmp(item->key, "Interval") == 0)
                        cna_config_get_interval (item, &cfg_wafl->interval);
                else if (!strcasecmp(item->key, "GetNameCache"))
@@ -2674,17 +2647,15 @@ static int cna_config_volume_usage(host_config_t *host, /* {{{ */
                const oconfig_item_t *ci)
 {
        cfg_volume_usage_t *cfg_volume_usage;
-       int i;
 
        if ((host == NULL) || (ci == NULL))
                return (EINVAL);
 
        if (host->cfg_volume_usage == NULL)
        {
-               cfg_volume_usage = malloc (sizeof (*cfg_volume_usage));
+               cfg_volume_usage = calloc (1, sizeof (*cfg_volume_usage));
                if (cfg_volume_usage == NULL)
                        return (ENOMEM);
-               memset (cfg_volume_usage, 0, sizeof (*cfg_volume_usage));
 
                /* Set default flags */
                cfg_volume_usage->query = NULL;
@@ -2708,10 +2679,10 @@ static int cna_config_volume_usage(host_config_t *host, /* {{{ */
                host->cfg_volume_usage = cfg_volume_usage;
        }
        cfg_volume_usage = host->cfg_volume_usage;
-       
-       for (i = 0; i < ci->children_num; ++i) {
+
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *item = ci->children + i;
-               
+
                /* if (!item || !item->key || !*item->key) continue; */
                if (strcasecmp(item->key, "Interval") == 0)
                        cna_config_get_interval (item, &cfg_volume_usage->interval);
@@ -2736,17 +2707,15 @@ static int cna_config_snapvault (host_config_t *host, /* {{{ */
                const oconfig_item_t *ci)
 {
        cfg_snapvault_t *cfg_snapvault;
-       int i;
 
        if ((host == NULL) || (ci == NULL))
                return EINVAL;
 
        if (host->cfg_snapvault == NULL)
        {
-               cfg_snapvault = malloc (sizeof (*cfg_snapvault));
+               cfg_snapvault = calloc (1, sizeof (*cfg_snapvault));
                if (cfg_snapvault == NULL)
                        return ENOMEM;
-               memset (cfg_snapvault, 0, sizeof (*cfg_snapvault));
                cfg_snapvault->query = NULL;
 
                host->cfg_snapvault = cfg_snapvault;
@@ -2754,7 +2723,7 @@ static int cna_config_snapvault (host_config_t *host, /* {{{ */
 
        cfg_snapvault = host->cfg_snapvault;
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *item = ci->children + i;
 
                if (strcasecmp (item->key, "Interval") == 0)
@@ -2772,17 +2741,15 @@ static int cna_config_system (host_config_t *host, /* {{{ */
                oconfig_item_t *ci)
 {
        cfg_system_t *cfg_system;
-       int i;
-       
+
        if ((host == NULL) || (ci == NULL))
                return (EINVAL);
 
        if (host->cfg_system == NULL)
        {
-               cfg_system = malloc (sizeof (*cfg_system));
+               cfg_system = calloc (1, sizeof (*cfg_system));
                if (cfg_system == NULL)
                        return (ENOMEM);
-               memset (cfg_system, 0, sizeof (*cfg_system));
 
                /* Set default flags */
                cfg_system->flags = CFG_SYSTEM_ALL;
@@ -2792,7 +2759,7 @@ static int cna_config_system (host_config_t *host, /* {{{ */
        }
        cfg_system = host->cfg_system;
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *item = ci->children + i;
 
                if (strcasecmp(item->key, "Interval") == 0) {
@@ -2827,10 +2794,9 @@ static host_config_t *cna_alloc_host (void) /* {{{ */
 {
        host_config_t *host;
 
-       host = malloc(sizeof(*host));
-       if (! host)
+       host = calloc (1, sizeof (*host));
+       if (host == NULL)
                return (NULL);
-       memset (host, 0, sizeof (*host));
 
        host->name = NULL;
        host->protocol = NA_SERVER_TRANSPORT_HTTPS;
@@ -2906,8 +2872,7 @@ static int cna_read (user_data_t *ud);
 static int cna_register_host (host_config_t *host) /* {{{ */
 {
        char cb_name[256];
-       struct timespec interval;
-       user_data_t ud;
+       user_data_t ud = { 0 };
 
        if (host->vfiler)
                ssnprintf (cb_name, sizeof (cb_name), "netapp-%s-%s",
@@ -2915,15 +2880,12 @@ static int cna_register_host (host_config_t *host) /* {{{ */
        else
                ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name);
 
-       CDTIME_T_TO_TIMESPEC (host->interval, &interval);
-
-       memset (&ud, 0, sizeof (ud));
        ud.data = host;
        ud.free_func = (void (*) (void *)) free_host_config;
 
        plugin_register_complex_read (/* group = */ NULL, cb_name,
                        /* callback  = */ cna_read,
-                       /* interval  = */ (host->interval > 0) ? &interval : NULL,
+                       /* interval  = */ host->interval,
                        /* user data = */ &ud);
 
        return (0);
@@ -2935,7 +2897,6 @@ static int cna_config_host (host_config_t *host, /* {{{ */
        oconfig_item_t *item;
        _Bool is_vfiler = 0;
        int status;
-       int i;
 
        if (! strcasecmp (ci->key, "VFiler"))
                is_vfiler = 1;
@@ -2949,7 +2910,7 @@ static int cna_config_host (host_config_t *host, /* {{{ */
        if (status != 0)
                return (1);
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                item = ci->children + i;
 
                status = 0;
@@ -3088,9 +3049,8 @@ static int cna_init_host (host_config_t *host) /* {{{ */
 
 static int cna_init (void) /* {{{ */
 {
-       char err[256];
+       char err[256] = { 0 };
 
-       memset (err, 0, sizeof (err));
        if (!na_startup(err, sizeof(err))) {
                err[sizeof (err) - 1] = 0;
                ERROR("netapp plugin: Error initializing netapp API: %s", err);
@@ -3159,10 +3119,9 @@ static int cna_read (user_data_t *ud) { /* {{{ */
 } /* }}} int cna_read */
 
 static int cna_config (oconfig_item_t *ci) { /* {{{ */
-       int i;
        oconfig_item_t *item;
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                item = ci->children + i;
 
                if (strcasecmp(item->key, "Host") == 0)
index aa9760f..cfca46f 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 
 #include <asm/types.h>
-#include <sys/socket.h>
 
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
@@ -110,12 +110,10 @@ static int add_ignorelist (const char *dev, const char *type,
 {
   ir_ignorelist_t *entry;
 
-  entry = (ir_ignorelist_t *) malloc (sizeof (ir_ignorelist_t));
+  entry = calloc (1, sizeof (*entry));
   if (entry == NULL)
     return (-1);
 
-  memset (entry, '\0', sizeof (ir_ignorelist_t));
-
   if (strcasecmp (dev, "All") != 0)
   {
     entry->device = strdup (dev);
@@ -159,14 +157,12 @@ static int add_ignorelist (const char *dev, const char *type,
 static int check_ignorelist (const char *dev,
     const char *type, const char *type_instance)
 {
-  ir_ignorelist_t *i;
-
   assert ((dev != NULL) && (type != NULL));
 
   if (ir_ignorelist_head == NULL)
     return (ir_ignorelist_invert ? 0 : 1);
 
-  for (i = ir_ignorelist_head; i != NULL; i = i->next)
+  for (ir_ignorelist_t *i = ir_ignorelist_head; i != NULL; i = i->next)
   {
     /* i->device == NULL  =>  match all devices */
     if ((i->device != NULL)
@@ -247,7 +243,7 @@ static int update_iflist (struct ifinfomsg *msg, const char *dev)
   {
     char **temp;
 
-    temp = (char **) realloc (iflist, (msg->ifi_index + 1) * sizeof (char *));
+    temp = realloc (iflist, (msg->ifi_index + 1) * sizeof (char *));
     if (temp == NULL)
     {
       ERROR ("netlink plugin: update_iflist: realloc failed.");
@@ -471,7 +467,7 @@ static int qos_filter_cb (const struct nlmsghdr *nlh, void *args)
   const char *kind = NULL;
 
   /* char *type_instance; */
-  char *tc_type;
+  const char *tc_type;
   char tc_inst[DATA_MAX_NAME_LEN];
 
   _Bool stats_submitted = 0;
@@ -727,8 +723,6 @@ static int ir_read (void)
   int ret;
   unsigned int seq, portid;
 
-  size_t ifindex;
-
   static const int type_id[] = { RTM_GETQDISC, RTM_GETTCLASS, RTM_GETTFILTER };
   static const char *type_name[] = { "qdisc", "class", "filter" };
 
@@ -763,15 +757,14 @@ static int ir_read (void)
 
   /* `link_filter_cb' will update `iflist' which is used here to iterate
    * over all interfaces. */
-  for (ifindex = 1; ifindex < iflist_len; ifindex++)
+  for (size_t ifindex = 1; ifindex < iflist_len; ifindex++)
   {
     struct tcmsg *tm;
-    size_t type_index;
 
     if (iflist[ifindex] == NULL)
       continue;
 
-    for (type_index = 0; type_index < STATIC_ARRAY_SIZE (type_id); type_index++)
+    for (size_t type_index = 0; type_index < STATIC_ARRAY_SIZE (type_id); type_index++)
     {
       if (check_ignorelist (iflist[ifindex], type_name[type_index], NULL))
       {
index c6845eb..1458a0a 100644 (file)
 #define _BSD_SOURCE /* For struct ip_mreq */
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "configfile.h"
 #include "utils_fbhash.h"
-#include "utils_avltree.h"
 #include "utils_cache.h"
 #include "utils_complain.h"
 
 #include "network.h"
 
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
 #if HAVE_NETDB_H
 # include <netdb.h>
 #endif
@@ -59,7 +53,6 @@
 #endif
 
 #if HAVE_LIBGCRYPT
-# include <pthread.h>
 # if defined __APPLE__
 /* default xcode compiler throws warnings even when deprecated functionality
  * is not used. -Werror breaks the build because of erroneous warnings.
@@ -283,8 +276,8 @@ typedef struct receive_list_entry_s receive_list_entry_t;
 static int network_config_ttl = 0;
 /* Ethernet - (IPv6 + UDP) = 1500 - (40 + 8) = 1452 */
 static size_t network_config_packet_size = 1452;
-static int network_config_forward = 0;
-static int network_config_stats = 0;
+static _Bool network_config_forward = 0;
+static _Bool network_config_stats = 0;
 
 static sockent_t *sending_sockets = NULL;
 
@@ -310,6 +303,7 @@ static pthread_t dispatch_thread_id;
 static char            *send_buffer;
 static char            *send_buffer_ptr;
 static int              send_buffer_fill;
+static cdtime_t         send_buffer_last_update;
 static value_list_t     send_buffer_vl = VALUE_LIST_STATIC;
 static pthread_mutex_t  send_buffer_lock = PTHREAD_MUTEX_INITIALIZER;
 
@@ -353,7 +347,7 @@ static _Bool check_send_okay (const value_list_t *vl) /* {{{ */
   _Bool received = 0;
   int status;
 
-  if (network_config_forward != 0)
+  if (network_config_forward)
     return (1);
 
   if (vl->meta == NULL)
@@ -376,9 +370,7 @@ static _Bool check_send_okay (const value_list_t *vl) /* {{{ */
 
 static _Bool check_notify_received (const notification_t *n) /* {{{ */
 {
-  notification_meta_t *ptr;
-
-  for (ptr = n->meta; ptr != NULL; ptr = ptr->next)
+  for (notification_meta_t *ptr = n->meta; ptr != NULL; ptr = ptr->next)
     if ((strcmp ("network:received", ptr->name) == 0)
         && (ptr->type == NM_TYPE_BOOLEAN))
       return ((_Bool) ptr->nm_value.nm_boolean);
@@ -416,10 +408,10 @@ static int network_dispatch_values (value_list_t *vl, /* {{{ */
 {
   int status;
 
-  if ((vl->time <= 0)
-      || (strlen (vl->host) <= 0)
-      || (strlen (vl->plugin) <= 0)
-      || (strlen (vl->type) <= 0))
+  if ((vl->time == 0)
+      || (strlen (vl->host) == 0)
+      || (strlen (vl->plugin) == 0)
+      || (strlen (vl->type) == 0))
     return (-EINVAL);
 
   if (!check_receive_okay (vl))
@@ -613,11 +605,11 @@ static gcry_cipher_hd_t network_get_aes256_cypher (sockent_t *se, /* {{{ */
 } /* }}} int network_get_aes256_cypher */
 #endif /* HAVE_LIBGCRYPT */
 
-static int write_part_values (char **ret_buffer, int *ret_buffer_len,
+static int write_part_values (char **ret_buffer, size_t *ret_buffer_len,
                const data_set_t *ds, const value_list_t *vl)
 {
        char *packet_ptr;
-       int packet_len;
+       size_t packet_len;
        int num_values;
 
        part_header_t pkg_ph;
@@ -625,8 +617,7 @@ static int write_part_values (char **ret_buffer, int *ret_buffer_len,
        uint8_t      *pkg_values_types;
        value_t      *pkg_values;
 
-       int offset;
-       int i;
+       size_t offset;
 
        num_values = vl->values_len;
        packet_len = sizeof (part_header_t) + sizeof (uint16_t)
@@ -636,14 +627,14 @@ static int write_part_values (char **ret_buffer, int *ret_buffer_len,
        if (*ret_buffer_len < packet_len)
                return (-1);
 
-       pkg_values_types = (uint8_t *) malloc (num_values * sizeof (uint8_t));
+       pkg_values_types = malloc (num_values * sizeof (*pkg_values_types));
        if (pkg_values_types == NULL)
        {
                ERROR ("network plugin: write_part_values: malloc failed.");
                return (-1);
        }
 
-       pkg_values = (value_t *) malloc (num_values * sizeof (value_t));
+       pkg_values = malloc (num_values * sizeof (*pkg_values));
        if (pkg_values == NULL)
        {
                free (pkg_values_types);
@@ -656,7 +647,7 @@ static int write_part_values (char **ret_buffer, int *ret_buffer_len,
 
        pkg_num_values = htons ((uint16_t) vl->values_len);
 
-       for (i = 0; i < num_values; i++)
+       for (int i = 0; i < num_values; i++)
        {
                pkg_values_types[i] = (uint8_t) ds->ds[i].type;
                switch (ds->ds[i].type)
@@ -714,16 +705,16 @@ static int write_part_values (char **ret_buffer, int *ret_buffer_len,
        return (0);
 } /* int write_part_values */
 
-static int write_part_number (char **ret_buffer, int *ret_buffer_len,
+static int write_part_number (char **ret_buffer, size_t *ret_buffer_len,
                int type, uint64_t value)
 {
        char *packet_ptr;
-       int packet_len;
+       size_t packet_len;
 
        part_header_t pkg_head;
        uint64_t pkg_value;
 
-       int offset;
+       size_t offset;
 
        packet_len = sizeof (pkg_head) + sizeof (pkg_value);
 
@@ -749,16 +740,16 @@ static int write_part_number (char **ret_buffer, int *ret_buffer_len,
        return (0);
 } /* int write_part_number */
 
-static int write_part_string (char **ret_buffer, int *ret_buffer_len,
-               int type, const char *str, int str_len)
+static int write_part_string (char **ret_buffer, size_t *ret_buffer_len,
+               int type, const char *str, size_t str_len)
 {
        char *buffer;
-       int buffer_len;
+       size_t buffer_len;
 
        uint16_t pkg_type;
        uint16_t pkg_length;
 
-       int offset;
+       size_t offset;
 
        buffer_len = 2 * sizeof (uint16_t) + str_len + 1;
        if (*ret_buffer_len < buffer_len)
@@ -787,18 +778,17 @@ static int write_part_string (char **ret_buffer, int *ret_buffer_len,
 } /* int write_part_string */
 
 static int parse_part_values (void **ret_buffer, size_t *ret_buffer_len,
-               value_t **ret_values, int *ret_num_values)
+               value_t **ret_values, size_t *ret_num_values)
 {
        char *buffer = *ret_buffer;
        size_t buffer_len = *ret_buffer_len;
 
        uint16_t tmp16;
        size_t exp_size;
-       int   i;
 
        uint16_t pkg_length;
        uint16_t pkg_type;
-       uint16_t pkg_numval;
+       size_t pkg_numval;
 
        uint8_t *pkg_types;
        value_t *pkg_values;
@@ -820,7 +810,7 @@ static int parse_part_values (void **ret_buffer, size_t *ret_buffer_len,
 
        memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
        buffer += sizeof (tmp16);
-       pkg_numval = ntohs (tmp16);
+       pkg_numval = (size_t) ntohs (tmp16);
 
        assert (pkg_type == TYPE_VALUES);
 
@@ -835,6 +825,7 @@ static int parse_part_values (void **ret_buffer, size_t *ret_buffer_len,
                                exp_size, buffer_len);
                return (-1);
        }
+       assert (pkg_numval <= ((buffer_len - 6) / 9));
 
        if (pkg_length != exp_size)
        {
@@ -844,22 +835,22 @@ static int parse_part_values (void **ret_buffer, size_t *ret_buffer_len,
                return (-1);
        }
 
-       pkg_types = (uint8_t *) malloc (pkg_numval * sizeof (uint8_t));
-       pkg_values = (value_t *) malloc (pkg_numval * sizeof (value_t));
+       pkg_types = calloc (pkg_numval, sizeof (*pkg_types));
+       pkg_values = calloc (pkg_numval, sizeof (*pkg_values));
        if ((pkg_types == NULL) || (pkg_values == NULL))
        {
                sfree (pkg_types);
                sfree (pkg_values);
-               ERROR ("network plugin: parse_part_values: malloc failed.");
+               ERROR ("network plugin: parse_part_values: calloc failed.");
                return (-1);
        }
 
-       memcpy ((void *) pkg_types, (void *) buffer, pkg_numval * sizeof (uint8_t));
-       buffer += pkg_numval * sizeof (uint8_t);
-       memcpy ((void *) pkg_values, (void *) buffer, pkg_numval * sizeof (value_t));
-       buffer += pkg_numval * sizeof (value_t);
+       memcpy (pkg_types, buffer, pkg_numval * sizeof (*pkg_types));
+       buffer += pkg_numval * sizeof (*pkg_types);
+       memcpy (pkg_values, buffer, pkg_numval * sizeof (*pkg_values));
+       buffer += pkg_numval * sizeof (*pkg_values);
 
-       for (i = 0; i < pkg_numval; i++)
+       for (size_t i = 0; i < pkg_numval; i++)
        {
                switch (pkg_types[i])
                {
@@ -951,7 +942,7 @@ static int parse_part_string (void **ret_buffer, size_t *ret_buffer_len,
        uint16_t pkg_length;
        size_t payload_size;
 
-       if (output_len <= 0)
+       if (output_len == 0)
                return (EINVAL);
 
        if (buffer_len < header_size)
@@ -1158,7 +1149,7 @@ static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
   if (memcmp (pss.hash, hash, sizeof (pss.hash)) != 0)
   {
     WARNING ("network plugin: Verifying HMAC-SHA-256 signature failed: "
-        "Hash mismatch.");
+        "Hash mismatch. Username: %s", pss.username);
   }
   else
   {
@@ -1234,7 +1225,7 @@ static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
   size_t buffer_offset;
   uint16_t username_len;
   part_encryption_aes256_t pea;
-  unsigned char hash[sizeof (pea.hash)];
+  unsigned char hash[sizeof (pea.hash)] = { 0 };
 
   gcry_cipher_hd_t cypher;
   gcry_error_t err;
@@ -1267,7 +1258,7 @@ static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
   BUFFER_READ (&username_len, sizeof (username_len));
   username_len = ntohs (username_len);
 
-  if ((username_len <= 0)
+  if ((username_len == 0)
       || (username_len > (part_size - (PART_ENCRYPTION_AES256_SIZE + 1))))
   {
     NOTICE ("network plugin: parse_part_encr_aes256: "
@@ -1293,6 +1284,7 @@ static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
       pea.username);
   if (cypher == NULL)
   {
+    ERROR ("network plugin: Failed to get cypher. Username: %s", pea.username);
     sfree (pea.username);
     return (-1);
   }
@@ -1308,8 +1300,8 @@ static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
   if (err != 0)
   {
     sfree (pea.username);
-    ERROR ("network plugin: gcry_cipher_decrypt returned: %s",
-        gcry_strerror (err));
+    ERROR ("network plugin: gcry_cipher_decrypt returned: %s. Username: %s",
+        gcry_strerror (err), pea.username);
     return (-1);
   }
 
@@ -1321,13 +1313,12 @@ static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
   assert (buffer_offset == (part_size - payload_len));
 
   /* Check hash sum */
-  memset (hash, 0, sizeof (hash));
   gcry_md_hash_buffer (GCRY_MD_SHA1, hash,
       buffer + buffer_offset, payload_len);
   if (memcmp (hash, pea.hash, sizeof (hash)) != 0)
   {
+    ERROR ("network plugin: Checksum mismatch. Username: %s", pea.username);
     sfree (pea.username);
-    ERROR ("network plugin: Decryption failed: Checksum mismatch.");
     return (-1);
   }
 
@@ -1386,7 +1377,7 @@ static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
     warning_has_been_printed = 1;
   }
 
-  *ret_buffer += ph_length;
+  *ret_buffer = (void *) (((char *) *ret_buffer) + ph_length);
   *ret_buffer_size -= ph_length;
 
   return (0);
@@ -1402,17 +1393,16 @@ static int parse_packet (sockent_t *se, /* {{{ */
        int status;
 
        value_list_t vl = VALUE_LIST_INIT;
-       notification_t n;
+       notification_t n = { 0 };
 
 #if HAVE_LIBGCRYPT
        int packet_was_signed = (flags & PP_SIGNED);
-        int packet_was_encrypted = (flags & PP_ENCRYPTED);
+       int packet_was_encrypted = (flags & PP_ENCRYPTED);
        int printed_ignore_warning = 0;
 #endif /* HAVE_LIBGCRYPT */
 
 
        memset (&vl, '\0', sizeof (vl));
-       memset (&n, '\0', sizeof (n));
        status = 0;
 
        while ((status == 0) && (0 < buffer_size)
@@ -1425,7 +1415,7 @@ static int parse_packet (sockent_t *se, /* {{{ */
                                (void *) buffer,
                                sizeof (pkg_type));
                memcpy ((void *) &pkg_length,
-                               (void *) (buffer + sizeof (pkg_type)),
+                               (void *) (((char *) buffer) + sizeof (pkg_type)),
                                sizeof (pkg_length));
 
                pkg_length = ntohs (pkg_length);
@@ -1600,13 +1590,13 @@ static int parse_packet (sockent_t *se, /* {{{ */
                                                "unknown severity %i.",
                                                n.severity);
                        }
-                       else if (n.time <= 0)
+                       else if (n.time == 0)
                        {
                                INFO ("network plugin: "
                                                "Ignoring notification with "
                                                "time == 0.");
                        }
-                       else if (strlen (n.message) <= 0)
+                       else if (strlen (n.message) == 0)
                        {
                                INFO ("network plugin: "
                                                "Ignoring notification with "
@@ -1659,9 +1649,7 @@ static void free_sockent_client (struct sockent_client *sec) /* {{{ */
 
 static void free_sockent_server (struct sockent_server *ses) /* {{{ */
 {
-  size_t i;
-
-  for (i = 0; i < ses->fd_num; i++)
+  for (size_t i = 0; i < ses->fd_num; i++)
   {
     if (ses->fd[i] >= 0)
     {
@@ -1786,18 +1774,16 @@ static int network_set_interface (const sockent_t *se, const struct addrinfo *ai
                         * index is preferred here, because of its similarity
                         * to the way IPv6 handles this. Unfortunately, it
                         * appears not to be portable. */
-                       struct ip_mreqn mreq;
-
-                       memset (&mreq, 0, sizeof (mreq));
-                       mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
-                       mreq.imr_address.s_addr = ntohl (INADDR_ANY);
-                       mreq.imr_ifindex = se->interface;
+                       struct ip_mreqn mreq = {
+                               .imr_multiaddr.s_addr = addr->sin_addr.s_addr,
+                               .imr_address.s_addr = ntohl (INADDR_ANY),
+                               .imr_ifindex = se->interface
+                       };
 #else
-                       struct ip_mreq mreq;
-
-                       memset (&mreq, 0, sizeof (mreq));
-                       mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
-                       mreq.imr_interface.s_addr = ntohl (INADDR_ANY);
+                       struct ip_mreq mreq = {
+                               .imr_multiaddr.s_addr = addr->sin_addr.s_addr,
+                               .imr_interface.s_addr = ntohl (INADDR_ANY)
+                       };
 #endif
 
                        if (setsockopt (se->data.client.fd, IPPROTO_IP, IP_MULTICAST_IF,
@@ -2032,10 +2018,9 @@ static sockent_t *sockent_create (int type) /* {{{ */
        if ((type != SOCKENT_TYPE_CLIENT) && (type != SOCKENT_TYPE_SERVER))
                return (NULL);
 
-       se = malloc (sizeof (*se));
+       se = calloc (1, sizeof (*se));
        if (se == NULL)
                return (NULL);
-       memset (se, 0, sizeof (*se));
 
        se->type = type;
        se->node = NULL;
@@ -2161,8 +2146,7 @@ static int sockent_client_connect (sockent_t *se) /* {{{ */
        static c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
 
        struct sockent_client *client;
-       struct addrinfo  ai_hints;
-       struct addrinfo *ai_list = NULL, *ai_ptr;
+       struct addrinfo *ai_list;
        int status;
        _Bool reconnect = 0;
        cdtime_t now;
@@ -2182,13 +2166,12 @@ static int sockent_client_connect (sockent_t *se) /* {{{ */
        if (client->fd >= 0 && !reconnect) /* already connected and not stale*/
                return (0);
 
-       memset (&ai_hints, 0, sizeof (ai_hints));
-#ifdef AI_ADDRCONFIG
-       ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
-       ai_hints.ai_family   = AF_UNSPEC;
-       ai_hints.ai_socktype = SOCK_DGRAM;
-       ai_hints.ai_protocol = IPPROTO_UDP;
+       struct addrinfo ai_hints = {
+               .ai_family   = AF_UNSPEC,
+               .ai_flags    = AI_ADDRCONFIG,
+               .ai_protocol = IPPROTO_UDP,
+               .ai_socktype = SOCK_DGRAM
+       };
 
        status = getaddrinfo (se->node,
                        (se->service != NULL) ? se->service : NET_DEFAULT_PORT,
@@ -2209,7 +2192,7 @@ static int sockent_client_connect (sockent_t *se) /* {{{ */
                                se->node);
        }
 
-       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
        {
                if (client->fd >= 0) /* when we reconnect */
                        sockent_client_disconnect(se);
@@ -2226,16 +2209,15 @@ static int sockent_client_connect (sockent_t *se) /* {{{ */
                        continue;
                }
 
-               client->addr = malloc (sizeof (*client->addr));
+               client->addr = calloc (1, sizeof (*client->addr));
                if (client->addr == NULL)
                {
-                       ERROR ("network plugin: malloc failed.");
+                       ERROR ("network plugin: calloc failed.");
                        close (client->fd);
                        client->fd = -1;
                        continue;
                }
 
-               memset (client->addr, 0, sizeof (*client->addr));
                assert (sizeof (*client->addr) >= ai_ptr->ai_addrlen);
                memcpy (client->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
                client->addrlen = ai_ptr->ai_addrlen;
@@ -2260,8 +2242,7 @@ static int sockent_client_connect (sockent_t *se) /* {{{ */
 /* Open the file descriptors for a initialized sockent structure. */
 static int sockent_server_listen (sockent_t *se) /* {{{ */
 {
-       struct addrinfo  ai_hints;
-       struct addrinfo *ai_list, *ai_ptr;
+       struct addrinfo *ai_list;
        int              status;
 
         const char *node;
@@ -2282,17 +2263,12 @@ static int sockent_server_listen (sockent_t *se) /* {{{ */
         DEBUG ("network plugin: sockent_server_listen: node = %s; service = %s;",
             node, service);
 
-       memset (&ai_hints, 0, sizeof (ai_hints));
-       ai_hints.ai_flags  = 0;
-#ifdef AI_PASSIVE
-       ai_hints.ai_flags |= AI_PASSIVE;
-#endif
-#ifdef AI_ADDRCONFIG
-       ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
-       ai_hints.ai_family   = AF_UNSPEC;
-       ai_hints.ai_socktype = SOCK_DGRAM;
-       ai_hints.ai_protocol = IPPROTO_UDP;
+       struct addrinfo ai_hints = {
+               .ai_family   = AF_UNSPEC,
+               .ai_flags    = AI_ADDRCONFIG | AI_PASSIVE,
+               .ai_protocol = IPPROTO_UDP,
+               .ai_socktype = SOCK_DGRAM
+       };
 
        status = getaddrinfo (node, service, &ai_hints, &ai_list);
        if (status != 0)
@@ -2304,7 +2280,7 @@ static int sockent_server_listen (sockent_t *se) /* {{{ */
                return (-1);
        }
 
-       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
        {
                int *tmp;
 
@@ -2343,7 +2319,7 @@ static int sockent_server_listen (sockent_t *se) /* {{{ */
 
        freeaddrinfo (ai_list);
 
-       if (se->data.server.fd_num <= 0)
+       if (se->data.server.fd_num == 0)
                return (-1);
        return (0);
 } /* }}} int sockent_server_listen */
@@ -2359,7 +2335,6 @@ static int sockent_add (sockent_t *se) /* {{{ */
        if (se->type == SOCKENT_TYPE_SERVER)
        {
                struct pollfd *tmp;
-               size_t i;
 
                tmp = realloc (listen_sockets_pollfd,
                                sizeof (*tmp) * (listen_sockets_num
@@ -2372,7 +2347,7 @@ static int sockent_add (sockent_t *se) /* {{{ */
                listen_sockets_pollfd = tmp;
                tmp = listen_sockets_pollfd + listen_sockets_num;
 
-               for (i = 0; i < se->data.server.fd_num; i++)
+               for (size_t i = 0; i < se->data.server.fd_num; i++)
                {
                        memset (tmp + i, 0, sizeof (*tmp));
                        tmp[i].fd = se->data.server.fd[i];
@@ -2471,7 +2446,6 @@ static int network_receive (void) /* {{{ */
        char buffer[network_config_packet_size];
        int  buffer_len;
 
-       int i;
        int status = 0;
 
        receive_list_entry_t *private_list_head;
@@ -2497,7 +2471,7 @@ static int network_receive (void) /* {{{ */
                        break;
                }
 
-               for (i = 0; (i < listen_sockets_num) && (status > 0); i++)
+               for (size_t i = 0; (i < listen_sockets_num) && (status > 0); i++)
                {
                        receive_list_entry_t *ent;
 
@@ -2525,14 +2499,14 @@ static int network_receive (void) /* {{{ */
                         * these entries in the dispatch thread but put them in
                         * another list, so we don't have to allocate more and
                         * more of these structures. */
-                       ent = malloc (sizeof (receive_list_entry_t));
+                       ent = calloc (1, sizeof (*ent));
                        if (ent == NULL)
                        {
-                               ERROR ("network plugin: malloc failed.");
+                               ERROR ("network plugin: calloc failed.");
                                status = ENOMEM;
                                break;
                        }
-                       memset (ent, 0, sizeof (receive_list_entry_t));
+
                        ent->data = malloc (network_config_packet_size);
                        if (ent->data == NULL)
                        {
@@ -2612,11 +2586,12 @@ static void network_init_buffer (void)
        memset (send_buffer, 0, network_config_packet_size);
        send_buffer_ptr = send_buffer;
        send_buffer_fill = 0;
+       send_buffer_last_update = 0;
 
        memset (&send_buffer_vl, 0, sizeof (send_buffer_vl));
 } /* int network_init_buffer */
 
-static void networt_send_buffer_plain (sockent_t *se, /* {{{ */
+static void network_send_buffer_plain (sockent_t *se, /* {{{ */
                const char *buffer, size_t buffer_size)
 {
        int status;
@@ -2646,7 +2621,7 @@ static void networt_send_buffer_plain (sockent_t *se, /* {{{ */
 
                break;
        } /* while (42) */
-} /* }}} void networt_send_buffer_plain */
+} /* }}} void network_send_buffer_plain */
 
 #if HAVE_LIBGCRYPT
 #define BUFFER_ADD(p,s) do { \
@@ -2654,10 +2629,9 @@ static void networt_send_buffer_plain (sockent_t *se, /* {{{ */
   buffer_offset += (s); \
 } while (0)
 
-static void networt_send_buffer_signed (sockent_t *se, /* {{{ */
+static void network_send_buffer_signed (sockent_t *se, /* {{{ */
                const char *in_buffer, size_t in_buffer_size)
 {
-  part_signature_sha256_t ps;
   char buffer[BUFF_SIG_SIZE + in_buffer_size];
   size_t buffer_offset;
   size_t username_len;
@@ -2699,9 +2673,10 @@ static void networt_send_buffer_signed (sockent_t *se, /* {{{ */
       in_buffer, in_buffer_size);
 
   /* Initialize the `ps' structure. */
-  memset (&ps, 0, sizeof (ps));
-  ps.head.type = htons (TYPE_SIGN_SHA256);
-  ps.head.length = htons (PART_SIGNATURE_SHA256_SIZE + username_len);
+  part_signature_sha256_t ps = {
+    .head.type = htons (TYPE_SIGN_SHA256),
+    .head.length = htons (PART_SIGNATURE_SHA256_SIZE + username_len)
+  };
 
   /* Calculate the hash value. */
   gcry_md_write (hd, buffer + PART_SIGNATURE_SHA256_SIZE,
@@ -2728,13 +2703,12 @@ static void networt_send_buffer_signed (sockent_t *se, /* {{{ */
   hd = NULL;
 
   buffer_offset = PART_SIGNATURE_SHA256_SIZE + username_len + in_buffer_size;
-  networt_send_buffer_plain (se, buffer, buffer_offset);
-} /* }}} void networt_send_buffer_signed */
+  network_send_buffer_plain (se, buffer, buffer_offset);
+} /* }}} void network_send_buffer_signed */
 
-static void networt_send_buffer_encrypted (sockent_t *se, /* {{{ */
+static void network_send_buffer_encrypted (sockent_t *se, /* {{{ */
                const char *in_buffer, size_t in_buffer_size)
 {
-  part_encryption_aes256_t pea;
   char buffer[BUFF_SIG_SIZE + in_buffer_size];
   size_t buffer_size;
   size_t buffer_offset;
@@ -2744,10 +2718,10 @@ static void networt_send_buffer_encrypted (sockent_t *se, /* {{{ */
   gcry_cipher_hd_t cypher;
 
   /* Initialize the header fields */
-  memset (&pea, 0, sizeof (pea));
-  pea.head.type = htons (TYPE_ENCR_AES256);
-
-  pea.username = se->data.client.username;
+  part_encryption_aes256_t pea = {
+    .head.type = htons (TYPE_ENCR_AES256),
+    .username = se->data.client.username
+  };
 
   username_len = strlen (pea.username);
   if ((PART_ENCRYPTION_AES256_SIZE + username_len) > BUFF_SIG_SIZE)
@@ -2761,7 +2735,7 @@ static void networt_send_buffer_encrypted (sockent_t *se, /* {{{ */
     - sizeof (pea.hash);
 
   assert (buffer_size <= sizeof (buffer));
-  DEBUG ("network plugin: networt_send_buffer_encrypted: "
+  DEBUG ("network plugin: network_send_buffer_encrypted: "
       "buffer_size = %zu;", buffer_size);
 
   pea.head.length = htons ((uint16_t) (PART_ENCRYPTION_AES256_SIZE
@@ -2808,31 +2782,29 @@ static void networt_send_buffer_encrypted (sockent_t *se, /* {{{ */
   }
 
   /* Send it out without further modifications */
-  networt_send_buffer_plain (se, buffer, buffer_size);
-} /* }}} void networt_send_buffer_encrypted */
+  network_send_buffer_plain (se, buffer, buffer_size);
+} /* }}} void network_send_buffer_encrypted */
 #undef BUFFER_ADD
 #endif /* HAVE_LIBGCRYPT */
 
 static void network_send_buffer (char *buffer, size_t buffer_len) /* {{{ */
 {
-  sockent_t *se;
-
   DEBUG ("network plugin: network_send_buffer: buffer_len = %zu", buffer_len);
 
-  for (se = sending_sockets; se != NULL; se = se->next)
+  for (sockent_t *se = sending_sockets; se != NULL; se = se->next)
   {
 #if HAVE_LIBGCRYPT
     if (se->data.client.security_level == SECURITY_LEVEL_ENCRYPT)
-      networt_send_buffer_encrypted (se, buffer, buffer_len);
+      network_send_buffer_encrypted (se, buffer, buffer_len);
     else if (se->data.client.security_level == SECURITY_LEVEL_SIGN)
-      networt_send_buffer_signed (se, buffer, buffer_len);
+      network_send_buffer_signed (se, buffer, buffer_len);
     else /* if (se->data.client.security_level == SECURITY_LEVEL_NONE) */
 #endif /* HAVE_LIBGCRYPT */
-      networt_send_buffer_plain (se, buffer, buffer_len);
+      network_send_buffer_plain (se, buffer, buffer_len);
   } /* for (sending_sockets) */
 } /* }}} void network_send_buffer */
 
-static int add_to_buffer (char *buffer, int buffer_size, /* {{{ */
+static int add_to_buffer (char *buffer, size_t buffer_size, /* {{{ */
                value_list_t *vl_def,
                const data_set_t *ds, const value_list_t *vl)
 {
@@ -2956,6 +2928,7 @@ static int network_write (const data_set_t *ds, const value_list_t *vl,
                /* status == bytes added to the buffer */
                send_buffer_fill += status;
                send_buffer_ptr  += status;
+               send_buffer_last_update = cdtime();
 
                stats_values_sent++;
        }
@@ -2992,58 +2965,13 @@ static int network_write (const data_set_t *ds, const value_list_t *vl,
        return ((status < 0) ? -1 : 0);
 } /* int network_write */
 
-static int network_config_set_boolean (const oconfig_item_t *ci, /* {{{ */
-    int *retval)
-{
-  if ((ci->values_num != 1)
-      || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN)
-        && (ci->values[0].type != OCONFIG_TYPE_STRING)))
-  {
-    ERROR ("network plugin: The `%s' config option needs "
-        "exactly one boolean argument.", ci->key);
-    return (-1);
-  }
-
-  if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
-  {
-    if (ci->values[0].value.boolean)
-      *retval = 1;
-    else
-      *retval = 0;
-  }
-  else
-  {
-    char *str = ci->values[0].value.string;
-
-    if (IS_TRUE (str))
-      *retval = 1;
-    else if (IS_FALSE (str))
-      *retval = 0;
-    else
-    {
-      ERROR ("network plugin: Cannot parse string value `%s' of the `%s' "
-          "option as boolean value.",
-          str, ci->key);
-      return (-1);
-    }
-  }
-
-  return (0);
-} /* }}} int network_config_set_boolean */
-
 static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */
 {
-  int tmp;
-  if ((ci->values_num != 1)
-      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
-  {
-    WARNING ("network plugin: The `TimeToLive' config option needs exactly "
-        "one numeric argument.");
-    return (-1);
-  }
+  int tmp = 0;
 
-  tmp = (int) ci->values[0].value.number;
-  if ((tmp > 0) && (tmp <= 255))
+  if (cf_util_get_int (ci, &tmp) != 0)
+    return (-1);
+  else if ((tmp > 0) && (tmp <= 255))
     network_config_ttl = tmp;
   else {
     WARNING ("network plugin: The `TimeToLive' must be between 1 and 255.");
@@ -3056,63 +2984,30 @@ static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */
 static int network_config_set_interface (const oconfig_item_t *ci, /* {{{ */
     int *interface)
 {
-  if ((ci->values_num != 1)
-      || (ci->values[0].type != OCONFIG_TYPE_STRING))
-  {
-    WARNING ("network plugin: The `Interface' config option needs exactly "
-        "one string argument.");
-    return (-1);
-  }
+  char if_name[256];
 
-  if (interface == NULL)
+  if (cf_util_get_string_buffer (ci, if_name, sizeof (if_name)) != 0)
     return (-1);
 
-  *interface = if_nametoindex (ci->values[0].value.string);
-
+  *interface = if_nametoindex (if_name);
   return (0);
 } /* }}} int network_config_set_interface */
 
 static int network_config_set_buffer_size (const oconfig_item_t *ci) /* {{{ */
 {
-  int tmp;
-  if ((ci->values_num != 1)
-      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
-  {
-    WARNING ("network plugin: The `MaxPacketSize' config option needs exactly "
-        "one numeric argument.");
-    return (-1);
-  }
+  int tmp = 0;
 
-  tmp = (int) ci->values[0].value.number;
-  if ((tmp >= 1024) && (tmp <= 65535))
+  if (cf_util_get_int (ci, &tmp) != 0)
+    return (-1);
+  else if ((tmp >= 1024) && (tmp <= 65535))
     network_config_packet_size = tmp;
-
-  return (0);
-} /* }}} int network_config_set_buffer_size */
-
-#if HAVE_LIBGCRYPT
-static int network_config_set_string (const oconfig_item_t *ci, /* {{{ */
-    char **ret_string)
-{
-  char *tmp;
-  if ((ci->values_num != 1)
-      || (ci->values[0].type != OCONFIG_TYPE_STRING))
-  {
-    WARNING ("network plugin: The `%s' config option needs exactly "
-        "one string argument.", ci->key);
+  else {
+    WARNING ("network plugin: The `MaxPacketSize' must be between 1024 and 65535.");
     return (-1);
   }
 
-  tmp = strdup (ci->values[0].value.string);
-  if (tmp == NULL)
-    return (-1);
-
-  sfree (*ret_string);
-  *ret_string = tmp;
-
   return (0);
-} /* }}} int network_config_set_string */
-#endif /* HAVE_LIBGCRYPT */
+} /* }}} int network_config_set_buffer_size */
 
 #if HAVE_LIBGCRYPT
 static int network_config_set_security_level (oconfig_item_t *ci, /* {{{ */
@@ -3148,7 +3043,6 @@ static int network_config_add_listen (const oconfig_item_t *ci) /* {{{ */
 {
   sockent_t *se;
   int status;
-  int i;
 
   if ((ci->values_num < 1) || (ci->values_num > 2)
       || (ci->values[0].type != OCONFIG_TYPE_STRING)
@@ -3170,21 +3064,20 @@ static int network_config_add_listen (const oconfig_item_t *ci) /* {{{ */
   if (ci->values_num >= 2)
     se->service = strdup (ci->values[1].value.string);
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
 #if HAVE_LIBGCRYPT
     if (strcasecmp ("AuthFile", child->key) == 0)
-      network_config_set_string (child, &se->data.server.auth_file);
+      cf_util_get_string (child, &se->data.server.auth_file);
     else if (strcasecmp ("SecurityLevel", child->key) == 0)
       network_config_set_security_level (child,
           &se->data.server.security_level);
     else
 #endif /* HAVE_LIBGCRYPT */
     if (strcasecmp ("Interface", child->key) == 0)
-      network_config_set_interface (child,
-          &se->interface);
+      network_config_set_interface (child, &se->interface);
     else
     {
       WARNING ("network plugin: Option `%s' is not allowed here.",
@@ -3215,7 +3108,7 @@ static int network_config_add_listen (const oconfig_item_t *ci) /* {{{ */
   status = sockent_server_listen (se);
   if (status != 0)
   {
-    ERROR ("network plugin: network_config_add_server: sockent_server_listen failed.");
+    ERROR ("network plugin: network_config_add_listen: sockent_server_listen failed.");
     sockent_destroy (se);
     return (-1);
   }
@@ -3235,7 +3128,6 @@ static int network_config_add_server (const oconfig_item_t *ci) /* {{{ */
 {
   sockent_t *se;
   int status;
-  int i;
 
   if ((ci->values_num < 1) || (ci->values_num > 2)
       || (ci->values[0].type != OCONFIG_TYPE_STRING)
@@ -3257,25 +3149,24 @@ static int network_config_add_server (const oconfig_item_t *ci) /* {{{ */
   if (ci->values_num >= 2)
     se->service = strdup (ci->values[1].value.string);
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
 #if HAVE_LIBGCRYPT
     if (strcasecmp ("Username", child->key) == 0)
-      network_config_set_string (child, &se->data.client.username);
+      cf_util_get_string (child, &se->data.client.username);
     else if (strcasecmp ("Password", child->key) == 0)
-      network_config_set_string (child, &se->data.client.password);
+      cf_util_get_string (child, &se->data.client.password);
     else if (strcasecmp ("SecurityLevel", child->key) == 0)
       network_config_set_security_level (child,
           &se->data.client.security_level);
     else
 #endif /* HAVE_LIBGCRYPT */
     if (strcasecmp ("Interface", child->key) == 0)
-      network_config_set_interface (child,
-          &se->interface);
-               else if (strcasecmp ("ResolveInterval", child->key) == 0)
-                       cf_util_get_cdtime(child, &se->data.client.resolve_interval);
+      network_config_set_interface (child, &se->interface);
+    else if (strcasecmp ("ResolveInterval", child->key) == 0)
+      cf_util_get_cdtime(child, &se->data.client.resolve_interval);
     else
     {
       WARNING ("network plugin: Option `%s' is not allowed here.",
@@ -3305,7 +3196,7 @@ static int network_config_add_server (const oconfig_item_t *ci) /* {{{ */
   }
 
   /* No call to sockent_client_connect() here -- it is called from
-   * networt_send_buffer_plain(). */
+   * network_send_buffer_plain(). */
 
   status = sockent_add (se);
   if (status != 0)
@@ -3320,17 +3211,15 @@ static int network_config_add_server (const oconfig_item_t *ci) /* {{{ */
 
 static int network_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
   /* The options need to be applied first */
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
     if (strcasecmp ("TimeToLive", child->key) == 0)
       network_config_set_ttl (child);
   }
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -3344,9 +3233,9 @@ static int network_config (oconfig_item_t *ci) /* {{{ */
     else if (strcasecmp ("MaxPacketSize", child->key) == 0)
       network_config_set_buffer_size (child);
     else if (strcasecmp ("Forward", child->key) == 0)
-      network_config_set_boolean (child, &network_config_forward);
+      cf_util_get_boolean (child, &network_config_forward);
     else if (strcasecmp ("ReportStats", child->key) == 0)
-      network_config_set_boolean (child, &network_config_stats);
+      cf_util_get_boolean (child, &network_config_stats);
     else
     {
       WARNING ("network plugin: Option `%s' is not allowed here.",
@@ -3360,10 +3249,10 @@ static int network_config (oconfig_item_t *ci) /* {{{ */
 static int network_notification (const notification_t *n,
     user_data_t __attribute__((unused)) *user_data)
 {
-  char  buffer[network_config_packet_size];
-  char *buffer_ptr = buffer;
-  int   buffer_free = sizeof (buffer);
-  int   status;
+  char   buffer[network_config_packet_size];
+  char  *buffer_ptr = buffer;
+  size_t buffer_free = sizeof (buffer);
+  int    status;
 
   if (!check_send_notify_okay (n))
     return (0);
@@ -3433,8 +3322,6 @@ static int network_notification (const notification_t *n,
 
 static int network_shutdown (void)
 {
-       sockent_t *se;
-
        listen_loop++;
 
        /* Kill the listening thread */
@@ -3465,7 +3352,7 @@ static int network_shutdown (void)
 
        sfree (send_buffer);
 
-       for (se = sending_sockets; se != NULL; se = se->next)
+       for (sockent_t *se = sending_sockets; se != NULL; se = se->next)
                sockent_client_disconnect (se);
        sockent_destroy (sending_sockets);
 
@@ -3571,7 +3458,7 @@ static int network_init (void)
        }
 #endif
 
-       if (network_config_stats != 0)
+       if (network_config_stats)
                plugin_register_read ("network", network_stats_read);
 
        plugin_register_shutdown ("network", network_shutdown);
@@ -3649,15 +3536,25 @@ static int network_init (void)
  * just send the buffer if `flush'  is called - if the requested value was in
  * there, good. If not, well, then there is nothing to flush.. -octo
  */
-static int network_flush (__attribute__((unused)) cdtime_t timeout,
+static int network_flush (cdtime_t timeout,
                __attribute__((unused)) const char *identifier,
                __attribute__((unused)) user_data_t *user_data)
 {
        pthread_mutex_lock (&send_buffer_lock);
 
        if (send_buffer_fill > 0)
-         flush_buffer ();
-
+       {
+               if (timeout > 0)
+               {
+                       cdtime_t now = cdtime ();
+                       if ((send_buffer_last_update + timeout) > now)
+                       {
+                               pthread_mutex_unlock (&send_buffer_lock);
+                               return (0);
+                       }
+               }
+               flush_buffer ();
+       }
        pthread_mutex_unlock (&send_buffer_lock);
 
        return (0);
index be82372..c128c81 100644 (file)
--- a/src/nfs.c
+++ b/src/nfs.c
@@ -23,6 +23,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -221,7 +222,7 @@ static size_t nfs4_server40_procedures_names_num = STATIC_ARRAY_SIZE (nfs4_serve
 static const char *nfs4_server41_procedures_names[] =
 {
        "backchannel_ctl",
-       "bind_conn_to_session", 
+       "bind_conn_to_session",
        "exchange_id",
        "create_session",
        "destroy_session",
@@ -345,8 +346,6 @@ static int nfs_init (void)
 #elif HAVE_LIBKSTAT
 static int nfs_init (void)
 {
-       kstat_t *ksp_chain = NULL;
-
        nfs2_ksp_client = NULL;
        nfs2_ksp_server = NULL;
        nfs3_ksp_client = NULL;
@@ -357,7 +356,7 @@ static int nfs_init (void)
        if (kc == NULL)
                return (-1);
 
-       for (ksp_chain = kc->kc_chain; ksp_chain != NULL;
+       for (kstat_t *ksp_chain = kc->kc_chain; ksp_chain != NULL;
                        ksp_chain = ksp_chain->ks_next)
        {
                if (strncmp (ksp_chain->ks_module, "nfs", 3) != 0)
@@ -385,7 +384,6 @@ static void nfs_procedures_submit (const char *plugin_instance,
                value_t *values, size_t values_num)
 {
        value_list_t vl = VALUE_LIST_INIT;
-       size_t i;
 
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
@@ -394,7 +392,7 @@ static void nfs_procedures_submit (const char *plugin_instance,
                        sizeof (vl.plugin_instance));
        sstrncpy (vl.type, "nfs_procedure", sizeof (vl.type));
 
-       for (i = 0; i < values_num; i++)
+       for (size_t i = 0; i < values_num; i++)
        {
                vl.values = values + i;
                sstrncpy (vl.type_instance, type_instances[i],
@@ -404,17 +402,16 @@ static void nfs_procedures_submit (const char *plugin_instance,
 } /* void nfs_procedures_submit */
 
 #if KERNEL_LINUX
-static void nfs_submit_fields (int nfs_version, const char *instance, 
+static void nfs_submit_fields (int nfs_version, const char *instance,
                char **fields, size_t fields_num, const char **proc_names)
 {
        char plugin_instance[DATA_MAX_NAME_LEN];
        value_t values[fields_num];
-       size_t i;
 
        ssnprintf (plugin_instance, sizeof (plugin_instance), "v%i%s",
                        nfs_version, instance);
 
-       for (i = 0; i < fields_num; i++)
+       for (size_t i = 0; i < fields_num; i++)
                (void) parse_value (fields[i], &values[i], DS_TYPE_DERIVE);
 
        nfs_procedures_submit (plugin_instance, proc_names, values,
@@ -434,19 +431,19 @@ static int nfs_submit_fields_safe (int nfs_version, const char *instance,
                return (EINVAL);
        }
 
-       nfs_submit_fields (nfs_version, instance, fields, fields_num, 
+       nfs_submit_fields (nfs_version, instance, fields, fields_num,
                        proc_names);
 
        return (0);
 }
 
-static int nfs_submit_nfs4_server (const char *instance, char **fields, 
+static int nfs_submit_nfs4_server (const char *instance, char **fields,
                size_t fields_num)
 {
        static int suppress_warning = 0;
 
        if (fields_num != NFS4_SERVER40_NUM_PROC &&
-               fields_num != NFS4_SERVER41_NUM_PROC) 
+               fields_num != NFS4_SERVER41_NUM_PROC)
        {
                if (!suppress_warning)
                {
@@ -466,7 +463,7 @@ static int nfs_submit_nfs4_server (const char *instance, char **fields,
                }
        }
 
-        nfs_submit_fields (4, instance, fields, 
+        nfs_submit_fields (4, instance, fields,
                        nfs4_server40_procedures_names_num,
                        nfs4_server40_procedures_names);
 
@@ -474,15 +471,15 @@ static int nfs_submit_nfs4_server (const char *instance, char **fields,
        {
                fields += nfs4_server40_procedures_names_num;
 
-               nfs_submit_fields (4, instance, fields, 
-                               nfs4_server41_procedures_names_num, 
+               nfs_submit_fields (4, instance, fields,
+                               nfs4_server41_procedures_names_num,
                                nfs4_server41_procedures_names);
        }
 
        return (0);
 }
 
-static int nfs_submit_nfs4_client (const char *instance, char **fields, 
+static int nfs_submit_nfs4_client (const char *instance, char **fields,
                size_t fields_num)
 {
        size_t proc40_names_num, proc41_names_num;
@@ -554,7 +551,7 @@ static int nfs_submit_nfs4_client (const char *instance, char **fields,
        return (0);
 }
 
-static void nfs_read_linux (FILE *fh, char *inst)
+static void nfs_read_linux (FILE *fh, const char *inst)
 {
        char buffer[1024];
 
@@ -589,26 +586,25 @@ static void nfs_read_linux (FILE *fh, char *inst)
                else if (strcmp (fields[0], "proc4ops") == 0)
                {
                        if (inst[0] == 's')
-                               nfs_submit_nfs4_server (inst, fields + 2, 
+                               nfs_submit_nfs4_server (inst, fields + 2,
                                                (size_t) (fields_num - 2));
                }
                else if (strcmp (fields[0], "proc4") == 0)
                {
                        if (inst[0] == 'c')
                                nfs_submit_nfs4_client (inst, fields + 2,
-                                               (size_t) (fields_num - 2));                     
+                                               (size_t) (fields_num - 2));
                }
        } /* while (fgets) */
 } /* void nfs_read_linux */
 #endif /* KERNEL_LINUX */
 
 #if HAVE_LIBKSTAT
-static int nfs_read_kstat (kstat_t *ksp, int nfs_version, char *inst,
+static int nfs_read_kstat (kstat_t *ksp, int nfs_version, const char *inst,
                char const **proc_names, size_t proc_names_num)
 {
        char plugin_instance[DATA_MAX_NAME_LEN];
        value_t values[proc_names_num];
-       size_t i;
 
        if (ksp == NULL)
                return (EINVAL);
@@ -617,7 +613,7 @@ static int nfs_read_kstat (kstat_t *ksp, int nfs_version, char *inst,
                        nfs_version, inst);
 
        kstat_read(kc, ksp, NULL);
-       for (i = 0; i < proc_names_num; i++)
+       for (size_t i = 0; i < proc_names_num; i++)
        {
                /* The name passed to kstat_data_lookup() doesn't have the
                 * "const" modifier, so we need to copy the name here. */
index 4e4ce3b..e346cee 100644 (file)
@@ -27,6 +27,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -71,7 +72,7 @@ static size_t nginx_curl_callback (void *buf, size_t size, size_t nmemb,
     len = (sizeof (nginx_buffer) - 1) - nginx_buffer_len;
   }
 
-  if (len <= 0)
+  if (len == 0)
     return (len);
 
   memcpy (&nginx_buffer[nginx_buffer_len], buf, len);
@@ -188,15 +189,14 @@ static int init (void)
   }
   else
   {
-    curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS,
-       CDTIME_T_TO_MS(plugin_get_interval()));
+    curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
   }
 #endif
 
   return (0);
 } /* void init */
 
-static void submit (char *type, char *inst, long long value)
+static void submit (const char *type, const char *inst, long long value)
 {
   value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
@@ -225,8 +225,6 @@ static void submit (char *type, char *inst, long long value)
 
 static int nginx_read (void)
 {
-  int i;
-
   char *ptr;
   char *lines[16];
   int   lines_num = 0;
@@ -264,7 +262,7 @@ static int nginx_read (void)
    *  16630948 16630948 31070465
    * Reading: 6 Writing: 179 Waiting: 106
    */
-  for (i = 0; i < lines_num; i++)
+  for (int i = 0; i < lines_num; i++)
   {
     fields_num = strsplit (lines[i], fields,
        (sizeof (fields) / sizeof (fields[0])));
index c2d9752..ef7b95b 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -66,9 +67,7 @@ static int set_timeout (oconfig_item_t *ci, int *timeout)
 
 static int c_notify_config (oconfig_item_t *ci)
 {
-       int i = 0;
-
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *c = ci->children + i;
 
                if (0 == strcasecmp (c->key, "OkayTimeout"))
index 76d48d4..cefeb22 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
 #include <auth-client.h>
 #include <libesmtp.h>
-#include <pthread.h>
 
 #define MAXSTRING               256
 
@@ -66,9 +66,8 @@ static char *email_subject = NULL;
 /* Callback to get username and password */
 static int authinteract (auth_client_request_t request, char **result,
     int fields, void __attribute__((unused)) *arg)
-{               
-  int i;
-  for (i = 0; i < fields; i++)
+{
+  for (int i = 0; i < fields; i++)
   {
     if (request[i].flags & AUTH_USER)
       result[i] = smtp_user;
@@ -145,7 +144,7 @@ static int notify_email_init (void)
   if ( !smtp_auth_set_context (session, authctx)) {
     pthread_mutex_unlock (&session_lock);
     ERROR ("notify_email plugin: cannot set SMTP auth context");
-    return (-1);   
+    return (-1);
   }
 
   pthread_mutex_unlock (&session_lock);
@@ -176,7 +175,7 @@ static int notify_email_config (const char *key, const char *value)
   {
     char **tmp;
 
-    tmp = (char **) realloc ((void *) recipients, (recipients_len + 1) * sizeof (char *));
+    tmp = realloc (recipients, (recipients_len + 1) * sizeof (char *));
     if (tmp == NULL) {
       ERROR ("notify_email: realloc failed.");
       return (-1);
@@ -282,7 +281,7 @@ static int notify_email_notification (const notification_t *n,
   if (!(message = smtp_add_message (session))) {
     pthread_mutex_unlock (&session_lock);
     ERROR ("notify_email plugin: cannot set SMTP message");
-    return (-1);   
+    return (-1);
   }
   smtp_set_reverse_path (message, email_from);
   smtp_set_header (message, "To", NULL, NULL);
diff --git a/src/notify_nagios.c b/src/notify_nagios.c
new file mode 100644 (file)
index 0000000..57a034d
--- /dev/null
@@ -0,0 +1,166 @@
+/**
+ * collectd - src/notify_nagios.c
+ * Copyright (C) 2015       Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "collectd.h"
+
+#include "plugin.h"
+#include "common.h"
+#include "configfile.h"
+
+#define NAGIOS_OK       0
+#define NAGIOS_WARNING  1
+#define NAGIOS_CRITICAL 2
+#define NAGIOS_UNKNOWN  3
+
+#ifndef NAGIOS_COMMAND_FILE
+# define NAGIOS_COMMAND_FILE "/usr/local/nagios/var/rw/nagios.cmd"
+#endif
+
+static char *nagios_command_file;
+
+static int nagios_config (oconfig_item_t *ci) /* {{{ */
+{
+  for (int i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("CommandFile", child->key) == 0)
+      cf_util_get_string (child, &nagios_command_file);
+    else
+      WARNING ("notify_nagios plugin: Ignoring unknown config option \"%s\".",
+          child->key);
+  }
+
+  return 0;
+} /* }}} nagios_config */
+
+static int nagios_print (char const *buffer) /* {{{ */
+{
+  char const *file = NAGIOS_COMMAND_FILE;
+  int fd;
+  int status;
+  struct flock lock = { 0 };
+
+  if (nagios_command_file != NULL)
+    file = nagios_command_file;
+
+  fd = open (file, O_WRONLY | O_APPEND);
+  if (fd < 0)
+  {
+    char errbuf[1024];
+    status = errno;
+    ERROR ("notify_nagios plugin: Opening \"%s\" failed: %s",
+        file, sstrerror (status, errbuf, sizeof (errbuf)));
+    return status;
+  }
+
+  lock.l_type = F_WRLCK;
+  lock.l_whence = SEEK_END;
+
+  status = fcntl (fd, F_GETLK, &lock);
+  if (status != 0)
+  {
+    char errbuf[1024];
+    status = errno;
+    ERROR ("notify_nagios plugin: Failed to acquire write lock on \"%s\": %s",
+        file, sstrerror (status, errbuf, sizeof (errbuf)));
+    close (fd);
+    return status;
+  }
+
+  status = (int) lseek (fd, 0, SEEK_END);
+  if (status == -1)
+  {
+    char errbuf[1024];
+    status = errno;
+    ERROR ("notify_nagios plugin: Seeking to end of \"%s\" failed: %s",
+        file, sstrerror (status, errbuf, sizeof (errbuf)));
+    close (fd);
+    return status;
+  }
+
+  status = (int) swrite (fd, buffer, strlen (buffer));
+  if (status != 0)
+  {
+    char errbuf[1024];
+    status = errno;
+    ERROR ("notify_nagios plugin: Writing to \"%s\" failed: %s",
+        file, sstrerror (status, errbuf, sizeof (errbuf)));
+    close (fd);
+    return status;
+  }
+
+  close (fd);
+  return status;
+} /* }}} int nagios_print */
+
+static int nagios_notify (const notification_t *n, /* {{{ */
+    __attribute__((unused)) user_data_t *user_data)
+{
+  char svc_description[4 * DATA_MAX_NAME_LEN];
+  char buffer[4096];
+  int code;
+  int status;
+
+  status = format_name (svc_description, (int) sizeof (svc_description),
+      /* host */ "", n->plugin, n->plugin_instance, n->type, n->type_instance);
+  if (status != 0)
+  {
+    ERROR ("notify_nagios plugin: Formatting service name failed.");
+    return status;
+  }
+
+  switch (n->severity)
+  {
+    case NOTIF_OKAY:
+      code = NAGIOS_OK;
+      break;
+    case NOTIF_WARNING:
+      code = NAGIOS_WARNING;
+      break;
+    case NOTIF_FAILURE:
+      code = NAGIOS_CRITICAL;
+      break;
+    default:
+      code = NAGIOS_UNKNOWN;
+      break;
+  }
+
+  ssnprintf (buffer, sizeof (buffer),
+      "[%.0f] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",
+      CDTIME_T_TO_DOUBLE (n->time), n->host, &svc_description[1], code,
+      n->message);
+
+  return nagios_print (buffer);
+} /* }}} int nagios_notify */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("notify_nagios", nagios_config);
+  plugin_register_notification ("notify_nagios", nagios_notify, NULL);
+} /* void module_register (void) */
+
+/* vim: set sw=2 sts=2 ts=8 et : */
index ce54e02..a009365 100644 (file)
@@ -28,6 +28,7 @@
 #define _BSD_SOURCE /* For NI_MAXHOST */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -38,9 +39,6 @@
 #if HAVE_NETDB_H
 # include <netdb.h>
 #endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
 #if HAVE_NETINET_IN_H
 # include <netinet/in.h>
 #endif
 # include <poll.h>
 #endif
 
+#ifndef STA_NANO
+# define STA_NANO 0x2000
+#endif
+
 static const char *config_keys[] =
 {
        "Host",
@@ -250,7 +252,7 @@ struct info_kernel
 };
 
 /* List of reference clock names */
-static char *refclock_names[] =
+static const char *refclock_names[] =
 {
        "UNKNOWN",    "LOCAL",        "GPS_TRAK",   "WWV_PST",     /*  0- 3 */
        "SPECTRACOM", "TRUETIME",     "IRIG_AUDIO", "CHU_AUDIO",   /*  4- 7 */
@@ -265,7 +267,7 @@ static char *refclock_names[] =
        "JJY",        "TT_IRIG",      "GPS_ZYFER",  "GPS_RIPENCC", /* 40-43 */
        "NEOCLK4X"                                                 /* 44    */
 };
-static int refclock_names_num = STATIC_ARRAY_SIZE (refclock_names);
+static size_t refclock_names_num = STATIC_ARRAY_SIZE (refclock_names);
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * End of the copied stuff..                                         *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -310,7 +312,7 @@ static int ntpd_config (const char *key, const char *value)
        return (0);
 }
 
-static void ntpd_submit (char *type, char *type_inst, gauge_t value)
+static void ntpd_submit (const char *type, const char *type_inst, gauge_t value)
 {
        value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
@@ -331,8 +333,8 @@ static void ntpd_submit (char *type, char *type_inst, gauge_t value)
 /* Each time a peer is polled, ntpd shifts the reach register to the left and
  * sets the LSB based on whether the peer was reachable. If the LSB is zero,
  * the values are out of date. */
-static void ntpd_submit_reach (char *type, char *type_inst, uint8_t reach,
-               gauge_t value)
+static void ntpd_submit_reach (const char *type, const char *type_inst,
+               uint8_t reach, gauge_t value)
 {
        if (!(reach & 1))
                value = NAN;
@@ -342,12 +344,10 @@ static void ntpd_submit_reach (char *type, char *type_inst, uint8_t reach,
 
 static int ntpd_connect (void)
 {
-       char *host;
-       char *port;
+       const char *host;
+       const char *port;
 
-       struct addrinfo  ai_hints;
        struct addrinfo *ai_list;
-       struct addrinfo *ai_ptr;
        int              status;
 
        if (sock_descr >= 0)
@@ -363,14 +363,12 @@ static int ntpd_connect (void)
        if (strlen (port) == 0)
                port = NTPD_DEFAULT_PORT;
 
-       memset (&ai_hints, '\0', sizeof (ai_hints));
-       ai_hints.ai_flags    = 0;
-#ifdef AI_ADDRCONFIG
-       ai_hints.ai_flags   |= AI_ADDRCONFIG;
-#endif
-       ai_hints.ai_family   = PF_UNSPEC;
-       ai_hints.ai_socktype = SOCK_DGRAM;
-       ai_hints.ai_protocol = IPPROTO_UDP;
+       struct addrinfo ai_hints = {
+               .ai_family   = AF_UNSPEC,
+               .ai_flags    = AI_ADDRCONFIG,
+               .ai_protocol = IPPROTO_UDP,
+               .ai_socktype = SOCK_DGRAM
+       };
 
        if ((status = getaddrinfo (host, port, &ai_hints, &ai_list)) != 0)
        {
@@ -383,7 +381,7 @@ static int ntpd_connect (void)
                return (-1);
        }
 
-       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
        {
                /* create our socket descriptor */
                if ((sock_descr = socket (ai_ptr->ai_family,
@@ -421,7 +419,6 @@ static int ntpd_receive_response (int *res_items, int *res_size,
        struct resp_pkt  res;
        int              status;
        int              done;
-       int              i;
 
        char            *items;
        size_t           items_num;
@@ -430,13 +427,13 @@ static int ntpd_receive_response (int *res_items, int *res_size,
        struct timeval   time_now;
        int              timeout;
 
-       int              pkt_item_num;        /* items in this packet */
-       int              pkt_item_len;        /* size of the items in this packet */
+       int              pkt_item_num;                /* items in this packet */
+       int              pkt_item_len;                /* size of the items in this packet */
        int              pkt_sequence;
-       char             pkt_recvd[MAXSEQ+1]; /* sequence numbers that have been received */
-       int              pkt_recvd_num;       /* number of packets that have been received */
-       int              pkt_lastseq;         /* the last sequence number */
-       ssize_t          pkt_padding;         /* Padding in this packet */
+       char             pkt_recvd[MAXSEQ+1] = { 0 }; /* sequence numbers that have been received */
+       int              pkt_recvd_num;               /* number of packets that have been received */
+       int              pkt_lastseq;                 /* the last sequence number */
+       ssize_t          pkt_padding;                 /* Padding in this packet */
 
        if ((sd = ntpd_connect ()) < 0)
                return (-1);
@@ -444,7 +441,6 @@ static int ntpd_receive_response (int *res_items, int *res_size,
        items = NULL;
        items_num = 0;
 
-       memset (pkt_recvd, '\0', sizeof (pkt_recvd));
        pkt_recvd_num = 0;
        pkt_lastseq   = -1;
 
@@ -508,7 +504,7 @@ static int ntpd_receive_response (int *res_items, int *res_size,
                        break;
                }
 
-               memset ((void *) &res, '\0', sizeof (res));
+               memset (&res, '\0', sizeof (res));
                status = recv (sd, (void *) &res, sizeof (res), 0 /* no flags */);
 
                if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
@@ -666,7 +662,7 @@ static int ntpd_receive_response (int *res_items, int *res_size,
                 */
                DEBUG ("realloc (%p, %zu)", (void *) *res_data,
                                (items_num + pkt_item_num) * res_item_size);
-               items = realloc ((void *) *res_data,
+               items = realloc (*res_data,
                                (items_num + pkt_item_num) * res_item_size);
                if (items == NULL)
                {
@@ -676,7 +672,7 @@ static int ntpd_receive_response (int *res_items, int *res_size,
                items_num += pkt_item_num;
                *res_data = items;
 
-               for (i = 0; i < pkt_item_num; i++)
+               for (int i = 0; i < pkt_item_num; i++)
                {
                        /* dst: There are already `*res_items' items with
                         *      res_item_size bytes each in in `*res_data'. Set
@@ -713,7 +709,7 @@ static int ntpd_receive_response (int *res_items, int *res_size,
 static int ntpd_send_request (int req_code, int req_items, int req_size, char *req_data)
 {
        int             sd;
-       struct req_pkt  req;
+       struct req_pkt  req = { 0 };
        size_t          req_data_len;
        int             status;
 
@@ -723,7 +719,6 @@ static int ntpd_send_request (int req_code, int req_items, int req_size, char *r
        if ((sd = ntpd_connect ()) < 0)
                return (-1);
 
-       memset ((void *) &req, '\0', sizeof (req));
        req.rm_vn_mode = RM_VN_MODE(0, 0, 0);
        req.auth_seq   = AUTH_SEQ (0, 0);
        req.implementation = IMPL_XNTPD;
@@ -804,20 +799,17 @@ static uint32_t ntpd_get_refclock_id (struct info_peer_summary const *peer_info)
 static int ntpd_get_name_from_address (char *buffer, size_t buffer_size,
                struct info_peer_summary const *peer_info, _Bool do_reverse_lookup)
 {
-       struct sockaddr_storage sa;
+       struct sockaddr_storage sa = { 0 };
        socklen_t sa_len;
        int flags = 0;
        int status;
 
-       memset (&sa, 0, sizeof (sa));
-
        if (peer_info->v6_flag)
        {
-               struct sockaddr_in6 sa6;
+               struct sockaddr_in6 sa6 = { 0 };
 
                assert (sizeof (sa) >= sizeof (sa6));
 
-               memset (&sa6, 0, sizeof (sa6));
                sa6.sin6_family = AF_INET6;
                sa6.sin6_port = htons (123);
                memcpy (&sa6.sin6_addr, &peer_info->srcadr6,
@@ -828,11 +820,10 @@ static int ntpd_get_name_from_address (char *buffer, size_t buffer_size,
        }
        else
        {
-               struct sockaddr_in sa4;
+               struct sockaddr_in sa4 = { 0 };
 
                assert (sizeof (sa) >= sizeof (sa4));
 
-               memset (&sa4, 0, sizeof (sa4));
                sa4.sin_family = AF_INET;
                sa4.sin_port = htons (123);
                memcpy (&sa4.sin_addr, &peer_info->srcadr,
@@ -868,7 +859,7 @@ static int ntpd_get_name_refclock (char *buffer, size_t buffer_size,
        uint32_t refclock_id = ntpd_get_refclock_id (peer_info);
        uint32_t unit_id = ntohl (peer_info->srcadr) & 0x00FF;
 
-       if (refclock_id >= refclock_names_num)
+       if (((size_t) refclock_id) >= refclock_names_num)
                return (ntpd_get_name_from_address (buffer, buffer_size,
                                        peer_info,
                                        /* do_reverse_lookup = */ 0));
@@ -910,11 +901,9 @@ static int ntpd_read (void)
        gauge_t offset_error;
 
        int status;
-       int i;
 
        /* On Linux, if the STA_NANO bit is set in ik->status, then ik->offset
-        * is is nanoseconds, otherwise it's microseconds.
-        * TODO(octo): STA_NANO is defined in the Linux specific <sys/timex.h> header. */
+        * is is nanoseconds, otherwise it's microseconds. */
        double scale_loop  = 1e-6;
        double scale_error = 1e-6;
 
@@ -939,6 +928,11 @@ static int ntpd_read (void)
                return (-1);
        }
 
+       if (ntohs(ik->status) & STA_NANO) {
+               scale_loop  = 1e-9;
+               scale_error = 1e-9;
+       }
+
        /* kerninfo -> estimated error */
        offset_loop  = scale_loop * ((gauge_t) ntohl (ik->offset));
        freq_loop    = ntpd_read_fp (ik->freq);
@@ -974,7 +968,7 @@ static int ntpd_read (void)
                return (-1);
        }
 
-       for (i = 0; i < ps_num; i++)
+       for (int i = 0; i < ps_num; i++)
        {
                struct info_peer_summary *ptr;
                double offset;
index a87a17e..8f5bf48 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -130,11 +131,10 @@ static int numa_init (void) /* {{{ */
   while (42)
   {
     char path[PATH_MAX];
-    struct stat statbuf;
+    struct stat statbuf = { 0 };
     int status;
 
     ssnprintf (path, sizeof (path), NUMA_ROOT_DIR "/node%i", max_node + 1);
-    memset (&statbuf, 0, sizeof (statbuf));
 
     status = stat (path, &statbuf);
     if (status == 0)
index d5ecc98..b5c6b41 100644 (file)
--- a/src/nut.c
+++ b/src/nut.c
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
-#include <pthread.h>
 #include <upsclient.h>
 
 #if HAVE_UPSCONN_T
@@ -80,13 +80,12 @@ static int nut_add_ups (const char *name)
 
   DEBUG ("nut plugin: nut_add_ups (name = %s);", name);
 
-  ups = (nut_ups_t *) malloc (sizeof (nut_ups_t));
+  ups = calloc (1, sizeof (*ups));
   if (ups == NULL)
   {
-    ERROR ("nut plugin: nut_add_ups: malloc failed.");
+    ERROR ("nut plugin: nut_add_ups: calloc failed.");
     return (1);
   }
-  memset (ups, '\0', sizeof (nut_ups_t));
 
   status = upscli_splitname (name, &ups->upsname, &ups->hostname,
       &ups->port);
@@ -152,7 +151,7 @@ static int nut_read_one (nut_ups_t *ups)
   /* (Re-)Connect if we have no connection */
   if (ups->conn == NULL)
   {
-    ups->conn = (collectd_upsconn_t *) malloc (sizeof (collectd_upsconn_t));
+    ups->conn = malloc (sizeof (*ups->conn));
     if (ups->conn == NULL)
     {
       ERROR ("nut plugin: malloc failed.");
@@ -249,7 +248,6 @@ static int nut_read_one (nut_ups_t *ups)
 
 static int nut_read (void)
 {
-  nut_ups_t *ups;
   int success = 0;
 
   pthread_mutex_lock (&read_lock);
@@ -260,7 +258,7 @@ static int nut_read (void)
   if (success != 0)
     return (0);
 
-  for (ups = upslist_head; ups != NULL; ups = ups->next)
+  for (nut_ups_t *ups = upslist_head; ups != NULL; ups = ups->next)
     if (nut_read_one (ups) == 0)
       success++;
 
index 6d0576c..899ad3e 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
 #include <sys/types.h>
 #include <netdb.h>
-#include <sys/socket.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 
@@ -150,22 +150,18 @@ static size_t strtabsplit (char *string, char **fields, size_t size) /* {{{ */
 
 static FILE *olsrd_connect (void) /* {{{ */
 {
-  struct addrinfo  ai_hints;
-  struct addrinfo *ai_list, *ai_ptr;
+  struct addrinfo *ai_list;
   int              ai_return;
 
   FILE *fh;
 
-  memset (&ai_hints, 0, sizeof (ai_hints));
-  ai_hints.ai_flags    = 0;
-#ifdef AI_ADDRCONFIG
-  ai_hints.ai_flags   |= AI_ADDRCONFIG;
-#endif
-  ai_hints.ai_family   = PF_UNSPEC;
-  ai_hints.ai_socktype = SOCK_STREAM;
-  ai_hints.ai_protocol = IPPROTO_TCP;
+  struct addrinfo ai_hints = {
+    .ai_family   = AF_UNSPEC,
+    .ai_flags    = AI_ADDRCONFIG,
+    .ai_protocol = IPPROTO_TCP,
+    .ai_socktype = SOCK_STREAM
+  };
 
-  ai_list = NULL;
   ai_return = getaddrinfo (olsrd_get_node (), olsrd_get_service (),
       &ai_hints, &ai_list);
   if (ai_return != 0)
@@ -177,7 +173,7 @@ static FILE *olsrd_connect (void) /* {{{ */
   }
 
   fh = NULL;
-  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
   {
     int fd;
     int status;
@@ -558,9 +554,8 @@ static int olsrd_cb_topology (int lineno, /* {{{ */
 
     if (config_want_topology == OLSRD_WANT_DETAIL)
     {
-      char type_instance[DATA_MAX_NAME_LEN];
+      char type_instance[DATA_MAX_NAME_LEN] = { 0 };
 
-      memset (type_instance, 0, sizeof (type_instance));
       ssnprintf (type_instance, sizeof (type_instance), "%s-%s-lq",
           fields[0], fields[1]);
       DEBUG ("olsrd plugin: type_instance = %s; lq = %g;", type_instance, lq);
@@ -582,9 +577,8 @@ static int olsrd_cb_topology (int lineno, /* {{{ */
     }
     else
     {
-      char type_instance[DATA_MAX_NAME_LEN];
+      char type_instance[DATA_MAX_NAME_LEN] = { 0 };
 
-      memset (type_instance, 0, sizeof (type_instance));
       ssnprintf (type_instance, sizeof (type_instance), "%s-%s-nlq",
           fields[0], fields[1]);
       DEBUG ("olsrd plugin: type_instance = %s; nlq = %g;", type_instance, nlq);
@@ -612,7 +606,7 @@ static int olsrd_read_table (FILE *fh, /* {{{ */
   {
     /* An empty line ends the table. */
     buffer_len = strchomp (buffer);
-    if (buffer_len <= 0)
+    if (buffer_len == 0)
     {
       (*callback) (lineno, /* fields_num = */ 0, /* fields = */ NULL);
       break;
@@ -623,7 +617,7 @@ static int olsrd_read_table (FILE *fh, /* {{{ */
     (*callback) (lineno, fields_num, fields);
     lineno++;
   } /* while (fgets) */
-  
+
   return (0);
 } /* }}} int olsrd_read_table */
 
@@ -664,9 +658,9 @@ static int olsrd_read (void) /* {{{ */
   while (fgets (buffer, sizeof (buffer), fh) != NULL)
   {
     buffer_len = strchomp (buffer);
-    if (buffer_len <= 0)
+    if (buffer_len == 0)
       continue;
-    
+
     if (strcmp ("Table: Links", buffer) == 0)
       olsrd_read_table (fh, olsrd_cb_links);
     else if (strcmp ("Table: Neighbors", buffer) == 0)
@@ -691,7 +685,7 @@ static int olsrd_read (void) /* {{{ */
   } /* while (fgets) */
 
   fclose (fh);
-  
+
   return (0);
 } /* }}} int olsrd_read */
 
index 51e6407..235eff8 100644 (file)
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_ignorelist.h"
@@ -176,11 +177,11 @@ static int direct_list_insert(const char * config)
 {
     regmatch_t               pmatch[3];
     size_t                   nmatch = 3;
-    direct_access_element_t *element = NULL;
+    direct_access_element_t *element;
 
     DEBUG ("onewire plugin: direct_list_insert <%s>", config);
 
-    element = (direct_access_element_t *) malloc (sizeof(*element));
+    element = malloc (sizeof (*element));
     if (element == NULL)
     {
         ERROR ("onewire plugin: direct_list_insert - cannot allocate element");
@@ -338,7 +339,6 @@ static int cow_read_values (const char *path, const char *name,
   value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
   int success = 0;
-  size_t i;
 
   if (sensor_list != NULL)
   {
@@ -354,7 +354,7 @@ static int cow_read_values (const char *path, const char *name,
   sstrncpy (vl.plugin, "onewire", sizeof (vl.plugin));
   sstrncpy (vl.plugin_instance, name, sizeof (vl.plugin_instance));
 
-  for (i = 0; i < family_info->features_num; i++)
+  for (size_t i = 0; i < family_info->features_num; i++)
   {
     char *buffer;
     size_t buffer_size;
@@ -415,11 +415,11 @@ static int cow_read_ds2409 (const char *path)
   int status;
 
   status = ssnprintf (subpath, sizeof (subpath), "%s/main", path);
-  if ((status > 0) && (status < sizeof (subpath)))
+  if ((status > 0) && (status < (int) sizeof (subpath)))
     cow_read_bus (subpath);
 
   status = ssnprintf (subpath, sizeof (subpath), "%s/aux", path);
-  if ((status > 0) && (status < sizeof (subpath)))
+  if ((status > 0) && (status < (int) sizeof (subpath)))
     cow_read_bus (subpath);
 
   return (0);
@@ -459,7 +459,7 @@ static int cow_read_bus (const char *path)
     else
       status = ssnprintf (subpath, sizeof (subpath), "%s/%s",
           path, buffer_ptr);
-    if ((status <= 0) || (status >= sizeof (subpath)))
+    if ((status <= 0) || (status >= (int) sizeof (subpath)))
       continue;
 
     for (i = 0; i < ow_family_features_num; i++)
@@ -590,7 +590,6 @@ static int cow_shutdown (void)
 static int cow_init (void)
 {
   int status;
-  struct timespec cb_interval;
 
   if (device_g == NULL)
   {
@@ -606,11 +605,8 @@ static int cow_init (void)
     return (1);
   }
 
-  CDTIME_T_TO_TIMESPEC (ow_interval, &cb_interval);
-
   plugin_register_complex_read (/* group = */ NULL, "onewire", cow_read,
-      (ow_interval != 0) ? &cb_interval : NULL,
-      /* user data = */ NULL);
+      ow_interval, /* user data = */ NULL);
   plugin_register_shutdown ("onewire", cow_shutdown);
 
   return (0);
index bd79b26..282e2dc 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * collectd - src/openldap.c
  * Copyright (C) 2011       Kimo Rosenbaum
- * Copyright (C) 2014       Marc Fournier
+ * Copyright (C) 2014-2015  Marc Fournier
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -27,6 +27,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -43,6 +44,8 @@ struct cldap_s /* {{{ */
 {
        char *name;
 
+       char *binddn;
+       char *password;
        char *cacert;
        char *host;
        int   state;
@@ -56,11 +59,16 @@ struct cldap_s /* {{{ */
 };
 typedef struct cldap_s cldap_t; /* }}} */
 
+static cldap_t **databases   = NULL;
+static size_t  databases_num = 0;
+
 static void cldap_free (cldap_t *st) /* {{{ */
 {
        if (st == NULL)
                return;
 
+       sfree (st->binddn);
+       sfree (st->password);
        sfree (st->cacert);
        sfree (st->host);
        sfree (st->name);
@@ -75,6 +83,13 @@ static int cldap_init_host (cldap_t *st) /* {{{ */
 {
        LDAP *ld;
        int rc;
+
+       if (st->state && st->ld)
+       {
+               DEBUG ("openldap plugin: Already connected to %s", st->url);
+               return (0);
+       }
+
        rc = ldap_initialize (&ld, st->url);
        if (rc != LDAP_SUCCESS)
        {
@@ -92,6 +107,8 @@ static int cldap_init_host (cldap_t *st) /* {{{ */
        ldap_set_option (st->ld, LDAP_OPT_TIMEOUT,
                &(const struct timeval){st->timeout, 0});
 
+       ldap_set_option (st->ld, LDAP_OPT_RESTART, LDAP_OPT_ON);
+
        if (st->cacert != NULL)
                ldap_set_option (st->ld, LDAP_OPT_X_TLS_CACERTFILE, st->cacert);
 
@@ -115,10 +132,19 @@ static int cldap_init_host (cldap_t *st) /* {{{ */
        }
 
        struct berval cred;
-       cred.bv_val = "";
-       cred.bv_len = 0;
+       if (st->password != NULL)
+       {
+               cred.bv_val = st->password;
+               cred.bv_len = strlen (st->password);
+       }
+       else
+       {
+               cred.bv_val = "";
+               cred.bv_len = 0;
+       }
 
-       rc = ldap_sasl_bind_s (st->ld, NULL, NULL, &cred, NULL, NULL, NULL);
+       rc = ldap_sasl_bind_s (st->ld, st->binddn, LDAP_SASL_SIMPLE, &cred,
+                       NULL, NULL, NULL);
        if (rc != LDAP_SUCCESS)
        {
                ERROR ("openldap plugin: Failed to bind to %s: %s",
@@ -147,13 +173,9 @@ static void cldap_submit_value (const char *type, const char *type_instance, /*
        if ((st->host == NULL)
                        || (strcmp ("", st->host) == 0)
                        || (strcmp ("localhost", st->host) == 0))
-       {
                sstrncpy (vl.host, hostname_g, sizeof (vl.host));
-       }
        else
-       {
                sstrncpy (vl.host, st->host, sizeof (vl.host));
-       }
 
        sstrncpy (vl.plugin, "openldap", sizeof (vl.plugin));
        if (st->name != NULL)
@@ -187,7 +209,7 @@ static void cldap_submit_gauge (const char *type, const char *type_instance, /*
 static int cldap_read_host (user_data_t *ud) /* {{{ */
 {
        cldap_t *st;
-       LDAPMessage *e, *result;
+       LDAPMessage *result;
        char *dn;
        int rc;
        int status;
@@ -223,11 +245,12 @@ static int cldap_read_host (user_data_t *ud) /* {{{ */
                ERROR ("openldap plugin: Failed to execute search: %s",
                                ldap_err2string (rc));
                ldap_msgfree (result);
+               st->state = 0;
                ldap_unbind_ext_s (st->ld, NULL, NULL);
                return (-1);
        }
 
-       for (e = ldap_first_entry (st->ld, result); e != NULL;
+       for (LDAPMessage *e = ldap_first_entry (st->ld, result); e != NULL;
                e = ldap_next_entry (st->ld, e))
        {
                if ((dn = ldap_get_dn (st->ld, e)) != NULL)
@@ -520,7 +543,6 @@ static int cldap_read_host (user_data_t *ud) /* {{{ */
        }
 
        ldap_msgfree (result);
-       ldap_unbind_ext_s (st->ld, NULL, NULL);
        return (0);
 } /* }}} int cldap_read_host */
 
@@ -537,16 +559,14 @@ static int cldap_read_host (user_data_t *ud) /* {{{ */
 static int cldap_config_add (oconfig_item_t *ci) /* {{{ */
 {
        cldap_t *st;
-       int i;
        int status;
 
-       st = malloc (sizeof (*st));
+       st = calloc (1, sizeof (*st));
        if (st == NULL)
        {
-               ERROR ("openldap plugin: malloc failed.");
+               ERROR ("openldap plugin: calloc failed.");
                return (-1);
        }
-       memset (st, 0, sizeof (*st));
 
        status = cf_util_get_string (ci, &st->name);
        if (status != 0)
@@ -556,15 +576,19 @@ static int cldap_config_add (oconfig_item_t *ci) /* {{{ */
        }
 
        st->starttls = 0;
-       st->timeout = -1;
+       st->timeout = (long) (CDTIME_T_TO_MS(plugin_get_interval()) / 1000);
        st->verifyhost = 1;
        st->version = LDAP_VERSION3;
 
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
 
-               if (strcasecmp ("CACert", child->key) == 0)
+               if (strcasecmp ("BindDN", child->key) == 0)
+                       status = cf_util_get_string (child, &st->binddn);
+               else if (strcasecmp ("Password", child->key) == 0)
+                       status = cf_util_get_string (child, &st->password);
+               else if (strcasecmp ("CACert", child->key) == 0)
                        status = cf_util_get_string (child, &st->cacert);
                else if (strcasecmp ("StartTLS", child->key) == 0)
                        status = cf_util_get_boolean (child, &st->starttls);
@@ -600,9 +624,8 @@ static int cldap_config_add (oconfig_item_t *ci) /* {{{ */
        if ((status == 0) && (st->url != NULL))
        {
                LDAPURLDesc *ludpp;
-               int rc;
 
-               if ((rc = ldap_url_parse (st->url, &ludpp)) != 0)
+               if (ldap_url_parse (st->url, &ludpp) != 0)
                {
                        ERROR ("openldap plugin: Instance `%s': "
                                "Invalid URL: `%s'",
@@ -611,32 +634,45 @@ static int cldap_config_add (oconfig_item_t *ci) /* {{{ */
                }
 
                if ((status == 0) && (ludpp->lud_host != NULL))
-               {
                        st->host = strdup (ludpp->lud_host);
-               }
 
                ldap_free_urldesc (ludpp);
        }
 
        if (status == 0)
        {
-               user_data_t ud;
-               char callback_name[3*DATA_MAX_NAME_LEN];
-
-               memset (&ud, 0, sizeof (ud));
-               ud.data = st;
-
-               memset (callback_name, 0, sizeof (callback_name));
-               ssnprintf (callback_name, sizeof (callback_name),
-                               "openldap/%s/%s",
-                               (st->host != NULL) ? st->host : hostname_g,
-                               (st->name != NULL) ? st->name : "default"),
-
-               status = plugin_register_complex_read (/* group = */ NULL,
-                               /* name      = */ callback_name,
-                               /* callback  = */ cldap_read_host,
-                               /* interval  = */ NULL,
-                               /* user_data = */ &ud);
+               cldap_t **temp;
+
+               temp = (cldap_t **) realloc (databases,
+                       sizeof (*databases) * (databases_num + 1));
+
+               if (temp == NULL)
+               {
+                       ERROR ("openldap plugin: realloc failed");
+                       status = -1;
+               }
+               else
+               {
+                       user_data_t ud = { 0 };
+                       char callback_name[3*DATA_MAX_NAME_LEN] = { 0 };
+
+                       databases = temp;
+                       databases[databases_num] = st;
+                       databases_num++;
+
+                       ud.data = st;
+
+                       ssnprintf (callback_name, sizeof (callback_name),
+                                       "openldap/%s/%s",
+                                       (st->host != NULL) ? st->host : hostname_g,
+                                       (st->name != NULL) ? st->name : "default"),
+
+                       status = plugin_register_complex_read (/* group = */ NULL,
+                                       /* name      = */ callback_name,
+                                       /* callback  = */ cldap_read_host,
+                                       /* interval  = */ 0,
+                                       /* user_data = */ &ud);
+               }
        }
 
        if (status != 0)
@@ -650,10 +686,9 @@ static int cldap_config_add (oconfig_item_t *ci) /* {{{ */
 
 static int cldap_config (oconfig_item_t *ci) /* {{{ */
 {
-       int i;
        int status = 0;
 
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
 
@@ -681,10 +716,22 @@ static int cldap_init (void) /* {{{ */
        return (0);
 } /* }}} int cldap_init */
 
+static int cldap_shutdown (void) /* {{{ */
+{
+       for (size_t i = 0; i < databases_num; i++)
+               if (databases[i]->ld != NULL)
+                       ldap_unbind_ext_s (databases[i]->ld, NULL, NULL);
+       sfree (databases);
+       databases_num = 0;
+
+       return (0);
+} /* }}} int cldap_shutdown */
+
 void module_register (void) /* {{{ */
 {
        plugin_register_complex_config ("openldap", cldap_config);
        plugin_register_init ("openldap", cldap_init);
+       plugin_register_shutdown ("openldap", cldap_shutdown);
 } /* }}} void module_register */
 
 #if defined(__APPLE__)
index 93c8f1b..00ae736 100644 (file)
@@ -26,6 +26,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -95,7 +96,8 @@ static int openvpn_strsplit (char *string, char **fields, size_t size)
 } /* int openvpn_strsplit */
 
 /* dispatches number of users */
-static void numusers_submit (char *pinst, char *tinst, gauge_t value)
+static void numusers_submit (const char *pinst, const char *tinst,
+               gauge_t value)
 {
        value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
@@ -115,8 +117,10 @@ static void numusers_submit (char *pinst, char *tinst, gauge_t value)
        plugin_dispatch_values (&vl);
 } /* void numusers_submit */
 
-/* dispatches stats about traffic (TCP or UDP) generated by the tunnel per single endpoint */
-static void iostats_submit (char *pinst, char *tinst, derive_t rx, derive_t tx)
+/* dispatches stats about traffic (TCP or UDP) generated by the tunnel
+ * per single endpoint */
+static void iostats_submit (const char *pinst, const char *tinst,
+               derive_t rx, derive_t tx)
 {
        value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
@@ -145,7 +149,7 @@ static void iostats_submit (char *pinst, char *tinst, derive_t rx, derive_t tx)
 } /* void traffic_submit */
 
 /* dispatches stats about data compression shown when in single mode */
-static void compression_submit (char *pinst, char *tinst,
+static void compression_submit (const char *pinst, const char *tinst,
                derive_t uncompressed, derive_t compressed)
 {
        value_t values[2];
@@ -168,7 +172,7 @@ static void compression_submit (char *pinst, char *tinst,
        plugin_dispatch_values (&vl);
 } /* void compression_submit */
 
-static int single_read (char *name, FILE *fh)
+static int single_read (const char *name, FILE *fh)
 {
        char buffer[1024];
        char *fields[4];
@@ -261,7 +265,7 @@ static int single_read (char *name, FILE *fh)
 } /* int single_read */
 
 /* for reading status version 1 */
-static int multi1_read (char *name, FILE *fh)
+static int multi1_read (const char *name, FILE *fh)
 {
        char buffer[1024];
        char *fields[10];
@@ -324,7 +328,7 @@ static int multi1_read (char *name, FILE *fh)
 } /* int multi1_read */
 
 /* for reading status version 2 */
-static int multi2_read (char *name, FILE *fh)
+static int multi2_read (const char *name, FILE *fh)
 {
        char buffer[1024];
        char *fields[10];
@@ -386,7 +390,7 @@ static int multi2_read (char *name, FILE *fh)
 } /* int multi2_read */
 
 /* for reading status version 3 */
-static int multi3_read (char *name, FILE *fh)
+static int multi3_read (const char *name, FILE *fh)
 {
        char buffer[1024];
        char *fields[15];
@@ -451,7 +455,7 @@ static int multi3_read (char *name, FILE *fh)
 } /* int multi3_read */
 
 /* for reading status version 4 */
-static int multi4_read (char *name, FILE *fh)
+static int multi4_read (const char *name, FILE *fh)
 {
        char buffer[1024];
        char *fields[11];
@@ -518,12 +522,12 @@ static int multi4_read (char *name, FILE *fh)
 static int openvpn_read (void)
 {
        FILE *fh;
-       int  i, read;
+       int  read;
 
        read = 0;
 
        /* call the right read function for every status entry in the list */
-       for (i = 0; i < vpn_num; i++)
+       for (int i = 0; i < vpn_num; i++)
        {
                int vpn_read = 0;
 
@@ -647,7 +651,7 @@ static int openvpn_config (const char *key, const char *value)
        if (strcasecmp ("StatusFile", key) == 0)
        {
                char    *status_file, *status_name, *filename;
-               int     status_version, i;
+               int     status_version;
                vpn_status_t *temp;
 
                /* try to detect the status file format */
@@ -683,7 +687,7 @@ static int openvpn_config (const char *key, const char *value)
                }
 
                /* scan the list looking for a clone */
-               for (i = 0; i < vpn_num; i++)
+               for (int i = 0; i < vpn_num; i++)
                {
                        if (strcasecmp (vpn_list[i]->name, status_name) == 0)
                        {
@@ -696,7 +700,7 @@ static int openvpn_config (const char *key, const char *value)
                }
 
                /* create a new vpn element since file, version and name are ok */
-               temp = (vpn_status_t *) malloc (sizeof (vpn_status_t));
+               temp = malloc (sizeof (*temp));
                if (temp == NULL)
                {
                        char errbuf[1024];
@@ -709,17 +713,19 @@ static int openvpn_config (const char *key, const char *value)
                temp->version = status_version;
                temp->name = status_name;
 
-               vpn_list = (vpn_status_t **) realloc (vpn_list, (vpn_num + 1) * sizeof (vpn_status_t *));
-               if (vpn_list == NULL)
+               vpn_status_t **tmp_list = realloc (vpn_list, (vpn_num + 1) * sizeof (*vpn_list));
+               if (tmp_list == NULL)
                {
                        char errbuf[1024];
                        ERROR ("openvpn plugin: realloc failed: %s",
                                        sstrerror (errno, errbuf, sizeof (errbuf)));
 
+                       sfree (vpn_list);
                        sfree (temp->file);
                        sfree (temp);
                        return (1);
                }
+               vpn_list = tmp_list;
 
                vpn_list[vpn_num] = temp;
                vpn_num++;
@@ -772,9 +778,7 @@ static int openvpn_config (const char *key, const char *value)
 /* shutdown callback */
 static int openvpn_shutdown (void)
 {
-       int i;
-
-       for (i = 0; i < vpn_num; i++)
+       for (int i = 0; i < vpn_num; i++)
        {
                sfree (vpn_list[i]->file);
                sfree (vpn_list[i]);
index ab0812b..1554830 100644 (file)
@@ -46,6 +46,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -93,7 +94,6 @@ static void o_report_error (const char *where, /* {{{ */
   char buffer[2048];
   sb4 error_code;
   int status;
-  unsigned int record_number;
 
   if (db_name == NULL)
     db_name = "(none)";
@@ -102,7 +102,7 @@ static void o_report_error (const char *where, /* {{{ */
 
   /* An operation may cause / return multiple errors. Loop until we have
    * handled all errors available (with a fail-save limit of 16). */
-  for (record_number = 1; record_number <= 16; record_number++)
+  for (unsigned int record_number = 1; record_number <= 16; record_number++)
   {
     memset (buffer, 0, sizeof (buffer));
     error_code = -1;
@@ -144,8 +144,6 @@ static void o_report_error (const char *where, /* {{{ */
 
 static void o_database_free (o_database_t *db) /* {{{ */
 {
-  size_t i;
-
   if (db == NULL)
     return;
 
@@ -156,7 +154,7 @@ static void o_database_free (o_database_t *db) /* {{{ */
   sfree (db->queries);
 
   if (db->q_prep_areas != NULL)
-    for (i = 0; i < db->queries_num; ++i)
+    for (size_t i = 0; i < db->queries_num; ++i)
       udb_query_delete_preparation_area (db->q_prep_areas[i]);
   free (db->q_prep_areas);
 
@@ -174,7 +172,7 @@ static void o_database_free (o_database_t *db) /* {{{ */
  *       ValuesFrom "value"
  *     </Result>
  *   </Query>
- *     
+ *
  *   <Database "plugin_instance1">
  *     ConnectID "db01"
  *     Username "oracle"
@@ -188,7 +186,6 @@ static int o_config_add_database (oconfig_item_t *ci) /* {{{ */
 {
   o_database_t *db;
   int status;
-  int i;
 
   if ((ci->values_num != 1)
       || (ci->values[0].type != OCONFIG_TYPE_STRING))
@@ -198,13 +195,12 @@ static int o_config_add_database (oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  db = (o_database_t *) malloc (sizeof (*db));
+  db = calloc (1, sizeof (*db));
   if (db == NULL)
   {
-    ERROR ("oracle plugin: malloc failed.");
+    ERROR ("oracle plugin: calloc failed.");
     return (-1);
   }
-  memset (db, 0, sizeof (*db));
   db->name = NULL;
   db->host = NULL;
   db->connect_id = NULL;
@@ -219,7 +215,7 @@ static int o_config_add_database (oconfig_item_t *ci) /* {{{ */
   }
 
   /* Fill the `o_database_t' structure.. */
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -273,12 +269,12 @@ static int o_config_add_database (oconfig_item_t *ci) /* {{{ */
 
     if (db->q_prep_areas == NULL)
     {
-      WARNING ("oracle plugin: malloc failed");
+      WARNING ("oracle plugin: calloc failed");
       status = -1;
       break;
     }
 
-    for (i = 0; i < db->queries_num; ++i)
+    for (int i = 0; i < db->queries_num; ++i)
     {
       db->q_prep_areas[i]
         = udb_query_allocate_preparation_area (db->queries[i]);
@@ -300,7 +296,7 @@ static int o_config_add_database (oconfig_item_t *ci) /* {{{ */
   {
     o_database_t **temp;
 
-    temp = (o_database_t **) realloc (databases,
+    temp = realloc (databases,
         sizeof (*databases) * (databases_num + 1));
     if (temp == NULL)
     {
@@ -326,9 +322,7 @@ static int o_config_add_database (oconfig_item_t *ci) /* {{{ */
 
 static int o_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
     if (strcasecmp ("Query", child->key) == 0)
@@ -400,7 +394,6 @@ static int o_read_database_query (o_database_t *db, /* {{{ */
   OCIDefine **oci_defines;
 
   int status;
-  size_t i;
 
   oci_statement = udb_query_get_user_data (q);
 
@@ -463,7 +456,7 @@ static int o_read_database_query (o_database_t *db, /* {{{ */
   {
     ub4 param_counter = 0;
     status = OCIAttrGet (oci_statement, OCI_HTYPE_STMT, /* {{{ */
-        &param_counter, /* size pointer = */ NULL, 
+        &param_counter, /* size pointer = */ NULL,
         OCI_ATTR_PARAM_COUNT, oci_error);
     if (status != OCI_SUCCESS)
     {
@@ -476,7 +469,7 @@ static int o_read_database_query (o_database_t *db, /* {{{ */
   } while (0); /* }}} */
 
   /* Allocate the following buffers:
-   * 
+   *
    *  +---------------+-----------------------------------+
    *  ! Name          ! Size                              !
    *  +---------------+-----------------------------------+
@@ -502,13 +495,12 @@ static int o_read_database_query (o_database_t *db, /* {{{ */
 #define ALLOC_OR_FAIL(ptr, ptr_size) \
   do { \
     size_t alloc_size = (size_t) ((ptr_size)); \
-    (ptr) = malloc (alloc_size); \
+    (ptr) = calloc (1, alloc_size); \
     if ((ptr) == NULL) { \
       FREE_ALL; \
-      ERROR ("oracle plugin: o_read_database_query: malloc failed."); \
+      ERROR ("oracle plugin: o_read_database_query: calloc failed."); \
       return (-1); \
     } \
-    memset ((ptr), 0, alloc_size); \
   } while (0)
 
   /* Initialize everything to NULL so the above works. */
@@ -519,13 +511,13 @@ static int o_read_database_query (o_database_t *db, /* {{{ */
   ALLOC_OR_FAIL (column_names, column_num * sizeof (char *));
   ALLOC_OR_FAIL (column_names[0], column_num * DATA_MAX_NAME_LEN
       * sizeof (char));
-  for (i = 1; i < column_num; i++)
+  for (size_t i = 1; i < column_num; i++)
     column_names[i] = column_names[i - 1] + DATA_MAX_NAME_LEN;
 
   ALLOC_OR_FAIL (column_values, column_num * sizeof (char *));
   ALLOC_OR_FAIL (column_values[0], column_num * DATA_MAX_NAME_LEN
       * sizeof (char));
-  for (i = 1; i < column_num; i++)
+  for (size_t i = 1; i < column_num; i++)
     column_values[i] = column_values[i - 1] + DATA_MAX_NAME_LEN;
 
   ALLOC_OR_FAIL (oci_defines, column_num * sizeof (OCIDefine *));
@@ -533,7 +525,7 @@ static int o_read_database_query (o_database_t *db, /* {{{ */
 
   /* ``Define'' the returned data, i. e. bind the columns to the buffers
    * allocated above. */
-  for (i = 0; i < column_num; i++) /* {{{ */
+  for (size_t i = 0; i < column_num; i++) /* {{{ */
   {
     char *column_name;
     ub4 column_name_length;
@@ -644,7 +636,6 @@ static int o_read_database_query (o_database_t *db, /* {{{ */
 
 static int o_read_database (o_database_t *db) /* {{{ */
 {
-  size_t i;
   int status;
 
   if (db->oci_service_context != NULL)
@@ -653,7 +644,7 @@ static int o_read_database (o_database_t *db) /* {{{ */
     ub4 connection_status;
 
     server_handle = NULL;
-    status = OCIAttrGet ((void *) db->oci_service_context, OCI_HTYPE_SVCCTX, 
+    status = OCIAttrGet ((void *) db->oci_service_context, OCI_HTYPE_SVCCTX,
         (void *) &server_handle, /* size pointer = */ NULL,
         OCI_ATTR_SERVER, oci_error);
     if (status != OCI_SUCCESS)
@@ -719,7 +710,7 @@ static int o_read_database (o_database_t *db) /* {{{ */
   DEBUG ("oracle plugin: o_read_database: db->connect_id = %s; db->oci_service_context = %p;",
       db->connect_id, db->oci_service_context);
 
-  for (i = 0; i < db->queries_num; i++)
+  for (size_t i = 0; i < db->queries_num; i++)
     o_read_database_query (db, db->queries[i], db->q_prep_areas[i]);
 
   return (0);
@@ -745,7 +736,7 @@ static int o_shutdown (void) /* {{{ */
       OCIHandleFree (databases[i]->oci_service_context, OCI_HTYPE_SVCCTX);
       databases[i]->oci_service_context = NULL;
     }
-  
+
   for (i = 0; i < queries_num; i++)
   {
     OCIStmt *oci_statement;
@@ -757,7 +748,7 @@ static int o_shutdown (void) /* {{{ */
       udb_query_set_user_data (queries[i], NULL);
     }
   }
-  
+
   OCIHandleFree (oci_env, OCI_HTYPE_ENV);
   oci_env = NULL;
 
index 82b9b8c..48374b6 100644 (file)
@@ -34,6 +34,7 @@
 
 #define DONT_POISON_SPRINTF_YET 1
 #include "collectd.h"
+
 #undef DONT_POISON_SPRINTF_YET
 
 #include "configfile.h"
@@ -63,8 +64,6 @@
 
 #include "filter_chain.h"
 
-#include <pthread.h>
-
 #if !defined(USE_ITHREADS)
 # error "Perl does not support ithreads!"
 #endif /* !defined(USE_ITHREADS) */
@@ -305,33 +304,31 @@ static int hv2data_source (pTHX_ HV *hash, data_source_t *ds)
        return 0;
 } /* static int hv2data_source (HV *, data_source_t *) */
 
-static int av2value (pTHX_ char *name, AV *array, value_t *value, int len)
+/* av2value converts at most "len" elements from "array" to "value". Returns the
+ * number of elements converted or zero on error. */
+static size_t av2value (pTHX_ char *name, AV *array, value_t *value, size_t array_len)
 {
        const data_set_t *ds;
 
-       int i = 0;
-
-       if ((NULL == name) || (NULL == array) || (NULL == value))
-               return -1;
-
-       if (av_len (array) < len - 1)
-               len = av_len (array) + 1;
-
-       if (0 >= len)
-               return -1;
+       if ((NULL == name) || (NULL == array) || (NULL == value) || (array_len == 0))
+               return 0;
 
        ds = plugin_get_ds (name);
        if (NULL == ds) {
                log_err ("av2value: Unknown dataset \"%s\"", name);
-               return -1;
+               return 0;
        }
 
-       if (ds->ds_num < len) {
-               log_warn ("av2value: Value length exceeds data set length.");
-               len = ds->ds_num;
+       if (array_len < ds->ds_num) {
+               log_warn ("av2value: array does not contain enough elements for type \"%s\": got %zu, want %zu",
+                               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",
+                               name, array_len, ds->ds_num);
        }
 
-       for (i = 0; i < len; ++i) {
+       for (size_t i = 0; i < ds->ds_num; ++i) {
                SV **tmp = av_fetch (array, i, 0);
 
                if (NULL != tmp) {
@@ -345,11 +342,12 @@ static int av2value (pTHX_ char *name, AV *array, value_t *value, int len)
                                value[i].absolute = SvIV (*tmp);
                }
                else {
-                       return -1;
+                       return 0;
                }
        }
-       return len;
-} /* static int av2value (char *, AV *, value_t *, int) */
+
+       return ds->ds_num;
+} /* static size_t av2value (char *, AV *, value_t *, size_t) */
 
 /*
  * value list:
@@ -384,16 +382,14 @@ static int hv2value_list (pTHX_ HV *hash, value_list_t *vl)
 
        {
                AV  *array = (AV *)SvRV (*tmp);
-               int len    = av_len (array) + 1;
-
-               if (len <= 0)
+               /* av_len returns the highest index, not the actual length. */
+               size_t array_len = (size_t) (av_len (array) + 1);
+               if (array_len == 0)
                        return -1;
 
-               vl->values     = (value_t *)smalloc (len * sizeof (value_t));
-               vl->values_len = av2value (aTHX_ vl->type, (AV *)SvRV (*tmp),
-                               vl->values, len);
-
-               if (-1 == vl->values_len) {
+               vl->values     = calloc (array_len, sizeof (*vl->values));
+               vl->values_len = av2value (aTHX_ vl->type, (AV *)SvRV (*tmp), vl->values, array_len);
+               if (vl->values_len == 0) {
                        sfree (vl->values);
                        return -1;
                }
@@ -431,7 +427,7 @@ static int hv2value_list (pTHX_ HV *hash, value_list_t *vl)
 
 static int av2data_set (pTHX_ AV *array, char *name, data_set_t *ds)
 {
-       int len, i;
+       int len;
 
        if ((NULL == array) || (NULL == name) || (NULL == ds))
                return -1;
@@ -443,10 +439,10 @@ static int av2data_set (pTHX_ AV *array, char *name, data_set_t *ds)
                return -1;
        }
 
-       ds->ds = (data_source_t *)smalloc ((len + 1) * sizeof (data_source_t));
+       ds->ds = smalloc ((len + 1) * sizeof (*ds->ds));
        ds->ds_num = len + 1;
 
-       for (i = 0; i <= len; ++i) {
+       for (int i = 0; i <= len; ++i) {
                SV **elem = av_fetch (array, i, 0);
 
                if (NULL == elem) {
@@ -490,9 +486,8 @@ static int av2notification_meta (pTHX_ AV *array, notification_meta_t **meta)
        notification_meta_t **m = meta;
 
        int len = av_len (array);
-       int i;
 
-       for (i = 0; i <= len; ++i) {
+       for (int i = 0; i <= len; ++i) {
                SV **tmp = av_fetch (array, i, 0);
                HV  *hash;
 
@@ -507,7 +502,7 @@ static int av2notification_meta (pTHX_ AV *array, notification_meta_t **meta)
 
                hash = (HV *)SvRV (*tmp);
 
-               *m = (notification_meta_t *)smalloc (sizeof (**m));
+               *m = smalloc (sizeof (**m));
 
                if (NULL == (tmp = hv_fetch (hash, "name", 4, 0))) {
                        log_warn ("av2notification_meta: Skipping invalid "
@@ -608,14 +603,12 @@ static int hv2notification (pTHX_ HV *hash, notification_t *n)
 
 static int data_set2av (pTHX_ data_set_t *ds, AV *array)
 {
-       int i = 0;
-
        if ((NULL == ds) || (NULL == array))
                return -1;
 
        av_extend (array, ds->ds_num);
 
-       for (i = 0; i < ds->ds_num; ++i) {
+       for (size_t i = 0; i < ds->ds_num; ++i) {
                HV *source = newHV ();
 
                if (NULL == hv_store (source, "name", 4,
@@ -644,24 +637,17 @@ static int data_set2av (pTHX_ data_set_t *ds, AV *array)
 static int value_list2hv (pTHX_ value_list_t *vl, data_set_t *ds, HV *hash)
 {
        AV *values = NULL;
-
-       int i   = 0;
-       int len = 0;
+       size_t i;
 
        if ((NULL == vl) || (NULL == ds) || (NULL == hash))
                return -1;
 
-       len = vl->values_len;
-
-       if (ds->ds_num < len) {
-               log_warn ("value2av: Value length exceeds data set length.");
-               len = ds->ds_num;
-       }
-
        values = newAV ();
-       av_extend (values, len - 1);
+       /* av_extend takes the last *index* to which the array should be extended. */
+       av_extend (values, vl->values_len - 1);
 
-       for (i = 0; i < len; ++i) {
+       assert (ds->ds_num == vl->values_len);
+       for (i = 0; i < vl->values_len; ++i) {
                SV *val = NULL;
 
                if (DS_TYPE_COUNTER == ds->ds[i].type)
@@ -722,7 +708,6 @@ 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;
-       int i;
 
        while (meta) {
                ++meta_num;
@@ -731,7 +716,7 @@ static int notification_meta2av (pTHX_ notification_meta_t *meta, AV *array)
 
        av_extend (array, meta_num);
 
-       for (i = 0; NULL != meta; meta = meta->next, ++i) {
+       for (int i = 0; NULL != meta; meta = meta->next, ++i) {
                HV *m = newHV ();
                SV *value;
 
@@ -818,8 +803,6 @@ static int notification2hv (pTHX_ notification_t *n, HV *hash)
 
 static int oconfig_item2hv (pTHX_ oconfig_item_t *ci, HV *hash)
 {
-       int i;
-
        AV *values;
        AV *children;
 
@@ -836,7 +819,7 @@ static int oconfig_item2hv (pTHX_ oconfig_item_t *ci, HV *hash)
                return -1;
        }
 
-       for (i = 0; i < ci->values_num; ++i) {
+       for (int i = 0; i < ci->values_num; ++i) {
                SV *value;
 
                switch (ci->values[i].type) {
@@ -873,7 +856,7 @@ static int oconfig_item2hv (pTHX_ oconfig_item_t *ci, HV *hash)
                return -1;
        }
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                HV *child = newHV ();
 
                if (0 != oconfig_item2hv (aTHX_ ci->children + i, child)) {
@@ -994,15 +977,13 @@ static int pplugin_write (pTHX_ const char *plugin, AV *data_set, HV *values)
  */
 static int pplugin_dispatch_notification (pTHX_ HV *notif)
 {
-       notification_t n;
+       notification_t n = { 0 };
 
        int ret;
 
        if (NULL == notif)
                return -1;
 
-       memset (&n, 0, sizeof (n));
-
        if (0 != hv2notification (aTHX_ notif, &n))
                return -1;
 
@@ -1257,7 +1238,7 @@ static c_ithread_t *c_ithread_create (PerlInterpreter *base)
 
        assert (NULL != perl_threads);
 
-       t = (c_ithread_t *)smalloc (sizeof (c_ithread_t));
+       t = smalloc (sizeof (*t));
        memset (t, 0, sizeof (c_ithread_t));
 
        t->interp = (NULL == base)
@@ -1470,7 +1451,7 @@ static int fc_create (int type, const oconfig_item_t *ci, void **user_data)
                return -1;
        }
 
-       data = (pfc_user_data_t *)smalloc (sizeof (*data));
+       data = smalloc (sizeof (*data));
        data->name      = sstrdup (ci->values[0].value.string);
        data->user_data = newSV (0);
 
@@ -2121,9 +2102,8 @@ static int perl_flush (cdtime_t timeout, const char *identifier,
 
 static int perl_shutdown (void)
 {
-       c_ithread_t *t = NULL;
-
-       int ret = 0;
+       c_ithread_t *t;
+       int ret;
 
        dTHX;
 
@@ -2133,8 +2113,6 @@ static int perl_shutdown (void)
                return 0;
 
        if (NULL == aTHX) {
-               t = NULL;
-
                pthread_mutex_lock (&perl_threads->mutex);
                t = c_ithread_create (perl_threads->head->interp);
                pthread_mutex_unlock (&perl_threads->mutex);
@@ -2254,21 +2232,19 @@ static void xs_init (pTHX)
        SV   *tmp   = NULL;
        char *file  = __FILE__;
 
-       int i = 0;
-
        dXSUB_SYS;
 
        /* enable usage of Perl modules using shared libraries */
        newXS ("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
 
        /* register API */
-       for (i = 0; NULL != api[i].f; ++i)
+       for (int i = 0; NULL != api[i].f; ++i)
                newXS (api[i].name, api[i].f, file);
 
        stash = gv_stashpv ("Collectd", 1);
 
        /* export "constants" */
-       for (i = 0; '\0' != constants[i].name[0]; ++i)
+       for (int i = 0; '\0' != constants[i].name[0]; ++i)
                newCONSTSUB (stash, constants[i].name, newSViv (constants[i].value));
 
        /* export global variables
@@ -2277,7 +2253,7 @@ static void xs_init (pTHX)
         * accessing any such variable (this is basically the same as using
         * tie() in Perl) */
        /* global strings */
-       for (i = 0; '\0' != g_strings[i].name[0]; ++i) {
+       for (int i = 0; '\0' != g_strings[i].name[0]; ++i) {
                tmp = get_sv (g_strings[i].name, 1);
                sv_magicext (tmp, NULL, PERL_MAGIC_ext, &g_pv_vtbl,
                                g_strings[i].var, 0);
@@ -2302,9 +2278,7 @@ static int init_pi (int argc, char **argv)
        log_info ("Initializing Perl interpreter...");
 #if COLLECT_DEBUG
        {
-               int i = 0;
-
-               for (i = 0; i < argc; ++i)
+               for (int i = 0; i < argc; ++i)
                        log_debug ("argv[%i] = \"%s\"", i, argv[i]);
        }
 #endif /* COLLECT_DEBUG */
@@ -2323,7 +2297,7 @@ static int init_pi (int argc, char **argv)
 #endif
        PERL_SYS_INIT3 (&argc, &argv, &environ);
 
-       perl_threads = (c_ithread_list_t *)smalloc (sizeof (c_ithread_list_t));
+       perl_threads = smalloc (sizeof (*perl_threads));
        memset (perl_threads, 0, sizeof (c_ithread_list_t));
 
        pthread_mutexattr_init(&perl_threads->mutexattr);
@@ -2455,7 +2429,7 @@ static int perl_config_enabledebugger (pTHX_ oconfig_item_t *ci)
 
        value = ci->values[0].value.string;
 
-       perl_argv = (char **)realloc (perl_argv,
+       perl_argv = realloc (perl_argv,
                        (++perl_argc + 1) * sizeof (char *));
 
        if (NULL == perl_argv) {
@@ -2467,7 +2441,7 @@ static int perl_config_enabledebugger (pTHX_ oconfig_item_t *ci)
                perl_argv[perl_argc - 1] = "-d";
        }
        else {
-               perl_argv[perl_argc - 1] = (char *)smalloc (strlen (value) + 4);
+               perl_argv[perl_argc - 1] = smalloc (strlen (value) + 4);
                sstrncpy (perl_argv[perl_argc - 1], "-d:", 4);
                sstrncpy (perl_argv[perl_argc - 1] + 3, value, strlen (value) + 1);
        }
@@ -2492,7 +2466,7 @@ static int perl_config_includedir (pTHX_ oconfig_item_t *ci)
        value = ci->values[0].value.string;
 
        if (NULL == aTHX) {
-               perl_argv = (char **)realloc (perl_argv,
+               perl_argv = realloc (perl_argv,
                                (++perl_argc + 1) * sizeof (char *));
 
                if (NULL == perl_argv) {
@@ -2500,7 +2474,7 @@ static int perl_config_includedir (pTHX_ oconfig_item_t *ci)
                        exit (3);
                }
 
-               perl_argv[perl_argc - 1] = (char *)smalloc (strlen (value) + 3);
+               perl_argv[perl_argc - 1] = smalloc (strlen (value) + 3);
                sstrncpy(perl_argv[perl_argc - 1], "-I", 3);
                sstrncpy(perl_argv[perl_argc - 1] + 2, value, strlen (value) + 1);
 
@@ -2573,11 +2547,10 @@ static int perl_config_plugin (pTHX_ oconfig_item_t *ci)
 static int perl_config (oconfig_item_t *ci)
 {
        int status = 0;
-       int i = 0;
 
        dTHXa (NULL);
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *c = ci->children + i;
                int current_status = 0;
 
@@ -2618,7 +2591,7 @@ static int perl_config (oconfig_item_t *ci)
 void module_register (void)
 {
        perl_argc = 4;
-       perl_argv = (char **)smalloc ((perl_argc + 1) * sizeof (char *));
+       perl_argv = smalloc ((perl_argc + 1) * sizeof (*perl_argv));
 
        /* default options for the Perl interpreter */
        perl_argv[0] = "";
index 112e28f..d7a5a15 100644 (file)
--- a/src/pf.c
+++ b/src/pf.c
  */
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 
 #if HAVE_SYS_IOCTL_H
 # include <sys/ioctl.h>
 #endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
 #if HAVE_NET_IF_H
 # include <net/if.h>
 #endif
@@ -85,7 +83,6 @@ static int pf_read (void)
        struct pf_status state;
        int fd;
        int status;
-       int i;
 
        fd = open (pf_device, O_RDONLY);
        if (fd < 0)
@@ -97,7 +94,6 @@ static int pf_read (void)
                return (-1);
        }
 
-       memset (&state, 0, sizeof (state));
        status = ioctl (fd, DIOCGETSTATUS, &state);
        if (status != 0)
        {
@@ -109,7 +105,6 @@ static int pf_read (void)
        }
 
        close (fd);
-       fd = -1;
 
        if (!state.running)
        {
@@ -117,16 +112,16 @@ static int pf_read (void)
                return (-1);
        }
 
-       for (i = 0; i < PFRES_MAX; i++)
+       for (int i = 0; i < PFRES_MAX; i++)
                pf_submit ("pf_counters", pf_reasons[i], state.counters[i],
                                /* is gauge = */ 0);
-       for (i = 0; i < LCNT_MAX; i++)
+       for (int i = 0; i < LCNT_MAX; i++)
                pf_submit ("pf_limits", pf_lcounters[i], state.lcounters[i],
                                /* is gauge = */ 0);
-       for (i = 0; i < FCNT_MAX; i++)
+       for (int i = 0; i < FCNT_MAX; i++)
                pf_submit ("pf_state", pf_fcounters[i], state.fcounters[i],
                                /* is gauge = */ 0);
-       for (i = 0; i < SCNT_MAX; i++)
+       for (int i = 0; i < SCNT_MAX; i++)
                pf_submit ("pf_source", pf_scounters[i], state.scounters[i],
                                /* is gauge = */ 0);
 
index e94ad8f..b9eed68 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
-#include <pthread.h>
-#include <sys/socket.h>
 #include <netdb.h>
 #include <poll.h>
 
@@ -172,7 +171,7 @@ static void service_statnode_add(const char *name, /* {{{ */
     const char *script)
 {
   pinba_statnode_t *node;
-  
+
   node = realloc (stat_nodes,
       sizeof (*stat_nodes) * (stat_nodes_num + 1));
   if (node == NULL)
@@ -184,7 +183,7 @@ static void service_statnode_add(const char *name, /* {{{ */
 
   node = stat_nodes + stat_nodes_num;
   memset (node, 0, sizeof (*node));
-  
+
   /* reset strings */
   node->name   = NULL;
   node->host   = NULL;
@@ -192,13 +191,13 @@ static void service_statnode_add(const char *name, /* {{{ */
   node->script = NULL;
 
   node->mem_peak = NAN;
-  
+
   /* fill query data */
   strset (&node->name, name);
   strset (&node->host, host);
   strset (&node->server, server);
   strset (&node->script, script);
-  
+
   /* increment counter */
   stat_nodes_num++;
 } /* }}} void service_statnode_add */
@@ -210,14 +209,14 @@ static unsigned int service_statnode_collect (pinba_statnode_t *res, /* {{{ */
     unsigned int index)
 {
   pinba_statnode_t *node;
-  
+
   if (stat_nodes_num == 0)
     return 0;
-  
+
   /* begin collecting */
   if (index == 0)
     pthread_mutex_lock (&stat_nodes_lock);
-  
+
   /* end collecting */
   if (index >= stat_nodes_num)
   {
@@ -230,7 +229,7 @@ static unsigned int service_statnode_collect (pinba_statnode_t *res, /* {{{ */
 
   /* reset node */
   node->mem_peak = NAN;
-  
+
   return (index + 1);
 } /* }}} unsigned int service_statnode_collect */
 
@@ -253,11 +252,9 @@ static void service_statnode_process (pinba_statnode_t *node, /* {{{ */
 
 static void service_process_request (Pinba__Request *request) /* {{{ */
 {
-  unsigned int i;
-
   pthread_mutex_lock (&stat_nodes_lock);
-  
-  for (i = 0; i < stat_nodes_num; i++)
+
+  for (unsigned int i = 0; i < stat_nodes_num; i++)
   {
     if ((stat_nodes[i].host != NULL)
         && (strcmp (request->hostname, stat_nodes[i].host) != 0))
@@ -273,7 +270,7 @@ static void service_process_request (Pinba__Request *request) /* {{{ */
 
     service_statnode_process(&stat_nodes[i], request);
   }
-  
+
   pthread_mutex_unlock(&stat_nodes_lock);
 } /* }}} void service_process_request */
 
@@ -353,25 +350,20 @@ static pinba_socket_t *pinba_socket_open (const char *node, /* {{{ */
 {
   pinba_socket_t *s;
   struct addrinfo *ai_list;
-  struct addrinfo *ai_ptr;
-  struct addrinfo  ai_hints;
   int status;
 
-  memset (&ai_hints, 0, sizeof (ai_hints));
-  ai_hints.ai_flags = AI_PASSIVE;
-  ai_hints.ai_family = AF_UNSPEC;
-  ai_hints.ai_socktype = SOCK_DGRAM;
-  ai_hints.ai_addr = NULL;
-  ai_hints.ai_canonname = NULL;
-  ai_hints.ai_next = NULL;
-
   if (node == NULL)
     node = PINBA_DEFAULT_NODE;
 
   if (service == NULL)
     service = PINBA_DEFAULT_SERVICE;
 
-  ai_list = NULL;
+  struct addrinfo  ai_hints = {
+    .ai_family = AF_UNSPEC,
+    .ai_flags = AI_PASSIVE,
+    .ai_socktype = SOCK_DGRAM
+  };
+
   status = getaddrinfo (node, service,
       &ai_hints, &ai_list);
   if (status != 0)
@@ -382,22 +374,21 @@ static pinba_socket_t *pinba_socket_open (const char *node, /* {{{ */
   }
   assert (ai_list != NULL);
 
-  s = malloc (sizeof (*s));
+  s = calloc (1, sizeof (*s));
   if (s == NULL)
   {
     freeaddrinfo (ai_list);
-    ERROR ("pinba plugin: malloc failed.");
+    ERROR ("pinba plugin: calloc failed.");
     return (NULL);
   }
-  memset (s, 0, sizeof (*s));
 
-  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
   {
     status = pb_add_socket (s, ai_ptr);
     if (status != 0)
       break;
   } /* for (ai_list) */
-  
+
   freeaddrinfo (ai_list);
 
   if (s->fd_num < 1)
@@ -412,35 +403,33 @@ static pinba_socket_t *pinba_socket_open (const char *node, /* {{{ */
 
 static void pinba_socket_free (pinba_socket_t *socket) /* {{{ */
 {
-  nfds_t i;
-
   if (!socket)
     return;
-  
-  for (i = 0; i < socket->fd_num; i++)
+
+  for (nfds_t i = 0; i < socket->fd_num; i++)
   {
     if (socket->fd[i].fd < 0)
       continue;
     close (socket->fd[i].fd);
     socket->fd[i].fd = -1;
   }
-  
+
   sfree(socket);
 } /* }}} void pinba_socket_free */
 
 static int pinba_process_stats_packet (const uint8_t *buffer, /* {{{ */
     size_t buffer_size)
 {
-  Pinba__Request *request;  
-  
+  Pinba__Request *request;
+
   request = pinba__request__unpack (NULL, buffer_size, buffer);
-  
+
   if (!request)
     return (-1);
 
   service_process_request(request);
   pinba__request__free_unpacked (request, NULL);
-    
+
   return (0);
 } /* }}} int pinba_process_stats_packet */
 
@@ -508,7 +497,6 @@ static int receive_loop (void) /* {{{ */
   while (!collector_thread_do_shutdown)
   {
     int status;
-    nfds_t i;
 
     if (s->fd_num < 1)
       break;
@@ -531,7 +519,7 @@ static int receive_loop (void) /* {{{ */
       return (-1);
     }
 
-    for (i = 0; i < s->fd_num; i++)
+    for (nfds_t i = 0; i < s->fd_num; i++)
     {
       if (s->fd[i].revents & (POLLERR | POLLHUP | POLLNVAL))
       {
@@ -571,13 +559,12 @@ static int pinba_config_view (const oconfig_item_t *ci) /* {{{ */
   char *server = NULL;
   char *script = NULL;
   int status;
-  int i;
 
   status = cf_util_get_string (ci, &name);
   if (status != 0)
     return (status);
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -610,13 +597,11 @@ static int pinba_config_view (const oconfig_item_t *ci) /* {{{ */
 
 static int plugin_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-  
   /* The lock should not be necessary in the config callback, but let's be
    * sure.. */
   pthread_mutex_lock (&stat_nodes_lock);
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -631,7 +616,7 @@ static int plugin_config (oconfig_item_t *ci) /* {{{ */
   }
 
   pthread_mutex_unlock(&stat_nodes_lock);
-  
+
   return (0);
 } /* }}} int pinba_config */
 
@@ -695,7 +680,7 @@ static int plugin_submit (const pinba_statnode_t *res) /* {{{ */
 {
   value_t value;
   value_list_t vl = VALUE_LIST_INIT;
-  
+
   vl.values = &value;
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
@@ -703,15 +688,15 @@ static int plugin_submit (const pinba_statnode_t *res) /* {{{ */
   sstrncpy (vl.plugin_instance, res->name, sizeof (vl.plugin_instance));
 
   value.derive = res->req_count;
-  sstrncpy (vl.type, "total_requests", sizeof (vl.type)); 
+  sstrncpy (vl.type, "total_requests", sizeof (vl.type));
   plugin_dispatch_values (&vl);
 
   value.derive = float_counter_get (&res->req_time, /* factor = */ 1000);
-  sstrncpy (vl.type, "total_time_in_ms", sizeof (vl.type)); 
+  sstrncpy (vl.type, "total_time_in_ms", sizeof (vl.type));
   plugin_dispatch_values (&vl);
 
   value.derive = res->doc_size;
-  sstrncpy (vl.type, "total_bytes", sizeof (vl.type)); 
+  sstrncpy (vl.type, "total_bytes", sizeof (vl.type));
   plugin_dispatch_values (&vl);
 
   value.derive = float_counter_get (&res->ru_utime, /* factor = */ 100);
@@ -736,12 +721,12 @@ static int plugin_read (void) /* {{{ */
 {
   unsigned int i=0;
   pinba_statnode_t data;
-  
+
   while ((i = service_statnode_collect (&data, i)) != 0)
   {
     plugin_submit (&data);
   }
-  
+
   return 0;
 } /* }}} int plugin_read */
 
index 5fd5439..22e61c6 100644 (file)
@@ -1,3 +1,5 @@
+syntax = "proto2";
+
 package Pinba;
 option optimize_for = SPEED;
 
index 5df82f4..52db2c7 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 #include "utils_complain.h"
 
-#include <pthread.h>
 #include <netinet/in.h>
 #if HAVE_NETDB_H
 # include <netdb.h> /* NI_MAXHOST */
 #endif
 
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
+
 #include <oping.h>
 
 #ifndef NI_MAXHOST
@@ -73,6 +77,7 @@ static char  *ping_source = NULL;
 #ifdef HAVE_OPING_1_3
 static char  *ping_device = NULL;
 #endif
+static char  *ping_data = NULL;
 static int    ping_ttl = PING_DEF_TTL;
 static double ping_interval = 1.0;
 static double ping_timeout = 0.9;
@@ -91,6 +96,7 @@ static const char *config_keys[] =
 #ifdef HAVE_OPING_1_3
   "Device",
 #endif
+  "Size",
   "TTL",
   "Interval",
   "Timeout",
@@ -150,11 +156,10 @@ static void time_calc (struct timespec *ts_dest, /* {{{ */
 
 static int ping_dispatch_all (pingobj_t *pingobj) /* {{{ */
 {
-  pingobj_iter_t *iter;
   hostlist_t *hl;
   int status;
 
-  for (iter = ping_iterator_get (pingobj);
+  for (pingobj_iter_t *iter = ping_iterator_get (pingobj);
       iter != NULL;
       iter = ping_iterator_next (iter))
   { /* {{{ */
@@ -210,7 +215,8 @@ static int ping_dispatch_all (pingobj_t *pingobj) /* {{{ */
       hl->pkg_missed++;
 
     /* if the host did not answer our last N packages, trigger a resolv. */
-    if (ping_max_missed >= 0 && hl->pkg_missed >= ping_max_missed)
+    if ((ping_max_missed >= 0)
+        && (hl->pkg_missed >= ((uint32_t) ping_max_missed)))
     { /* {{{ */
       /* we reset the missed package counter here, since we only want to
        * trigger a resolv every N packages and not every package _AFTER_ N
@@ -248,7 +254,6 @@ static void *ping_thread (void *arg) /* {{{ */
   struct timespec ts_wait;
   struct timespec ts_int;
 
-  hostlist_t *hl;
   int count;
 
   c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
@@ -279,9 +284,12 @@ static void *ping_thread (void *arg) /* {{{ */
   ping_setopt (pingobj, PING_OPT_TIMEOUT, (void *) &ping_timeout);
   ping_setopt (pingobj, PING_OPT_TTL, (void *) &ping_ttl);
 
+  if (ping_data != NULL)
+    ping_setopt (pingobj, PING_OPT_DATA, (void *) ping_data);
+
   /* Add all the hosts to the ping object. */
   count = 0;
-  for (hl = hostlist_head; hl != NULL; hl = hl->next)
+  for (hostlist_t *hl = hostlist_head; hl != NULL; hl = hl->next)
   {
     int tmp_status;
     tmp_status = ping_host_add (pingobj, hl->host);
@@ -444,6 +452,20 @@ static int ping_init (void) /* {{{ */
         "Will use a timeout of %gs.", ping_timeout);
   }
 
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_NET_RAW)
+  if (check_capability (CAP_NET_RAW) != 0)
+  {
+    if (getuid () == 0)
+      WARNING ("ping plugin: Running collectd as root, but the CAP_NET_RAW "
+          "capability is missing. The plugin's read function will probably "
+          "fail. Is your init system dropping capabilities?");
+    else
+      WARNING ("ping plugin: collectd doesn't have the CAP_NET_RAW capability. "
+          "If you don't want to run collectd as root, try running \"setcap "
+          "cap_net_raw=ep\" on the collectd binary.");
+  }
+#endif
+
   return (start_thread ());
 } /* }}} int ping_init */
 
@@ -474,7 +496,7 @@ static int ping_config (const char *key, const char *value) /* {{{ */
     hostlist_t *hl;
     char *host;
 
-    hl = (hostlist_t *) malloc (sizeof (hostlist_t));
+    hl = malloc (sizeof (*hl));
     if (hl == NULL)
     {
       char errbuf[1024];
@@ -535,6 +557,37 @@ static int ping_config (const char *key, const char *value) /* {{{ */
       WARNING ("ping plugin: Ignoring invalid interval %g (%s)",
           tmp, value);
   }
+  else if (strcasecmp (key, "Size") == 0) {
+    size_t size = (size_t) atoi (value);
+
+    /* Max IP packet size - (IPv6 + ICMP) = 65535 - (40 + 8) = 65487 */
+    if (size <= 65487)
+    {
+      sfree (ping_data);
+      ping_data = malloc (size + 1);
+      if (ping_data == NULL)
+      {
+        ERROR ("ping plugin: malloc failed.");
+        return (1);
+      }
+
+      /* Note: By default oping is using constant string
+       * "liboping -- ICMP ping library <http://octo.it/liboping/>"
+       * which is exactly 56 bytes.
+       *
+       * Optimally we would follow the ping(1) behaviour, but we
+       * cannot use byte 00 or start data payload at exactly same
+       * location, due to oping library limitations. */
+      for (size_t i = 0; i < size; i++) /* {{{ */
+      {
+        /* This restricts data pattern to be only composed of easily
+         * printable characters, and not NUL character. */
+        ping_data[i] = ('0' + i % 64);
+      }  /* }}} for (i = 0; i < size; i++) */
+      ping_data[size] = 0;
+    } else
+      WARNING ("ping plugin: Ignoring invalid Size %zu.", size);
+  }
   else if (strcasecmp (key, "Timeout") == 0)
   {
     double tmp;
@@ -581,15 +634,13 @@ static void submit (const char *host, const char *type, /* {{{ */
 
 static int ping_read (void) /* {{{ */
 {
-  hostlist_t *hl;
-
   if (ping_thread_error != 0)
   {
     ERROR ("ping plugin: The ping thread had a problem. Restarting it.");
 
     stop_thread ();
 
-    for (hl = hostlist_head; hl != NULL; hl = hl->next)
+    for (hostlist_t *hl = hostlist_head; hl != NULL; hl = hl->next)
     {
       hl->pkg_sent = 0;
       hl->pkg_recv = 0;
@@ -602,7 +653,7 @@ static int ping_read (void) /* {{{ */
     return (-1);
   } /* if (ping_thread_error != 0) */
 
-  for (hl = hostlist_head; hl != NULL; hl = hl->next) /* {{{ */
+  for (hostlist_t *hl = hostlist_head; hl != NULL; hl = hl->next) /* {{{ */
   {
     uint32_t pkg_sent;
     uint32_t pkg_recv;
@@ -686,6 +737,11 @@ static int ping_shutdown (void) /* {{{ */
     hl = hl_next;
   }
 
+  if (ping_data != NULL) {
+    free (ping_data);
+    ping_data = NULL;
+  }
+
   return (0);
 } /* }}} int ping_shutdown */
 
index 23c4af3..7e69877 100644 (file)
@@ -31,6 +31,7 @@
  */
 
 #include "collectd.h"
+
 #include "common.h"
 
 #include "configfile.h"
 #include "utils_db_query.h"
 #include "utils_complain.h"
 
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-
 #include <pg_config_manual.h>
 #include <libpq-fe.h>
 
@@ -154,7 +151,7 @@ typedef struct {
        int ref_cnt;
 } c_psql_database_t;
 
-static char *def_queries[] = {
+static const char *const def_queries[] = {
        "backends",
        "transactions",
        "queries",
@@ -218,13 +215,13 @@ static c_psql_database_t *c_psql_database_new (const char *name)
        c_psql_database_t **tmp;
        c_psql_database_t  *db;
 
-       db = (c_psql_database_t *)malloc (sizeof(*db));
+       db = malloc (sizeof(*db));
        if (NULL == db) {
                log_err ("Out of memory.");
                return NULL;
        }
 
-       tmp = (c_psql_database_t **)realloc (databases,
+       tmp = realloc (databases,
                        (databases_num + 1) * sizeof (*databases));
        if (NULL == tmp) {
                log_err ("Out of memory.");
@@ -280,8 +277,6 @@ static c_psql_database_t *c_psql_database_new (const char *name)
 
 static void c_psql_database_delete (void *data)
 {
-       size_t i;
-
        c_psql_database_t *db = data;
 
        --db->ref_cnt;
@@ -299,7 +294,7 @@ static void c_psql_database_delete (void *data)
        db->conn = NULL;
 
        if (db->q_prep_areas)
-               for (i = 0; i < db->queries_num; ++i)
+               for (size_t i = 0; i < db->queries_num; ++i)
                        udb_query_delete_preparation_area (db->q_prep_areas[i]);
        free (db->q_prep_areas);
 
@@ -429,16 +424,15 @@ static PGresult *c_psql_exec_query_noparams (c_psql_database_t *db,
 static PGresult *c_psql_exec_query_params (c_psql_database_t *db,
                udb_query_t *q, c_psql_user_data_t *data)
 {
-       char *params[db->max_params_num];
-       char  interval[64];
-       int   i;
+       const char *params[db->max_params_num];
+       char        interval[64];
 
        if ((data == NULL) || (data->params_num == 0))
                return (c_psql_exec_query_noparams (db, q));
 
        assert (db->max_params_num >= data->params_num);
 
-       for (i = 0; i < data->params_num; ++i) {
+       for (int i = 0; i < data->params_num; ++i) {
                switch (data->params[i]) {
                        case C_PSQL_PARAM_HOST:
                                params[i] = C_PSQL_IS_UNIX_DOMAIN_SOCKET (db->host)
@@ -487,7 +481,6 @@ static int c_psql_exec_query (c_psql_database_t *db, udb_query_t *q,
 
        int rows_num;
        int status;
-       int row, col;
 
        /* The user data may hold parameter information, but may be NULL. */
        data = udb_query_get_user_data (q);
@@ -555,8 +548,8 @@ static int c_psql_exec_query (c_psql_database_t *db, udb_query_t *q,
                log_err ("calloc failed.");
                BAIL_OUT (-1);
        }
-       
-       for (col = 0; col < column_num; ++col) {
+
+       for (int col = 0; col < column_num; ++col) {
                /* Pointers returned by `PQfname' are freed by `PQclear' via
                 * `BAIL_OUT'. */
                column_names[col] = PQfname (res, col);
@@ -581,7 +574,8 @@ static int c_psql_exec_query (c_psql_database_t *db, udb_query_t *q,
                BAIL_OUT (-1);
        }
 
-       for (row = 0; row < rows_num; ++row) {
+       for (int row = 0; row < rows_num; ++row) {
+        int col;
                for (col = 0; col < column_num; ++col) {
                        /* Pointers returned by `PQgetvalue' are freed by `PQclear' via
                         * `BAIL_OUT'. */
@@ -615,7 +609,6 @@ static int c_psql_read (user_data_t *ud)
        c_psql_database_t *db;
 
        int success = 0;
-       int i;
 
        if ((ud == NULL) || (ud->data == NULL)) {
                log_err ("c_psql_read: Invalid user data.");
@@ -635,7 +628,7 @@ static int c_psql_read (user_data_t *ud)
                return -1;
        }
 
-       for (i = 0; i < db->queries_num; ++i)
+       for (size_t i = 0; i < db->queries_num; ++i)
        {
                udb_query_preparation_area_t *prep_area;
                udb_query_t *q;
@@ -664,12 +657,10 @@ static char *values_name_to_sqlarray (const data_set_t *ds,
        char  *str_ptr;
        size_t str_len;
 
-       int i;
-
        str_ptr = string;
        str_len = string_len;
 
-       for (i = 0; i < ds->ds_num; ++i) {
+       for (size_t i = 0; i < ds->ds_num; ++i) {
                int status = ssnprintf (str_ptr, str_len, ",'%s'", ds->ds[i].name);
 
                if (status < 1)
@@ -703,12 +694,10 @@ static char *values_type_to_sqlarray (const data_set_t *ds,
        char  *str_ptr;
        size_t str_len;
 
-       int i;
-
        str_ptr = string;
        str_len = string_len;
 
-       for (i = 0; i < ds->ds_num; ++i) {
+       for (size_t i = 0; i < ds->ds_num; ++i) {
                int status;
 
                if (store_rates)
@@ -752,12 +741,10 @@ static char *values_to_sqlarray (const data_set_t *ds, const value_list_t *vl,
 
        gauge_t *rates = NULL;
 
-       int i;
-
        str_ptr = string;
        str_len = string_len;
 
-       for (i = 0; i < vl->values_len; ++i) {
+       for (size_t i = 0; i < vl->values_len; ++i) {
                int status = 0;
 
                if ((ds->ds[i].type != DS_TYPE_GAUGE)
@@ -829,7 +816,7 @@ static int c_psql_write (const data_set_t *ds, const value_list_t *vl,
 {
        c_psql_database_t *db;
 
-       char time_str[32];
+       char time_str[RFC3339NANO_SIZE];
        char values_name_str[1024];
        char values_type_str[1024];
        char values_str[1024];
@@ -837,7 +824,6 @@ static int c_psql_write (const data_set_t *ds, const value_list_t *vl,
        const char *params[9];
 
        int success = 0;
-       int i;
 
        if ((ud == NULL) || (ud->data == NULL)) {
                log_err ("c_psql_write: Invalid user data.");
@@ -848,8 +834,8 @@ static int c_psql_write (const data_set_t *ds, const value_list_t *vl,
        assert (db->database != NULL);
        assert (db->writers != NULL);
 
-       if (cdtime_to_iso8601 (time_str, sizeof (time_str), vl->time) == 0) {
-               log_err ("c_psql_write: Failed to convert time to ISO 8601 format");
+       if (rfc3339nano (time_str, sizeof (time_str), vl->time) != 0) {
+               log_err ("c_psql_write: Failed to convert time to RFC 3339 format");
                return -1;
        }
 
@@ -870,7 +856,7 @@ static int c_psql_write (const data_set_t *ds, const value_list_t *vl,
 #undef VALUE_OR_NULL
 
        if( db->expire_delay > 0 && vl->time < (cdtime() - vl->interval - db->expire_delay) ) {
-               log_info ("c_psql_write: Skipped expired value @ %s - %s/%s-%s/%s-%s/%s", 
+               log_info ("c_psql_write: Skipped expired value @ %s - %s/%s-%s/%s-%s/%s",
                        params[0], params[1], params[2], params[3], params[4], params[5], params[6] );
                return 0;
         }
@@ -886,7 +872,7 @@ static int c_psql_write (const data_set_t *ds, const value_list_t *vl,
                        && (db->next_commit == 0))
                c_psql_begin (db);
 
-       for (i = 0; i < db->writers_num; ++i) {
+       for (size_t i = 0; i < db->writers_num; ++i) {
                c_psql_writer_t *writer;
                PGresult *res;
 
@@ -974,14 +960,13 @@ static int c_psql_flush (cdtime_t timeout,
 {
        c_psql_database_t **dbs = databases;
        size_t dbs_num = databases_num;
-       size_t i;
 
        if ((ud != NULL) && (ud->data != NULL)) {
                dbs = (void *)&ud->data;
                dbs_num = 1;
        }
 
-       for (i = 0; i < dbs_num; ++i) {
+       for (size_t i = 0; i < dbs_num; ++i) {
                c_psql_database_t *db = dbs[i];
 
                /* don't commit if the timeout is larger than the regular commit
@@ -995,13 +980,11 @@ static int c_psql_flush (cdtime_t timeout,
 
 static int c_psql_shutdown (void)
 {
-       size_t i = 0;
-
        _Bool had_flush = 0;
 
        plugin_unregister_read_group ("postgresql");
 
-       for (i = 0; i < databases_num; ++i) {
+       for (size_t i = 0; i < databases_num; ++i) {
                c_psql_database_t *db = databases[i];
 
                if (db->writers_num > 0) {
@@ -1045,12 +1028,11 @@ static int config_query_param_add (udb_query_t *q, oconfig_item_t *ci)
 
        data = udb_query_get_user_data (q);
        if (NULL == data) {
-               data = malloc (sizeof (*data));
+               data = calloc (1, sizeof (*data));
                if (NULL == data) {
                        log_err ("Out of memory.");
                        return -1;
                }
-               memset (data, 0, sizeof (*data));
                data->params = NULL;
                data->params_num = 0;
 
@@ -1119,7 +1101,7 @@ static int config_add_writer (oconfig_item_t *ci,
                if (strcasecmp (name, src_writers[i].name) != 0)
                        continue;
 
-               tmp = (c_psql_writer_t **)realloc (*dst_writers,
+               tmp = realloc (*dst_writers,
                                sizeof (**dst_writers) * (*dst_writers_num + 1));
                if (tmp == NULL) {
                        log_err ("Out of memory.");
@@ -1147,7 +1129,6 @@ static int c_psql_config_writer (oconfig_item_t *ci)
        c_psql_writer_t *tmp;
 
        int status = 0;
-       int i;
 
        if ((ci->values_num != 1)
                        || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
@@ -1155,7 +1136,7 @@ static int c_psql_config_writer (oconfig_item_t *ci)
                return 1;
        }
 
-       tmp = (c_psql_writer_t *)realloc (writers,
+       tmp = realloc (writers,
                        sizeof (*writers) * (writers_num + 1));
        if (tmp == NULL) {
                log_err ("Out of memory.");
@@ -1170,7 +1151,7 @@ static int c_psql_config_writer (oconfig_item_t *ci)
        writer->statement = NULL;
        writer->store_rates = 1;
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *c = ci->children + i;
 
                if (strcasecmp ("Statement", c->key) == 0)
@@ -1196,26 +1177,21 @@ static int c_psql_config_database (oconfig_item_t *ci)
        c_psql_database_t *db;
 
        char cb_name[DATA_MAX_NAME_LEN];
-       struct timespec cb_interval = { 0, 0 };
-       user_data_t ud;
+       user_data_t ud = { 0 };
 
        static _Bool have_flush = 0;
 
-       int i;
-
        if ((1 != ci->values_num)
                        || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
                log_err ("<Database> expects a single string argument.");
                return 1;
        }
 
-       memset (&ud, 0, sizeof (ud));
-
        db = c_psql_database_new (ci->values[0].value.string);
        if (db == NULL)
                return -1;
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *c = ci->children + i;
 
                if (0 == strcasecmp (c->key, "Host"))
@@ -1252,7 +1228,7 @@ static int c_psql_config_database (oconfig_item_t *ci)
 
        /* If no `Query' options were given, add the default queries.. */
        if ((db->queries_num == 0) && (db->writers_num == 0)){
-               for (i = 0; i < def_queries_num; i++)
+               for (int i = 0; i < def_queries_num; i++)
                        udb_query_pick_from_list_by_name (def_queries[i],
                                        queries, queries_num,
                                        &db->queries, &db->queries_num);
@@ -1269,7 +1245,7 @@ static int c_psql_config_database (oconfig_item_t *ci)
                }
        }
 
-       for (i = 0; (size_t)i < db->queries_num; ++i) {
+       for (int i = 0; (size_t)i < db->queries_num; ++i) {
                c_psql_user_data_t *data;
                data = udb_query_get_user_data (db->queries[i]);
                if ((data != NULL) && (data->params_num > db->max_params_num))
@@ -1291,12 +1267,9 @@ static int c_psql_config_database (oconfig_item_t *ci)
        ssnprintf (cb_name, sizeof (cb_name), "postgresql-%s", db->instance);
 
        if (db->queries_num > 0) {
-               CDTIME_T_TO_TIMESPEC (db->interval, &cb_interval);
-
                ++db->ref_cnt;
                plugin_register_complex_read ("postgresql", cb_name, c_psql_read,
-                               /* interval = */ (db->interval > 0) ? &cb_interval : NULL,
-                               &ud);
+                               /* interval = */ db->interval, &ud);
        }
        if (db->writers_num > 0) {
                ++db->ref_cnt;
@@ -1325,8 +1298,6 @@ static int c_psql_config (oconfig_item_t *ci)
 {
        static int have_def_config = 0;
 
-       int i;
-
        if (0 == have_def_config) {
                oconfig_item_t *c;
 
@@ -1343,7 +1314,7 @@ static int c_psql_config (oconfig_item_t *ci)
                                        "any queries - please check your installation.");
        }
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *c = ci->children + i;
 
                if (0 == strcasecmp (c->key, "Query"))
index c9e9359..e215a8c 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -37,7 +38,6 @@
 #include <string.h>
 #include <errno.h>
 #include <sys/types.h>
-#include <sys/socket.h>
 #include <sys/un.h>
 
 #ifndef UNIX_PATH_MAX
@@ -76,52 +76,75 @@ struct list_item_s
 
 struct statname_lookup_s
 {
-  char *name;
-  char *type;
-  char *type_instance;
+  const char *name;
+  const char *type;
+  const char *type_instance;
 };
 typedef struct statname_lookup_s statname_lookup_t;
 
 /* Description of statistics returned by the recursor: {{{
-all-outqueries      counts the number of outgoing UDP queries since starting
-answers0-1          counts the number of queries answered within 1 millisecond
-answers100-1000     counts the number of queries answered within 1 second
-answers10-100       counts the number of queries answered within 100 milliseconds
-answers1-10         counts the number of queries answered within 10 milliseconds
-answers-slow        counts the number of queries answered after 1 second
-cache-entries       shows the number of entries in the cache
-cache-hits          counts the number of cache hits since starting
-cache-misses        counts the number of cache misses since starting
-chain-resends       number of queries chained to existing outstanding query
-client-parse-errors counts number of client packets that could not be parsed
-concurrent-queries  shows the number of MThreads currently running
-dlg-only-drops      number of records dropped because of delegation only setting
-negcache-entries    shows the number of entries in the Negative answer cache
-noerror-answers     counts the number of times it answered NOERROR since starting
-nsspeeds-entries    shows the number of entries in the NS speeds map
-nsset-invalidations number of times an nsset was dropped because it no longer worked
-nxdomain-answers    counts the number of times it answered NXDOMAIN since starting
-outgoing-timeouts   counts the number of timeouts on outgoing UDP queries since starting
-qa-latency          shows the current latency average
-questions           counts all End-user initiated queries with the RD bit set
-resource-limits     counts number of queries that could not be performed because of resource limits
-server-parse-errors counts number of server replied packets that could not be parsed
-servfail-answers    counts the number of times it answered SERVFAIL since starting
-spoof-prevents      number of times PowerDNS considered itself spoofed, and dropped the data
-sys-msec            number of CPU milliseconds spent in 'system' mode
-tcp-client-overflow number of times an IP address was denied TCP access because it already had too many connections
-tcp-outqueries      counts the number of outgoing TCP queries since starting
-tcp-questions       counts all incoming TCP queries (since starting)
-throttled-out       counts the number of throttled outgoing UDP queries since starting
-throttle-entries    shows the number of entries in the throttle map
-unauthorized-tcp    number of TCP questions denied because of allow-from restrictions
-unauthorized-udp    number of UDP questions denied because of allow-from restrictions
-unexpected-packets  number of answers from remote servers that were unexpected (might point to spoofing)
-uptime              number of seconds process has been running (since 3.1.5)
-user-msec           number of CPU milliseconds spent in 'user' mode
+all-outqueries        counts the number of outgoing UDP queries since starting
+answers-slow          counts the number of queries answered after 1 second
+answers0-1            counts the number of queries answered within 1 millisecond
+answers1-10           counts the number of queries answered within 10 milliseconds
+answers10-100         counts the number of queries answered within 100 milliseconds
+answers100-1000       counts the number of queries answered within 1 second
+cache-bytes           size of the cache in bytes (since 3.3.1)
+cache-entries         shows the number of entries in the cache
+cache-hits            counts the number of cache hits since starting, this does not include hits that got answered from the packet-cache
+cache-misses          counts the number of cache misses since starting
+case-mismatches       counts the number of mismatches in character case since starting
+chain-resends         number of queries chained to existing outstanding query
+client-parse-errors   counts number of client packets that could not be parsed
+concurrent-queries    shows the number of MThreads currently running
+dlg-only-drops        number of records dropped because of delegation only setting
+dont-outqueries       number of outgoing queries dropped because of 'dont-query' setting (since 3.3)
+edns-ping-matches     number of servers that sent a valid EDNS PING respons
+edns-ping-mismatches  number of servers that sent an invalid EDNS PING response
+failed-host-entries   number of servers that failed to resolve
+ipv6-outqueries       number of outgoing queries over IPv6
+ipv6-questions        counts all End-user initiated queries with the RD bit set, received over IPv6 UDP
+malloc-bytes          returns the number of bytes allocated by the process (broken, always returns 0)
+max-mthread-stack     maximum amount of thread stack ever used
+negcache-entries      shows the number of entries in the Negative answer cache
+no-packet-error       number of errorneous received packets
+noedns-outqueries     number of queries sent out without EDNS
+noerror-answers       counts the number of times it answered NOERROR since starting
+noping-outqueries     number of queries sent out without ENDS PING
+nsset-invalidations   number of times an nsset was dropped because it no longer worked
+nsspeeds-entries      shows the number of entries in the NS speeds map
+nxdomain-answers      counts the number of times it answered NXDOMAIN since starting
+outgoing-timeouts     counts the number of timeouts on outgoing UDP queries since starting
+over-capacity-drops   questions dropped because over maximum concurrent query limit (since 3.2)
+packetcache-bytes     size of the packet cache in bytes (since 3.3.1)
+packetcache-entries   size of packet cache (since 3.2)
+packetcache-hits      packet cache hits (since 3.2)
+packetcache-misses    packet cache misses (since 3.2)
+policy-drops          packets dropped because of (Lua) policy decision
+qa-latency            shows the current latency average
+questions             counts all end-user initiated queries with the RD bit set
+resource-limits       counts number of queries that could not be performed because of resource limits
+security-status       security status based on security polling
+server-parse-errors   counts number of server replied packets that could not be parsed
+servfail-answers      counts the number of times it answered SERVFAIL since starting
+spoof-prevents        number of times PowerDNS considered itself spoofed, and dropped the data
+sys-msec              number of CPU milliseconds spent in 'system' mode
+tcp-client-overflow   number of times an IP address was denied TCP access because it already had too many connections
+tcp-clients           counts the number of currently active TCP/IP clients
+tcp-outqueries        counts the number of outgoing TCP queries since starting
+tcp-questions         counts all incoming TCP queries (since starting)
+throttle-entries      shows the number of entries in the throttle map
+throttled-out         counts the number of throttled outgoing UDP queries since starting
+throttled-outqueries  idem to throttled-out
+unauthorized-tcp      number of TCP questions denied because of allow-from restrictions
+unauthorized-udp      number of UDP questions denied because of allow-from restrictions
+unexpected-packets    number of answers from remote servers that were unexpected (might point to spoofing)
+unreachables          number of times nameservers were unreachable since starting
+uptime                number of seconds process has been running (since 3.1.5)
+user-msec             number of CPU milliseconds spent in 'user' mode
 }}} */
 
-const char* const default_server_fields[] = /* {{{ */
+static const char* const default_server_fields[] = /* {{{ */
 {
   "latency",
   "packetcache-hit",
@@ -136,9 +159,9 @@ const char* const default_server_fields[] = /* {{{ */
   "udp-answers",
   "udp-queries",
 }; /* }}} */
-int default_server_fields_num = STATIC_ARRAY_SIZE (default_server_fields);
+static int default_server_fields_num = STATIC_ARRAY_SIZE (default_server_fields);
 
-statname_lookup_t lookup_table[] = /* {{{ */
+static statname_lookup_t lookup_table[] = /* {{{ */
 {
   /*********************
    * Server statistics *
@@ -157,8 +180,13 @@ statname_lookup_t lookup_table[] = /* {{{ */
   {"udp-answers-bytes",      "total_bytes",  "udp-answers-bytes"},
 
   /* Cache stuff */
+  {"cache-bytes",            "cache_size",   "cache-bytes"},
+  {"packetcache-bytes",      "cache_size",   "packet-bytes"},
+  {"packetcache-entries",    "cache_size",   "packet-entries"},
   {"packetcache-hit",        "cache_result", "packet-hit"},
+  {"packetcache-hits",       "cache_result", "packet-hit"},
   {"packetcache-miss",       "cache_result", "packet-miss"},
+  {"packetcache-misses",     "cache_result", "packet-miss"},
   {"packetcache-size",       "cache_size",   "packet"},
   {"key-cache-size",         "cache_size",   "key"},
   {"meta-cache-size",        "cache_size",   "meta"},
@@ -179,6 +207,7 @@ statname_lookup_t lookup_table[] = /* {{{ */
   {"corrupt-packets",        "ipt_packets",  "corrupt"},
   {"deferred-cache-inserts", "counter",      "cache-deferred_insert"},
   {"deferred-cache-lookup",  "counter",      "cache-deferred_lookup"},
+  {"dont-outqueries",        "dns_question", "dont-outqueries"},
   {"qsize-a",                "cache_size",   "answers"},
   {"qsize-q",                "cache_size",   "questions"},
   {"servfail-packets",       "ipt_packets",  "servfail"},
@@ -195,54 +224,69 @@ statname_lookup_t lookup_table[] = /* {{{ */
    * Recursor statistics *
    ***********************/
   /* Answers by return code */
-  {"noerror-answers",     "dns_rcode",    "NOERROR"},
-  {"nxdomain-answers",    "dns_rcode",    "NXDOMAIN"},
-  {"servfail-answers",    "dns_rcode",    "SERVFAIL"},
+  {"noerror-answers",      "dns_rcode",    "NOERROR"},
+  {"nxdomain-answers",     "dns_rcode",    "NXDOMAIN"},
+  {"servfail-answers",     "dns_rcode",    "SERVFAIL"},
 
   /* CPU utilization */
-  {"sys-msec",            "cpu",          "system"},
-  {"user-msec",           "cpu",          "user"},
+  {"sys-msec",             "cpu",          "system"},
+  {"user-msec",            "cpu",          "user"},
 
   /* Question-to-answer latency */
-  {"qa-latency",          "latency",      NULL},
+  {"qa-latency",           "latency",      NULL},
 
   /* Cache */
-  {"cache-entries",       "cache_size",   NULL},
-  {"cache-hits",          "cache_result", "hit"},
-  {"cache-misses",        "cache_result", "miss"},
+  {"cache-entries",        "cache_size",   NULL},
+  {"cache-hits",           "cache_result", "hit"},
+  {"cache-misses",         "cache_result", "miss"},
 
   /* Total number of questions.. */
-  {"questions",           "dns_qtype",    "total"},
+  {"questions",            "dns_qtype",    "total"},
 
   /* All the other stuff.. */
-  {"all-outqueries",      "dns_question", "outgoing"},
-  {"answers0-1",          "dns_answer",   "0_1"},
-  {"answers1-10",         "dns_answer",   "1_10"},
-  {"answers10-100",       "dns_answer",   "10_100"},
-  {"answers100-1000",     "dns_answer",   "100_1000"},
-  {"answers-slow",        "dns_answer",   "slow"},
-  {"chain-resends",       "dns_question", "chained"},
-  {"client-parse-errors", "counter",      "drops-client_parse_error"},
-  {"concurrent-queries",  "dns_question", "concurrent"},
-  {"dlg-only-drops",      "counter",      "drops-delegation_only"},
-  {"negcache-entries",    "cache_size",   "negative"},
-  {"nsspeeds-entries",    "gauge",        "entries-ns_speeds"},
-  {"nsset-invalidations", "counter",      "ns_set_invalidation"},
-  {"outgoing-timeouts",   "counter",      "drops-timeout_outgoing"},
-  {"resource-limits",     "counter",      "drops-resource_limit"},
-  {"server-parse-errors", "counter",      "drops-server_parse_error"},
-  {"spoof-prevents",      "counter",      "drops-spoofed"},
-  {"tcp-client-overflow", "counter",      "denied-client_overflow_tcp"},
-  {"tcp-outqueries",      "dns_question", "outgoing-tcp"},
-  {"tcp-questions",       "dns_question", "incoming-tcp"},
-  {"throttled-out",       "dns_question", "outgoing-throttled"},
-  {"throttle-entries",    "gauge",        "entries-throttle"},
-  {"unauthorized-tcp",    "counter",      "denied-unauthorized_tcp"},
-  {"unauthorized-udp",    "counter",      "denied-unauthorized_udp"},
-  {"unexpected-packets",  "dns_answer",   "unexpected"},
-  {"uptime",              "uptime",       NULL}
+  {"all-outqueries",       "dns_question", "outgoing"},
+  {"answers0-1",           "dns_answer",   "0_1"},
+  {"answers1-10",          "dns_answer",   "1_10"},
+  {"answers10-100",        "dns_answer",   "10_100"},
+  {"answers100-1000",      "dns_answer",   "100_1000"},
+  {"answers-slow",         "dns_answer",   "slow"},
+  {"case-mismatches",      "counter",      "case_mismatches"},
+  {"chain-resends",        "dns_question", "chained"},
+  {"client-parse-errors",  "counter",      "drops-client_parse_error"},
+  {"concurrent-queries",   "dns_question", "concurrent"},
+  {"dlg-only-drops",       "counter",      "drops-delegation_only"},
+  {"edns-ping-matches",    "counter",      "edns-ping_matches"},
+  {"edns-ping-mismatches", "counter",      "edns-ping_mismatches"},
+  {"failed-host-entries",  "counter",      "entries-failed_host"},
+  {"ipv6-outqueries",      "dns_question", "outgoing-ipv6"},
+  {"ipv6-questions",       "dns_question", "incoming-ipv6"},
+  {"malloc-bytes",         "gauge",        "malloc_bytes"},
+  {"max-mthread-stack",    "gauge",        "max_mthread_stack"},
+  {"no-packet-error",      "gauge",        "no_packet_error"},
+  {"noedns-outqueries",    "dns_question", "outgoing-noedns"},
+  {"noping-outqueries",    "dns_question", "outgoing-noping"},
+  {"over-capacity-drops",  "dns_question", "incoming-over_capacity"},
+  {"negcache-entries",     "cache_size",   "negative"},
+  {"nsspeeds-entries",     "gauge",        "entries-ns_speeds"},
+  {"nsset-invalidations",  "counter",      "ns_set_invalidation"},
+  {"outgoing-timeouts",    "counter",      "drops-timeout_outgoing"},
+  {"policy-drops",         "counter",      "drops-policy"},
+  {"resource-limits",      "counter",      "drops-resource_limit"},
+  {"server-parse-errors",  "counter",      "drops-server_parse_error"},
+  {"spoof-prevents",       "counter",      "drops-spoofed"},
+  {"tcp-client-overflow",  "counter",      "denied-client_overflow_tcp"},
+  {"tcp-clients",          "gauge",        "clients-tcp"},
+  {"tcp-outqueries",       "dns_question", "outgoing-tcp"},
+  {"tcp-questions",        "dns_question", "incoming-tcp"},
+  {"throttled-out",        "dns_question", "outgoing-throttled"},
+  {"throttle-entries",     "gauge",        "entries-throttle"},
+  {"throttled-outqueries", "dns_question", "outgoing-throttle"},
+  {"unauthorized-tcp",     "counter",      "denied-unauthorized_tcp"},
+  {"unauthorized-udp",     "counter",      "denied-unauthorized_udp"},
+  {"unexpected-packets",   "dns_answer",   "unexpected"},
+  {"uptime",               "uptime",       NULL}
 }; /* }}} */
-int lookup_table_length = STATIC_ARRAY_SIZE (lookup_table);
+static int lookup_table_length = STATIC_ARRAY_SIZE (lookup_table);
 
 static llist_t *list = NULL;
 
@@ -250,14 +294,12 @@ static llist_t *list = NULL;
 static char *local_sockpath = NULL;
 
 /* TODO: Do this before 4.4:
- * - Recursor:
- *   - Complete list of known pdns -> collectd mappings.
  * - Update the collectd.conf(5) manpage.
  *
  * -octo
  */
 
-/* <http://doc.powerdns.com/recursor-stats.html> */
+/* <https://doc.powerdns.com/md/recursor/stats/> */
 static void submit (const char *plugin_instance, /* {{{ */
     const char *pdns_type, const char *value)
 {
@@ -298,7 +340,7 @@ static void submit (const char *plugin_instance, /* {{{ */
 
   if (ds->ds_num != 1)
   {
-    ERROR ("powerdns plugin: type `%s' has %i data sources, "
+    ERROR ("powerdns plugin: type `%s' has %zu data sources, "
         "but I can only handle one.",
         type, ds->ds_num);
     return;
@@ -334,7 +376,7 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */
   char *buffer = NULL;
   size_t buffer_size = 0;
 
-  struct sockaddr_un sa_unix;
+  struct sockaddr_un sa_unix = { 0 };
 
   struct timeval stv_timeout;
   cdtime_t cdt_timeout;
@@ -346,7 +388,6 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */
     return (-1);
   }
 
-  memset (&sa_unix, 0, sizeof (sa_unix));
   sa_unix.sun_family = AF_UNIX;
   sstrncpy (sa_unix.sun_path,
       (local_sockpath != NULL) ? local_sockpath : PDNS_LOCAL_SOCKPATH,
@@ -424,7 +465,7 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */
     return (-1);
 
   assert (buffer_size > 0);
-  buffer = (char *) malloc (buffer_size);
+  buffer = malloc (buffer_size);
   if (buffer == NULL)
   {
     FUNC_ERROR ("malloc");
@@ -501,7 +542,7 @@ static int powerdns_get_data_stream (list_item_t *item, /* {{{ */
     else if (status == 0)
       break;
 
-    buffer_new = (char *) realloc (buffer, buffer_size + status + 1);
+    buffer_new = realloc (buffer, buffer_size + status + 1);
     if (buffer_new == NULL)
     {
       FUNC_ERROR ("realloc");
@@ -590,8 +631,6 @@ static int powerdns_read_server (list_item_t *item) /* {{{ */
   saveptr = NULL;
   while ((key = strtok_r (dummy, ",", &saveptr)) != NULL)
   {
-    int i;
-
     dummy = NULL;
 
     value = strchr (key, '=');
@@ -605,6 +644,7 @@ static int powerdns_read_server (list_item_t *item) /* {{{ */
       continue;
 
     /* Check if this item was requested. */
+    int i;
     for (i = 0; i < fields_num; i++)
       if (strcasecmp (key, fields[i]) == 0)
        break;
@@ -650,12 +690,12 @@ static int powerdns_update_recursor_command (list_item_t *li) /* {{{ */
       return (-1);
     }
     buffer[sizeof (buffer) - 1] = 0;
-    int i = strlen (buffer);
-    if (i < sizeof (buffer) - 2)
+    size_t len = strlen (buffer);
+    if (len < sizeof (buffer) - 2)
     {
-      buffer[i++] = ' ';
-      buffer[i++] = '\n';
-      buffer[i++] = '\0';
+      buffer[len++] = ' ';
+      buffer[len++] = '\n';
+      buffer[len++] = '\0';
     }
   }
 
@@ -740,7 +780,6 @@ static int powerdns_read_recursor (list_item_t *item) /* {{{ */
 static int powerdns_config_add_collect (list_item_t *li, /* {{{ */
     oconfig_item_t *ci)
 {
-  int i;
   char **temp;
 
   if (ci->values_num < 1)
@@ -750,7 +789,7 @@ static int powerdns_config_add_collect (list_item_t *li, /* {{{ */
     return (-1);
   }
 
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
     if (ci->values[i].type != OCONFIG_TYPE_STRING)
     {
       WARNING ("powerdns plugin: Only string arguments are allowed to "
@@ -758,7 +797,7 @@ static int powerdns_config_add_collect (list_item_t *li, /* {{{ */
       return (-1);
     }
 
-  temp = (char **) realloc (li->fields,
+  temp = realloc (li->fields,
       sizeof (char *) * (li->fields_num + ci->values_num));
   if (temp == NULL)
   {
@@ -767,7 +806,7 @@ static int powerdns_config_add_collect (list_item_t *li, /* {{{ */
   }
   li->fields = temp;
 
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
   {
     li->fields[li->fields_num] = strdup (ci->values[i].value.string);
     if (li->fields[li->fields_num] == NULL)
@@ -790,7 +829,6 @@ static int powerdns_config_add_server (oconfig_item_t *ci) /* {{{ */
 
   list_item_t *item;
   int status;
-  int i;
 
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
   {
@@ -799,13 +837,12 @@ static int powerdns_config_add_server (oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  item = (list_item_t *) malloc (sizeof (list_item_t));
+  item = calloc (1, sizeof (*item));
   if (item == NULL)
   {
-    ERROR ("powerdns plugin: malloc failed.");
+    ERROR ("powerdns plugin: calloc failed.");
     return (-1);
   }
-  memset (item, '\0', sizeof (list_item_t));
 
   item->instance = strdup (ci->values[0].value.string);
   if (item->instance == NULL)
@@ -840,7 +877,7 @@ static int powerdns_config_add_server (oconfig_item_t *ci) /* {{{ */
   }
 
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
@@ -900,8 +937,6 @@ static int powerdns_config_add_server (oconfig_item_t *ci) /* {{{ */
 
 static int powerdns_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
   DEBUG ("powerdns plugin: powerdns_config (ci = %p);", (void *) ci);
 
   if (list == NULL)
@@ -915,7 +950,7 @@ static int powerdns_config (oconfig_item_t *ci) /* {{{ */
     }
   }
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
@@ -948,9 +983,7 @@ static int powerdns_config (oconfig_item_t *ci) /* {{{ */
 
 static int powerdns_read (void)
 {
-  llentry_t *e;
-
-  for (e = llist_head (list); e != NULL; e = e->next)
+  for (llentry_t *e = llist_head (list); e != NULL; e = e->next)
   {
     list_item_t *item = e->value;
     item->func (item);
@@ -961,12 +994,10 @@ static int powerdns_read (void)
 
 static int powerdns_shutdown (void)
 {
-  llentry_t *e;
-
   if (list == NULL)
     return (0);
 
-  for (e = llist_head (list); e != NULL; e = e->next)
+  for (llentry_t *e = llist_head (list); e != NULL; e = e->next)
   {
     list_item_t *item = (list_item_t *) e->value;
     e->value = NULL;
index 7a3c0e9..d34fe40 100644 (file)
@@ -35,6 +35,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -186,6 +187,9 @@ typedef struct procstat_entry_s
        derive_t io_syscr;
        derive_t io_syscw;
 
+       derive_t cswitch_vol;
+       derive_t cswitch_invol;
+
        struct procstat_entry_s *next;
 } procstat_entry_t;
 
@@ -217,12 +221,17 @@ typedef struct procstat
        derive_t io_syscr;
        derive_t io_syscw;
 
+       derive_t cswitch_vol;
+       derive_t cswitch_invol;
+
        struct procstat   *next;
        struct procstat_entry_s *instances;
 } procstat_t;
 
 static procstat_t *list_head_g = NULL;
 
+static _Bool report_ctx_switch = 0;
+
 #if HAVE_THREAD_INFO
 static mach_port_t port_host_self;
 static mach_port_t port_task_self;
@@ -260,20 +269,19 @@ static void ps_list_register (const char *name, const char *regexp)
        procstat_t *ptr;
        int status;
 
-       new = (procstat_t *) malloc (sizeof (procstat_t));
+       new = calloc (1, sizeof (*new));
        if (new == NULL)
        {
-               ERROR ("processes plugin: ps_list_register: malloc failed.");
+               ERROR ("processes plugin: ps_list_register: calloc failed.");
                return;
        }
-       memset (new, 0, sizeof (procstat_t));
        sstrncpy (new->name, name, sizeof (new->name));
 
 #if HAVE_REGEX_H
        if (regexp != NULL)
        {
                DEBUG ("ProcessMatch: adding \"%s\" as criteria to process %s.", regexp, name);
-               new->re = (regex_t *) malloc (sizeof (regex_t));
+               new->re = malloc (sizeof (*new->re));
                if (new->re == NULL)
                {
                        ERROR ("processes plugin: ps_list_register: malloc failed.");
@@ -285,8 +293,8 @@ static void ps_list_register (const char *name, const char *regexp)
                if (status != 0)
                {
                        DEBUG ("ProcessMatch: compiling the regular expression \"%s\" failed.", regexp);
-                       sfree(new->re);
-                       sfree(new);
+                       sfree (new->re);
+                       sfree (new);
                        return;
                }
        }
@@ -359,17 +367,39 @@ static int ps_list_match (const char *name, const char *cmdline, procstat_t *ps)
        return (0);
 } /* int ps_list_match */
 
+static void ps_update_counter (_Bool init, derive_t *group_counter,
+                               derive_t *curr_counter, unsigned long *curr_value,
+                               derive_t new_counter, unsigned long new_value)
+{
+       if (init)
+       {
+               *curr_value = new_value;
+               *curr_counter += new_value;
+               *group_counter += new_value;
+               return;
+       }
+
+       if (new_counter < *curr_counter)
+               *curr_value = new_counter + (ULONG_MAX - *curr_counter);
+       else
+               *curr_value = new_counter - *curr_counter;
+
+       *curr_counter = new_counter;
+       *group_counter += *curr_value;
+}
+
 /* add process entry to 'instances' of process 'name' (or refresh it) */
 static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t *entry)
 {
-       procstat_t *ps;
        procstat_entry_t *pse;
 
        if (entry->id == 0)
                return;
 
-       for (ps = list_head_g; ps != NULL; ps = ps->next)
+       for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next)
        {
+               _Bool want_init;
+
                if ((ps_list_match (name, cmdline, ps)) == 0)
                        continue;
 
@@ -381,10 +411,9 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t
                {
                        procstat_entry_t *new;
 
-                       new = (procstat_entry_t *) malloc (sizeof (procstat_entry_t));
+                       new = calloc (1, sizeof (*new));
                        if (new == NULL)
                                return;
-                       memset (new, 0, sizeof (procstat_entry_t));
                        new->id = entry->id;
 
                        if (pse == NULL)
@@ -407,6 +436,8 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t
                pse->io_wchar   = entry->io_wchar;
                pse->io_syscr   = entry->io_syscr;
                pse->io_syscw   = entry->io_syscw;
+               pse->cswitch_vol   = entry->cswitch_vol;
+               pse->cswitch_invol = entry->cswitch_invol;
 
                ps->num_proc   += pse->num_proc;
                ps->num_lwp    += pse->num_lwp;
@@ -421,90 +452,40 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t
                ps->io_syscr   += ((pse->io_syscr == -1)?0:pse->io_syscr);
                ps->io_syscw   += ((pse->io_syscw == -1)?0:pse->io_syscw);
 
-               if ((entry->vmem_minflt_counter == 0)
-                               && (entry->vmem_majflt_counter == 0))
-               {
-                       pse->vmem_minflt_counter += entry->vmem_minflt;
-                       pse->vmem_minflt = entry->vmem_minflt;
-
-                       pse->vmem_majflt_counter += entry->vmem_majflt;
-                       pse->vmem_majflt = entry->vmem_majflt;
-               }
-               else
-               {
-                       if (entry->vmem_minflt_counter < pse->vmem_minflt_counter)
-                       {
-                               pse->vmem_minflt = entry->vmem_minflt_counter
-                                       + (ULONG_MAX - pse->vmem_minflt_counter);
-                       }
-                       else
-                       {
-                               pse->vmem_minflt = entry->vmem_minflt_counter - pse->vmem_minflt_counter;
-                       }
-                       pse->vmem_minflt_counter = entry->vmem_minflt_counter;
-
-                       if (entry->vmem_majflt_counter < pse->vmem_majflt_counter)
-                       {
-                               pse->vmem_majflt = entry->vmem_majflt_counter
-                                       + (ULONG_MAX - pse->vmem_majflt_counter);
-                       }
-                       else
-                       {
-                               pse->vmem_majflt = entry->vmem_majflt_counter - pse->vmem_majflt_counter;
-                       }
-                       pse->vmem_majflt_counter = entry->vmem_majflt_counter;
-               }
-
-               ps->vmem_minflt_counter += pse->vmem_minflt;
-               ps->vmem_majflt_counter += pse->vmem_majflt;
-
-               if ((entry->cpu_user_counter == 0)
-                               && (entry->cpu_system_counter == 0))
-               {
-                       pse->cpu_user_counter += entry->cpu_user;
-                       pse->cpu_user = entry->cpu_user;
-
-                       pse->cpu_system_counter += entry->cpu_system;
-                       pse->cpu_system = entry->cpu_system;
-               }
-               else
-               {
-                       if (entry->cpu_user_counter < pse->cpu_user_counter)
-                       {
-                               pse->cpu_user = entry->cpu_user_counter
-                                       + (ULONG_MAX - pse->cpu_user_counter);
-                       }
-                       else
-                       {
-                               pse->cpu_user = entry->cpu_user_counter - pse->cpu_user_counter;
-                       }
-                       pse->cpu_user_counter = entry->cpu_user_counter;
-
-                       if (entry->cpu_system_counter < pse->cpu_system_counter)
-                       {
-                               pse->cpu_system = entry->cpu_system_counter
-                                       + (ULONG_MAX - pse->cpu_system_counter);
-                       }
-                       else
-                       {
-                               pse->cpu_system = entry->cpu_system_counter - pse->cpu_system_counter;
-                       }
-                       pse->cpu_system_counter = entry->cpu_system_counter;
-               }
-
-               ps->cpu_user_counter   += pse->cpu_user;
-               ps->cpu_system_counter += pse->cpu_system;
+               ps->cswitch_vol   += ((pse->cswitch_vol == -1)?0:pse->cswitch_vol);
+               ps->cswitch_invol += ((pse->cswitch_invol == -1)?0:pse->cswitch_invol);
+
+               want_init = (entry->vmem_minflt_counter == 0)
+                               && (entry->vmem_majflt_counter == 0);
+               ps_update_counter (want_init,
+                               &ps->vmem_minflt_counter,
+                               &pse->vmem_minflt_counter, &pse->vmem_minflt,
+                               entry->vmem_minflt_counter, entry->vmem_minflt);
+               ps_update_counter (want_init,
+                               &ps->vmem_majflt_counter,
+                               &pse->vmem_majflt_counter, &pse->vmem_majflt,
+                               entry->vmem_majflt_counter, entry->vmem_majflt);
+
+               want_init = (entry->cpu_user_counter == 0)
+                               && (entry->cpu_system_counter == 0);
+               ps_update_counter (want_init,
+                               &ps->cpu_user_counter,
+                               &pse->cpu_user_counter, &pse->cpu_user,
+                               entry->cpu_user_counter, entry->cpu_user);
+               ps_update_counter (want_init,
+                               &ps->cpu_system_counter,
+                               &pse->cpu_system_counter, &pse->cpu_system,
+                               entry->cpu_system_counter, entry->cpu_system);
        }
 }
 
 /* remove old entries from instances of processes in list_head_g */
 static void ps_list_reset (void)
 {
-       procstat_t *ps;
        procstat_entry_t *pse;
        procstat_entry_t *pse_prev;
 
-       for (ps = list_head_g; ps != NULL; ps = ps->next)
+       for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next)
        {
                ps->num_proc    = 0;
                ps->num_lwp     = 0;
@@ -517,6 +498,8 @@ static void ps_list_reset (void)
                ps->io_wchar = -1;
                ps->io_syscr = -1;
                ps->io_syscw = -1;
+               ps->cswitch_vol   = -1;
+               ps->cswitch_invol = -1;
 
                pse_prev = NULL;
                pse = ps->instances;
@@ -554,15 +537,13 @@ static void ps_list_reset (void)
 /* put all pre-defined 'Process' names from config to list_head_g tree */
 static int ps_config (oconfig_item_t *ci)
 {
-       int i;
-
 #if KERNEL_LINUX
        const size_t max_procname_len = 15;
 #elif KERNEL_SOLARIS || KERNEL_FREEBSD
        const size_t max_procname_len = MAXCOMLEN -1;
 #endif
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *c = ci->children + i;
 
                if (strcasecmp (c->key, "Process") == 0)
@@ -616,6 +597,10 @@ static int ps_config (oconfig_item_t *ci)
                        ps_list_register (c->values[0].value.string,
                                        c->values[1].value.string);
                }
+               else if (strcasecmp (c->key, "CollectContextSwitch") == 0)
+               {
+                       cf_util_get_boolean (c, &report_ctx_switch);
+               }
                else
                {
                        ERROR ("processes plugin: The `%s' configuration option is not "
@@ -765,19 +750,36 @@ static void ps_submit_proc_list (procstat_t *ps)
                plugin_dispatch_values (&vl);
        }
 
+       if ( report_ctx_switch )
+       {
+               sstrncpy (vl.type, "contextswitch", sizeof (vl.type));
+               sstrncpy (vl.type_instance, "voluntary", sizeof (vl.type_instance));
+               vl.values[0].derive = ps->cswitch_vol;
+               vl.values_len = 1;
+               plugin_dispatch_values (&vl);
+
+               sstrncpy (vl.type, "contextswitch", sizeof (vl.type));
+               sstrncpy (vl.type_instance, "involuntary", sizeof (vl.type_instance));
+               vl.values[0].derive = ps->cswitch_invol;
+               vl.values_len = 1;
+               plugin_dispatch_values (&vl);
+       }
+
        DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; "
                        "vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
                        "vmem_code = %lu; "
                        "vmem_minflt_counter = %"PRIi64"; vmem_majflt_counter = %"PRIi64"; "
                        "cpu_user_counter = %"PRIi64"; cpu_system_counter = %"PRIi64"; "
                        "io_rchar = %"PRIi64"; io_wchar = %"PRIi64"; "
-                       "io_syscr = %"PRIi64"; io_syscw = %"PRIi64";",
+                       "io_syscr = %"PRIi64"; io_syscw = %"PRIi64"; "
+                       "cswitch_vol = %"PRIi64"; cswitch_invol = %"PRIi64";",
                        ps->name, ps->num_proc, ps->num_lwp,
                        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_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw,
+                       ps->cswitch_vol, ps->cswitch_invol);
 } /* void ps_submit_proc_list */
 
 #if KERNEL_LINUX || KERNEL_SOLARIS
@@ -802,42 +804,99 @@ static void ps_submit_fork_rate (derive_t value)
 
 /* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
 #if KERNEL_LINUX
-static int ps_read_tasks (long pid)
+static procstat_t *ps_read_tasks_status (long pid, procstat_t *ps)
 {
        char           dirname[64];
        DIR           *dh;
+       char           filename[64];
+       FILE          *fh;
        struct dirent *ent;
-       int count = 0;
+       derive_t cswitch_vol = 0;
+       derive_t cswitch_invol = 0;
+       char buffer[1024];
+       char *fields[8];
+       int numfields;
 
        ssnprintf (dirname, sizeof (dirname), "/proc/%li/task", pid);
 
        if ((dh = opendir (dirname)) == NULL)
        {
                DEBUG ("Failed to open directory `%s'", dirname);
-               return (-1);
+               return (NULL);
        }
 
        while ((ent = readdir (dh)) != NULL)
        {
+               char *tpid;
+
                if (!isdigit ((int) ent->d_name[0]))
                        continue;
-               else
-                       count++;
+
+               tpid = ent->d_name;
+
+               ssnprintf (filename, sizeof (filename), "/proc/%li/task/%s/status", pid, tpid);
+               if ((fh = fopen (filename, "r")) == NULL)
+               {
+                       DEBUG ("Failed to open file `%s'", filename);
+                       continue;
+               }
+
+               while (fgets (buffer, sizeof(buffer), fh) != NULL)
+               {
+                       derive_t tmp;
+                       char *endptr;
+
+                       if (strncmp (buffer, "voluntary_ctxt_switches", 23) != 0
+                               && strncmp (buffer, "nonvoluntary_ctxt_switches", 26) != 0)
+                               continue;
+
+                       numfields = strsplit (buffer, fields,
+                               STATIC_ARRAY_SIZE (fields));
+
+                       if (numfields < 2)
+                               continue;
+
+                       errno = 0;
+                       endptr = NULL;
+                       tmp = (derive_t) strtoll (fields[1], &endptr, /* base = */ 10);
+                       if ((errno == 0) && (endptr != fields[1]))
+                       {
+                               if (strncmp (buffer, "voluntary_ctxt_switches", 23) == 0)
+                               {
+                                       cswitch_vol += tmp;
+                               }
+                               else if (strncmp (buffer, "nonvoluntary_ctxt_switches", 26) == 0)
+                               {
+                                       cswitch_invol += tmp;
+                               }
+                       }
+               } /* while (fgets) */
+
+               if (fclose (fh))
+               {
+                       char errbuf[1024];
+                       WARNING ("processes: fclose: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               }
        }
        closedir (dh);
 
-       return ((count >= 1) ? count : 1);
-} /* int *ps_read_tasks */
+       ps->cswitch_vol = cswitch_vol;
+       ps->cswitch_invol = cswitch_invol;
 
-/* Read advanced virtual memory data from /proc/pid/status */
-static procstat_t *ps_read_vmem (long pid, procstat_t *ps)
+       return (ps);
+} /* int *ps_read_tasks_status */
+
+/* Read data from /proc/pid/status */
+static procstat_t *ps_read_status (long pid, procstat_t *ps)
 {
        FILE *fh;
        char buffer[1024];
        char filename[64];
-       unsigned long long lib = 0;
-       unsigned long long exe = 0;
-       unsigned long long data = 0;
+       unsigned long lib = 0;
+       unsigned long exe = 0;
+       unsigned long data = 0;
+       unsigned long threads = 0;
        char *fields[8];
        int numfields;
 
@@ -847,10 +906,11 @@ static procstat_t *ps_read_vmem (long pid, procstat_t *ps)
 
        while (fgets (buffer, sizeof(buffer), fh) != NULL)
        {
-               long long tmp;
+               unsigned long tmp;
                char *endptr;
 
-               if (strncmp (buffer, "Vm", 2) != 0)
+               if (strncmp (buffer, "Vm", 2) != 0
+                               && strncmp (buffer, "Threads", 7) != 0)
                        continue;
 
                numfields = strsplit (buffer, fields,
@@ -861,7 +921,7 @@ static procstat_t *ps_read_vmem (long pid, procstat_t *ps)
 
                errno = 0;
                endptr = NULL;
-               tmp = strtoll (fields[1], &endptr, /* base = */ 10);
+               tmp = strtoul (fields[1], &endptr, /* base = */ 10);
                if ((errno == 0) && (endptr != fields[1]))
                {
                        if (strncmp (buffer, "VmData", 6) == 0)
@@ -876,6 +936,10 @@ static procstat_t *ps_read_vmem (long pid, procstat_t *ps)
                        {
                                exe = tmp;
                        }
+                       else if  (strncmp(buffer, "Threads", 7) == 0)
+                       {
+                               threads = tmp;
+                       }
                }
        } /* while (fgets) */
 
@@ -888,6 +952,8 @@ static procstat_t *ps_read_vmem (long pid, procstat_t *ps)
 
        ps->vmem_data = data * 1024;
        ps->vmem_code = (exe + lib) * 1024;
+       if (threads != 0)
+               ps->num_lwp = threads;
 
        return (ps);
 } /* procstat_t *ps_read_vmem */
@@ -955,9 +1021,9 @@ static int ps_read_process (long pid, procstat_t *ps, char *state)
        char *fields[64];
        char  fields_len;
 
-       int   buffer_len;
+       size_t buffer_len;
 
-       char *buffer_ptr;
+       char  *buffer_ptr;
        size_t name_start_pos;
        size_t name_end_pos;
        size_t name_len;
@@ -968,14 +1034,16 @@ static int ps_read_process (long pid, procstat_t *ps, char *state)
        long long unsigned vmem_rss;
        long long unsigned stack_size;
 
+       ssize_t status;
+
        memset (ps, 0, sizeof (procstat_t));
 
        ssnprintf (filename, sizeof (filename), "/proc/%li/stat", pid);
 
-       buffer_len = read_file_contents (filename,
-                       buffer, sizeof(buffer) - 1);
-       if (buffer_len <= 0)
+       status = read_file_contents (filename, buffer, sizeof(buffer) - 1);
+       if (status <= 0)
                return (-1);
+       buffer_len = (size_t) status;
        buffer[buffer_len] = 0;
 
        /* The name of the process is enclosed in parens. Since the name can
@@ -984,13 +1052,11 @@ static int ps_read_process (long pid, procstat_t *ps, char *state)
         * strchr(3) and strrchr(3) to avoid pointer arithmetic which would
         * otherwise be required to determine name_len. */
        name_start_pos = 0;
-       while ((buffer[name_start_pos] != '(')
-                       && (name_start_pos < buffer_len))
+       while (name_start_pos < buffer_len && buffer[name_start_pos] != '(')
                name_start_pos++;
 
        name_end_pos = buffer_len;
-       while ((buffer[name_end_pos] != ')')
-                       && (name_end_pos > 0))
+       while (name_end_pos > 0 && buffer[name_end_pos] != ')')
                name_end_pos--;
 
        /* Either '(' or ')' is not found or they are in the wrong order.
@@ -1030,11 +1096,16 @@ static int ps_read_process (long pid, procstat_t *ps, char *state)
        }
        else
        {
-               if ( (ps->num_lwp = ps_read_tasks (pid)) == -1 )
+               ps->num_lwp = strtoul (fields[17], /* endptr = */ NULL, /* base = */ 10);
+               if ((ps_read_status(pid, ps)) == NULL)
                {
-                       /* returns -1 => kernel 2.4 */
-                       ps->num_lwp = 1;
+                       /* No VMem data */
+                       ps->vmem_data = -1;
+                       ps->vmem_code = -1;
+                       DEBUG("ps_read_process: did not get vmem data for pid %li", pid);
                }
+               if (ps->num_lwp == 0)
+                       ps->num_lwp = 1;
                ps->num_proc = 1;
        }
 
@@ -1067,14 +1138,6 @@ static int ps_read_process (long pid, procstat_t *ps, char *state)
        cpu_system_counter = cpu_system_counter * 1000000 / CONFIG_HZ;
        vmem_rss = vmem_rss * pagesize_g;
 
-       if ( (ps_read_vmem(pid, ps)) == NULL)
-       {
-               /* No VMem data */
-               ps->vmem_data = -1;
-               ps->vmem_code = -1;
-               DEBUG("ps_read_process: did not get vmem data for pid %li", pid);
-       }
-
        ps->cpu_user_counter = cpu_user_counter;
        ps->cpu_system_counter = cpu_system_counter;
        ps->vmem_size = (unsigned long) vmem_size;
@@ -1092,6 +1155,18 @@ static int ps_read_process (long pid, procstat_t *ps, char *state)
                DEBUG("ps_read_process: not get io data for pid %li", pid);
        }
 
+       if ( report_ctx_switch )
+       {
+               if ( (ps_read_tasks_status(pid, ps)) == NULL)
+               {
+                       ps->cswitch_vol = -1;
+                       ps->cswitch_invol = -1;
+
+                       DEBUG("ps_read_tasks_status: not get context "
+                                       "switch data for pid %li", pid);
+               }
+       }
+
        /* success */
        return (0);
 } /* int ps_read_process (...) */
@@ -1153,7 +1228,7 @@ static char *ps_get_cmdline (long pid, char *name, char *buf, size_t buf_len)
                buf_ptr += status;
                len     -= status;
 
-               if (len <= 0)
+               if (len == 0)
                        break;
        }
 
@@ -1242,16 +1317,16 @@ static char *ps_get_cmdline (long pid, char *name __attribute__((unused)), /* {{
 {
        char path[PATH_MAX];
        psinfo_t info;
-       int status;
+       ssize_t status;
 
        snprintf(path, sizeof (path), "/proc/%li/psinfo", pid);
 
        status = read_file_contents (path, (void *) &info, sizeof (info));
-       if (status != sizeof (info))
+       if ((status < 0) || (((size_t) status) != sizeof (info)))
        {
                ERROR ("processes plugin: Unexpected return value "
                                "while reading \"%s\": "
-                               "Returned %i but expected %zu.",
+                               "Returned %zd but expected %zu.",
                                path, status, buffer_size);
                return (NULL);
        }
@@ -1283,18 +1358,15 @@ static int ps_read_process(long pid, procstat_t *ps, char *state)
        snprintf(f_usage, sizeof (f_usage), "/proc/%li/usage", pid);
 
 
-       buffer = malloc(sizeof (pstatus_t));
-       memset(buffer, 0, sizeof (pstatus_t));
+       buffer = calloc(1, sizeof (pstatus_t));
        read_file_contents(filename, buffer, sizeof (pstatus_t));
        myStatus = (pstatus_t *) buffer;
 
-       buffer = malloc(sizeof (psinfo_t));
-       memset(buffer, 0, sizeof(psinfo_t));
+       buffer = calloc(1, sizeof (psinfo_t));
        read_file_contents(f_psinfo, buffer, sizeof (psinfo_t));
        myInfo = (psinfo_t *) buffer;
 
-       buffer = malloc(sizeof (prusage_t));
-       memset(buffer, 0, sizeof(prusage_t));
+       buffer = calloc(1, sizeof (prusage_t));
        read_file_contents(f_usage, buffer, sizeof (prusage_t));
        myUsage = (prusage_t *) buffer;
 
@@ -1352,6 +1424,12 @@ static int ps_read_process(long pid, procstat_t *ps, char *state)
        ps->io_syscr = myUsage->pr_sysc;
        ps->io_syscw = myUsage->pr_sysc;
 
+       /*
+        * TODO: context switch counters for Solaris
+   */
+       ps->cswitch_vol   = -1;
+       ps->cswitch_invol = -1;
+
 
        /*
         * TODO: Find way of setting BLOCKED and PAGING status
@@ -1383,16 +1461,15 @@ static int ps_read_process(long pid, procstat_t *ps, char *state)
  * are retrieved from kstat (module cpu, name sys, class misc, stat nthreads).
  * The result is the sum for all the threads created on each cpu
  */
-static int read_fork_rate()
+static int read_fork_rate (void)
 {
        extern kstat_ctl_t *kc;
-       kstat_t *ksp_chain = NULL;
        derive_t result = 0;
 
        if (kc == NULL)
                return (-1);
 
-       for (ksp_chain = kc->kc_chain;
+       for (kstat_t *ksp_chain = kc->kc_chain;
                        ksp_chain != NULL;
                        ksp_chain = ksp_chain->ks_next)
        {
@@ -1458,17 +1535,14 @@ static int ps_read (void)
 #if HAVE_THREAD_INFO
        kern_return_t            status;
 
-       int                      pset;
        processor_set_t          port_pset_priv;
 
-       int                      task;
        task_array_t             task_list;
        mach_msg_type_number_t   task_list_len;
 
        int                      task_pid;
        char                     task_name[MAXCOMLEN + 1];
 
-       int                      thread;
        thread_act_array_t       thread_list;
        mach_msg_type_number_t   thread_list_len;
        thread_basic_info_data_t thread_data;
@@ -1493,7 +1567,7 @@ static int ps_read (void)
         * Tasks are assigned to sets of processors, so that's where you go to
         * get a list.
         */
-       for (pset = 0; pset < pset_list_len; pset++)
+       for (int pset = 0; pset < pset_list_len; pset++)
        {
                if ((status = host_processor_set_priv (port_host_self,
                                                pset_list[pset],
@@ -1514,7 +1588,7 @@ static int ps_read (void)
                        continue;
                }
 
-               for (task = 0; task < task_list_len; task++)
+               for (int task = 0; task < task_list_len; task++)
                {
                        ps = NULL;
                        if (mach_get_task_name (task_list[task],
@@ -1589,6 +1663,10 @@ static int ps_read (void)
 
                                pse.cpu_user_counter = task_absolutetime_info.total_user;
                                pse.cpu_system_counter = task_absolutetime_info.total_system;
+
+                               /* context switch counters not implemented */
+                               pse.cswitch_vol   = -1;
+                               pse.cswitch_invol = -1;
                        }
 
                        status = task_threads (task_list[task], &thread_list,
@@ -1608,7 +1686,7 @@ static int ps_read (void)
                                continue; /* with next task_list */
                        }
 
-                       for (thread = 0; thread < thread_list_len; thread++)
+                       for (int thread = 0; thread < thread_list_len; thread++)
                        {
                                thread_data_len = THREAD_BASIC_INFO_COUNT;
                                status = thread_info (thread_list[thread],
@@ -1739,8 +1817,6 @@ static int ps_read (void)
        procstat_entry_t pse;
        char       state;
 
-       procstat_t *ps_ptr;
-
        running = sleeping = zombies = stopped = paging = blocked = 0;
        ps_list_reset ();
 
@@ -1794,6 +1870,9 @@ static int ps_read (void)
                pse.io_syscr = ps.io_syscr;
                pse.io_syscw = ps.io_syscw;
 
+               pse.cswitch_vol = ps.cswitch_vol;
+               pse.cswitch_invol = ps.cswitch_invol;
+
                switch (state)
                {
                        case 'R': running++;  break;
@@ -1818,7 +1897,7 @@ static int ps_read (void)
        ps_submit_state ("paging",   paging);
        ps_submit_state ("blocked",  blocked);
 
-       for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+       for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
                ps_submit_proc_list (ps_ptr);
 
        read_fork_rate();
@@ -1838,9 +1917,7 @@ static int ps_read (void)
        struct kinfo_proc *procs;          /* array of processes */
        struct kinfo_proc *proc_ptr = NULL;
        int count;                         /* returns number of processes */
-       int i;
 
-       procstat_t *ps_ptr;
        procstat_entry_t pse;
 
        ps_list_reset ();
@@ -1865,7 +1942,7 @@ static int ps_read (void)
        }
 
        /* Iterate through the processes in kinfo_proc */
-       for (i = 0; i < count; i++)
+       for (int i = 0; i < count; i++)
        {
                /* Create only one process list entry per _process_, i.e.
                 * filter out threads (duplicate PID entries). */
@@ -1939,6 +2016,10 @@ static int ps_read (void)
                        pse.io_syscr = -1;
                        pse.io_syscw = -1;
 
+                       /* context switch counters not implemented */
+                       pse.cswitch_vol   = -1;
+                       pse.cswitch_invol = -1;
+
                        ps_list_add (procs[i].ki_comm, have_cmdline ? cmdline : NULL, &pse);
 
                        switch (procs[i].ki_stat)
@@ -1964,7 +2045,7 @@ static int ps_read (void)
        ps_submit_state ("idle",     idle);
        ps_submit_state ("wait",     wait);
 
-       for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+       for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
                ps_submit_proc_list (ps_ptr);
 /* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD */
 
@@ -1982,9 +2063,7 @@ static int ps_read (void)
        struct kinfo_proc *procs;          /* array of processes */
        struct kinfo_proc *proc_ptr = NULL;
        int count;                         /* returns number of processes */
-       int i;
 
-       procstat_t *ps_ptr;
        procstat_entry_t pse;
 
        ps_list_reset ();
@@ -2009,7 +2088,7 @@ static int ps_read (void)
        }
 
        /* Iterate through the processes in kinfo_proc */
-       for (i = 0; i < count; i++)
+       for (int i = 0; i < count; i++)
        {
                /* Create only one process list entry per _process_, i.e.
                 * filter out threads (duplicate PID entries). */
@@ -2072,6 +2151,10 @@ static int ps_read (void)
                        pse.io_syscr = -1;
                        pse.io_syscw = -1;
 
+                       /* context switch counters not implemented */
+                       pse.cswitch_vol   = -1;
+                       pse.cswitch_invol = -1;
+
                        ps_list_add (procs[i].p_comm, have_cmdline ? cmdline : NULL, &pse);
 
                        switch (procs[i].p_stat)
@@ -2097,7 +2180,7 @@ static int ps_read (void)
        ps_submit_state ("idle",     idle);
        ps_submit_state ("dead",     dead);
 
-       for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+       for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
                ps_submit_proc_list (ps_ptr);
 /* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_OPENBSD */
 
@@ -2113,7 +2196,6 @@ static int ps_read (void)
        pid_t pindex = 0;
        int nprocs;
 
-       procstat_t *ps;
        procstat_entry_t pse;
 
        ps_list_reset ();
@@ -2121,9 +2203,7 @@ static int ps_read (void)
                                        /* fdsinfo = */ NULL, sizeof(struct fdsinfo64),
                                        &pindex, MAXPROCENTRY)) > 0)
        {
-               int i;
-
-               for (i = 0; i < nprocs; i++)
+               for (int i = 0; i < nprocs; i++)
                {
                        tid64_t thindex;
                        int nthreads;
@@ -2218,6 +2298,9 @@ static int ps_read (void)
                        pse.io_syscr = -1;
                        pse.io_syscw = -1;
 
+                       pse.cswitch_vol   = -1;
+                       pse.cswitch_invol = -1;
+
                        ps_list_add (cmdline, cargs, &pse);
                } /* for (i = 0 .. nprocs) */
 
@@ -2231,7 +2314,7 @@ static int ps_read (void)
        ps_submit_state ("paging",   paging);
        ps_submit_state ("blocked",  blocked);
 
-       for (ps = list_head_g; ps != NULL; ps = ps->next)
+       for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next)
                ps_submit_proc_list (ps);
 /* #endif HAVE_PROCINFO_H */
 
@@ -2255,7 +2338,6 @@ static int ps_read (void)
        DIR *proc;
 
        int status;
-       procstat_t *ps_ptr;
        char state;
 
        char cmdline[PRARGSZ];
@@ -2314,6 +2396,9 @@ static int ps_read (void)
                pse.io_syscr = ps.io_syscr;
                pse.io_syscw = ps.io_syscw;
 
+               pse.cswitch_vol = -1;
+               pse.cswitch_invol = -1;
+
                switch (state)
                {
                        case 'R': running++;  break;
@@ -2342,7 +2427,7 @@ static int ps_read (void)
        ps_submit_state ("system",   system);
        ps_submit_state ("orphan",   orphan);
 
-       for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+       for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
                ps_submit_proc_list (ps_ptr);
 
        read_fork_rate();
index 1a39aad..208da8b 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_ignorelist.h"
@@ -48,7 +49,7 @@ static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
 static ignorelist_t *values_list = NULL;
 
-/* 
+/*
  * Functions
  */
 static void submit (const char *protocol_name,
index b5c01aa..83748b4 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *   Sven Trenkel <collectd at semidefinite.de>  
+ *   Sven Trenkel <collectd at semidefinite.de>
  **/
 
 #include <Python.h>
 #include <structmember.h>
 
 #include "collectd.h"
+
 #include "common.h"
 
 #include "cpython.h"
@@ -57,11 +58,11 @@ static char children_doc[] = "This is a tuple of child nodes. For most nodes thi
 
 static PyObject *Config_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
        Config *self;
-       
+
        self = (Config *) type->tp_alloc(type, 0);
        if (self == NULL)
                return NULL;
-       
+
        self->parent = NULL;
        self->key = NULL;
        self->values = NULL;
@@ -73,11 +74,11 @@ static int Config_init(PyObject *s, PyObject *args, PyObject *kwds) {
        PyObject *key = NULL, *parent = NULL, *values = NULL, *children = NULL, *tmp;
        Config *self = (Config *) s;
        static char *kwlist[] = {"key", "parent", "values", "children", NULL};
-       
+
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist,
                        &key, &parent, &values, &children))
                return -1;
-       
+
        if (!IS_BYTES_OR_UNICODE(key)) {
                PyErr_SetString(PyExc_TypeError, "argument 1 must be str");
                Py_XDECREF(parent);
@@ -122,7 +123,7 @@ static PyObject *Config_repr(PyObject *s) {
        Config *self = (Config *) s;
        PyObject *ret = NULL;
        static PyObject *node_prefix = NULL, *root_prefix = NULL, *ending = NULL;
-       
+
        /* This is ok because we have the GIL, so this is thread-save by default. */
        if (node_prefix == NULL)
                node_prefix = cpy_string_to_unicode_or_bytes("<collectd.Config node ");
@@ -132,7 +133,7 @@ static PyObject *Config_repr(PyObject *s) {
                ending = cpy_string_to_unicode_or_bytes(">");
        if (node_prefix == NULL || root_prefix == NULL || ending == NULL)
                return NULL;
-       
+
        ret = PyObject_Str(self->key);
        CPY_SUBSTITUTE(PyObject_Repr, ret, ret);
        if (self->parent == NULL || self->parent == Py_None)
@@ -140,7 +141,7 @@ static PyObject *Config_repr(PyObject *s) {
        else
                CPY_STRCAT(&ret, node_prefix);
        CPY_STRCAT(&ret, ending);
-       
+
        return ret;
 }
 
index c752414..24046de 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *   Sven Trenkel <collectd at semidefinite.de>  
+ *   Sven Trenkel <collectd at semidefinite.de>
  **/
 
 #include <Python.h>
 #include <structmember.h>
 
 #include <signal.h>
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
 
 #include "collectd.h"
+
 #include "common.h"
 
 #include "cpython.h"
@@ -221,7 +219,9 @@ static char reg_shutdown_doc[] = "register_shutdown(callback[, data][, name]) ->
                "    data if it was supplied.";
 
 
-static int do_interactive = 0;
+static pthread_t main_thread;
+static PyOS_sighandler_t python_sigint_handler;
+static _Bool do_interactive = 0;
 
 /* This is our global thread state. Python saves some stuff in thread-local
  * storage. So if we allow the interpreter to run in the background
@@ -250,16 +250,16 @@ static void cpy_destroy_user_data(void *data) {
 static void cpy_build_name(char *buf, size_t size, PyObject *callback, const char *name) {
        const char *module = NULL;
        PyObject *mod = NULL;
-       
+
        if (name != NULL) {
                snprintf(buf, size, "python.%s", name);
                return;
        }
-       
+
        mod = PyObject_GetAttrString(callback, "__module__"); /* New reference. */
        if (mod != NULL)
                module = cpy_unicode_or_bytes_to_string(&mod);
-       
+
        if (module != NULL) {
                snprintf(buf, size, "python.%s", module);
                Py_XDECREF(mod);
@@ -267,16 +267,16 @@ static void cpy_build_name(char *buf, size_t size, PyObject *callback, const cha
                return;
        }
        Py_XDECREF(mod);
-       
+
        snprintf(buf, size, "python.%p", callback);
        PyErr_Clear();
 }
 
 void cpy_log_exception(const char *context) {
-       int l = 0, i;
+       int l = 0;
        const char *typename = NULL, *message = NULL;
        PyObject *type, *value, *traceback, *tn, *m, *list;
-       
+
        PyErr_Fetch(&type, &value, &traceback);
        PyErr_NormalizeException(&type, &value, &traceback);
        if (type == NULL) return;
@@ -306,7 +306,7 @@ void cpy_log_exception(const char *context) {
        if (list)
                l = PyObject_Length(list);
 
-       for (i = 0; i < l; ++i) {
+       for (int i = 0; i < l; ++i) {
                PyObject *line;
                char const *msg;
                char *cpy;
@@ -355,7 +355,6 @@ static int cpy_read_callback(user_data_t *data) {
 }
 
 static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_list, user_data_t *data) {
-       int i;
        cpy_callback_t *c = data->data;
        PyObject *ret, *list, *temp, *dict = NULL;
        Values *v;
@@ -366,24 +365,15 @@ static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_li
                        cpy_log_exception("write callback");
                        CPY_RETURN_FROM_THREADS 0;
                }
-               for (i = 0; i < value_list->values_len; ++i) {
+               for (size_t i = 0; i < value_list->values_len; ++i) {
                        if (ds->ds[i].type == DS_TYPE_COUNTER) {
-                               if ((long) value_list->values[i].counter == value_list->values[i].counter)
-                                       PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].counter));
-                               else
-                                       PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
+                               PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
                        } else if (ds->ds[i].type == DS_TYPE_GAUGE) {
                                PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].gauge));
                        } else if (ds->ds[i].type == DS_TYPE_DERIVE) {
-                               if ((long) value_list->values[i].derive == value_list->values[i].derive)
-                                       PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].derive));
-                               else
-                                       PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
+                               PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
                        } else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) {
-                               if ((long) value_list->values[i].absolute == value_list->values[i].absolute)
-                                       PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].absolute));
-                               else
-                                       PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
+                               PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
                        } else {
                                Py_BEGIN_ALLOW_THREADS
                                ERROR("cpy_write_callback: Unknown value type %d.", ds->ds[i].type);
@@ -404,14 +394,14 @@ static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_li
                        meta_data_t *meta = value_list->meta;
 
                        num = meta_data_toc(meta, &table);
-                       for (i = 0; i < num; ++i) {
+                       for (size_t i = 0; i < num; ++i) {
                                int type;
                                char *string;
                                int64_t si;
                                uint64_t ui;
                                double d;
                                _Bool b;
-                               
+
                                type = meta_data_type(meta, table[i]);
                                if (type == MD_TYPE_STRING) {
                                        if (meta_data_get_string(meta, table[i], &string))
@@ -549,7 +539,7 @@ static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args
        char *name = NULL;
        PyObject *callback = NULL, *data = NULL, *mod = NULL;
        static char *kwlist[] = {"callback", "data", "name", NULL};
-       
+
        if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
        if (PyCallable_Check(callback) == 0) {
                PyMem_Free(name);
@@ -561,10 +551,9 @@ static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args
        Py_INCREF(callback);
        Py_XINCREF(data);
 
-       c = malloc(sizeof(*c));
+       c = calloc(1, sizeof(*c));
        if (c == NULL)
                return NULL;
-       memset (c, 0, sizeof (*c));
 
        c->name = strdup(buf);
        c->callback = callback;
@@ -584,7 +573,6 @@ static PyObject *float_or_none(float number) {
 }
 
 static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
-       int i;
        char *name;
        const data_set_t *ds;
        PyObject *list, *tuple;
@@ -597,7 +585,7 @@ static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
                return NULL;
        }
        list = PyList_New(ds->ds_num); /* New reference. */
-       for (i = 0; i < ds->ds_num; ++i) {
+       for (size_t i = 0; i < ds->ds_num; ++i) {
                tuple = PyTuple_New(4);
                PyTuple_SET_ITEM(tuple, 0, cpy_string_to_unicode_or_bytes(ds->ds[i].name));
                PyTuple_SET_ITEM(tuple, 1, cpy_string_to_unicode_or_bytes(DS_TYPE_TO_STRING(ds->ds[i].type)));
@@ -612,7 +600,7 @@ static PyObject *cpy_flush(PyObject *self, PyObject *args, PyObject *kwds) {
        int timeout = -1;
        char *plugin = NULL, *identifier = NULL;
        static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
-       
+
        if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin, &timeout, NULL, &identifier) == 0) return NULL;
        Py_BEGIN_ALLOW_THREADS
        plugin_flush(plugin, timeout, identifier);
@@ -636,11 +624,11 @@ static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObjec
        char buf[512];
        reg_function_t *register_function = (reg_function_t *) reg;
        cpy_callback_t *c = NULL;
-       user_data_t user_data;
+       user_data_t user_data = { 0 };
        char *name = NULL;
        PyObject *callback = NULL, *data = NULL;
        static char *kwlist[] = {"callback", "data", "name", NULL};
-       
+
        if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
        if (PyCallable_Check(callback) == 0) {
                PyMem_Free(name);
@@ -649,21 +637,19 @@ static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObjec
        }
        cpy_build_name(buf, sizeof(buf), callback, name);
        PyMem_Free(name);
-       
+
        Py_INCREF(callback);
        Py_XINCREF(data);
 
-       c = malloc(sizeof(*c));
+       c = calloc(1, sizeof(*c));
        if (c == NULL)
                return NULL;
-       memset (c, 0, sizeof (*c));
 
        c->name = strdup(buf);
        c->callback = callback;
        c->data = data;
        c->next = NULL;
 
-       memset (&user_data, 0, sizeof (user_data));
        user_data.free_func = cpy_destroy_user_data;
        user_data.data = c;
 
@@ -674,13 +660,12 @@ static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObjec
 static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwds) {
        char buf[512];
        cpy_callback_t *c = NULL;
-       user_data_t user_data;
+       user_data_t user_data = { 0 };
        double interval = 0;
        char *name = NULL;
        PyObject *callback = NULL, *data = NULL;
-       struct timespec ts;
        static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
-       
+
        if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback, &interval, &data, NULL, &name) == 0) return NULL;
        if (PyCallable_Check(callback) == 0) {
                PyMem_Free(name);
@@ -689,29 +674,24 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwd
        }
        cpy_build_name(buf, sizeof(buf), callback, name);
        PyMem_Free(name);
-       
+
        Py_INCREF(callback);
        Py_XINCREF(data);
 
-       c = malloc(sizeof(*c));
+       c = calloc(1, sizeof(*c));
        if (c == NULL)
                return NULL;
-       memset (c, 0, sizeof (*c));
 
        c->name = strdup(buf);
        c->callback = callback;
        c->data = data;
        c->next = NULL;
 
-       memset (&user_data, 0, sizeof (user_data));
        user_data.free_func = cpy_destroy_user_data;
        user_data.data = c;
 
-       ts.tv_sec = interval;
-       ts.tv_nsec = (interval - ts.tv_sec) * 1000000000;
        plugin_register_complex_read(/* group = */ "python", buf,
-                       cpy_read_callback, &ts, &user_data);
-
+                       cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), &user_data);
        return cpy_string_to_unicode_or_bytes(buf);
 }
 
@@ -914,14 +894,13 @@ static PyMethodDef cpy_methods[] = {
 };
 
 static int cpy_shutdown(void) {
-       cpy_callback_t *c;
        PyObject *ret;
-       
+
        /* This can happen if the module was loaded but not configured. */
        if (state != NULL)
                PyEval_RestoreThread(state);
 
-       for (c = cpy_shutdown_callbacks; c; c = c->next) {
+       for (cpy_callback_t *c = cpy_shutdown_callbacks; c; c = c->next) {
                ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
                if (ret == NULL)
                        cpy_log_exception("shutdown callback");
@@ -933,63 +912,52 @@ static int cpy_shutdown(void) {
        return 0;
 }
 
-static void cpy_int_handler(int sig) {
-       return;
-}
-
 static void *cpy_interactive(void *data) {
-       sigset_t sigset;
-       struct sigaction sig_int_action, old;
-       
+       PyOS_sighandler_t cur_sig;
+
        /* Signal handler in a plugin? Bad stuff, but the best way to
         * handle it I guess. In an interactive session people will
         * press Ctrl+C at some time, which will generate a SIGINT.
         * This will cause collectd to shutdown, thus killing the
         * interactive interpreter, and leaving the terminal in a
         * mess. Chances are, this isn't what the user wanted to do.
-        * 
+        *
         * So this is the plan:
-        * 1. Block SIGINT in the main thread.
-        * 2. Install our own signal handler that does nothing.
-        * 3. Unblock SIGINT in the interactive thread.
+        * 1. Restore Python's own signal handler
+        * 2. Tell Python we just forked so it will accept this thread
+        *    as the main one. No version of Python will ever handle
+        *    interrupts anywhere but in the main thread.
+        * 3. After the interactive loop is done, restore collectd's
+        *    SIGINT handler.
+        * 4. Raise SIGINT for a clean shutdown. The signal is sent to
+        *    the main thread to ensure it wakes up the main interval
+        *    sleep so that collectd shuts down immediately not in 10
+        *    seconds.
         *
         * This will make sure that SIGINT won't kill collectd but
-        * still interrupt syscalls like sleep and pause.
-        * It does not raise a KeyboardInterrupt exception because so
-        * far nobody managed to figure out how to do that. */
-       memset (&sig_int_action, '\0', sizeof (sig_int_action));
-       sig_int_action.sa_handler = cpy_int_handler;
-       sigaction (SIGINT, &sig_int_action, &old);
-       
-       sigemptyset(&sigset);
-       sigaddset(&sigset, SIGINT);
-       pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
+        * still interrupt syscalls like sleep and pause. */
+
        PyEval_AcquireThread(state);
        if (PyImport_ImportModule("readline") == NULL) {
                /* This interactive session will suck. */
                cpy_log_exception("interactive session init");
-       }
+       }
+       cur_sig = PyOS_setsig(SIGINT, python_sigint_handler);
+       /* We totally forked just now. Everyone saw that, right? */
+       PyOS_AfterFork();
        PyRun_InteractiveLoop(stdin, "<stdin>");
+       PyOS_setsig(SIGINT, cur_sig);
        PyErr_Print();
        PyEval_ReleaseThread(state);
        NOTICE("python: Interactive interpreter exited, stopping collectd ...");
-       /* Restore the original collectd SIGINT handler and raise SIGINT.
-        * The main thread still has SIGINT blocked and there's nothing we
-        * can do about that so this thread will handle it. But that's not
-        * important, except that it won't interrupt the main loop and so
-        * it might take a few seconds before collectd really shuts down. */
-       sigaction (SIGINT, &old, NULL);
-       raise(SIGINT);
-       pause();
+       pthread_kill(main_thread, SIGINT);
        return NULL;
 }
 
 static int cpy_init(void) {
-       cpy_callback_t *c;
        PyObject *ret;
        static pthread_t thread;
-       sigset_t sigset;
-       
+
        if (!Py_IsInitialized()) {
                WARNING("python: Plugin loaded but not configured.");
                plugin_unregister_shutdown("python");
@@ -997,17 +965,15 @@ static int cpy_init(void) {
        }
        PyEval_InitThreads();
        /* Now it's finally OK to use python threads. */
-       for (c = cpy_init_callbacks; c; c = c->next) {
+       for (cpy_callback_t *c = cpy_init_callbacks; c; c = c->next) {
                ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
                if (ret == NULL)
                        cpy_log_exception("init callback");
                else
                        Py_DECREF(ret);
        }
-       sigemptyset(&sigset);
-       sigaddset(&sigset, SIGINT);
-       pthread_sigmask(SIG_BLOCK, &sigset, NULL);
        state = PyEval_SaveThread();
+       main_thread = pthread_self();
        if (do_interactive) {
                if (plugin_thread_create(&thread, NULL, cpy_interactive, NULL)) {
                        ERROR("python: Error creating thread for interactive interpreter.");
@@ -1018,14 +984,13 @@ static int cpy_init(void) {
 }
 
 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
-       int i;
        PyObject *item, *values, *children, *tmp;
-       
+
        if (parent == NULL)
                parent = Py_None;
-       
+
        values = PyTuple_New(ci->values_num); /* New reference. */
-       for (i = 0; i < ci->values_num; ++i) {
+       for (int i = 0; i < ci->values_num; ++i) {
                if (ci->values[i].type == OCONFIG_TYPE_STRING) {
                        PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(ci->values[i].value.string));
                } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
@@ -1034,13 +999,13 @@ static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
                        PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
                }
        }
-       
+
        tmp = cpy_string_to_unicode_or_bytes(ci->key);
        item = PyObject_CallFunction((void *) &ConfigType, "NONO", tmp, parent, values, Py_None);
        if (item == NULL)
                return NULL;
        children = PyTuple_New(ci->children_num); /* New reference. */
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                PyTuple_SET_ITEM(children, i, cpy_oconfig_to_pyconfig(ci->children + i, item));
        }
        tmp = ((Config *) item)->children;
@@ -1064,6 +1029,7 @@ PyMODINIT_FUNC PyInit_collectd(void) {
 #endif
 
 static int cpy_init_python(void) {
+       PyOS_sighandler_t cur_sig;
        PyObject *sys;
        PyObject *module;
 
@@ -1074,9 +1040,12 @@ static int cpy_init_python(void) {
 #else
        char *argv = "";
 #endif
-       
+
+       /* Chances are the current signal handler is already SIG_DFL, but let's make sure. */
+       cur_sig = PyOS_setsig(SIGINT, SIG_DFL);
        Py_Initialize();
-       
+       python_sigint_handler = PyOS_setsig(SIGINT, cur_sig);
+
        PyType_Ready(&ConfigType);
        PyType_Ready(&PluginDataType);
        ValuesType.tp_base = &PluginDataType;
@@ -1127,8 +1096,8 @@ static int cpy_init_python(void) {
 }
 
 static int cpy_config(oconfig_item_t *ci) {
-       int i;
        PyObject *tb;
+       int status = 0;
 
        /* Ok in theory we shouldn't do initialization at this point
         * but we have to. In order to give python scripts a chance
@@ -1139,27 +1108,40 @@ static int cpy_config(oconfig_item_t *ci) {
 
        if (!Py_IsInitialized() && cpy_init_python()) return 1;
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *item = ci->children + i;
-               
+
                if (strcasecmp(item->key, "Interactive") == 0) {
-                       if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
+                       if (cf_util_get_boolean(item, &do_interactive) != 0) {
+                               status = 1;
                                continue;
-                       do_interactive = item->values[0].value.boolean;
+                       }
                } else if (strcasecmp(item->key, "Encoding") == 0) {
-                       if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_STRING)
+                       char *encoding = NULL;
+                       if (cf_util_get_string(item, &encoding) != 0) {
+                               status = 1;
                                continue;
+                       }
 #ifdef IS_PY3K
-                       NOTICE("python: \"Encoding\" was used in the config file but Python3 was used, which does not support changing encodings. Ignoring this.");
+                       ERROR("python: \"Encoding\" was used in the config file but Python3 was used, which does not support changing encodings");
+                       status = 1;
+                       sfree(encoding);
+                       continue;
 #else
                        /* Why is this even necessary? And undocumented? */
-                       if (PyUnicode_SetDefaultEncoding(item->values[0].value.string))
+                       if (PyUnicode_SetDefaultEncoding(encoding)) {
                                cpy_log_exception("setting default encoding");
+                               status = 1;
+                       }
 #endif
+                       sfree(encoding);
                } else if (strcasecmp(item->key, "LogTraces") == 0) {
-                       if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
+                       _Bool log_traces;
+                       if (cf_util_get_boolean(item, &log_traces) != 0) {
+                               status = 1;
                                continue;
-                       if (!item->values[0].value.boolean) {
+                       }
+                       if (!log_traces) {
                                Py_XDECREF(cpy_format_exception);
                                cpy_format_exception = NULL;
                                continue;
@@ -1169,43 +1151,53 @@ static int cpy_config(oconfig_item_t *ci) {
                        tb = PyImport_ImportModule("traceback"); /* New reference. */
                        if (tb == NULL) {
                                cpy_log_exception("python initialization");
+                               status = 1;
                                continue;
                        }
                        cpy_format_exception = PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
                        Py_DECREF(tb);
-                       if (cpy_format_exception == NULL)
+                       if (cpy_format_exception == NULL) {
                                cpy_log_exception("python initialization");
+                               status = 1;
+                       }
                } else if (strcasecmp(item->key, "ModulePath") == 0) {
                        char *dir = NULL;
                        PyObject *dir_object;
-                       
-                       if (cf_util_get_string(item, &dir) != 0) 
+
+                       if (cf_util_get_string(item, &dir) != 0) {
+                               status = 1;
                                continue;
+                       }
                        dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
                        if (dir_object == NULL) {
                                ERROR("python plugin: Unable to convert \"%s\" to "
                                      "a python object.", dir);
                                free(dir);
                                cpy_log_exception("python initialization");
+                               status = 1;
                                continue;
                        }
                        if (PyList_Insert(sys_path, 0, dir_object) != 0) {
                                ERROR("python plugin: Unable to prepend \"%s\" to "
                                      "python module path.", dir);
                                cpy_log_exception("python initialization");
+                               status = 1;
                        }
                        Py_DECREF(dir_object);
                        free(dir);
                } else if (strcasecmp(item->key, "Import") == 0) {
                        char *module_name = NULL;
                        PyObject *module;
-                       
-                       if (cf_util_get_string(item, &module_name) != 0) 
+
+                       if (cf_util_get_string(item, &module_name) != 0) {
+                               status = 1;
                                continue;
+                       }
                        module = PyImport_ImportModule(module_name); /* New reference. */
                        if (module == NULL) {
                                ERROR("python plugin: Error importing module \"%s\".", module_name);
                                cpy_log_exception("importing module");
+                               status = 1;
                        }
                        free(module_name);
                        Py_XDECREF(module);
@@ -1213,9 +1205,11 @@ static int cpy_config(oconfig_item_t *ci) {
                        char *name = NULL;
                        cpy_callback_t *c;
                        PyObject *ret;
-                       
-                       if (cf_util_get_string(item, &name) != 0)
+
+                       if (cf_util_get_string(item, &name) != 0) {
+                               status = 1;
                                continue;
+                       }
                        for (c = cpy_config_callbacks; c; c = c->next) {
                                if (strcasecmp(c->name + 7, name) == 0)
                                        break;
@@ -1234,15 +1228,17 @@ static int cpy_config(oconfig_item_t *ci) {
                        else
                                ret = PyObject_CallFunction(c->callback, "NO",
                                        cpy_oconfig_to_pyconfig(item, NULL), c->data); /* New reference. */
-                       if (ret == NULL)
+                       if (ret == NULL) {
                                cpy_log_exception("loading module");
-                       else
+                               status = 1;
+                       } else
                                Py_DECREF(ret);
                } else {
-                       WARNING("python plugin: Ignoring unknown config key \"%s\".", item->key);
+                       ERROR("python plugin: Unknown config key \"%s\".", item->key);
+                       status = 1;
                }
        }
-       return 0;
+       return (status);
 }
 
 void module_register(void) {
index 0ea81f8..a7cb792 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *   Sven Trenkel <collectd at semidefinite.de>  
+ *   Sven Trenkel <collectd at semidefinite.de>
  **/
 
 #include <Python.h>
 #include <structmember.h>
 
 #include "collectd.h"
+
 #include "common.h"
 
 #include "cpython.h"
@@ -45,7 +46,7 @@ static PyObject *cpy_common_repr(PyObject *s) {
        static PyObject *l_type = NULL, *l_type_instance = NULL, *l_plugin = NULL, *l_plugin_instance = NULL;
        static PyObject *l_host = NULL, *l_time = NULL;
        PluginData *self = (PluginData *) s;
-       
+
        if (l_type == NULL)
                l_type = cpy_string_to_unicode_or_bytes("(type=");
        if (l_type_instance == NULL)
@@ -58,10 +59,10 @@ static PyObject *cpy_common_repr(PyObject *s) {
                l_host = cpy_string_to_unicode_or_bytes(",host=");
        if (l_time == NULL)
                l_time = cpy_string_to_unicode_or_bytes(",time=");
-       
+
        if (!l_type || !l_type_instance || !l_plugin || !l_plugin_instance || !l_host || !l_time)
                return NULL;
-       
+
        ret = cpy_string_to_unicode_or_bytes(s->ob_type->tp_name);
 
        CPY_STRCAT(&ret, l_type);
@@ -106,19 +107,19 @@ static PyObject *cpy_common_repr(PyObject *s) {
        return ret;
 }
 
-static char time_doc[] = "This is the Unix timestap of the time this value was read.\n"
+static char time_doc[] = "This is the Unix timestamp of the time this value was read.\n"
                "For dispatching values this can be set to 0 which means \"now\".\n"
                "This means the time the value is actually dispatched, not the time\n"
                "it was set to 0.";
 
 static char host_doc[] = "The hostname of the host this value was read from.\n"
                "For dispatching this can be set to an empty string which means\n"
-               "the local hostname as defined in the collectd.conf.";
+               "the local hostname as defined in collectd.conf.";
 
 static char type_doc[] = "The type of this value. This type has to be defined\n"
-               "in your types.db. Attempting to set it to any other value will\n"
-               "raise a TypeError exception.\n"
-               "Assigning a type is mandetory, calling dispatch without doing\n"
+               "in the types.db file. Attempting to set it to any other value\n"
+               "will raise a TypeError exception.\n"
+               "Assigning a type is mandatory, calling dispatch without doing\n"
                "so will raise a RuntimeError exception.";
 
 static char type_instance_doc[] = "";
@@ -129,16 +130,16 @@ static char plugin_doc[] = "The name of the plugin that read the data. Setting t
 static char plugin_instance_doc[] = "";
 
 static char PluginData_doc[] = "This is an internal class that is the base for Values\n"
-               "and Notification. It is pretty useless by itself and was therefore not\n"
+               "and Notification. It is pretty useless by itself and is therefore not\n"
                "exported to the collectd module.";
 
 static PyObject *PluginData_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
        PluginData *self;
-       
+
        self = (PluginData *) type->tp_alloc(type, 0);
        if (self == NULL)
                return NULL;
-       
+
        self->time = 0;
        self->host[0] = 0;
        self->plugin[0] = 0;
@@ -154,11 +155,11 @@ static int PluginData_init(PyObject *s, PyObject *args, PyObject *kwds) {
        char *type = NULL, *plugin_instance = NULL, *type_instance = NULL, *plugin = NULL, *host = NULL;
        static char *kwlist[] = {"type", "plugin_instance", "type_instance",
                        "plugin", "host", "time", NULL};
-       
+
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetd", kwlist, NULL, &type,
                        NULL, &plugin_instance, NULL, &type_instance, NULL, &plugin, NULL, &host, &time))
                return -1;
-       
+
        if (type && plugin_get_ds(type) == NULL) {
                PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
                FreeAll();
@@ -180,13 +181,13 @@ static int PluginData_init(PyObject *s, PyObject *args, PyObject *kwds) {
 static PyObject *PluginData_repr(PyObject *s) {
        PyObject *ret;
        static PyObject *l_closing = NULL;
-       
+
        if (l_closing == NULL)
                l_closing = cpy_string_to_unicode_or_bytes(")");
-       
+
        if (l_closing == NULL)
                return NULL;
-       
+
        ret = cpy_common_repr(s);
        CPY_STRCAT(&ret, l_closing);
        return ret;
@@ -199,14 +200,14 @@ static PyMemberDef PluginData_members[] = {
 
 static PyObject *PluginData_getstring(PyObject *self, void *data) {
        const char *value = ((char *) self) + (intptr_t) data;
-       
+
        return cpy_string_to_unicode_or_bytes(value);
 }
 
 static int PluginData_setstring(PyObject *self, PyObject *value, void *data) {
        char *old;
        const char *new;
-       
+
        if (value == NULL) {
                PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
                return -1;
@@ -226,7 +227,7 @@ static int PluginData_setstring(PyObject *self, PyObject *value, void *data) {
 static int PluginData_settype(PyObject *self, PyObject *value, void *data) {
        char *old;
        const char *new;
-       
+
        if (value == NULL) {
                PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
                return -1;
@@ -312,8 +313,8 @@ static char interval_doc[] = "The interval is the timespan in seconds between tw
 static char values_doc[] = "These are the actual values that get dispatched to collectd.\n"
                "It has to be a sequence (a tuple or list) of numbers.\n"
                "The size of the sequence and the type of its content depend on the type\n"
-               "member your types.db file. For more information on this read the types.db\n"
-               "man page.\n"
+               "member in the types.db file. For more information on this read the\n"
+               "types.db man page.\n"
                "\n"
                "If the sequence does not have the correct size upon dispatch a RuntimeError\n"
                "exception will be raised. If the content of the sequence is not a number,\n"
@@ -322,7 +323,7 @@ static char values_doc[] = "These are the actual values that get dispatched to c
 static char meta_doc[] = "These are the meta data for this Value object.\n"
                "It has to be a dictionary of numbers, strings or bools. All keys must be\n"
                "strings. int and long objects will be dispatched as signed integers unless\n"
-               "they are between 2**63 and 2**64-1, which will result in a unsigned integer.\n"
+               "they are between 2**63 and 2**64-1, which will result in an unsigned integer.\n"
                "You can force one of these storage classes by using the classes\n"
                "collectd.Signed and collectd.Unsigned. A meta object received by a write\n"
                "callback will always contain Signed or Unsigned objects.";
@@ -340,7 +341,7 @@ static char dispatch_doc[] = "dispatch([type][, values][, plugin_instance][, typ
 static char write_doc[] = "write([destination][, type][, values][, plugin_instance][, type_instance]"
                "[, plugin][, host][, time][, interval]) -> None.  Dispatch a value list.\n"
                "\n"
-               "Write this instance to a single plugin or all plugins if 'destination' is obmitted.\n"
+               "Write this instance to a single plugin or all plugins if 'destination' is omitted.\n"
                "This will bypass the main collectd process and all filtering and caching.\n"
                "Other than that it works similar to 'dispatch'. In most cases 'dispatch' should be\n"
                "used instead of 'write'.\n";
@@ -349,11 +350,11 @@ static char Values_doc[] = "A Values object used for dispatching values to colle
 
 static PyObject *Values_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
        Values *self;
-       
+
        self = (Values *) PluginData_new(type, args, kwds);
        if (self == NULL)
                return NULL;
-       
+
        self->values = PyList_New(0);
        self->meta = PyDict_New();
        self->interval = 0;
@@ -367,12 +368,12 @@ static int Values_init(PyObject *s, PyObject *args, PyObject *kwds) {
        char *type = NULL, *plugin_instance = NULL, *type_instance = NULL, *plugin = NULL, *host = NULL;
        static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "interval", "meta", NULL};
-       
+
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist,
                        NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance,
                        NULL, &plugin, NULL, &host, &time, &interval, &meta))
                return -1;
-       
+
        if (type && plugin_get_ds(type) == NULL) {
                PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
                FreeAll();
@@ -394,18 +395,18 @@ static int Values_init(PyObject *s, PyObject *args, PyObject *kwds) {
        } else {
                Py_INCREF(values);
        }
-       
+
        if (meta == NULL) {
                meta = PyDict_New();
                PyErr_Clear();
        } else {
                Py_INCREF(meta);
        }
-       
+
        tmp = self->values;
        self->values = values;
        Py_XDECREF(tmp);
-       
+
        tmp = self->meta;
        self->meta = meta;
        Py_XDECREF(tmp);
@@ -415,10 +416,10 @@ static int Values_init(PyObject *s, PyObject *args, PyObject *kwds) {
 }
 
 static meta_data_t *cpy_build_meta(PyObject *meta) {
-       int i, s;
+       int s;
        meta_data_t *m = NULL;
        PyObject *l;
-       
+
        if ((meta == NULL) || (meta == Py_None))
                return NULL;
 
@@ -434,10 +435,10 @@ static meta_data_t *cpy_build_meta(PyObject *meta) {
        }
 
        m = meta_data_create();
-       for (i = 0; i < s; ++i) {
+       for (int i = 0; i < s; ++i) {
                const char *string, *keystring;
                PyObject *key, *value, *item, *tmp;
-               
+
                item = PyList_GET_ITEM(l, i);
                key = PyTuple_GET_ITEM(item, 0);
                Py_INCREF(key);
@@ -502,15 +503,15 @@ static meta_data_t *cpy_build_meta(PyObject *meta) {
 }
 
 static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
-       int i, ret;
+       int ret;
        const data_set_t *ds;
-       int size;
+       size_t size;
        value_t *value;
        value_list_t value_list = VALUE_LIST_INIT;
        PyObject *values = self->values, *meta = self->meta;
        double time = self->data.time, interval = self->interval;
        char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL, *type_instance = NULL;
-       
+
        static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "interval", "meta", NULL};
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist,
@@ -542,15 +543,15 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
                PyErr_Format(PyExc_TypeError, "meta must be a dict");
                return NULL;
        }
-       size = (int) PySequence_Length(values);
+       size = (size_t) PySequence_Length(values);
        if (size != ds->ds_num) {
-               PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", value_list.type, ds->ds_num, size);
+               PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu", value_list.type, ds->ds_num, size);
                return NULL;
        }
-       value = malloc(size * sizeof(*value));
-       for (i = 0; i < size; ++i) {
+       value = calloc(size, sizeof(*value));
+       for (size_t i = 0; i < size; ++i) {
                PyObject *item, *num;
-               item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
+               item = PySequence_Fast_GET_ITEM(values, (int) i); /* Borrowed reference. */
                switch (ds->ds[i].type) {
                case DS_TYPE_COUNTER:
                        num = PyNumber_Long(item); /* New reference. */
@@ -616,15 +617,15 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
 }
 
 static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
-       int i, ret;
+       int ret;
        const data_set_t *ds;
-       int size;
+       size_t size;
        value_t *value;
        value_list_t value_list = VALUE_LIST_INIT;
        PyObject *values = self->values, *meta = self->meta;
        double time = self->data.time, interval = self->interval;
        char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL, *type_instance = NULL, *dest = NULL;
-       
+
        static char *kwlist[] = {"destination", "type", "values", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "interval", "meta", NULL};
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|etOetetetetdiO", kwlist, NULL, &dest,
@@ -651,13 +652,13 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
                PyErr_Format(PyExc_TypeError, "values must be list or tuple");
                return NULL;
        }
-       size = (int) PySequence_Length(values);
+       size = (size_t) PySequence_Length(values);
        if (size != ds->ds_num) {
-               PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", value_list.type, ds->ds_num, size);
+               PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu", value_list.type, ds->ds_num, size);
                return NULL;
        }
-       value = malloc(size * sizeof(*value));
-       for (i = 0; i < size; ++i) {
+       value = calloc(size, sizeof(*value));
+       for (size_t i = 0; i < size; ++i) {
                PyObject *item, *num;
                item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
                switch (ds->ds[i].type) {
@@ -707,7 +708,7 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
        value_list.values_len = size;
        value_list.time = DOUBLE_TO_CDTIME_T(time);
        value_list.interval = DOUBLE_TO_CDTIME_T(interval);
-       value_list.meta = cpy_build_meta(meta);;
+       value_list.meta = cpy_build_meta(meta);
        if (value_list.host[0] == 0)
                sstrncpy(value_list.host, hostname_g, sizeof(value_list.host));
        if (value_list.plugin[0] == 0)
@@ -728,7 +729,7 @@ static PyObject *Values_repr(PyObject *s) {
        PyObject *ret, *tmp;
        static PyObject *l_interval = NULL, *l_values = NULL, *l_meta = NULL, *l_closing = NULL;
        Values *self = (Values *) s;
-       
+
        if (l_interval == NULL)
                l_interval = cpy_string_to_unicode_or_bytes(",interval=");
        if (l_values == NULL)
@@ -737,10 +738,10 @@ static PyObject *Values_repr(PyObject *s) {
                l_meta = cpy_string_to_unicode_or_bytes(",meta=");
        if (l_closing == NULL)
                l_closing = cpy_string_to_unicode_or_bytes(")");
-       
+
        if (l_interval == NULL || l_values == NULL || l_meta == NULL || l_closing == NULL)
                return NULL;
-       
+
        ret = cpy_common_repr(s);
        if (self->interval != 0) {
                CPY_STRCAT(&ret, l_interval);
@@ -854,12 +855,12 @@ static int Notification_init(PyObject *s, PyObject *args, PyObject *kwds) {
        char *type = NULL, *plugin_instance = NULL, *type_instance = NULL, *plugin = NULL, *host = NULL;
        static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "severity", NULL};
-       
+
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetetdi", kwlist,
                        NULL, &type, NULL, &message, NULL, &plugin_instance, NULL, &type_instance,
                        NULL, &plugin, NULL, &host, &time, &severity))
                return -1;
-       
+
        if (type && plugin_get_ds(type) == NULL) {
                PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
                FreeAll();
@@ -889,7 +890,7 @@ static PyObject *Notification_dispatch(Notification *self, PyObject *args, PyObj
        int severity = self->severity;
        char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL, *type_instance = NULL;
        char *message = NULL;
-       
+
        static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "severity", NULL};
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetetdi", kwlist,
@@ -937,11 +938,11 @@ static PyObject *Notification_dispatch(Notification *self, PyObject *args, PyObj
 
 static PyObject *Notification_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
        Notification *self;
-       
+
        self = (Notification *) PluginData_new(type, args, kwds);
        if (self == NULL)
                return NULL;
-       
+
        self->message[0] = 0;
        self->severity = 0;
        return (PyObject *) self;
@@ -950,7 +951,7 @@ static PyObject *Notification_new(PyTypeObject *type, PyObject *args, PyObject *
 static int Notification_setstring(PyObject *self, PyObject *value, void *data) {
        char *old;
        const char *new;
-       
+
        if (value == NULL) {
                PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
                return -1;
@@ -971,17 +972,17 @@ static PyObject *Notification_repr(PyObject *s) {
        PyObject *ret, *tmp;
        static PyObject *l_severity = NULL, *l_message = NULL, *l_closing = NULL;
        Notification *self = (Notification *) s;
-       
+
        if (l_severity == NULL)
                l_severity = cpy_string_to_unicode_or_bytes(",severity=");
        if (l_message == NULL)
                l_message = cpy_string_to_unicode_or_bytes(",message=");
        if (l_closing == NULL)
                l_closing = cpy_string_to_unicode_or_bytes(")");
-       
+
        if (l_severity == NULL || l_message == NULL || l_closing == NULL)
                return NULL;
-       
+
        ret = cpy_common_repr(s);
        if (self->severity != 0) {
                CPY_STRCAT(&ret, l_severity);
index 2586ca0..7395ba0 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
-#include <pthread.h>
 #include <sys/time.h>
 #include <hiredis/hiredis.h>
 
@@ -126,11 +126,10 @@ static redis_query_t *redis_config_query (oconfig_item_t *ci) /* {{{ */
 {
     redis_query_t *rq;
     int status;
-    int i;
 
     rq = calloc(1, sizeof(*rq));
     if (rq == NULL) {
-        ERROR("redis plugin: calloca failed adding redis_query.");
+        ERROR("redis plugin: calloc failed adding redis_query.");
         return NULL;
     }
     status = cf_util_get_string_buffer(ci, rq->query, sizeof(rq->query));
@@ -144,7 +143,7 @@ static redis_query_t *redis_config_query (oconfig_item_t *ci) /* {{{ */
     (void)sstrncpy(rq->instance, rq->query, sizeof(rq->instance));
     replace_special(rq->instance, sizeof(rq->instance));
 
-    for (i = 0; i < ci->children_num; i++) {
+    for (int i = 0; i < ci->children_num; i++) {
         oconfig_item_t *option = ci->children + i;
 
         if (strcasecmp("Type", option->key) == 0) {
@@ -166,23 +165,22 @@ static redis_query_t *redis_config_query (oconfig_item_t *ci) /* {{{ */
 
 static int redis_config_node (oconfig_item_t *ci) /* {{{ */
 {
-  redis_node_t rn;
   redis_query_t *rq;
-  int i;
   int status;
   int timeout;
 
-  memset (&rn, 0, sizeof (rn));
+  redis_node_t rn = {
+    .port = REDIS_DEF_PORT,
+    .timeout.tv_usec = REDIS_DEF_TIMEOUT
+  };
+
   sstrncpy (rn.host, REDIS_DEF_HOST, sizeof (rn.host));
-  rn.port = REDIS_DEF_PORT;
-  rn.timeout.tv_usec = REDIS_DEF_TIMEOUT;
-  rn.queries = NULL;
 
   status = cf_util_get_string_buffer (ci, rn.name, sizeof (rn.name));
   if (status != 0)
     return (status);
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
@@ -230,9 +228,7 @@ static int redis_config_node (oconfig_item_t *ci) /* {{{ */
 
 static int redis_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
@@ -304,7 +300,7 @@ static int redis_handle_info (char *node, char const *info_line, char const *typ
     int i;
 
     str += strlen (field_name) + 1; /* also skip the ':' */
-    for(i=0;(*str && (isdigit(*str) || *str == '.'));i++,str++)
+    for(i=0;(*str && (isdigit((unsigned char)*str) || *str == '.'));i++,str++)
       buf[i] = *str;
     buf[i] ='\0';
 
@@ -380,10 +376,7 @@ static int redis_handle_query (redisContext *rh, redis_node_t *rn, redis_query_t
 
 static int redis_read (void) /* {{{ */
 {
-  redis_node_t *rn;
-  redis_query_t *rq;
-
-  for (rn = nodes_head; rn != NULL; rn = rn->next)
+  for (redis_node_t *rn = nodes_head; rn != NULL; rn = rn->next)
   {
     redisContext *rh;
     redisReply   *rr;
@@ -431,12 +424,18 @@ static int redis_read (void) /* {{{ */
     redis_handle_info (rn->name, rr->str, "volatile_changes", NULL, "changes_since_last_save", DS_TYPE_GAUGE);
     redis_handle_info (rn->name, rr->str, "total_connections", NULL, "total_connections_received", DS_TYPE_DERIVE);
     redis_handle_info (rn->name, rr->str, "total_operations", NULL, "total_commands_processed", DS_TYPE_DERIVE);
+    redis_handle_info (rn->name, rr->str, "operations_per_second", NULL, "instantaneous_ops_per_sec", DS_TYPE_GAUGE);
     redis_handle_info (rn->name, rr->str, "expired_keys", NULL, "expired_keys", DS_TYPE_DERIVE);
+    redis_handle_info (rn->name, rr->str, "evicted_keys", NULL, "evicted_keys", DS_TYPE_DERIVE);
     redis_handle_info (rn->name, rr->str, "pubsub", "channels", "pubsub_channels", DS_TYPE_GAUGE);
     redis_handle_info (rn->name, rr->str, "pubsub", "patterns", "pubsub_patterns", DS_TYPE_GAUGE);
     redis_handle_info (rn->name, rr->str, "current_connections", "slaves", "connected_slaves", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "cache_result", "hits", "keyspace_hits", DS_TYPE_DERIVE);
+    redis_handle_info (rn->name, rr->str, "cache_result", "misses", "keyspace_misses", DS_TYPE_DERIVE);
+    redis_handle_info (rn->name, rr->str, "total_bytes", "input", "total_net_input_bytes", DS_TYPE_DERIVE);
+    redis_handle_info (rn->name, rr->str, "total_bytes", "output", "total_net_output_bytes", DS_TYPE_DERIVE);
 
-    for (rq = rn->queries; rq != NULL; rq = rq->next)
+    for (redis_query_t *rq = rn->queries; rq != NULL; rq = rq->next)
         redis_handle_query(rh, rn, rq);
 
 redis_fail:
diff --git a/src/riemann.proto b/src/riemann.proto
deleted file mode 100644 (file)
index 3e946a3..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-option java_package = "com.aphyr.riemann";
-option java_outer_classname = "Proto";
-
-message State {
-  optional int64 time = 1;
-  optional string state = 2;
-  optional string service = 3;
-  optional string host = 4;
-  optional string description = 5;
-  optional bool once = 6;
-  repeated string tags = 7;
-  optional float ttl = 8;
-}
-
-message Event {
-  optional int64 time = 1;
-  optional string state = 2;
-  optional string service = 3;
-  optional string host = 4;
-  optional string description = 5;
-  repeated string tags = 7;
-  optional float ttl = 8;
-  repeated Attribute attributes = 9;
-
-  optional sint64 metric_sint64 = 13;
-  optional double metric_d = 14;
-  optional float metric_f = 15;
-}
-
-message Query {
-  optional string string = 1;
-}
-
-message Msg {
-  optional bool ok = 2;
-  optional string error = 3;
-  repeated State states = 4;
-  optional Query query = 5;
-  repeated Event events = 6;
-}
-
-message Attribute {
-  required string key = 1;
-  optional string value = 2;
-}
index 4863d7c..a270f48 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -326,12 +327,10 @@ static int cr_config_router (oconfig_item_t *ci) /* {{{ */
   char read_name[128];
   user_data_t user_data;
   int status;
-  int i;
 
-  router_data = malloc (sizeof (*router_data));
+  router_data = calloc (1, sizeof (*router_data));
   if (router_data == NULL)
     return (-1);
-  memset (router_data, 0, sizeof (*router_data));
   router_data->connection = NULL;
   router_data->node = NULL;
   router_data->service = NULL;
@@ -339,7 +338,7 @@ static int cr_config_router (oconfig_item_t *ci) /* {{{ */
   router_data->password = NULL;
 
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -414,7 +413,7 @@ static int cr_config_router (oconfig_item_t *ci) /* {{{ */
   user_data.free_func = (void *) cr_free_data;
   if (status == 0)
     status = plugin_register_complex_read (/* group = */ NULL, read_name,
-       cr_read, /* interval = */ NULL, &user_data);
+       cr_read, /* interval = */ 0, &user_data);
 
   if (status != 0)
     cr_free_data (router_data);
@@ -424,9 +423,7 @@ static int cr_config_router (oconfig_item_t *ci) /* {{{ */
 
 static int cr_config (oconfig_item_t *ci)
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
index 645032c..0425419 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "utils_rrdcreate.h"
@@ -69,7 +70,6 @@ static int value_list_to_string (char *buffer, int buffer_len,
 {
   int offset;
   int status;
-  int i;
   time_t t;
 
   assert (0 == strcmp (ds->type, vl->type));
@@ -82,7 +82,7 @@ static int value_list_to_string (char *buffer, int buffer_len,
     return (-1);
   offset = status;
 
-  for (i = 0; i < ds->ds_num; i++)
+  for (size_t i = 0; i < ds->ds_num; i++)
   {
     if ((ds->ds[i].type != DS_TYPE_COUNTER)
         && (ds->ds[i].type != DS_TYPE_GAUGE)
@@ -95,7 +95,7 @@ static int value_list_to_string (char *buffer, int buffer_len,
       status = ssnprintf (buffer + offset, buffer_len - offset,
           ":%llu", vl->values[i].counter);
     }
-    else if (ds->ds[i].type == DS_TYPE_GAUGE) 
+    else if (ds->ds[i].type == DS_TYPE_GAUGE)
     {
       status = ssnprintf (buffer + offset, buffer_len - offset,
           ":%f", vl->values[i].gauge);
@@ -107,7 +107,7 @@ static int value_list_to_string (char *buffer, int buffer_len,
     else /* if (ds->ds[i].type == DS_TYPE_ABSOLUTE) */ {
       status = ssnprintf (buffer + offset, buffer_len - offset,
          ":%"PRIu64, vl->values[i].absolute);
+
     }
 
     if ((status < 1) || (status >= (buffer_len - offset)))
@@ -217,9 +217,7 @@ static int rc_config_add_timespan (int timespan)
 
 static int rc_config (oconfig_item_t *ci)
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t const *child = ci->children + i;
     const char *key = child->key;
@@ -293,7 +291,6 @@ static int rc_read (void)
 {
   int status;
   rrdc_stats_t *head;
-  rrdc_stats_t *ptr;
 
   value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
@@ -330,7 +327,7 @@ static int rc_read (void)
     return (-1);
   }
 
-  for (ptr = head; ptr != NULL; ptr = ptr->next)
+  for (rrdc_stats_t *ptr = head; ptr != NULL; ptr = ptr->next)
   {
     if (ptr->type == RRDC_STATS_TYPE_GAUGE)
       values[0].gauge = (gauge_t) ptr->value.gauge;
index 7cfdae6..094dd42 100644 (file)
@@ -24,6 +24,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "utils_avltree.h"
 
 #include <rrd.h>
 
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-
 /*
  * Private types
  */
@@ -166,7 +163,7 @@ static int srrd_update (char *filename, char *template,
        assert (template == NULL);
 
        new_argc = 2 + argc;
-       new_argv = (char **) malloc ((new_argc + 1) * sizeof (char *));
+       new_argv = malloc ((new_argc + 1) * sizeof (*new_argv));
        if (new_argv == NULL)
        {
                ERROR ("rrdtool plugin: malloc failed.");
@@ -204,7 +201,6 @@ static int value_list_to_string_multiple (char *buffer, int buffer_len,
        int offset;
        int status;
        time_t tt;
-       int i;
 
        memset (buffer, '\0', buffer_len);
 
@@ -214,7 +210,7 @@ static int value_list_to_string_multiple (char *buffer, int buffer_len,
                return (-1);
        offset = status;
 
-       for (i = 0; i < ds->ds_num; i++)
+       for (size_t i = 0; i < ds->ds_num; i++)
        {
                if ((ds->ds[i].type != DS_TYPE_COUNTER)
                                && (ds->ds[i].type != DS_TYPE_GAUGE)
@@ -335,7 +331,6 @@ static void *rrd_queue_thread (void __attribute__((unused)) *data)
                char **values;
                int    values_num;
                int    status;
-               int    i;
 
                values = NULL;
                values_num = 0;
@@ -416,7 +411,7 @@ static void *rrd_queue_thread (void __attribute__((unused)) *data)
                pthread_mutex_unlock (&queue_lock);
 
                /* We now need the cache lock so the entry isn't updated while
-                * we make a copy of it's values */
+                * we make a copy of its values */
                pthread_mutex_lock (&cache_lock);
 
                status = c_avl_get (cache, queue_entry->filename,
@@ -442,7 +437,7 @@ static void *rrd_queue_thread (void __attribute__((unused)) *data)
                }
 
                /* Update `tv_next_update' */
-               if (write_rate > 0.0) 
+               if (write_rate > 0.0)
                 {
                   gettimeofday (&tv_now, /* timezone = */ NULL);
                   tv_next_update.tv_sec = tv_now.tv_sec;
@@ -462,7 +457,7 @@ static void *rrd_queue_thread (void __attribute__((unused)) *data)
                                values_num, (values_num == 1) ? "" : "s",
                                queue_entry->filename);
 
-               for (i = 0; i < values_num; i++)
+               for (int i = 0; i < values_num; i++)
                {
                        sfree (values[i]);
                }
@@ -480,7 +475,7 @@ static int rrd_queue_enqueue (const char *filename,
 {
   rrd_queue_t *queue_entry;
 
-  queue_entry = (rrd_queue_t *) malloc (sizeof (rrd_queue_t));
+  queue_entry = malloc (sizeof (*queue_entry));
   if (queue_entry == NULL)
     return (-1);
 
@@ -522,7 +517,7 @@ static int rrd_queue_dequeue (const char *filename,
   {
     if (strcmp (this->filename, filename) == 0)
       break;
-    
+
     prev = this;
     this = this->next;
   }
@@ -560,7 +555,6 @@ static void rrd_cache_flush (cdtime_t timeout)
 
        char *key;
        c_avl_iterator_t *iter;
-       int i;
 
        DEBUG ("rrdtool plugin: Flushing cache, timeout = %.3f",
                        CDTIME_T_TO_DOUBLE (timeout));
@@ -588,7 +582,7 @@ static void rrd_cache_flush (cdtime_t timeout)
                }
                else /* ancient and no values -> waste of memory */
                {
-                       char **tmp = (char **) realloc ((void *) keys,
+                       char **tmp = realloc (keys,
                                        (keys_num + 1) * sizeof (char *));
                        if (tmp == NULL)
                        {
@@ -607,8 +601,8 @@ static void rrd_cache_flush (cdtime_t timeout)
                }
        } /* while (c_avl_iterator_next) */
        c_avl_iterator_destroy (iter);
-       
-       for (i = 0; i < keys_num; i++)
+
+       for (int i = 0; i < keys_num; i++)
        {
                if (c_avl_remove (cache, keys[i], (void *) &key, (void *) &rc) != 0)
                {
@@ -692,7 +686,7 @@ static int64_t rrd_get_random_variation (void)
   long min;
   long max;
 
-  if (random_timeout <= 0)
+  if (random_timeout == 0)
     return (0);
 
   /* Assure that "cache_timeout + random_variation" is never negative. */
@@ -756,7 +750,7 @@ static int rrd_cache_insert (const char *filename,
                return (-1);
        }
 
-       values_new = (char **) realloc ((void *) rc->values,
+       values_new = realloc ((void *) rc->values,
                        (rc->values_num + 1) * sizeof (char *));
        if (values_new == NULL)
        {
@@ -860,7 +854,6 @@ static int rrd_cache_destroy (void) /* {{{ */
   while (c_avl_pick (cache, &key, &value) == 0)
   {
     rrd_cache_t *rc;
-    int i;
 
     sfree (key);
     key = NULL;
@@ -871,7 +864,7 @@ static int rrd_cache_destroy (void) /* {{{ */
     if (rc->values_num > 0)
       non_empty++;
 
-    for (i = 0; i < rc->values_num; i++)
+    for (int i = 0; i < rc->values_num; i++)
       sfree (rc->values[i]);
     sfree (rc->values);
     sfree (rc);
@@ -1087,7 +1080,7 @@ static int rrd_config (const char *key, const char *value)
                while ((ptr = strtok_r (dummy, ", \t", &saveptr)) != NULL)
                {
                        dummy = NULL;
-                       
+
                        tmp_alloc = realloc (rrdcreate_config.timespans,
                                        sizeof (int) * (rrdcreate_config.timespans_num + 1));
                        if (tmp_alloc == NULL)
index dc6a210..de2a4f7 100644 (file)
@@ -18,7 +18,7 @@
  *
  * Authors:
  *   Florian octo Forster <octo at collectd.org>
- *   
+ *
  *   Lubos Stanek <lubek at users.sourceforge.net> Wed Oct 27, 2006
  *   - config ExtendedSensorNaming option
  *   - precise sensor feature selection (chip-bus-address/type-feature)
@@ -34,6 +34,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -76,7 +77,7 @@ struct sensors_labeltypes_s
 typedef struct sensors_labeltypes_s sensors_labeltypes_t;
 
 /* finite list of known labels extracted from lm_sensors */
-static sensors_labeltypes_t known_features[] = 
+static sensors_labeltypes_t known_features[] =
 {
        { "fan1", SENSOR_TYPE_FANSPEED },
        { "fan2", SENSOR_TYPE_FANSPEED },
@@ -140,7 +141,8 @@ static const char *config_keys[] =
 {
        "Sensor",
        "IgnoreSelected",
-       "SensorConfigFile"
+       "SensorConfigFile",
+       "UseLabels"
 };
 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
@@ -169,6 +171,7 @@ typedef struct featurelist
 } featurelist_t;
 
 static char *conffile = NULL;
+static _Bool use_labels = 0;
 /* #endif (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500) */
 
 #else /* if SENSORS_API_VERSION >= 0x500 */
@@ -176,7 +179,7 @@ static char *conffile = NULL;
        "as bug."
 #endif
 
-featurelist_t *first_feature = NULL;
+static featurelist_t *first_feature = NULL;
 static ignorelist_t *sensor_list;
 
 #if SENSORS_API_VERSION < 0x400
@@ -213,11 +216,9 @@ static int sensors_snprintf_chip_name (char *buf, size_t buf_size,
 
 static int sensors_feature_name_to_type (const char *name)
 {
-       int i;
-
        /* Yes, this is slow, but it's only ever done during initialization, so
         * it's a one time cost.. */
-       for (i = 0; i < known_features_num; i++)
+       for (int i = 0; i < known_features_num; i++)
                if (strcasecmp (known_features[i].label, name) == 0)
                        return (known_features[i].type);
 
@@ -257,6 +258,12 @@ static int sensors_config (const char *key, const char *value)
                if (IS_TRUE (value))
                        ignorelist_set_invert (sensor_list, 0);
        }
+#if (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500)
+       else if (strcasecmp (key, "UseLabels") == 0)
+       {
+               use_labels = IS_TRUE (value) ? 1 : 0;
+       }
+#endif
        else
        {
                return (-1);
@@ -267,7 +274,6 @@ static int sensors_config (const char *key, const char *value)
 
 static void sensors_free_features (void)
 {
-       featurelist_t *thisft;
        featurelist_t *nextft;
 
        if (first_feature == NULL)
@@ -275,7 +281,7 @@ static void sensors_free_features (void)
 
        sensors_cleanup ();
 
-       for (thisft = first_feature; thisft != NULL; thisft = nextft)
+       for (featurelist_t *thisft = first_feature; thisft != NULL; thisft = nextft)
        {
                nextft = thisft->next;
                sfree (thisft);
@@ -289,7 +295,7 @@ static int sensors_load_conf (void)
 
        FILE *fh = NULL;
        featurelist_t *last_feature = NULL;
-       
+
        const sensors_chip_name *chip;
        int chip_num;
 
@@ -378,13 +384,12 @@ static int sensors_load_conf (void)
                                continue;
                        }
 
-                       fl = (featurelist_t *) malloc (sizeof (featurelist_t));
+                       fl = calloc (1, sizeof (*fl));
                        if (fl == NULL)
                        {
-                               ERROR ("sensors plugin: malloc failed.");
+                               ERROR ("sensors plugin: calloc failed.");
                                continue;
                        }
-                       memset (fl, '\0', sizeof (featurelist_t));
 
                        fl->chip = chip;
                        fl->data = feature;
@@ -435,13 +440,12 @@ static int sensors_load_conf (void)
                                                && (subfeature->type != SENSORS_SUBFEATURE_POWER_INPUT))
                                        continue;
 
-                               fl = (featurelist_t *) malloc (sizeof (featurelist_t));
+                               fl = calloc (1, sizeof (*fl));
                                if (fl == NULL)
                                {
-                                       ERROR ("sensors plugin: malloc failed.");
+                                       ERROR ("sensors plugin: calloc failed.");
                                        continue;
                                }
-                               memset (fl, '\0', sizeof (featurelist_t));
 
                                fl->chip = chip;
                                fl->feature = feature;
@@ -515,13 +519,11 @@ static void sensors_submit (const char *plugin_instance,
 
 static int sensors_read (void)
 {
-       featurelist_t *fl;
-
        if (sensors_load_conf () != 0)
                return (-1);
 
 #if SENSORS_API_VERSION < 0x400
-       for (fl = first_feature; fl != NULL; fl = fl->next)
+       for (featurelist_t *fl = first_feature; fl != NULL; fl = fl->next)
        {
                double value;
                int status;
@@ -549,12 +551,13 @@ static int sensors_read (void)
 /* #endif SENSORS_API_VERSION < 0x400 */
 
 #elif (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500)
-       for (fl = first_feature; fl != NULL; fl = fl->next)
+       for (featurelist_t *fl = first_feature; fl != NULL; fl = fl->next)
        {
                double value;
                int status;
                char plugin_instance[DATA_MAX_NAME_LEN];
                char type_instance[DATA_MAX_NAME_LEN];
+               char *sensor_label;
                const char *type;
 
                status = sensors_get_value (fl->chip,
@@ -567,8 +570,17 @@ static int sensors_read (void)
                if (status < 0)
                        continue;
 
-               sstrncpy (type_instance, fl->feature->name,
-                               sizeof (type_instance));
+               if (use_labels)
+               {
+                       sensor_label = sensors_get_label (fl->chip, fl->feature);
+                       sstrncpy (type_instance, sensor_label, sizeof (type_instance));
+                       free (sensor_label);
+               }
+               else
+               {
+                       sstrncpy (type_instance, fl->feature->name,
+                                       sizeof (type_instance));
+               }
 
                if (fl->feature->type == SENSORS_FEATURE_IN)
                        type = "voltage";
index 4300822..cf7ad2a 100644 (file)
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -54,13 +55,6 @@ static int serial_read (void)
        FILE *fh;
        char buffer[1024];
 
-       derive_t rx = 0;
-       derive_t tx = 0;
-       
-       char *fields[16];
-       int i, numfields;
-       int len;
-
        /* there are a variety of names for the serial device */
        if ((fh = fopen ("/proc/tty/driver/serial", "r")) == NULL &&
                (fh = fopen ("/proc/tty/driver/ttyS", "r")) == NULL)
@@ -73,10 +67,15 @@ static int serial_read (void)
 
        while (fgets (buffer, sizeof (buffer), fh) != NULL)
        {
-               int have_rx = 0, have_tx = 0;
+               derive_t rx = 0;
+               derive_t tx = 0;
+               _Bool have_rx = 0, have_tx = 0;
+               size_t len;
 
-               numfields = strsplit (buffer, fields, 16);
+               char *fields[16];
+               int numfields;
 
+               numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
                if (numfields < 6)
                        continue;
 
@@ -84,14 +83,14 @@ static int serial_read (void)
                 * 0: uart:16550A port:000003F8 irq:4 tx:0 rx:0
                 * 1: uart:16550A port:000002F8 irq:3 tx:0 rx:0
                 */
-               len = strlen (fields[0]) - 1;
-               if (len < 1)
+               len = strlen (fields[0]);
+               if (len < 2)
                        continue;
-               if (fields[0][len] != ':')
+               if (fields[0][len - 1] != ':')
                        continue;
-               fields[0][len] = '\0';
+               fields[0][len - 1] = 0;
 
-               for (i = 1; i < numfields; i++)
+               for (int i = 1; i < numfields; i++)
                {
                        len = strlen (fields[i]);
                        if (len < 4)
@@ -99,20 +98,18 @@ static int serial_read (void)
 
                        if (strncmp (fields[i], "tx:", 3) == 0)
                        {
-                               tx = atoll (fields[i] + 3);
-                               have_tx++;
+                               if (strtoderive (fields[i] + 3, &tx) == 0)
+                                       have_tx = 1;
                        }
                        else if (strncmp (fields[i], "rx:", 3) == 0)
                        {
-                               rx = atoll (fields[i] + 3);
-                               have_rx++;
+                               if (strtoderive (fields[i] + 3, &rx) == 0)
+                                       have_rx = 1;
                        }
                }
 
-               if ((have_rx == 0) || (have_tx == 0))
-                       continue;
-
-               serial_submit (fields[0], rx, tx);
+               if (have_rx && have_tx)
+                       serial_submit (fields[0], rx, tx);
        }
 
        fclose (fh);
index 487f31a..4006455 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -27,7 +28,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
-#include <pthread.h>
 
 #include <glib.h>
 #include <libsigrok/libsigrok.h>
@@ -70,13 +70,11 @@ static int sigrok_log_callback(void*cb_data __attribute__((unused)),
 static int sigrok_config_device(oconfig_item_t *ci)
 {
        struct config_device *cfdev;
-       int i;
 
-       if (!(cfdev = malloc(sizeof(struct config_device)))) {
-               ERROR("sigrok plugin: malloc() failed.");
+       if (!(cfdev = calloc(1, sizeof(*cfdev)))) {
+               ERROR("sigrok plugin: calloc failed.");
                return -1;
        }
-       memset(cfdev, 0, sizeof(*cfdev));
        if (cf_util_get_string(ci, &cfdev->name)) {
                free(cfdev);
                WARNING("sigrok plugin: Invalid device name.");
@@ -84,7 +82,7 @@ static int sigrok_config_device(oconfig_item_t *ci)
        }
        cfdev->min_dispatch_interval = DEFAULT_MIN_DISPATCH_INTERVAL;
 
-       for (i = 0; i < ci->children_num; i++) {
+       for (int i = 0; i < ci->children_num; i++) {
                oconfig_item_t *item = ci->children + i;
                if (!strcasecmp(item->key, "driver"))
                        cf_util_get_string(item, &cfdev->driver);
@@ -106,9 +104,7 @@ static int sigrok_config_device(oconfig_item_t *ci)
 
 static int sigrok_config(oconfig_item_t *ci)
 {
-       int i;
-
-       for (i = 0; i < ci->children_num; i++) {
+       for (int i = 0; i < ci->children_num; i++) {
                oconfig_item_t *item = ci->children + i;
                if (strcasecmp("LogLevel", item->key) == 0) {
                        int status;
@@ -136,9 +132,9 @@ static int sigrok_config(oconfig_item_t *ci)
        return 0;
 }
 
-static char *sigrok_value_type(const struct sr_datafeed_analog *analog)
+static const char *sigrok_value_type(const struct sr_datafeed_analog *analog)
 {
-       char *s;
+       const char *s;
 
        if (analog->mq == SR_MQ_VOLTAGE)
                s = "voltage";
@@ -165,13 +161,12 @@ static void sigrok_feed_callback(const struct sr_dev_inst *sdi,
 {
        const struct sr_datafeed_analog *analog;
        struct config_device *cfdev;
-       GSList *l;
        value_t value;
        value_list_t vl = VALUE_LIST_INIT;
 
        /* Find this device's configuration. */
        cfdev = NULL;
-       for (l = config_devices; l; l = l->next) {
+       for (GSList *l = config_devices; l; l = l->next) {
                cfdev = l->data;
                if (cfdev->sdi == sdi) {
                        /* Found it. */
@@ -236,14 +231,14 @@ static int sigrok_init_driver(struct config_device *cfdev,
 
        drvopts = NULL;
        if (cfdev->conn) {
-               if (!(src = malloc(sizeof(struct sr_config))))
+               if (!(src = malloc(sizeof(*src))))
                        return -1;
                src->key = SR_CONF_CONN;
                src->data = g_variant_new_string(cfdev->conn);
                drvopts = g_slist_append(drvopts, src);
        }
        if (cfdev->serialcomm) {
-               if (!(src = malloc(sizeof(struct sr_config))))
+               if (!(src = malloc(sizeof(*src))))
                        return -1;
                src->key = SR_CONF_SERIALCOMM;
                src->data = g_variant_new_string(cfdev->serialcomm);
index 2207bd6..752cb74 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_ignorelist.h"
 static const char *config_keys[] =
 {
   "Disk",
-  "IgnoreSelected"
+  "IgnoreSelected",
+  "IgnoreSleepMode",
+  "UseSerial"
 };
 
 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
 static ignorelist_t *ignorelist = NULL;
+static int ignore_sleep_mode = 0;
+static int use_serial = 0;
 
 static int smart_config (const char *key, const char *value)
 {
@@ -60,6 +65,16 @@ static int smart_config (const char *key, const char *value)
       invert = 0;
     ignorelist_set_invert (ignorelist, invert);
   }
+  else if (strcasecmp ("IgnoreSleepMode", key) == 0)
+  {
+    if (IS_TRUE (value))
+      ignore_sleep_mode = 1;
+  }
+  else if (strcasecmp ("UseSerial", key) == 0)
+  {
+    if (IS_TRUE (value))
+      use_serial = 1;
+  }
   else
   {
     return (-1);
@@ -68,7 +83,8 @@ static int smart_config (const char *key, const char *value)
   return (0);
 } /* int smart_config */
 
-static void smart_submit (const char *dev, char *type, char *type_inst, double value)
+static void smart_submit (const char *dev, const char *type,
+               const char *type_inst, double value)
 {
        value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
@@ -129,7 +145,7 @@ static void smart_handle_disk_attribute(SkDisk *d, const SkSmartAttributeParsedD
   }
 }
 
-static void smart_handle_disk (const char *dev)
+static void smart_handle_disk (const char *dev, const char *serial)
 {
   SkDisk *d = NULL;
   SkBool awake = FALSE;
@@ -138,9 +154,16 @@ static void smart_handle_disk (const char *dev)
   const SkSmartParsedData *spd;
   uint64_t poweron, powercycles, badsectors, temperature;
 
-  shortname = strrchr(dev, '/');
-  if (!shortname) return;
-  shortname++;
+  if (use_serial && serial)
+  {
+    shortname = serial;
+  }
+  else
+  {
+    shortname = strrchr(dev, '/');
+    if (!shortname) return;
+    shortname++;
+  }
   if (ignorelist_match (ignorelist, shortname) != 0) {
     DEBUG ("smart plugin: ignoring %s.", dev);
     return;
@@ -164,10 +187,13 @@ static void smart_handle_disk (const char *dev)
     DEBUG ("smart plugin: disk %s has no SMART support.", dev);
     goto end;
   }
-  if (sk_disk_check_sleep_mode (d, &awake) < 0 || !awake)
+  if (!ignore_sleep_mode)
   {
-    DEBUG ("smart plugin: disk %s is sleeping.", dev);
-    goto end;
+    if (sk_disk_check_sleep_mode (d, &awake) < 0 || !awake)
+    {
+      DEBUG ("smart plugin: disk %s is sleeping.", dev);
+      goto end;
+    }
   }
   if (sk_disk_smart_read_data (d) < 0)
   {
@@ -246,13 +272,14 @@ static int smart_read (void)
   devices = udev_enumerate_get_list_entry (enumerate);
   udev_list_entry_foreach (dev_list_entry, devices)
   {
-    const char *path, *devpath;
+    const char *path, *devpath, *serial;
     path = udev_list_entry_get_name (dev_list_entry);
     dev = udev_device_new_from_syspath (handle_udev, path);
     devpath = udev_device_get_devnode (dev);
+    serial = udev_device_get_property_value (dev, "ID_SERIAL");
 
     /* Query status with libatasmart */
-    smart_handle_disk (devpath);
+    smart_handle_disk (devpath, serial);
     udev_device_unref (dev);
   }
 
index ae41d03..e0e1973 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_complain.h"
 
-#include <pthread.h>
-
 #include <net-snmp/net-snmp-config.h>
 #include <net-snmp/net-snmp-includes.h>
 
@@ -61,7 +60,7 @@ struct data_definition_s
   instance_t instance;
   char *instance_prefix;
   oid_t *values;
-  int values_len;
+  size_t values_len;
   double scale;
   double shift;
   struct data_definition_s *next;
@@ -166,9 +165,8 @@ static int csnmp_oid_to_string (char *buffer, size_t buffer_size,
 {
   char oid_str[MAX_OID_LEN][16];
   char *oid_str_ptr[MAX_OID_LEN];
-  size_t i;
 
-  for (i = 0; i < o->oid_len; i++)
+  for (size_t i = 0; i < o->oid_len; i++)
   {
     ssnprintf (oid_str[i], sizeof (oid_str[i]), "%lu", (unsigned long) o->oid[i]);
     oid_str_ptr[i] = oid_str[i];
@@ -293,15 +291,13 @@ static int csnmp_config_add_data_instance_prefix (data_definition_t *dd,
 
 static int csnmp_config_add_data_values (data_definition_t *dd, oconfig_item_t *ci)
 {
-  int i;
-
   if (ci->values_num < 1)
   {
     WARNING ("snmp plugin: `Values' needs at least one argument.");
     return (-1);
   }
 
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
     if (ci->values[i].type != OCONFIG_TYPE_STRING)
     {
       WARNING ("snmp plugin: `Values' needs only string argument.");
@@ -310,12 +306,12 @@ static int csnmp_config_add_data_values (data_definition_t *dd, oconfig_item_t *
 
   sfree (dd->values);
   dd->values_len = 0;
-  dd->values = (oid_t *) malloc (sizeof (oid_t) * ci->values_num);
+  dd->values = malloc (sizeof (*dd->values) * ci->values_num);
   if (dd->values == NULL)
     return (-1);
-  dd->values_len = ci->values_num;
+  dd->values_len = (size_t) ci->values_num;
 
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
   {
     dd->values[i].oid_len = MAX_OID_LEN;
 
@@ -336,12 +332,10 @@ static int csnmp_config_add_data_values (data_definition_t *dd, oconfig_item_t *
 
 static int csnmp_config_add_data_blacklist(data_definition_t *dd, oconfig_item_t *ci)
 {
-  int i;
-
   if (ci->values_num < 1)
     return (0);
 
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
   {
     if (ci->values[i].type != OCONFIG_TYPE_STRING)
     {
@@ -353,7 +347,7 @@ static int csnmp_config_add_data_blacklist(data_definition_t *dd, oconfig_item_t
   dd->ignores_len = 0;
   dd->ignores = NULL;
 
-  for (i = 0; i < ci->values_num; ++i)
+  for (int i = 0; i < ci->values_num; ++i)
   {
     if (strarray_add(&(dd->ignores), &(dd->ignores_len), ci->values[i].value.string) != 0)
     {
@@ -382,12 +376,10 @@ static int csnmp_config_add_data (oconfig_item_t *ci)
 {
   data_definition_t *dd;
   int status = 0;
-  int i;
 
-  dd = (data_definition_t *) malloc (sizeof (data_definition_t));
+  dd = calloc (1, sizeof (*dd));
   if (dd == NULL)
     return (-1);
-  memset (dd, '\0', sizeof (data_definition_t));
 
   status = cf_util_get_string(ci, &dd->name);
   if (status != 0)
@@ -399,7 +391,7 @@ static int csnmp_config_add_data (oconfig_item_t *ci)
   dd->scale = 1.0;
   dd->shift = 0.0;
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
@@ -459,7 +451,7 @@ static int csnmp_config_add_data (oconfig_item_t *ci)
     return (-1);
   }
 
-  DEBUG ("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = %i }",
+  DEBUG ("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = %zu }",
       dd->name, dd->type, (dd->is_table != 0) ? "true" : "false", dd->values_len);
 
   if (data_head == NULL)
@@ -505,7 +497,6 @@ static int csnmp_config_add_host_collect (host_definition_t *host,
   data_definition_t *data;
   data_definition_t **data_list;
   int data_list_len;
-  int i;
 
   if (ci->values_num < 1)
   {
@@ -513,7 +504,7 @@ static int csnmp_config_add_host_collect (host_definition_t *host,
     return (-1);
   }
 
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
     if (ci->values[i].type != OCONFIG_TYPE_STRING)
     {
       WARNING ("snmp plugin: All arguments to `Collect' must be strings.");
@@ -521,13 +512,13 @@ static int csnmp_config_add_host_collect (host_definition_t *host,
     }
 
   data_list_len = host->data_list_len + ci->values_num;
-  data_list = (data_definition_t **) realloc (host->data_list,
+  data_list = realloc (host->data_list,
       sizeof (data_definition_t *) * data_list_len);
   if (data_list == NULL)
     return (-1);
   host->data_list = data_list;
 
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
   {
     for (data = data_head; data != NULL; data = data->next)
       if (strcasecmp (ci->values[i].value.string, data->name) == 0)
@@ -640,17 +631,14 @@ static int csnmp_config_add_host (oconfig_item_t *ci)
 {
   host_definition_t *hd;
   int status = 0;
-  int i;
 
   /* Registration stuff. */
   char cb_name[DATA_MAX_NAME_LEN];
-  user_data_t cb_data;
-  struct timespec cb_interval;
+  user_data_t cb_data = { 0 };
 
-  hd = (host_definition_t *) malloc (sizeof (host_definition_t));
+  hd = calloc (1, sizeof (*hd));
   if (hd == NULL)
     return (-1);
-  memset (hd, '\0', sizeof (host_definition_t));
   hd->version = 2;
   C_COMPLAIN_INIT (&hd->complaint);
 
@@ -664,7 +652,7 @@ static int csnmp_config_add_host (oconfig_item_t *ci)
   hd->sess_handle = NULL;
   hd->interval = 0;
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
     status = 0;
@@ -777,15 +765,11 @@ static int csnmp_config_add_host (oconfig_item_t *ci)
 
   ssnprintf (cb_name, sizeof (cb_name), "snmp-%s", hd->name);
 
-  memset (&cb_data, 0, sizeof (cb_data));
   cb_data.data = hd;
   cb_data.free_func = csnmp_host_definition_destroy;
 
-  CDTIME_T_TO_TIMESPEC (hd->interval, &cb_interval);
-
   status = plugin_register_complex_read (/* group = */ NULL, cb_name,
-      csnmp_read_host, /* interval = */ &cb_interval,
-      /* user_data = */ &cb_data);
+      csnmp_read_host, hd->interval, /* user_data = */ &cb_data);
   if (status != 0)
   {
     ERROR ("snmp plugin: Registering complex read function failed.");
@@ -798,11 +782,9 @@ static int csnmp_config_add_host (oconfig_item_t *ci)
 
 static int csnmp_config (oconfig_item_t *ci)
 {
-  int i;
-
   call_snmp_init_once ();
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
     if (strcasecmp ("Data", child->key) == 0)
@@ -950,9 +932,8 @@ static value_t csnmp_value_list_to_value (struct variable_list *vl, int type,
   }
   else
   {
-    char oid_buffer[1024];
+    char oid_buffer[1024] = { 0 };
 
-    memset (oid_buffer, 0, sizeof (oid_buffer));
     snprint_objid (oid_buffer, sizeof (oid_buffer) - 1,
         vl->name, vl->name_length);
 
@@ -1055,50 +1036,67 @@ static value_t csnmp_value_list_to_value (struct variable_list *vl, int type,
   return (ret);
 } /* value_t csnmp_value_list_to_value */
 
+/* csnmp_strvbcopy_hexstring converts the bit string contained in "vb" to a hex
+ * representation and writes it to dst. Returns zero on success and ENOMEM if
+ * dst is not large enough to hold the string. dst is guaranteed to be
+ * nul-terminated. */
 static int csnmp_strvbcopy_hexstring (char *dst, /* {{{ */
     const struct variable_list *vb, size_t dst_size)
 {
   char *buffer_ptr;
   size_t buffer_free;
-  size_t i;
+
+  dst[0] = 0;
 
   buffer_ptr = dst;
   buffer_free = dst_size;
 
-  for (i = 0; i < vb->val_len; i++)
+  for (size_t i = 0; i < vb->val_len; i++)
   {
     int status;
 
     status = snprintf (buffer_ptr, buffer_free,
         (i == 0) ? "%02x" : ":%02x", (unsigned int) vb->val.bitstring[i]);
+    assert (status >= 0);
 
-    if (status >= buffer_free)
+    if (((size_t) status) >= buffer_free) /* truncated */
     {
-      buffer_ptr += (buffer_free - 1);
-      *buffer_ptr = 0;
-      return (dst_size + (buffer_free - status));
+      dst[dst_size - 1] = 0;
+      return ENOMEM;
     }
     else /* if (status < buffer_free) */
     {
-      buffer_ptr += status;
-      buffer_free -= status;
+      buffer_ptr  += (size_t) status;
+      buffer_free -= (size_t) status;
     }
   }
 
-  return ((int) (dst_size - buffer_free));
+  return 0;
 } /* }}} int csnmp_strvbcopy_hexstring */
 
+/* csnmp_strvbcopy copies the octet string or bit string contained in vb to
+ * dst. If non-printable characters are detected, it will switch to a hex
+ * representation of the string. Returns zero on success, EINVAL if vb does not
+ * contain a string and ENOMEM if dst is not large enough to contain the
+ * string. */
 static int csnmp_strvbcopy (char *dst, /* {{{ */
     const struct variable_list *vb, size_t dst_size)
 {
   char *src;
   size_t num_chars;
-  size_t i;
 
   if (vb->type == ASN_OCTET_STR)
     src = (char *) vb->val.string;
   else if (vb->type == ASN_BIT_STR)
     src = (char *) vb->val.bitstring;
+  else if (vb->type == ASN_IPADDRESS)
+  {
+    return ssnprintf (dst, dst_size, "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8"",
+          (uint8_t) vb->val.string[0],
+          (uint8_t) vb->val.string[1],
+          (uint8_t) vb->val.string[2],
+          (uint8_t) vb->val.string[3]);
+  }
   else
   {
     dst[0] = 0;
@@ -1109,7 +1107,7 @@ static int csnmp_strvbcopy (char *dst, /* {{{ */
   if (num_chars > vb->val_len)
     num_chars = vb->val_len;
 
-  for (i = 0; i < num_chars; i++)
+  for (size_t i = 0; i < num_chars; i++)
   {
     /* Check for control characters. */
     if ((unsigned char)src[i] < 32)
@@ -1117,8 +1115,12 @@ static int csnmp_strvbcopy (char *dst, /* {{{ */
     dst[i] = src[i];
   }
   dst[num_chars] = 0;
+  dst[dst_size - 1] = 0;
+
+  if (dst_size <= vb->val_len)
+    return ENOMEM;
 
-  return ((int) vb->val_len);
+  return 0;
 } /* }}} int csnmp_strvbcopy */
 
 static int csnmp_instance_list_add (csnmp_list_instances_t **head,
@@ -1130,7 +1132,6 @@ static int csnmp_instance_list_add (csnmp_list_instances_t **head,
   struct variable_list *vb;
   oid_t vb_name;
   int status;
-  uint32_t i;
   uint32_t is_matched;
 
   /* Set vb on the last variable */
@@ -1143,13 +1144,12 @@ static int csnmp_instance_list_add (csnmp_list_instances_t **head,
 
   csnmp_oid_init (&vb_name, vb->name, vb->name_length);
 
-  il = malloc (sizeof (*il));
+  il = calloc (1, sizeof (*il));
   if (il == NULL)
   {
-    ERROR ("snmp plugin: malloc failed.");
+    ERROR ("snmp plugin: calloc failed.");
     return (-1);
   }
-  memset (il, 0, sizeof (*il));
   il->next = NULL;
 
   status = csnmp_oid_suffix (&il->suffix, &vb_name, &dd->instance.oid);
@@ -1160,13 +1160,13 @@ static int csnmp_instance_list_add (csnmp_list_instances_t **head,
   }
 
   /* Get instance name */
-  if ((vb->type == ASN_OCTET_STR) || (vb->type == ASN_BIT_STR))
+  if ((vb->type == ASN_OCTET_STR) || (vb->type == ASN_BIT_STR) || (vb->type == ASN_IPADDRESS))
   {
     char *ptr;
 
     csnmp_strvbcopy (il->instance, vb, sizeof (il->instance));
     is_matched = 0;
-    for (i = 0; i < dd->ignores_len; i++)
+    for (uint32_t i = 0; i < dd->ignores_len; i++)
     {
       status = fnmatch(dd->ignores[i], il->instance, 0);
       if (status == 0)
@@ -1226,7 +1226,7 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
   csnmp_list_instances_t *instance_list_ptr;
   csnmp_table_values_t **value_table_ptr;
 
-  int i;
+  size_t i;
   _Bool have_more;
   oid_t current_suffix;
 
@@ -1241,7 +1241,7 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
 
   instance_list_ptr = instance_list;
 
-  value_table_ptr = calloc ((size_t) data->values_len, sizeof (*value_table_ptr));
+  value_table_ptr = calloc (data->values_len, sizeof (*value_table_ptr));
   if (value_table_ptr == NULL)
     return (-1);
   for (i = 0; i < data->values_len; i++)
@@ -1262,7 +1262,6 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
   vl.interval = host->interval;
 
   have_more = 1;
-  memset (&current_suffix, 0, sizeof (current_suffix));
   while (have_more)
   {
     _Bool suffix_skipped = 0;
@@ -1361,8 +1360,12 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
     for (i = 0; i < data->values_len; i++)
       vl.values[i] = value_table_ptr[i]->value;
 
-    /* If we get here `vl.type_instance' and all `vl.values' have been set */
-    plugin_dispatch_values (&vl);
+    /* If we get here `vl.type_instance' and all `vl.values' have been set
+     * vl.type_instance can be empty, i.e. a blank port description on a
+     * switch if you're using IF-MIB::ifDescr as Instance.
+     */
+    if (vl.type_instance[0] != '\0')
+      plugin_dispatch_values (&vl);
 
     if (instance_list != NULL)
       instance_list_ptr = instance_list_ptr->next;
@@ -1384,7 +1387,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
 
   const data_set_t *ds;
 
-  uint32_t oid_list_len = (uint32_t) (data->values_len + 1);
+  size_t oid_list_len = data->values_len + 1;
   /* Holds the last OID returned by the device. We use this in the GETNEXT
    * request to proceed. */
   oid_t oid_list[oid_list_len];
@@ -1393,8 +1396,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
   _Bool oid_list_todo[oid_list_len];
 
   int status;
-  int i;
-  uint32_t j;
+  size_t i;
 
   /* `value_list_head' and `value_list_tail' implement a linked list for each
    * value. `instance_list_head' and `instance_list_tail' implement a linked list of
@@ -1422,7 +1424,7 @@ 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 %i values, but config talks about %i",
+    ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu",
         data->type, ds->ds_num, data->values_len);
     return (-1);
   }
@@ -1435,8 +1437,8 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
   else /* no InstanceFrom option specified. */
     oid_list_len--;
 
-  for (j = 0; j < oid_list_len; j++)
-    oid_list_todo[j] = 1;
+  for (i = 0; i < oid_list_len; i++)
+    oid_list_todo[i] = 1;
 
   /* We're going to construct n linked lists, one for each "value".
    * value_list_head will contain pointers to the heads of these linked lists,
@@ -1468,13 +1470,13 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
     }
 
     oid_list_todo_num = 0;
-    for (j = 0; j < oid_list_len; j++)
+    for (i = 0; i < oid_list_len; i++)
     {
       /* Do not rerequest already finished OIDs */
-      if (!oid_list_todo[j])
+      if (!oid_list_todo[i])
         continue;
       oid_list_todo_num++;
-      snmp_add_null_var (req, oid_list[j].oid, oid_list[j].oid_len);
+      snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len);
     }
 
     if (oid_list_todo_num == 0)
@@ -1570,7 +1572,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
         ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
         if (ret != 0)
         {
-          DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
+          DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; "
               "Value probably left its subtree.",
               host->name, data->name, i);
           oid_list_todo[i] = 0;
@@ -1582,21 +1584,20 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
         if ((value_list_tail[i] != NULL)
             && (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0))
         {
-          DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
+          DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; "
               "Suffix is not increasing.",
               host->name, data->name, i);
           oid_list_todo[i] = 0;
           continue;
         }
 
-        vt = malloc (sizeof (*vt));
+        vt = calloc (1, sizeof (*vt));
         if (vt == NULL)
         {
-          ERROR ("snmp plugin: malloc failed.");
+          ERROR ("snmp plugin: calloc failed.");
           status = -1;
           break;
         }
-        memset (vt, 0, sizeof (*vt));
 
         vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type,
             data->scale, data->shift, host->name, data->name);
@@ -1659,14 +1660,14 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
 static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
 {
   struct snmp_pdu *req;
-  struct snmp_pdu *res;
+  struct snmp_pdu *res = NULL;
   struct variable_list *vb;
 
   const data_set_t *ds;
   value_list_t vl = VALUE_LIST_INIT;
 
   int status;
-  int i;
+  size_t i;
 
   DEBUG ("snmp plugin: csnmp_read_value (host = %s, data = %s)",
       host->name, data->name);
@@ -1686,13 +1687,13 @@ 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 %i values, but config talks about %i",
+    ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu",
         data->type, ds->ds_num, data->values_len);
     return (-1);
   }
 
   vl.values_len = ds->ds_num;
-  vl.values = (value_t *) malloc (sizeof (value_t) * vl.values_len);
+  vl.values = malloc (sizeof (*vl.values) * vl.values_len);
   if (vl.values == NULL)
     return (-1);
   for (i = 0; i < vl.values_len; i++)
@@ -1721,7 +1722,6 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
   for (i = 0; i < data->values_len; i++)
     snmp_add_null_var (req, data->values[i].oid, data->values[i].oid_len);
 
-  res = NULL;
   status = snmp_sess_synch_response (host->sess_handle, req, &res);
 
   if ((status != STAT_SUCCESS) || (res == NULL))
@@ -1734,7 +1734,6 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
 
     if (res != NULL)
       snmp_free_pdu (res);
-    res = NULL;
 
     sfree (errstr);
     sfree (vl.values);
@@ -1760,9 +1759,7 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
             data->scale, data->shift, host->name, data->name);
   } /* for (res->variables) */
 
-  if (res != NULL)
-    snmp_free_pdu (res);
-  res = NULL;
+  snmp_free_pdu (res);
 
   DEBUG ("snmp plugin: -> plugin_dispatch_values (&vl);");
   plugin_dispatch_values (&vl);
@@ -1774,8 +1771,6 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
 static int csnmp_read_host (user_data_t *ud)
 {
   host_definition_t *host;
-  cdtime_t time_start;
-  cdtime_t time_end;
   int status;
   int success;
   int i;
@@ -1785,8 +1780,6 @@ static int csnmp_read_host (user_data_t *ud)
   if (host->interval == 0)
     host->interval = plugin_get_interval ();
 
-  time_start = cdtime ();
-
   if (host->sess_handle == NULL)
     csnmp_host_open_session (host);
 
@@ -1807,16 +1800,6 @@ static int csnmp_read_host (user_data_t *ud)
       success++;
   }
 
-  time_end = cdtime ();
-  if ((time_end - time_start) > host->interval)
-  {
-    WARNING ("snmp plugin: Host `%s' should be queried every %.3f "
-        "seconds, but reading all values takes %.3f seconds.",
-        host->name,
-        CDTIME_T_TO_DOUBLE (host->interval),
-        CDTIME_T_TO_DOUBLE (time_end - time_start));
-  }
-
   if (success == 0)
     return (-1);
 
index 54b6e94..040181a 100644 (file)
  */
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "configfile.h"
 #include "utils_avltree.h"
-#include "utils_complain.h"
 #include "utils_latency.h"
 
-#include <pthread.h>
-
 #include <sys/types.h>
-#include <sys/socket.h>
 #include <netdb.h>
 #include <poll.h>
 
@@ -65,6 +62,7 @@ struct statsd_metric_s
 {
   metric_type_t type;
   double value;
+  derive_t counter;
   latency_counter_t *latency;
   c_avl_tree_t *set;
   unsigned long updates_num;
@@ -89,6 +87,7 @@ static _Bool conf_delete_sets     = 0;
 static double *conf_timer_percentile = NULL;
 static size_t  conf_timer_percentile_num = 0;
 
+static _Bool conf_counter_sum     = 0;
 static _Bool conf_timer_lower     = 0;
 static _Bool conf_timer_upper     = 0;
 static _Bool conf_timer_sum       = 0;
@@ -126,14 +125,13 @@ static statsd_metric_t *statsd_metric_lookup_unsafe (char const *name, /* {{{ */
     return (NULL);
   }
 
-  metric = malloc (sizeof (*metric));
+  metric = calloc (1, sizeof (*metric));
   if (metric == NULL)
   {
-    ERROR ("statsd plugin: malloc failed.");
+    ERROR ("statsd plugin: calloc failed.");
     sfree (key_copy);
     return (NULL);
   }
-  memset (metric, 0, sizeof (*metric));
 
   metric->type = type;
   metric->latency = NULL;
@@ -262,6 +260,8 @@ static int statsd_handle_counter (char const *name, /* {{{ */
   if (status != 0)
     return (status);
 
+  /* Changes to the counter are added to (statsd_metric_t*)->value. ->counter is
+   * only updated in statsd_metric_submit_unsafe(). */
   return (statsd_metric_add (name, (double) (value.gauge / scale.gauge),
         STATSD_COUNTER));
 } /* }}} int statsd_handle_counter */
@@ -356,7 +356,7 @@ static int statsd_handle_set (char const *name, /* {{{ */
 
   /* Make sure metric->set exists. */
   if (metric->set == NULL)
-    metric->set = c_avl_create ((void *) strcmp);
+    metric->set = c_avl_create ((int (*) (const void *, const void *)) strcmp);
 
   if (metric->set == NULL)
   {
@@ -501,22 +501,18 @@ static int statsd_network_init (struct pollfd **ret_fds, /* {{{ */
   struct pollfd *fds = NULL;
   size_t fds_num = 0;
 
-  struct addrinfo ai_hints;
-  struct addrinfo *ai_list = NULL;
-  struct addrinfo *ai_ptr;
+  struct addrinfo *ai_list;
   int status;
 
   char const *node = (conf_node != NULL) ? conf_node : STATSD_DEFAULT_NODE;
   char const *service = (conf_service != NULL)
     ? conf_service : STATSD_DEFAULT_SERVICE;
 
-  memset (&ai_hints, 0, sizeof (ai_hints));
-  ai_hints.ai_flags = AI_PASSIVE;
-#ifdef AI_ADDRCONFIG
-  ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
-  ai_hints.ai_family = AF_UNSPEC;
-  ai_hints.ai_socktype = SOCK_DGRAM;
+  struct addrinfo ai_hints = {
+    .ai_family = AF_UNSPEC,
+    .ai_flags = AI_PASSIVE | AI_ADDRCONFIG,
+    .ai_socktype = SOCK_DGRAM
+  };
 
   status = getaddrinfo (node, service, &ai_hints, &ai_list);
   if (status != 0)
@@ -526,7 +522,7 @@ static int statsd_network_init (struct pollfd **ret_fds, /* {{{ */
     return (status);
   }
 
-  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
   {
     int fd;
     struct pollfd *tmp;
@@ -593,7 +589,6 @@ static void *statsd_network_thread (void *args) /* {{{ */
   struct pollfd *fds = NULL;
   size_t fds_num = 0;
   int status;
-  size_t i;
 
   status = statsd_network_init (&fds, &fds_num);
   if (status != 0)
@@ -617,7 +612,7 @@ static void *statsd_network_thread (void *args) /* {{{ */
       break;
     }
 
-    for (i = 0; i < fds_num; i++)
+    for (size_t i = 0; i < fds_num; i++)
     {
       if ((fds[i].revents & (POLLIN | POLLPRI)) == 0)
         continue;
@@ -628,7 +623,7 @@ static void *statsd_network_thread (void *args) /* {{{ */
   } /* while (!network_thread_shutdown) */
 
   /* Clean up */
-  for (i = 0; i < fds_num; i++)
+  for (size_t i = 0; i < fds_num; i++)
     close (fds[i].fd);
   sfree (fds);
 
@@ -668,9 +663,7 @@ static int statsd_config_timer_percentile (oconfig_item_t *ci) /* {{{ */
 
 static int statsd_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -686,6 +679,8 @@ static int statsd_config (oconfig_item_t *ci) /* {{{ */
       cf_util_get_boolean (child, &conf_delete_gauges);
     else if (strcasecmp ("DeleteSets", child->key) == 0)
       cf_util_get_boolean (child, &conf_delete_sets);
+    else if (strcasecmp ("CounterSum", child->key) == 0)
+      cf_util_get_boolean (child, &conf_counter_sum);
     else if (strcasecmp ("TimerLower", child->key) == 0)
       cf_util_get_boolean (child, &conf_timer_lower);
     else if (strcasecmp ("TimerUpper", child->key) == 0)
@@ -708,7 +703,7 @@ static int statsd_init (void) /* {{{ */
 {
   pthread_mutex_lock (&metrics_lock);
   if (metrics_tree == NULL)
-    metrics_tree = c_avl_create ((void *) strcmp);
+    metrics_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
 
   if (!network_thread_running)
   {
@@ -756,8 +751,7 @@ static int statsd_metric_clear_set_unsafe (statsd_metric_t *metric) /* {{{ */
 } /* }}} int statsd_metric_clear_set_unsafe */
 
 /* Must hold metrics_lock when calling this function. */
-static int statsd_metric_submit_unsafe (char const *name, /* {{{ */
-    statsd_metric_t const *metric)
+static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metric) /* {{{ */
 {
   value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
@@ -782,7 +776,6 @@ static int statsd_metric_submit_unsafe (char const *name, /* {{{ */
     values[0].gauge = (gauge_t) metric->value;
   else if (metric->type == STATSD_TIMER)
   {
-    size_t i;
     _Bool have_events = (metric->updates_num > 0);
 
     /* Make sure all timer metrics share the *same* timestamp. */
@@ -822,7 +815,7 @@ static int statsd_metric_submit_unsafe (char const *name, /* {{{ */
       plugin_dispatch_values (&vl);
     }
 
-    for (i = 0; i < conf_timer_percentile_num; i++)
+    for (size_t i = 0; i < conf_timer_percentile_num; i++)
     {
       ssnprintf (vl.type_instance, sizeof (vl.type_instance),
           "%s-percentile-%.0f", name, conf_timer_percentile[i]);
@@ -853,17 +846,28 @@ static int statsd_metric_submit_unsafe (char const *name, /* {{{ */
       values[0].gauge = (gauge_t) c_avl_size (metric->set);
   }
   else { /* STATSD_COUNTER */
-      /*
-       * Expand a single value to two metrics:
-       *
-       * - The absolute counter, as a gauge
-       * - A derived rate for this counter
-       */
-      values[0].derive = (derive_t) metric->value;
-      plugin_dispatch_values(&vl);
+    gauge_t delta = nearbyint (metric->value);
+
+    /* Etsy's statsd writes counters as two metrics: a rate and the change since
+     * the last write. Since collectd does not reset its DERIVE metrics to zero,
+     * this makes little sense, but we're dispatching a "count" metric here
+     * anyway - if requested by the user - for compatibility reasons. */
+    if (conf_counter_sum)
+    {
+      sstrncpy (vl.type, "count", sizeof (vl.type));
+      values[0].gauge = delta;
+      plugin_dispatch_values (&vl);
+
+      /* restore vl.type */
+      sstrncpy (vl.type, "derive", sizeof (vl.type));
+    }
+
+    /* Rather than resetting value to zero, subtract delta so we correctly keep
+     * track of residuals. */
+    metric->value   -= delta;
+    metric->counter += (derive_t) delta;
 
-      sstrncpy(vl.type, "gauge", sizeof (vl.type));
-      values[0].gauge = (gauge_t) metric->value;
+    values[0].derive = metric->counter;
   }
 
   return (plugin_dispatch_values (&vl));
@@ -877,7 +881,6 @@ static int statsd_read (void) /* {{{ */
 
   char **to_be_deleted = NULL;
   size_t to_be_deleted_num = 0;
-  size_t i;
 
   pthread_mutex_lock (&metrics_lock);
 
@@ -912,7 +915,7 @@ static int statsd_read (void) /* {{{ */
   }
   c_avl_iterator_destroy (iter);
 
-  for (i = 0; i < to_be_deleted_num; i++)
+  for (size_t i = 0; i < to_be_deleted_num; i++)
   {
     int status;
 
index e4c5d24..9c63e9b 100644 (file)
@@ -35,6 +35,7 @@
 #endif
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -82,6 +83,10 @@ static derive_t pagesize;
 static _Bool report_by_device = 0;
 /* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS */
 
+#elif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS
+/* No global variables */
+/* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS */
+
 #elif defined(VM_SWAPUSAGE)
 /* No global variables */
 /* #endif defined(VM_SWAPUSAGE) */
@@ -108,9 +113,7 @@ static _Bool values_percentage = 0;
 
 static int swap_config (oconfig_item_t *ci) /* {{{ */
 {
-       int i;
-
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
                if (strcasecmp ("ReportBytes", child->key) == 0)
@@ -505,7 +508,6 @@ static int swap_read (void) /* {{{ */
        char *s_paths;
         int swap_num;
         int status;
-        int i;
 
         gauge_t avail = 0;
         gauge_t total = 0;
@@ -538,7 +540,7 @@ static int swap_read (void) /* {{{ */
                sfree (s);
                return (-1);
        }
-        for (i = 0; i < swap_num; i++)
+        for (int i = 0; i < swap_num; i++)
                s->swt_ent[i].ste_path = s_paths + (i * PATH_MAX);
         s->swt_n = swap_num;
 
@@ -568,7 +570,7 @@ static int swap_read (void) /* {{{ */
                /* less elements returned than requested */
                swap_num = status;
 
-        for (i = 0; i < swap_num; i++)
+        for (int i = 0; i < swap_num; i++)
         {
                char path[PATH_MAX];
                gauge_t this_total;
@@ -621,7 +623,6 @@ static int swap_read (void) /* {{{ */
        struct swapent *swap_entries;
        int swap_num;
        int status;
-       int i;
 
        gauge_t used  = 0;
        gauge_t total = 0;
@@ -660,7 +661,7 @@ static int swap_read (void) /* {{{ */
 
        /* TODO: Report per-device stats. The path name is available from
         * swap_entries[i].se_path */
-       for (i = 0; i < swap_num; i++)
+       for (int i = 0; i < swap_num; i++)
        {
                if ((swap_entries[i].se_flags & SWF_ENABLE) == 0)
                        continue;
@@ -673,6 +674,7 @@ static int swap_read (void) /* {{{ */
        {
                ERROR ("swap plugin: Total swap space (%g) is less than used swap space (%g).",
                                total, used);
+               sfree (swap_entries);
                return (-1);
        }
 
@@ -757,14 +759,13 @@ static int swap_read (void) /* {{{ */
 #elif HAVE_PERFSTAT
 static int swap_read (void) /* {{{ */
 {
-       perfstat_memory_total_t pmemory;
+       perfstat_memory_total_t pmemory = { 0 };
        int status;
 
        gauge_t total;
        gauge_t free;
        gauge_t reserved;
 
-       memset (&pmemory, 0, sizeof (pmemory));
         status = perfstat_memory_total (NULL, &pmemory, sizeof(perfstat_memory_total_t), 1);
        if (status < 0)
        {
index 3f73178..73e5e1f 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -90,7 +91,7 @@ static int sl_notification (const notification_t *n,
        char  buf[1024] = "";
        size_t offset = 0;
        int log_severity;
-       char *severity_string;
+       const char *severity_string;
        int status;
 
        if (n->severity > notif_severity)
index fcbac4f..ba65f41 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include "collectd.h"
+
 #include "common.h"
 
 #include "configfile.h"
  */
 
 typedef struct {
-       char  *type;
-       char  *instance_prefix;
-       int   *instances;
-       size_t instances_num;
-       int   *values;
-       size_t values_num;
+       char   *type;
+       char   *instance_prefix;
+       size_t *instances;
+       size_t  instances_num;
+       size_t *values;
+       size_t  values_num;
 
        const data_set_t *ds;
 } tbl_result_t;
@@ -105,13 +106,11 @@ static void tbl_setup (tbl_t *tbl, char *file)
 
 static void tbl_clear (tbl_t *tbl)
 {
-       size_t i;
-
        sfree (tbl->file);
        sfree (tbl->sep);
        sfree (tbl->instance);
 
-       for (i = 0; i < tbl->results_num; ++i)
+       for (size_t i = 0; i < tbl->results_num; ++i)
                tbl_result_clear (tbl->results + i);
        sfree (tbl->results);
        tbl->results_num = 0;
@@ -139,38 +138,39 @@ static int tbl_config_set_s (char *name, char **var, oconfig_item_t *ci)
        return 0;
 } /* tbl_config_set_separator */
 
-static int tbl_config_append_array_i (char *name, int **var, size_t *len,
+static int tbl_config_append_array_i (char *name, size_t **var, size_t *len,
                oconfig_item_t *ci)
 {
-       int *tmp;
-
-       size_t i;
+       size_t *tmp;
+       size_t num;
 
        if (1 > ci->values_num) {
                log_err ("\"%s\" expects at least one argument.", name);
                return 1;
        }
 
-       for (i = 0; i < ci->values_num; ++i) {
+       num = (size_t) ci->values_num;
+       for (size_t i = 0; i < num; ++i) {
                if (OCONFIG_TYPE_NUMBER != ci->values[i].type) {
                        log_err ("\"%s\" expects numerical arguments only.", name);
                        return 1;
                }
        }
 
-       *len += ci->values_num;
-       tmp = (int *)realloc (*var, *len * sizeof (**var));
+       tmp = realloc (*var, ((*len) + num) * sizeof (**var));
        if (NULL == tmp) {
                char errbuf[1024];
                log_err ("realloc failed: %s.",
                                sstrerror (errno, errbuf, sizeof (errbuf)));
                return -1;
        }
-
        *var = tmp;
 
-       for (i = *len - ci->values_num; i < *len; ++i)
-               (*var)[i] = (int)ci->values[i].value.number;
+       for (size_t i = 0; i < num; ++i) {
+               (*var)[*len] = (size_t) ci->values[i].value.number;
+               (*len)++;
+       }
+
        return 0;
 } /* tbl_config_append_array_s */
 
@@ -179,14 +179,13 @@ static int tbl_config_result (tbl_t *tbl, oconfig_item_t *ci)
        tbl_result_t *res;
 
        int status = 0;
-       size_t i;
 
        if (0 != ci->values_num) {
                log_err ("<Result> does not expect any arguments.");
                return 1;
        }
 
-       res = (tbl_result_t *)realloc (tbl->results,
+       res = realloc (tbl->results,
                        (tbl->results_num + 1) * sizeof (*tbl->results));
        if (res == NULL) {
                char errbuf[1024];
@@ -201,7 +200,7 @@ static int tbl_config_result (tbl_t *tbl, oconfig_item_t *ci)
        res = tbl->results + tbl->results_num - 1;
        tbl_result_setup (res);
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *c = ci->children + i;
 
                if (0 == strcasecmp (c->key, "Type"))
@@ -244,7 +243,6 @@ static int tbl_config_table (oconfig_item_t *ci)
        tbl_t *tbl;
 
        int status = 0;
-       size_t i;
 
        if ((1 != ci->values_num)
                        || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
@@ -252,7 +250,7 @@ static int tbl_config_table (oconfig_item_t *ci)
                return 1;
        }
 
-       tbl = (tbl_t *)realloc (tables, (tables_num + 1) * sizeof (*tables));
+       tbl = realloc (tables, (tables_num + 1) * sizeof (*tables));
        if (NULL == tbl) {
                char errbuf[1024];
                log_err ("realloc failed: %s.",
@@ -266,7 +264,7 @@ static int tbl_config_table (oconfig_item_t *ci)
        tbl = tables + tables_num - 1;
        tbl_setup (tbl, ci->values[0].value.string);
 
-       for (i = 0; i < ci->children_num; ++i) {
+       for (size_t i = 0; i < ((size_t) ci->children_num); ++i) {
                oconfig_item_t *c = ci->children + i;
 
                if (0 == strcasecmp (c->key, "Separator"))
@@ -304,15 +302,14 @@ static int tbl_config_table (oconfig_item_t *ci)
                return status;
        }
 
-       for (i = 0; i < tbl->results_num; ++i) {
+       for (size_t i = 0; i < tbl->results_num; ++i) {
                tbl_result_t *res = tbl->results + i;
-               size_t j;
 
-               for (j = 0; j < res->instances_num; ++j)
+               for (size_t j = 0; j < res->instances_num; ++j)
                        if (res->instances[j] > tbl->max_colnum)
                                tbl->max_colnum = res->instances[j];
 
-               for (j = 0; j < res->values_num; ++j)
+               for (size_t j = 0; j < res->values_num; ++j)
                        if (res->values[j] > tbl->max_colnum)
                                tbl->max_colnum = res->values[j];
        }
@@ -321,9 +318,7 @@ static int tbl_config_table (oconfig_item_t *ci)
 
 static int tbl_config (oconfig_item_t *ci)
 {
-       size_t i;
-
-       for (i = 0; i < ci->children_num; ++i) {
+       for (int i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *c = ci->children + i;
 
                if (0 == strcasecmp (c->key, "Table"))
@@ -340,9 +335,7 @@ static int tbl_config (oconfig_item_t *ci)
 
 static int tbl_prepare (tbl_t *tbl)
 {
-       size_t i;
-
-       for (i = 0; i < tbl->results_num; ++i) {
+       for (size_t i = 0; i < tbl->results_num; ++i) {
                tbl_result_t *res = tbl->results + i;
 
                res->ds = plugin_get_ds (res->type);
@@ -352,9 +345,9 @@ static int tbl_prepare (tbl_t *tbl)
                        return -1;
                }
 
-               if (res->values_num != (size_t)res->ds->ds_num) {
+               if (res->values_num != res->ds->ds_num) {
                        log_err ("Invalid type \"%s\". Expected %zu data source%s, "
-                                       "got %i.", res->type, res->values_num,
+                                       "got %zu.", res->type, res->values_num,
                                        (1 == res->values_num) ? "" : "s",
                                        res->ds->ds_num);
                        return -1;
@@ -365,9 +358,7 @@ static int tbl_prepare (tbl_t *tbl)
 
 static int tbl_finish (tbl_t *tbl)
 {
-       size_t i;
-
-       for (i = 0; i < tbl->results_num; ++i)
+       for (size_t i = 0; i < tbl->results_num; ++i)
                tbl->results[i].ds = NULL;
        return 0;
 } /* tbl_finish */
@@ -378,12 +369,10 @@ static int tbl_result_dispatch (tbl_t *tbl, tbl_result_t *res,
        value_list_t vl = VALUE_LIST_INIT;
        value_t values[res->values_num];
 
-       size_t i;
-
        assert (NULL != res->ds);
        assert (res->values_num == res->ds->ds_num);
 
-       for (i = 0; i < res->values_num; ++i) {
+       for (size_t i = 0; i < res->values_num; ++i) {
                char *value;
 
                assert (res->values[i] < fields_num);
@@ -410,7 +399,7 @@ static int tbl_result_dispatch (tbl_t *tbl, tbl_result_t *res,
                char *instances[res->instances_num];
                char  instances_str[DATA_MAX_NAME_LEN];
 
-               for (i = 0; i < res->instances_num; ++i) {
+               for (size_t i = 0; i < res->instances_num; ++i) {
                        assert (res->instances[i] < fields_num);
                        instances[i] = fields[res->instances[i]];
                }
@@ -442,9 +431,8 @@ static int tbl_parse_line (tbl_t *tbl, char *line, size_t len)
        char *fields[tbl->max_colnum + 1];
        char *ptr, *saveptr;
 
-       size_t i;
+       size_t i = 0;
 
-       i = 0;
        ptr = line;
        saveptr = NULL;
        while (NULL != (fields[i] = strtok_r (ptr, tbl->sep, &saveptr))) {
@@ -456,7 +444,7 @@ static int tbl_parse_line (tbl_t *tbl, char *line, size_t len)
        }
 
        if (i <= tbl->max_colnum) {
-               log_err ("Not enough columns in line "
+               log_warn ("Not enough columns in line "
                                "(expected at least %zu, got %zu).",
                                tbl->max_colnum + 1, i);
                return -1;
@@ -488,11 +476,11 @@ static int tbl_read_table (tbl_t *tbl)
        while (NULL != fgets (buf, sizeof (buf), fh)) {
                if ('\0' != buf[sizeof (buf) - 1]) {
                        buf[sizeof (buf) - 1] = '\0';
-                       log_err ("Table %s: Truncated line: %s", tbl->file, buf);
+                       log_warn ("Table %s: Truncated line: %s", tbl->file, buf);
                }
 
                if (0 != tbl_parse_line (tbl, buf, sizeof (buf))) {
-                       log_err ("Table %s: Failed to parse line: %s", tbl->file, buf);
+                       log_warn ("Table %s: Failed to parse line: %s", tbl->file, buf);
                        continue;
                }
        }
@@ -516,12 +504,11 @@ static int tbl_read_table (tbl_t *tbl)
 static int tbl_read (void)
 {
        int status = -1;
-       size_t i;
 
        if (0 == tables_num)
                return 0;
 
-       for (i = 0; i < tables_num; ++i) {
+       for (size_t i = 0; i < tables_num; ++i) {
                tbl_t *tbl = tables + i;
 
                if (0 != tbl_prepare (tbl)) {
@@ -539,9 +526,7 @@ static int tbl_read (void)
 
 static int tbl_shutdown (void)
 {
-       size_t i;
-
-       for (i = 0; i < tables_num; ++i)
+       for (size_t i = 0; i < tables_num; ++i)
                tbl_clear (&tables[i]);
        sfree (tables);
        return 0;
index 708cd2a..b8922ec 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_tail_match.h"
@@ -56,9 +57,9 @@ struct ctail_config_match_s
 };
 typedef struct ctail_config_match_s ctail_config_match_t;
 
-cu_tail_match_t **tail_match_list = NULL;
-size_t tail_match_list_num = 0;
-cdtime_t tail_match_list_intervals[255];
+static cu_tail_match_t **tail_match_list = NULL;
+static size_t tail_match_list_num = 0;
+static cdtime_t tail_match_list_intervals[255];
 
 static int ctail_config_add_match_dstype (ctail_config_match_t *cm,
     oconfig_item_t *ci)
@@ -137,11 +138,8 @@ static int ctail_config_add_match_dstype (ctail_config_match_t *cm,
 static int ctail_config_add_match (cu_tail_match_t *tm,
     const char *plugin_instance, oconfig_item_t *ci, cdtime_t interval)
 {
-  ctail_config_match_t cm;
+  ctail_config_match_t cm = { 0 };
   int status;
-  int i;
-
-  memset (&cm, '\0', sizeof (cm));
 
   if (ci->values_num != 0)
   {
@@ -149,7 +147,7 @@ static int ctail_config_add_match (cu_tail_match_t *tm,
   }
 
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
@@ -224,7 +222,6 @@ static int ctail_config_add_file (oconfig_item_t *ci)
   cdtime_t interval = 0;
   char *plugin_instance = NULL;
   int num_matches = 0;
-  int i;
 
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
   {
@@ -240,7 +237,7 @@ static int ctail_config_add_file (oconfig_item_t *ci)
     return (-1);
   }
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
     int status = 0;
@@ -279,7 +276,7 @@ static int ctail_config_add_file (oconfig_item_t *ci)
   {
     cu_tail_match_t **temp;
 
-    temp = (cu_tail_match_t **) realloc (tail_match_list,
+    temp = realloc (tail_match_list,
         sizeof (cu_tail_match_t *) * (tail_match_list_num + 1));
     if (temp == NULL)
     {
@@ -299,9 +296,7 @@ static int ctail_config_add_file (oconfig_item_t *ci)
 
 static int ctail_config (oconfig_item_t *ci)
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
@@ -332,10 +327,8 @@ static int ctail_read (user_data_t *ud)
 
 static int ctail_init (void)
 {
-  struct timespec cb_interval;
   char str[255];
-  user_data_t ud;
-  size_t i;
+  user_data_t ud = { 0 };
 
   if (tail_match_list_num == 0)
   {
@@ -343,14 +336,11 @@ static int ctail_init (void)
     return (-1);
   }
 
-  memset(&ud, '\0', sizeof(ud));
-
-  for (i = 0; i < tail_match_list_num; i++)
+  for (size_t i = 0; i < tail_match_list_num; i++)
   {
     ud.data = (void *)tail_match_list[i];
     ssnprintf(str, sizeof(str), "tail-%zu", i);
-    CDTIME_T_TO_TIMESPEC (tail_match_list_intervals[i], &cb_interval);
-    plugin_register_complex_read (NULL, str, ctail_read, &cb_interval, &ud);
+    plugin_register_complex_read (NULL, str, ctail_read, tail_match_list_intervals[i], &ud);
   }
 
   return (0);
@@ -358,9 +348,7 @@ static int ctail_init (void)
 
 static int ctail_shutdown (void)
 {
-  size_t i;
-
-  for (i = 0; i < tail_match_list_num; i++)
+  for (size_t i = 0; i < tail_match_list_num; i++)
   {
     tail_match_destroy (tail_match_list[i]);
     tail_match_list[i] = NULL;
index c3efcc9..79ea466 100644 (file)
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h" /* plugin_register_*, plugin_dispatch_values */
 #include "common.h" /* auxiliary functions */
 #include "utils_tail.h"
 #include <string.h>
 
 struct metric_definition_s {
-    char *name;
-    char *type;
-    char *instance;
-    int data_source_type;
-    int value_from;
+    char   *name;
+    char   *type;
+    char   *instance;
+    int     data_source_type;
+    ssize_t value_from;
     struct metric_definition_s *next;
 };
 typedef struct metric_definition_s metric_definition_t;
 
 struct instance_definition_s {
-    char *instance;
-    char *path;
-    cu_tail_t *tail;
+    char                 *instance;
+    char                 *path;
+    cu_tail_t            *tail;
     metric_definition_t **metric_list;
-    size_t metric_list_len;
-    cdtime_t interval;
-    int time_from;
+    size_t                metric_list_len;
+    cdtime_t              interval;
+    ssize_t               time_from;
     struct instance_definition_s *next;
 };
 typedef struct instance_definition_s instance_definition_t;
@@ -85,7 +86,7 @@ static int tcsv_submit (instance_definition_t *id,
 static cdtime_t parse_time (char const *tbuf)
 {
     double t;
-    char *endptr = 0;
+    char *endptr = NULL;
 
     errno = 0;
     t = strtod (tbuf, &endptr);
@@ -100,37 +101,37 @@ static int tcsv_read_metric (instance_definition_t *id,
         char **fields, size_t fields_num)
 {
     value_t v;
-    cdtime_t t;
+    cdtime_t t = 0;
     int status;
 
     if (md->data_source_type == -1)
         return (EINVAL);
 
-    if (md->value_from >= fields_num)
-        return (EINVAL);
-
-    if (id->time_from >= 0 && (id->time_from >= fields_num))
+    assert (md->value_from >= 0);
+    if (((size_t) md->value_from) >= fields_num)
         return (EINVAL);
 
-    t = 0;
-    if (id->time_from >= 0)
-        t = parse_time (fields[id->time_from]);
-
     status = parse_value (fields[md->value_from], &v, md->data_source_type);
     if (status != 0)
         return (status);
 
+    if (id->time_from >= 0) {
+        if (((size_t) id->time_from) >= fields_num)
+            return (EINVAL);
+        t = parse_time (fields[id->time_from]);
+    }
+
     return (tcsv_submit (id, md, v, t));
 }
 
-static _Bool tcsv_check_index (int index, size_t fields_num, char const *name)
+static _Bool tcsv_check_index (ssize_t index, size_t fields_num, char const *name)
 {
     if (index < 0)
         return 1;
     else if (((size_t) index) < fields_num)
         return 1;
 
-    ERROR ("tail_csv plugin: Metric \"%s\": Request for index %i when "
+    ERROR ("tail_csv plugin: Metric \"%s\": Request for index %zd when "
             "only %zu fields are available.",
             name, index, fields_num);
     return (0);
@@ -267,36 +268,31 @@ static void tcsv_metric_definition_destroy(void *arg){
     tcsv_metric_definition_destroy (next);
 }
 
-static int tcsv_config_get_index(oconfig_item_t *ci, int *ret_index) {
-    int index;
-
+static int tcsv_config_get_index(oconfig_item_t *ci, ssize_t *ret_index) {
     if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)){
         WARNING("tail_csv plugin: The \"%s\" config option needs exactly one "
                 "integer argument.", ci->key);
         return (-1);
     }
 
-    index = (int) ci->values[0].value.number;
-    if (index < 0) {
+    if (ci->values[0].value.number < 0) {
         WARNING("tail_csv plugin: The \"%s\" config option must be positive "
                 "(or zero).", ci->key);
         return (-1);
     }
 
-    *ret_index = index;
+    *ret_index = (ssize_t) ci->values[0].value.number;
     return (0);
 }
 
 /* Parse metric  */
 static int tcsv_config_add_metric(oconfig_item_t *ci){
     metric_definition_t *md;
-    int status = 0;
-    int i;
+    int status;
 
-    md = (metric_definition_t *)malloc(sizeof(*md));
+    md = calloc(1, sizeof(*md));
     if (md == NULL)
         return (-1);
-    memset(md, 0, sizeof(*md));
     md->name = NULL;
     md->type = NULL;
     md->instance = NULL;
@@ -310,7 +306,7 @@ static int tcsv_config_add_metric(oconfig_item_t *ci){
         return (-1);
     }
 
-    for (i = 0; i < ci->children_num; ++i){
+    for (int i = 0; i < ci->children_num; ++i){
         oconfig_item_t *option = ci->children + i;
 
         if (strcasecmp("Type", option->key) == 0)
@@ -380,7 +376,6 @@ static int tcsv_config_add_instance_collect(instance_definition_t *id, oconfig_i
     metric_definition_t *metric;
     metric_definition_t **metric_list;
     size_t metric_list_size;
-    int i;
 
     if (ci->values_num < 1) {
         WARNING("tail_csv plugin: The `Collect' config option needs at least one argument.");
@@ -393,7 +388,7 @@ static int tcsv_config_add_instance_collect(instance_definition_t *id, oconfig_i
         return (-1);
     id->metric_list = metric_list;
 
-    for (i = 0; i < ci->values_num; i++) {
+    for (int i = 0; i < ci->values_num; i++) {
         char *metric_name;
 
         if (ci->values[i].type != OCONFIG_TYPE_STRING) {
@@ -423,17 +418,14 @@ static int tcsv_config_add_file(oconfig_item_t *ci)
 {
     instance_definition_t* id;
     int status = 0;
-    int i;
 
     /* Registration variables */
     char cb_name[DATA_MAX_NAME_LEN];
-    user_data_t cb_data;
-    struct timespec cb_interval;
+    user_data_t cb_data = { 0 };
 
-    id = malloc(sizeof(*id));
+    id = calloc(1, sizeof(*id));
     if (id == NULL)
         return (-1);
-    memset(id, 0, sizeof(*id));
     id->instance = NULL;
     id->path = NULL;
     id->metric_list = NULL;
@@ -449,7 +441,7 @@ static int tcsv_config_add_file(oconfig_item_t *ci)
     /* Use default interval. */
     id->interval = plugin_get_interval();
 
-    for (i = 0; i < ci->children_num; ++i){
+    for (int i = 0; i < ci->children_num; ++i){
         oconfig_item_t *option = ci->children + i;
         status = 0;
 
@@ -490,11 +482,9 @@ static int tcsv_config_add_file(oconfig_item_t *ci)
     }
 
     ssnprintf (cb_name, sizeof (cb_name), "tail_csv/%s", id->path);
-    memset(&cb_data, 0, sizeof(cb_data));
     cb_data.data = id;
     cb_data.free_func = tcsv_instance_definition_destroy;
-    CDTIME_T_TO_TIMESPEC(id->interval, &cb_interval);
-    status = plugin_register_complex_read(NULL, cb_name, tcsv_read, &cb_interval, &cb_data);
+    status = plugin_register_complex_read(NULL, cb_name, tcsv_read, id->interval, &cb_data);
 
     if (status != 0){
         ERROR("tail_csv plugin: Registering complex read function failed.");
@@ -507,8 +497,7 @@ static int tcsv_config_add_file(oconfig_item_t *ci)
 
 /* Parse blocks */
 static int tcsv_config(oconfig_item_t *ci){
-    int i;
-    for (i = 0; i < ci->children_num; ++i){
+    for (int i = 0; i < ci->children_num; ++i){
         oconfig_item_t *child = ci->children + i;
         if (strcasecmp("Metric", child->key) == 0)
             tcsv_config_add_metric(child);
@@ -544,7 +533,7 @@ static int tcsv_init(void) { /* {{{ */
         }
         else if (ds->ds_num != 1)
         {
-            ERROR ("tail_csv plugin: The type \"%s\" has %i data sources. "
+            ERROR ("tail_csv plugin: The type \"%s\" has %zu data sources. "
                     "Only types with a single data soure are supported.",
                     ds->type, ds->ds_num);
             continue;
index a8e7dc4..52da2bc 100644 (file)
@@ -21,6 +21,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -98,7 +99,6 @@ static int tape_read (void)
 # error "kstat_io_t does not have the required members"
 #endif
        static kstat_io_t kio;
-       int i;
 
        if (kc == NULL)
                return (-1);
@@ -106,7 +106,7 @@ static int tape_read (void)
        if (numtape <= 0)
                return (-1);
 
-       for (i = 0; i < numtape; i++)
+       for (int i = 0; i < numtape; i++)
        {
                if (kstat_read (kc, ksp[i], &kio) == -1)
                        continue;
index ceb454e..21c071e 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "filter_chain.h"
 #include "utils_cache.h"
@@ -124,21 +125,19 @@ static int tn_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
 {
   tn_data_t *data;
   int status;
-  int i;
 
-  data = (tn_data_t *) malloc (sizeof (*data));
+  data = calloc (1, sizeof (*data));
   if (data == NULL)
   {
-    ERROR ("tn_create: malloc failed.");
+    ERROR ("tn_create: calloc failed.");
     return (-ENOMEM);
   }
-  memset (data, 0, sizeof (*data));
 
   data->message = NULL;
   data->severity = 0;
 
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -193,14 +192,12 @@ static int tn_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
     notification_meta_t __attribute__((unused)) **meta, void **user_data)
 {
   tn_data_t *data;
-  notification_t n;
+  notification_t n = { 0 };
   char temp[NOTIF_MAX_MSG_LEN];
 
   gauge_t *rates;
   int rates_failed;
 
-  int i;
-
   if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
     return (-EINVAL);
 
@@ -212,7 +209,6 @@ static int tn_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
   }
 
   /* Initialize the structure. */
-  memset (&n, 0, sizeof (n));
   n.severity = data->severity;
   n.time = cdtime ();
   sstrncpy (n.message, data->message, sizeof (n.message));
@@ -236,7 +232,8 @@ static int tn_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
 
   rates_failed = 0;
   rates = NULL;
-  for (i = 0; i < ds->ds_num; i++)
+
+  for (size_t i = 0; i < ds->ds_num; i++)
   {
     char template[DATA_MAX_NAME_LEN];
     char value_str[DATA_MAX_NAME_LEN];
@@ -277,9 +274,8 @@ static int tn_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
 
 void module_register (void)
 {
-       target_proc_t tproc;
+       target_proc_t tproc = { 0 };
 
-       memset (&tproc, 0, sizeof (tproc));
        tproc.create  = tn_create;
        tproc.destroy = tn_destroy;
        tproc.invoke  = tn_invoke;
index a85eced..40a6fec 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "filter_chain.h"
 #include "utils_subst.h"
@@ -61,7 +62,7 @@ static char *tr_strdup (const char *orig) /* {{{ */
     return (NULL);
 
   sz = strlen (orig) + 1;
-  dest = (char *) malloc (sz);
+  dest = malloc (sz);
   if (dest == NULL)
     return (NULL);
 
@@ -102,13 +103,12 @@ static int tr_config_add_action (tr_action_t **dest, /* {{{ */
     return (-1);
   }
 
-  act = (tr_action_t *) malloc (sizeof (*act));
+  act = calloc (1, sizeof (*act));
   if (act == NULL)
   {
-    ERROR ("tr_config_add_action: malloc failed.");
+    ERROR ("tr_config_add_action: calloc failed.");
     return (-ENOMEM);
   }
-  memset (act, 0, sizeof (*act));
 
   act->replacement = NULL;
   act->may_be_empty = may_be_empty;
@@ -156,20 +156,18 @@ static int tr_config_add_action (tr_action_t **dest, /* {{{ */
 static int tr_action_invoke (tr_action_t *act_head, /* {{{ */
     char *buffer_in, size_t buffer_in_size, int may_be_empty)
 {
-  tr_action_t *act;
   int status;
   char buffer[DATA_MAX_NAME_LEN];
-  regmatch_t matches[8];
+  regmatch_t matches[8] = { [0] = { 0 } };
 
   if (act_head == NULL)
     return (-EINVAL);
 
   sstrncpy (buffer, buffer_in, sizeof (buffer));
-  memset (matches, 0, sizeof (matches));
 
   DEBUG ("target_replace plugin: tr_action_invoke: <- buffer = %s;", buffer);
 
-  for (act = act_head; act != NULL; act = act->next)
+  for (tr_action_t *act = act_head; act != NULL; act = act->next)
   {
     char temp[DATA_MAX_NAME_LEN];
     char *subst_status;
@@ -190,7 +188,7 @@ static int tr_action_invoke (tr_action_t *act_head, /* {{{ */
     }
 
     subst_status = subst (temp, sizeof (temp), buffer,
-        matches[0].rm_so, matches[0].rm_eo, act->replacement);
+        (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, "
@@ -242,15 +240,13 @@ static int tr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
 {
   tr_data_t *data;
   int status;
-  int i;
 
-  data = (tr_data_t *) malloc (sizeof (*data));
+  data = calloc (1, sizeof (*data));
   if (data == NULL)
   {
-    ERROR ("tr_create: malloc failed.");
+    ERROR ("tr_create: calloc failed.");
     return (-ENOMEM);
   }
-  memset (data, 0, sizeof (*data));
 
   data->host = NULL;
   data->plugin = NULL;
@@ -259,7 +255,7 @@ static int tr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
   data->type_instance = NULL;
 
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -348,9 +344,8 @@ static int tr_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
 
 void module_register (void)
 {
-       target_proc_t tproc;
+       target_proc_t tproc = { 0 };
 
-       memset (&tproc, 0, sizeof (tproc));
        tproc.create  = tr_create;
        tproc.destroy = tr_destroy;
        tproc.invoke  = tr_invoke;
index b29a02b..22af4e3 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "filter_chain.h"
 
@@ -89,22 +90,11 @@ static int ts_invoke_counter (const data_set_t *ds, value_list_t *vl, /* {{{ */
 
        if (failure == 0)
        {
-               uint64_t difference;
+               uint64_t diff;
                double rate;
 
-               /* Calcualte the rate */
-               if (prev_counter > curr_counter) /* => counter overflow */
-               {
-                       if (prev_counter <= 4294967295UL) /* 32 bit overflow */
-                               difference = (4294967295UL - prev_counter) + curr_counter;
-                       else /* 64 bit overflow */
-                               difference = (18446744073709551615ULL - prev_counter) + curr_counter;
-               }
-               else /* no overflow */
-               {
-                       difference = curr_counter - prev_counter;
-               }
-               rate = ((double) difference) / CDTIME_T_TO_DOUBLE (vl->interval);
+               diff = (uint64_t) counter_diff (prev_counter, curr_counter);
+               rate = ((double) diff) / CDTIME_T_TO_DOUBLE (vl->interval);
 
                /* Modify the rate. */
                if (!isnan (data->factor))
@@ -114,9 +104,9 @@ static int ts_invoke_counter (const data_set_t *ds, value_list_t *vl, /* {{{ */
 
                /* Calculate the internal counter. */
                int_fraction += (rate * CDTIME_T_TO_DOUBLE (vl->interval));
-               difference = (uint64_t) int_fraction;
-               int_fraction -= ((double) difference);
-               int_counter  += difference;
+               diff = (uint64_t) int_fraction;
+               int_fraction -= ((double) diff);
+               int_counter  += diff;
 
                assert (int_fraction >= 0.0);
                assert (int_fraction <  1.0);
@@ -313,7 +303,6 @@ static int ts_config_add_data_source(ts_data_t *data, /* {{{ */
 {
        size_t new_data_sources_num;
        char **temp;
-       int i;
 
        /* Check number of arbuments. */
        if (ci->values_num < 1)
@@ -324,7 +313,7 @@ static int ts_config_add_data_source(ts_data_t *data, /* {{{ */
        }
 
        /* Check type of arguments */
-       for (i = 0; i < ci->values_num; i++)
+       for (int i = 0; i < ci->values_num; i++)
        {
                if (ci->values[i].type == OCONFIG_TYPE_STRING)
                        continue;
@@ -339,7 +328,7 @@ static int ts_config_add_data_source(ts_data_t *data, /* {{{ */
 
        /* Allocate space for the char pointers */
        new_data_sources_num = data->data_sources_num + ((size_t) ci->values_num);
-       temp = (char **) realloc (data->data_sources,
+       temp = realloc (data->data_sources,
                        new_data_sources_num * sizeof (char *));
        if (temp == NULL)
        {
@@ -349,7 +338,7 @@ static int ts_config_add_data_source(ts_data_t *data, /* {{{ */
        data->data_sources = temp;
 
        /* Copy the strings, allocating memory as needed.  */
-       for (i = 0; i < ci->values_num; i++)
+       for (int i = 0; i < ci->values_num; i++)
        {
                size_t j;
 
@@ -380,8 +369,7 @@ static int ts_destroy (void **user_data) /* {{{ */
 
        if ((data != NULL) && (data->data_sources != NULL))
        {
-               size_t i;
-               for (i = 0; i < data->data_sources_num; i++)
+               for (size_t i = 0; i < data->data_sources_num; i++)
                        sfree (data->data_sources[i]);
                sfree (data->data_sources);
        }
@@ -396,21 +384,19 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
 {
        ts_data_t *data;
        int status;
-       int i;
 
-       data = (ts_data_t *) malloc (sizeof (*data));
+       data = calloc (1, sizeof (*data));
        if (data == NULL)
        {
-               ERROR ("ts_create: malloc failed.");
+               ERROR ("ts_create: calloc failed.");
                return (-ENOMEM);
        }
-       memset (data, 0, sizeof (*data));
 
        data->factor = NAN;
        data->offset = NAN;
 
        status = 0;
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
 
@@ -458,7 +444,6 @@ static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
                notification_meta_t __attribute__((unused)) **meta, void **user_data)
 {
        ts_data_t *data;
-       int i;
 
        if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
                return (-EINVAL);
@@ -470,7 +455,7 @@ static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
                return (-EINVAL);
        }
 
-       for (i = 0; i < ds->ds_num; i++)
+       for (size_t i = 0; i < ds->ds_num; i++)
        {
                /* If we've got a list of data sources, is it in the list? */
                if (data->data_sources) {
@@ -502,9 +487,8 @@ static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
 
 void module_register (void)
 {
-       target_proc_t tproc;
+       target_proc_t tproc = { 0 };
 
-       memset (&tproc, 0, sizeof (tproc));
        tproc.create  = ts_create;
        tproc.destroy = ts_destroy;
        tproc.invoke  = ts_invoke;
index daeaf8b..fee5ffd 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "filter_chain.h"
 
@@ -35,9 +36,27 @@ struct ts_data_s
   char *plugin_instance;
   /* char *type; */
   char *type_instance;
+  meta_data_t *meta;
 };
 typedef struct ts_data_s ts_data_t;
 
+static int ts_util_get_key_and_string_wo_strdup (const oconfig_item_t *ci, char **ret_key, char **ret_string) /* {{{ */
+{
+  if ((ci->values_num != 2)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING)
+      || (ci->values[1].type != OCONFIG_TYPE_STRING))
+  {
+    ERROR ("ts_util_get_key_and_string_wo_strdup: The %s option requires "
+        "exactly two string argument.", ci->key);
+    return (-1);
+  }
+
+  *ret_key = ci->values[0].value.string;
+  *ret_string = ci->values[1].value.string;
+
+  return (0);
+} /* }}} int ts_util_get_key_and_string_wo_strdup */
+
 static int ts_config_add_string (char **dest, /* {{{ */
     const oconfig_item_t *ci, int may_be_empty)
 {
@@ -60,6 +79,44 @@ static int ts_config_add_string (char **dest, /* {{{ */
   return (0);
 } /* }}} int ts_config_add_string */
 
+static int ts_config_add_meta (meta_data_t **dest, /* {{{ */
+    const oconfig_item_t *ci, int may_be_empty)
+{
+  char *key = NULL;
+  char *string = NULL;
+  int status;
+
+  status = ts_util_get_key_and_string_wo_strdup (ci, &key, &string);
+  if (status != 0)
+    return (status);
+
+  if (strlen (key) == 0)
+  {
+    ERROR ("Target `set': The `%s' option does not accept empty string as first argument.",
+        ci->key);
+    return (-1);
+  }
+
+  if (!may_be_empty && (strlen (string) == 0))
+  {
+    ERROR ("Target `set': The `%s' option does not accept empty string as second argument.",
+        ci->key);
+    return (-1);
+  }
+
+  if ((*dest) == NULL)
+  {
+    // Create a new meta_data_t
+    if ((*dest = meta_data_create()) == NULL)
+    {
+      ERROR ("Target `set': failed to create a meta data for `%s'.", ci->key);
+      return (-1);
+    }
+  }
+
+  return (meta_data_add_string (*dest, key, string));
+} /* }}} int ts_config_add_meta */
+
 static int ts_destroy (void **user_data) /* {{{ */
 {
   ts_data_t *data;
@@ -76,6 +133,7 @@ static int ts_destroy (void **user_data) /* {{{ */
   free (data->plugin_instance);
   /* free (data->type); */
   free (data->type_instance);
+  meta_data_destroy(data->meta);
   free (data);
 
   return (0);
@@ -85,24 +143,23 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
 {
   ts_data_t *data;
   int status;
-  int i;
 
-  data = (ts_data_t *) malloc (sizeof (*data));
+  data = calloc (1, sizeof (*data));
   if (data == NULL)
   {
-    ERROR ("ts_create: malloc failed.");
+    ERROR ("ts_create: calloc failed.");
     return (-ENOMEM);
   }
-  memset (data, 0, sizeof (*data));
 
   data->host = NULL;
   data->plugin = NULL;
   data->plugin_instance = NULL;
   /* data->type = NULL; */
   data->type_instance = NULL;
+  data->meta = NULL;
 
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -124,6 +181,9 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
     else if (strcasecmp ("TypeInstance", child->key) == 0)
       status = ts_config_add_string (&data->type_instance, child,
           /* may be empty = */ 1);
+    else if (strcasecmp ("MetaDataSet", child->key) == 0)
+      status = ts_config_add_meta (&data->meta, child,
+          /* may be empty = */ 1);
     else
     {
       ERROR ("Target `set': The `%s' configuration option is not understood "
@@ -142,10 +202,12 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
         && (data->plugin == NULL)
         && (data->plugin_instance == NULL)
         /* && (data->type == NULL) */
-        && (data->type_instance == NULL))
+        && (data->type_instance == NULL)
+        && (data->meta == NULL))
     {
       ERROR ("Target `set': You need to set at least one of `Host', "
-          "`Plugin', `PluginInstance' or `TypeInstance'.");
+          "`Plugin', `PluginInstance', `TypeInstance', "
+          "`MetaDataSet' or `MetaDataEval'.");
       status = -1;
     }
 
@@ -177,6 +239,11 @@ static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
     return (-EINVAL);
   }
 
+  if (data->meta != NULL)
+  {
+    meta_data_clone_merge(&(vl->meta), data->meta);
+  }
+
 #define SET_FIELD(f) if (data->f != NULL) { sstrncpy (vl->f, data->f, sizeof (vl->f)); }
   SET_FIELD (host);
   SET_FIELD (plugin);
@@ -189,9 +256,8 @@ static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
 
 void module_register (void)
 {
-       target_proc_t tproc;
+       target_proc_t tproc = { 0 };
 
-       memset (&tproc, 0, sizeof (tproc));
        tproc.create  = ts_create;
        tproc.destroy = ts_destroy;
        tproc.invoke  = ts_invoke;
index d85a181..f7baa3a 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "filter_chain.h"
@@ -463,9 +464,8 @@ static int v5_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
 
 void module_register (void)
 {
-       target_proc_t tproc;
+       target_proc_t tproc = { 0 };
 
-       memset (&tproc, 0, sizeof (tproc));
        tproc.create  = v5_create;
        tproc.destroy = v5_destroy;
        tproc.invoke  = v5_invoke;
index 5d4bb69..e74e4bc 100644 (file)
@@ -58,6 +58,7 @@
  */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
 
 #if KERNEL_LINUX
 # include <asm/types.h>
-/* sys/socket.h is necessary to compile when using netlink on older systems. */
-# include <sys/socket.h>
 # include <linux/netlink.h>
 #if HAVE_LINUX_INET_DIAG_H
 # include <linux/inet_diag.h>
 #endif
-# include <sys/socket.h>
 # include <arpa/inet.h>
 /* #endif KERNEL_LINUX */
 
@@ -90,9 +88,6 @@
 #if HAVE_SYS_TYPES_H
 # include <sys/types.h>
 #endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
 #if HAVE_NET_IF_H
 # include <net/if.h>
 #endif
 /* This is for OpenBSD and NetBSD. */
 #elif HAVE_LIBKVM_NLIST
 # include <sys/queue.h>
-# include <sys/socket.h>
 # include <net/route.h>
 # include <netinet/in.h>
 # include <netinet/in_systm.h>
@@ -290,7 +284,7 @@ static uint32_t count_total[TCP_STATE_MAX + 1];
 static uint32_t sequence_number = 0;
 #endif
 
-enum
+static enum
 {
   SRC_DUNNO,
   SRC_NETLINK,
@@ -311,7 +305,6 @@ static void conn_submit_port_entry (port_entry_t *pe)
 {
   value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
-  int i;
 
   conn_prepare_vl (&vl, values);
 
@@ -321,7 +314,7 @@ static void conn_submit_port_entry (port_entry_t *pe)
     ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
        "%"PRIu16"-local", pe->port);
 
-    for (i = 1; i <= TCP_STATE_MAX; i++)
+    for (int i = 1; i <= TCP_STATE_MAX; i++)
     {
       vl.values[0].gauge = pe->count_local[i];
 
@@ -336,7 +329,7 @@ static void conn_submit_port_entry (port_entry_t *pe)
     ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
        "%"PRIu16"-remote", pe->port);
 
-    for (i = 1; i <= TCP_STATE_MAX; i++)
+    for (int i = 1; i <= TCP_STATE_MAX; i++)
     {
       vl.values[0].gauge = pe->count_remote[i];
 
@@ -351,13 +344,12 @@ static void conn_submit_port_total (void)
 {
   value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
-  int i;
 
   conn_prepare_vl (&vl, values);
 
   sstrncpy (vl.plugin_instance, "all", sizeof (vl.plugin_instance));
 
-  for (i = 1; i <= TCP_STATE_MAX; i++)
+  for (int i = 1; i <= TCP_STATE_MAX; i++)
   {
     vl.values[0].gauge = count_total[i];
 
@@ -369,12 +361,10 @@ static void conn_submit_port_total (void)
 
 static void conn_submit_all (void)
 {
-  port_entry_t *pe;
-
   if (port_collect_total)
     conn_submit_port_total ();
 
-  for (pe = port_list_head; pe != NULL; pe = pe->next)
+  for (port_entry_t *pe = port_list_head; pe != NULL; pe = pe->next)
     conn_submit_port_entry (pe);
 } /* void conn_submit_all */
 
@@ -392,10 +382,9 @@ static port_entry_t *conn_get_port_entry (uint16_t port, int create)
 
   if ((ret == NULL) && (create != 0))
   {
-    ret = (port_entry_t *) malloc (sizeof (port_entry_t));
+    ret = calloc (1, sizeof (*ret));
     if (ret == NULL)
       return (NULL);
-    memset (ret, '\0', sizeof (port_entry_t));
 
     ret->port = port;
     ret->next = port_list_head;
@@ -493,10 +482,6 @@ static int conn_read_netlink (void)
 {
 #if HAVE_STRUCT_LINUX_INET_DIAG_REQ
   int fd;
-  struct sockaddr_nl nladdr;
-  struct nlreq req;
-  struct msghdr msg;
-  struct iovec iov;
   struct inet_diag_msg *r;
   char buf[8192];
 
@@ -511,34 +496,38 @@ static int conn_read_netlink (void)
     return (-1);
   }
 
-  memset(&nladdr, 0, sizeof(nladdr));
-  nladdr.nl_family = AF_NETLINK;
-
-  memset(&req, 0, sizeof(req));
-  req.nlh.nlmsg_len = sizeof(req);
-  req.nlh.nlmsg_type = TCPDIAG_GETSOCK;
-  /* NLM_F_ROOT: return the complete table instead of a single entry.
-   * NLM_F_MATCH: return all entries matching criteria (not implemented)
-   * NLM_F_REQUEST: must be set on all request messages */
-  req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
-  req.nlh.nlmsg_pid = 0;
-  /* The sequence_number is used to track our messages. Since netlink is not
-   * reliable, we don't want to end up with a corrupt or incomplete old
-   * message in case the system is/was out of memory. */
-  req.nlh.nlmsg_seq = ++sequence_number;
-  req.r.idiag_family = AF_INET;
-  req.r.idiag_states = 0xfff;
-  req.r.idiag_ext = 0;
-
-  memset(&iov, 0, sizeof(iov));
-  iov.iov_base = &req;
-  iov.iov_len = sizeof(req);
-
-  memset(&msg, 0, sizeof(msg));
-  msg.msg_name = (void*)&nladdr;
-  msg.msg_namelen = sizeof(nladdr);
-  msg.msg_iov = &iov;
-  msg.msg_iovlen = 1;
+  struct sockaddr_nl nladdr = {
+    .nl_family = AF_NETLINK
+  };
+
+  struct nlreq req = {
+    .nlh.nlmsg_len = sizeof(req),
+    .nlh.nlmsg_type = TCPDIAG_GETSOCK,
+    /* NLM_F_ROOT: return the complete table instead of a single entry.
+     * NLM_F_MATCH: return all entries matching criteria (not implemented)
+     * NLM_F_REQUEST: must be set on all request messages */
+    .nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST,
+    .nlh.nlmsg_pid = 0,
+    /* The sequence_number is used to track our messages. Since netlink is not
+     * reliable, we don't want to end up with a corrupt or incomplete old
+     * message in case the system is/was out of memory. */
+    .nlh.nlmsg_seq = ++sequence_number,
+    .r.idiag_family = AF_INET,
+    .r.idiag_states = 0xfff,
+    .r.idiag_ext = 0
+  };
+
+  struct iovec iov = {
+    .iov_base = &req,
+    .iov_len = sizeof(req)
+  };
+
+  struct msghdr msg = {
+    .msg_name = (void*)&nladdr,
+    .msg_namelen = sizeof(nladdr),
+    .msg_iov = &iov,
+    .msg_iovlen = 1
+  };
 
   if (sendmsg (fd, &msg, 0) < 0)
   {
@@ -839,7 +828,7 @@ static int conn_read (void)
     return (-1);
   }
 
-  buffer = (char *) malloc (buffer_len);
+  buffer = malloc (buffer_len);
   if (buffer == NULL)
   {
     ERROR ("tcpconns plugin: malloc failed.");
@@ -1024,7 +1013,6 @@ static int conn_read (void)
 static int conn_read (void)
 {
   int size;
-  int i;
   int nconn;
   void *data;
   struct netinfo_header *header;
@@ -1066,7 +1054,7 @@ static int conn_read (void)
   nconn = header->size;
   conn = (struct netinfo_conn *)(data + sizeof(struct netinfo_header));
 
-  for (i=0; i < nconn; conn++, i++)
+  for (int i = 0; i < nconn; conn++, i++)
   {
     conn_handle_ports (conn->srcport, conn->dstport, conn->tcp_state);
   }
index 0e683ce..a1cde32 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <sys/types.h>
-#include <sys/socket.h>
 #include <netdb.h>
 
 /*
@@ -84,13 +84,12 @@ static int tss2_add_vserver (int vserver_port)
        }
 
        /* Allocate memory */
-       entry = (vserver_list_t *) malloc (sizeof (vserver_list_t));
+       entry = calloc (1, sizeof (*entry));
        if (entry == NULL)
        {
-               ERROR ("teamspeak2 plugin: malloc failed.");
+               ERROR ("teamspeak2 plugin: calloc failed.");
                return (-1);
        }
-       memset (entry, 0, sizeof (vserver_list_t));
 
        /* Save data */
        entry->port = vserver_port;
@@ -141,7 +140,7 @@ static void tss2_submit_gauge (const char *plugin_instance,
        if (type_instance != NULL)
                sstrncpy (vl.type_instance, type_instance,
                                sizeof (vl.type_instance));
-       
+
        plugin_dispatch_values (&vl);
 } /* void tss2_submit_gauge */
 
@@ -200,9 +199,7 @@ static int tss2_get_socket (FILE **ret_read_fh, FILE **ret_write_fh)
         * Returns connected file objects or establishes the connection
         * if it's not already present
         */
-       struct addrinfo ai_hints;
        struct addrinfo *ai_head;
-       struct addrinfo *ai_ptr;
        int sd = -1;
        int status;
 
@@ -218,12 +215,11 @@ static int tss2_get_socket (FILE **ret_read_fh, FILE **ret_write_fh)
        }
 
        /* Get all addrs for this hostname */
-       memset (&ai_hints, 0, sizeof (ai_hints));
-#ifdef AI_ADDRCONFIG
-       ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
-       ai_hints.ai_family = AF_UNSPEC;
-       ai_hints.ai_socktype = SOCK_STREAM;
+       struct addrinfo ai_hints = {
+               .ai_family = AF_UNSPEC,
+               .ai_flags = AI_ADDRCONFIG,
+               .ai_socktype = SOCK_STREAM
+       };
 
        status = getaddrinfo ((config_host != NULL) ? config_host : DEFAULT_HOST,
                        (config_port != NULL) ? config_port : DEFAULT_PORT,
@@ -237,7 +233,7 @@ static int tss2_get_socket (FILE **ret_read_fh, FILE **ret_write_fh)
        }
 
        /* Try all given hosts until we can connect to one */
-       for (ai_ptr = ai_head; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       for (struct addrinfo *ai_ptr = ai_head; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
        {
                /* Create socket */
                sd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype,
@@ -353,7 +349,7 @@ static int tss2_receive_line (FILE *fh, char *buffer, int buffer_size)
         * Receive a single line from the given file object
         */
        char *temp;
-        
+
        /*
         * fgets is blocking but much easier then doing anything else
         * TODO: Non-blocking Version would be safer
@@ -436,7 +432,7 @@ static int tss2_vserver_gapl (FILE *read_fh, FILE *write_fh,
                char buffer[4096];
                char *value;
                char *endptr = NULL;
-               
+
                status = tss2_receive_line (read_fh, buffer, sizeof (buffer));
                if (status != 0)
                {
@@ -447,7 +443,7 @@ static int tss2_vserver_gapl (FILE *read_fh, FILE *write_fh,
                        return (-1);
                }
                buffer[sizeof (buffer) - 1] = 0;
-               
+
                if (strncmp ("average_packet_loss=", buffer,
                                        strlen ("average_packet_loss=")) == 0)
                {
@@ -463,9 +459,9 @@ static int tss2_vserver_gapl (FILE *read_fh, FILE *write_fh,
                                }
                                value++;
                        }
-                       
+
                        value = &buffer[20];
-                       
+
                        packet_loss = strtod (value, &endptr);
                        if (value == endptr)
                        {
@@ -490,7 +486,7 @@ static int tss2_vserver_gapl (FILE *read_fh, FILE *write_fh,
                                        buffer);
                }
        }
-       
+
        *ret_value = packet_loss;
        return (0);
 } /* int tss2_vserver_gapl */
@@ -513,7 +509,7 @@ static int tss2_read_vserver (vserver_list_t *vserver)
        gauge_t packet_loss = NAN;
        int valid = 0;
 
-       char plugin_instance[DATA_MAX_NAME_LEN];
+       char plugin_instance[DATA_MAX_NAME_LEN] = { 0 };
 
        FILE *read_fh;
        FILE *write_fh;
@@ -529,8 +525,6 @@ static int tss2_read_vserver (vserver_list_t *vserver)
        if (vserver == NULL)
        {
                /* Request global information */
-               memset (plugin_instance, 0, sizeof (plugin_instance));
-
                status = tss2_send_request (write_fh, "gi\r\n");
        }
        else
@@ -560,7 +554,7 @@ static int tss2_read_vserver (vserver_list_t *vserver)
                char *key;
                char *value;
                char *endptr = NULL;
-               
+
                /* Read one line of the server's answer */
                status = tss2_receive_line (read_fh, buffer, sizeof (buffer));
                if (status != 0)
@@ -725,7 +719,7 @@ static int tss2_config (const char *key, const char *value)
        /*
         * Interpret configuration values
         */
-    if (strcasecmp ("Host", key) == 0)
+       if (strcasecmp ("Host", key) == 0)
        {
                char *temp;
 
@@ -755,7 +749,7 @@ static int tss2_config (const char *key, const char *value)
        {
                /* Server variable found */
                int status;
-               
+
                status = tss2_add_vserver (atoi (value));
                if (status != 0)
                        return (1);
@@ -775,7 +769,6 @@ static int tss2_read (void)
         * Poll function which collects global and vserver information
         * and submits it to collectd
         */
-       vserver_list_t *vserver;
        int success = 0;
        int status;
 
@@ -791,7 +784,7 @@ static int tss2_read (void)
        }
 
        /* Handle vservers */
-       for (vserver = server_list; vserver != NULL; vserver = vserver->next)
+       for (vserver_list_t *vserver = server_list; vserver != NULL; vserver = vserver->next)
        {
                status = tss2_read_vserver (vserver);
                if (status == 0)
@@ -805,10 +798,10 @@ static int tss2_read (void)
                        continue;
                }
        }
-       
+
        if (success == 0)
                return (-1);
-    return (0);
+       return (0);
 } /* int tss2_read */
 
 static int tss2_shutdown(void)
@@ -834,7 +827,7 @@ static int tss2_shutdown(void)
        /* Get rid of the configuration */
        sfree (config_host);
        sfree (config_port);
-       
+
     return (0);
 } /* int tss2_shutdown */
 
index 5dd75bc..96c94e5 100644 (file)
--- a/src/ted.c
+++ b/src/ted.c
@@ -35,6 +35,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -70,11 +71,15 @@ static int ted_read_value(double *ret_power, double *ret_voltage)
 {
     unsigned char receive_buffer[300];
     unsigned char package_buffer[300];
-    char pkt_request[1] = {0xAA};
+    unsigned char pkt_request[1] = {0xAA};
     int package_buffer_pos;
 
     fd_set input;
-    struct timeval timeout;
+
+    /* Initialize timeout structure, set to 2 seconds */
+    struct timeval timeout = {
+      .tv_sec = 2
+    };
 
     int end_flag;
     int escape_flag;
@@ -87,11 +92,6 @@ static int ted_read_value(double *ret_power, double *ret_voltage)
     FD_ZERO (&input);
     FD_SET (fd, &input);
 
-    /* Initialize timeout structure, set to 2 seconds */
-    memset (&timeout, 0, sizeof (timeout));
-    timeout.tv_sec = 2;
-    timeout.tv_usec = 0;
-
     /* clear out anything in the buffer */
     tcflush (fd, TCIFLUSH);
 
@@ -108,7 +108,6 @@ static int ted_read_value(double *ret_power, double *ret_voltage)
     while (end_flag == 0)
     {
         ssize_t receive_buffer_length;
-        ssize_t i;
 
         /* check for timeout or input error*/
         status = select (fd + 1, &input, NULL, NULL, &timeout);
@@ -147,7 +146,7 @@ static int ted_read_value(double *ret_power, double *ret_voltage)
             WARNING ("ted plugin: Received EOF from file descriptor.");
             return (-1);
         }
-        else if (receive_buffer_length > sizeof (receive_buffer))
+        else if (((size_t) receive_buffer_length) > sizeof (receive_buffer))
         {
             ERROR ("ted plugin: read(2) returned invalid value %zi.",
                     receive_buffer_length);
@@ -165,7 +164,7 @@ static int ted_read_value(double *ret_power, double *ret_voltage)
          * the beginning of the package has been found. */
 
         escape_flag = 0;
-        for (i = 0; i < receive_buffer_length; i++)
+        for (ssize_t i = 0; i < receive_buffer_length; i++)
         {
             /* Check if previous byte was the escape byte. */
             if (escape_flag == 1)
@@ -263,7 +262,7 @@ static int ted_open_device (void)
     return (0);
 } /* int ted_open_device */
 
-static void ted_submit (char *type, double value)
+static void ted_submit (const char *type, double value)
 {
     value_t values[1];
     value_list_t vl = VALUE_LIST_INIT;
@@ -312,7 +311,6 @@ static int ted_read (void)
     double power;
     double voltage;
     int status;
-    int i;
 
     status = ted_open_device ();
     if (status != 0)
@@ -320,7 +318,7 @@ static int ted_read (void)
 
     power = NAN;
     voltage = NAN;
-    for (i = 0; i <= conf_retries; i++)
+    for (int i = 0; i <= conf_retries; i++)
     {
         status = ted_read_value (&power, &voltage);
         if (status == 0)
index 5df1b83..1bcc276 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/tests/macros.h
- * Copyright (C) 2013       Florian octo Forster
+ * Copyright (C) 2013-2015  Florian octo Forster
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  *   Florian octo Forster <octo at collectd.org>
  */
 
+#ifndef TESTING_H
+#define TESTING_H 1
+
+#include <inttypes.h>
+
 static int fail_count__ = 0;
 static int check_count__ = 0;
 
-#define DEF_TEST(func) static int test_##func ()
+#ifndef DBL_PRECISION
+# define DBL_PRECISION 1e-12
+#endif
+
+#define DEF_TEST(func) static int test_##func (void)
 
 #define RUN_TEST(func) do { \
   int status; \
@@ -42,16 +51,56 @@ static int check_count__ = 0;
 #define OK1(cond, text) do { \
   _Bool result = (cond); \
   printf ("%s %i - %s\n", result ? "ok" : "not ok", ++check_count__, text); \
+  if (!result) { return -1; } \
 } while (0)
 #define OK(cond) OK1(cond, #cond)
 
-#define STREQ(expect, actual) do { \
-  if (strcmp (expect, actual) != 0) { \
-    printf ("not ok %i - %s incorrect: expected \"%s\", got \"%s\"\n", \
-        ++check_count__, #actual, expect, actual); \
+#define EXPECT_EQ_STR(expect, actual) do { \
+  /* Evaluate 'actual' only once. */ \
+  const char *got__ = actual; \
+  if (strcmp (expect, got__) != 0) { \
+    printf ("not ok %i - %s = \"%s\", want \"%s\"\n", \
+        ++check_count__, #actual, got__, expect); \
     return (-1); \
   } \
-  printf ("ok %i - %s evaluates to \"%s\"\n", ++check_count__, #actual, expect); \
+  printf ("ok %i - %s = \"%s\"\n", ++check_count__, #actual, got__); \
+} while (0)
+
+#define EXPECT_EQ_INT(expect, actual) do { \
+  int want__ = (int) expect; \
+  int got__  = (int) actual; \
+  if (got__ != want__) { \
+    printf ("not ok %i - %s = %d, want %d\n", \
+        ++check_count__, #actual, got__, want__); \
+    return (-1); \
+  } \
+  printf ("ok %i - %s = %d\n", ++check_count__, #actual, got__); \
+} while (0)
+
+#define EXPECT_EQ_UINT64(expect, actual) do { \
+  uint64_t want__ = (uint64_t) expect; \
+  uint64_t got__  = (uint64_t) actual; \
+  if (got__ != want__) { \
+    printf ("not ok %i - %s = %"PRIu64", want %"PRIu64"\n", \
+        ++check_count__, #actual, got__, want__); \
+    return (-1); \
+  } \
+  printf ("ok %i - %s = %"PRIu64"\n", ++check_count__, #actual, got__); \
+} while (0)
+
+#define EXPECT_EQ_DOUBLE(expect, actual) do { \
+  double want__ = (double) expect; \
+  double got__  = (double) actual; \
+  if (isnan (want__) && !isnan (got__)) { \
+    printf ("not ok %i - %s = %.15g, want %.15g\n", \
+        ++check_count__, #actual, got__, want__); \
+    return (-1); \
+  } else if (!isnan (want__) && (((want__-got__) < -DBL_PRECISION) || ((want__-got__) > DBL_PRECISION))) { \
+    printf ("not ok %i - %s = %.15g, want %.15g\n", \
+        ++check_count__, #actual, got__, want__); \
+    return (-1); \
+  } \
+  printf ("ok %i - %s = %.15g\n", ++check_count__, #actual, got__); \
 } while (0)
 
 #define CHECK_NOT_NULL(expr) do { \
@@ -65,3 +114,5 @@ static int check_count__ = 0;
   status_ = (long) (expr); \
   OK1(status_ == 0L, #expr); \
 } while (0)
+
+#endif /* TESTING_H */
index 27c92bc..c6db8c0 100644 (file)
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -35,8 +36,8 @@ static const char *config_keys[] = {
        "ForceUseProcfs"
 };
 
-const char *const dirname_sysfs = "/sys/class/thermal";
-const char *const dirname_procfs = "/proc/acpi/thermal_zone";
+static const char *const dirname_sysfs = "/sys/class/thermal";
+static const char *const dirname_procfs = "/proc/acpi/thermal_zone";
 
 static _Bool force_procfs = 0;
 static ignorelist_t *device_list;
index 45ee3b4..1d9bcf9 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_avltree.h"
 #include "utils_cache.h"
 #include "utils_threshold.h"
 
-#include <assert.h>
-#include <pthread.h>
-
 /*
  * Threshold management
  * ====================
@@ -70,7 +68,7 @@ static int ut_threshold_add (const threshold_t *th)
     return (-1);
   }
 
-  th_copy = (threshold_t *) malloc (sizeof (threshold_t));
+  th_copy = malloc (sizeof (*th_copy));
   if (th_copy == NULL)
   {
     sfree (name_copy);
@@ -78,7 +76,6 @@ static int ut_threshold_add (const threshold_t *th)
     return (-1);
   }
   memcpy (th_copy, th, sizeof (threshold_t));
-  th_ptr = NULL;
 
   DEBUG ("ut_threshold_add: Adding entry `%s'", name);
 
@@ -219,7 +216,6 @@ static int ut_config_type_hysteresis (threshold_t *th, oconfig_item_t *ci)
 
 static int ut_config_type (const threshold_t *th_orig, oconfig_item_t *ci)
 {
-  int i;
   threshold_t th;
   int status = 0;
 
@@ -248,7 +244,7 @@ static int ut_config_type (const threshold_t *th_orig, oconfig_item_t *ci)
   th.hysteresis = 0;
   th.flags = UT_FLAG_INTERESTING; /* interesting by default */
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
@@ -313,7 +309,6 @@ static int ut_config_plugin_instance (threshold_t *th, oconfig_item_t *ci)
 
 static int ut_config_plugin (const threshold_t *th_orig, oconfig_item_t *ci)
 {
-  int i;
   threshold_t th;
   int status = 0;
 
@@ -335,7 +330,7 @@ static int ut_config_plugin (const threshold_t *th_orig, oconfig_item_t *ci)
   memcpy (&th, th_orig, sizeof (th));
   sstrncpy (th.plugin, ci->values[0].value.string, sizeof (th.plugin));
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
@@ -359,7 +354,6 @@ static int ut_config_plugin (const threshold_t *th_orig, oconfig_item_t *ci)
 
 static int ut_config_host (const threshold_t *th_orig, oconfig_item_t *ci)
 {
-  int i;
   threshold_t th;
   int status = 0;
 
@@ -381,7 +375,7 @@ static int ut_config_host (const threshold_t *th_orig, oconfig_item_t *ci)
   memcpy (&th, th_orig, sizeof (th));
   sstrncpy (th.host, ci->values[0].value.string, sizeof (th.host));
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
@@ -553,10 +547,9 @@ static int ut_report_state (const data_set_t *ds,
     {
       gauge_t value;
       gauge_t sum;
-      int i;
 
       sum = 0.0;
-      for (i = 0; i < vl->values_len; i++)
+      for (size_t i = 0; i < vl->values_len; i++)
       {
         if (isnan (values[i]))
           continue;
@@ -701,7 +694,6 @@ static int ut_check_one_threshold (const data_set_t *ds,
 { /* {{{ */
   int ret = -1;
   int ds_index = -1;
-  int i;
   gauge_t values_copy[ds->ds_num];
 
   memcpy (values_copy, values, sizeof (values_copy));
@@ -720,7 +712,7 @@ static int ut_check_one_threshold (const data_set_t *ds,
     }
 
     /* Prepare `sum' and `num'. */
-    for (i = 0; i < ds->ds_num; i++)
+    for (size_t i = 0; i < ds->ds_num; i++)
       if (!isnan (values[i]))
       {
         num++;
@@ -730,17 +722,17 @@ static int ut_check_one_threshold (const data_set_t *ds,
     if ((num == 0) /* All data sources are undefined. */
         || (sum == 0.0)) /* Sum is zero, cannot calculate percentage. */
     {
-      for (i = 0; i < ds->ds_num; i++)
+      for (size_t i = 0; i < ds->ds_num; i++)
         values_copy[i] = NAN;
     }
     else /* We can actually calculate the percentage. */
     {
-      for (i = 0; i < ds->ds_num; i++)
+      for (size_t i = 0; i < ds->ds_num; i++)
         values_copy[i] = 100.0 * values[i] / sum;
     }
   } /* if (UT_FLAG_PERCENTAGE) */
 
-  for (i = 0; i < ds->ds_num; i++)
+  for (size_t i = 0; i < ds->ds_num; i++)
   {
     int status;
 
@@ -870,15 +862,12 @@ static int ut_missing (const value_list_t *vl,
 
 static int ut_config (oconfig_item_t *ci)
 { /* {{{ */
-  int i;
   int status = 0;
   int old_size = c_avl_size (threshold_tree);
 
-  threshold_t th;
-
   if (threshold_tree == NULL)
   {
-    threshold_tree = c_avl_create ((void *) strcmp);
+    threshold_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
     if (threshold_tree == NULL)
     {
       ERROR ("ut_config: c_avl_create failed.");
@@ -886,17 +875,15 @@ static int ut_config (oconfig_item_t *ci)
     }
   }
 
-  memset (&th, '\0', sizeof (th));
-  th.warning_min = NAN;
-  th.warning_max = NAN;
-  th.failure_min = NAN;
-  th.failure_max = NAN;
-
-  th.hits = 0;
-  th.hysteresis = 0;
-  th.flags = UT_FLAG_INTERESTING; /* interesting by default */
+  threshold_t th = {
+    .warning_min = NAN,
+    .warning_max = NAN,
+    .failure_min = NAN,
+    .failure_max = NAN,
+    .flags = UT_FLAG_INTERESTING /* interesting by default */
+  };
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *option = ci->children + i;
 
index f04a5fc..7c6d912 100644 (file)
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "utils_cache.h"
@@ -106,8 +107,8 @@ static void tt_submit (gauge_t val, const char* type)
 
 static void tt_open_db (void)
 {
-       char* host = NULL;
-       int   port = DEFAULT_PORT;
+       const char *host;
+       int         port = DEFAULT_PORT;
 
        if (rdb != NULL)
                return;
index fc1b5dc..2d8a08e 100644 (file)
@@ -36,6 +36,7 @@
 #define _GNU_SOURCE
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_time.h"
@@ -651,11 +652,10 @@ for_all_cpus(int (func)(struct thread_data *, struct core_data *, struct pkg_dat
        struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base)
 {
        int retval;
-       unsigned int pkg_no, core_no, thread_no;
 
-       for (pkg_no = 0; pkg_no < topology.num_packages; ++pkg_no) {
-               for (core_no = 0; core_no < topology.num_cores; ++core_no) {
-                       for (thread_no = 0; thread_no < topology.num_threads; ++thread_no) {
+       for (unsigned int pkg_no = 0; pkg_no < topology.num_packages; ++pkg_no) {
+               for (unsigned int core_no = 0; core_no < topology.num_cores; ++core_no) {
+                       for (unsigned int thread_no = 0; thread_no < topology.num_threads; ++thread_no) {
                                struct thread_data *t;
                                struct core_data *c;
                                struct pkg_data *p;
@@ -691,11 +691,10 @@ for_all_cpus_delta(const struct thread_data *thread_new_base, const struct core_
                   const struct thread_data *thread_old_base, const struct core_data *core_old_base, const struct pkg_data *pkg_old_base)
 {
        int retval;
-       unsigned int pkg_no, core_no, thread_no;
 
-       for (pkg_no = 0; pkg_no < topology.num_packages; ++pkg_no) {
-               for (core_no = 0; core_no < topology.num_cores; ++core_no) {
-                       for (thread_no = 0; thread_no < topology.num_threads; ++thread_no) {
+       for (unsigned int pkg_no = 0; pkg_no < topology.num_packages; ++pkg_no) {
+               for (unsigned int core_no = 0; core_no < topology.num_cores; ++core_no) {
+                       for (unsigned int thread_no = 0; thread_no < topology.num_threads; ++thread_no) {
                                struct thread_data *t_delta;
                                const struct thread_data *t_old, *t_new;
                                struct core_data *c_delta;
@@ -1149,7 +1148,6 @@ allocate_cpu_set(cpu_set_t ** set, size_t * size) {
 static int __attribute__((warn_unused_result))
 topology_probe(void)
 {
-       unsigned int i;
        int ret;
        unsigned int max_package_id, max_core_id, max_threads;
        max_package_id = max_core_id = max_threads = 0;
@@ -1186,7 +1184,7 @@ topology_probe(void)
         * For online cpus
         * find max_core_id, max_package_id
         */
-       for (i = 0; i <= topology.max_cpu_id; ++i) {
+       for (unsigned int i = 0; i <= topology.max_cpu_id; ++i) {
                unsigned int num_threads;
                struct cpu_topology *cpu = &topology.cpus[i];
 
@@ -1251,7 +1249,6 @@ err:
 static int
 allocate_counters(struct thread_data **threads, struct core_data **cores, struct pkg_data **packages)
 {
-       unsigned int i;
        unsigned int total_threads, total_cores;
 
        if ((topology.num_threads == 0)
@@ -1271,7 +1268,7 @@ allocate_counters(struct thread_data **threads, struct core_data **cores, struct
                return -1;
        }
 
-       for (i = 0; i < total_threads; ++i)
+       for (unsigned int i = 0; i < total_threads; ++i)
                (*threads)[i].cpu_id = topology.max_cpu_id + 1;
 
        total_cores = topology.num_cores * topology.num_packages;
@@ -1321,9 +1318,7 @@ init_counter(struct thread_data *thread_base, struct core_data *core_base,
 static void
 initialize_counters(void)
 {
-       unsigned int cpu_id;
-
-       for (cpu_id = 0; cpu_id <= topology.max_cpu_id; ++cpu_id) {
+       for (unsigned int cpu_id = 0; cpu_id <= topology.max_cpu_id; ++cpu_id) {
                if (cpu_is_not_present(cpu_id))
                        continue;
                init_counter(EVEN_COUNTERS, cpu_id);
@@ -1342,7 +1337,7 @@ free_all_buffers(void)
 
        CPU_FREE(cpu_present_set);
        cpu_present_set = NULL;
-       cpu_present_set = 0;
+       cpu_present_setsize = 0;
 
        CPU_FREE(cpu_affinity_set);
        cpu_affinity_set = NULL;
@@ -1479,35 +1474,22 @@ out:
 static int
 check_permissions(void)
 {
-#ifdef HAVE_SYS_CAPABILITY_H
-       struct __user_cap_header_struct cap_header_data;
-       cap_user_header_t cap_header = &cap_header_data;
-       struct __user_cap_data_struct cap_data_data;
-       cap_user_data_t cap_data = &cap_data_data;
-       int ret = 0;
-#endif /* HAVE_SYS_CAPABILITY_H */
 
        if (getuid() == 0) {
                /* We have everything we need */
                return 0;
-#ifndef HAVE_SYS_CAPABILITY_H
+#if !defined(HAVE_SYS_CAPABILITY_H) && !defined(CAP_SYS_RAWIO)
        } else {
                ERROR("turbostat plugin: Initialization failed: this plugin "
                      "requires collectd to run as root");
                return -1;
        }
-#else /* HAVE_SYS_CAPABILITY_H */
+#else /* HAVE_SYS_CAPABILITY_H && CAP_SYS_RAWIO */
        }
 
-       /* check for CAP_SYS_RAWIO */
-       cap_header->pid = getpid();
-       cap_header->version = _LINUX_CAPABILITY_VERSION;
-       if (capget(cap_header, cap_data) < 0) {
-               ERROR("turbostat plugin: capget failed");
-               return -1;
-       }
+       int ret = 0;
 
-       if ((cap_data->effective & (1 << CAP_SYS_RAWIO)) == 0) {
+       if (check_capability(CAP_SYS_RAWIO) != 0) {
                WARNING("turbostat plugin: Collectd doesn't have the "
                        "CAP_SYS_RAWIO capability. If you don't want to run "
                        "collectd as root, try running \"setcap "
@@ -1529,7 +1511,7 @@ check_permissions(void)
                      "collectd a special capability (CAP_SYS_RAWIO) and read "
                       "access to /dev/cpu/*/msr (see previous warnings)");
        return ret;
-#endif /* HAVE_SYS_CAPABILITY_H */
+#endif /* HAVE_SYS_CAPABILITY_H && CAP_SYS_RAWIO */
 }
 
 static int
index 303f605..cc79af0 100644 (file)
-absolute               value:ABSOLUTE:0:U
-apache_bytes           value:DERIVE:0:U
-apache_connections     value:GAUGE:0:65535
-apache_idle_workers    value:GAUGE:0:65535
-apache_requests                value:DERIVE:0:U
-apache_scoreboard      value:GAUGE:0:65535
-ath_nodes              value:GAUGE:0:65535
-ath_stat               value:DERIVE:0:U
-backends               value:GAUGE:0:65535
-bitrate                        value:GAUGE:0:4294967295
-blocked_clients value:GAUGE:0:U
-bytes                  value:GAUGE:0:U
-cache_eviction         value:DERIVE:0:U
-cache_operation                value:DERIVE:0:U
-cache_ratio            value:GAUGE:0:100
-cache_result           value:DERIVE:0:U
-cache_size             value:GAUGE:0:U
-capacity       value:GAUGE:0:U
-ceph_bytes             value:GAUGE:U:U
-ceph_latency   value:GAUGE:U:U
-ceph_rate                      value:DERIVE:0:U
-changes_since_last_save   value:GAUGE:0:U
-charge                 value:GAUGE:0:U
-compression_ratio      value:GAUGE:0:2
-compression            uncompressed:DERIVE:0:U, compressed:DERIVE:0:U
-connections            value:DERIVE:0:U
-conntrack              value:GAUGE:0:4294967295
-contextswitch          value:DERIVE:0:U
-count                  value:GAUGE:0:U
-counter                        value:COUNTER:U:U
-cpufreq                        value:GAUGE:0:U
-cpu                    value:DERIVE:0:U
-current_connections    value:GAUGE:0:U
-current_sessions       value:GAUGE:0:U
-current                        value:GAUGE:U:U
-delay                  value:GAUGE:-1000000:1000000
-derive                 value:DERIVE:0:U
-df_complex             value:GAUGE:0:U
-df_inodes              value:GAUGE:0:U
-df                     used:GAUGE:0:1125899906842623, free:GAUGE:0:1125899906842623
-disk_latency           read:GAUGE:0:U, write:GAUGE:0:U
-disk_merged            read:DERIVE:0:U, write:DERIVE:0:U
-disk_octets            read:DERIVE:0:U, write:DERIVE:0:U
-disk_ops_complex       value:DERIVE:0:U
-disk_ops               read:DERIVE:0:U, write:DERIVE:0:U
-disk_time              read:DERIVE:0:U, write:DERIVE:0:U
-disk_io_time           io_time:DERIVE:0:U, weighted_io_time:DERIVE:0:U
-dns_answer             value:DERIVE:0:U
-dns_notify             value:DERIVE:0:U
-dns_octets             queries:DERIVE:0:U, responses:DERIVE:0:U
-dns_opcode             value:DERIVE:0:U
-dns_qtype_cached       value:GAUGE:0:4294967295
-dns_qtype              value:DERIVE:0:U
-dns_query              value:DERIVE:0:U
-dns_question           value:DERIVE:0:U
-dns_rcode              value:DERIVE:0:U
-dns_reject             value:DERIVE:0:U
-dns_request            value:DERIVE:0:U
-dns_resolver           value:DERIVE:0:U
-dns_response           value:DERIVE:0:U
-dns_transfer           value:DERIVE:0:U
-dns_update             value:DERIVE:0:U
-dns_zops               value:DERIVE:0:U
-drbd_resource  value:DERIVE:0:U
-duration               seconds:GAUGE:0:U
-email_check            value:GAUGE:0:U
-email_count            value:GAUGE:0:U
-email_size             value:GAUGE:0:U
-entropy                        value:GAUGE:0:4294967295
-expired_keys    value:DERIVE:0:U
-fanspeed               value:GAUGE:0:U
-file_handles           value:GAUGE:0:U
-file_size              value:GAUGE:0:U
-files                  value:GAUGE:0:U
-flow                   value:GAUGE:0:U
-fork_rate              value:DERIVE:0:U
-frequency_offset       value:GAUGE:-1000000:1000000
-frequency              value:GAUGE:0:U
-fscache_stat           value:DERIVE:0:U
-gauge                  value:GAUGE:U:U
-hash_collisions                value:DERIVE:0:U
-http_request_methods   value:DERIVE:0:U
-http_requests          value:DERIVE:0:U
-http_response_codes    value:DERIVE:0:U
-humidity               value:GAUGE:0:100
-if_collisions          value:DERIVE:0:U
-if_dropped             rx:DERIVE:0:U, tx:DERIVE:0:U
-if_errors              rx:DERIVE:0:U, tx:DERIVE:0:U
-if_multicast           value:DERIVE:0:U
-if_octets              rx:DERIVE:0:U, tx:DERIVE:0:U
-if_packets             rx:DERIVE:0:U, tx:DERIVE:0:U
-if_rx_errors           value:DERIVE:0:U
-if_rx_octets           value:DERIVE:0:U
-if_tx_errors           value:DERIVE:0:U
-if_tx_octets           value:DERIVE:0:U
-invocations            value:DERIVE:0:U
-io_octets              rx:DERIVE:0:U, tx:DERIVE:0:U
-io_packets             rx:DERIVE:0:U, tx:DERIVE:0:U
-ipt_bytes              value:DERIVE:0:U
-ipt_packets            value:DERIVE:0:U
-irq                    value:DERIVE:0:U
-latency                        value:GAUGE:0:U
-links                  value:GAUGE:0:U
-load                   shortterm:GAUGE:0:5000, midterm:GAUGE:0:5000, longterm:GAUGE:0:5000
-md_disks               value:GAUGE:0:U
-memcached_command      value:DERIVE:0:U
-memcached_connections  value:GAUGE:0:U
-memcached_items                value:GAUGE:0:U
-memcached_octets       rx:DERIVE:0:U, tx:DERIVE:0:U
-memcached_ops          value:DERIVE:0:U
-memory                 value:GAUGE:0:281474976710656
-memory_lua             value:GAUGE:0:281474976710656
-multimeter             value:GAUGE:U:U
-mutex_operations       value:DERIVE:0:U
-mysql_commands         value:DERIVE:0:U
-mysql_handler          value:DERIVE:0:U
-mysql_locks            value:DERIVE:0:U
-mysql_log_position     value:DERIVE:0:U
-mysql_octets           rx:DERIVE:0:U, tx:DERIVE:0:U
-mysql_bpool_pages      value:GAUGE:0:U
-mysql_bpool_bytes      value:GAUGE:0:U
-mysql_bpool_counters   value:DERIVE:0:U
-mysql_innodb_data      value:DERIVE:0:U
-mysql_innodb_dblwr     value:DERIVE:0:U
-mysql_innodb_log       value:DERIVE:0:U
-mysql_innodb_pages     value:DERIVE:0:U
-mysql_innodb_row_lock  value:DERIVE:0:U
-mysql_innodb_rows      value:DERIVE:0:U
-mysql_select           value:DERIVE:0:U
-mysql_sort             value:DERIVE:0:U
-nfs_procedure          value:DERIVE:0:U
-nginx_connections      value:GAUGE:0:U
-nginx_requests         value:DERIVE:0:U
-node_octets            rx:DERIVE:0:U, tx:DERIVE:0:U
-node_rssi              value:GAUGE:0:255
-node_stat              value:DERIVE:0:U
-node_tx_rate           value:GAUGE:0:127
-objects                        value:GAUGE:0:U
-operations             value:DERIVE:0:U
-packets                        value:DERIVE:0:U
-pending_operations     value:GAUGE:0:U
-percent                        value:GAUGE:0:100.1
-percent_bytes          value:GAUGE:0:100.1
-percent_inodes         value:GAUGE:0:100.1
-pf_counters            value:DERIVE:0:U
-pf_limits              value:DERIVE:0:U
-pf_source              value:DERIVE:0:U
-pf_states              value:GAUGE:0:U
-pf_state               value:DERIVE:0:U
-pg_blks                        value:DERIVE:0:U
-pg_db_size             value:GAUGE:0:U
-pg_n_tup_c             value:DERIVE:0:U
-pg_n_tup_g             value:GAUGE:0:U
-pg_numbackends         value:GAUGE:0:U
-pg_scan                        value:DERIVE:0:U
-pg_xact                        value:DERIVE:0:U
-ping_droprate          value:GAUGE:0:100
-ping_stddev            value:GAUGE:0:65535
-ping                   value:GAUGE:0:65535
-players                        value:GAUGE:0:1000000
-power                  value:GAUGE:0:U
-pressure                       value:GAUGE:0:U
-protocol_counter       value:DERIVE:0:U
-ps_code                        value:GAUGE:0:9223372036854775807
-ps_count               processes:GAUGE:0:1000000, threads:GAUGE:0:1000000
-ps_cputime             user:DERIVE:0:U, syst:DERIVE:0:U
-ps_data                        value:GAUGE:0:9223372036854775807
-ps_disk_octets         read:DERIVE:0:U, write:DERIVE:0:U
-ps_disk_ops            read:DERIVE:0:U, write:DERIVE:0:U
-ps_pagefaults          minflt:DERIVE:0:U, majflt:DERIVE:0:U
-ps_rss                 value:GAUGE:0:9223372036854775807
-ps_stacksize           value:GAUGE:0:9223372036854775807
-ps_state               value:GAUGE:0:65535
-ps_vm                  value:GAUGE:0:9223372036854775807
-pubsub        value:GAUGE:0:U
-queue_length           value:GAUGE:0:U
-records                        value:GAUGE:0:U
-requests               value:GAUGE:0:U
-response_time          value:GAUGE:0:U
-response_code          value:GAUGE:0:U
-route_etx              value:GAUGE:0:U
-route_metric           value:GAUGE:0:U
-routes                 value:GAUGE:0:U
-segments               value:GAUGE:0:65535
-serial_octets          rx:DERIVE:0:U, tx:DERIVE:0:U
-signal_noise           value:GAUGE:U:0
-signal_power           value:GAUGE:U:0
-signal_quality         value:GAUGE:0:U
-smart_poweron          value:GAUGE:0:U
-smart_powercycles      value:GAUGE:0:U
-smart_badsectors       value:GAUGE:0:U
-smart_temperature      value:GAUGE:-300:300
+absolute                value:ABSOLUTE:0:U
+apache_bytes            value:DERIVE:0:U
+apache_connections      value:GAUGE:0:65535
+apache_idle_workers     value:GAUGE:0:65535
+apache_requests         value:DERIVE:0:U
+apache_scoreboard       value:GAUGE:0:65535
+ath_nodes               value:GAUGE:0:65535
+ath_stat                value:DERIVE:0:U
+backends                value:GAUGE:0:65535
+bitrate                 value:GAUGE:0:4294967295
+blocked_clients         value:GAUGE:0:U
+bytes                   value:GAUGE:0:U
+cache_eviction          value:DERIVE:0:U
+cache_operation         value:DERIVE:0:U
+cache_ratio             value:GAUGE:0:100
+cache_result            value:DERIVE:0:U
+cache_size              value:GAUGE:0:1125899906842623
+capacity                value:GAUGE:0:U
+ceph_bytes              value:GAUGE:U:U
+ceph_latency            value:GAUGE:U:U
+ceph_rate               value:DERIVE:0:U
+changes_since_last_save value:GAUGE:0:U
+charge                  value:GAUGE:0:U
+clock_last_meas         value:GAUGE:0:U
+clock_last_update       value:GAUGE:U:U
+clock_mode              value:GAUGE:0:U
+clock_reachability      value:GAUGE:0:U
+clock_skew_ppm          value:GAUGE:-2:2
+clock_state             value:GAUGE:0:U
+clock_stratum           value:GAUGE:0:U
+compression             uncompressed:DERIVE:0:U, compressed:DERIVE:0:U
+compression_ratio       value:GAUGE:0:2
+connections             value:DERIVE:0:U
+conntrack               value:GAUGE:0:4294967295
+contextswitch           value:DERIVE:0:U
+count                   value:GAUGE:0:U
+counter                 value:COUNTER:U:U
+cpu                     value:DERIVE:0:U
+cpufreq                 value:GAUGE:0:U
+current                 value:GAUGE:U:U
+current_connections     value:GAUGE:0:U
+current_sessions        value:GAUGE:0:U
+delay                   value:GAUGE:-1000000:1000000
+derive                  value:DERIVE:0:U
+df                      used:GAUGE:0:1125899906842623, free:GAUGE:0:1125899906842623
+df_complex              value:GAUGE:0:U
+df_inodes               value:GAUGE:0:U
+dilution_of_precision   value:GAUGE:0:U
+disk_io_time            io_time:DERIVE:0:U, weighted_io_time:DERIVE:0:U
+disk_latency            read:GAUGE:0:U, write:GAUGE:0:U
+disk_merged             read:DERIVE:0:U, write:DERIVE:0:U
+disk_octets             read:DERIVE:0:U, write:DERIVE:0:U
+disk_ops                read:DERIVE:0:U, write:DERIVE:0:U
+disk_ops_complex        value:DERIVE:0:U
+disk_time               read:DERIVE:0:U, write:DERIVE:0:U
+dns_answer              value:DERIVE:0:U
+dns_notify              value:DERIVE:0:U
+dns_octets              queries:DERIVE:0:U, responses:DERIVE:0:U
+dns_opcode              value:DERIVE:0:U
+dns_qtype               value:DERIVE:0:U
+dns_qtype_cached        value:GAUGE:0:4294967295
+dns_query               value:DERIVE:0:U
+dns_question            value:DERIVE:0:U
+dns_rcode               value:DERIVE:0:U
+dns_reject              value:DERIVE:0:U
+dns_request             value:DERIVE:0:U
+dns_resolver            value:DERIVE:0:U
+dns_response            value:DERIVE:0:U
+dns_transfer            value:DERIVE:0:U
+dns_update              value:DERIVE:0:U
+dns_zops                value:DERIVE:0:U
+drbd_resource           value:DERIVE:0:U
+duration                seconds:GAUGE:0:U
+email_check             value:GAUGE:0:U
+email_count             value:GAUGE:0:U
+email_size              value:GAUGE:0:U
+entropy                 value:GAUGE:0:4294967295
+evicted_keys            value:DERIVE:0:U
+expired_keys            value:DERIVE:0:U
+fanspeed                value:GAUGE:0:U
+file_handles            value:GAUGE:0:U
+file_size               value:GAUGE:0:U
+files                   value:GAUGE:0:U
+flow                    value:GAUGE:0:U
+fork_rate               value:DERIVE:0:U
+frequency               value:GAUGE:0:U
+frequency_error         value:GAUGE:-2:2 
+frequency_offset        value:GAUGE:-1000000:1000000
+fscache_stat            value:DERIVE:0:U
+gauge                   value:GAUGE:U:U
+hash_collisions         value:DERIVE:0:U
+http_request_methods    value:DERIVE:0:U
+http_requests           value:DERIVE:0:U
+http_response_codes     value:DERIVE:0:U
+humidity                value:GAUGE:0:100
+if_collisions           value:DERIVE:0:U
+if_dropped              rx:DERIVE:0:U, tx:DERIVE:0:U
+if_errors               rx:DERIVE:0:U, tx:DERIVE:0:U
+if_multicast            value:DERIVE:0:U
+if_octets               rx:DERIVE:0:U, tx:DERIVE:0:U
+if_packets              rx:DERIVE:0:U, tx:DERIVE:0:U
+if_rx_errors            value:DERIVE:0:U
+if_rx_octets            value:DERIVE:0:U
+if_tx_errors            value:DERIVE:0:U
+if_tx_octets            value:DERIVE:0:U
+invocations             value:DERIVE:0:U
+io_octets               rx:DERIVE:0:U, tx:DERIVE:0:U
+io_packets              rx:DERIVE:0:U, tx:DERIVE:0:U
+ipt_bytes               value:DERIVE:0:U
+ipt_packets             value:DERIVE:0:U
+irq                     value:DERIVE:0:U
+latency                 value:GAUGE:0:U
+links                   value:GAUGE:0:U
+load                    shortterm:GAUGE:0:5000, midterm:GAUGE:0:5000, longterm:GAUGE:0:5000
+md_disks                value:GAUGE:0:U
+memcached_command       value:DERIVE:0:U
+memcached_connections   value:GAUGE:0:U
+memcached_items         value:GAUGE:0:U
+memcached_octets        rx:DERIVE:0:U, tx:DERIVE:0:U
+memcached_ops           value:DERIVE:0:U
+memory                  value:GAUGE:0:281474976710656
+memory_lua              value:GAUGE:0:281474976710656
+memory_throttle_count   value:DERIVE:0:U
+multimeter              value:GAUGE:U:U
+mutex_operations        value:DERIVE:0:U
+mysql_bpool_bytes       value:GAUGE:0:U
+mysql_bpool_counters    value:DERIVE:0:U
+mysql_bpool_pages       value:GAUGE:0:U
+mysql_commands          value:DERIVE:0:U
+mysql_handler           value:DERIVE:0:U
+mysql_innodb_data       value:DERIVE:0:U
+mysql_innodb_dblwr      value:DERIVE:0:U
+mysql_innodb_log        value:DERIVE:0:U
+mysql_innodb_pages      value:DERIVE:0:U
+mysql_innodb_row_lock   value:DERIVE:0:U
+mysql_innodb_rows       value:DERIVE:0:U
+mysql_locks             value:DERIVE:0:U
+mysql_log_position      value:DERIVE:0:U
+mysql_octets            rx:DERIVE:0:U, tx:DERIVE:0:U
+mysql_select            value:DERIVE:0:U
+mysql_sort              value:DERIVE:0:U
+mysql_sort_merge_passes value:DERIVE:0:U
+mysql_sort_rows         value:DERIVE:0:U
+mysql_slow_queries      value:DERIVE:0:U
+nfs_procedure           value:DERIVE:0:U
+nginx_connections       value:GAUGE:0:U
+nginx_requests          value:DERIVE:0:U
+node_octets             rx:DERIVE:0:U, tx:DERIVE:0:U
+node_rssi               value:GAUGE:0:255
+node_stat               value:DERIVE:0:U
+node_tx_rate            value:GAUGE:0:127
+objects                 value:GAUGE:0:U
+operations              value:DERIVE:0:U
+operations_per_second   value:GAUGE:0:U
+packets                 value:DERIVE:0:U
+pending_operations      value:GAUGE:0:U
+percent                 value:GAUGE:0:100.1
+percent_bytes           value:GAUGE:0:100.1
+percent_inodes          value:GAUGE:0:100.1
+pf_counters             value:DERIVE:0:U
+pf_limits               value:DERIVE:0:U
+pf_source               value:DERIVE:0:U
+pf_state                value:DERIVE:0:U
+pf_states               value:GAUGE:0:U
+pg_blks                 value:DERIVE:0:U
+pg_db_size              value:GAUGE:0:U
+pg_n_tup_c              value:DERIVE:0:U
+pg_n_tup_g              value:GAUGE:0:U
+pg_numbackends          value:GAUGE:0:U
+pg_scan                 value:DERIVE:0:U
+pg_xact                 value:DERIVE:0:U
+ping                    value:GAUGE:0:65535
+ping_droprate           value:GAUGE:0:100
+ping_stddev             value:GAUGE:0:65535
+players                 value:GAUGE:0:1000000
+power                   value:GAUGE:0:U
+pressure                value:GAUGE:0:U
+protocol_counter        value:DERIVE:0:U
+ps_code                 value:GAUGE:0:9223372036854775807
+ps_count                processes:GAUGE:0:1000000, threads:GAUGE:0:1000000
+ps_cputime              user:DERIVE:0:U, syst:DERIVE:0:U
+ps_data                 value:GAUGE:0:9223372036854775807
+ps_disk_octets          read:DERIVE:0:U, write:DERIVE:0:U
+ps_disk_ops             read:DERIVE:0:U, write:DERIVE:0:U
+ps_pagefaults           minflt:DERIVE:0:U, majflt:DERIVE:0:U
+ps_rss                  value:GAUGE:0:9223372036854775807
+ps_stacksize            value:GAUGE:0:9223372036854775807
+ps_state                value:GAUGE:0:65535
+ps_vm                   value:GAUGE:0:9223372036854775807
+pubsub                  value:GAUGE:0:U
+queue_length            value:GAUGE:0:U
+records                 value:GAUGE:0:U
+requests                value:GAUGE:0:U
+response_code           value:GAUGE:0:U
+response_time           value:GAUGE:0:U
+root_delay              value:GAUGE:U:U
+root_dispersion         value:GAUGE:U:U
+route_etx               value:GAUGE:0:U
+route_metric            value:GAUGE:0:U
+routes                  value:GAUGE:0:U
+satellites              value:GAUGE:0:U
+segments                value:GAUGE:0:65535
+serial_octets           rx:DERIVE:0:U, tx:DERIVE:0:U
+signal_noise            value:GAUGE:U:0
+signal_power            value:GAUGE:U:0
+signal_quality          value:GAUGE:0:U
 smart_attribute         current:GAUGE:0:255, worst:GAUGE:0:255, threshold:GAUGE:0:255, pretty:GAUGE:0:U
-snr                    value:GAUGE:0:U
-spam_check             value:GAUGE:0:U
-spam_score             value:GAUGE:U:U
-spl                    value:GAUGE:U:U
-swap_io                        value:DERIVE:0:U
-swap                   value:GAUGE:0:1099511627776
-tcp_connections                value:GAUGE:0:4294967295
-temperature            value:GAUGE:U:U
-threads                        value:GAUGE:0:U
-time_dispersion                value:GAUGE:-1000000:1000000
-timeleft               value:GAUGE:0:U
-time_offset            value:GAUGE:-1000000:1000000
-total_bytes            value:DERIVE:0:U
-total_connections      value:DERIVE:0:U
-total_objects          value:DERIVE:0:U
-total_operations       value:DERIVE:0:U
-total_requests         value:DERIVE:0:U
-total_sessions         value:DERIVE:0:U
-total_threads          value:DERIVE:0:U
-total_time_in_ms       value:DERIVE:0:U
-total_values           value:DERIVE:0:U
-uptime                 value:GAUGE:0:4294967295
-users                  value:GAUGE:0:65535
-vcl                    value:GAUGE:0:65535
-vcpu                   value:GAUGE:0:U
-virt_cpu_total         value:DERIVE:0:U
-virt_vcpu              value:DERIVE:0:U
-vmpage_action          value:DERIVE:0:U
-vmpage_faults          minflt:DERIVE:0:U, majflt:DERIVE:0:U
-vmpage_io              in:DERIVE:0:U, out:DERIVE:0:U
-vmpage_number          value:GAUGE:0:4294967295
-volatile_changes       value:GAUGE:0:U
-voltage_threshold      value:GAUGE:U:U, threshold:GAUGE:U:U
-voltage                        value:GAUGE:U:U
-vs_memory              value:GAUGE:0:9223372036854775807
-vs_processes           value:GAUGE:0:65535
-vs_threads             value:GAUGE:0:65535
+smart_badsectors        value:GAUGE:0:U
+smart_powercycles       value:GAUGE:0:U
+smart_poweron           value:GAUGE:0:U
+smart_temperature       value:GAUGE:-300:300
+snr                     value:GAUGE:0:U
+spam_check              value:GAUGE:0:U
+spam_score              value:GAUGE:U:U
+spl                     value:GAUGE:U:U
+swap                    value:GAUGE:0:1099511627776
+swap_io                 value:DERIVE:0:U
+tcp_connections         value:GAUGE:0:4294967295
+temperature             value:GAUGE:U:U
+threads                 value:GAUGE:0:U
+time_dispersion         value:GAUGE:-1000000:1000000
+time_offset             value:GAUGE:-1000000:1000000
+time_offset_ntp         value:GAUGE:-1000000:1000000
+time_offset_rms         value:GAUGE:-1000000:1000000
+time_ref                value:GAUGE:0:U
+timeleft                value:GAUGE:0:U
+total_bytes             value:DERIVE:0:U
+total_connections       value:DERIVE:0:U
+total_objects           value:DERIVE:0:U
+total_operations        value:DERIVE:0:U
+total_requests          value:DERIVE:0:U
+total_sessions          value:DERIVE:0:U
+total_threads           value:DERIVE:0:U
+total_time_in_ms        value:DERIVE:0:U
+total_values            value:DERIVE:0:U
+uptime                  value:GAUGE:0:4294967295
+users                   value:GAUGE:0:65535
+vcl                     value:GAUGE:0:65535
+vcpu                    value:GAUGE:0:U
+virt_cpu_total          value:DERIVE:0:U
+virt_vcpu               value:DERIVE:0:U
+vmpage_action           value:DERIVE:0:U
+vmpage_faults           minflt:DERIVE:0:U, majflt:DERIVE:0:U
+vmpage_io               in:DERIVE:0:U, out:DERIVE:0:U
+vmpage_number           value:GAUGE:0:4294967295
+volatile_changes        value:GAUGE:0:U
+voltage                 value:GAUGE:U:U
+voltage_threshold       value:GAUGE:U:U, threshold:GAUGE:U:U
+vs_memory               value:GAUGE:0:9223372036854775807
+vs_processes            value:GAUGE:0:65535
+vs_threads              value:GAUGE:0:65535
 
 #
 # Legacy types
 # (required for the v5 upgrade target)
 #
-arc_counts             demand_data:COUNTER:0:U, demand_metadata:COUNTER:0:U, prefetch_data:COUNTER:0:U, prefetch_metadata:COUNTER:0:U
-arc_l2_bytes           read:COUNTER:0:U, write:COUNTER:0:U
-arc_l2_size            value:GAUGE:0:U
-arc_ratio              value:GAUGE:0:U
-arc_size               current:GAUGE:0:U, target:GAUGE:0:U, minlimit:GAUGE:0:U, maxlimit:GAUGE:0:U
-mysql_qcache           hits:COUNTER:0:U, inserts:COUNTER:0:U, not_cached:COUNTER:0:U, lowmem_prunes:COUNTER:0:U, queries_in_cache:GAUGE:0:U
-mysql_threads          running:GAUGE:0:U, connected:GAUGE:0:U, cached:GAUGE:0:U, created:COUNTER:0:U
+arc_counts              demand_data:COUNTER:0:U, demand_metadata:COUNTER:0:U, prefetch_data:COUNTER:0:U, prefetch_metadata:COUNTER:0:U
+arc_l2_bytes            read:COUNTER:0:U, write:COUNTER:0:U
+arc_l2_size             value:GAUGE:0:U
+arc_ratio               value:GAUGE:0:U
+arc_size                current:GAUGE:0:U, target:GAUGE:0:U, minlimit:GAUGE:0:U, maxlimit:GAUGE:0:U
+mysql_qcache            hits:COUNTER:0:U, inserts:COUNTER:0:U, not_cached:COUNTER:0:U, lowmem_prunes:COUNTER:0:U, queries_in_cache:GAUGE:0:U
+mysql_threads           running:GAUGE:0:U, connected:GAUGE:0:U, cached:GAUGE:0:U, created:COUNTER:0:U
index e62ed6c..1faeff9 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 #include "utils_cmd_putval.h"
 #include "utils_cmd_putnotif.h"
 
-/* Folks without pthread will need to disable this plugin. */
-#include <pthread.h>
-
-#include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/un.h>
 
@@ -80,7 +77,7 @@ static pthread_t listen_thread = (pthread_t) 0;
  */
 static int us_open_socket (void)
 {
-       struct sockaddr_un sa;
+       struct sockaddr_un sa = { 0 };
        int status;
 
        sock_fd = socket (PF_UNIX, SOCK_STREAM, 0);
@@ -92,7 +89,6 @@ static int us_open_socket (void)
                return (-1);
        }
 
-       memset (&sa, '\0', sizeof (sa));
        sa.sun_family = AF_UNIX;
        sstrncpy (sa.sun_path, (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
                        sizeof (sa.sun_path));
@@ -152,7 +148,7 @@ static int us_open_socket (void)
 
        do
        {
-               char *grpname;
+               const char *grpname;
                struct group *g;
                struct group sg;
                char grbuf[2048];
@@ -369,7 +365,7 @@ static void *us_server_thread (void __attribute__((unused)) *arg)
                        pthread_exit ((void *) 1);
                }
 
-               remote_fd = (int *) malloc (sizeof (int));
+               remote_fd = malloc (sizeof (*remote_fd));
                if (remote_fd == NULL)
                {
                        char errbuf[1024];
index 345128d..cbe2f8c 100644 (file)
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -179,17 +180,13 @@ static int uptime_init (void) /* {{{ */
 /* #endif HAVE_LIBKSTAT */
 
 # elif HAVE_SYS_SYSCTL_H
-       struct timeval boottv;
+       struct timeval boottv = { 0 };
        size_t boottv_len;
        int status;
 
-       int mib[2];
-
-       mib[0] = CTL_KERN;
-       mib[1] = KERN_BOOTTIME;
+       int mib[] = { CTL_KERN, KERN_BOOTTIME };
 
        boottv_len = sizeof (boottv);
-       memset (&boottv, 0, boottv_len);
 
        status = sysctl (mib, STATIC_ARRAY_SIZE (mib), &boottv, &boottv_len,
                        /* new_value = */ NULL, /* new_length = */ 0);
index 139c976..30e0dbe 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (C) 2005-2007  Sebastian Harl
  * Copyright (C) 2005       Niki W. Waibel
  * Copyright (C) 2005-2007  Florian octo Forster
- * Copyright (C) 2008       Oleg King 
+ * Copyright (C) 2008       Oleg King
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -26,6 +26,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -77,7 +78,7 @@ static int users_read (void)
 
        users_submit (users);
 /* #endif HAVE_GETUTXENT */
-       
+
 #elif HAVE_GETUTENT
        unsigned int users = 0;
        struct utmp *entry = NULL;
@@ -106,7 +107,7 @@ static int users_read (void)
        us = sg_get_user_stats ();
 # endif
        if (us == NULL)
-               return (-1);   
+               return (-1);
 
        users_submit ((gauge_t)
 # if HAVE_LIBSTATGRAB_0_90
index a01d234..1876150 100644 (file)
@@ -27,6 +27,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_parse_option.h"
@@ -43,8 +44,6 @@ int handle_flush (FILE *fh, char *buffer)
        char **identifiers = NULL;
        size_t identifiers_num = 0;
 
-       size_t i;
-
 #define PRINT_TO_SOCK(fh, ...) \
        do { \
                if (fprintf (fh, __VA_ARGS__) < 0) { \
@@ -122,15 +121,14 @@ int handle_flush (FILE *fh, char *buffer)
                }
        } /* while (*buffer != 0) */
 
-       for (i = 0; (i == 0) || (i < plugins_num); i++)
+       for (size_t i = 0; (i == 0) || (i < plugins_num); i++)
        {
                char *plugin = NULL;
-               int j;
 
                if (plugins_num != 0)
                        plugin = plugins[i];
 
-               for (j = 0; (j == 0) || (j < identifiers_num); j++)
+               for (size_t j = 0; (j == 0) || (j < identifiers_num); j++)
                {
                        char *identifier = NULL;
                        int status;
index 80babe3..b2a0a23 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -53,7 +54,6 @@ int handle_getthreshold (FILE *fh, char *buffer)
   char *type;
   char *type_instance;
 
-  value_list_t vl;
   threshold_t threshold;
 
   int   status;
@@ -110,7 +110,9 @@ int handle_getthreshold (FILE *fh, char *buffer)
     return (-1);
   }
 
-  memset (&vl, 0, sizeof (vl));
+  value_list_t vl = {
+    .values = NULL
+  };
   sstrncpy (vl.host, host, sizeof (vl.host));
   sstrncpy (vl.plugin, plugin, sizeof (vl.plugin));
   if (plugin_instance != NULL)
@@ -120,7 +122,6 @@ int handle_getthreshold (FILE *fh, char *buffer)
     sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
   sfree (identifier_copy);
 
-  memset (&threshold, 0, sizeof (threshold));
   status = ut_search_threshold (&vl, &threshold);
   if (status == ENOENT)
   {
index 2d16222..cd88760 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -60,7 +61,6 @@ int handle_getval (FILE *fh, char *buffer)
   const data_set_t *ds;
 
   int   status;
-  size_t i;
 
   if ((fh == NULL) || (buffer == NULL))
     return (-1);
@@ -132,20 +132,20 @@ int handle_getval (FILE *fh, char *buffer)
     return (-1);
   }
 
-  if ((size_t) ds->ds_num != values_num)
+  if (ds->ds_num != values_num)
   {
-    ERROR ("ds[%s]->ds_num = %i, "
-       "but uc_get_rate_by_name returned %u values.",
-       ds->type, ds->ds_num, (unsigned int) values_num);
+    ERROR ("ds[%s]->ds_num = %zu, "
+       "but uc_get_rate_by_name returned %zu values.",
+       ds->type, ds->ds_num, values_num);
     print_to_socket (fh, "-1 Error reading value from cache.\n");
     sfree (values);
     sfree (identifier_copy);
     return (-1);
   }
 
-  print_to_socket (fh, "%u Value%s found\n", (unsigned int) values_num,
+  print_to_socket (fh, "%zu Value%s found\n", values_num,
       (values_num == 1) ? "" : "s");
-  for (i = 0; i < values_num; i++)
+  for (size_t i = 0; i < values_num; i++)
   {
     print_to_socket (fh, "%s=", ds->ds[i].name);
     if (isnan (values[i]))
index b698388..afbd01d 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -33,8 +34,7 @@
 #include "utils_parse_option.h"
 
 #define free_everything_and_return(status) do { \
-    size_t j; \
-    for (j = 0; j < number; j++) { \
+    for (size_t j = 0; j < number; j++) { \
       sfree(names[j]); \
       names[j] = NULL; \
     } \
@@ -60,7 +60,6 @@ int handle_listval (FILE *fh, char *buffer)
   char **names = NULL;
   cdtime_t *times = NULL;
   size_t number = 0;
-  size_t i;
   int status;
 
   DEBUG ("utils_cmd_listval: handle_listval (fh = %p, buffer = %s);",
@@ -97,7 +96,7 @@ int handle_listval (FILE *fh, char *buffer)
 
   print_to_socket (fh, "%i Value%s found\n",
       (int) number, (number == 1) ? "" : "s");
-  for (i = 0; i < number; i++)
+  for (size_t i = 0; i < number; i++)
     print_to_socket (fh, "%.3f %s\n", CDTIME_T_TO_DOUBLE (times[i]),
                names[i]);
 
index 145cd10..669ef83 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -119,7 +120,7 @@ static int set_option (notification_t *n, const char *option, const char *value)
 int handle_putnotif (FILE *fh, char *buffer)
 {
   char *command;
-  notification_t n;
+  notification_t n = { 0 };
   int status;
 
   if ((fh == NULL) || (buffer == NULL))
@@ -143,8 +144,6 @@ int handle_putnotif (FILE *fh, char *buffer)
     return (-1);
   }
 
-  memset (&n, '\0', sizeof (n));
-
   status = 0;
   while (*buffer != 0)
   {
index 43244f6..bf3e2b6 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -163,7 +164,7 @@ int handle_putval (FILE *fh, char *buffer)
        sfree (identifier_copy);
 
        vl.values_len = ds->ds_num;
-       vl.values = (value_t *) malloc (vl.values_len * sizeof (value_t));
+       vl.values = malloc (vl.values_len * sizeof (*vl.values));
        if (vl.values == NULL)
        {
                print_to_socket (fh, "-1 malloc failed.\n");
@@ -218,7 +219,8 @@ int handle_putval (FILE *fh, char *buffer)
        } /* while (*buffer != 0) */
        /* Done parsing the options. */
 
-       print_to_socket (fh, "0 Success: %i %s been dispatched.\n",
+       if (fh!=stdout)
+               print_to_socket (fh, "0 Success: %i %s been dispatched.\n",
                        values_submitted,
                        (values_submitted == 1) ? "value has" : "values have");
 
index f9eaf88..79d77a2 100644 (file)
@@ -101,11 +101,10 @@ static unsigned int     crc32_tab[] = {
 uint32_t
 crc32_buffer(const unsigned char *s, size_t len)
 {
-    size_t      i;
     uint32_t   ret;
 
     ret = 0;
-    for (i = 0;  i < len;  i++)
+    for (size_t i = 0;  i < len;  i++)
         ret = crc32_tab[(ret ^ s[i]) & 0xff] ^ (ret >> 8);
     return ret;
 }
diff --git a/src/utils_curl_stats.c b/src/utils_curl_stats.c
new file mode 100644 (file)
index 0000000..0509ff4
--- /dev/null
@@ -0,0 +1,248 @@
+/**
+ * collectd - src/utils_curl_stats.c
+ * Copyright (C) 2015       Sebastian 'tokkee' Harl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Sebastian Harl <sh@tokkee.org>
+ **/
+
+#include "collectd.h"
+
+#include "common.h"
+#include "utils_curl_stats.h"
+
+#include <stdbool.h>
+#include <stddef.h>
+
+struct curl_stats_s
+{
+       bool total_time;
+       bool namelookup_time;
+       bool connect_time;
+       bool pretransfer_time;
+       bool size_upload;
+       bool size_download;
+       bool speed_download;
+       bool speed_upload;
+       bool header_size;
+       bool request_size;
+       bool content_length_download;
+       bool content_length_upload;
+       bool starttransfer_time;
+       bool redirect_time;
+       bool redirect_count;
+       bool num_connects;
+       bool appconnect_time;
+};
+
+/*
+ * Private functions
+ */
+
+static int dispatch_gauge (CURL *curl, CURLINFO info, value_list_t *vl)
+{
+       CURLcode code;
+       value_t v;
+
+       code = curl_easy_getinfo (curl, info, &v.gauge);
+       if (code != CURLE_OK)
+               return -1;
+
+       vl->values = &v;
+       vl->values_len = 1;
+
+       return plugin_dispatch_values (vl);
+} /* dispatch_gauge */
+
+/* dispatch a speed, in bytes/second */
+static int dispatch_speed (CURL *curl, CURLINFO info, value_list_t *vl)
+{
+       CURLcode code;
+       value_t v;
+
+       code = curl_easy_getinfo (curl, info, &v.gauge);
+       if (code != CURLE_OK)
+               return -1;
+
+       v.gauge *= 8;
+
+       vl->values = &v;
+       vl->values_len = 1;
+
+       return plugin_dispatch_values (vl);
+} /* dispatch_speed */
+
+/* dispatch a size/count, reported as a long value */
+static int dispatch_size (CURL *curl, CURLINFO info, value_list_t *vl)
+{
+       CURLcode code;
+       value_t v;
+       long raw;
+
+       code = curl_easy_getinfo (curl, info, &raw);
+       if (code != CURLE_OK)
+               return -1;
+
+       v.gauge = (double)raw;
+
+       vl->values = &v;
+       vl->values_len = 1;
+
+       return plugin_dispatch_values (vl);
+} /* dispatch_size */
+
+static struct {
+       const char *name;
+       const char *config_key;
+       size_t offset;
+
+       int (*dispatcher)(CURL *, CURLINFO, value_list_t *);
+       const char *type;
+       CURLINFO info;
+} field_specs[] = {
+#define SPEC(name, config_key, dispatcher, type, info) \
+       { #name, config_key, offsetof (curl_stats_t, name), dispatcher, type, info }
+
+       SPEC (total_time,              "TotalTime",              dispatch_gauge, "duration", CURLINFO_TOTAL_TIME),
+       SPEC (namelookup_time,         "NamelookupTime",         dispatch_gauge, "duration", CURLINFO_NAMELOOKUP_TIME),
+       SPEC (connect_time,            "ConnectTime",            dispatch_gauge, "duration", CURLINFO_CONNECT_TIME),
+       SPEC (pretransfer_time,        "PretransferTime",        dispatch_gauge, "duration", CURLINFO_PRETRANSFER_TIME),
+       SPEC (size_upload,             "SizeUpload",             dispatch_gauge, "bytes",    CURLINFO_SIZE_UPLOAD),
+       SPEC (size_download,           "SizeDownload",           dispatch_gauge, "bytes",    CURLINFO_SIZE_DOWNLOAD),
+       SPEC (speed_download,          "SpeedDownload",          dispatch_speed, "bitrate",  CURLINFO_SPEED_DOWNLOAD),
+       SPEC (speed_upload,            "SpeedUpload",            dispatch_speed, "bitrate",  CURLINFO_SPEED_UPLOAD),
+       SPEC (header_size,             "HeaderSize",             dispatch_size,  "bytes",    CURLINFO_HEADER_SIZE),
+       SPEC (request_size,            "RequestSize",            dispatch_size,  "bytes",    CURLINFO_REQUEST_SIZE),
+       SPEC (content_length_download, "ContentLengthDownload",  dispatch_gauge, "bytes",    CURLINFO_CONTENT_LENGTH_DOWNLOAD),
+       SPEC (content_length_upload,   "ContentLengthUpload",    dispatch_gauge, "bytes",    CURLINFO_CONTENT_LENGTH_UPLOAD),
+       SPEC (starttransfer_time,      "StarttransferTime",      dispatch_gauge, "duration", CURLINFO_STARTTRANSFER_TIME),
+       SPEC (redirect_time,           "RedirectTime",           dispatch_gauge, "duration", CURLINFO_REDIRECT_TIME),
+       SPEC (redirect_count,          "RedirectCount",          dispatch_size,  "count",    CURLINFO_REDIRECT_COUNT),
+       SPEC (num_connects,            "NumConnects",            dispatch_size,  "count",    CURLINFO_NUM_CONNECTS),
+#ifdef HAVE_CURLINFO_APPCONNECT_TIME
+       SPEC (appconnect_time,         "AppconnectTime",         dispatch_gauge, "duration", CURLINFO_APPCONNECT_TIME),
+#endif
+
+#undef SPEC
+};
+
+static void enable_field (curl_stats_t *s, size_t offset)
+{
+       *(bool *)((char *)s + offset) = true;
+} /* enable_field */
+
+static bool field_enabled (curl_stats_t *s, size_t offset)
+{
+       return *(bool *)((char *)s + offset);
+} /* field_enabled */
+
+/*
+ * Public API
+ */
+curl_stats_t *curl_stats_from_config (oconfig_item_t *ci)
+{
+       curl_stats_t *s;
+
+       if (ci == NULL)
+               return NULL;
+
+       s = calloc (1, sizeof (*s));
+       if (s == NULL)
+               return NULL;
+
+       for (int i = 0; i < ci->children_num; ++i)
+       {
+               oconfig_item_t *c = ci->children + i;
+               size_t field;
+
+               _Bool enabled = 0;
+
+               for (field = 0; field < STATIC_ARRAY_SIZE (field_specs); ++field) {
+                       if (! strcasecmp (c->key, field_specs[field].config_key))
+                               break;
+                       if (! strcasecmp (c->key, field_specs[field].name))
+                               break;
+               }
+               if (field >= STATIC_ARRAY_SIZE (field_specs))
+               {
+                       ERROR ("curl stats: Unknown field name %s", c->key);
+                       free (s);
+                       return NULL;
+               }
+
+
+               if (cf_util_get_boolean (c, &enabled) != 0) {
+                       free (s);
+                       return NULL;
+               }
+               if (enabled)
+                       enable_field (s, field_specs[field].offset);
+       }
+
+       return s;
+} /* curl_stats_from_config */
+
+void curl_stats_destroy (curl_stats_t *s)
+{
+       if (s != NULL)
+               free (s);
+} /* curl_stats_destroy */
+
+int curl_stats_dispatch (curl_stats_t *s, CURL *curl,
+               const char *hostname, const char *plugin, const char *plugin_instance)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+
+       if (s == NULL)
+               return 0;
+       if ((curl == NULL) || (hostname == NULL) || (plugin == NULL))
+       {
+               ERROR ("curl stats: dispatch() called with missing arguments "
+                               "(curl=%p; hostname=%s; plugin=%s)", curl,
+                               hostname == NULL ? "<NULL>" : hostname,
+                               plugin == NULL ? "<NULL>" : plugin);
+               return -1;
+       }
+
+       sstrncpy (vl.host, hostname, sizeof (vl.host));
+       sstrncpy (vl.plugin, plugin, sizeof (vl.plugin));
+       if (plugin_instance != NULL)
+               sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+
+       for (size_t field = 0; field < STATIC_ARRAY_SIZE (field_specs); ++field)
+       {
+               int status;
+
+               if (! field_enabled (s, field_specs[field].offset))
+                       continue;
+
+               sstrncpy (vl.type, field_specs[field].type, sizeof (vl.type));
+               sstrncpy (vl.type_instance, field_specs[field].name, sizeof (vl.type_instance));
+
+               vl.values = NULL;
+               vl.values_len = 0;
+               status = field_specs[field].dispatcher (curl, field_specs[field].info, &vl);
+               if (status < 0)
+                       return status;
+       }
+
+       return 0;
+} /* curl_stats_dispatch */
diff --git a/src/utils_curl_stats.h b/src/utils_curl_stats.h
new file mode 100644 (file)
index 0000000..f708c62
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * collectd - src/utils_curl_stats.h
+ * Copyright (C) 2015       Sebastian 'tokkee' Harl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Sebastian Harl <sh@tokkee.org>
+ **/
+
+#ifndef UTILS_CURL_STATS_H
+#define UTILS_CURL_STATS_H 1
+
+#include "configfile.h"
+#include "plugin.h"
+
+#include <curl/curl.h>
+
+struct curl_stats_s;
+typedef struct curl_stats_s curl_stats_t;
+
+/*
+ * curl_stats_from_config allocates and constructs a cURL statistics object
+ * from the specified configuration which is expected to be a single block of
+ * boolean options named after cURL information fields. The boolean value
+ * indicates whether to collect the respective information.
+ *
+ * See http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html
+ */
+curl_stats_t *curl_stats_from_config (oconfig_item_t *ci);
+
+void curl_stats_destroy (curl_stats_t *s);
+
+/*
+ * curl_stats_dispatch dispatches performance values from the the specified
+ * cURL session to the daemon.
+ */
+int curl_stats_dispatch (curl_stats_t *s, CURL *curl,
+               const char *hostname, const char *plugin, const char *plugin_instance);
+
+#endif /* UTILS_CURL_STATS_H */
index fcded6b..e734358 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -54,6 +55,7 @@ struct udb_query_s /* {{{ */
   char *name;
   char *statement;
   void *user_data;
+  char *plugin_instance_from;
 
   unsigned int min_version;
   unsigned int max_version;
@@ -70,6 +72,7 @@ struct udb_result_preparation_area_s /* {{{ */
   char  **instances_buffer;
   char  **values_buffer;
   char  **metadata_buffer;
+  char   *plugin_instance;
 
   struct udb_result_preparation_area_s *next;
 }; /* }}} */
@@ -78,6 +81,7 @@ typedef struct udb_result_preparation_area_s udb_result_preparation_area_t;
 struct udb_query_preparation_area_s /* {{{ */
 {
   size_t column_num;
+  size_t plugin_instance_pos;
   char *host;
   char *plugin;
   char *db_name;
@@ -122,7 +126,6 @@ static int udb_config_add_string (char ***ret_array, /* {{{ */
 {
   char **array;
   size_t array_len;
-  int i;
 
   if (ci->values_num < 1)
   {
@@ -131,7 +134,7 @@ static int udb_config_add_string (char ***ret_array, /* {{{ */
     return (-1);
   }
 
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
   {
     if (ci->values[i].type != OCONFIG_TYPE_STRING)
     {
@@ -142,7 +145,7 @@ static int udb_config_add_string (char ***ret_array, /* {{{ */
   }
 
   array_len = *ret_array_len;
-  array = (char **) realloc (*ret_array,
+  array = realloc (*ret_array,
       sizeof (char *) * (array_len + ci->values_num));
   if (array == NULL)
   {
@@ -151,7 +154,7 @@ static int udb_config_add_string (char ***ret_array, /* {{{ */
   }
   *ret_array = array;
 
-  for (i = 0; i < ci->values_num; i++)
+  for (int i = 0; i < ci->values_num; i++)
   {
     array[array_len] = strdup (ci->values[i].value.string);
     if (array[array_len] == NULL)
@@ -196,23 +199,21 @@ static int udb_result_submit (udb_result_t *r, /* {{{ */
     udb_query_t const *q, udb_query_preparation_area_t *q_area)
 {
   value_list_t vl = VALUE_LIST_INIT;
-  size_t i;
-  int status;
 
   assert (r != NULL);
   assert (r_area->ds != NULL);
   assert (((size_t) r_area->ds->ds_num) == r->values_num);
   assert (r->values_num > 0);
 
-  vl.values = (value_t *) calloc (r->values_num, sizeof (value_t));
+  vl.values = calloc (r->values_num, sizeof (*vl.values));
   if (vl.values == NULL)
   {
-    ERROR ("db query utils: malloc failed.");
+    ERROR ("db query utils: calloc failed.");
     return (-1);
   }
   vl.values_len = r_area->ds->ds_num;
 
-  for (i = 0; i < r->values_num; i++)
+  for (size_t i = 0; i < r->values_num; i++)
   {
     char *value_str = r_area->values_buffer[i];
 
@@ -221,6 +222,7 @@ static int udb_result_submit (udb_result_t *r, /* {{{ */
       ERROR ("db query utils: udb_result_submit: Parsing `%s' as %s failed.",
           value_str, DS_TYPE_TO_STRING (r_area->ds->ds[i].type));
       errno = EINVAL;
+      free (vl.values);
       return (-1);
     }
   }
@@ -230,11 +232,18 @@ static int udb_result_submit (udb_result_t *r, /* {{{ */
 
   sstrncpy (vl.host, q_area->host, sizeof (vl.host));
   sstrncpy (vl.plugin, q_area->plugin, sizeof (vl.plugin));
-  sstrncpy (vl.plugin_instance, q_area->db_name, sizeof (vl.plugin_instance));
   sstrncpy (vl.type, r->type, sizeof (vl.type));
 
+  /* Set vl.plugin_instance */
+  if (q->plugin_instance_from != NULL) {
+    sstrncpy (vl.plugin_instance, r_area->plugin_instance, sizeof (vl.plugin_instance));
+  }
+  else {
+    sstrncpy (vl.plugin_instance, q_area->db_name, sizeof (vl.plugin_instance));
+  }
+
   /* Set vl.type_instance {{{ */
-  if (r->instances_num <= 0)
+  if (r->instances_num == 0)
   {
     if (r->instance_prefix == NULL)
       vl.type_instance[0] = 0;
@@ -286,9 +295,9 @@ static int udb_result_submit (udb_result_t *r, /* {{{ */
       return (-ENOMEM);
     }
 
-    for (i = 0; i < r->metadata_num; i++)
+    for (size_t i = 0; i < r->metadata_num; i++)
     {
-      status = meta_data_add_string (vl.meta, r->metadata[i],
+      int status = meta_data_add_string (vl.meta, r->metadata[i],
           r_area->metadata_buffer[i]);
       if (status != 0)
       {
@@ -332,19 +341,20 @@ static int udb_result_handle_result (udb_result_t *r, /* {{{ */
     udb_result_preparation_area_t *r_area,
     udb_query_t const *q, char **column_values)
 {
-  size_t i;
-
   assert (r && q_area && r_area);
 
-  for (i = 0; i < r->instances_num; i++)
+  for (size_t i = 0; i < r->instances_num; i++)
     r_area->instances_buffer[i] = column_values[r_area->instances_pos[i]];
 
-  for (i = 0; i < r->values_num; i++)
+  for (size_t i = 0; i < r->values_num; i++)
     r_area->values_buffer[i] = column_values[r_area->values_pos[i]];
 
-  for (i = 0; i < r->metadata_num; i++)
+  for (size_t i = 0; i < r->metadata_num; i++)
     r_area->metadata_buffer[i] = column_values[r_area->metadata_pos[i]];
 
+  if (q->plugin_instance_from)
+    r_area->plugin_instance = column_values[q_area->plugin_instance_pos];
+
   return udb_result_submit (r, r_area, q, q_area);
 } /* }}} int udb_result_handle_result */
 
@@ -352,8 +362,6 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
     udb_result_preparation_area_t *prep_area,
     char **column_names, size_t column_num)
 {
-  size_t i;
-
   if ((r == NULL) || (prep_area == NULL))
     return (-EINVAL);
 
@@ -383,10 +391,10 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
     BAIL_OUT (-1);
   }
 
-  if (((size_t) prep_area->ds->ds_num) != r->values_num)
+  if (prep_area->ds->ds_num != r->values_num)
   {
     ERROR ("db query utils: udb_result_prepare_result: The type `%s' "
-        "requires exactly %i value%s, but the configuration specifies %zu.",
+        "requires exactly %zu value%s, but the configuration specifies %zu.",
         r->type,
         prep_area->ds->ds_num, (prep_area->ds->ds_num == 1) ? "" : "s",
         r->values_num);
@@ -402,7 +410,7 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
       = (size_t *) calloc (r->instances_num, sizeof (size_t));
     if (prep_area->instances_pos == NULL)
     {
-      ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+      ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
       BAIL_OUT (-ENOMEM);
     }
 
@@ -410,7 +418,7 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
       = (char **) calloc (r->instances_num, sizeof (char *));
     if (prep_area->instances_buffer == NULL)
     {
-      ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+      ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
       BAIL_OUT (-ENOMEM);
     }
   } /* if (r->instances_num > 0) */
@@ -419,7 +427,7 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
     = (size_t *) calloc (r->values_num, sizeof (size_t));
   if (prep_area->values_pos == NULL)
   {
-    ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+    ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
     BAIL_OUT (-ENOMEM);
   }
 
@@ -427,7 +435,7 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
     = (char **) calloc (r->values_num, sizeof (char *));
   if (prep_area->values_buffer == NULL)
   {
-    ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+    ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
     BAIL_OUT (-ENOMEM);
   }
 
@@ -435,7 +443,7 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
     = (size_t *) calloc (r->metadata_num, sizeof (size_t));
   if (prep_area->metadata_pos == NULL)
   {
-    ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+    ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
     BAIL_OUT (-ENOMEM);
   }
 
@@ -443,14 +451,14 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
     = (char **) calloc (r->metadata_num, sizeof (char *));
   if (prep_area->metadata_buffer == NULL)
   {
-    ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+    ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
     BAIL_OUT (-ENOMEM);
   }
 
   /* }}} */
 
-  /* Determine the position of the instance columns {{{ */
-  for (i = 0; i < r->instances_num; i++)
+  /* Determine the position of the plugin instance column {{{ */
+  for (size_t i = 0; i < r->instances_num; i++)
   {
     size_t j;
 
@@ -472,8 +480,9 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
     }
   } /* }}} for (i = 0; i < r->instances_num; i++) */
 
+
   /* Determine the position of the value columns {{{ */
-  for (i = 0; i < r->values_num; i++)
+  for (size_t i = 0; i < r->values_num; i++)
   {
     size_t j;
 
@@ -496,7 +505,7 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
   } /* }}} for (i = 0; i < r->values_num; i++) */
 
   /* Determine the position of the metadata columns {{{ */
-  for (i = 0; i < r->metadata_num; i++)
+  for (size_t i = 0; i < r->metadata_num; i++)
   {
     size_t j;
 
@@ -524,22 +533,21 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
 
 static void udb_result_free (udb_result_t *r) /* {{{ */
 {
-  size_t i;
-
   if (r == NULL)
     return;
 
   sfree (r->type);
+  sfree (r->instance_prefix);
 
-  for (i = 0; i < r->instances_num; i++)
+  for (size_t i = 0; i < r->instances_num; i++)
     sfree (r->instances[i]);
   sfree (r->instances);
 
-  for (i = 0; i < r->values_num; i++)
+  for (size_t i = 0; i < r->values_num; i++)
     sfree (r->values[i]);
   sfree (r->values);
 
-  for (i = 0; i < r->metadata_num; i++)
+  for (size_t i = 0; i < r->metadata_num; i++)
     sfree (r->metadata[i]);
   sfree (r->metadata);
 
@@ -553,7 +561,6 @@ static int udb_result_create (const char *query_name, /* {{{ */
 {
   udb_result_t *r;
   int status;
-  int i;
 
   if (ci->values_num != 0)
   {
@@ -562,13 +569,12 @@ static int udb_result_create (const char *query_name, /* {{{ */
         ci->values_num, (ci->values_num == 1) ? "" : "s");
   }
 
-  r = (udb_result_t *) malloc (sizeof (*r));
+  r = calloc (1, sizeof (*r));
   if (r == NULL)
   {
-    ERROR ("db query utils: malloc failed.");
+    ERROR ("db query utils: calloc failed.");
     return (-1);
   }
-  memset (r, 0, sizeof (*r));
   r->type = NULL;
   r->instance_prefix = NULL;
   r->instances = NULL;
@@ -578,7 +584,7 @@ static int udb_result_create (const char *query_name, /* {{{ */
 
   /* Fill the `udb_result_t' structure.. */
   status = 0;
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -657,6 +663,7 @@ static void udb_query_free_one (udb_query_t *q) /* {{{ */
 
   sfree (q->name);
   sfree (q->statement);
+  sfree (q->plugin_instance_from);
 
   udb_result_free (q->results);
 
@@ -675,7 +682,6 @@ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */
 
   udb_query_t *q;
   int status;
-  int i;
 
   if ((ret_query_list == NULL) || (ret_query_list_len == NULL))
     return (-EINVAL);
@@ -690,15 +696,17 @@ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */
     return (-1);
   }
 
-  q = (udb_query_t *) malloc (sizeof (*q));
+  q = calloc (1, sizeof (*q));
   if (q == NULL)
   {
-    ERROR ("db query utils: malloc failed.");
+    ERROR ("db query utils: calloc failed.");
     return (-1);
   }
-  memset (q, 0, sizeof (*q));
   q->min_version = 0;
   q->max_version = UINT_MAX;
+  q->statement = NULL;
+  q->results = NULL;
+  q->plugin_instance_from = NULL;
 
   status = udb_config_set_string (&q->name, ci);
   if (status != 0)
@@ -708,7 +716,7 @@ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */
   }
 
   /* Fill the `udb_query_t' structure.. */
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -720,6 +728,8 @@ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */
       status = udb_config_set_uint (&q->min_version, child);
     else if (strcasecmp ("MaxVersion", child->key) == 0)
       status = udb_config_set_uint (&q->max_version, child);
+    else if (strcasecmp ("PluginInstanceFrom", child->key) == 0)
+      status = udb_config_set_string (&q->plugin_instance_from, child);
 
     /* Call custom callbacks */
     else if (cb != NULL)
@@ -764,7 +774,7 @@ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */
   {
     udb_query_t **temp;
 
-    temp = (udb_query_t **) realloc (query_list,
+    temp = realloc (query_list,
         sizeof (*query_list) * (query_list_len + 1));
     if (temp == NULL)
     {
@@ -793,12 +803,10 @@ int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */
 
 void udb_query_free (udb_query_t **query_list, size_t query_list_len) /* {{{ */
 {
-  size_t i;
-
   if (query_list == NULL)
     return;
 
-  for (i = 0; i < query_list_len; i++)
+  for (size_t i = 0; i < query_list_len; i++)
     udb_query_free_one (query_list[i]);
 
   sfree (query_list);
@@ -808,7 +816,6 @@ int udb_query_pick_from_list_by_name (const char *name, /* {{{ */
     udb_query_t **src_list, size_t src_list_len,
     udb_query_t ***dst_list, size_t *dst_list_len)
 {
-  size_t i;
   int num_added;
 
   if ((name == NULL) || (src_list == NULL) || (dst_list == NULL)
@@ -820,7 +827,7 @@ int udb_query_pick_from_list_by_name (const char *name, /* {{{ */
   }
 
   num_added = 0;
-  for (i = 0; i < src_list_len; i++)
+  for (size_t i = 0; i < src_list_len; i++)
   {
     udb_query_t **tmp_list;
     size_t tmp_list_len;
@@ -829,7 +836,7 @@ int udb_query_pick_from_list_by_name (const char *name, /* {{{ */
       continue;
 
     tmp_list_len = *dst_list_len;
-    tmp_list = (udb_query_t **) realloc (*dst_list, (tmp_list_len + 1)
+    tmp_list = realloc (*dst_list, (tmp_list_len + 1)
         * sizeof (udb_query_t *));
     if (tmp_list == NULL)
     {
@@ -981,9 +988,7 @@ int udb_query_handle_result (udb_query_t const *q, /* {{{ */
 #if defined(COLLECT_DEBUG) && COLLECT_DEBUG /* {{{ */
   do
   {
-    size_t i;
-
-    for (i = 0; i < prep_area->column_num; i++)
+    for (size_t i = 0; i < prep_area->column_num; i++)
     {
       DEBUG ("db query utils: udb_query_handle_result (%s, %s): "
           "column[%zu] = %s;",
@@ -1044,9 +1049,7 @@ int udb_query_prepare_result (udb_query_t const *q, /* {{{ */
 #if defined(COLLECT_DEBUG) && COLLECT_DEBUG
   do
   {
-    size_t i;
-
-    for (i = 0; i < column_num; i++)
+    for (size_t i = 0; i < column_num; i++)
     {
       DEBUG ("db query utils: udb_query_prepare_result: "
           "query = %s; column[%zu] = %s;",
@@ -1055,6 +1058,31 @@ int udb_query_prepare_result (udb_query_t const *q, /* {{{ */
   } while (0);
 #endif
 
+  /* Determine the position of the PluginInstance column {{{ */
+  if (q->plugin_instance_from != NULL)
+  {
+    size_t i;
+
+    for (i = 0; i < column_num; i++)
+    {
+      if (strcasecmp (q->plugin_instance_from, column_names[i]) == 0)
+      {
+        prep_area->plugin_instance_pos = i;
+        break;
+      }
+    }
+
+    if (i >= column_num)
+    {
+      ERROR ("db query utils: udb_query_prepare_result: "
+          "Column `%s' from `PluginInstanceFrom' could not be found.",
+          q->plugin_instance_from);
+      udb_query_finish_result (q, prep_area);
+      return (-ENOENT);
+    }
+  }
+  /* }}} */
+
   for (r = q->results, r_area = prep_area->result_prep_areas;
       r != NULL; r = r->next, r_area = r_area->next)
   {
@@ -1084,17 +1112,16 @@ udb_query_allocate_preparation_area (udb_query_t *q) /* {{{ */
   udb_result_preparation_area_t **next_r_area;
   udb_result_t *r;
 
-  q_area = malloc (sizeof (*q_area));
+  q_area = calloc (1, sizeof (*q_area));
   if (q_area == NULL)
     return NULL;
-  memset (q_area, 0, sizeof (*q_area));
 
   next_r_area = &q_area->result_prep_areas;
   for (r = q->results; r != NULL; r = r->next)
   {
     udb_result_preparation_area_t *r_area;
 
-    r_area = malloc (sizeof (*r_area));
+    r_area = calloc (1, sizeof (*r_area));
     if (r_area == NULL)
     {
       udb_result_preparation_area_t *a = q_area->result_prep_areas;
@@ -1110,8 +1137,6 @@ udb_query_allocate_preparation_area (udb_query_t *q) /* {{{ */
       return NULL;
     }
 
-    memset (r_area, 0, sizeof (*r_area));
-
     *next_r_area = r_area;
     next_r_area  = &r_area->next;
   }
index 08b10bd..8586adb 100644 (file)
@@ -41,7 +41,7 @@ typedef struct udb_query_preparation_area_s udb_query_preparation_area_t;
 typedef int (*udb_query_create_callback_t) (udb_query_t *q,
     oconfig_item_t *ci);
 
-/* 
+/*
  * Public functions
  */
 int udb_query_create (udb_query_t ***ret_query_list,
@@ -62,7 +62,7 @@ const char *udb_query_get_statement (udb_query_t *q);
 void  udb_query_set_user_data (udb_query_t *q, void *user_data);
 void *udb_query_get_user_data (udb_query_t *q);
 
-/* 
+/*
  * udb_query_check_version
  *
  * Returns 0 if the query is NOT suitable for `version' and >0 if the
index 6abfde1..f38a7bd 100644 (file)
 #define _BSD_SOURCE
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-
 #if HAVE_NET_IF_ARP_H
 # include <net/if_arp.h>
 #endif
@@ -66,9 +63,6 @@
 #if HAVE_NETINET_IP6_H
 # include <netinet/ip6.h>
 #endif
-#if HAVE_NETINET_IP_COMPAT_H
-# include <netinet/ip_compat.h>
-#endif
 #if HAVE_NETINET_IF_ETHER_H
 # include <netinet/if_ether.h>
 #endif
@@ -163,9 +157,6 @@ typedef int (printer)(const char *, ...);
 /*
  * Global variables
  */
-int qtype_counts[T_MAX];
-int opcode_counts[OP_MAX];
-int qclass_counts[C_MAX];
 
 #if HAVE_PCAP_H
 static pcap_t *pcap_obj = NULL;
@@ -204,9 +195,7 @@ static int cmp_in6_addr (const struct in6_addr *a,
 
 static inline int ignore_list_match (const struct in6_addr *addr)
 {
-    ip_list_t *ptr;
-
-    for (ptr = IgnoreList; ptr != NULL; ptr = ptr->next)
+    for (ip_list_t *ptr = IgnoreList; ptr != NULL; ptr = ptr->next)
        if (cmp_in6_addr (addr, &ptr->addr) == 0)
            return (1);
     return (0);
@@ -219,7 +208,7 @@ static void ignore_list_add (const struct in6_addr *addr)
     if (ignore_list_match (addr) != 0)
        return;
 
-    new = malloc (sizeof (ip_list_t));
+    new = malloc (sizeof (*new));
     if (new == NULL)
     {
        perror ("malloc");
@@ -235,7 +224,6 @@ static void ignore_list_add (const struct in6_addr *addr)
 void ignore_list_add_name (const char *name)
 {
     struct addrinfo *ai_list;
-    struct addrinfo *ai_ptr;
     struct in6_addr  addr;
     int status;
 
@@ -243,7 +231,7 @@ void ignore_list_add_name (const char *name)
     if (status != 0)
        return;
 
-    for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+    for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
     {
        if (ai_ptr->ai_family == AF_INET)
        {
@@ -293,8 +281,7 @@ void dnstop_set_callback (void (*cb) (const rfc1035_header_t *))
 
 #define RFC1035_MAXLABELSZ 63
 static int
-rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
-)
+rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns)
 {
     off_t no = 0;
     unsigned char c;
@@ -302,10 +289,10 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
     static int loop_detect = 0;
     if (loop_detect > 2)
        return 4;               /* compression loop */
-    if (ns <= 0)
+    if (ns == 0)
        return 4;               /* probably compression loop */
     do {
-       if ((*off) >= sz)
+       if ((*off) >= ((off_t) sz))
            break;
        c = *(buf + (*off));
        if (c > 191) {
@@ -317,11 +304,11 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
            s = ntohs(s);
            (*off) += sizeof(s);
            /* Sanity check */
-           if ((*off) >= sz)
+           if ((*off) >= ((off_t) sz))
                return 1;       /* message too short */
            ptr = s & 0x3FFF;
            /* Make sure the pointer is inside this message */
-           if (ptr >= sz)
+           if (ptr >= ((off_t) sz))
                return 2;       /* bad compression ptr */
            if (ptr < DNS_MSG_HDR_SZ)
                return 2;       /* bad compression ptr */
@@ -334,7 +321,6 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
             * "(The 10 and 01 combinations are reserved for future use.)"
             */
            return 3;           /* reserved label/compression flags */
-           break;
        } else {
            (*off)++;
            len = (size_t) c;
@@ -355,7 +341,7 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
     if (no > 0)
        *(name + no - 1) = '\0';
     /* make sure we didn't allow someone to overflow the name buffer */
-    assert(no <= ns);
+    assert(no <= ((off_t) ns));
     return 0;
 }
 
@@ -425,11 +411,6 @@ handle_dns(const char *buf, int len)
 
     qh.length = (uint16_t) len;
 
-    /* gather stats */
-    qtype_counts[qh.qtype]++;
-    qclass_counts[qh.qclass]++;
-    opcode_counts[qh.opcode]++;
-
     if (Callback != NULL)
            Callback (&qh);
 
@@ -768,22 +749,41 @@ const char *qtype_str(int t)
            case ns_t_srv:      return ("SRV");
            case ns_t_atma:     return ("ATMA");
            case ns_t_naptr:    return ("NAPTR");
+           case ns_t_opt:      return ("OPT");
+# if __NAMESER >= 19991006
            case ns_t_kx:       return ("KX");
            case ns_t_cert:     return ("CERT");
            case ns_t_a6:       return ("A6");
            case ns_t_dname:    return ("DNAME");
            case ns_t_sink:     return ("SINK");
-           case ns_t_opt:      return ("OPT");
-# if __NAMESER >= 19991006
            case ns_t_tsig:     return ("TSIG");
 # endif
+# if __NAMESER >= 20090302
+           case ns_t_apl:      return ("APL");
+           case ns_t_ds:       return ("DS");
+           case ns_t_sshfp:    return ("SSHFP");
+           case ns_t_ipseckey: return ("IPSECKEY");
+           case ns_t_rrsig:    return ("RRSIG");
+           case ns_t_nsec:     return ("NSEC");
+           case ns_t_dnskey:   return ("DNSKEY");
+           case ns_t_dhcid:    return ("DHCID");
+           case ns_t_nsec3:    return ("NSEC3");
+           case ns_t_nsec3param: return ("NSEC3PARAM");
+           case ns_t_hip:      return ("HIP");
+           case ns_t_spf:      return ("SPF");
            case ns_t_ixfr:     return ("IXFR");
+# endif
            case ns_t_axfr:     return ("AXFR");
            case ns_t_mailb:    return ("MAILB");
            case ns_t_maila:    return ("MAILA");
            case ns_t_any:      return ("ANY");
+# if __NAMESER >= 19991006
            case ns_t_zxfr:     return ("ZXFR");
-/* #endif __NAMESER >= 19991006 */
+# endif
+# if __NAMESER >= 20090302
+           case ns_t_dlv:       return ("DLV");
+# endif
+/* #endif __NAMESER >= 19991001 */
 #elif (defined (__BIND)) && (__BIND >= 19950621)
            case T_A:           return ("A"); /* 1 ... */
            case T_NS:          return ("NS");
@@ -845,9 +845,7 @@ const char *qtype_str(int t)
            default:
                    ssnprintf (buf, sizeof (buf), "#%i", t);
                    return (buf);
-    }; /* switch (t) */
-    /* NOTREACHED */
-    return (NULL);
+    } /* switch (t) */
 }
 
 const char *opcode_str (int o)
@@ -856,24 +854,18 @@ const char *opcode_str (int o)
     switch (o) {
     case 0:
        return "Query";
-       break;
     case 1:
        return "Iquery";
-       break;
     case 2:
        return "Status";
-       break;
     case 4:
        return "Notify";
-       break;
     case 5:
        return "Update";
-       break;
     default:
        ssnprintf(buf, sizeof (buf), "Opcode%d", o);
        return buf;
     }
-    /* NOTREACHED */
 }
 
 const char *rcode_str (int rcode)
@@ -917,8 +909,6 @@ const char *rcode_str (int rcode)
                        ssnprintf (buf, sizeof (buf), "RCode%i", rcode);
                        return (buf);
        }
-       /* Never reached */
-       return (NULL);
 } /* const char *rcode_str (int rcode) */
 
 #if 0
index 83f0ea4..5c547c6 100644 (file)
@@ -3,10 +3,10 @@
  * Copyright (C) 2006       Florian octo Forster
  * Copyright (C) 2002       The Measurement Factory, Inc.
  * All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright notice,
  *    this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright notice,
@@ -48,8 +48,6 @@
 #define DNS_MSG_HDR_SZ 12
 
 #define T_MAX 65536
-#define OP_MAX 16
-#define C_MAX 65536
 #define MAX_QNAME_SZ 512
 
 struct rfc1035_header_s {
@@ -75,10 +73,6 @@ struct rfc1035_header_s {
 };
 typedef struct rfc1035_header_s rfc1035_header_t;
 
-extern int qtype_counts[T_MAX];
-extern int opcode_counts[OP_MAX];
-extern int qclass_counts[C_MAX];
-
 #if HAVE_PCAP_H
 void dnstop_set_pcap_obj (pcap_t *po);
 #endif
index cbd1506..893bfbd 100644 (file)
@@ -25,9 +25,8 @@
  **/
 
 #include "collectd.h"
-#include "plugin.h"
 
-#include <pthread.h>
+#include "plugin.h"
 
 #include "utils_fbhash.h"
 #include "utils_avltree.h"
@@ -71,7 +70,7 @@ static int fbh_read_file (fbhash_t *h) /* {{{ */
 {
   FILE *fh;
   char buffer[4096];
-  struct flock fl;
+  struct flock fl = { 0 };
   c_avl_tree_t *tree;
   int status;
 
@@ -79,11 +78,8 @@ static int fbh_read_file (fbhash_t *h) /* {{{ */
   if (fh == NULL)
     return (-1);
 
-  memset (&fl, 0, sizeof (fl));
   fl.l_type = F_RDLCK;
   fl.l_whence = SEEK_SET;
-  fl.l_start = 0;
-  fl.l_len = 0; /* == entire file */
   /* TODO: Lock file? -> fcntl */
 
   status = fcntl (fileno (fh), F_SETLK, &fl);
@@ -93,7 +89,7 @@ static int fbh_read_file (fbhash_t *h) /* {{{ */
     return (-1);
   }
 
-  tree = c_avl_create ((void *) strcmp);
+  tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
   if (tree == NULL)
   {
     fclose (fh);
@@ -179,11 +175,9 @@ static int fbh_read_file (fbhash_t *h) /* {{{ */
 
 static int fbh_check_file (fbhash_t *h) /* {{{ */
 {
-  struct stat statbuf;
+  struct stat statbuf = { 0 };
   int status;
 
-  memset (&statbuf, 0, sizeof (statbuf));
-
   status = stat (h->filename, &statbuf);
   if (status != 0)
     return (-1);
@@ -209,10 +203,9 @@ fbhash_t *fbh_create (const char *file) /* {{{ */
   if (file == NULL)
     return (NULL);
 
-  h = malloc (sizeof (*h));
+  h = calloc (1, sizeof (*h));
   if (h == NULL)
     return (NULL);
-  memset (h, 0, sizeof (*h));
 
   h->filename = strdup (file);
   if (h->filename == NULL)
index 023f7a4..e523420 100644 (file)
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 
@@ -84,14 +85,12 @@ static int gr_format_values (char *ret, size_t ret_len,
 static void gr_copy_escape_part (char *dst, const char *src, size_t dst_len,
     char escape_char)
 {
-    size_t i;
-
     memset (dst, 0, dst_len);
 
     if (src == NULL)
         return;
 
-    for (i = 0; i < dst_len; i++)
+    for (size_t i = 0; i < dst_len; i++)
     {
         if (src[i] == 0)
         {
@@ -172,11 +171,9 @@ static int gr_format_name (char *ret, int ret_len,
 
 static void escape_graphite_string (char *buffer, char escape_char)
 {
-       char *head;
-
        assert (strchr(GRAPHITE_FORBIDDEN, escape_char) == NULL);
 
-       for (head = buffer + strcspn(buffer, GRAPHITE_FORBIDDEN);
+       for (char *head = buffer + strcspn(buffer, GRAPHITE_FORBIDDEN);
             *head != '\0';
             head += strcspn(head, GRAPHITE_FORBIDDEN))
                *head = escape_char;
@@ -188,14 +185,13 @@ int format_graphite (char *buffer, size_t buffer_size,
     unsigned int flags)
 {
     int status = 0;
-    int i;
     int buffer_pos = 0;
 
     gauge_t *rates = NULL;
     if (flags & GRAPHITE_STORE_RATES)
       rates = uc_get_rate (ds, vl);
 
-    for (i = 0; i < ds->ds_num; i++)
+    for (size_t i = 0; i < ds->ds_num; i++)
     {
         char const *ds_name = NULL;
         char        key[10*DATA_MAX_NAME_LEN];
index 398defb..60576da 100644 (file)
@@ -23,6 +23,7 @@
 #define UTILS_FORMAT_GRAPHITE_H 1
 
 #include "collectd.h"
+
 #include "plugin.h"
 
 #define GRAPHITE_STORE_RATES        0x01
index 020d80b..5b5fcdf 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/utils_format_json.c
- * Copyright (C) 2009       Florian octo Forster
+ * Copyright (C) 2009-2015  Florian octo Forster
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  **/
 
 #include "collectd.h"
+
+#include "utils_format_json.h"
+
 #include "plugin.h"
 #include "common.h"
-
 #include "utils_cache.h"
-#include "utils_format_json.h"
+
+#if HAVE_LIBYAJL
+# include <yajl/yajl_common.h>
+# include <yajl/yajl_gen.h>
+# if HAVE_YAJL_YAJL_VERSION_H
+#  include <yajl/yajl_version.h>
+# endif
+# if defined(YAJL_MAJOR) && (YAJL_MAJOR > 1)
+#  define HAVE_YAJL_V2 1
+# endif
+#endif
 
 static int json_escape_string (char *buffer, size_t buffer_size, /* {{{ */
     const char *string)
 {
-  size_t src_pos;
   size_t dst_pos;
 
   if ((buffer == NULL) || (string == NULL))
@@ -56,7 +67,7 @@ static int json_escape_string (char *buffer, size_t buffer_size, /* {{{ */
 
   /* Escape special characters */
   BUFFER_ADD ('"');
-  for (src_pos = 0; string[src_pos] != 0; src_pos++)
+  for (size_t src_pos = 0; string[src_pos] != 0; src_pos++)
   {
     if ((string[src_pos] == '"')
         || (string[src_pos] == '\\'))
@@ -81,7 +92,6 @@ static int values_to_json (char *buffer, size_t buffer_size, /* {{{ */
                 const data_set_t *ds, const value_list_t *vl, int store_rates)
 {
   size_t offset = 0;
-  int i;
   gauge_t *rates = NULL;
 
   memset (buffer, 0, buffer_size);
@@ -105,7 +115,7 @@ static int values_to_json (char *buffer, size_t buffer_size, /* {{{ */
 } while (0)
 
   BUFFER_ADD ("[");
-  for (i = 0; i < ds->ds_num; i++)
+  for (size_t i = 0; i < ds->ds_num; i++)
   {
     if (i > 0)
       BUFFER_ADD (",");
@@ -160,7 +170,6 @@ static int dstypes_to_json (char *buffer, size_t buffer_size, /* {{{ */
                 const data_set_t *ds)
 {
   size_t offset = 0;
-  int i;
 
   memset (buffer, 0, buffer_size);
 
@@ -177,7 +186,7 @@ static int dstypes_to_json (char *buffer, size_t buffer_size, /* {{{ */
 } while (0)
 
   BUFFER_ADD ("[");
-  for (i = 0; i < ds->ds_num; i++)
+  for (size_t i = 0; i < ds->ds_num; i++)
   {
     if (i > 0)
       BUFFER_ADD (",");
@@ -197,7 +206,6 @@ static int dsnames_to_json (char *buffer, size_t buffer_size, /* {{{ */
                 const data_set_t *ds)
 {
   size_t offset = 0;
-  int i;
 
   memset (buffer, 0, buffer_size);
 
@@ -214,7 +222,7 @@ static int dsnames_to_json (char *buffer, size_t buffer_size, /* {{{ */
 } while (0)
 
   BUFFER_ADD ("[");
-  for (i = 0; i < ds->ds_num; i++)
+  for (size_t i = 0; i < ds->ds_num; i++)
   {
     if (i > 0)
       BUFFER_ADD (",");
@@ -235,7 +243,6 @@ static int meta_data_keys_to_json (char *buffer, size_t buffer_size, /* {{{ */
 {
   size_t offset = 0;
   int status;
-  size_t i;
 
   buffer[0] = 0;
 
@@ -250,7 +257,7 @@ static int meta_data_keys_to_json (char *buffer, size_t buffer_size, /* {{{ */
     offset += ((size_t) status); \
 } while (0)
 
-  for (i = 0; i < keys_num; ++i)
+  for (size_t i = 0; i < keys_num; ++i)
   {
     int type;
     char *key = keys[i];
@@ -297,7 +304,7 @@ static int meta_data_keys_to_json (char *buffer, size_t buffer_size, /* {{{ */
     }
   } /* for (keys) */
 
-  if (offset <= 0)
+  if (offset == 0)
     return (ENOENT);
 
   buffer[0] = '{'; /* replace leading ',' */
@@ -314,7 +321,6 @@ static int meta_data_to_json (char *buffer, size_t buffer_size, /* {{{ */
   char **keys = NULL;
   size_t keys_num;
   int status;
-  size_t i;
 
   if ((buffer == NULL) || (buffer_size == 0) || (meta == NULL))
     return (EINVAL);
@@ -326,7 +332,7 @@ static int meta_data_to_json (char *buffer, size_t buffer_size, /* {{{ */
 
   status = meta_data_keys_to_json (buffer, buffer_size, meta, keys, keys_num);
 
-  for (i = 0; i < keys_num; ++i)
+  for (size_t i = 0; i < keys_num; ++i)
     sfree (keys[i]);
   sfree (keys);
 
@@ -498,4 +504,215 @@ int format_json_value_list (char *buffer, /* {{{ */
         store_rates, (*ret_buffer_free) - 2));
 } /* }}} int format_json_value_list */
 
+#if HAVE_LIBYAJL
+static int json_add_string (yajl_gen g, char const *str) /* {{{ */
+{
+  if (str == NULL)
+    return (int) yajl_gen_null (g);
+
+  return (int) yajl_gen_string (g, (unsigned char const *) str, (unsigned int) strlen (str));
+} /* }}} int json_add_string */
+
+#define JSON_ADD(g, str) do {                        \
+  yajl_gen_status status = json_add_string (g, str); \
+  if (status != yajl_gen_status_ok) { return -1; }   \
+} while (0)
+
+#define JSON_ADDF(g, format, ...) do {               \
+  char *str = ssnprintf_alloc (format, __VA_ARGS__); \
+  yajl_gen_status status = json_add_string (g, str); \
+  free (str);                                        \
+  if (status != yajl_gen_status_ok) { return -1; }   \
+} while (0)
+
+static int format_json_meta (yajl_gen g, notification_meta_t *meta) /* {{{ */
+{
+  if (meta == NULL)
+    return 0;
+
+  JSON_ADD (g, meta->name);
+  switch (meta->type)
+  {
+    case NM_TYPE_STRING:
+      JSON_ADD (g, meta->nm_value.nm_string);
+      break;
+    case NM_TYPE_SIGNED_INT:
+      JSON_ADDF (g, "%"PRIi64, meta->nm_value.nm_signed_int);
+      break;
+    case NM_TYPE_UNSIGNED_INT:
+      JSON_ADDF (g, "%"PRIu64, meta->nm_value.nm_unsigned_int);
+      break;
+    case NM_TYPE_DOUBLE:
+      JSON_ADDF (g, JSON_GAUGE_FORMAT, meta->nm_value.nm_double);
+      break;
+    case NM_TYPE_BOOLEAN:
+      JSON_ADD (g, meta->nm_value.nm_boolean ? "true" : "false");
+      break;
+    default:
+      ERROR ("format_json_meta: unknown meta data type %d (name \"%s\")", meta->type, meta->name);
+      yajl_gen_null (g);
+  }
+
+  return format_json_meta (g, meta->next);
+} /* }}} int format_json_meta */
+
+static int format_time (yajl_gen g, cdtime_t t) /* {{{ */
+{
+  char buffer[RFC3339NANO_SIZE] = "";
+
+  if (rfc3339nano (buffer, sizeof (buffer), t) != 0)
+    return -1;
+
+  JSON_ADD (g, buffer);
+  return 0;
+} /* }}} int format_time */
+
+static int format_alert (yajl_gen g, notification_t const *n) /* {{{ */
+{
+  yajl_gen_array_open (g);
+  yajl_gen_map_open (g); /* BEGIN alert */
+
+  /*
+   * labels
+   */
+  JSON_ADD (g, "labels");
+  yajl_gen_map_open (g); /* BEGIN labels */
+
+  JSON_ADD (g, "alertname");
+  if (strncmp (n->plugin, n->type, strlen (n->plugin)) == 0)
+    JSON_ADDF (g, "collectd_%s", n->type);
+  else
+    JSON_ADDF (g, "collectd_%s_%s", n->plugin, n->type);
+
+  JSON_ADD (g, "instance");
+  JSON_ADD (g, n->host);
+
+  /* mangling of plugin instance and type instance into labels is copied from
+   * the Prometheus collectd exporter. */
+  if (strlen (n->plugin_instance) > 0)
+  {
+    JSON_ADD (g, n->plugin);
+    JSON_ADD (g, n->plugin_instance);
+  }
+  if (strlen (n->type_instance) > 0)
+  {
+    if (strlen (n->plugin_instance) > 0)
+      JSON_ADD (g, "type");
+    else
+      JSON_ADD (g, n->plugin);
+    JSON_ADD (g, n->type_instance);
+  }
+
+  JSON_ADD (g, "severity");
+  JSON_ADD (g, (n->severity == NOTIF_FAILURE) ? "FAILURE"
+                   : (n->severity == NOTIF_WARNING) ? "WARNING"
+                   : (n->severity == NOTIF_OKAY) ? "OKAY"
+                   : "UNKNOWN");
+
+  JSON_ADD (g, "service");
+  JSON_ADD (g, "collectd");
+
+  yajl_gen_map_close (g); /* END labels */
+
+  /*
+   * annotations
+   */
+  JSON_ADD (g, "annotations");
+  yajl_gen_map_open (g); /* BEGIN annotations */
+
+  JSON_ADD (g, "summary");
+  JSON_ADD (g, n->message);
+
+  if (format_json_meta (g, n->meta) != 0)
+    return -1;
+
+  yajl_gen_map_close (g); /* END annotations */
+
+  JSON_ADD (g, "startsAt");
+  format_time (g, n->time);
+
+  yajl_gen_map_close (g); /* END alert */
+  yajl_gen_array_close (g);
+
+  return 0;
+} /* }}} format_alert */
+
+/*
+ * Format (prometheus/alertmanager v1):
+ *
+ * [{
+ *   "labels": {
+ *     "alertname": "collectd_cpu",
+ *     "instance":  "host.example.com",
+ *     "severity":  "FAILURE",
+ *     "service":   "collectd",
+ *     "cpu":       "0",
+ *     "type":      "wait"
+ *   },
+ *   "annotations": {
+ *     "summary": "...",
+ *     // meta
+ *   },
+ *   "startsAt": <rfc3339 time>,
+ *   "endsAt": <rfc3339 time>, // not used
+ * }]
+ */
+int format_json_notification (char *buffer, size_t buffer_size, /* {{{ */
+                              notification_t const *n)
+{
+  yajl_gen g;
+  unsigned char const *out;
+#if HAVE_YAJL_V2
+  size_t unused_out_len;
+#else
+  unsigned int unused_out_len;
+#endif
+
+  if ((buffer == NULL) || (n == NULL))
+    return EINVAL;
+
+#if HAVE_YAJL_V2
+  g = yajl_gen_alloc (NULL);
+  if (g == NULL)
+    return -1;
+# if COLLECT_DEBUG
+  yajl_gen_config (g, yajl_gen_beautify, 1);
+  yajl_gen_config (g, yajl_gen_validate_utf8, 1);
+# endif
+
+#else /* !HAVE_YAJL_V2 */
+  yajl_gen_config conf = { 0 };
+# if COLLECT_DEBUG
+  conf.beautify = 1;
+  conf.indentString = "  ";
+# endif
+  g = yajl_gen_alloc (&conf, NULL);
+  if (g == NULL)
+    return -1;
+#endif
+
+  if (format_alert (g, n) != 0)
+  {
+    yajl_gen_clear (g);
+    yajl_gen_free (g);
+    return -1;
+  }
+
+  /* copy to output buffer */
+  yajl_gen_get_buf (g, &out, &unused_out_len);
+  sstrncpy (buffer, (void *) out, buffer_size);
+
+  yajl_gen_clear (g);
+  yajl_gen_free (g);
+  return 0;
+} /* }}} format_json_notification */
+#else
+int format_json_notification (char *buffer, size_t buffer_size, /* {{{ */
+                              notification_t const *n)
+{
+  ERROR ("format_json_notification: Not available (requires libyajl).");
+  return ENOTSUP;
+} /* }}} int format_json_notification */
+#endif
+
 /* vim: set sw=2 sts=2 et fdm=marker : */
index f1fbb6e..a3eda30 100644 (file)
@@ -28,6 +28,7 @@
 #define UTILS_FORMAT_JSON_H 1
 
 #include "collectd.h"
+
 #include "plugin.h"
 
 #ifndef JSON_GAUGE_FORMAT
@@ -41,5 +42,7 @@ int format_json_value_list (char *buffer,
     const data_set_t *ds, const value_list_t *vl, int store_rates);
 int format_json_finalize (char *buffer,
     size_t *ret_buffer_fill, size_t *ret_buffer_free);
+int format_json_notification (char *buffer, size_t buffer_size,
+    notification_t const *n);
 
 #endif /* UTILS_FORMAT_JSON_H */
diff --git a/src/utils_format_json_test.c b/src/utils_format_json_test.c
new file mode 100644 (file)
index 0000000..1c8a8ce
--- /dev/null
@@ -0,0 +1,170 @@
+/**
+ * collectd - src/utils_format_json_test.c
+ * Copyright (C) 2015       Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "collectd.h"
+
+#include "testing.h"
+#include "utils_format_json.h"
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+
+#include <yajl/yajl_common.h>
+#include <yajl/yajl_parse.h>
+#if HAVE_YAJL_YAJL_VERSION_H
+# include <yajl/yajl_version.h>
+#endif
+#if YAJL_MAJOR > 1
+# define HAVE_YAJL_V2 1
+#endif
+
+typedef struct
+{
+  char const *key;
+  char const *value;
+} label_t;
+
+typedef struct
+{
+  label_t *expected_labels;
+  size_t   expected_labels_num;
+
+  label_t *current_label;
+} test_case_t;
+
+#if HAVE_YAJL_V2
+static int test_map_key (void *ctx, unsigned char const *key, size_t key_len)
+#else
+static int test_map_key (void *ctx, unsigned char const *key, unsigned int key_len)
+#endif
+{
+  test_case_t *c = ctx;
+  size_t i;
+
+  c->current_label = NULL;
+  for (i = 0; i < c->expected_labels_num; i++)
+  {
+    label_t *l = c->expected_labels + i;
+    if ((strlen (l->key) == key_len)
+        && (strncmp (l->key, (char const *) key, key_len) == 0))
+    {
+      c->current_label = l;
+      break;
+    }
+  }
+
+  return 1; /* continue */
+}
+
+static int expect_label (char const *name, char const *got, char const *want)
+{
+  _Bool ok = (strcmp (got, want) == 0);
+  char msg[1024];
+
+  if (ok)
+    snprintf (msg, sizeof (msg), "label[\"%s\"] = \"%s\"", name, got);
+  else
+    snprintf (msg, sizeof (msg), "label[\"%s\"] = \"%s\", want \"%s\"", name, got, want);
+
+  OK1 (ok, msg);
+  return 0;
+}
+
+#if HAVE_YAJL_V2
+static int test_string (void *ctx, unsigned char const *value, size_t value_len)
+#else
+static int test_string (void *ctx, unsigned char const *value, unsigned int value_len)
+#endif
+{
+  test_case_t *c = ctx;
+
+  if (c->current_label != NULL)
+  {
+    label_t *l = c->current_label;
+    char *got;
+    int status;
+
+    got = malloc (value_len + 1);
+    memmove (got, value, value_len);
+    got[value_len] = 0;
+
+    status = expect_label (l->key, got, l->value);
+
+    free (got);
+
+    if (status != 0)
+      return 0; /* abort */
+  }
+
+  return 1; /* continue */
+}
+
+static int expect_json_labels (char *json, label_t *labels, size_t labels_num)
+{
+  yajl_callbacks funcs = {
+    .yajl_string = test_string,
+    .yajl_map_key = test_map_key,
+  };
+
+  test_case_t c = { labels, labels_num, NULL };
+
+  yajl_handle hndl;
+#if HAVE_YAJL_V2
+  CHECK_NOT_NULL (hndl = yajl_alloc (&funcs, /* alloc = */ NULL, &c));
+#else
+  CHECK_NOT_NULL (hndl = yajl_alloc (&funcs, /* config = */ NULL, /* alloc = */ NULL, &c));
+#endif
+  OK (yajl_parse (hndl, (unsigned char *) json, strlen (json)) == yajl_status_ok);
+
+  yajl_free (hndl);
+  return 0;
+}
+
+DEF_TEST(notification)
+{
+  label_t labels[] = {
+    {"summary", "this is a message"},
+    {"alertname", "collectd_unit_test"},
+    {"instance", "example.com"},
+    {"service", "collectd"},
+    {"unit", "case"},
+  };
+
+  /* 1448284606.125 ^= 1555083754651779072 */
+  notification_t n = { NOTIF_WARNING, 1555083754651779072ULL, "this is a message",
+    "example.com", "unit", "", "test", "case", NULL };
+
+  char got[1024];
+  CHECK_ZERO (format_json_notification (got, sizeof (got), &n));
+  // printf ("got = \"%s\";\n", got);
+
+  return expect_json_labels (got, labels, STATIC_ARRAY_SIZE (labels));
+}
+
+int main (void)
+{
+  RUN_TEST(notification);
+
+  END_TEST;
+}
diff --git a/src/utils_format_kairosdb.c b/src/utils_format_kairosdb.c
new file mode 100644 (file)
index 0000000..41055c7
--- /dev/null
@@ -0,0 +1,378 @@
+/**
+ * collectd - src/utils_format_kairosdb.c
+ * Copyright (C) 2016       Aurelien beorn Rougemont
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Aurelien beorn Rougemont <beorn at gandi dot net>
+ **/
+
+
+#include "collectd.h"
+
+#include "plugin.h"
+#include "common.h"
+
+#include "utils_cache.h"
+#include "utils_format_kairosdb.h"
+
+
+/* This is the KAIROSDB format for write_http output
+ *
+ * Target format
+ * [
+ *   {
+ *     "name":"collectd.vmem"
+ *     "datapoints":
+ *       [
+ *         [1453897164060, 97.000000]
+ *       ],
+ *      "tags":
+ *        {
+ *          "host": "fqdn.domain.tld",
+ *          "plugin_instance": "vmpage_number",
+ *          "type": "kernel_stack",
+ *          "ds": "value"
+ *          ""
+ *        }
+ *   }
+ * ]
+ */
+
+static int kairosdb_escape_string (char *buffer, size_t buffer_size, /* {{{ */
+    const char *string)
+{
+  size_t dst_pos;
+
+  if ((buffer == NULL) || (string == NULL))
+    return (-EINVAL);
+
+  if (buffer_size < 3)
+    return (-ENOMEM);
+
+  dst_pos = 0;
+
+#define BUFFER_ADD(c) do { \
+  if (dst_pos >= (buffer_size - 1)) { \
+    buffer[buffer_size - 1] = 0; \
+    return (-ENOMEM); \
+  } \
+  buffer[dst_pos] = (c); \
+  dst_pos++; \
+} while (0)
+
+  /* Escape special characters */
+  /* authorize -_. and alpha num but also escapes " */
+  BUFFER_ADD ('"');
+  for (size_t src_pos = 0; string[src_pos] != 0; src_pos++)
+  {
+    if (isalnum(string[src_pos]) ||
+      0x2d == string[src_pos] ||
+      0x2e == string[src_pos] ||
+      0x5f == string[src_pos])
+        BUFFER_ADD (tolower(string[src_pos]));
+  } /* for */
+  BUFFER_ADD ('"');
+  buffer[dst_pos] = 0;
+
+#undef BUFFER_ADD
+
+  return (0);
+} /* }}} int kairosdb_escape_string */
+
+static int values_to_kairosdb (char *buffer, size_t buffer_size, /* {{{ */
+                const data_set_t *ds, const value_list_t *vl, int store_rates,
+                size_t ds_idx)
+{
+  size_t offset = 0;
+  gauge_t *rates = NULL;
+
+  memset (buffer, 0, buffer_size);
+
+#define BUFFER_ADD(...) do { \
+  int status; \
+  status = ssnprintf (buffer + offset, buffer_size - offset, \
+      __VA_ARGS__); \
+  if (status < 1) \
+  { \
+    sfree(rates); \
+    return (-1); \
+  } \
+  else if (((size_t) status) >= (buffer_size - offset)) \
+  { \
+    sfree(rates); \
+    return (-ENOMEM); \
+  } \
+  else \
+    offset += ((size_t) status); \
+} while (0)
+
+  if (ds->ds[ds_idx].type == DS_TYPE_GAUGE)
+  {
+    if (isfinite (vl->values[ds_idx].gauge))
+    {
+      BUFFER_ADD ("[[");
+      BUFFER_ADD ("%"PRIu64, CDTIME_T_TO_MS (vl->time));
+      BUFFER_ADD (",");
+      BUFFER_ADD (JSON_GAUGE_FORMAT, vl->values[ds_idx].gauge);
+    }
+    else
+    {
+      DEBUG ("utils_format_kairosdb: invalid vl->values[ds_idx].gauge for %s|%s|%s|%s|%s",
+                vl->plugin,
+                vl->plugin_instance,
+                vl->type,
+                vl->type_instance,
+                ds->ds[ds_idx].name);
+      return (-1);
+    }
+  }
+  else if (store_rates)
+  {
+    if (rates == NULL)
+      rates = uc_get_rate (ds, vl);
+    if (rates == NULL)
+    {
+      WARNING ("utils_format_kairosdb: uc_get_rate failed for %s|%s|%s|%s|%s",
+                vl->plugin,
+                vl->plugin_instance,
+                vl->type,
+                vl->type_instance,
+                ds->ds[ds_idx].name);
+
+      return (-1);
+    }
+
+    if (isfinite (rates[ds_idx]))
+    {
+      BUFFER_ADD ("[[");
+      BUFFER_ADD ("%"PRIu64, CDTIME_T_TO_MS (vl->time));
+      BUFFER_ADD (",");
+      BUFFER_ADD (JSON_GAUGE_FORMAT, rates[ds_idx]);
+    }
+    else
+    {
+      WARNING ("utils_format_kairosdb: invalid rates[ds_idx] for %s|%s|%s|%s|%s",
+                vl->plugin,
+                vl->plugin_instance,
+                vl->type,
+                vl->type_instance,
+                ds->ds[ds_idx].name);
+      sfree(rates);
+      return (-1);
+    }
+  }
+  else if (ds->ds[ds_idx].type == DS_TYPE_COUNTER)
+  {
+    BUFFER_ADD ("[[");
+    BUFFER_ADD ("%"PRIu64, CDTIME_T_TO_MS (vl->time));
+    BUFFER_ADD (",");
+    BUFFER_ADD ("%llu", 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));
+    BUFFER_ADD (",");
+    BUFFER_ADD ("%"PRIi64, vl->values[ds_idx].derive);
+  }
+  else if (ds->ds[ds_idx].type == DS_TYPE_ABSOLUTE)
+  {
+    BUFFER_ADD ("[[");
+    BUFFER_ADD ("%"PRIu64, CDTIME_T_TO_MS (vl->time));
+    BUFFER_ADD (",");
+    BUFFER_ADD ("%"PRIu64, vl->values[ds_idx].absolute);
+  }
+  else
+  {
+    ERROR ("format_kairosdb: Unknown data source type: %i",
+        ds->ds[ds_idx].type);
+    sfree (rates);
+    return (-1);
+  }
+  BUFFER_ADD ("]]");
+
+#undef BUFFER_ADD
+
+  DEBUG ("format_kairosdb: values_to_kairosdb: buffer = %s;", buffer);
+  sfree(rates);
+  return (0);
+} /* }}} int values_to_kairosdb */
+
+static int value_list_to_kairosdb (char *buffer, size_t buffer_size, /* {{{ */
+                const data_set_t *ds, const value_list_t *vl, int store_rates)
+{
+  char temp[512];
+  size_t offset = 0;
+  int status;
+
+  memset (buffer, 0, buffer_size);
+
+#define BUFFER_ADD(...) do { \
+  status = ssnprintf (buffer + offset, buffer_size - offset, \
+      __VA_ARGS__); \
+  if (status < 1) \
+    return (-1); \
+  else if (((size_t) status) >= (buffer_size - offset)) \
+    return (-ENOMEM); \
+  else \
+    offset += ((size_t) status); \
+} while (0)
+
+#define BUFFER_ADD_KEYVAL(key, value) do { \
+  status = kairosdb_escape_string (temp, sizeof (temp), (value)); \
+  if (status != 0) \
+    return (status); \
+  BUFFER_ADD (",\"%s\": %s", (key), temp); \
+} while (0)
+
+  for (size_t i = 0; i < ds->ds_num; i++)
+  {
+    /* All value lists have a leading comma. The first one will be replaced with
+     * a square bracket in `format_kairosdb_finalize'. */
+    BUFFER_ADD (",{");
+
+    BUFFER_ADD ("\"name\":\"collectd");
+
+    BUFFER_ADD (".%s", vl->plugin);
+
+    status = values_to_kairosdb (temp, sizeof (temp), ds, vl, store_rates, i);
+    if (status != 0)
+      return (status);
+
+    BUFFER_ADD ("\", \"datapoints\": %s", temp);
+
+    /*
+     * Now adds meta data to metric as tags
+     */
+
+    memset (temp, 0, sizeof(temp));
+
+    BUFFER_ADD (", \"tags\":\{");
+
+    BUFFER_ADD ("\"host\": \"%s\"", vl->host);
+    if (strlen(vl->plugin_instance))
+      BUFFER_ADD_KEYVAL ("plugin_instance", vl->plugin_instance);
+    BUFFER_ADD_KEYVAL ("type", vl->type);
+    if (strlen(vl->type_instance))
+      BUFFER_ADD_KEYVAL ("type_instance", vl->type_instance);
+    if (ds->ds_num != 1)
+      BUFFER_ADD_KEYVAL ("ds", ds->ds[i].name);
+    BUFFER_ADD ("}}");
+  } /* for ds->ds_num */
+
+#undef BUFFER_ADD_KEYVAL
+#undef BUFFER_ADD
+
+  DEBUG ("format_kairosdb: value_list_to_kairosdb: buffer = %s;", buffer);
+
+  return (0);
+} /* }}} int value_list_to_kairosdb */
+
+static int format_kairosdb_value_list_nocheck (char *buffer, /* {{{ */
+    size_t *ret_buffer_fill, size_t *ret_buffer_free,
+    const data_set_t *ds, const value_list_t *vl,
+    int store_rates, size_t temp_size)
+{
+  char temp[temp_size];
+  int status;
+
+  status = value_list_to_kairosdb (temp, sizeof (temp), ds, vl, store_rates);
+  if (status != 0)
+    return (status);
+  temp_size = strlen (temp);
+
+  memcpy (buffer + (*ret_buffer_fill), temp, temp_size + 1);
+  (*ret_buffer_fill) += temp_size;
+  (*ret_buffer_free) -= temp_size;
+
+  return (0);
+} /* }}} int format_kairosdb_value_list_nocheck */
+
+int format_kairosdb_initialize (char *buffer, /* {{{ */
+    size_t *ret_buffer_fill, size_t *ret_buffer_free)
+{
+  size_t buffer_fill;
+  size_t buffer_free;
+
+  if ((buffer == NULL) || (ret_buffer_fill == NULL) || (ret_buffer_free == NULL))
+    return (-EINVAL);
+
+  buffer_fill = *ret_buffer_fill;
+  buffer_free = *ret_buffer_free;
+
+  buffer_free = buffer_fill + buffer_free;
+  buffer_fill = 0;
+
+  if (buffer_free < 3)
+    return (-ENOMEM);
+
+  memset (buffer, 0, buffer_free);
+  *ret_buffer_fill = buffer_fill;
+  *ret_buffer_free = buffer_free;
+
+  return (0);
+} /* }}} int format_kairosdb_initialize */
+
+int format_kairosdb_finalize (char *buffer, /* {{{ */
+    size_t *ret_buffer_fill, size_t *ret_buffer_free)
+{
+  size_t pos;
+
+  if ((buffer == NULL) || (ret_buffer_fill == NULL) || (ret_buffer_free == NULL))
+    return (-EINVAL);
+
+  if (*ret_buffer_free < 2)
+    return (-ENOMEM);
+
+  /* Replace the leading comma added in `value_list_to_kairosdb' with a square
+   * bracket. */
+  if (buffer[0] != ',')
+    return (-EINVAL);
+  buffer[0] = '[';
+
+  pos = *ret_buffer_fill;
+  buffer[pos] = ']';
+  buffer[pos+1] = 0;
+
+  (*ret_buffer_fill)++;
+  (*ret_buffer_free)--;
+
+  return (0);
+} /* }}} int format_kairosdb_finalize */
+
+int format_kairosdb_value_list (char *buffer, /* {{{ */
+    size_t *ret_buffer_fill, size_t *ret_buffer_free,
+    const data_set_t *ds, const value_list_t *vl, int store_rates)
+{
+  if ((buffer == NULL)
+      || (ret_buffer_fill == NULL) || (ret_buffer_free == NULL)
+      || (ds == NULL) || (vl == NULL))
+    return (-EINVAL);
+
+  if (*ret_buffer_free < 3)
+    return (-ENOMEM);
+
+  return (format_kairosdb_value_list_nocheck (buffer,
+        ret_buffer_fill, ret_buffer_free, ds, vl,
+        store_rates, (*ret_buffer_free) - 2));
+} /* }}} int format_kairosdb_value_list */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_format_kairosdb.h b/src/utils_format_kairosdb.h
new file mode 100644 (file)
index 0000000..764b0b1
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * collectd - src/utils_format_kairosdb.h
+ * Copyright (C) 2016       Aurelien Rougemont
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Aurelien beorn Rougemont <beorn at gandi dot net>
+ **/
+
+#ifndef UTILS_FORMAT_KAIROSDB_H
+#define UTILS_FORMAT_KAIROSDB_H 1
+
+#include "collectd.h"
+
+#include "plugin.h"
+
+#ifndef JSON_GAUGE_FORMAT
+# define JSON_GAUGE_FORMAT GAUGE_FORMAT
+#endif
+
+int format_kairosdb_initialize (char *buffer,
+    size_t *ret_buffer_fill, size_t *ret_buffer_free);
+int format_kairosdb_value_list (char *buffer,
+    size_t *ret_buffer_fill, size_t *ret_buffer_free,
+    const data_set_t *ds, const value_list_t *vl, int store_rates);
+int format_kairosdb_finalize (char *buffer,
+    size_t *ret_buffer_fill, size_t *ret_buffer_free);
+
+#endif /* UTILS_FORMAT_KAIROSDB_H */
index ca7d5fa..c67752a 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "utils_latency.h"
 #include "common.h"
@@ -96,9 +97,8 @@ static void change_bin_width (latency_counter_t *lc, cdtime_t latency) /* {{{ */
   if (lc->num > 0) // if the histogram has data then iterate else skip
   {
       double width_change_ratio = ((double) old_bin_width) / ((double) new_bin_width);
-      size_t i;
 
-      for (i = 0; i < HISTOGRAM_NUM_BINS; i++)
+      for (size_t i = 0; i < HISTOGRAM_NUM_BINS; i++)
       {
          size_t new_bin = (size_t) (((double) i) * width_change_ratio);
          if (i == new_bin)
@@ -121,13 +121,12 @@ latency_counter_t *latency_counter_create (void) /* {{{ */
 {
   latency_counter_t *lc;
 
-  lc = malloc (sizeof (*lc));
+  lc = calloc (1, sizeof (*lc));
   if (lc == NULL)
     return (NULL);
-  memset (lc, 0, sizeof (*lc));
 
-  latency_counter_reset (lc);
   lc->bin_width = HISTOGRAM_DEFAULT_BIN_WIDTH;
+  latency_counter_reset (lc);
   return (lc);
 } /* }}} latency_counter_t *latency_counter_create */
 
@@ -176,6 +175,28 @@ void latency_counter_reset (latency_counter_t *lc) /* {{{ */
     return;
 
   cdtime_t bin_width = lc->bin_width;
+  cdtime_t max_bin = (lc->max - 1) / lc->bin_width;
+
+/*
+  If max latency is REDUCE_THRESHOLD times less than histogram's range,
+  then cut it in half. REDUCE_THRESHOLD must be >= 2.
+  Value of 4 is selected to reduce frequent changes of bin width.
+*/
+#define REDUCE_THRESHOLD 4
+  if ((lc->num > 0) && (lc->bin_width >= HISTOGRAM_DEFAULT_BIN_WIDTH * 2)
+     && (max_bin < HISTOGRAM_NUM_BINS / REDUCE_THRESHOLD))
+  {
+    /* new bin width will be the previous power of 2 */
+    bin_width = bin_width / 2;
+
+    DEBUG("utils_latency: latency_counter_reset: max_latency = %.3f; "
+          "max_bin = %"PRIu64"; old_bin_width = %.3f; new_bin_width = %.3f;",
+        CDTIME_T_TO_DOUBLE (lc->max),
+        max_bin,
+        CDTIME_T_TO_DOUBLE (lc->bin_width),
+        CDTIME_T_TO_DOUBLE (bin_width));
+  }
+
   memset (lc, 0, sizeof (*lc));
 
   /* preserve bin width */
index 2cfa71b..cb56b08 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "utils_time.h"
 
 struct latency_counter_s;
diff --git a/src/utils_latency_test.c b/src/utils_latency_test.c
new file mode 100644 (file)
index 0000000..9c3b0ad
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+ * collectd - src/utils_latency_test.c
+ * Copyright (C) 2015       Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#define DBL_PRECISION 1e-9
+
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "collectd.h"
+
+#include "testing.h"
+#include "utils_time.h"
+#include "utils_latency.h"
+
+DEF_TEST(simple)
+{
+  struct {
+    double val;
+    double min;
+    double max;
+    double sum;
+    double avg;
+  } cases[] = {
+  /* val  min  max  sum   avg */
+    {0.5, 0.5, 0.5, 0.5,  0.5},
+    {0.3, 0.3, 0.5, 0.8,  0.4},
+    {0.7, 0.3, 0.7, 1.5,  0.5},
+    {2.5, 0.3, 2.5, 4.0,  1.0},
+    { 99, 0.3,  99, 103, 20.6},
+    /* { -1, 0.3,  99, 103, 20.6}, see issue #1139 */
+  };
+  latency_counter_t *l;
+
+  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, cases[i].val, DOUBLE_TO_CDTIME_T (cases[i].val));
+    latency_counter_add (l, DOUBLE_TO_CDTIME_T (cases[i].val));
+
+    EXPECT_EQ_DOUBLE (cases[i].min, CDTIME_T_TO_DOUBLE (latency_counter_get_min (l)));
+    EXPECT_EQ_DOUBLE (cases[i].max, CDTIME_T_TO_DOUBLE (latency_counter_get_max (l)));
+    EXPECT_EQ_DOUBLE (cases[i].sum, CDTIME_T_TO_DOUBLE (latency_counter_get_sum (l)));
+    EXPECT_EQ_DOUBLE (cases[i].avg, CDTIME_T_TO_DOUBLE (latency_counter_get_average (l)));
+  }
+
+  latency_counter_destroy (l);
+  return 0;
+}
+
+DEF_TEST(percentile)
+{
+  latency_counter_t *l;
+
+  CHECK_NOT_NULL (l = latency_counter_create ());
+
+  for (size_t i = 0; i < 100; i++) {
+    latency_counter_add (l, TIME_T_TO_CDTIME_T (((time_t) i) + 1));
+  }
+
+  EXPECT_EQ_DOUBLE (  1.0, CDTIME_T_TO_DOUBLE (latency_counter_get_min (l)));
+  EXPECT_EQ_DOUBLE (100.0, CDTIME_T_TO_DOUBLE (latency_counter_get_max (l)));
+  EXPECT_EQ_DOUBLE (100.0 * 101.0 / 2.0, CDTIME_T_TO_DOUBLE (latency_counter_get_sum (l)));
+  EXPECT_EQ_DOUBLE ( 50.5, CDTIME_T_TO_DOUBLE (latency_counter_get_average (l)));
+
+  EXPECT_EQ_DOUBLE (50.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 50.0)));
+  EXPECT_EQ_DOUBLE (80.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 80.0)));
+  EXPECT_EQ_DOUBLE (95.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 95.0)));
+  EXPECT_EQ_DOUBLE (99.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 99.0)));
+
+  CHECK_ZERO (latency_counter_get_percentile (l, -1.0));
+  CHECK_ZERO (latency_counter_get_percentile (l, 101.0));
+
+  latency_counter_destroy (l);
+  return 0;
+}
+
+int main (void)
+{
+  RUN_TEST(simple);
+  RUN_TEST(percentile);
+
+  END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
index da53b98..b8dabb1 100644 (file)
@@ -32,6 +32,7 @@
 #endif
 
 #include "collectd.h"
+
 #include "utils_mount.h"
 
 #include "common.h" /* sstrncpy() et alii */
@@ -215,7 +216,6 @@ uuidcache_init(void)
        FILE *procpt;
        char uuid[16], *label = NULL;
        char device[110];
-       int firstPass;
        int handleOnFirst;
 
        if(uuidCache) {
@@ -227,7 +227,7 @@ uuidcache_init(void)
                return;
        }
 
-       for(firstPass = 1; firstPass >= 0; firstPass--) {
+       for(int firstPass = 1; firstPass >= 0; firstPass--) {
                fseek(procpt, 0, SEEK_SET);
                while(fgets(line, sizeof(line), procpt)) {
                        if(sscanf(line, " %d %d %d %[^\n ]",
@@ -317,14 +317,13 @@ static char *
 get_spec_by_uuid(const char *s)
 {
        char uuid[16];
-       int i;
 
        if(strlen(s) != 36
        || s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-') {
                goto bad_uuid;
        }
 
-       for(i=0; i<16; i++) {
+       for(int i=0; i<16; i++) {
                if(*s == '-') {
                        s++;
                }
@@ -381,7 +380,6 @@ static char *get_device_name(const char *optstr)
 static cu_mount_t *cu_mount_listmntent (void)
 {
        cu_mount_t *last = *list;
-       struct tabmntent *p;
        struct mntent *mnt;
 
        struct tabmntent *mntlist;
@@ -393,7 +391,7 @@ static cu_mount_t *cu_mount_listmntent (void)
 #endif /* COLLECT_DEBUG */
        }
 
-       for(p = mntlist; p; p = p->next) {
+       for(struct tabmntent *p = mntlist; p; p = p->next) {
                char *loop = NULL, *device = NULL;
 
                mnt = p->ment;
@@ -450,7 +448,6 @@ static cu_mount_t *cu_mount_getfsstat (void)
        STRUCT_STATFS *buf;
 
        int num;
-       int i;
 
        cu_mount_t *first = NULL;
        cu_mount_t *last  = NULL;
@@ -467,10 +464,8 @@ static cu_mount_t *cu_mount_getfsstat (void)
                return (NULL);
        }
 
-       if ((buf = (STRUCT_STATFS *) malloc (bufsize * sizeof (STRUCT_STATFS)))
-                       == NULL)
+       if ((buf = calloc (bufsize, sizeof (*buf))) == NULL)
                return (NULL);
-       memset (buf, '\0', bufsize * sizeof (STRUCT_STATFS));
 
        /* The bufsize needs to be passed in bytes. Really. This is not in the
         * manpage.. -octo */
@@ -485,12 +480,11 @@ static cu_mount_t *cu_mount_getfsstat (void)
                return (NULL);
        }
 
-       for (i = 0; i < num; i++)
+       for (int i = 0; i < num; i++)
        {
-               if ((new = malloc (sizeof (cu_mount_t))) == NULL)
+               if ((new = calloc (1, sizeof (*new))) == NULL)
                        break;
-               memset (new, '\0', sizeof (cu_mount_t));
-               
+
                /* Copy values from `struct mnttab' */
                new->dir         = sstrdup (buf[i].f_mntonname);
                new->spec_device = sstrdup (buf[i].f_mntfromname);
@@ -541,10 +535,9 @@ static cu_mount_t *cu_mount_gen_getmntent (void)
 
        while (getmntent (fp, &mt) == 0)
        {
-               if ((new = malloc (sizeof (cu_mount_t))) == NULL)
+               if ((new = calloc (1, sizeof (*new))) == NULL)
                        break;
-               memset (new, '\0', sizeof (cu_mount_t));
-               
+
                /* Copy values from `struct mnttab' */
                new->dir         = sstrdup (mt.mnt_mountp);
                new->spec_device = sstrdup (mt.mnt_special);
@@ -599,9 +592,8 @@ static cu_mount_t *cu_mount_getmntent (void)
 
        while (getmntent_r (fp, &me, mntbuf, sizeof (mntbuf) ))
        {
-               if ((new = malloc (sizeof (cu_mount_t))) == NULL)
+               if ((new = calloc (1, sizeof (*new))) == NULL)
                        break;
-               memset (new, '\0', sizeof (cu_mount_t));
 
                /* Copy values from `struct mntent *' */
                new->dir         = sstrdup (me.mnt_dir);
@@ -656,10 +648,9 @@ static cu_mount_t *cu_mount_getmntent (void)
 
        while ((me = getmntent (fp)) != NULL)
        {
-               if ((new = malloc (sizeof (cu_mount_t))) == NULL)
+               if ((new = calloc (1, sizeof (*new))) == NULL)
                        break;
-               memset (new, '\0', sizeof (cu_mount_t));
-               
+
                /* Copy values from `struct mntent *' */
                new->dir         = sstrdup (me->mnt_dir);
                new->spec_device = sstrdup (me->mnt_fsname);
@@ -746,10 +737,9 @@ cu_mount_t *cu_mount_getlist(cu_mount_t **list)
 
 void cu_mount_freelist (cu_mount_t *list)
 {
-       cu_mount_t *this;
        cu_mount_t *next;
 
-       for (this = list; this != NULL; this = next)
+       for (cu_mount_t *this = list; this != NULL; this = next)
        {
                next = this->next;
 
@@ -763,7 +753,7 @@ void cu_mount_freelist (cu_mount_t *list)
 } /* void cu_mount_freelist(cu_mount_t *list) */
 
 char *
-cu_mount_checkoption(char *line, char *keyword, int full)
+cu_mount_checkoption(char *line, const char *keyword, int full)
 {
        char *line2, *l2, *p1, *p2;
        int l;
@@ -804,7 +794,7 @@ cu_mount_checkoption(char *line, char *keyword, int full)
 } /* char *cu_mount_checkoption(char *line, char *keyword, int full) */
 
 char *
-cu_mount_getoptionvalue(char *line, char *keyword)
+cu_mount_getoptionvalue(char *line, const char *keyword)
 {
        char *r;
 
@@ -820,13 +810,13 @@ cu_mount_getoptionvalue(char *line, char *keyword)
                        if((p-r) == 1) {
                                return NULL;
                        }
-                       m = (char *)smalloc(p-r+1);
+                       m = smalloc(p-r+1);
                        sstrncpy(m, r, p-r+1);
                        return m;
                }
        }
        return r;
-} /* char *cu_mount_getoptionvalue(char *line, char *keyword) */
+} /* char *cu_mount_getoptionvalue(char *line, const char *keyword) */
 
 int
 cu_mount_type(const char *type)
index 7518188..0a5c980 100644 (file)
@@ -113,7 +113,7 @@ void cu_mount_freelist(cu_mount_t *list);
        allocated by *list and *list itself as well.
 */
 
-char *cu_mount_checkoption(char *line, char *keyword, int full);
+char *cu_mount_checkoption(char *line, const char *keyword, int full);
 /*
   DESCRIPTION
        The cu_mount_checkoption() function is a replacement of
@@ -153,7 +153,7 @@ char *cu_mount_checkoption(char *line, char *keyword, int full);
        maybe you might want to try cu_mount_getoptionvalue()...
 */
 
-char *cu_mount_getoptionvalue(char *line, char *keyword);
+char *cu_mount_getoptionvalue(char *line, const char *keyword);
 /*
   DESCRIPTION
        The cu_mount_getoptionvalue() function can be used to grab
index a16b262..c084deb 100644 (file)
  *   Florian octo Forster <octo at collectd.org>
  */
 
-#include "testing.h"
 #include "collectd.h"
+
+#include "common.h"
+#include "testing.h"
 #include "utils_mount.h"
 
 #if HAVE_LIBKSTAT
@@ -80,16 +82,25 @@ DEF_TEST(cu_mount_getoptionvalue)
 {
   char line_opts[] = "foo=one,bar=two,qux=three";
   char line_bool[] = "one,two,three";
-
-  STREQ ("one", cu_mount_getoptionvalue (line_opts, "foo="));
-  STREQ ("two", cu_mount_getoptionvalue (line_opts, "bar="));
-  STREQ ("three", cu_mount_getoptionvalue (line_opts, "qux="));
-  OK (NULL == cu_mount_getoptionvalue (line_opts, "unknown="));
-
-  STREQ ("", cu_mount_getoptionvalue (line_bool, "one"));
-  STREQ ("", cu_mount_getoptionvalue (line_bool, "two"));
-  STREQ ("", cu_mount_getoptionvalue (line_bool, "three"));
-  OK (NULL == cu_mount_getoptionvalue (line_bool, "four"));
+  char *v;
+
+  EXPECT_EQ_STR ("one", v = cu_mount_getoptionvalue (line_opts, "foo="));
+  sfree (v);
+  EXPECT_EQ_STR ("two", v = cu_mount_getoptionvalue (line_opts, "bar="));
+  sfree (v);
+  EXPECT_EQ_STR ("three", v = cu_mount_getoptionvalue (line_opts, "qux="));
+  sfree (v);
+  OK (NULL == (v = cu_mount_getoptionvalue (line_opts, "unknown=")));
+  sfree (v);
+
+  EXPECT_EQ_STR ("", v = cu_mount_getoptionvalue (line_bool, "one"));
+  sfree (v);
+  EXPECT_EQ_STR ("", v = cu_mount_getoptionvalue (line_bool, "two"));
+  sfree (v);
+  EXPECT_EQ_STR ("", v = cu_mount_getoptionvalue (line_bool, "three"));
+  sfree (v);
+  OK (NULL == (v = cu_mount_getoptionvalue (line_bool, "four")));
+  sfree (v);
 
   return (0);
 }
index 7f06f29..3652a66 100644 (file)
@@ -25,8 +25,7 @@
  **/
 
 #include "collectd.h"
-#include "common.h"
-#include "plugin.h"
+
 #include "utils_parse_option.h"
 
 int parse_string (char **ret_buffer, char **ret_string)
@@ -92,7 +91,7 @@ int parse_string (char **ret_buffer, char **ret_string)
       buffer++;
     }
   }
-  
+
   /* Eat up trailing spaces */
   while (isspace ((int) *buffer))
     buffer++;
index 5add323..884de8f 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "utils_rrdcreate.h"
 
@@ -62,7 +63,7 @@ static int rra_timespans[] =
 };
 static int rra_timespans_num = STATIC_ARRAY_SIZE (rra_timespans);
 
-static char *rra_types[] =
+static const char *const rra_types[] =
 {
   "AVERAGE",
   "MIN",
@@ -70,7 +71,7 @@ static char *rra_types[] =
 };
 static int rra_types_num = STATIC_ARRAY_SIZE (rra_types);
 
-#if !defined(HAVE_THREADSAFE_LIBRRD) || !HAVE_THREADSAFE_LIBRRD
+#if !defined(HAVE_THREADSAFE_LIBRRD)
 static pthread_mutex_t librrd_lock = PTHREAD_MUTEX_INITIALIZER;
 #endif
 
@@ -82,9 +83,7 @@ static pthread_mutex_t async_creation_lock = PTHREAD_MUTEX_INITIALIZER;
  */
 static void rra_free (int rra_num, char **rra_def) /* {{{ */
 {
-  int i;
-
-  for (i = 0; i < rra_num; i++)
+  for (int i = 0; i < rra_num; i++)
   {
     sfree (rra_def[i]);
   }
@@ -99,8 +98,7 @@ static void srrd_create_args_destroy (srrd_create_args_t *args)
   sfree (args->filename);
   if (args->argv != NULL)
   {
-    int i;
-    for (i = 0; i < args->argc; i++)
+    for (int i = 0; i < args->argc; i++)
       sfree (args->argv[i]);
     sfree (args->argv);
   }
@@ -113,13 +111,12 @@ static srrd_create_args_t *srrd_create_args_create (const char *filename,
 {
   srrd_create_args_t *args;
 
-  args = malloc (sizeof (*args));
+  args = calloc (1, sizeof (*args));
   if (args == NULL)
   {
-    ERROR ("srrd_create_args_create: malloc failed.");
+    ERROR ("srrd_create_args_create: calloc failed.");
     return (NULL);
   }
-  memset (args, 0, sizeof (*args));
   args->filename = NULL;
   args->pdp_step = pdp_step;
   args->last_up = last_up;
@@ -173,7 +170,6 @@ static int rra_get (char ***ret, const value_list_t *vl, /* {{{ */
 
   int cdp_num;
   int cdp_len;
-  int i, j;
 
   /* The stepsize we use here: If it is user-set, use it. If not, use the
    * interval of the value-list. */
@@ -216,13 +212,12 @@ static int rra_get (char ***ret, const value_list_t *vl, /* {{{ */
   rra_max = rts_num * rra_types_num;
   assert (rra_max > 0);
 
-  if ((rra_def = malloc ((rra_max + 1) * sizeof (*rra_def))) == NULL)
+  if ((rra_def = calloc (rra_max + 1, sizeof (*rra_def))) == NULL)
     return (-1);
-  memset (rra_def, 0, (rra_max + 1) * sizeof (*rra_def));
   rra_num = 0;
 
   cdp_len = 0;
-  for (i = 0; i < rts_num; i++)
+  for (int i = 0; i < rts_num; i++)
   {
     int span = rts[i];
 
@@ -238,7 +233,7 @@ static int rra_get (char ***ret, const value_list_t *vl, /* {{{ */
     cdp_num = (int) ceil (((double) span)
         / ((double) (cdp_len * ss)));
 
-    for (j = 0; j < rra_types_num; j++)
+    for (int j = 0; j < rra_types_num; j++)
     {
       char buffer[128];
       int status;
@@ -271,9 +266,7 @@ static int rra_get (char ***ret, const value_list_t *vl, /* {{{ */
 
 static void ds_free (int ds_num, char **ds_def) /* {{{ */
 {
-  int i;
-
-  for (i = 0; i < ds_num; i++)
+  for (int i = 0; i < ds_num; i++)
     if (ds_def[i] != NULL)
       free (ds_def[i]);
   free (ds_def);
@@ -284,7 +277,7 @@ static int ds_get (char ***ret, /* {{{ */
     const rrdcreate_config_t *cfg)
 {
   char **ds_def;
-  int ds_num;
+  size_t ds_num;
 
   char min[32];
   char max[32];
@@ -292,20 +285,19 @@ static int ds_get (char ***ret, /* {{{ */
 
   assert (ds->ds_num > 0);
 
-  ds_def = malloc (ds->ds_num * sizeof (*ds_def));
+  ds_def = calloc (ds->ds_num, sizeof (*ds_def));
   if (ds_def == NULL)
   {
     char errbuf[1024];
-    ERROR ("rrdtool plugin: malloc failed: %s",
+    ERROR ("rrdtool plugin: calloc failed: %s",
         sstrerror (errno, errbuf, sizeof (errbuf)));
     return (-1);
   }
-  memset (ds_def, 0, ds->ds_num * sizeof (*ds_def));
 
   for (ds_num = 0; ds_num < ds->ds_num; ds_num++)
   {
     data_source_t *d = ds->ds + ds_num;
-    char *type;
+    const char *type;
     int status;
 
     ds_def[ds_num] = NULL;
@@ -358,7 +350,7 @@ static int ds_get (char ***ret, /* {{{ */
     return (-1);
   }
 
-  if (ds_num <= 0)
+  if (ds_num == 0)
   {
     sfree (ds_def);
     return (0);
@@ -421,7 +413,7 @@ static int srrd_create (const char *filename, /* {{{ */
   char last_up_str[16];
 
   new_argc = 6 + argc;
-  new_argv = (char **) malloc ((new_argc + 1) * sizeof (char *));
+  new_argv = malloc ((new_argc + 1) * sizeof (*new_argv));
   if (new_argv == NULL)
   {
     ERROR ("rrdtool plugin: malloc failed.");
@@ -689,7 +681,7 @@ int cu_rrd_create_file (const char *filename, /* {{{ */
 
   argc = ds_num + rra_num;
 
-  if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
+  if ((argv = malloc (sizeof (*argv) * (argc + 1))) == NULL)
   {
     char errbuf[1024];
     ERROR ("cu_rrd_create_file failed: %s",
index f85910e..2ca9ddf 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "collectd.h"
 
+
 #include <pthread.h>
 #include <regex.h>
 
@@ -157,7 +158,7 @@ static int lu_copy_ident_to_match_part (part_match_t *match_part, /* {{{ */
   assert (sizeof (match_part->str) > len);
   /* strip trailing slash */
   match_part->str[len - 2] = 0;
-  
+
   status = regcomp (&match_part->regex, match_part->str,
       /* flags = */ REG_EXTENDED);
   if (status != 0)
@@ -169,7 +170,7 @@ static int lu_copy_ident_to_match_part (part_match_t *match_part, /* {{{ */
     return (EINVAL);
   }
   match_part->is_regex = 1;
-  
+
   return (0);
 } /* }}} int lu_copy_ident_to_match_part */
 
@@ -204,13 +205,12 @@ static void *lu_create_user_obj (lookup_t *obj, /* {{{ */
 {
   user_obj_t *user_obj;
 
-  user_obj = malloc (sizeof (*user_obj));
+  user_obj = calloc (1, sizeof (*user_obj));
   if (user_obj == NULL)
   {
-    ERROR ("utils_vl_lookup: malloc failed.");
+    ERROR ("utils_vl_lookup: calloc failed.");
     return (NULL);
   }
-  memset (user_obj, 0, sizeof (*user_obj));
   user_obj->next = NULL;
 
   user_obj->user_obj = obj->cb_user_class (ds, vl, user_class->user_class);
@@ -337,7 +337,7 @@ static int lu_handle_user_class_list (lookup_t *obj, /* {{{ */
 {
   user_class_list_t *ptr;
   int retval = 0;
-  
+
   for (ptr = user_class_list; ptr != NULL; ptr = ptr->next)
   {
     int status;
@@ -373,17 +373,16 @@ static by_type_entry_t *lu_search_by_type (lookup_t *obj, /* {{{ */
     return (NULL);
   }
 
-  by_type = malloc (sizeof (*by_type));
+  by_type = calloc (1, sizeof (*by_type));
   if (by_type == NULL)
   {
-    ERROR ("utils_vl_lookup: malloc failed.");
+    ERROR ("utils_vl_lookup: calloc failed.");
     sfree (type_copy);
     return (NULL);
   }
-  memset (by_type, 0, sizeof (*by_type));
   by_type->wildcard_plugin_list = NULL;
-  
-  by_type->by_plugin_tree = c_avl_create ((void *) strcmp);
+
+  by_type->by_plugin_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
   if (by_type->by_plugin_tree == NULL)
   {
     ERROR ("utils_vl_lookup: c_avl_create failed.");
@@ -403,7 +402,7 @@ static by_type_entry_t *lu_search_by_type (lookup_t *obj, /* {{{ */
     sfree (type_copy);
     return (NULL);
   }
-  
+
   return (by_type);
 } /* }}} by_type_entry_t *lu_search_by_type */
 
@@ -497,6 +496,21 @@ static void lu_destroy_user_class_list (lookup_t *obj, /* {{{ */
       obj->cb_free_class (user_class_list->entry.user_class);
     user_class_list->entry.user_class = NULL;
 
+#define CLEAR_FIELD(field) do { \
+    if (user_class_list->entry.match.field.is_regex) { \
+      regfree (&user_class_list->entry.match.field.regex); \
+      user_class_list->entry.match.field.is_regex = 0; \
+    } \
+} while (0)
+
+    CLEAR_FIELD (host);
+    CLEAR_FIELD (plugin);
+    CLEAR_FIELD (plugin_instance);
+    CLEAR_FIELD (type);
+    CLEAR_FIELD (type_instance);
+
+#undef CLEAR_FIELD
+
     lu_destroy_user_obj (obj, user_class_list->entry.user_obj_list);
     user_class_list->entry.user_obj_list = NULL;
     pthread_mutex_destroy (&user_class_list->entry.lock);
@@ -509,7 +523,7 @@ static void lu_destroy_user_class_list (lookup_t *obj, /* {{{ */
 static void lu_destroy_by_type (lookup_t *obj, /* {{{ */
     by_type_entry_t *by_type)
 {
-  
+
   while (42)
   {
     char *plugin = NULL;
@@ -544,15 +558,14 @@ lookup_t *lookup_create (lookup_class_callback_t cb_user_class, /* {{{ */
     lookup_free_class_callback_t cb_free_class,
     lookup_free_obj_callback_t cb_free_obj)
 {
-  lookup_t *obj = malloc (sizeof (*obj));
+  lookup_t *obj = calloc (1, sizeof (*obj));
   if (obj == NULL)
   {
-    ERROR ("utils_vl_lookup: malloc failed.");
+    ERROR ("utils_vl_lookup: calloc failed.");
     return (NULL);
   }
-  memset (obj, 0, sizeof (*obj));
 
-  obj->by_type_tree = c_avl_create ((void *) strcmp);
+  obj->by_type_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
   if (obj->by_type_tree == NULL)
   {
     ERROR ("utils_vl_lookup: c_avl_create failed.");
@@ -605,13 +618,12 @@ int lookup_add (lookup_t *obj, /* {{{ */
   if (by_type == NULL)
     return (-1);
 
-  user_class_obj = malloc (sizeof (*user_class_obj));
+  user_class_obj = calloc (1, sizeof (*user_class_obj));
   if (user_class_obj == NULL)
   {
-    ERROR ("utils_vl_lookup: malloc failed.");
+    ERROR ("utils_vl_lookup: calloc failed.");
     return (ENOMEM);
   }
-  memset (user_class_obj, 0, sizeof (*user_class_obj));
   pthread_mutex_init (&user_class_obj->entry.lock, /* attr = */ NULL);
   user_class_obj->entry.user_class = user_class;
   lu_copy_ident_to_match (&user_class_obj->entry.match, ident, group_by);
@@ -655,6 +667,6 @@ int lookup_search (lookup_t *obj, /* {{{ */
       return (status);
     retval += status;
   }
-    
+
   return (retval);
 } /* }}} lookup_search */
index 6a2676a..4466063 100644 (file)
@@ -24,8 +24,9 @@
  *   Florian Forster <octo at collectd.org>
  **/
 
-#include "testing.h"
 #include "collectd.h"
+
+#include "testing.h"
 #include "utils_vl_lookup.h"
 
 static _Bool expect_new_obj = 0;
@@ -65,10 +66,10 @@ static void *lookup_class_callback (data_set_t const *ds,
   identifier_t *class = user_class;
   identifier_t *obj;
 
-  OK(expect_new_obj);
+  assert (expect_new_obj);
 
   memcpy (&last_class_ident, class, sizeof (last_class_ident));
-  
+
   obj = malloc (sizeof (*obj));
   strncpy (obj->host, vl->host, sizeof (obj->host));
   strncpy (obj->plugin, vl->plugin, sizeof (obj->plugin));
@@ -81,7 +82,7 @@ static void *lookup_class_callback (data_set_t const *ds,
   return ((void *) obj);
 }
 
-static void checked_lookup_add (lookup_t *obj, /* {{{ */
+static int checked_lookup_add (lookup_t *obj, /* {{{ */
     char const *host,
     char const *plugin, char const *plugin_instance,
     char const *type, char const *type_instance,
@@ -90,7 +91,6 @@ static void checked_lookup_add (lookup_t *obj, /* {{{ */
   identifier_t ident;
   void *user_class;
 
-  memset (&ident, 0, sizeof (ident));
   strncpy (ident.host, host, sizeof (ident.host));
   strncpy (ident.plugin, plugin, sizeof (ident.plugin));
   strncpy (ident.plugin_instance, plugin_instance, sizeof (ident.plugin_instance));
@@ -101,7 +101,8 @@ static void checked_lookup_add (lookup_t *obj, /* {{{ */
   memmove (user_class, &ident, sizeof (ident));
 
   OK(lookup_add (obj, &ident, group_by, user_class) == 0);
-} /* }}} void test_add */
+  return 0;
+} /* }}} int checked_lookup_add */
 
 static int checked_lookup_search (lookup_t *obj,
     char const *host,
@@ -129,20 +130,11 @@ static int checked_lookup_search (lookup_t *obj,
   return (status);
 }
 
-static lookup_t *checked_lookup_create (void)
-{
-  lookup_t *obj = lookup_create (
-      lookup_class_callback,
-      lookup_obj_callback,
-      (void *) free,
-      (void *) free);
-  OK(obj != NULL);
-  return (obj);
-}
-
 DEF_TEST(group_by_specific_host)
 {
-  lookup_t *obj = checked_lookup_create ();
+  lookup_t *obj;
+  CHECK_NOT_NULL (obj = lookup_create (
+        lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
 
   checked_lookup_add (obj, "/.*/", "test", "", "test", "/.*/", LU_GROUP_BY_HOST);
   checked_lookup_search (obj, "host0", "test", "", "test", "0",
@@ -160,7 +152,9 @@ DEF_TEST(group_by_specific_host)
 
 DEF_TEST(group_by_any_host)
 {
-  lookup_t *obj = checked_lookup_create ();
+  lookup_t *obj;
+  CHECK_NOT_NULL (obj = lookup_create (
+        lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
 
   checked_lookup_add (obj, "/.*/", "/.*/", "/.*/", "test", "/.*/", LU_GROUP_BY_HOST);
   checked_lookup_search (obj, "host0", "plugin0", "", "test", "0",
@@ -186,9 +180,12 @@ DEF_TEST(group_by_any_host)
 
 DEF_TEST(multiple_lookups)
 {
-  lookup_t *obj = checked_lookup_create ();
+  lookup_t *obj;
   int status;
 
+  CHECK_NOT_NULL (obj = lookup_create (
+        lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
+
   checked_lookup_add (obj, "/.*/", "plugin0", "", "test", "/.*/", LU_GROUP_BY_HOST);
   checked_lookup_add (obj, "/.*/", "/.*/", "", "test", "ti0", LU_GROUP_BY_HOST);
 
@@ -211,7 +208,9 @@ DEF_TEST(multiple_lookups)
 
 DEF_TEST(regex)
 {
-  lookup_t *obj = checked_lookup_create ();
+  lookup_t *obj;
+  CHECK_NOT_NULL (obj = lookup_create (
+        lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
 
   checked_lookup_add (obj, "/^db[0-9]\\./", "cpu", "/.*/", "cpu", "/.*/",
       LU_GROUP_BY_TYPE_INSTANCE);
index 2df6063..8976626 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * collectd - src/uuid.c
  * Copyright (C) 2007  Red Hat Inc.
+ * Copyright (C) 2015  Ruben Kerkhof
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "configfile.h"
 #include "plugin.h"
 
-#if HAVE_LIBHAL
+#if HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
+#if HAVE_LIBHAL_H
 #include <libhal.h>
 #endif
 
@@ -47,18 +53,20 @@ looks_like_a_uuid (const char *uuid)
 {
     int len;
 
-    if (!uuid) return 0;
+    if (!uuid)
+        return (0);
 
     len = strlen (uuid);
 
     if (len < UUID_PRINTABLE_COMPACT_LENGTH)
-        return 0;
+        return (0);
 
     while (*uuid) {
-        if (!isxdigit ((int)*uuid) && *uuid != '-') return 0;
+        if (!isxdigit ((int)*uuid) && *uuid != '-')
+            return (0);
         uuid++;
     }
-    return 1;
+    return (1);
 }
 
 static char *
@@ -86,28 +94,54 @@ uuid_parse_dmidecode(FILE *file)
         if (!looks_like_a_uuid (fields[1]))
             continue;
 
-        return strdup (fields[1]);
+        return (strdup (fields[1]));
     }
-    return NULL;
+    return (NULL);
 }
 
 static char *
 uuid_get_from_dmidecode(void)
 {
-    FILE *dmidecode = popen("dmidecode 2>/dev/null", "r");
+    FILE *dmidecode = popen("dmidecode -t system 2>/dev/null", "r");
     char *uuid;
 
-    if (!dmidecode) {
-        return NULL;
-    }
-    
+    if (!dmidecode)
+        return (NULL);
+
     uuid = uuid_parse_dmidecode(dmidecode);
 
     pclose(dmidecode);
-    return uuid;
+    return (uuid);
+}
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
+static char *
+uuid_get_from_sysctlbyname(const char *name)
+{
+    char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1];
+    size_t len = sizeof (uuid);
+    if (sysctlbyname(name, &uuid, &len, NULL, 0) == -1)
+        return NULL;
+    return (strdup (uuid));
 }
+#elif defined(__OpenBSD__)
+static char *
+uuid_get_from_sysctl(void)
+{
+    char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1];
+    size_t len = sizeof (uuid);
+    int mib[2];
 
-#if HAVE_LIBHAL
+    mib[0] = CTL_HW;
+    mib[1] = HW_UUID;
+
+    if (sysctl(mib, 2, uuid, &len, NULL, 0) == -1)
+        return NULL;
+    return (strdup (uuid));
+}
+#endif
+
+#if HAVE_LIBHAL_H
 
 #define UUID_PATH "/org/freedesktop/Hal/devices/computer"
 #define UUID_PROPERTY "smbios.system.uuid"
@@ -122,50 +156,42 @@ uuid_get_from_hal(void)
 
     dbus_error_init(&error);
 
-    if (!(con = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) ) {
+    if (!(con = dbus_bus_get(DBUS_BUS_SYSTEM, &error)))
         goto bailout_nobus;
-    }
 
     ctx = libhal_ctx_new();
     libhal_ctx_set_dbus_connection(ctx, con);
 
-    if (!libhal_ctx_init(ctx, &error)) {
+    if (!libhal_ctx_init(ctx, &error))
         goto bailout;
-    }
 
     if (!libhal_device_property_exists(ctx,
                                        UUID_PATH,
                                        UUID_PROPERTY,
-                                       &error)) {
+                                       &error))
         goto bailout;
-    }
 
     char *uuid  = libhal_device_get_property_string(ctx,
                                                     UUID_PATH,
                                                     UUID_PROPERTY,
                                                     &error);
-    if (looks_like_a_uuid (uuid)) {
-        return uuid;
-    }
+    if (looks_like_a_uuid (uuid))
+        return (uuid);
 
  bailout:
     {
         DBusError ctxerror;
         dbus_error_init(&ctxerror);
-        if (!(libhal_ctx_shutdown(ctx, &ctxerror))) {
+        if (!(libhal_ctx_shutdown(ctx, &ctxerror)))
             dbus_error_free(&ctxerror);
-        }
     }
 
     libhal_ctx_free(ctx);
-    //dbus_connection_unref(con);
 
  bailout_nobus:
-    if (dbus_error_is_set(&error)) {
-        /*printf("Error %s\n", error.name);*/
+    if (dbus_error_is_set(&error))
         dbus_error_free(&error);
-    }
-    return NULL;
+    return (NULL);
 }
 #endif
 
@@ -177,16 +203,16 @@ uuid_get_from_file(const char *path)
 
     file = fopen (path, "r");
     if (file == NULL)
-        return NULL;
+        return (NULL);
 
     if (!fgets(uuid, sizeof(uuid), file)) {
         fclose(file);
-        return NULL;
+        return (NULL);
     }
     fclose(file);
     strstripnewline (uuid);
 
-    return strdup (uuid);
+    return (strdup (uuid));
 }
 
 static char *
@@ -195,25 +221,40 @@ uuid_get_local(void)
     char *uuid;
 
     /* Check /etc/uuid / UUIDFile before any other method. */
-    if ((uuid = uuid_get_from_file(uuidfile ? uuidfile : "/etc/uuid")) != NULL){
-        return uuid;
-    }
+    if ((uuid = uuid_get_from_file(uuidfile ? uuidfile : "/etc/uuid")) != NULL)
+        return (uuid);
+
+#if defined(__APPLE__)
+    if ((uuid = uuid_get_from_sysctlbyname("kern.uuid")) != NULL)
+        return (uuid);
+#elif defined(__FreeBSD__)
+    if ((uuid = uuid_get_from_sysctlbyname("kern.hostuuid")) != NULL)
+        return (uuid);
+#elif defined(__NetBSD__)
+    if ((uuid = uuid_get_from_sysctlbyname("machdep.dmi.system-uuid")) != NULL)
+        return (uuid);
+#elif defined(__OpenBSD__)
+    if ((uuid = uuid_get_from_sysctl()) != NULL)
+        return (uuid);
+#elif defined(__linux__)
+    if ((uuid = uuid_get_from_file("/sys/class/dmi/id/product_uuid")) != NULL)
+        return (uuid);
+#endif
 
-#if HAVE_LIBHAL
-    if ((uuid = uuid_get_from_hal()) != NULL) {
-        return uuid;
-    }
+#if HAVE_LIBHAL_H
+    if ((uuid = uuid_get_from_hal()) != NULL)
+        return (uuid);
 #endif
 
-    if ((uuid = uuid_get_from_dmidecode()) != NULL) {
-        return uuid;
-    }
+    if ((uuid = uuid_get_from_dmidecode()) != NULL)
+        return (uuid);
 
-    if ((uuid = uuid_get_from_file("/sys/hypervisor/uuid")) != NULL) {
-        return uuid;
-    }
+#if defined(__linux__)
+    if ((uuid = uuid_get_from_file("/sys/hypervisor/uuid")) != NULL)
+        return (uuid);
+#endif
 
-    return NULL;
+    return (NULL);
 }
 
 static int
@@ -222,14 +263,13 @@ uuid_config (const char *key, const char *value)
     if (strcasecmp (key, "UUIDFile") == 0) {
         char *tmp = strdup (value);
         if (tmp == NULL)
-            return -1;
+            return (-1);
         sfree (uuidfile);
         uuidfile = tmp;
-    } else {
-        return 1;
+        return (0);
     }
 
-    return 0;
+    return (1);
 }
 
 static int
@@ -240,11 +280,11 @@ uuid_init (void)
     if (uuid) {
         sstrncpy (hostname_g, uuid, DATA_MAX_NAME_LEN);
         sfree (uuid);
-        return 0;
+        return (0);
     }
 
     WARNING ("uuid: could not read UUID using any known method");
-    return 0;
+    return (0);
 }
 
 void module_register (void)
diff --git a/src/valgrind.FreeBSD.suppress b/src/valgrind.FreeBSD.suppress
new file mode 100644 (file)
index 0000000..28ea677
--- /dev/null
@@ -0,0 +1,8 @@
+{
+   strlen_bogus_invalid_read_after_strdup
+   Memcheck:Addr4
+   fun:parse_value
+   fun:parse_values
+   fun:test_parse_values
+   fun:main
+}
index a138d18..bc6d294 100644 (file)
@@ -24,6 +24,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -793,6 +794,7 @@ static int varnish_read (user_data_t *ud) /* {{{ */
 {
        struct VSM_data *vd;
        const c_varnish_stats_t *stats;
+       _Bool ok;
 
        user_config_t *conf;
 
@@ -822,10 +824,11 @@ static int varnish_read (user_data_t *ud) /* {{{ */
        }
 
 #if HAVE_VARNISH_V3
-       if (VSC_Open (vd, /* diag = */ 1))
+       ok = (VSC_Open (vd, /* diag = */ 1) == 0);
 #else /* if HAVE_VARNISH_V4 */
-       if (VSM_Open (vd))
+       ok = (VSM_Open (vd) == 0);
 #endif
+       if (!ok)
        {
                VSM_Delete (vd);
                ERROR ("varnish plugin: Unable to open connection.");
@@ -941,10 +944,9 @@ static int varnish_init (void) /* {{{ */
        if (have_instance)
                return (0);
 
-       conf = malloc (sizeof (*conf));
+       conf = calloc (1, sizeof (*conf));
        if (conf == NULL)
                return (ENOMEM);
-       memset (conf, 0, sizeof (*conf));
 
        /* Default settings: */
        conf->instance = NULL;
@@ -957,7 +959,7 @@ static int varnish_init (void) /* {{{ */
        plugin_register_complex_read (/* group = */ "varnish",
                        /* name      = */ "varnish/localhost",
                        /* callback  = */ varnish_read,
-                       /* interval  = */ NULL,
+                       /* interval  = */ 0,
                        /* user data = */ &ud);
 
        return (0);
@@ -968,12 +970,10 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
        user_config_t *conf;
        user_data_t ud;
        char callback_name[DATA_MAX_NAME_LEN];
-       int i;
 
-       conf = malloc (sizeof (*conf));
+       conf = calloc (1, sizeof (*conf));
        if (conf == NULL)
                return (ENOMEM);
-       memset (conf, 0, sizeof (*conf));
        conf->instance = NULL;
 
        varnish_config_apply_default (conf);
@@ -1004,7 +1004,7 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
                return (EINVAL);
        }
 
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
 
@@ -1014,9 +1014,11 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
                        cf_util_get_boolean (child, &conf->collect_connections);
                else if (strcasecmp ("CollectESI", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_esi);
-#ifdef HAVE_VARNISH_V3
                else if (strcasecmp ("CollectDirectorDNS", child->key) == 0)
+#ifdef HAVE_VARNISH_V3
                        cf_util_get_boolean (child, &conf->collect_dirdns);
+#else
+                       WARNING ("Varnish plugin: \"%s\" is available for Varnish %s only.", child->key, "v3");
 #endif
                else if (strcasecmp ("CollectBackend", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_backend);
@@ -1026,11 +1028,16 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
                        cf_util_get_boolean (child, &conf->collect_hcb);
                else if (strcasecmp ("CollectObjects", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_objects);
-#if HAVE_VARNISH_V2
                else if (strcasecmp ("CollectPurge", child->key) == 0)
+#if HAVE_VARNISH_V2
                        cf_util_get_boolean (child, &conf->collect_purge);
 #else
+                       WARNING ("Varnish plugin: \"%s\" is available for Varnish %s only.", child->key, "v2");
+#endif
                else if (strcasecmp ("CollectBan", child->key) == 0)
+#if HAVE_VARNISH_V2
+                       WARNING ("Varnish plugin: \"%s\" is not available for Varnish %s.", child->key, "v2");
+#else
                        cf_util_get_boolean (child, &conf->collect_ban);
 #endif
                else if (strcasecmp ("CollectSession", child->key) == 0)
@@ -1039,27 +1046,37 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
                        cf_util_get_boolean (child, &conf->collect_shm);
                else if (strcasecmp ("CollectSMS", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_sms);
-#if HAVE_VARNISH_V2
                else if (strcasecmp ("CollectSMA", child->key) == 0)
+#if HAVE_VARNISH_V2
                        cf_util_get_boolean (child, &conf->collect_sma);
+#else
+                       WARNING ("Varnish plugin: \"%s\" is available for Varnish %s only.", child->key, "v2");
+#endif
                else if (strcasecmp ("CollectSM", child->key) == 0)
+#if HAVE_VARNISH_V2
                        cf_util_get_boolean (child, &conf->collect_sm);
+#else
+                       WARNING ("Varnish plugin: \"%s\" is available for Varnish %s only.", child->key, "v2");
 #endif
                else if (strcasecmp ("CollectStruct", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_struct);
                else if (strcasecmp ("CollectTotals", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_totals);
-#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
                else if (strcasecmp ("CollectUptime", child->key) == 0)
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
                        cf_util_get_boolean (child, &conf->collect_uptime);
+#else
+                       WARNING ("Varnish plugin: \"%s\" is available for Varnish %s only.", child->key, "v3 and v4");
 #endif
                else if (strcasecmp ("CollectVCL", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_vcl);
                else if (strcasecmp ("CollectWorkers", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_workers);
-#if HAVE_VARNISH_V4
                else if (strcasecmp ("CollectVSM", child->key) == 0)
+#if HAVE_VARNISH_V4
                        cf_util_get_boolean (child, &conf->collect_vsm);
+#else
+                       WARNING ("Varnish plugin: \"%s\" is available for Varnish %s only.", child->key, "v4");
 #endif
                else
                {
@@ -1121,7 +1138,7 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
        plugin_register_complex_read (/* group = */ "varnish",
                        /* name      = */ callback_name,
                        /* callback  = */ varnish_read,
-                       /* interval  = */ NULL,
+                       /* interval  = */ 0,
                        /* user data = */ &ud);
 
        have_instance = 1;
@@ -1131,9 +1148,7 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
 
 static int varnish_config (oconfig_item_t *ci) /* {{{ */
 {
-       int i;
-
-       for (i = 0; i < ci->children_num; i++)
+       for (int i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
 
index c9355c4..7df51c1 100644 (file)
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -128,7 +129,7 @@ enum plginst_field {
 };
 
 static enum plginst_field plugin_instance_format[PLGINST_MAX_FIELDS] =
-    { plginst_name };
+    { plginst_none };
 
 /* InterfaceFormat. */
 enum if_field {
@@ -154,7 +155,7 @@ static int refresh_lists (void);
 static void
 init_value_list (value_list_t *vl, virDomainPtr dom)
 {
-    int i, n;
+    int n;
     const char *name;
     char uuid[VIR_UUID_STRING_BUFLEN];
 
@@ -163,7 +164,7 @@ init_value_list (value_list_t *vl, virDomainPtr dom)
     vl->host[0] = '\0';
 
     /* Construct the hostname field according to HostnameFormat. */
-    for (i = 0; i < HF_MAX_FIELDS; ++i) {
+    for (int i = 0; i < HF_MAX_FIELDS; ++i) {
         if (hostname_format[i] == hf_none)
             continue;
 
@@ -194,7 +195,7 @@ init_value_list (value_list_t *vl, virDomainPtr dom)
     vl->host[sizeof (vl->host) - 1] = '\0';
 
     /* Construct the plugin instance field according to PluginInstanceFormat. */
-    for (i = 0; i < PLGINST_MAX_FIELDS; ++i) {
+    for (int i = 0; i < PLGINST_MAX_FIELDS; ++i) {
         if (plugin_instance_format[i] == plginst_none)
             continue;
 
@@ -394,7 +395,7 @@ lv_config (const char *key, const char *value)
     if (strcasecmp (key, "HostnameFormat") == 0) {
         char *value_copy;
         char *fields[HF_MAX_FIELDS];
-        int i, n;
+        int n;
 
         value_copy = strdup (value);
         if (value_copy == NULL) {
@@ -409,7 +410,7 @@ lv_config (const char *key, const char *value)
             return -1;
         }
 
-        for (i = 0; i < n; ++i) {
+        for (int i = 0; i < n; ++i) {
             if (strcasecmp (fields[i], "hostname") == 0)
                 hostname_format[i] = hf_hostname;
             else if (strcasecmp (fields[i], "name") == 0)
@@ -424,7 +425,7 @@ lv_config (const char *key, const char *value)
         }
         sfree (value_copy);
 
-        for (i = n; i < HF_MAX_FIELDS; ++i)
+        for (int i = n; i < HF_MAX_FIELDS; ++i)
             hostname_format[i] = hf_none;
 
         return 0;
@@ -433,7 +434,7 @@ lv_config (const char *key, const char *value)
     if (strcasecmp (key, "PluginInstanceFormat") == 0) {
         char *value_copy;
         char *fields[PLGINST_MAX_FIELDS];
-        int i, n;
+        int n;
 
         value_copy = strdup (value);
         if (value_copy == NULL) {
@@ -448,8 +449,11 @@ lv_config (const char *key, const char *value)
             return -1;
         }
 
-        for (i = 0; i < n; ++i) {
-            if (strcasecmp (fields[i], "name") == 0)
+        for (int i = 0; i < n; ++i) {
+            if (strcasecmp (fields[i], "none") == 0) {
+                plugin_instance_format[i] = plginst_none;
+                break;
+            } else if (strcasecmp (fields[i], "name") == 0)
                 plugin_instance_format[i] = plginst_name;
             else if (strcasecmp (fields[i], "uuid") == 0)
                 plugin_instance_format[i] = plginst_uuid;
@@ -461,7 +465,7 @@ lv_config (const char *key, const char *value)
         }
         sfree (value_copy);
 
-        for (i = n; i < PLGINST_MAX_FIELDS; ++i)
+        for (int i = n; i < PLGINST_MAX_FIELDS; ++i)
             plugin_instance_format[i] = plginst_none;
 
         return 0;
@@ -489,7 +493,6 @@ static int
 lv_read (void)
 {
     time_t t;
-    int i;
 
     if (conn == NULL) {
         /* `conn_string == NULL' is acceptable. */
@@ -519,25 +522,24 @@ lv_read (void)
     }
 
 #if 0
-    for (i = 0; i < nr_domains; ++i)
+    for (int i = 0; i < nr_domains; ++i)
         fprintf (stderr, "domain %s\n", virDomainGetName (domains[i]));
-    for (i = 0; i < nr_block_devices; ++i)
+    for (int i = 0; i < nr_block_devices; ++i)
         fprintf  (stderr, "block device %d %s:%s\n",
                   i, virDomainGetName (block_devices[i].dom),
                   block_devices[i].path);
-    for (i = 0; i < nr_interface_devices; ++i)
+    for (int i = 0; i < nr_interface_devices; ++i)
         fprintf (stderr, "interface device %d %s:%s\n",
                  i, virDomainGetName (interface_devices[i].dom),
                  interface_devices[i].path);
 #endif
 
     /* Get CPU usage, memory, VCPU usage for each domain. */
-    for (i = 0; i < nr_domains; ++i) {
+    for (int i = 0; i < nr_domains; ++i) {
         virDomainInfo info;
         virVcpuInfoPtr vinfo = NULL;
         virDomainMemoryStatPtr minfo = NULL;
         int status;
-        int j;
 
         status = virDomainGetInfo (domains[i], &info);
         if (status != 0)
@@ -572,7 +574,7 @@ lv_read (void)
             continue;
         }
 
-        for (j = 0; j < info.nrVirtCpu; ++j)
+        for (int j = 0; j < info.nrVirtCpu; ++j)
             vcpu_submit (vinfo[j].cpuTime,
                     domains[i], vinfo[j].number, "virt_vcpu");
 
@@ -584,7 +586,7 @@ lv_read (void)
             continue;
         }
 
-        status =  virDomainMemoryStats (domains[i], minfo, VIR_DOMAIN_MEMORY_STAT_NR, 0);
+        status = virDomainMemoryStats (domains[i], minfo, VIR_DOMAIN_MEMORY_STAT_NR, 0);
 
         if (status < 0) {
             ERROR ("virt plugin: virDomainMemoryStats failed with status %i.",
@@ -593,7 +595,7 @@ lv_read (void)
             continue;
         }
 
-        for (j = 0; j < status; j++) {
+        for (int j = 0; j < status; j++) {
             memory_stats_submit ((gauge_t) minfo[j].val * 1024, domains[i], minfo[j].tag);
         }
 
@@ -602,7 +604,7 @@ lv_read (void)
 
 
     /* Get block device stats for each domain. */
-    for (i = 0; i < nr_block_devices; ++i) {
+    for (int i = 0; i < nr_block_devices; ++i) {
         struct _virDomainBlockStats stats;
 
         if (virDomainBlockStats (block_devices[i].dom, block_devices[i].path,
@@ -621,7 +623,7 @@ lv_read (void)
     } /* for (nr_block_devices) */
 
     /* Get interface stats for each domain. */
-    for (i = 0; i < nr_interface_devices; ++i) {
+    for (int i = 0; i < nr_interface_devices; ++i) {
         struct _virDomainInterfaceStats stats;
         char *display_name = NULL;
 
@@ -679,12 +681,11 @@ refresh_lists (void)
     }
 
     if (n > 0) {
-        int i;
         int *domids;
 
         /* Get list of domains. */
-        domids = malloc (sizeof (int) * n);
-        if (domids == 0) {
+        domids = malloc (sizeof (*domids) * n);
+        if (domids == NULL) {
             ERROR (PLUGIN_NAME " plugin: malloc failed.");
             return -1;
         }
@@ -701,14 +702,13 @@ refresh_lists (void)
         free_domains ();
 
         /* Fetch each domain and add it to the list, unless ignore. */
-        for (i = 0; i < n; ++i) {
+        for (int i = 0; i < n; ++i) {
             virDomainPtr dom = NULL;
             const char *name;
             char *xml = NULL;
             xmlDocPtr xml_doc = NULL;
             xmlXPathContextPtr xpath_ctx = NULL;
             xmlXPathObjectPtr xpath_obj = NULL;
-            int j;
 
             dom = virDomainLookupByID (conn, domids[i]);
             if (dom == NULL) {
@@ -755,7 +755,7 @@ refresh_lists (void)
                 xpath_obj->nodesetval == NULL)
                 goto cont;
 
-            for (j = 0; j < xpath_obj->nodesetval->nodeNr; ++j) {
+            for (int j = 0; j < xpath_obj->nodesetval->nodeNr; ++j) {
                 xmlNodePtr node;
                 char *path = NULL;
 
@@ -784,16 +784,15 @@ refresh_lists (void)
 
             xmlNodeSetPtr xml_interfaces = xpath_obj->nodesetval;
 
-            for (j = 0; j < xml_interfaces->nodeNr; ++j) {
+            for (int j = 0; j < xml_interfaces->nodeNr; ++j) {
                 char *path = NULL;
                 char *address = NULL;
                 xmlNodePtr xml_interface;
 
                 xml_interface = xml_interfaces->nodeTab[j];
                 if (!xml_interface) continue;
-                xmlNodePtr child = NULL;
 
-                for (child = xml_interface->children; child; child = child->next) {
+                for (xmlNodePtr child = xml_interface->children; child; child = child->next) {
                     if (child->type != XML_ELEMENT_NODE) continue;
 
                     if (xmlStrEqual(child->name, (const xmlChar *) "target")) {
@@ -830,12 +829,10 @@ refresh_lists (void)
 }
 
 static void
-free_domains ()
+free_domains (void)
 {
-    int i;
-
     if (domains) {
-        for (i = 0; i < nr_domains; ++i)
+        for (int i = 0; i < nr_domains; ++i)
             virDomainFree (domains[i]);
         sfree (domains);
     }
@@ -863,12 +860,10 @@ add_domain (virDomainPtr dom)
 }
 
 static void
-free_block_devices ()
+free_block_devices (void)
 {
-    int i;
-
     if (block_devices) {
-        for (i = 0; i < nr_block_devices; ++i)
+        for (int i = 0; i < nr_block_devices; ++i)
             sfree (block_devices[i].path);
         sfree (block_devices);
     }
@@ -903,12 +898,10 @@ add_block_device (virDomainPtr dom, const char *path)
 }
 
 static void
-free_interface_devices ()
+free_interface_devices (void)
 {
-    int i;
-
     if (interface_devices) {
-        for (i = 0; i < nr_interface_devices; ++i) {
+        for (int i = 0; i < nr_interface_devices; ++i) {
             sfree (interface_devices[i].path);
             sfree (interface_devices[i].address);
             sfree (interface_devices[i].number);
index 7bb0433..46ffa13 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -147,7 +148,7 @@ static int vmem_read (void)
     if (fields[1] == endptr)
       continue;
 
-    /* 
+    /*
      * Number of pages
      *
      * The total number of {inst} pages, e. g dirty pages.
@@ -167,7 +168,7 @@ static int vmem_read (void)
       }
     }
 
-    /* 
+    /*
      * Page in and page outs. For memory and swap.
      */
     else if (strcmp ("pgpgin", key) == 0)
index bd2e867..a730593 100644 (file)
@@ -27,6 +27,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -146,7 +147,7 @@ static int vserver_read (void)
        if (proc == NULL)
        {
                char errbuf[1024];
-               ERROR ("vserver plugin: fopen (%s): %s", PROCDIR, 
+               ERROR ("vserver plugin: fopen (%s): %s", PROCDIR,
                                sstrerror (errno, errbuf, sizeof (errbuf)));
                return (-1);
        }
@@ -185,7 +186,7 @@ static int vserver_read (void)
                len = ssnprintf (file, sizeof (file), PROCDIR "/%s", dent->d_name);
                if ((len < 0) || (len >= BUFSIZE))
                        continue;
-               
+
                status = stat (file, &statbuf);
                if (status != 0)
                {
@@ -194,7 +195,7 @@ static int vserver_read (void)
                                        file, sstrerror (errno, errbuf, sizeof (errbuf)));
                        continue;
                }
-               
+
                if (!S_ISDIR (statbuf.st_mode))
                        continue;
 
@@ -215,7 +216,7 @@ static int vserver_read (void)
                {
                        derive_t rx;
                        derive_t tx;
-                       char *type_instance;
+                       const char *type_instance;
 
                        if (strsplit (buffer, cols, 4) < 4)
                                continue;
@@ -265,7 +266,7 @@ static int vserver_read (void)
 
                        if (2 == n)
                        {
-                               char   *type_instance;
+                               const char *type_instance;
                                gauge_t value;
 
                                if (0 == strcmp (cols[0], "nr_threads:"))
@@ -314,8 +315,8 @@ static int vserver_read (void)
 
                while ((fh != NULL) && (NULL != fgets (buffer, BUFSIZE, fh)))
                {
-                       char *type = "vs_memory";
-                       char *type_instance;
+                       const char *type = "vs_memory";
+                       const char *type_instance;
                        gauge_t value;
 
                        if (strsplit (buffer, cols, 2) < 2)
index f2a3cf5..b998462 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -41,7 +42,7 @@ static double wireless_dbm_to_watt (double dbm)
 
        /*
         * dbm = 10 * log_{10} (1000 * power / W)
-        * power = 10^(dbm/10) * W/1000 
+        * power = 10^(dbm/10) * W/1000
         */
 
        watt = pow (10.0, (dbm / 10.0)) / 1000.0;
@@ -88,7 +89,7 @@ static int wireless_read (void)
        double  quality;
        double  power;
        double  noise;
-       
+
        char *fields[8];
        int   numfields;
 
index a7eef3f..77003f1 100644 (file)
   */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
-#include "utils_cache.h"
 #include "utils_complain.h"
 #include "utils_format_graphite.h"
 
-/* Folks without pthread will need to disable this plugin. */
-#include <pthread.h>
-
-#include <sys/socket.h>
 #include <netdb.h>
 
-#ifndef WG_DEFAULT_NODE
-# define WG_DEFAULT_NODE "localhost"
-#endif
-
-#ifndef WG_DEFAULT_SERVICE
-# define WG_DEFAULT_SERVICE "2003"
-#endif
-
-#ifndef WG_DEFAULT_PROTOCOL
-# define WG_DEFAULT_PROTOCOL "tcp"
-#endif
-
-#ifndef WG_DEFAULT_LOG_SEND_ERRORS
-# define WG_DEFAULT_LOG_SEND_ERRORS 1
-#endif
-
-#ifndef WG_DEFAULT_ESCAPE
-# define WG_DEFAULT_ESCAPE '_'
-#endif
+#define WG_DEFAULT_NODE "localhost"
+#define WG_DEFAULT_SERVICE "2003"
+#define WG_DEFAULT_PROTOCOL "tcp"
+#define WG_DEFAULT_LOG_SEND_ERRORS 1
+#define WG_DEFAULT_ESCAPE '_'
 
 /* Ethernet - (IPv6 + TCP) = 1500 - (40 + 32) = 1428 */
-#ifndef WG_SEND_BUF_SIZE
-# define WG_SEND_BUF_SIZE 1428
-#endif
+#define WG_SEND_BUF_SIZE 1428
 
-#ifndef WG_MIN_RECONNECT_INTERVAL
-# define WG_MIN_RECONNECT_INTERVAL TIME_T_TO_CDTIME_T (1)
-#endif
+#define WG_MIN_RECONNECT_INTERVAL TIME_T_TO_CDTIME_T (1)
 
 /*
  * Private variables
@@ -113,8 +91,36 @@ struct wg_callback
     pthread_mutex_t send_lock;
     c_complain_t init_complaint;
     cdtime_t last_connect_time;
+
+    /* Force reconnect useful for load balanced environments */
+    cdtime_t last_reconnect_time;
+    cdtime_t reconnect_interval;
+    _Bool reconnect_interval_reached;
 };
 
+/* wg_force_reconnect_check closes cb->sock_fd when it was open for longer
+ * than cb->reconnect_interval. Must hold cb->send_lock when calling. */
+static void wg_force_reconnect_check (struct wg_callback *cb)
+{
+    cdtime_t now;
+
+    if (cb->reconnect_interval == 0)
+        return;
+
+    /* check if address changes if addr_timeout */
+    now = cdtime ();
+    if ((now - cb->last_reconnect_time) < cb->reconnect_interval)
+        return;
+
+    /* here we should close connection on next */
+    close (cb->sock_fd);
+    cb->sock_fd = -1;
+    cb->last_reconnect_time = now;
+    cb->reconnect_interval_reached = 1;
+
+    INFO ("write_graphite plugin: Connection closed after %.3f seconds.",
+          CDTIME_T_TO_DOUBLE (now - cb->last_reconnect_time));
+}
 
 /*
  * Functions
@@ -129,18 +135,19 @@ static void wg_reset_buffer (struct wg_callback *cb)
 
 static int wg_send_buffer (struct wg_callback *cb)
 {
-    ssize_t status = 0;
+    ssize_t status;
+
+    if (cb->sock_fd < 0)
+        return (-1);
 
     status = swrite (cb->sock_fd, cb->send_buf, strlen (cb->send_buf));
     if (status != 0)
     {
-        const char *protocol = cb->protocol ? cb->protocol : WG_DEFAULT_PROTOCOL;
-
         if (cb->log_send_errors)
         {
             char errbuf[1024];
             ERROR ("write_graphite plugin: send to %s:%s (%s) failed with status %zi (%s)",
-                    cb->node, cb->service, protocol,
+                    cb->node, cb->service, cb->protocol,
                     status, sstrerror (errno, errbuf, sizeof (errbuf)));
         }
 
@@ -173,7 +180,7 @@ static int wg_flush_nolock (cdtime_t timeout, struct wg_callback *cb)
             return (0);
     }
 
-    if (cb->send_buf_fill <= 0)
+    if (cb->send_buf_fill == 0)
     {
         cb->send_buf_init_time = cdtime ();
         return (0);
@@ -187,16 +194,10 @@ static int wg_flush_nolock (cdtime_t timeout, struct wg_callback *cb)
 
 static int wg_callback_init (struct wg_callback *cb)
 {
-    struct addrinfo ai_hints;
     struct addrinfo *ai_list;
-    struct addrinfo *ai_ptr;
     cdtime_t now;
     int status;
 
-    const char *node = cb->node ? cb->node : WG_DEFAULT_NODE;
-    const char *service = cb->service ? cb->service : WG_DEFAULT_SERVICE;
-    const char *protocol = cb->protocol ? cb->protocol : WG_DEFAULT_PROTOCOL;
-
     char connerr[1024] = "";
 
     if (cb->sock_fd > 0)
@@ -209,29 +210,26 @@ static int wg_callback_init (struct wg_callback *cb)
         return (EAGAIN);
     cb->last_connect_time = now;
 
-    memset (&ai_hints, 0, sizeof (ai_hints));
-#ifdef AI_ADDRCONFIG
-    ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
-    ai_hints.ai_family = AF_UNSPEC;
+    struct addrinfo ai_hints = {
+        .ai_family = AF_UNSPEC,
+        .ai_flags  = AI_ADDRCONFIG
+    };
 
-    if (0 == strcasecmp ("tcp", protocol))
+    if (0 == strcasecmp ("tcp", cb->protocol))
         ai_hints.ai_socktype = SOCK_STREAM;
     else
         ai_hints.ai_socktype = SOCK_DGRAM;
 
-    ai_list = NULL;
-
-    status = getaddrinfo (node, service, &ai_hints, &ai_list);
+    status = getaddrinfo (cb->node, cb->service, &ai_hints, &ai_list);
     if (status != 0)
     {
         ERROR ("write_graphite plugin: getaddrinfo (%s, %s, %s) failed: %s",
-                node, service, protocol, gai_strerror (status));
+                cb->node, cb->service, cb->protocol, gai_strerror (status));
         return (-1);
     }
 
     assert (ai_list != NULL);
-    for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+    for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
     {
         cb->sock_fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype,
                 ai_ptr->ai_protocol);
@@ -242,6 +240,8 @@ static int wg_callback_init (struct wg_callback *cb)
             continue;
         }
 
+        set_sock_opts (cb->sock_fd);
+
         status = connect (cb->sock_fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
         if (status != 0)
         {
@@ -265,17 +265,23 @@ static int wg_callback_init (struct wg_callback *cb)
             sstrerror (errno, connerr, sizeof (connerr));
         c_complain (LOG_ERR, &cb->init_complaint,
                   "write_graphite plugin: Connecting to %s:%s via %s failed. "
-                  "The last error was: %s", node, service, protocol, connerr);
+                  "The last error was: %s", cb->node, cb->service, cb->protocol, connerr);
         return (-1);
     }
     else
     {
         c_release (LOG_INFO, &cb->init_complaint,
                 "write_graphite plugin: Successfully connected to %s:%s via %s.",
-                node, service, protocol);
+                cb->node, cb->service, cb->protocol);
     }
 
-    wg_reset_buffer (cb);
+    /* wg_force_reconnect_check does not flush the buffer before closing a
+     * sending socket, so only call wg_reset_buffer() if the socket was closed
+     * for a different reason (tracked in cb->reconnect_interval_reached). */
+    if (!cb->reconnect_interval_reached || (cb->send_buf_free == 0))
+        wg_reset_buffer (cb);
+    else
+        cb->reconnect_interval_reached = 0;
 
     return (0);
 }
@@ -351,6 +357,8 @@ static int wg_send_message (char const *message, struct wg_callback *cb)
 
     pthread_mutex_lock (&cb->send_lock);
 
+    wg_force_reconnect_check (cb);
+
     if (cb->sock_fd < 0)
     {
         status = wg_callback_init (cb);
@@ -383,9 +391,7 @@ static int wg_send_message (char const *message, struct wg_callback *cb)
     cb->send_buf_free -= message_len;
 
     DEBUG ("write_graphite plugin: [%s]:%s (%s) buf %zu/%zu (%.1f %%) \"%s\"",
-            cb->node,
-            cb->service,
-            cb->protocol,
+            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)),
             message);
@@ -398,7 +404,7 @@ static int wg_send_message (char const *message, struct wg_callback *cb)
 static int wg_write_messages (const data_set_t *ds, const value_list_t *vl,
         struct wg_callback *cb)
 {
-    char buffer[WG_SEND_BUF_SIZE];
+    char buffer[WG_SEND_BUF_SIZE] = { 0 };
     int status;
 
     if (0 != strcmp (ds->type, vl->type))
@@ -408,7 +414,6 @@ static int wg_write_messages (const data_set_t *ds, const value_list_t *vl,
         return -1;
     }
 
-    memset (buffer, 0, sizeof (buffer));
     status = format_graphite (buffer, sizeof (buffer), ds, vl,
             cb->prefix, cb->postfix, cb->escape_char, cb->format_flags);
     if (status != 0) /* error message has been printed already. */
@@ -441,11 +446,9 @@ static int wg_write (const data_set_t *ds, const value_list_t *vl,
 static int config_set_char (char *dest,
         oconfig_item_t *ci)
 {
-    char buffer[4];
+    char buffer[4] = { 0 };
     int status;
 
-    memset (buffer, 0, sizeof (buffer));
-
     status = cf_util_get_string_buffer (ci, buffer, sizeof (buffer));
     if (status != 0)
         return (status);
@@ -472,23 +475,24 @@ static int config_set_char (char *dest,
 static int wg_config_node (oconfig_item_t *ci)
 {
     struct wg_callback *cb;
-    user_data_t user_data;
+    user_data_t user_data = { 0 };
     char callback_name[DATA_MAX_NAME_LEN];
-    int i;
     int status = 0;
 
-    cb = malloc (sizeof (*cb));
+    cb = calloc (1, sizeof (*cb));
     if (cb == NULL)
     {
-        ERROR ("write_graphite plugin: malloc failed.");
+        ERROR ("write_graphite plugin: calloc failed.");
         return (-1);
     }
-    memset (cb, 0, sizeof (*cb));
     cb->sock_fd = -1;
     cb->name = NULL;
-    cb->node = NULL;
-    cb->service = NULL;
-    cb->protocol = NULL;
+    cb->node = strdup (WG_DEFAULT_NODE);
+    cb->service = strdup (WG_DEFAULT_SERVICE);
+    cb->protocol = strdup (WG_DEFAULT_PROTOCOL);
+    cb->last_reconnect_time = cdtime();
+    cb->reconnect_interval = 0;
+    cb->reconnect_interval_reached = 0;
     cb->log_send_errors = WG_DEFAULT_LOG_SEND_ERRORS;
     cb->prefix = NULL;
     cb->postfix = NULL;
@@ -509,7 +513,7 @@ static int wg_config_node (oconfig_item_t *ci)
     pthread_mutex_init (&cb->send_lock, /* attr = */ NULL);
     C_COMPLAIN_INIT (&cb->init_complaint);
 
-    for (i = 0; i < ci->children_num; i++)
+    for (int i = 0; i < ci->children_num; i++)
     {
         oconfig_item_t *child = ci->children + i;
 
@@ -529,6 +533,8 @@ static int wg_config_node (oconfig_item_t *ci)
                 status = -1;
             }
         }
+        else if (strcasecmp ("ReconnectInterval", child->key) == 0)
+            cf_util_get_cdtime (child, &cb->reconnect_interval);
         else if (strcasecmp ("LogSendErrors", child->key) == 0)
             cf_util_get_boolean (child, &cb->log_send_errors);
         else if (strcasecmp ("Prefix", child->key) == 0)
@@ -566,14 +572,11 @@ static int wg_config_node (oconfig_item_t *ci)
     /* FIXME: Legacy configuration syntax. */
     if (cb->name == NULL)
         ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s/%s/%s",
-                cb->node != NULL ? cb->node : WG_DEFAULT_NODE,
-                cb->service != NULL ? cb->service : WG_DEFAULT_SERVICE,
-                cb->protocol != NULL ? cb->protocol : WG_DEFAULT_PROTOCOL);
+                cb->node, cb->service, cb->protocol);
     else
         ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s",
                 cb->name);
 
-    memset (&user_data, 0, sizeof (user_data));
     user_data.data = cb;
     user_data.free_func = wg_callback_free;
     plugin_register_write (callback_name, wg_write, &user_data);
@@ -586,9 +589,7 @@ static int wg_config_node (oconfig_item_t *ci)
 
 static int wg_config (oconfig_item_t *ci)
 {
-    int i;
-
-    for (i = 0; i < ci->children_num; i++)
+    for (int i = 0; i < ci->children_num; i++)
     {
         oconfig_item_t *child = ci->children + i;
 
index 65197e6..d8d8c34 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
-#include "utils_cache.h"
 #include "utils_format_json.h"
-
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
+#include "utils_format_kairosdb.h"
 
 #include <curl/curl.h>
 
@@ -59,13 +56,17 @@ struct wh_callback_s
         char *clientkeypass;
         long sslversion;
         _Bool store_rates;
+        _Bool log_http_error;
         int   low_speed_limit;
         time_t low_speed_time;
         int timeout;
 
-#define WH_FORMAT_COMMAND 0
-#define WH_FORMAT_JSON    1
+#define WH_FORMAT_COMMAND  0
+#define WH_FORMAT_JSON     1
+#define WH_FORMAT_KAIROSDB 2
         int format;
+        _Bool send_metrics;
+        _Bool send_notifications;
 
         CURL *curl;
         struct curl_slist *headers;
@@ -81,14 +82,30 @@ struct wh_callback_s
 };
 typedef struct wh_callback_s wh_callback_t;
 
+static void wh_log_http_error (wh_callback_t *cb)
+{
+        if (!cb->log_http_error)
+                return;
+
+        long http_code = 0;
+
+        curl_easy_getinfo (cb->curl, CURLINFO_RESPONSE_CODE, &http_code);
+
+        if (http_code != 200)
+                INFO ("write_http plugin: HTTP Error code: %lu", http_code);
+}
+
 static void wh_reset_buffer (wh_callback_t *cb)  /* {{{ */
 {
+        if ((cb == NULL) || (cb->send_buffer == NULL))
+                return;
+
         memset (cb->send_buffer, 0, cb->send_buffer_size);
         cb->send_buffer_free = cb->send_buffer_size;
         cb->send_buffer_fill = 0;
         cb->send_buffer_init_time = cdtime ();
 
-        if (cb->format == WH_FORMAT_JSON)
+        if (cb->format == WH_FORMAT_JSON || cb->format == WH_FORMAT_KAIROSDB)
         {
                 format_json_initialize (cb->send_buffer,
                                 &cb->send_buffer_fill,
@@ -96,12 +113,16 @@ static void wh_reset_buffer (wh_callback_t *cb)  /* {{{ */
         }
 } /* }}} wh_reset_buffer */
 
-static int wh_send_buffer (wh_callback_t *cb) /* {{{ */
+/* must hold cb->send_lock when calling */
+static int wh_post_nolock (wh_callback_t *cb, char const *data) /* {{{ */
 {
         int status = 0;
 
-        curl_easy_setopt (cb->curl, CURLOPT_POSTFIELDS, cb->send_buffer);
+        curl_easy_setopt (cb->curl, CURLOPT_POSTFIELDS, data);
         status = curl_easy_perform (cb->curl);
+
+        wh_log_http_error (cb);
+
         if (status != CURLE_OK)
         {
                 ERROR ("write_http plugin: curl_easy_perform failed with "
@@ -109,7 +130,7 @@ static int wh_send_buffer (wh_callback_t *cb) /* {{{ */
                                 status, cb->curl_errbuf);
         }
         return (status);
-} /* }}} wh_send_buffer */
+} /* }}} wh_post_nolock */
 
 static int wh_callback_init (wh_callback_t *cb) /* {{{ */
 {
@@ -139,9 +160,8 @@ static int wh_callback_init (wh_callback_t *cb) /* {{{ */
         curl_easy_setopt (cb->curl, CURLOPT_NOSIGNAL, 1L);
         curl_easy_setopt (cb->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
 
-        cb->headers = NULL;
         cb->headers = curl_slist_append (cb->headers, "Accept:  */*");
-        if (cb->format == WH_FORMAT_JSON)
+        if (cb->format == WH_FORMAT_JSON || cb->format == WH_FORMAT_KAIROSDB)
                 cb->headers = curl_slist_append (cb->headers, "Content-Type: application/json");
         else
                 cb->headers = curl_slist_append (cb->headers, "Content-Type: text/plain");
@@ -166,7 +186,7 @@ static int wh_callback_init (wh_callback_t *cb) /* {{{ */
                 if (cb->pass != NULL)
                         credentials_size += strlen (cb->pass);
 
-                cb->credentials = (char *) malloc (credentials_size);
+                cb->credentials = malloc (credentials_size);
                 if (cb->credentials == NULL)
                 {
                         ERROR ("curl plugin: malloc failed.");
@@ -224,16 +244,16 @@ static int wh_flush_nolock (cdtime_t timeout, wh_callback_t *cb) /* {{{ */
 
         if (cb->format == WH_FORMAT_COMMAND)
         {
-                if (cb->send_buffer_fill <= 0)
+                if (cb->send_buffer_fill == 0)
                 {
                         cb->send_buffer_init_time = cdtime ();
                         return (0);
                 }
 
-                status = wh_send_buffer (cb);
+                status = wh_post_nolock (cb, cb->send_buffer);
                 wh_reset_buffer (cb);
         }
-        else if (cb->format == WH_FORMAT_JSON)
+        else if (cb->format == WH_FORMAT_JSON || cb->format == WH_FORMAT_KAIROSDB)
         {
                 if (cb->send_buffer_fill <= 2)
                 {
@@ -252,7 +272,7 @@ static int wh_flush_nolock (cdtime_t timeout, wh_callback_t *cb) /* {{{ */
                         return (status);
                 }
 
-                status = wh_send_buffer (cb);
+                status = wh_post_nolock (cb, cb->send_buffer);
                 wh_reset_buffer (cb);
         }
         else
@@ -280,15 +300,11 @@ static int wh_flush (cdtime_t timeout, /* {{{ */
 
         pthread_mutex_lock (&cb->send_lock);
 
-        if (cb->curl == NULL)
+        if (wh_callback_init (cb) != 0)
         {
-                status = wh_callback_init (cb);
-                if (status != 0)
-                {
-                        ERROR ("write_http plugin: wh_callback_init failed.");
-                        pthread_mutex_unlock (&cb->send_lock);
-                        return (-1);
-                }
+                ERROR ("write_http plugin: wh_callback_init failed.");
+                pthread_mutex_unlock (&cb->send_lock);
+                return (-1);
         }
 
         status = wh_flush_nolock (timeout, cb);
@@ -306,7 +322,8 @@ static void wh_callback_free (void *data) /* {{{ */
 
         cb = data;
 
-        wh_flush_nolock (/* timeout = */ 0, cb);
+        if (cb->send_buffer != NULL)
+                wh_flush_nolock (/* timeout = */ 0, cb);
 
         if (cb->curl != NULL)
         {
@@ -380,16 +397,11 @@ static int wh_write_command (const data_set_t *ds, const value_list_t *vl, /* {{
         }
 
         pthread_mutex_lock (&cb->send_lock);
-
-        if (cb->curl == NULL)
+        if (wh_callback_init (cb) != 0)
         {
-                status = wh_callback_init (cb);
-                if (status != 0)
-                {
-                        ERROR ("write_http plugin: wh_callback_init failed.");
-                        pthread_mutex_unlock (&cb->send_lock);
-                        return (-1);
-                }
+                ERROR ("write_http plugin: wh_callback_init failed.");
+                pthread_mutex_unlock (&cb->send_lock);
+                return (-1);
         }
 
         if (command_len >= cb->send_buffer_free)
@@ -428,6 +440,55 @@ static int wh_write_json (const data_set_t *ds, const value_list_t *vl, /* {{{ *
         int status;
 
         pthread_mutex_lock (&cb->send_lock);
+        if (wh_callback_init (cb) != 0)
+        {
+                ERROR ("write_http plugin: wh_callback_init failed.");
+                pthread_mutex_unlock (&cb->send_lock);
+                return (-1);
+        }
+
+        status = format_json_value_list (cb->send_buffer,
+                        &cb->send_buffer_fill,
+                        &cb->send_buffer_free,
+                        ds, vl, cb->store_rates);
+        if (status == -ENOMEM)
+        {
+                status = wh_flush_nolock (/* timeout = */ 0, cb);
+                if (status != 0)
+                {
+                        wh_reset_buffer (cb);
+                        pthread_mutex_unlock (&cb->send_lock);
+                        return (status);
+                }
+
+                status = format_json_value_list (cb->send_buffer,
+                                &cb->send_buffer_fill,
+                                &cb->send_buffer_free,
+                                ds, vl, cb->store_rates);
+        }
+        if (status != 0)
+        {
+                pthread_mutex_unlock (&cb->send_lock);
+                return (status);
+        }
+
+        DEBUG ("write_http plugin: <%s> buffer %zu/%zu (%g%%)",
+                        cb->location,
+                        cb->send_buffer_fill, cb->send_buffer_size,
+                        100.0 * ((double) cb->send_buffer_fill) / ((double) cb->send_buffer_size));
+
+        /* Check if we have enough space for this command. */
+        pthread_mutex_unlock (&cb->send_lock);
+
+        return (0);
+} /* }}} int wh_write_json */
+
+static int wh_write_kairosdb (const data_set_t *ds, const value_list_t *vl, /* {{{ */
+                wh_callback_t *cb)
+{
+        int status;
+
+        pthread_mutex_lock (&cb->send_lock);
 
         if (cb->curl == NULL)
         {
@@ -440,11 +501,11 @@ static int wh_write_json (const data_set_t *ds, const value_list_t *vl, /* {{{ *
                 }
         }
 
-        status = format_json_value_list (cb->send_buffer,
+        status = format_kairosdb_value_list (cb->send_buffer,
                         &cb->send_buffer_fill,
                         &cb->send_buffer_free,
                         ds, vl, cb->store_rates);
-        if (status == (-ENOMEM))
+        if (status == -ENOMEM)
         {
                 status = wh_flush_nolock (/* timeout = */ 0, cb);
                 if (status != 0)
@@ -454,7 +515,7 @@ static int wh_write_json (const data_set_t *ds, const value_list_t *vl, /* {{{ *
                         return (status);
                 }
 
-                status = format_json_value_list (cb->send_buffer,
+                status = format_kairosdb_value_list (cb->send_buffer,
                                 &cb->send_buffer_fill,
                                 &cb->send_buffer_free,
                                 ds, vl, cb->store_rates);
@@ -474,7 +535,7 @@ static int wh_write_json (const data_set_t *ds, const value_list_t *vl, /* {{{ *
         pthread_mutex_unlock (&cb->send_lock);
 
         return (0);
-} /* }}} int wh_write_json */
+} /* }}} int wh_write_kairosdb */
 
 static int wh_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
                 user_data_t *user_data)
@@ -486,15 +547,55 @@ static int wh_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
                 return (-EINVAL);
 
         cb = user_data->data;
+        assert (cb->send_metrics);
 
-        if (cb->format == WH_FORMAT_JSON)
+        switch(cb->format) {
+            case WH_FORMAT_JSON:
                 status = wh_write_json (ds, vl, cb);
-        else
+                break;
+            case WH_FORMAT_KAIROSDB:
+                status = wh_write_kairosdb (ds, vl, cb);
+                break;
+            default:
                 status = wh_write_command (ds, vl, cb);
-
+                break;
+        }
         return (status);
 } /* }}} int wh_write */
 
+static int wh_notify (notification_t const *n, user_data_t *ud) /* {{{ */
+{
+        wh_callback_t *cb;
+        char alert[4096];
+        int status;
+
+        if ((ud == NULL) || (ud->data == NULL))
+                return (EINVAL);
+
+        cb = ud->data;
+        assert (cb->send_notifications);
+
+        status = format_json_notification (alert, sizeof (alert), n);
+        if (status != 0)
+        {
+                ERROR ("write_http plugin: formatting notification failed");
+                return status;
+        }
+
+        pthread_mutex_lock (&cb->send_lock);
+        if (wh_callback_init (cb) != 0)
+        {
+                ERROR ("write_http plugin: wh_callback_init failed.");
+                pthread_mutex_unlock (&cb->send_lock);
+                return (-1);
+        }
+
+        status = wh_post_nolock (cb, alert);
+        pthread_mutex_unlock (&cb->send_lock);
+
+        return (status);
+} /* }}} int wh_notify */
+
 static int config_set_format (wh_callback_t *cb, /* {{{ */
                 oconfig_item_t *ci)
 {
@@ -513,6 +614,8 @@ static int config_set_format (wh_callback_t *cb, /* {{{ */
                 cb->format = WH_FORMAT_COMMAND;
         else if (strcasecmp ("JSON", string) == 0)
                 cb->format = WH_FORMAT_JSON;
+        else if (strcasecmp ("KAIROSDB", string) == 0)
+                cb->format = WH_FORMAT_KAIROSDB;
         else
         {
                 ERROR ("write_http plugin: Invalid format string: %s",
@@ -523,28 +626,49 @@ static int config_set_format (wh_callback_t *cb, /* {{{ */
         return (0);
 } /* }}} int config_set_format */
 
+static int wh_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
+    oconfig_item_t *ci)
+{
+  struct curl_slist *temp = NULL;
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("write_http plugin: `%s' needs exactly one string argument.", name);
+    return (-1);
+  }
+
+  temp = curl_slist_append(*dest, ci->values[0].value.string);
+  if (temp == NULL)
+    return (-1);
+
+  *dest = temp;
+
+  return (0);
+} /* }}} int wh_config_append_string */
+
 static int wh_config_node (oconfig_item_t *ci) /* {{{ */
 {
         wh_callback_t *cb;
         int buffer_size = 0;
-        user_data_t user_data;
+        user_data_t user_data = { 0 };
         char callback_name[DATA_MAX_NAME_LEN];
-        int i;
+        int status = 0;
 
-        cb = malloc (sizeof (*cb));
+        cb = calloc (1, sizeof (*cb));
         if (cb == NULL)
         {
-                ERROR ("write_http plugin: malloc failed.");
+                ERROR ("write_http plugin: calloc failed.");
                 return (-1);
         }
-        memset (cb, 0, sizeof (*cb));
         cb->verify_peer = 1;
         cb->verify_host = 1;
         cb->format = WH_FORMAT_COMMAND;
         cb->sslversion = CURL_SSLVERSION_DEFAULT;
         cb->low_speed_limit = 0;
         cb->timeout = 0;
+        cb->log_http_error = 0;
         cb->headers = NULL;
+        cb->send_metrics = 1;
+        cb->send_notifications = 0;
 
         pthread_mutex_init (&cb->send_lock, /* attr = */ NULL);
 
@@ -554,35 +678,37 @@ static int wh_config_node (oconfig_item_t *ci) /* {{{ */
         if (strcasecmp ("URL", ci->key) == 0)
                 cf_util_get_string (ci, &cb->location);
 
-        for (i = 0; i < ci->children_num; i++)
+        for (int i = 0; i < ci->children_num; i++)
         {
                 oconfig_item_t *child = ci->children + i;
 
                 if (strcasecmp ("URL", child->key) == 0)
-                        cf_util_get_string (child, &cb->location);
+                        status = cf_util_get_string (child, &cb->location);
                 else if (strcasecmp ("User", child->key) == 0)
-                        cf_util_get_string (child, &cb->user);
+                        status = cf_util_get_string (child, &cb->user);
                 else if (strcasecmp ("Password", child->key) == 0)
-                        cf_util_get_string (child, &cb->pass);
+                        status = cf_util_get_string (child, &cb->pass);
                 else if (strcasecmp ("VerifyPeer", child->key) == 0)
-                        cf_util_get_boolean (child, &cb->verify_peer);
+                        status = cf_util_get_boolean (child, &cb->verify_peer);
                 else if (strcasecmp ("VerifyHost", child->key) == 0)
-                        cf_util_get_boolean (child, &cb->verify_host);
+                        status = cf_util_get_boolean (child, &cb->verify_host);
                 else if (strcasecmp ("CACert", child->key) == 0)
-                        cf_util_get_string (child, &cb->cacert);
+                        status = cf_util_get_string (child, &cb->cacert);
                 else if (strcasecmp ("CAPath", child->key) == 0)
-                        cf_util_get_string (child, &cb->capath);
+                        status = cf_util_get_string (child, &cb->capath);
                 else if (strcasecmp ("ClientKey", child->key) == 0)
-                        cf_util_get_string (child, &cb->clientkey);
+                        status = cf_util_get_string (child, &cb->clientkey);
                 else if (strcasecmp ("ClientCert", child->key) == 0)
-                        cf_util_get_string (child, &cb->clientcert);
+                        status = cf_util_get_string (child, &cb->clientcert);
                 else if (strcasecmp ("ClientKeyPass", child->key) == 0)
-                        cf_util_get_string (child, &cb->clientkeypass);
+                        status = cf_util_get_string (child, &cb->clientkeypass);
                 else if (strcasecmp ("SSLVersion", child->key) == 0)
                 {
                         char *value = NULL;
 
-                        cf_util_get_string (child, &value);
+                        status = cf_util_get_string (child, &value);
+                        if (status != 0)
+                                break;
 
                         if (value == NULL || strcasecmp ("default", value) == 0)
                                 cb->sslversion = CURL_SSLVERSION_DEFAULT;
@@ -601,26 +727,47 @@ static int wh_config_node (oconfig_item_t *ci) /* {{{ */
                                 cb->sslversion = CURL_SSLVERSION_TLSv1_2;
 #endif
                         else
+                        {
                                 ERROR ("write_http plugin: Invalid SSLVersion "
                                                 "option: %s.", value);
+                                status = EINVAL;
+                        }
 
                         sfree(value);
                 }
                 else if (strcasecmp ("Format", child->key) == 0)
-                        config_set_format (cb, child);
+                        status = config_set_format (cb, child);
+                else if (strcasecmp ("Metrics", child->key) == 0)
+                        cf_util_get_boolean (child, &cb->send_metrics);
+                else if (strcasecmp ("Notifications", child->key) == 0)
+                        cf_util_get_boolean (child, &cb->send_notifications);
                 else if (strcasecmp ("StoreRates", child->key) == 0)
-                        cf_util_get_boolean (child, &cb->store_rates);
+                        status = cf_util_get_boolean (child, &cb->store_rates);
                 else if (strcasecmp ("BufferSize", child->key) == 0)
-                        cf_util_get_int (child, &buffer_size);
+                        status = cf_util_get_int (child, &buffer_size);
                 else if (strcasecmp ("LowSpeedLimit", child->key) == 0)
-                        cf_util_get_int (child, &cb->low_speed_limit);
+                        status = cf_util_get_int (child, &cb->low_speed_limit);
                 else if (strcasecmp ("Timeout", child->key) == 0)
-                        cf_util_get_int (child, &cb->timeout);
+                        status = cf_util_get_int (child, &cb->timeout);
+                else if (strcasecmp ("LogHttpError", child->key) == 0)
+                        status = cf_util_get_boolean (child, &cb->log_http_error);
+                else if (strcasecmp ("Header", child->key) == 0)
+                        status = wh_config_append_string ("Header", &cb->headers, child);
                 else
                 {
                         ERROR ("write_http plugin: Invalid configuration "
                                         "option: %s.", child->key);
+                        status = EINVAL;
                 }
+
+                if (status != 0)
+                        break;
+        }
+
+        if (status != 0)
+        {
+                wh_callback_free (cb);
+                return (status);
         }
 
         if (cb->location == NULL)
@@ -631,6 +778,14 @@ static int wh_config_node (oconfig_item_t *ci) /* {{{ */
                 return (-1);
         }
 
+        if (!cb->send_metrics && !cb->send_notifications)
+        {
+                ERROR ("write_http plugin: Neither metrics nor notifications "
+                       "are enabled for \"%s\".", cb->name);
+                wh_callback_free (cb);
+                return (-1);
+        }
+
         if (cb->low_speed_limit > 0)
                 cb->low_speed_time = CDTIME_T_TO_TIME_T(plugin_get_interval());
 
@@ -658,22 +813,31 @@ static int wh_config_node (oconfig_item_t *ci) /* {{{ */
         DEBUG ("write_http: Registering write callback '%s' with URL '%s'",
                         callback_name, cb->location);
 
-        memset (&user_data, 0, sizeof (user_data));
         user_data.data = cb;
-        user_data.free_func = NULL;
         plugin_register_flush (callback_name, wh_flush, &user_data);
 
         user_data.free_func = wh_callback_free;
-        plugin_register_write (callback_name, wh_write, &user_data);
+
+        if (cb->send_metrics)
+        {
+                plugin_register_write (callback_name, wh_write, &user_data);
+                user_data.free_func = NULL;
+
+                plugin_register_flush (callback_name, wh_flush, &user_data);
+        }
+
+        if (cb->send_notifications)
+        {
+                plugin_register_notification (callback_name, wh_notify, &user_data);
+                user_data.free_func = NULL;
+        }
 
         return (0);
 } /* }}} int wh_config_node */
 
 static int wh_config (oconfig_item_t *ci) /* {{{ */
 {
-        int i;
-
-        for (i = 0; i < ci->children_num; i++)
+        for (int i = 0; i < ci->children_num; i++)
         {
                 oconfig_item_t *child = ci->children + i;
 
index 775e2e0..6364c6c 100644 (file)
  */
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "configfile.h"
-#include "utils_cache.h"
 #include "utils_cmd_putval.h"
 #include "utils_format_graphite.h"
 #include "utils_format_json.h"
-#include "utils_crc32.h"
 
 #include <stdint.h>
 #include <librdkafka/rdkafka.h>
-#include <pthread.h>
-#include <zlib.h>
 #include <errno.h>
 
 struct kafka_topic_context {
 #define KAFKA_FORMAT_JSON        0
 #define KAFKA_FORMAT_COMMAND     1
 #define KAFKA_FORMAT_GRAPHITE    2
-    uint8_t                     format;
+    uint8_t                      format;
     unsigned int                 graphite_flags;
     _Bool                        store_rates;
     rd_kafka_topic_conf_t       *conf;
     rd_kafka_topic_t            *topic;
     rd_kafka_conf_t             *kafka_conf;
     rd_kafka_t                  *kafka;
-    int                          has_key;
-    uint32_t                    key;
+    char                        *key;
     char                        *prefix;
     char                        *postfix;
     char                         escape_char;
     char                        *topic_name;
-    pthread_mutex_t            lock;
+    pthread_mutex_t              lock;
 };
 
 static int kafka_handle(struct kafka_topic_context *);
@@ -75,13 +71,21 @@ static void kafka_log(const rd_kafka_t *rkt, int level,
 }
 #endif
 
+static uint32_t kafka_hash(const char *keydata, size_t keylen)
+{
+    uint32_t hash = 5381;
+    for (; keylen > 0; keylen--)
+        hash = ((hash << 5) + hash) + keydata[keylen - 1];
+    return hash;
+}
+
 static int32_t kafka_partition(const rd_kafka_topic_t *rkt,
                                const void *keydata, size_t keylen,
                                int32_t partition_cnt, void *p, void *m)
 {
-    uint32_t key = *((uint32_t *)keydata );
+    uint32_t key = kafka_hash(keydata, keylen);
     uint32_t target = key % partition_cnt;
-    int32_t   i = partition_cnt;
+    int32_t  i = partition_cnt;
 
     while (--i > 0 && !rd_kafka_topic_partition_available(rkt, target)) {
         target = (target + 1) % partition_cnt;
@@ -106,37 +110,37 @@ static int kafka_handle(struct kafka_topic_context *ctx) /* {{{ */
 
         if ((ctx->kafka = rd_kafka_new(RD_KAFKA_PRODUCER, conf,
                                     errbuf, sizeof(errbuf))) == NULL) {
-               ERROR("write_kafka plugin: cannot create kafka handle.");
-               return 1;
+            ERROR("write_kafka plugin: cannot create kafka handle.");
+            return 1;
         }
 
-       rd_kafka_conf_destroy(ctx->kafka_conf);
-       ctx->kafka_conf = NULL;
+        rd_kafka_conf_destroy(ctx->kafka_conf);
+        ctx->kafka_conf = NULL;
 
-       INFO ("write_kafka plugin: created KAFKA handle : %s", rd_kafka_name(ctx->kafka));
+        INFO ("write_kafka plugin: created KAFKA handle : %s", rd_kafka_name(ctx->kafka));
 
-#ifdef HAVE_LIBRDKAFKA_LOGGER
-       rd_kafka_set_logger(ctx->kafka, kafka_log);
+#if defined(HAVE_LIBRDKAFKA_LOGGER) && !defined(HAVE_LIBRDKAFKA_LOG_CB)
+        rd_kafka_set_logger(ctx->kafka, kafka_log);
 #endif
     }
 
     if (ctx->topic == NULL ) {
-       if ((topic_conf = rd_kafka_topic_conf_dup(ctx->conf)) == NULL) {
+        if ((topic_conf = rd_kafka_topic_conf_dup(ctx->conf)) == NULL) {
             ERROR("write_kafka plugin: cannot duplicate kafka topic config");
             return 1;
-       }
+        }
 
-       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)));
-               return errno;
-       }
+        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)));
+            return errno;
+        }
 
-       rd_kafka_topic_conf_destroy(ctx->conf);
-       ctx->conf = NULL;
+        rd_kafka_topic_conf_destroy(ctx->conf);
+        ctx->conf = NULL;
 
-       INFO ("write_kafka plugin: handle created for topic : %s", rd_kafka_topic_name(ctx->topic));
+        INFO ("write_kafka plugin: handle created for topic : %s", rd_kafka_topic_name(ctx->topic));
     }
 
     return(0);
@@ -144,16 +148,17 @@ static int kafka_handle(struct kafka_topic_context *ctx) /* {{{ */
 } /* }}} int kafka_handle */
 
 static int kafka_write(const data_set_t *ds, /* {{{ */
-             const value_list_t *vl,
-             user_data_t *ud)
+          const value_list_t *vl,
+          user_data_t *ud)
 {
-       int                      status = 0;
-    uint32_t    key;
-    char         buffer[8192];
-    size_t bfree = sizeof(buffer);
-    size_t bfill = 0;
-    size_t blen = 0;
-       struct kafka_topic_context      *ctx = ud->data;
+    int      status = 0;
+    void    *key;
+    size_t   keylen = 0;
+    char     buffer[8192];
+    size_t   bfree = sizeof(buffer);
+    size_t   bfill = 0;
+    size_t   blen = 0;
+    struct   kafka_topic_context  *ctx = ud->data;
 
     if ((ds == NULL) || (vl == NULL) || (ctx == NULL))
         return EINVAL;
@@ -177,7 +182,6 @@ static int kafka_write(const data_set_t *ds, /* {{{ */
         blen = strlen(buffer);
         break;
     case KAFKA_FORMAT_JSON:
-
         format_json_initialize(buffer, &bfill, &bfree);
         format_json_value_list(buffer, &bfill, &bfree, ds, vl,
                                ctx->store_rates);
@@ -200,27 +204,25 @@ static int kafka_write(const data_set_t *ds, /* {{{ */
         return -1;
     }
 
-    /*
-     * We partition our stream by metric name
-     */
-    if (ctx->has_key)
-        key = ctx->key;
+    key = ctx->key;
+    if (key != NULL)
+        keylen = strlen (key);
     else
-        key = rand();
+        keylen = 0;
 
     rd_kafka_produce(ctx->topic, RD_KAFKA_PARTITION_UA,
                      RD_KAFKA_MSG_F_COPY, buffer, blen,
-                     &key, sizeof(key), NULL);
+                     key, keylen, NULL);
 
-       return status;
+    return status;
 } /* }}} int kafka_write */
 
 static void kafka_topic_context_free(void *p) /* {{{ */
 {
-       struct kafka_topic_context *ctx = p;
+    struct kafka_topic_context *ctx = p;
 
-       if (ctx == NULL)
-               return;
+    if (ctx == NULL)
+        return;
 
     if (ctx->topic_name != NULL)
         sfree(ctx->topic_name);
@@ -239,24 +241,24 @@ static void kafka_topic_context_free(void *p) /* {{{ */
 static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{ */
 {
     int                          status;
-    int                          i;
     struct kafka_topic_context  *tctx;
     char                        *key = NULL;
     char                        *val;
     char                         callback_name[DATA_MAX_NAME_LEN];
     char                         errbuf[1024];
     user_data_t                  ud;
-       oconfig_item_t              *child;
+    oconfig_item_t              *child;
     rd_kafka_conf_res_t          ret;
 
-       if ((tctx = calloc(1, sizeof (*tctx))) == NULL) {
-               ERROR ("write_kafka plugin: calloc failed.");
+    if ((tctx = calloc(1, sizeof (*tctx))) == NULL) {
+        ERROR ("write_kafka plugin: calloc failed.");
         return;
-       }
+    }
 
     tctx->escape_char = '.';
     tctx->store_rates = 1;
     tctx->format = KAFKA_FORMAT_JSON;
+    tctx->key = NULL;
 
     if ((tctx->kafka_conf = rd_kafka_conf_dup(conf)) == NULL) {
         sfree(tctx);
@@ -290,48 +292,37 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
         goto errout;
     }
 
-       for (i = 0; i < ci->children_num; i++) {
-               /*
-                * The code here could be simplified but makes room
-                * for easy adding of new options later on.
-                */
-               child = &ci->children[i];
-               status = 0;
-
-               if (strcasecmp ("Property", child->key) == 0) {
-                       if (child->values_num != 2) {
-                               WARNING("kafka properties need both a key and a value.");
+    for (int i = 0; i < ci->children_num; i++) {
+        /*
+         * The code here could be simplified but makes room
+         * for easy adding of new options later on.
+         */
+        child = &ci->children[i];
+        status = 0;
+
+        if (strcasecmp ("Property", child->key) == 0) {
+            if (child->values_num != 2) {
+                WARNING("kafka properties need both a key and a value.");
                 goto errout;
-                       }
-                       if (child->values[0].type != OCONFIG_TYPE_STRING ||
-                           child->values[1].type != OCONFIG_TYPE_STRING) {
-                               WARNING("kafka properties needs string arguments.");
+            }
+            if (child->values[0].type != OCONFIG_TYPE_STRING ||
+                child->values[1].type != OCONFIG_TYPE_STRING) {
+                WARNING("kafka properties needs string arguments.");
                 goto errout;
-                       }
+            }
             key = child->values[0].value.string;
             val = child->values[1].value.string;
             ret = rd_kafka_topic_conf_set(tctx->conf,key, val,
                                           errbuf, sizeof(errbuf));
             if (ret != RD_KAFKA_CONF_OK) {
-                               WARNING("cannot set kafka topic property %s to %s: %s.",
+                WARNING("cannot set kafka topic property %s to %s: %s.",
                         key, val, errbuf);
                 goto errout;
-                       }
-
-        } else if (strcasecmp ("Key", child->key) == 0)  {
-            char *tmp_buf = NULL;
-            status = cf_util_get_string(child, &tmp_buf);
-            if (status != 0) {
-                WARNING("write_kafka plugin: invalid key supplied");
-                break;
-            }
-
-            if (strcasecmp(tmp_buf, "Random") != 0) {
-                tctx->has_key = 1;
-                tctx->key = crc32_buffer((u_char *)tmp_buf, strlen(tmp_buf));
             }
-            sfree(tmp_buf);
 
+        } else if (strcasecmp ("Key", child->key) == 0)  {
+            cf_util_get_string (child, &tctx->key);
+            assert (tctx->key != NULL);
         } else if (strcasecmp ("Format", child->key) == 0) {
             status = cf_util_get_string(child, &key);
             if (status != 0)
@@ -397,11 +388,11 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
     ud.data = tctx;
     ud.free_func = kafka_topic_context_free;
 
-       status = plugin_register_write (callback_name, kafka_write, &ud);
-       if (status != 0) {
-               WARNING ("write_kafka plugin: plugin_register_write (\"%s\") "
-                               "failed with status %i.",
-                               callback_name, status);
+    status = plugin_register_write (callback_name, kafka_write, &ud);
+    if (status != 0) {
+        WARNING ("write_kafka plugin: plugin_register_write (\"%s\") "
+                "failed with status %i.",
+                callback_name, status);
         goto errout;
     }
 
@@ -414,14 +405,13 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
     if (tctx->conf != NULL)
         rd_kafka_topic_conf_destroy(tctx->conf);
     if (tctx->kafka_conf != NULL)
-               rd_kafka_conf_destroy(tctx->kafka_conf);
+        rd_kafka_conf_destroy(tctx->kafka_conf);
     sfree(tctx);
 } /* }}} int kafka_config_topic */
 
 static int kafka_config(oconfig_item_t *ci) /* {{{ */
 {
-       int                          i;
-       oconfig_item_t              *child;
+    oconfig_item_t              *child;
     rd_kafka_conf_t             *conf;
     rd_kafka_conf_res_t          ret;
     char                         errbuf[1024];
@@ -430,49 +420,52 @@ static int kafka_config(oconfig_item_t *ci) /* {{{ */
         WARNING("cannot allocate kafka configuration.");
         return -1;
     }
-       for (i = 0; i < ci->children_num; i++)  {
-               child = &ci->children[i];
+    for (int i = 0; i < ci->children_num; i++)  {
+        child = &ci->children[i];
 
-               if (strcasecmp("Topic", child->key) == 0) {
-                       kafka_config_topic (conf, child);
-               } else if (strcasecmp(child->key, "Property") == 0) {
-                       char *key = NULL;
-                       char *val = NULL;
+        if (strcasecmp("Topic", child->key) == 0) {
+            kafka_config_topic (conf, child);
+        } else if (strcasecmp(child->key, "Property") == 0) {
+            char *key = NULL;
+            char *val = NULL;
 
-                       if (child->values_num != 2) {
-                               WARNING("kafka properties need both a key and a value.");
+            if (child->values_num != 2) {
+                WARNING("kafka properties need both a key and a value.");
                 goto errout;
-                       }
-                       if (child->values[0].type != OCONFIG_TYPE_STRING ||
-                           child->values[1].type != OCONFIG_TYPE_STRING) {
-                               WARNING("kafka properties needs string arguments.");
+            }
+            if (child->values[0].type != OCONFIG_TYPE_STRING ||
+                child->values[1].type != OCONFIG_TYPE_STRING) {
+                WARNING("kafka properties needs string arguments.");
                 goto errout;
-                       }
-                       if ((key = strdup(child->values[0].value.string)) == NULL) {
-                               WARNING("cannot allocate memory for attribute key.");
+            }
+            if ((key = strdup(child->values[0].value.string)) == NULL) {
+                WARNING("cannot allocate memory for attribute key.");
                 goto errout;
-                       }
-                       if ((val = strdup(child->values[1].value.string)) == NULL) {
-                               WARNING("cannot allocate memory for attribute value.");
+            }
+            if ((val = strdup(child->values[1].value.string)) == NULL) {
+                WARNING("cannot allocate memory for attribute value.");
+                sfree(key);
                 goto errout;
-                       }
+            }
             ret = rd_kafka_conf_set(conf, key, val, errbuf, sizeof(errbuf));
             if (ret != RD_KAFKA_CONF_OK) {
                 WARNING("cannot set kafka property %s to %s: %s",
                         key, val, errbuf);
+                sfree(key);
+                sfree(val);
                 goto errout;
             }
-                       sfree(key);
-                       sfree(val);
-               } else {
-                       WARNING ("write_kafka plugin: Ignoring unknown "
-                                "configuration option \"%s\" at top level.",
-                                child->key);
-               }
-       }
+            sfree(key);
+            sfree(val);
+        } else {
+            WARNING ("write_kafka plugin: Ignoring unknown "
+                 "configuration option \"%s\" at top level.",
+                 child->key);
+        }
+    }
     if (conf != NULL)
         rd_kafka_conf_destroy(conf);
-       return (0);
+    return (0);
  errout:
     if (conf != NULL)
         rd_kafka_conf_destroy(conf);
@@ -481,7 +474,5 @@ static int kafka_config(oconfig_item_t *ci) /* {{{ */
 
 void module_register(void)
 {
-       plugin_register_complex_config ("write_kafka", kafka_config);
+    plugin_register_complex_config ("write_kafka", kafka_config);
 }
-
-/* vim: set sw=8 sts=8 ts=8 noet : */
index e37aae9..3c59978 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
 #include "utils_format_graphite.h"
 
-/* Folks without pthread will need to disable this plugin. */
-#include <pthread.h>
-
-#include <sys/socket.h>
 #include <netdb.h>
 
 #define WL_BUF_SIZE 8192
 
 static int wl_write_messages (const data_set_t *ds, const value_list_t *vl)
 {
-    char buffer[WL_BUF_SIZE];
+    char buffer[WL_BUF_SIZE] = { 0 };
     int status;
 
     if (0 != strcmp (ds->type, vl->type))
@@ -52,7 +49,6 @@ static int wl_write_messages (const data_set_t *ds, const value_list_t *vl)
         return -1;
     }
 
-    memset (buffer, 0, sizeof (buffer));
     status = format_graphite (buffer, sizeof (buffer), ds, vl,
                               NULL, NULL, '_', 0);
     if (status != 0) /* error message has been printed already. */
index 24151ce..8fb13c3 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "configfile.h"
 #include "utils_cache.h"
 
-#include <pthread.h>
-
 #if HAVE_STDINT_H
 # define MONGO_HAVE_STDINT 1
 #else
@@ -77,7 +76,6 @@ static bson *wm_create_bson (const data_set_t *ds, /* {{{ */
 {
   bson *ret;
   gauge_t *rates;
-  int i;
 
   ret = bson_alloc (); /* matched by bson_dealloc() */
   if (ret == NULL)
@@ -109,7 +107,7 @@ static bson *wm_create_bson (const data_set_t *ds, /* {{{ */
   bson_append_string (ret, "type_instance", vl->type_instance);
 
   bson_append_start_array (ret, "values"); /* {{{ */
-  for (i = 0; i < ds->ds_num; i++)
+  for (int i = 0; i < ds->ds_num; i++)
   {
     char key[16];
 
@@ -131,7 +129,7 @@ static bson *wm_create_bson (const data_set_t *ds, /* {{{ */
   bson_append_finish_array (ret); /* }}} values */
 
   bson_append_start_array (ret, "dstypes"); /* {{{ */
-  for (i = 0; i < ds->ds_num; i++)
+  for (int i = 0; i < ds->ds_num; i++)
   {
     char key[16];
 
@@ -145,7 +143,7 @@ static bson *wm_create_bson (const data_set_t *ds, /* {{{ */
   bson_append_finish_array (ret); /* }}} dstypes */
 
   bson_append_start_array (ret, "dsnames"); /* {{{ */
-  for (i = 0; i < ds->ds_num; i++)
+  for (int i = 0; i < ds->ds_num; i++)
   {
     char key[16];
 
@@ -272,12 +270,10 @@ static int wm_config_node (oconfig_item_t *ci) /* {{{ */
 {
   wm_node_t *node;
   int status;
-  int i;
 
-  node = malloc (sizeof (*node));
+  node = calloc (1, sizeof (*node));
   if (node == NULL)
     return (ENOMEM);
-  memset (node, 0, sizeof (*node));
   mongo_init (node->conn);
   node->host = NULL;
   node->store_rates = 1;
@@ -291,7 +287,7 @@ static int wm_config_node (oconfig_item_t *ci) /* {{{ */
     return (status);
   }
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -360,9 +356,7 @@ static int wm_config_node (oconfig_item_t *ci) /* {{{ */
 
 static int wm_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
index 231738c..135a458 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/write_redis.c
- * Copyright (C) 2010       Florian Forster
+ * Copyright (C) 2010-2015  Florian Forster
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "configfile.h"
 
-#include <pthread.h>
 #include <sys/time.h>
 #include <hiredis/hiredis.h>
 
+#ifndef REDIS_DEFAULT_PREFIX
+# define REDIS_DEFAULT_PREFIX "collectd/"
+#endif
+
 struct wr_node_s
 {
   char name[DATA_MAX_NAME_LEN];
@@ -40,6 +44,10 @@ struct wr_node_s
   char *host;
   int port;
   struct timeval timeout;
+  char *prefix;
+  int database;
+  int max_set_size;
+  _Bool store_rates;
 
   redisContext *conn;
   pthread_mutex_t lock;
@@ -56,7 +64,7 @@ static int wr_write (const data_set_t *ds, /* {{{ */
   wr_node_t *node = ud->data;
   char ident[512];
   char key[512];
-  char value[512];
+  char value[512] = { 0 };
   char time[24];
   size_t value_size;
   char *value_ptr;
@@ -66,13 +74,14 @@ static int wr_write (const data_set_t *ds, /* {{{ */
   status = FORMAT_VL (ident, sizeof (ident), vl);
   if (status != 0)
     return (status);
-  ssnprintf (key, sizeof (key), "collectd/%s", ident);
+  ssnprintf (key, sizeof (key), "%s%s",
+      (node->prefix != NULL) ? node->prefix : REDIS_DEFAULT_PREFIX,
+      ident);
   ssnprintf (time, sizeof (time), "%.9f", CDTIME_T_TO_DOUBLE(vl->time));
 
-  memset (value, 0, sizeof (value));
   value_size = sizeof (value);
   value_ptr = &value[0];
-  status = format_values (value_ptr, value_size, ds, vl, /* store rates = */ 0);
+  status = format_values (value_ptr, value_size, ds, vl, node->store_rates);
   if (status != 0)
     return (status);
 
@@ -98,6 +107,12 @@ static int wr_write (const data_set_t *ds, /* {{{ */
       pthread_mutex_unlock (&node->lock);
       return (-1);
     }
+
+    rr = redisCommand(node->conn, "SELECT %d", node->database);
+    if (rr == NULL)
+      WARNING("SELECT command error. database:%d message:%s", node->database, node->conn->errstr);
+    else
+      freeReplyObject (rr);
   }
 
   rr = redisCommand (node->conn, "ZADD %s %s %s", key, time, value);
@@ -106,10 +121,21 @@ static int wr_write (const data_set_t *ds, /* {{{ */
   else
     freeReplyObject (rr);
 
+  if (node->max_set_size >= 0)
+  {
+    rr = redisCommand (node->conn, "ZREMRANGEBYRANK %s %d %d", key, 0, (-1 * node->max_set_size) - 1);
+    if (rr == NULL)
+      WARNING("ZREMRANGEBYRANK command error. key:%s message:%s", key, node->conn->errstr);
+    else
+      freeReplyObject (rr);
+  }
+
   /* TODO(octo): This is more overhead than necessary. Use the cache and
    * metadata to determine if it is a new metric and call SADD only once for
    * each metric. */
-  rr = redisCommand (node->conn, "SADD collectd/values %s", ident);
+  rr = redisCommand (node->conn, "SADD %svalues %s",
+      (node->prefix != NULL) ? node->prefix : REDIS_DEFAULT_PREFIX,
+      ident);
   if (rr==NULL)
     WARNING("SADD command error. ident:%s message:%s", ident, node->conn->errstr);
   else
@@ -142,17 +168,19 @@ static int wr_config_node (oconfig_item_t *ci) /* {{{ */
   wr_node_t *node;
   int timeout;
   int status;
-  int i;
 
-  node = malloc (sizeof (*node));
+  node = calloc (1, sizeof (*node));
   if (node == NULL)
     return (ENOMEM);
-  memset (node, 0, sizeof (*node));
   node->host = NULL;
   node->port = 0;
   node->timeout.tv_sec = 0;
   node->timeout.tv_usec = 1000;
   node->conn = NULL;
+  node->prefix = NULL;
+  node->database = 0;
+  node->max_set_size = -1;
+  node->store_rates = 1;
   pthread_mutex_init (&node->lock, /* attr = */ NULL);
 
   status = cf_util_get_string_buffer (ci, node->name, sizeof (node->name));
@@ -162,7 +190,7 @@ static int wr_config_node (oconfig_item_t *ci) /* {{{ */
     return (status);
   }
 
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -181,6 +209,18 @@ static int wr_config_node (oconfig_item_t *ci) /* {{{ */
       status = cf_util_get_int (child, &timeout);
       if (status == 0) node->timeout.tv_usec = timeout;
     }
+    else if (strcasecmp ("Prefix", child->key) == 0) {
+      status = cf_util_get_string (child, &node->prefix);
+    }
+    else if (strcasecmp ("Database", child->key) == 0) {
+      status = cf_util_get_int (child, &node->database);
+    }
+    else if (strcasecmp ("MaxSetSize", child->key) == 0) {
+      status = cf_util_get_int (child, &node->max_set_size);
+    }
+    else if (strcasecmp ("StoreRates", child->key) == 0) {
+      status = cf_util_get_boolean (child, &node->store_rates);
+    }
     else
       WARNING ("write_redis plugin: Ignoring unknown config option \"%s\".",
           child->key);
@@ -210,9 +250,7 @@ static int wr_config_node (oconfig_item_t *ci) /* {{{ */
 
 static int wr_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
index 58611a9..f143723 100644 (file)
@@ -2,6 +2,7 @@
  * collectd - src/write_riemann.c
  * Copyright (C) 2012,2013  Pierre-Yves Ritschard
  * Copyright (C) 2013       Florian octo Forster
+ * Copyright (C) 2015,2016  Gergely Nagy
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * Authors:
  *   Pierre-Yves Ritschard <pyr at spootnik.org>
  *   Florian octo Forster <octo at collectd.org>
+ *   Gergely Nagy <algernon at madhouse-project.org>
  */
 
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <netdb.h>
-#include <inttypes.h>
-#include <pthread.h>
-
 #include "collectd.h"
-#include "plugin.h"
+
 #include "common.h"
 #include "configfile.h"
+#include "plugin.h"
 #include "utils_cache.h"
-#include "riemann.pb-c.h"
+#include "utils_complain.h"
 #include "write_riemann_threshold.h"
 
-#define RIEMANN_HOST           "localhost"
-#define RIEMANN_PORT           "5555"
-#define RIEMANN_TTL_FACTOR      2.0
-#define RIEMANN_BATCH_MAX      8192
+#include <errno.h>
+#include <riemann/riemann-client.h>
+
+#define RIEMANN_HOST "localhost"
+#define RIEMANN_PORT 5555
+#define RIEMANN_TTL_FACTOR 2.0
+#define RIEMANN_BATCH_MAX 8192
 
 struct riemann_host {
-       char                    *name;
-       char                    *event_service_prefix;
-#define F_CONNECT       0x01
-       uint8_t                  flags;
-       pthread_mutex_t  lock;
-    _Bool            batch_mode;
-       _Bool            notifications;
-       _Bool            check_thresholds;
-       _Bool                    store_rates;
-       _Bool                    always_append_ds;
-       char                    *node;
-       char                    *service;
-       _Bool                    use_tcp;
-       int                          s;
-       double                   ttl_factor;
-    Msg             *batch_msg;
-    cdtime_t         batch_init;
-    int              batch_max;
-       int                          reference_count;
+  c_complain_t init_complaint;
+  char *name;
+  char *event_service_prefix;
+  pthread_mutex_t lock;
+  _Bool batch_mode;
+  _Bool notifications;
+  _Bool check_thresholds;
+  _Bool store_rates;
+  _Bool always_append_ds;
+  char *node;
+  int port;
+  riemann_client_type_t client_type;
+  riemann_client_t *client;
+  double ttl_factor;
+  cdtime_t batch_init;
+  int batch_max;
+  int batch_timeout;
+  int reference_count;
+  riemann_message_t *batch_msg;
+  char *tls_ca_file;
+  char *tls_cert_file;
+  char *tls_key_file;
+  struct timeval timeout;
 };
 
-static char    **riemann_tags;
-static size_t    riemann_tags_num;
-static char    **riemann_attrs;
-static size_t     riemann_attrs_num;
-
-static void riemann_event_protobuf_free (Event *event) /* {{{ */
-{
-       size_t i;
-
-       if (event == NULL)
-               return;
-
-       sfree (event->state);
-       sfree (event->service);
-       sfree (event->host);
-       sfree (event->description);
+static char **riemann_tags;
+static size_t riemann_tags_num;
+static char **riemann_attrs;
+static size_t riemann_attrs_num;
 
-       strarray_free (event->tags, event->n_tags);
-       event->tags = NULL;
-       event->n_tags = 0;
-
-       for (i = 0; i < event->n_attributes; i++)
-       {
-               sfree (event->attributes[i]->key);
-               sfree (event->attributes[i]->value);
-               sfree (event->attributes[i]);
-       }
-       sfree (event->attributes);
-       event->n_attributes = 0;
-
-       sfree (event);
-} /* }}} void riemann_event_protobuf_free */
-
-static void riemann_msg_protobuf_free(Msg *msg) /* {{{ */
+/* host->lock must be held when calling this function. */
+static int wrr_connect(struct riemann_host *host) /* {{{ */
 {
-       size_t i;
-
-       if (msg == NULL)
-               return;
-
-       for (i = 0; i < msg->n_events; i++)
-       {
-               riemann_event_protobuf_free (msg->events[i]);
-               msg->events[i] = NULL;
-       }
+  char const *node;
+  int port;
+
+  if (host->client)
+    return 0;
+
+  node = (host->node != NULL) ? host->node : RIEMANN_HOST;
+  port = (host->port) ? host->port : RIEMANN_PORT;
+
+  host->client = NULL;
+
+  host->client = riemann_client_create(
+      host->client_type, node, port, RIEMANN_CLIENT_OPTION_TLS_CA_FILE,
+      host->tls_ca_file, RIEMANN_CLIENT_OPTION_TLS_CERT_FILE,
+      host->tls_cert_file, RIEMANN_CLIENT_OPTION_TLS_KEY_FILE,
+      host->tls_key_file, RIEMANN_CLIENT_OPTION_NONE);
+  if (host->client == NULL) {
+    c_complain(LOG_ERR, &host->init_complaint,
+               "write_riemann plugin: Unable to connect to Riemann at %s:%d",
+               node, port);
+    return -1;
+  }
+  if (host->timeout.tv_sec != 0) {
+    if (riemann_client_set_timeout(host->client, &host->timeout) != 0) {
+      riemann_client_free(host->client);
+      host->client = NULL;
+      c_complain(LOG_ERR, &host->init_complaint,
+                 "write_riemann plugin: Unable to connect to Riemann at %s:%d",
+                 node, port);
+      return -1;
+    }
+  }
 
-       sfree (msg->events);
-       msg->n_events = 0;
+  set_sock_opts(riemann_client_get_fd(host->client));
 
-       sfree (msg);
-} /* }}} void riemann_msg_protobuf_free */
+  c_release(LOG_INFO, &host->init_complaint,
+            "write_riemann plugin: Successfully connected to %s:%d", node,
+            port);
 
-/* host->lock must be held when calling this function. */
-static int riemann_connect(struct riemann_host *host) /* {{{ */
-{
-       int                      e;
-       struct addrinfo         *ai, *res, hints;
-       char const              *node;
-       char const              *service;
-
-       if (host->flags & F_CONNECT)
-               return 0;
-
-       memset(&hints, 0, sizeof(hints));
-       memset(&service, 0, sizeof(service));
-       hints.ai_family = AF_UNSPEC;
-       hints.ai_socktype = host->use_tcp ? SOCK_STREAM : SOCK_DGRAM;
-#ifdef AI_ADDRCONFIG
-       hints.ai_flags |= AI_ADDRCONFIG;
-#endif
-
-       node = (host->node != NULL) ? host->node : RIEMANN_HOST;
-       service = (host->service != NULL) ? host->service : RIEMANN_PORT;
-
-       if ((e = getaddrinfo(node, service, &hints, &res)) != 0) {
-               ERROR ("write_riemann plugin: Unable to resolve host \"%s\": %s",
-                       node, gai_strerror(e));
-               return -1;
-       }
-
-       host->s = -1;
-       for (ai = res; ai != NULL; ai = ai->ai_next) {
-               if ((host->s = socket(ai->ai_family,
-                                     ai->ai_socktype,
-                                     ai->ai_protocol)) == -1) {
-                       continue;
-               }
-
-               if (connect(host->s, ai->ai_addr, ai->ai_addrlen) != 0) {
-                       close(host->s);
-                       host->s = -1;
-                       continue;
-               }
-
-               host->flags |= F_CONNECT;
-               DEBUG("write_riemann plugin: got a successful connection for: %s:%s",
-                               node, service);
-               break;
-       }
-
-       freeaddrinfo(res);
-
-       if (host->s < 0) {
-               WARNING("write_riemann plugin: Unable to connect to Riemann at %s:%s",
-                               node, service);
-               return -1;
-       }
-       return 0;
-} /* }}} int riemann_connect */
+  return 0;
+} /* }}} int wrr_connect */
 
 /* host->lock must be held when calling this function. */
-static int riemann_disconnect (struct riemann_host *host) /* {{{ */
+static int wrr_disconnect(struct riemann_host *host) /* {{{ */
 {
-       if ((host->flags & F_CONNECT) == 0)
-               return (0);
+  if (!host->client)
+    return (0);
 
-       close (host->s);
-       host->s = -1;
-       host->flags &= ~F_CONNECT;
+  riemann_client_free(host->client);
+  host->client = NULL;
 
-       return (0);
-} /* }}} int riemann_disconnect */
+  return (0);
+} /* }}} int wrr_disconnect */
 
-static int riemann_send_msg (struct riemann_host *host, const Msg *msg) /* {{{ */
-{
-       int status = 0;
-       u_char *buffer = NULL;
-       size_t  buffer_len;
-
-       status = riemann_connect (host);
-       if (status != 0)
-               return status;
-
-       buffer_len = msg__get_packed_size(msg);
-
-       if (host->use_tcp)
-               buffer_len += 4;
-
-       buffer = malloc (buffer_len);
-       if (buffer == NULL) {
-               ERROR ("write_riemann plugin: malloc failed.");
-               return ENOMEM;
-       }
-       memset (buffer, 0, buffer_len);
-
-       if (host->use_tcp)
-       {
-               uint32_t length = htonl ((uint32_t) (buffer_len - 4));
-               memcpy (buffer, &length, 4);
-               msg__pack(msg, buffer + 4);
-       }
-       else
-       {
-               msg__pack(msg, buffer);
-       }
-
-       status = (int) swrite (host->s, buffer, buffer_len);
-       if (status != 0)
-       {
-               char errbuf[1024];
-               ERROR ("write_riemann plugin: Sending to Riemann at %s:%s failed: %s",
-                               (host->node != NULL) ? host->node : RIEMANN_HOST,
-                               (host->service != NULL) ? host->service : RIEMANN_PORT,
-                               sstrerror (errno, errbuf, sizeof (errbuf)));
-               sfree (buffer);
-               return -1;
-       }
-
-       sfree (buffer);
-       return 0;
-} /* }}} int riemann_send_msg */
-
-static int riemann_recv_ack(struct riemann_host *host) /* {{{ */
+/**
+ * Function to send messages to riemann.
+ *
+ * Acquires the host lock, disconnects on errors.
+ */
+static int wrr_send_nolock(struct riemann_host *host,
+                           riemann_message_t *msg) /* {{{ */
 {
-       int status = 0;
-       Msg *msg = NULL;
-       uint32_t header;
+  int status = 0;
 
-       status = (int) sread (host->s, &header, 4);
-
-       if (status != 0)
-               return -1;
+  status = wrr_connect(host);
+  if (status != 0) {
+    return status;
+  }
 
-       size_t size = ntohl(header);
+  status = riemann_client_send_message(host->client, msg);
+  if (status != 0) {
+    wrr_disconnect(host);
+    return status;
+  }
 
-       // Buffer on the stack since acknowledges are typically small.
-       u_char buffer[size];
-       memset (buffer, 0, size);
+  /*
+   * For TCP we need to receive message acknowledgemenent.
+   */
+  if (host->client_type != RIEMANN_CLIENT_UDP) {
+    riemann_message_t *response;
 
-       status = (int) sread (host->s, buffer, size);
+    response = riemann_client_recv_message(host->client);
 
-       if (status != 0)
-               return status;
+    if (response == NULL) {
+      wrr_disconnect(host);
+      return errno;
+    }
+    riemann_message_free(response);
+  }
 
-       msg = msg__unpack (NULL, size, buffer);
+  return 0;
+} /* }}} int wrr_send */
 
-       if (msg == NULL)
-               return -1;
+static int wrr_send(struct riemann_host *host, riemann_message_t *msg) {
+  int status = 0;
 
-       if (!msg->ok)
-       {
-               ERROR ("write_riemann plugin: Sending to Riemann at %s:%s acknowledgement message reported error: %s",
-                               (host->node != NULL) ? host->node : RIEMANN_HOST,
-                               (host->service != NULL) ? host->service : RIEMANN_PORT,
-                               msg->error);
+  pthread_mutex_lock(&host->lock);
+  status = wrr_send_nolock(host, msg);
+  pthread_mutex_unlock(&host->lock);
+  return status;
+}
 
-               msg__free_unpacked(msg, NULL);
-               return -1;
-       }
+static riemann_message_t *
+wrr_notification_to_message(struct riemann_host *host, /* {{{ */
+                            notification_t const *n) {
+  riemann_message_t *msg;
+  riemann_event_t *event;
+  char service_buffer[6 * DATA_MAX_NAME_LEN];
+  char const *severity;
+
+  switch (n->severity) {
+  case NOTIF_OKAY:
+    severity = "ok";
+    break;
+  case NOTIF_WARNING:
+    severity = "warning";
+    break;
+  case NOTIF_FAILURE:
+    severity = "critical";
+    break;
+  default:
+    severity = "unknown";
+  }
+
+  format_name(service_buffer, sizeof(service_buffer),
+              /* host = */ "", n->plugin, n->plugin_instance, n->type,
+              n->type_instance);
+
+  event = riemann_event_create(
+      RIEMANN_EVENT_FIELD_HOST, n->host, RIEMANN_EVENT_FIELD_TIME,
+      (int64_t)CDTIME_T_TO_TIME_T(n->time), RIEMANN_EVENT_FIELD_TAGS,
+      "notification", NULL, RIEMANN_EVENT_FIELD_STATE, severity,
+      RIEMANN_EVENT_FIELD_SERVICE, &service_buffer[1],
+      RIEMANN_EVENT_FIELD_NONE);
+
+  if (n->host[0] != 0)
+    riemann_event_string_attribute_add(event, "host", n->host);
+  if (n->plugin[0] != 0)
+    riemann_event_string_attribute_add(event, "plugin", n->plugin);
+  if (n->plugin_instance[0] != 0)
+    riemann_event_string_attribute_add(event, "plugin_instance",
+                                       n->plugin_instance);
+
+  if (n->type[0] != 0)
+    riemann_event_string_attribute_add(event, "type", n->type);
+  if (n->type_instance[0] != 0)
+    riemann_event_string_attribute_add(event, "type_instance",
+                                       n->type_instance);
+
+  for (size_t i = 0; i < riemann_attrs_num; i += 2)
+    riemann_event_string_attribute_add(event, riemann_attrs[i],
+                                       riemann_attrs[i + 1]);
+
+  for (size_t i = 0; i < riemann_tags_num; i++)
+    riemann_event_tag_add(event, riemann_tags[i]);
+
+  if (n->message[0] != 0)
+    riemann_event_string_attribute_add(event, "description", n->message);
+
+  /* Pull in values from threshold and add extra attributes */
+  for (notification_meta_t *meta = n->meta; meta != NULL; meta = meta->next) {
+    if (strcasecmp("CurrentValue", meta->name) == 0 &&
+        meta->type == NM_TYPE_DOUBLE) {
+      riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_D,
+                        (double)meta->nm_value.nm_double,
+                        RIEMANN_EVENT_FIELD_NONE);
+      continue;
+    }
 
-       msg__free_unpacked (msg, NULL);
-       return 0;
-} /* }}} int riemann_recv_ack */
+    if (meta->type == NM_TYPE_STRING) {
+      riemann_event_string_attribute_add(event, meta->name,
+                                         meta->nm_value.nm_string);
+      continue;
+    }
+  }
+
+  msg = riemann_message_create_with_events(event, NULL);
+  if (msg == NULL) {
+    ERROR("write_riemann plugin: riemann_message_create_with_events() failed.");
+    riemann_event_free(event);
+    return (NULL);
+  }
+
+  DEBUG("write_riemann plugin: Successfully created message for notification: "
+        "host = \"%s\", service = \"%s\", state = \"%s\"",
+        event->host, event->service, event->state);
+  return (msg);
+} /* }}} riemann_message_t *wrr_notification_to_message */
+
+static riemann_event_t *
+wrr_value_to_event(struct riemann_host const *host, /* {{{ */
+                   data_set_t const *ds, value_list_t const *vl, size_t index,
+                   gauge_t const *rates, int status) {
+  riemann_event_t *event;
+  char name_buffer[5 * DATA_MAX_NAME_LEN];
+  char service_buffer[6 * DATA_MAX_NAME_LEN];
+  size_t i;
+
+  event = riemann_event_new();
+  if (event == NULL) {
+    ERROR("write_riemann plugin: riemann_event_new() failed.");
+    return (NULL);
+  }
+
+  format_name(name_buffer, sizeof(name_buffer),
+              /* host = */ "", vl->plugin, vl->plugin_instance, vl->type,
+              vl->type_instance);
+  if (host->always_append_ds || (ds->ds_num > 1)) {
+    if (host->event_service_prefix == NULL)
+      ssnprintf(service_buffer, sizeof(service_buffer), "%s/%s",
+                &name_buffer[1], ds->ds[index].name);
+    else
+      ssnprintf(service_buffer, sizeof(service_buffer), "%s%s/%s",
+                host->event_service_prefix, &name_buffer[1],
+                ds->ds[index].name);
+  } else {
+    if (host->event_service_prefix == NULL)
+      sstrncpy(service_buffer, &name_buffer[1], sizeof(service_buffer));
+    else
+      ssnprintf(service_buffer, sizeof(service_buffer), "%s%s",
+                host->event_service_prefix, &name_buffer[1]);
+  }
+
+  riemann_event_set(
+      event, RIEMANN_EVENT_FIELD_HOST, vl->host, RIEMANN_EVENT_FIELD_TIME,
+      (int64_t)CDTIME_T_TO_TIME_T(vl->time), RIEMANN_EVENT_FIELD_TTL,
+      (float)CDTIME_T_TO_DOUBLE(vl->interval) * host->ttl_factor,
+      RIEMANN_EVENT_FIELD_STRING_ATTRIBUTES, "plugin", vl->plugin, "type",
+      vl->type, "ds_name", ds->ds[index].name, NULL,
+      RIEMANN_EVENT_FIELD_SERVICE, service_buffer, RIEMANN_EVENT_FIELD_NONE);
+
+  if (host->check_thresholds) {
+    const char *state = NULL;
+
+    switch (status) {
+    case STATE_OKAY:
+      state = "ok";
+      break;
+    case STATE_ERROR:
+      state = "critical";
+      break;
+    case STATE_WARNING:
+      state = "warning";
+      break;
+    case STATE_MISSING:
+      state = "unknown";
+      break;
+    }
+    if (state)
+      riemann_event_set(event, RIEMANN_EVENT_FIELD_STATE, state,
+                        RIEMANN_EVENT_FIELD_NONE);
+  }
+
+  if (vl->plugin_instance[0] != 0)
+    riemann_event_string_attribute_add(event, "plugin_instance",
+                                       vl->plugin_instance);
+  if (vl->type_instance[0] != 0)
+    riemann_event_string_attribute_add(event, "type_instance",
+                                       vl->type_instance);
+
+  if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL)) {
+    char ds_type[DATA_MAX_NAME_LEN];
+
+    ssnprintf(ds_type, sizeof(ds_type), "%s:rate",
+              DS_TYPE_TO_STRING(ds->ds[index].type));
+    riemann_event_string_attribute_add(event, "ds_type", ds_type);
+  } else {
+    riemann_event_string_attribute_add(event, "ds_type",
+                                       DS_TYPE_TO_STRING(ds->ds[index].type));
+  }
+
+  {
+    char ds_index[DATA_MAX_NAME_LEN];
+
+    ssnprintf(ds_index, sizeof(ds_index), "%zu", index);
+    riemann_event_string_attribute_add(event, "ds_index", ds_index);
+  }
+
+  for (i = 0; i < riemann_attrs_num; i += 2)
+    riemann_event_string_attribute_add(event, riemann_attrs[i],
+                                       riemann_attrs[i + 1]);
+
+  for (i = 0; i < riemann_tags_num; i++)
+    riemann_event_tag_add(event, riemann_tags[i]);
+
+  if (ds->ds[index].type == DS_TYPE_GAUGE) {
+    riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_D,
+                      (double)vl->values[index].gauge,
+                      RIEMANN_EVENT_FIELD_NONE);
+  } else if (rates != NULL) {
+    riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_D, (double)rates[index],
+                      RIEMANN_EVENT_FIELD_NONE);
+  } else {
+    int64_t metric;
+
+    if (ds->ds[index].type == DS_TYPE_DERIVE)
+      metric = (int64_t)vl->values[index].derive;
+    else if (ds->ds[index].type == DS_TYPE_ABSOLUTE)
+      metric = (int64_t)vl->values[index].absolute;
+    else
+      metric = (int64_t)vl->values[index].counter;
+
+    riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_S64, (int64_t)metric,
+                      RIEMANN_EVENT_FIELD_NONE);
+  }
+
+  DEBUG("write_riemann plugin: Successfully created message for metric: "
+        "host = \"%s\", service = \"%s\"",
+        event->host, event->service);
+  return (event);
+} /* }}} riemann_event_t *wrr_value_to_event */
+
+static riemann_message_t *
+wrr_value_list_to_message(struct riemann_host const *host, /* {{{ */
+                          data_set_t const *ds, value_list_t const *vl,
+                          int *statuses) {
+  riemann_message_t *msg;
+  size_t i;
+  gauge_t *rates = NULL;
+
+  /* Initialize the Msg structure. */
+  msg = riemann_message_new();
+  if (msg == NULL) {
+    ERROR("write_riemann plugin: riemann_message_new failed.");
+    return (NULL);
+  }
+
+  if (host->store_rates) {
+    rates = uc_get_rate(ds, vl);
+    if (rates == NULL) {
+      ERROR("write_riemann plugin: uc_get_rate failed.");
+      riemann_message_free(msg);
+      return (NULL);
+    }
+  }
 
-/**
- * Function to send messages (Msg) to riemann.
- *
- * Acquires the host lock, disconnects on errors.
- */
-static int riemann_send(struct riemann_host *host, Msg const *msg) /* {{{ */
-{
-       int status = 0;
-       pthread_mutex_lock (&host->lock);
-
-       status = riemann_send_msg(host, msg);
-       if (status != 0) {
-               riemann_disconnect (host);
-               pthread_mutex_unlock (&host->lock);
-               return status;
-       }
-
-       /*
-        * For TCP we need to receive message acknowledgemenent.
-        */
-       if (host->use_tcp)
-       {
-               status = riemann_recv_ack(host);
-
-               if (status != 0)
-               {
-                       riemann_disconnect (host);
-                       pthread_mutex_unlock (&host->lock);
-                       return status;
-               }
-       }
-
-       pthread_mutex_unlock (&host->lock);
-       return 0;
-} /* }}} int riemann_send */
-
-static int riemann_event_add_tag (Event *event, char const *tag) /* {{{ */
-{
-       return (strarray_add (&event->tags, &event->n_tags, tag));
-} /* }}} int riemann_event_add_tag */
+  for (i = 0; i < vl->values_len; i++) {
+    riemann_event_t *event;
 
-static int riemann_event_add_attribute(Event *event, /* {{{ */
-               char const *key, char const *value)
-{
-       Attribute **new_attributes;
-       Attribute *a;
-
-       new_attributes = realloc (event->attributes,
-                       sizeof (*event->attributes) * (event->n_attributes + 1));
-       if (new_attributes == NULL)
-       {
-               ERROR ("write_riemann plugin: realloc failed.");
-               return (ENOMEM);
-       }
-       event->attributes = new_attributes;
-
-       a = malloc (sizeof (*a));
-       if (a == NULL)
-       {
-               ERROR ("write_riemann plugin: malloc failed.");
-               return (ENOMEM);
-       }
-       attribute__init (a);
-
-       a->key = strdup (key);
-       if (value != NULL)
-               a->value = strdup (value);
-
-       event->attributes[event->n_attributes] = a;
-       event->n_attributes++;
-
-       return (0);
-} /* }}} int riemann_event_add_attribute */
-
-static Msg *riemann_notification_to_protobuf(struct riemann_host *host, /* {{{ */
-               notification_t const *n)
-{
-       Msg *msg;
-       Event *event;
-       char service_buffer[6 * DATA_MAX_NAME_LEN];
-       char const *severity;
-       notification_meta_t *meta;
-       int i;
-
-       msg = malloc (sizeof (*msg));
-       if (msg == NULL)
-       {
-               ERROR ("write_riemann plugin: malloc failed.");
-               return (NULL);
-       }
-       memset (msg, 0, sizeof (*msg));
-       msg__init (msg);
-
-       msg->events = malloc (sizeof (*msg->events));
-       if (msg->events == NULL)
-       {
-               ERROR ("write_riemann plugin: malloc failed.");
-               sfree (msg);
-               return (NULL);
-       }
-
-       event = malloc (sizeof (*event));
-       if (event == NULL)
-       {
-               ERROR ("write_riemann plugin: malloc failed.");
-               sfree (msg->events);
-               sfree (msg);
-               return (NULL);
-       }
-       memset (event, 0, sizeof (*event));
-       event__init (event);
-
-       msg->events[0] = event;
-       msg->n_events = 1;
-
-       event->host = strdup (n->host);
-       event->time = CDTIME_T_TO_TIME_T (n->time);
-       event->has_time = 1;
-
-       switch (n->severity)
-       {
-               case NOTIF_OKAY:        severity = "ok"; break;
-               case NOTIF_WARNING:     severity = "warning"; break;
-               case NOTIF_FAILURE:     severity = "critical"; break;
-               default:                severity = "unknown";
-       }
-       event->state = strdup (severity);
-
-       riemann_event_add_tag (event, "notification");
-       if (n->host[0] != 0)
-               riemann_event_add_attribute (event, "host", n->host);
-       if (n->plugin[0] != 0)
-               riemann_event_add_attribute (event, "plugin", n->plugin);
-       if (n->plugin_instance[0] != 0)
-               riemann_event_add_attribute (event, "plugin_instance",
-                               n->plugin_instance);
-
-       if (n->type[0] != 0)
-               riemann_event_add_attribute (event, "type", n->type);
-       if (n->type_instance[0] != 0)
-               riemann_event_add_attribute (event, "type_instance",
-                               n->type_instance);
-
-       for (i = 0; i < riemann_attrs_num; i += 2)
-               riemann_event_add_attribute(event,
-                                           riemann_attrs[i],
-                                           riemann_attrs[i +1]);
-
-       for (i = 0; i < riemann_tags_num; i++)
-               riemann_event_add_tag (event, riemann_tags[i]);
-
-       format_name (service_buffer, sizeof (service_buffer),
-                       /* host = */ "", n->plugin, n->plugin_instance,
-                       n->type, n->type_instance);
-       event->service = strdup (&service_buffer[1]);
-
-       if (n->message[0] != 0)
-               riemann_event_add_attribute (event, "description", n->message);
-
-       /* Pull in values from threshold and add extra attributes */
-       for (meta = n->meta; meta != NULL; meta = meta->next)
-       {
-               if (strcasecmp ("CurrentValue", meta->name) == 0 && meta->type == NM_TYPE_DOUBLE)
-               {
-                       event->metric_d = meta->nm_value.nm_double;
-                       event->has_metric_d = 1;
-                       continue;
-               }
-
-               if (meta->type == NM_TYPE_STRING) {
-                       riemann_event_add_attribute (event, meta->name, meta->nm_value.nm_string);
-                       continue;
-               }
-       }
-
-       DEBUG ("write_riemann plugin: Successfully created protobuf for notification: "
-                       "host = \"%s\", service = \"%s\", state = \"%s\"",
-                       event->host, event->service, event->state);
-       return (msg);
-} /* }}} Msg *riemann_notification_to_protobuf */
-
-static Event *riemann_value_to_protobuf(struct riemann_host const *host, /* {{{ */
-               data_set_t const *ds,
-               value_list_t const *vl, size_t index,
-                                        gauge_t const *rates,
-                                        int status)
-{
-       Event *event;
-       char name_buffer[5 * DATA_MAX_NAME_LEN];
-       char service_buffer[6 * DATA_MAX_NAME_LEN];
-       double ttl;
-       int i;
-
-       event = malloc (sizeof (*event));
-       if (event == NULL)
-       {
-               ERROR ("write_riemann plugin: malloc failed.");
-               return (NULL);
-       }
-       memset (event, 0, sizeof (*event));
-       event__init (event);
-
-       event->host = strdup (vl->host);
-       event->time = CDTIME_T_TO_TIME_T (vl->time);
-       event->has_time = 1;
-
-       if (host->check_thresholds) {
-               switch (status) {
-                       case STATE_OKAY:
-                               event->state = strdup("ok");
-                               break;
-                       case STATE_ERROR:
-                               event->state = strdup("critical");
-                               break;
-                       case STATE_WARNING:
-                               event->state = strdup("warning");
-                               break;
-                       case STATE_MISSING:
-                               event->state = strdup("unknown");
-                               break;
-               }
-       }
-
-       ttl = CDTIME_T_TO_DOUBLE (vl->interval) * host->ttl_factor;
-       event->ttl = (float) ttl;
-       event->has_ttl = 1;
-
-       riemann_event_add_attribute (event, "plugin", vl->plugin);
-       if (vl->plugin_instance[0] != 0)
-               riemann_event_add_attribute (event, "plugin_instance",
-                               vl->plugin_instance);
-
-       riemann_event_add_attribute (event, "type", vl->type);
-       if (vl->type_instance[0] != 0)
-               riemann_event_add_attribute (event, "type_instance",
-                               vl->type_instance);
-
-       if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL))
-       {
-               char ds_type[DATA_MAX_NAME_LEN];
-
-               ssnprintf (ds_type, sizeof (ds_type), "%s:rate",
-                               DS_TYPE_TO_STRING(ds->ds[index].type));
-               riemann_event_add_attribute (event, "ds_type", ds_type);
-       }
-       else
-       {
-               riemann_event_add_attribute (event, "ds_type",
-                               DS_TYPE_TO_STRING(ds->ds[index].type));
-       }
-       riemann_event_add_attribute (event, "ds_name", ds->ds[index].name);
-       {
-               char ds_index[DATA_MAX_NAME_LEN];
-
-               ssnprintf (ds_index, sizeof (ds_index), "%zu", index);
-               riemann_event_add_attribute (event, "ds_index", ds_index);
-       }
-
-       for (i = 0; i < riemann_attrs_num; i += 2)
-               riemann_event_add_attribute(event,
-                                           riemann_attrs[i],
-                                           riemann_attrs[i +1]);
-
-       for (i = 0; i < riemann_tags_num; i++)
-               riemann_event_add_tag (event, riemann_tags[i]);
-
-       if (ds->ds[index].type == DS_TYPE_GAUGE)
-       {
-               event->has_metric_d = 1;
-               event->metric_d = (double) vl->values[index].gauge;
-       }
-       else if (rates != NULL)
-       {
-               event->has_metric_d = 1;
-               event->metric_d = (double) rates[index];
-       }
-       else
-       {
-               event->has_metric_sint64 = 1;
-               if (ds->ds[index].type == DS_TYPE_DERIVE)
-                       event->metric_sint64 = (int64_t) vl->values[index].derive;
-               else if (ds->ds[index].type == DS_TYPE_ABSOLUTE)
-                       event->metric_sint64 = (int64_t) vl->values[index].absolute;
-               else
-                       event->metric_sint64 = (int64_t) vl->values[index].counter;
-       }
-
-       format_name (name_buffer, sizeof (name_buffer),
-                       /* host = */ "", vl->plugin, vl->plugin_instance,
-                       vl->type, vl->type_instance);
-       if (host->always_append_ds || (ds->ds_num > 1))
-       {
-               if (host->event_service_prefix == NULL)
-                       ssnprintf (service_buffer, sizeof (service_buffer), "%s/%s",
-                                       &name_buffer[1], ds->ds[index].name);
-               else
-                       ssnprintf (service_buffer, sizeof (service_buffer), "%s%s/%s",
-                                       host->event_service_prefix, &name_buffer[1], ds->ds[index].name);
-       }
-       else
-       {
-               if (host->event_service_prefix == NULL)
-                       sstrncpy (service_buffer, &name_buffer[1], sizeof (service_buffer));
-               else
-                       ssnprintf (service_buffer, sizeof (service_buffer), "%s%s",
-                                       host->event_service_prefix, &name_buffer[1]);
-       }
-
-       event->service = strdup (service_buffer);
-
-       DEBUG ("write_riemann plugin: Successfully created protobuf for metric: "
-                       "host = \"%s\", service = \"%s\"",
-                       event->host, event->service);
-       return (event);
-} /* }}} Event *riemann_value_to_protobuf */
-
-static Msg *riemann_value_list_to_protobuf (struct riemann_host const *host, /* {{{ */
-                                           data_set_t const *ds,
-                                           value_list_t const *vl,
-                                           int *statuses)
-{
-       Msg *msg;
-       size_t i;
-       gauge_t *rates = NULL;
-
-       /* Initialize the Msg structure. */
-       msg = malloc (sizeof (*msg));
-       if (msg == NULL)
-       {
-               ERROR ("write_riemann plugin: malloc failed.");
-               return (NULL);
-       }
-       memset (msg, 0, sizeof (*msg));
-       msg__init (msg);
-
-       /* Set up events. First, the list of pointers. */
-       msg->n_events = (size_t) vl->values_len;
-       msg->events = calloc (msg->n_events, sizeof (*msg->events));
-       if (msg->events == NULL)
-       {
-               ERROR ("write_riemann plugin: calloc failed.");
-               riemann_msg_protobuf_free (msg);
-               return (NULL);
-       }
-
-       if (host->store_rates)
-       {
-               rates = uc_get_rate (ds, vl);
-               if (rates == NULL)
-               {
-                       ERROR ("write_riemann plugin: uc_get_rate failed.");
-                       riemann_msg_protobuf_free (msg);
-                       return (NULL);
-               }
-       }
-
-       for (i = 0; i < msg->n_events; i++)
-       {
-               msg->events[i] = riemann_value_to_protobuf (host, ds, vl,
-                                                           (int) i, rates, statuses[i]);
-               if (msg->events[i] == NULL)
-               {
-                       riemann_msg_protobuf_free (msg);
-                       sfree (rates);
-                       return (NULL);
-               }
-       }
-
-       sfree (rates);
-       return (msg);
-} /* }}} Msg *riemann_value_list_to_protobuf */
+    event = wrr_value_to_event(host, ds, vl, (int)i, rates, statuses[i]);
+    if (event == NULL) {
+      riemann_message_free(msg);
+      sfree(rates);
+      return (NULL);
+    }
+    riemann_message_append_events(msg, event, NULL);
+  }
 
+  sfree(rates);
+  return (msg);
+} /* }}} riemann_message_t *wrr_value_list_to_message */
 
 /*
  * Always call while holding host->lock !
  */
-static int riemann_batch_flush_nolock (cdtime_t timeout,
-                                       struct riemann_host *host)
-{
-    cdtime_t    now;
-    int         status = 0;
-
-    if (timeout > 0) {
-        now = cdtime ();
-        if ((host->batch_init + timeout) > now)
-            return status;
+static int wrr_batch_flush_nolock(cdtime_t timeout, struct riemann_host *host) {
+  cdtime_t now;
+  int status = 0;
+
+  now = cdtime();
+  if (timeout > 0) {
+    if ((host->batch_init + timeout) > now) {
+      return status;
     }
-    riemann_send_msg(host, host->batch_msg);
-    riemann_msg_protobuf_free(host->batch_msg);
-
-       if (host->use_tcp && ((status = riemann_recv_ack(host)) != 0))
-        riemann_disconnect (host);
+  }
+  wrr_send_nolock(host, host->batch_msg);
+  riemann_message_free(host->batch_msg);
 
-    host->batch_init = cdtime();
-    host->batch_msg = NULL;
-    return status;
+  host->batch_init = now;
+  host->batch_msg = NULL;
+  return status;
 }
 
-static int riemann_batch_flush (cdtime_t timeout,
-        const char *identifier __attribute__((unused)),
-        user_data_t *user_data)
-{
-    struct riemann_host *host;
-    int status;
+static int wrr_batch_flush(cdtime_t timeout,
+                           const char *identifier __attribute__((unused)),
+                           user_data_t *user_data) {
+  struct riemann_host *host;
+  int status;
+
+  if (user_data == NULL)
+    return (-EINVAL);
+
+  host = user_data->data;
+  pthread_mutex_lock(&host->lock);
+  status = wrr_batch_flush_nolock(timeout, host);
+  if (status != 0)
+    c_complain(
+        LOG_ERR, &host->init_complaint,
+        "write_riemann plugin: riemann_client_send failed with status %i",
+        status);
+  else
+    c_release(LOG_DEBUG, &host->init_complaint,
+              "write_riemann plugin: batch sent.");
+
+  pthread_mutex_unlock(&host->lock);
+  return status;
+}
 
-    if (user_data == NULL)
-        return (-EINVAL);
+static int wrr_batch_add_value_list(struct riemann_host *host, /* {{{ */
+                                    data_set_t const *ds,
+                                    value_list_t const *vl, int *statuses) {
+  riemann_message_t *msg;
+  size_t len;
+  int ret;
+  cdtime_t timeout;
 
-    host = user_data->data;
-    pthread_mutex_lock (&host->lock);
-    status = riemann_batch_flush_nolock (timeout, host);
-    if (status != 0)
-        ERROR ("write_riemann plugin: riemann_send failed with status %i",
-               status);
+  msg = wrr_value_list_to_message(host, ds, vl, statuses);
+  if (msg == NULL)
+    return -1;
 
-    pthread_mutex_unlock(&host->lock);
-    return status;
-}
+  pthread_mutex_lock(&host->lock);
 
-static int riemann_batch_add_value_list (struct riemann_host *host, /* {{{ */
-                                         data_set_t const *ds,
-                                         value_list_t const *vl,
-                                         int *statuses)
-{
-       size_t i;
-    Event **events;
-    Msg *msg;
-    size_t len;
-    int ret;
+  if (host->batch_msg == NULL) {
+    host->batch_msg = msg;
+  } else {
+    int status;
 
-    msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
-    if (msg == NULL)
-        return -1;
+    status = riemann_message_append_events_n(host->batch_msg, msg->n_events,
+                                             msg->events);
+    msg->n_events = 0;
+    msg->events = NULL;
 
-    pthread_mutex_lock(&host->lock);
+    riemann_message_free(msg);
 
-    if (host->batch_msg == NULL) {
-        host->batch_msg = msg;
-    } else {
-        len = msg->n_events + host->batch_msg->n_events;
-        events = realloc(host->batch_msg->events,
-                         (len * sizeof(*host->batch_msg->events)));
-        if (events == NULL) {
-            pthread_mutex_unlock(&host->lock);
-            ERROR ("write_riemann plugin: out of memory");
-            riemann_msg_protobuf_free (msg);
-            return -1;
-        }
-        host->batch_msg->events = events;
-
-        for (i = host->batch_msg->n_events; i < len; i++)
-            host->batch_msg->events[i] = msg->events[i - host->batch_msg->n_events];
-
-        host->batch_msg->n_events = len;
-        sfree (msg->events);
-        msg->n_events = 0;
-        sfree (msg);
+    if (status != 0) {
+      pthread_mutex_unlock(&host->lock);
+      ERROR("write_riemann plugin: out of memory");
+      return -1;
     }
-
-       len = msg__get_packed_size(host->batch_msg);
-    ret = 0;
-    if (len >= host->batch_max) {
-        ret = riemann_batch_flush_nolock(0, host);
+  }
+
+  len = riemann_message_get_packed_size(host->batch_msg);
+  ret = 0;
+  if ((host->batch_max < 0) || (((size_t)host->batch_max) <= len)) {
+    ret = wrr_batch_flush_nolock(0, host);
+  } else {
+    if (host->batch_timeout > 0) {
+      timeout = TIME_T_TO_CDTIME_T((time_t)host->batch_timeout);
+      ret = wrr_batch_flush_nolock(timeout, host);
     }
+  }
 
-    pthread_mutex_unlock(&host->lock);
-    return ret;
-} /* }}} Msg *riemann_batch_add_value_list */
+  pthread_mutex_unlock(&host->lock);
+  return ret;
+} /* }}} riemann_message_t *wrr_batch_add_value_list */
 
-static int riemann_notification(const notification_t *n, user_data_t *ud) /* {{{ */
+static int wrr_notification(const notification_t *n, user_data_t *ud) /* {{{ */
 {
-       int                      status;
-       struct riemann_host     *host = ud->data;
-       Msg                     *msg;
-
-       if (!host->notifications)
-               return 0;
-
-    /*
-     * Never batch for notifications, send them ASAP
-     */
-       msg = riemann_notification_to_protobuf (host, n);
-       if (msg == NULL)
-               return (-1);
-
-       status = riemann_send (host, msg);
-       if (status != 0)
-               ERROR ("write_riemann plugin: riemann_send failed with status %i",
-                               status);
-
-       riemann_msg_protobuf_free (msg);
-       return (status);
-} /* }}} int riemann_notification */
-
-static int riemann_write(const data_set_t *ds, /* {{{ */
-             const value_list_t *vl,
-             user_data_t *ud)
-{
-       int                      status = 0;
-       int                      statuses[vl->values_len];
-       struct riemann_host     *host = ud->data;
-       Msg                     *msg;
+  int status;
+  struct riemann_host *host = ud->data;
+  riemann_message_t *msg;
+
+  if (!host->notifications)
+    return 0;
+
+  /*
+   * Never batch for notifications, send them ASAP
+   */
+  msg = wrr_notification_to_message(host, n);
+  if (msg == NULL)
+    return (-1);
+
+  status = wrr_send(host, msg);
+  if (status != 0)
+    c_complain(
+        LOG_ERR, &host->init_complaint,
+        "write_riemann plugin: riemann_client_send failed with status %i",
+        status);
+  else
+    c_release(LOG_DEBUG, &host->init_complaint,
+              "write_riemann plugin: riemann_client_send succeeded");
+
+  riemann_message_free(msg);
+  return (status);
+} /* }}} int wrr_notification */
+
+static int wrr_write(const data_set_t *ds, /* {{{ */
+                     const value_list_t *vl, user_data_t *ud) {
+  int status = 0;
+  int statuses[vl->values_len];
+  struct riemann_host *host = ud->data;
+  riemann_message_t *msg;
+
+  if (host->check_thresholds) {
+    status = write_riemann_threshold_check(ds, vl, statuses);
+    if (status != 0)
+      return status;
+  } else {
+    memset(statuses, 0, sizeof(statuses));
+  }
+
+  if (host->client_type != RIEMANN_CLIENT_UDP && host->batch_mode) {
+    wrr_batch_add_value_list(host, ds, vl, statuses);
+  } else {
+    msg = wrr_value_list_to_message(host, ds, vl, statuses);
+    if (msg == NULL)
+      return (-1);
 
-       if (host->check_thresholds)
-               write_riemann_threshold_check(ds, vl, statuses);
+    status = wrr_send(host, msg);
 
-    if (host->use_tcp == 1 && host->batch_mode) {
+    riemann_message_free(msg);
+  }
+  return status;
+} /* }}} int wrr_write */
 
-        riemann_batch_add_value_list (host, ds, vl, statuses);
+static void wrr_free(void *p) /* {{{ */
+{
+  struct riemann_host *host = p;
 
+  if (host == NULL)
+    return;
 
-    } else {
+  pthread_mutex_lock(&host->lock);
 
-        msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
-        if (msg == NULL)
-            return (-1);
+  host->reference_count--;
+  if (host->reference_count > 0) {
+    pthread_mutex_unlock(&host->lock);
+    return;
+  }
 
-        status = riemann_send (host, msg);
-        if (status != 0)
-            ERROR ("write_riemann plugin: riemann_send failed with status %i",
-                   status);
+  wrr_disconnect(host);
 
-        riemann_msg_protobuf_free (msg);
-    }
-       return status;
-} /* }}} int riemann_write */
+  pthread_mutex_destroy(&host->lock);
+  sfree(host);
+} /* }}} void wrr_free */
 
-static void riemann_free(void *p) /* {{{ */
+static int wrr_config_node(oconfig_item_t *ci) /* {{{ */
 {
-       struct riemann_host     *host = p;
-
-       if (host == NULL)
-               return;
-
-       pthread_mutex_lock (&host->lock);
-
-       host->reference_count--;
-       if (host->reference_count > 0)
-       {
-               pthread_mutex_unlock (&host->lock);
-               return;
-       }
+  struct riemann_host *host = NULL;
+  int status = 0;
+  int i;
+  oconfig_item_t *child;
+  char callback_name[DATA_MAX_NAME_LEN];
+  user_data_t ud;
+
+  if ((host = calloc(1, sizeof(*host))) == NULL) {
+    ERROR("write_riemann plugin: calloc failed.");
+    return ENOMEM;
+  }
+  pthread_mutex_init(&host->lock, NULL);
+  C_COMPLAIN_INIT(&host->init_complaint);
+  host->reference_count = 1;
+  host->node = NULL;
+  host->port = 0;
+  host->notifications = 1;
+  host->check_thresholds = 0;
+  host->store_rates = 1;
+  host->always_append_ds = 0;
+  host->batch_mode = 1;
+  host->batch_max = RIEMANN_BATCH_MAX; /* typical MSS */
+  host->batch_init = cdtime();
+  host->batch_timeout = 0;
+  host->ttl_factor = RIEMANN_TTL_FACTOR;
+  host->client = NULL;
+  host->client_type = RIEMANN_CLIENT_TCP;
+  host->timeout.tv_sec = 0;
+  host->timeout.tv_usec = 0;
+
+  status = cf_util_get_string(ci, &host->name);
+  if (status != 0) {
+    WARNING("write_riemann plugin: Required host name is missing.");
+    wrr_free(host);
+    return -1;
+  }
+
+  for (i = 0; i < ci->children_num; i++) {
+    /*
+     * The code here could be simplified but makes room
+     * for easy adding of new options later on.
+     */
+    child = &ci->children[i];
+    status = 0;
+
+    if (strcasecmp("Host", child->key) == 0) {
+      status = cf_util_get_string(child, &host->node);
+      if (status != 0)
+        break;
+    } else if (strcasecmp("Notifications", child->key) == 0) {
+      status = cf_util_get_boolean(child, &host->notifications);
+      if (status != 0)
+        break;
+    } else if (strcasecmp("EventServicePrefix", child->key) == 0) {
+      status = cf_util_get_string(child, &host->event_service_prefix);
+      if (status != 0)
+        break;
+    } else if (strcasecmp("CheckThresholds", child->key) == 0) {
+      status = cf_util_get_boolean(child, &host->check_thresholds);
+      if (status != 0)
+        break;
+    } else if (strcasecmp("Batch", child->key) == 0) {
+      status = cf_util_get_boolean(child, &host->batch_mode);
+      if (status != 0)
+        break;
+    } else if (strcasecmp("BatchMaxSize", child->key) == 0) {
+      status = cf_util_get_int(child, &host->batch_max);
+      if (status != 0)
+        break;
+    } else if (strcasecmp("BatchFlushTimeout", child->key) == 0) {
+      status = cf_util_get_int(child, &host->batch_timeout);
+      if (status != 0)
+        break;
+    } else if (strcasecmp("Timeout", child->key) == 0) {
+      status = cf_util_get_int(child, (int *)&host->timeout.tv_sec);
+      if (status != 0)
+        break;
+    } else if (strcasecmp("Port", child->key) == 0) {
+      host->port = cf_util_get_port_number(child);
+      if (host->port == -1) {
+        ERROR("write_riemann plugin: Invalid argument "
+              "configured for the \"Port\" "
+              "option.");
+        break;
+      }
+    } else if (strcasecmp("Protocol", child->key) == 0) {
+      char tmp[16];
+      status = cf_util_get_string_buffer(child, tmp, sizeof(tmp));
+      if (status != 0) {
+        ERROR("write_riemann plugin: cf_util_get_"
+              "string_buffer failed with "
+              "status %i.",
+              status);
+        break;
+      }
+
+      if (strcasecmp("UDP", tmp) == 0)
+        host->client_type = RIEMANN_CLIENT_UDP;
+      else if (strcasecmp("TCP", tmp) == 0)
+        host->client_type = RIEMANN_CLIENT_TCP;
+      else if (strcasecmp("TLS", tmp) == 0)
+        host->client_type = RIEMANN_CLIENT_TLS;
+      else
+        WARNING("write_riemann plugin: The value "
+                "\"%s\" is not valid for the "
+                "\"Protocol\" option. Use "
+                "either \"UDP\", \"TCP\" or \"TLS\".",
+                tmp);
+    } else if (strcasecmp("TLSCAFile", child->key) == 0) {
+      status = cf_util_get_string(child, &host->tls_ca_file);
+      if (status != 0) {
+        ERROR("write_riemann plugin: cf_util_get_"
+              "string_buffer failed with "
+              "status %i.",
+              status);
+        break;
+      }
+    } else if (strcasecmp("TLSCertFile", child->key) == 0) {
+      status = cf_util_get_string(child, &host->tls_cert_file);
+      if (status != 0) {
+        ERROR("write_riemann plugin: cf_util_get_"
+              "string_buffer failed with "
+              "status %i.",
+              status);
+        break;
+      }
+    } else if (strcasecmp("TLSKeyFile", child->key) == 0) {
+      status = cf_util_get_string(child, &host->tls_key_file);
+      if (status != 0) {
+        ERROR("write_riemann plugin: cf_util_get_"
+              "string_buffer failed with "
+              "status %i.",
+              status);
+        break;
+      }
+    } else if (strcasecmp("StoreRates", child->key) == 0) {
+      status = cf_util_get_boolean(child, &host->store_rates);
+      if (status != 0)
+        break;
+    } else if (strcasecmp("AlwaysAppendDS", child->key) == 0) {
+      status = cf_util_get_boolean(child, &host->always_append_ds);
+      if (status != 0)
+        break;
+    } else if (strcasecmp("TTLFactor", child->key) == 0) {
+      double tmp = NAN;
+      status = cf_util_get_double(child, &tmp);
+      if (status != 0)
+        break;
+      if (tmp >= 2.0) {
+        host->ttl_factor = tmp;
+      } else if (tmp >= 1.0) {
+        NOTICE("write_riemann plugin: The configured "
+               "TTLFactor is very small "
+               "(%.1f). A value of 2.0 or "
+               "greater is recommended.",
+               tmp);
+        host->ttl_factor = tmp;
+      } else if (tmp > 0.0) {
+        WARNING("write_riemann plugin: The configured "
+                "TTLFactor is too small to be "
+                "useful (%.1f). I'll use it "
+                "since the user knows best, "
+                "but under protest.",
+                tmp);
+        host->ttl_factor = tmp;
+      } else { /* zero, negative and NAN */
+        ERROR("write_riemann plugin: The configured "
+              "TTLFactor is invalid (%.1f).",
+              tmp);
+      }
+    } else {
+      WARNING("write_riemann plugin: ignoring unknown config "
+              "option: \"%s\"",
+              child->key);
+    }
+  }
+  if (status != 0) {
+    wrr_free(host);
+    return status;
+  }
+
+  ssnprintf(callback_name, sizeof(callback_name), "write_riemann/%s",
+            host->name);
+  ud.data = host;
+  ud.free_func = wrr_free;
+
+  pthread_mutex_lock(&host->lock);
+
+  status = plugin_register_write(callback_name, wrr_write, &ud);
+
+  if (host->client_type != RIEMANN_CLIENT_UDP && host->batch_mode) {
+    ud.free_func = NULL;
+    plugin_register_flush(callback_name, wrr_batch_flush, &ud);
+  }
+  if (status != 0)
+    WARNING("write_riemann plugin: plugin_register_write (\"%s\") "
+            "failed with status %i.",
+            callback_name, status);
+  else /* success */
+    host->reference_count++;
+
+  status = plugin_register_notification(callback_name, wrr_notification, &ud);
+  if (status != 0)
+    WARNING("write_riemann plugin: plugin_register_notification (\"%s\") "
+            "failed with status %i.",
+            callback_name, status);
+  else /* success */
+    host->reference_count++;
+
+  if (host->reference_count <= 1) {
+    /* Both callbacks failed => free memory.
+     * We need to unlock here, because riemann_free() will lock.
+     * This is not a race condition, because we're the only one
+     * holding a reference. */
+    pthread_mutex_unlock(&host->lock);
+    wrr_free(host);
+    return (-1);
+  }
 
-       riemann_disconnect (host);
+  host->reference_count--;
+  pthread_mutex_unlock(&host->lock);
 
-       sfree(host->service);
-       pthread_mutex_destroy (&host->lock);
-       sfree(host);
-} /* }}} void riemann_free */
+  return status;
+} /* }}} int wrr_config_node */
 
-static int riemann_config_node(oconfig_item_t *ci) /* {{{ */
+static int wrr_config(oconfig_item_t *ci) /* {{{ */
 {
-       struct riemann_host     *host = NULL;
-       int                      status = 0;
-       int                      i;
-       oconfig_item_t          *child;
-       char                     callback_name[DATA_MAX_NAME_LEN];
-       user_data_t              ud;
-
-       if ((host = calloc(1, sizeof (*host))) == NULL) {
-               ERROR ("write_riemann plugin: calloc failed.");
-               return ENOMEM;
-       }
-       pthread_mutex_init (&host->lock, NULL);
-       host->reference_count = 1;
-       host->node = NULL;
-       host->service = NULL;
-       host->notifications = 1;
-       host->check_thresholds = 0;
-       host->store_rates = 1;
-       host->always_append_ds = 0;
-       host->use_tcp = 1;
-       host->batch_mode = 1;
-       host->batch_max = RIEMANN_BATCH_MAX; /* typical MSS */
-       host->batch_init = cdtime();
-       host->ttl_factor = RIEMANN_TTL_FACTOR;
-
-       status = cf_util_get_string (ci, &host->name);
-       if (status != 0) {
-               WARNING("write_riemann plugin: Required host name is missing.");
-               riemann_free (host);
-               return -1;
-       }
-
-       for (i = 0; i < ci->children_num; i++) {
-               /*
-                * The code here could be simplified but makes room
-                * for easy adding of new options later on.
-                */
-               child = &ci->children[i];
-               status = 0;
-
-               if (strcasecmp ("Host", child->key) == 0) {
-                       status = cf_util_get_string (child, &host->node);
-                       if (status != 0)
-                               break;
-               } else if (strcasecmp ("Notifications", child->key) == 0) {
-                       status = cf_util_get_boolean(child, &host->notifications);
-                       if (status != 0)
-                               break;
-               } else if (strcasecmp ("EventServicePrefix", child->key) == 0) {
-                       status = cf_util_get_string (child, &host->event_service_prefix);
-                       if (status != 0)
-                               break;
-               } else if (strcasecmp ("CheckThresholds", child->key) == 0) {
-                       status = cf_util_get_boolean(child, &host->check_thresholds);
-                       if (status != 0)
-                               break;
-        } else if (strcasecmp ("Batch", child->key) == 0) {
-            status = cf_util_get_boolean(child, &host->batch_mode);
-            if (status != 0)
-                break;
-        } else if (strcasecmp("BatchMaxSize", child->key) == 0) {
-            status = cf_util_get_int(child, &host->batch_max);
-            if (status != 0)
-                break;
-               } else if (strcasecmp ("Port", child->key) == 0) {
-                       status = cf_util_get_service (child, &host->service);
-                       if (status != 0) {
-                               ERROR ("write_riemann plugin: Invalid argument "
-                                               "configured for the \"Port\" "
-                                               "option.");
-                               break;
-                       }
-               } else if (strcasecmp ("Protocol", child->key) == 0) {
-                       char tmp[16];
-                       status = cf_util_get_string_buffer (child,
-                                       tmp, sizeof (tmp));
-                       if (status != 0)
-                       {
-                               ERROR ("write_riemann plugin: cf_util_get_"
-                                               "string_buffer failed with "
-                                               "status %i.", status);
-                               break;
-                       }
-
-                       if (strcasecmp ("UDP", tmp) == 0)
-                               host->use_tcp = 0;
-                       else if (strcasecmp ("TCP", tmp) == 0)
-                               host->use_tcp = 1;
-                       else
-                               WARNING ("write_riemann plugin: The value "
-                                               "\"%s\" is not valid for the "
-                                               "\"Protocol\" option. Use "
-                                               "either \"UDP\" or \"TCP\".",
-                                               tmp);
-               } else if (strcasecmp ("StoreRates", child->key) == 0) {
-                       status = cf_util_get_boolean (child, &host->store_rates);
-                       if (status != 0)
-                               break;
-               } else if (strcasecmp ("AlwaysAppendDS", child->key) == 0) {
-                       status = cf_util_get_boolean (child,
-                                       &host->always_append_ds);
-                       if (status != 0)
-                               break;
-               } else if (strcasecmp ("TTLFactor", child->key) == 0) {
-                       double tmp = NAN;
-                       status = cf_util_get_double (child, &tmp);
-                       if (status != 0)
-                               break;
-                       if (tmp >= 2.0) {
-                               host->ttl_factor = tmp;
-                       } else if (tmp >= 1.0) {
-                               NOTICE ("write_riemann plugin: The configured "
-                                               "TTLFactor is very small "
-                                               "(%.1f). A value of 2.0 or "
-                                               "greater is recommended.",
-                                               tmp);
-                               host->ttl_factor = tmp;
-                       } else if (tmp > 0.0) {
-                               WARNING ("write_riemann plugin: The configured "
-                                               "TTLFactor is too small to be "
-                                               "useful (%.1f). I'll use it "
-                                               "since the user knows best, "
-                                               "but under protest.",
-                                               tmp);
-                               host->ttl_factor = tmp;
-                       } else { /* zero, negative and NAN */
-                               ERROR ("write_riemann plugin: The configured "
-                                               "TTLFactor is invalid (%.1f).",
-                                               tmp);
-                       }
-               } else {
-                       WARNING("write_riemann plugin: ignoring unknown config "
-                               "option: \"%s\"", child->key);
-               }
-       }
-       if (status != 0) {
-               riemann_free (host);
-               return status;
-       }
-
-       ssnprintf (callback_name, sizeof (callback_name), "write_riemann/%s",
-                       host->name);
-       ud.data = host;
-       ud.free_func = riemann_free;
-
-       pthread_mutex_lock (&host->lock);
-
-       status = plugin_register_write (callback_name, riemann_write, &ud);
-
-    if (host->use_tcp == 1 && host->batch_mode) {
-        ud.free_func = NULL;
-        plugin_register_flush(callback_name, riemann_batch_flush, &ud);
+  int i;
+  oconfig_item_t *child;
+  int status;
+
+  for (i = 0; i < ci->children_num; i++) {
+    child = &ci->children[i];
+
+    if (strcasecmp("Node", child->key) == 0) {
+      wrr_config_node(child);
+    } else if (strcasecmp(child->key, "attribute") == 0) {
+      char *key = NULL;
+      char *val = NULL;
+
+      if (child->values_num != 2) {
+        WARNING("riemann attributes need both a key and a value.");
+        return (-1);
+      }
+      if (child->values[0].type != OCONFIG_TYPE_STRING ||
+          child->values[1].type != OCONFIG_TYPE_STRING) {
+        WARNING("riemann attribute needs string arguments.");
+        return (-1);
+      }
+      if ((key = strdup(child->values[0].value.string)) == NULL) {
+        WARNING("cannot allocate memory for attribute key.");
+        return (-1);
+      }
+      if ((val = strdup(child->values[1].value.string)) == NULL) {
+        WARNING("cannot allocate memory for attribute value.");
+        sfree(key);
+        return (-1);
+      }
+      strarray_add(&riemann_attrs, &riemann_attrs_num, key);
+      strarray_add(&riemann_attrs, &riemann_attrs_num, val);
+      DEBUG("write_riemann: got attr: %s => %s", key, val);
+      sfree(key);
+      sfree(val);
+    } else if (strcasecmp(child->key, "tag") == 0) {
+      char *tmp = NULL;
+      status = cf_util_get_string(child, &tmp);
+      if (status != 0)
+        continue;
+
+      strarray_add(&riemann_tags, &riemann_tags_num, tmp);
+      DEBUG("write_riemann plugin: Got tag: %s", tmp);
+      sfree(tmp);
+    } else {
+      WARNING("write_riemann plugin: Ignoring unknown "
+              "configuration option \"%s\" at top level.",
+              child->key);
     }
-       if (status != 0)
-               WARNING ("write_riemann plugin: plugin_register_write (\"%s\") "
-                               "failed with status %i.",
-                               callback_name, status);
-       else /* success */
-               host->reference_count++;
-
-       status = plugin_register_notification (callback_name,
-                       riemann_notification, &ud);
-       if (status != 0)
-               WARNING ("write_riemann plugin: plugin_register_notification (\"%s\") "
-                               "failed with status %i.",
-                               callback_name, status);
-       else /* success */
-               host->reference_count++;
-
-       if (host->reference_count <= 1)
-       {
-               /* Both callbacks failed => free memory.
-                * We need to unlock here, because riemann_free() will lock.
-                * This is not a race condition, because we're the only one
-                * holding a reference. */
-               pthread_mutex_unlock (&host->lock);
-               riemann_free (host);
-               return (-1);
-       }
-
-       host->reference_count--;
-       pthread_mutex_unlock (&host->lock);
-
-       return status;
-} /* }}} int riemann_config_node */
-
-static int riemann_config(oconfig_item_t *ci) /* {{{ */
-{
-       int              i;
-       oconfig_item_t  *child;
-       int              status;
-
-       for (i = 0; i < ci->children_num; i++)  {
-               child = &ci->children[i];
-
-               if (strcasecmp("Node", child->key) == 0) {
-                       riemann_config_node (child);
-               } else if (strcasecmp(child->key, "attribute") == 0) {
-                       char *key = NULL;
-                       char *val = NULL;
-
-                       if (child->values_num != 2) {
-                               WARNING("riemann attributes need both a key and a value.");
-                               return (-1);
-                       }
-                       if (child->values[0].type != OCONFIG_TYPE_STRING ||
-                           child->values[1].type != OCONFIG_TYPE_STRING) {
-                               WARNING("riemann attribute needs string arguments.");
-                               return (-1);
-                       }
-                       if ((key = strdup(child->values[0].value.string)) == NULL) {
-                               WARNING("cannot allocate memory for attribute key.");
-                               return (-1);
-                       }
-                       if ((val = strdup(child->values[1].value.string)) == NULL) {
-                               WARNING("cannot allocate memory for attribute value.");
-                               sfree (key);
-                               return (-1);
-                       }
-                       strarray_add(&riemann_attrs, &riemann_attrs_num, key);
-                       strarray_add(&riemann_attrs, &riemann_attrs_num, val);
-                       DEBUG("write_riemann: got attr: %s => %s", key, val);
-                       sfree(key);
-                       sfree(val);
-               } else if (strcasecmp(child->key, "tag") == 0) {
-                       char *tmp = NULL;
-                       status = cf_util_get_string(child, &tmp);
-                       if (status != 0)
-                               continue;
-
-                       strarray_add (&riemann_tags, &riemann_tags_num, tmp);
-                       DEBUG("write_riemann plugin: Got tag: %s", tmp);
-                       sfree (tmp);
-               } else {
-                       WARNING ("write_riemann plugin: Ignoring unknown "
-                                "configuration option \"%s\" at top level.",
-                                child->key);
-               }
-       }
-       return (0);
-} /* }}} int riemann_config */
-
-void module_register(void)
-{
-       plugin_register_complex_config ("write_riemann", riemann_config);
+  }
+  return (0);
+} /* }}} int wrr_config */
+
+void module_register(void) {
+  plugin_register_complex_config("write_riemann", wrr_config);
 }
 
 /* vim: set sw=8 sts=8 ts=8 noet : */
index b1f7297..f2ba9dc 100644 (file)
  *   Andrés J. Díaz <ajdiaz at connectical.com>
  **/
 
-#include <assert.h>
-#include <ltdl.h>
-#include <pthread.h>
-
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_avltree.h"
@@ -134,7 +131,6 @@ static int ut_check_one_threshold (const data_set_t *ds,
     int *statuses)
 { /* {{{ */
   int ret = -1;
-  int i;
   int status;
   gauge_t values_copy[ds->ds_num];
 
@@ -154,7 +150,7 @@ static int ut_check_one_threshold (const data_set_t *ds,
     }
 
     /* Prepare `sum' and `num'. */
-    for (i = 0; i < ds->ds_num; i++)
+    for (size_t i = 0; i < ds->ds_num; i++)
       if (!isnan (values[i]))
       {
         num++;
@@ -164,17 +160,17 @@ static int ut_check_one_threshold (const data_set_t *ds,
     if ((num == 0) /* All data sources are undefined. */
         || (sum == 0.0)) /* Sum is zero, cannot calculate percentage. */
     {
-      for (i = 0; i < ds->ds_num; i++)
+      for (size_t i = 0; i < ds->ds_num; i++)
         values_copy[i] = NAN;
     }
     else /* We can actually calculate the percentage. */
     {
-      for (i = 0; i < ds->ds_num; i++)
+      for (size_t i = 0; i < ds->ds_num; i++)
         values_copy[i] = 100.0 * values[i] / sum;
     }
   } /* if (UT_FLAG_PERCENTAGE) */
 
-  for (i = 0; i < ds->ds_num; i++)
+  for (size_t i = 0; i < ds->ds_num; i++)
   {
     status = ut_check_one_data_source (ds, vl, th, values_copy, i);
     if (status != -1) {
@@ -203,7 +199,9 @@ int write_riemann_threshold_check (const data_set_t *ds, const value_list_t *vl,
   gauge_t *values;
   int status;
 
+  assert (vl->values_len > 0);
   memset(statuses, 0, vl->values_len * sizeof(*statuses));
+
   if (threshold_tree == NULL)
          return 0;
 
index 0d568fe..6cb4994 100644 (file)
 #define _GNU_SOURCE
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "configfile.h"
 #include "utils_cache.h"
-#include <sys/socket.h>
 #include <arpa/inet.h>
 #include <errno.h>
 #include <netdb.h>
 #include <inttypes.h>
-#include <pthread.h>
 #include <stddef.h>
 
 #include <stdlib.h>
 #define SENSU_HOST             "localhost"
 #define SENSU_PORT             "3030"
 
+#ifdef HAVE_ASPRINTF
+#define my_asprintf asprintf
+#define my_vasprintf vasprintf
+#else
+/*
+ * asprintf() is available from Solaris 10 update 11.
+ * For older versions, use asprintf() portable implementation from
+ * https://github.com/littlstar/asprintf.c/blob/master/
+ * copyright (c) 2014 joseph werle <joseph.werle@gmail.com> under MIT license.
+ */
+
+static int my_vasprintf(char **str, const char *fmt, va_list args) {
+       int size = 0;
+       va_list tmpa;
+       // copy
+       va_copy(tmpa, args);
+       // apply variadic arguments to
+       // sprintf with format to get size
+       size = vsnprintf(NULL, size, fmt, tmpa);
+       // toss args
+       va_end(tmpa);
+       // return -1 to be compliant if
+       // size is less than 0
+       if (size < 0) { return -1; }
+       // alloc with size plus 1 for `\0'
+       *str = (char *) malloc(size + 1);
+       // return -1 to be compliant
+       // if pointer is `NULL'
+       if (NULL == *str) { return -1; }
+       // format string with original
+       // variadic arguments and set new size
+       size = vsprintf(*str, fmt, args);
+       return size;
+}
+
+static int my_asprintf(char **str, const char *fmt, ...) {
+       int size = 0;
+       va_list args;
+       // init variadic argumens
+       va_start(args, fmt);
+       // format and get size
+       size = my_vasprintf(str, fmt, args);
+       // toss args
+       va_end(args);
+       return size;
+}
+
+#endif
+
 struct str_list {
        int nb_strs;
        char **strs;
@@ -96,8 +144,7 @@ static int add_str_to_list(struct str_list *strs,
 
 static void free_str_list(struct str_list *strs) /* {{{ */
 {
-       int i;
-       for (i=0; i<strs->nb_strs; i++)
+       for (int i=0; i<strs->nb_strs; i++)
                free(strs->strs[i]);
        free(strs->strs);
 }
@@ -106,25 +153,24 @@ static void free_str_list(struct str_list *strs) /* {{{ */
 static int sensu_connect(struct sensu_host *host) /* {{{ */
 {
        int                      e;
-       struct addrinfo         *ai, hints;
        char const              *node;
        char const              *service;
 
        // Resolve the target if we haven't done already
        if (!(host->flags & F_READY)) {
-               memset(&hints, 0, sizeof(hints));
                memset(&service, 0, sizeof(service));
                host->res = NULL;
-               hints.ai_family = AF_INET;
-               hints.ai_socktype = SOCK_STREAM;
-#ifdef AI_ADDRCONFIG
-               hints.ai_flags |= AI_ADDRCONFIG;
-#endif
 
                node = (host->node != NULL) ? host->node : SENSU_HOST;
                service = (host->service != NULL) ? host->service : SENSU_PORT;
 
-               if ((e = getaddrinfo(node, service, &hints, &(host->res))) != 0) {
+               struct addrinfo ai_hints = {
+                       .ai_family = AF_INET,
+                       .ai_flags = AI_ADDRCONFIG,
+                       .ai_socktype = SOCK_STREAM
+               };
+
+               if ((e = getaddrinfo(node, service, &ai_hints, &(host->res))) != 0) {
                        ERROR("write_sensu plugin: Unable to resolve host \"%s\": %s",
                                        node, gai_strerror(e));
                        return -1;
@@ -136,7 +182,7 @@ static int sensu_connect(struct sensu_host *host) /* {{{ */
 
        struct linger so_linger;
        host->s = -1;
-       for (ai = host->res; ai != NULL; ai = ai->ai_next) {
+       for (struct addrinfo *ai = host->res; ai != NULL; ai = ai->ai_next) {
                // create the socket
                if ((host->s = socket(ai->ai_family,
                                      ai->ai_socktype,
@@ -150,6 +196,8 @@ static int sensu_connect(struct sensu_host *host) /* {{{ */
                if (setsockopt(host->s, SOL_SOCKET, SO_LINGER, &so_linger, sizeof so_linger) != 0)
                        WARNING("write_sensu plugin: failed to set socket close() lingering");
 
+               set_sock_opts(host->s);
+
                // connect the socket
                if (connect(host->s, ai->ai_addr, ai->ai_addrlen) != 0) {
                        close(host->s);
@@ -178,9 +226,8 @@ static void sensu_close_socket(struct sensu_host *host) /* {{{ */
 static char *build_json_str_list(const char *tag, struct str_list const *list) /* {{{ */
 {
        int res;
-       char *ret_str;
+       char *ret_str = NULL;
        char *temp_str;
-       int i;
        if (list->nb_strs == 0) {
                ret_str = malloc(sizeof(char));
                if (ret_str == NULL) {
@@ -190,13 +237,14 @@ static char *build_json_str_list(const char *tag, struct str_list const *list) /
                ret_str[0] = '\0';
        }
 
-       res = asprintf(&temp_str, "\"%s\": [\"%s\"", tag, list->strs[0]);
+       res = my_asprintf(&temp_str, "\"%s\": [\"%s\"", tag, list->strs[0]);
        if (res == -1) {
                ERROR("write_sensu plugin: Unable to alloc memory");
+               free(ret_str);
                return NULL;
        }
-       for (i=1; i<list->nb_strs; i++) {
-               res = asprintf(&ret_str, "%s, \"%s\"", temp_str, list->strs[i]);
+       for (int i=1; i<list->nb_strs; i++) {
+               res = my_asprintf(&ret_str, "%s, \"%s\"", temp_str, list->strs[i]);
                free(temp_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -204,7 +252,7 @@ static char *build_json_str_list(const char *tag, struct str_list const *list) /
                }
                temp_str = ret_str;
        }
-       res = asprintf(&ret_str, "%s]", temp_str);
+       res = my_asprintf(&ret_str, "%s]", temp_str);
        free(temp_str);
        if (res == -1) {
                ERROR("write_sensu plugin: Unable to alloc memory");
@@ -261,9 +309,8 @@ static int sensu_format_name2(char *ret, int ret_len,
 
 static void in_place_replace_sensu_name_reserved(char *orig_name) /* {{{ */
 {
-       int i;
        int len=strlen(orig_name);
-       for (i=0; i<len; i++) {
+       for (int i=0; i<len; i++) {
                // some plugins like ipmi generate special characters in metric name
                switch(orig_name[i]) {
                        case '(': orig_name[i] = '_'; break;
@@ -284,7 +331,6 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
 {
        char name_buffer[5 * DATA_MAX_NAME_LEN];
        char service_buffer[6 * DATA_MAX_NAME_LEN];
-       int i;
        char *ret_str;
        char *temp_str;
        char *value_str;
@@ -308,7 +354,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
                }
        }
        else {
-               res = asprintf(&ret_str, "%s, %s", part1, handlers_str);
+               res = my_asprintf(&ret_str, "%s, %s", part1, handlers_str);
                free(handlers_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -317,7 +363,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
        }
 
        // incorporate the plugin name information
-       res = asprintf(&temp_str, "%s, \"collectd_plugin\": \"%s\"", ret_str, vl->plugin);
+       res = my_asprintf(&temp_str, "%s, \"collectd_plugin\": \"%s\"", ret_str, vl->plugin);
        free(ret_str);
        if (res == -1) {
                ERROR("write_sensu plugin: Unable to alloc memory");
@@ -326,7 +372,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
        ret_str = temp_str;
 
        // incorporate the plugin type
-       res = asprintf(&temp_str, "%s, \"collectd_plugin_type\": \"%s\"", ret_str, vl->type);
+       res = my_asprintf(&temp_str, "%s, \"collectd_plugin_type\": \"%s\"", ret_str, vl->type);
        free(ret_str);
        if (res == -1) {
                ERROR("write_sensu plugin: Unable to alloc memory");
@@ -336,7 +382,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
 
        // incorporate the plugin instance if any
        if (vl->plugin_instance[0] != 0) {
-               res = asprintf(&temp_str, "%s, \"collectd_plugin_instance\": \"%s\"", ret_str, vl->plugin_instance);
+               res = my_asprintf(&temp_str, "%s, \"collectd_plugin_instance\": \"%s\"", ret_str, vl->plugin_instance);
                free(ret_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -347,7 +393,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
 
        // incorporate the plugin type instance if any
        if (vl->type_instance[0] != 0) {
-               res = asprintf(&temp_str, "%s, \"collectd_plugin_type_instance\": \"%s\"", ret_str, vl->type_instance);
+               res = my_asprintf(&temp_str, "%s, \"collectd_plugin_type_instance\": \"%s\"", ret_str, vl->type_instance);
                free(ret_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -360,7 +406,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
        if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL)) {
                char ds_type[DATA_MAX_NAME_LEN];
                ssnprintf (ds_type, sizeof (ds_type), "%s:rate", DS_TYPE_TO_STRING(ds->ds[index].type));
-               res = asprintf(&temp_str, "%s, \"collectd_data_source_type\": \"%s\"", ret_str, ds_type);
+               res = my_asprintf(&temp_str, "%s, \"collectd_data_source_type\": \"%s\"", ret_str, ds_type);
                free(ret_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -368,7 +414,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
                }
                ret_str = temp_str;
        } else {
-               res = asprintf(&temp_str, "%s, \"collectd_data_source_type\": \"%s\"", ret_str, DS_TYPE_TO_STRING(ds->ds[index].type));
+               res = my_asprintf(&temp_str, "%s, \"collectd_data_source_type\": \"%s\"", ret_str, DS_TYPE_TO_STRING(ds->ds[index].type));
                free(ret_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -378,7 +424,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
        }
 
        // incorporate the data source name
-       res = asprintf(&temp_str, "%s, \"collectd_data_source_name\": \"%s\"", ret_str, ds->ds[index].name);
+       res = my_asprintf(&temp_str, "%s, \"collectd_data_source_name\": \"%s\"", ret_str, ds->ds[index].name);
        free(ret_str);
        if (res == -1) {
                ERROR("write_sensu plugin: Unable to alloc memory");
@@ -390,7 +436,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
        {
                char ds_index[DATA_MAX_NAME_LEN];
                ssnprintf (ds_index, sizeof (ds_index), "%zu", index);
-               res = asprintf(&temp_str, "%s, \"collectd_data_source_index\": %s", ret_str, ds_index);
+               res = my_asprintf(&temp_str, "%s, \"collectd_data_source_index\": %s", ret_str, ds_index);
                free(ret_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -400,8 +446,8 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
        }
 
        // add key value attributes from config if any
-       for (i = 0; i < sensu_attrs_num; i += 2) {
-               res = asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, sensu_attrs[i], sensu_attrs[i+1]);
+       for (size_t i = 0; i < sensu_attrs_num; i += 2) {
+               res = my_asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, sensu_attrs[i], sensu_attrs[i+1]);
                free(ret_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -412,7 +458,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
 
        // incorporate sensu tags from config if any
        if ((sensu_tags != NULL) && (strlen(sensu_tags) != 0)) {
-               res = asprintf(&temp_str, "%s, %s", ret_str, sensu_tags);
+               res = my_asprintf(&temp_str, "%s, %s", ret_str, sensu_tags);
                free(ret_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -423,14 +469,14 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
 
        // calculate the value and set to a string
        if (ds->ds[index].type == DS_TYPE_GAUGE) {
-               res = asprintf(&value_str, GAUGE_FORMAT, vl->values[index].gauge);
+               res = my_asprintf(&value_str, GAUGE_FORMAT, vl->values[index].gauge);
                if (res == -1) {
                        free(ret_str);
                        ERROR("write_sensu plugin: Unable to alloc memory");
                        return NULL;
                }
        } else if (rates != NULL) {
-               res = asprintf(&value_str, GAUGE_FORMAT, rates[index]);
+               res = my_asprintf(&value_str, GAUGE_FORMAT, rates[index]);
                if (res == -1) {
                        free(ret_str);
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -438,7 +484,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
                }
        } else {
                if (ds->ds[index].type == DS_TYPE_DERIVE) {
-                       res = asprintf(&value_str, "%"PRIi64, vl->values[index].derive);
+                       res = my_asprintf(&value_str, "%"PRIi64, vl->values[index].derive);
                        if (res == -1) {
                                free(ret_str);
                                ERROR("write_sensu plugin: Unable to alloc memory");
@@ -446,7 +492,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
                        }
                }
                else if (ds->ds[index].type == DS_TYPE_ABSOLUTE) {
-                       res = asprintf(&value_str, "%"PRIu64, vl->values[index].absolute);
+                       res = my_asprintf(&value_str, "%"PRIu64, vl->values[index].absolute);
                        if (res == -1) {
                                free(ret_str);
                                ERROR("write_sensu plugin: Unable to alloc memory");
@@ -454,7 +500,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
                        }
                }
                else {
-                       res = asprintf(&value_str, "%llu", vl->values[index].counter);
+                       res = my_asprintf(&value_str, "%llu", vl->values[index].counter);
                        if (res == -1) {
                                free(ret_str);
                                ERROR("write_sensu plugin: Unable to alloc memory");
@@ -486,7 +532,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
        in_place_replace_sensu_name_reserved(service_buffer);
 
        // finalize the buffer by setting the output and closing curly bracket
-       res = asprintf(&temp_str, "%s, \"output\": \"%s %s %ld\"}\n", ret_str, service_buffer, value_str, CDTIME_T_TO_TIME_T(vl->time));
+       res = my_asprintf(&temp_str, "%s, \"output\": \"%s %s %lld\"}\n",ret_str, service_buffer, value_str, (long long)CDTIME_T_TO_TIME_T(vl->time));
        free(ret_str);
        free(value_str);
        if (res == -1) {
@@ -525,11 +571,10 @@ static char *replace_str(const char *str, const char *old, /* {{{ */
        } else
                retlen = strlen(str);
 
-       ret = malloc(retlen + 1);
+       ret = calloc(1, retlen + 1);
        if (ret == NULL)
                return NULL;
        // added to original: not optimized, but keeps valgrind happy.
-       memset(ret, 0, retlen + 1);
 
        r = ret;
        p = str;
@@ -592,11 +637,10 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
 {
        char service_buffer[6 * DATA_MAX_NAME_LEN];
        char const *severity;
-       notification_meta_t *meta;
        char *ret_str;
        char *temp_str;
        int status;
-       int i;
+       size_t i;
        int res;
        // add the severity/status
        switch (n->severity) {
@@ -616,7 +660,7 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
                        severity = "UNKNOWN";
                        status = 3;
        }
-       res = asprintf(&temp_str, "{\"status\": %d", status);
+       res = my_asprintf(&temp_str, "{\"status\": %d", status);
        if (res == -1) {
                ERROR("write_sensu plugin: Unable to alloc memory");
                return NULL;
@@ -624,7 +668,7 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
        ret_str = temp_str;
 
        // incorporate the timestamp
-       res = asprintf(&temp_str, "%s, \"timestamp\": %ld", ret_str, CDTIME_T_TO_TIME_T(n->time));
+       res = my_asprintf(&temp_str, "%s, \"timestamp\": %lld", ret_str, (long long)CDTIME_T_TO_TIME_T(n->time));
        free(ret_str);
        if (res == -1) {
                ERROR("write_sensu plugin: Unable to alloc memory");
@@ -640,7 +684,7 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
        }
        // incorporate the handlers
        if (strlen(handlers_str) != 0) {
-               res = asprintf(&temp_str, "%s, %s", ret_str, handlers_str);
+               res = my_asprintf(&temp_str, "%s, %s", ret_str, handlers_str);
                free(ret_str);
                free(handlers_str);
                if (res == -1) {
@@ -654,7 +698,7 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
 
        // incorporate the plugin name information if any
        if (n->plugin[0] != 0) {
-               res = asprintf(&temp_str, "%s, \"collectd_plugin\": \"%s\"", ret_str, n->plugin);
+               res = my_asprintf(&temp_str, "%s, \"collectd_plugin\": \"%s\"", ret_str, n->plugin);
                free(ret_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -665,7 +709,7 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
 
        // incorporate the plugin type if any
        if (n->type[0] != 0) {
-               res = asprintf(&temp_str, "%s, \"collectd_plugin_type\": \"%s\"", ret_str, n->type);
+               res = my_asprintf(&temp_str, "%s, \"collectd_plugin_type\": \"%s\"", ret_str, n->type);
                free(ret_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -676,7 +720,7 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
 
        // incorporate the plugin instance if any
        if (n->plugin_instance[0] != 0) {
-               res = asprintf(&temp_str, "%s, \"collectd_plugin_instance\": \"%s\"", ret_str, n->plugin_instance);
+               res = my_asprintf(&temp_str, "%s, \"collectd_plugin_instance\": \"%s\"", ret_str, n->plugin_instance);
                free(ret_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -687,7 +731,7 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
 
        // incorporate the plugin type instance if any
        if (n->type_instance[0] != 0) {
-               res = asprintf(&temp_str, "%s, \"collectd_plugin_type_instance\": \"%s\"", ret_str, n->type_instance);
+               res = my_asprintf(&temp_str, "%s, \"collectd_plugin_type_instance\": \"%s\"", ret_str, n->type_instance);
                free(ret_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -698,7 +742,7 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
 
        // add key value attributes from config if any
        for (i = 0; i < sensu_attrs_num; i += 2) {
-               res = asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, sensu_attrs[i], sensu_attrs[i+1]);
+               res = my_asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, sensu_attrs[i], sensu_attrs[i+1]);
                free(ret_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -709,7 +753,7 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
 
        // incorporate sensu tags from config if any
        if ((sensu_tags != NULL) && (strlen(sensu_tags) != 0)) {
-               res = asprintf(&temp_str, "%s, %s", ret_str, sensu_tags);
+               res = my_asprintf(&temp_str, "%s, %s", ret_str, sensu_tags);
                free(ret_str);
                if (res == -1) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
@@ -724,7 +768,7 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
                                n->type, n->type_instance, host->separator);
        // replace sensu event name chars that are considered illegal
        in_place_replace_sensu_name_reserved(service_buffer);
-       res = asprintf(&temp_str, "%s, \"name\": \"%s\"", ret_str, &service_buffer[1]);
+       res = my_asprintf(&temp_str, "%s, \"name\": \"%s\"", ret_str, &service_buffer[1]);
        free(ret_str);
        if (res == -1) {
                ERROR("write_sensu plugin: Unable to alloc memory");
@@ -740,7 +784,7 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
                        free(ret_str);
                        return NULL;
                }
-               res = asprintf(&temp_str, "%s, \"output\": \"%s - %s\"", ret_str, severity, msg);
+               res = my_asprintf(&temp_str, "%s, \"output\": \"%s - %s\"", ret_str, severity, msg);
                free(ret_str);
                free(msg);
                if (res == -1) {
@@ -751,9 +795,9 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
        }
 
        // Pull in values from threshold and add extra attributes
-       for (meta = n->meta; meta != NULL; meta = meta->next) {
+       for (notification_meta_t *meta = n->meta; meta != NULL; meta = meta->next) {
                if (strcasecmp("CurrentValue", meta->name) == 0 && meta->type == NM_TYPE_DOUBLE) {
-                       res = asprintf(&temp_str, "%s, \"current_value\": \"%.8f\"", ret_str, meta->nm_value.nm_double);
+                       res = my_asprintf(&temp_str, "%s, \"current_value\": \"%.8f\"", ret_str, meta->nm_value.nm_double);
                        free(ret_str);
                        if (res == -1) {
                                ERROR("write_sensu plugin: Unable to alloc memory");
@@ -762,7 +806,7 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
                        ret_str = temp_str;
                }
                if (meta->type == NM_TYPE_STRING) {
-                       res = asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, meta->name, meta->nm_value.nm_string);
+                       res = my_asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, meta->name, meta->nm_value.nm_string);
                        free(ret_str);
                        if (res == -1) {
                                ERROR("write_sensu plugin: Unable to alloc memory");
@@ -773,7 +817,7 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
        }
 
        // close the curly bracket
-       res = asprintf(&temp_str, "%s}\n", ret_str);
+       res = my_asprintf(&temp_str, "%s}\n", ret_str);
        free(ret_str);
        if (res == -1) {
                ERROR("write_sensu plugin: Unable to alloc memory");
@@ -840,7 +884,6 @@ static int sensu_write(const data_set_t *ds, /* {{{ */
        int statuses[vl->values_len];
        struct sensu_host       *host = ud->data;
        gauge_t *rates = NULL;
-       int i;
        char *msg;
 
        pthread_mutex_lock(&host->lock);
@@ -854,7 +897,7 @@ static int sensu_write(const data_set_t *ds, /* {{{ */
                        return -1;
                }
        }
-       for (i = 0; i < (size_t) vl->values_len; i++) {
+       for (size_t i = 0; i < vl->values_len; i++) {
                msg = sensu_value_to_json(host, ds, vl, (int) i, rates, statuses[i]);
                if (msg == NULL) {
                        sfree(rates);
@@ -934,7 +977,6 @@ static int sensu_config_node(oconfig_item_t *ci) /* {{{ */
 {
        struct sensu_host       *host = NULL;
        int                                     status = 0;
-       int                                     i;
        oconfig_item_t          *child;
        char                            callback_name[DATA_MAX_NAME_LEN];
        user_data_t                     ud;
@@ -969,7 +1011,7 @@ static int sensu_config_node(oconfig_item_t *ci) /* {{{ */
                return -1;
        }
 
-       for (i = 0; i < ci->children_num; i++) {
+       for (int i = 0; i < ci->children_num; i++) {
                child = &ci->children[i];
                status = 0;
 
@@ -1110,7 +1152,6 @@ static int sensu_config_node(oconfig_item_t *ci) /* {{{ */
 
 static int sensu_config(oconfig_item_t *ci) /* {{{ */
 {
-       int              i;
        oconfig_item_t  *child;
        int              status;
        struct str_list sensu_tags_arr;
@@ -1118,7 +1159,7 @@ static int sensu_config(oconfig_item_t *ci) /* {{{ */
        sensu_tags_arr.nb_strs = 0;
        sensu_tags_arr.strs = NULL;
 
-       for (i = 0; i < ci->children_num; i++)  {
+       for (int i = 0; i < ci->children_num; i++)  {
                child = &ci->children[i];
 
                if (strcasecmp("Node", child->key) == 0) {
index ee4db23..bf49ba5 100644 (file)
  */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
 #include "utils_cache.h"
 
-#include <pthread.h>
-#include <sys/socket.h>
 #include <netdb.h>
 
 #ifndef WT_DEFAULT_NODE
@@ -143,7 +142,7 @@ static int wt_flush_nolock(cdtime_t timeout, struct wt_callback *cb)
             return 0;
     }
 
-    if (cb->send_buf_fill <= 0)
+    if (cb->send_buf_fill == 0)
     {
         cb->send_buf_init_time = cdtime();
         return 0;
@@ -157,9 +156,7 @@ static int wt_flush_nolock(cdtime_t timeout, struct wt_callback *cb)
 
 static int wt_callback_init(struct wt_callback *cb)
 {
-    struct addrinfo ai_hints;
     struct addrinfo *ai_list;
-    struct addrinfo *ai_ptr;
     int status;
 
     const char *node = cb->node ? cb->node : WT_DEFAULT_NODE;
@@ -168,14 +165,11 @@ static int wt_callback_init(struct wt_callback *cb)
     if (cb->sock_fd > 0)
         return 0;
 
-    memset(&ai_hints, 0, sizeof(ai_hints));
-#ifdef AI_ADDRCONFIG
-    ai_hints.ai_flags    |= AI_ADDRCONFIG;
-#endif
-    ai_hints.ai_family   = AF_UNSPEC;
-    ai_hints.ai_socktype = SOCK_STREAM;
-
-    ai_list = NULL;
+    struct addrinfo ai_hints = {
+        .ai_family = AF_UNSPEC,
+        .ai_flags = AI_ADDRCONFIG,
+        .ai_socktype = SOCK_STREAM
+    };
 
     status = getaddrinfo(node, service, &ai_hints, &ai_list);
     if (status != 0)
@@ -186,13 +180,15 @@ static int wt_callback_init(struct wt_callback *cb)
     }
 
     assert (ai_list != NULL);
-    for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+    for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
     {
         cb->sock_fd = socket(ai_ptr->ai_family, ai_ptr->ai_socktype,
                              ai_ptr->ai_protocol);
         if (cb->sock_fd < 0)
             continue;
 
+        set_sock_opts(cb->sock_fd);
+
         status = connect(cb->sock_fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
         if (status != 0)
         {
@@ -347,7 +343,7 @@ static int wt_format_name(char *ret, int ret_len,
 {
     int status;
     char *temp = NULL;
-    char *prefix = "";
+    const char *prefix = "";
     const char *meta_prefix = "tsdb_prefix";
 
     if (vl->meta) {
@@ -410,11 +406,11 @@ static int wt_send_message (const char* key, const char* value,
                             const char* host, meta_data_t *md)
 {
     int status;
-    int message_len;
+    size_t message_len;
     char *temp = NULL;
-    char *tags = "";
+    const char *tags = "";
     char message[1024];
-    char *host_tags = cb->host_tags ? cb->host_tags : "";
+    const char *host_tags = cb->host_tags ? cb->host_tags : "";
     const char *meta_tsdb = "tsdb_tags";
 
     /* skip if value is NaN */
@@ -435,7 +431,7 @@ static int wt_send_message (const char* key, const char* value,
         }
     }
 
-    message_len = ssnprintf (message,
+    status = ssnprintf (message,
                              sizeof(message),
                              "put %s %.0f %s fqdn=%s %s %s\r\n",
                              key,
@@ -444,12 +440,14 @@ static int wt_send_message (const char* key, const char* value,
                              host,
                              tags,
                              host_tags);
-
     sfree(temp);
+    if (status < 0)
+        return -1;
+    message_len = (size_t) status;
 
     if (message_len >= sizeof(message)) {
         ERROR("write_tsdb plugin: message buffer too small: "
-              "Need %d bytes.", message_len + 1);
+              "Need %zu bytes.", message_len + 1);
         return -1;
     }
 
@@ -505,7 +503,7 @@ static int wt_write_messages(const data_set_t *ds, const value_list_t *vl,
     char key[10*DATA_MAX_NAME_LEN];
     char values[512];
 
-    int status, i;
+    int status;
 
     if (0 != strcmp(ds->type, vl->type))
     {
@@ -514,7 +512,7 @@ static int wt_write_messages(const data_set_t *ds, const value_list_t *vl,
         return -1;
     }
 
-    for (i = 0; i < ds->ds_num; i++)
+    for (size_t i = 0; i < ds->ds_num; i++)
     {
         const char *ds_name = NULL;
 
@@ -573,17 +571,15 @@ static int wt_write(const data_set_t *ds, const value_list_t *vl,
 static int wt_config_tsd(oconfig_item_t *ci)
 {
     struct wt_callback *cb;
-    user_data_t user_data;
+    user_data_t user_data = { 0 };
     char callback_name[DATA_MAX_NAME_LEN];
-    int i;
 
-    cb = malloc(sizeof(*cb));
+    cb = calloc(1, sizeof(*cb));
     if (cb == NULL)
     {
-        ERROR("write_tsdb plugin: malloc failed.");
+        ERROR("write_tsdb plugin: calloc failed.");
         return -1;
     }
-    memset(cb, 0, sizeof(*cb));
     cb->sock_fd = -1;
     cb->node = NULL;
     cb->service = NULL;
@@ -592,7 +588,7 @@ static int wt_config_tsd(oconfig_item_t *ci)
 
     pthread_mutex_init (&cb->send_lock, NULL);
 
-    for (i = 0; i < ci->children_num; i++)
+    for (int i = 0; i < ci->children_num; i++)
     {
         oconfig_item_t *child = ci->children + i;
 
@@ -617,7 +613,6 @@ static int wt_config_tsd(oconfig_item_t *ci)
               cb->node != NULL ? cb->node : WT_DEFAULT_NODE,
               cb->service != NULL ? cb->service : WT_DEFAULT_SERVICE);
 
-    memset(&user_data, 0, sizeof(user_data));
     user_data.data = cb;
     user_data.free_func = wt_callback_free;
     plugin_register_write(callback_name, wt_write, &user_data);
@@ -630,9 +625,7 @@ static int wt_config_tsd(oconfig_item_t *ci)
 
 static int wt_config(oconfig_item_t *ci)
 {
-    int i;
-
-    for (i = 0; i < ci->children_num; i++)
+    for (int i = 0; i < ci->children_num; i++)
     {
         oconfig_item_t *child = ci->children + i;
 
diff --git a/src/xencpu.c b/src/xencpu.c
new file mode 100644 (file)
index 0000000..f1cd938
--- /dev/null
@@ -0,0 +1,164 @@
+/**
+ * collectd - src/xencpu.c
+ * Copyright (C) 2016       Pavel Rochnyak
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Pavel Rochnyak <pavel2000 ngs.ru>
+ **/
+
+#include "collectd.h"
+
+#include "common.h"
+#include "plugin.h"
+
+#include <xenctrl.h>
+
+#ifdef XENCTRL_HAS_XC_INTERFACE
+
+//Xen-4.1+
+#define XC_INTERFACE_INIT_ARGS NULL,NULL,0
+xc_interface *xc_handle;
+
+#else /* XENCTRL_HAS_XC_INTERFACE */
+
+//For xen-3.4/xen-4.0
+#include <string.h>
+#define xc_strerror(xc_interface, errcode) strerror(errcode)
+#define XC_INTERFACE_INIT_ARGS
+typedef int xc_interface;
+xc_interface xc_handle = 0;
+
+#endif /* XENCTRL_HAS_XC_INTERFACE */
+
+uint32_t num_cpus = 0;
+xc_cpuinfo_t *cpu_info;
+static value_to_rate_state_t *cpu_states;
+
+static int xencpu_init (void)
+{
+    xc_handle = xc_interface_open(XC_INTERFACE_INIT_ARGS);
+    if (!xc_handle)
+    {
+        ERROR ("xencpu: xc_interface_open() failed");
+        return (-1);
+    }
+
+    xc_physinfo_t *physinfo;
+
+    physinfo = calloc(1, sizeof(xc_physinfo_t));
+    if (physinfo == NULL)
+    {
+        ERROR ("xencpu plugin: calloc() for physinfo failed.");
+        xc_interface_close(xc_handle);
+        return (ENOMEM);
+    }
+
+    if (xc_physinfo(xc_handle, physinfo) < 0)
+    {
+        ERROR ("xencpu plugin: xc_physinfo() failed");
+        xc_interface_close(xc_handle);
+        free(physinfo);
+        return (-1);
+    }
+
+    num_cpus = physinfo->nr_cpus;
+    free(physinfo);
+
+    INFO ("xencpu plugin: Found %"PRIu32" processors.", num_cpus);
+
+    cpu_info = calloc(num_cpus, sizeof(xc_cpuinfo_t));
+    if (cpu_info == NULL)
+    {
+        ERROR ("xencpu plugin: calloc() for num_cpus failed.");
+        xc_interface_close(xc_handle);
+        return (ENOMEM);
+    }
+
+    cpu_states = calloc (num_cpus, sizeof (value_to_rate_state_t));
+    if (cpu_states == NULL)
+    {
+        ERROR ("xencpu plugin: calloc() for cpu_states failed.");
+        xc_interface_close(xc_handle);
+        free(cpu_info);
+        return (ENOMEM);
+    }
+
+    return (0);
+} /* static int xencpu_init */
+
+static int xencpu_shutdown (void)
+{
+    free(cpu_states);
+    free(cpu_info);
+    xc_interface_close(xc_handle);
+
+    return 0;
+} /* static int xencpu_shutdown */
+
+static void submit_value (int cpu_num, gauge_t percent)
+{
+    value_t values[1];
+    value_list_t vl = VALUE_LIST_INIT;
+
+    values[0].gauge = percent;
+
+    vl.values = values;
+    vl.values_len = 1;
+
+    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+    sstrncpy (vl.plugin, "xencpu", sizeof (vl.plugin));
+    sstrncpy (vl.type, "percent", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "load", sizeof (vl.type_instance));
+
+    if (cpu_num >= 0) {
+        ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+                "%i", cpu_num);
+    }
+    plugin_dispatch_values (&vl);
+} /* static void submit_value */
+
+static int xencpu_read (void)
+{
+    cdtime_t now = cdtime ();
+
+    int rc, nr_cpus;
+
+    rc = xc_getcpuinfo(xc_handle, num_cpus, cpu_info, &nr_cpus);
+    if (rc < 0) {
+        ERROR ("xencpu: xc_getcpuinfo() Failed: %d %s\n", rc, xc_strerror(xc_handle,errno));
+        return (-1);
+    }
+
+    int status;
+    for (int cpu = 0; cpu < nr_cpus; cpu++) {
+        gauge_t rate = NAN;
+        value_t value = {.derive = cpu_info[cpu].idletime};
+
+        status = value_to_rate (&rate, value, DS_TYPE_DERIVE, now, &cpu_states[cpu]);
+        if (status == 0) {
+            submit_value(cpu, 100 - rate/10000000);
+        }
+    }
+
+    return (0);
+} /* static int xencpu_read */
+
+void module_register (void)
+{
+    plugin_register_init ("xencpu", xencpu_init);
+    plugin_register_read ("xencpu", xencpu_read);
+    plugin_register_shutdown ("xencpu", xencpu_shutdown);
+} /* void module_register */
index 29f2acd..3535995 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 
index 8feb31d..8261282 100644 (file)
@@ -28,6 +28,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
 
 typedef        llist_t kstat_t;
 
-static long long get_zfs_value(kstat_t *zfs_stats  __attribute__((unused)),
-               char *name)
+static int put_zfs_value (kstat_t *ksp, char const *k, value_t v)
+{
+       llentry_t *e;
+       char *k_copy;
+       value_t *v_copy;
+
+       k_copy = strdup (k);
+       if (k_copy == NULL)
+               return ENOMEM;
+
+       v_copy = malloc (sizeof (*v_copy));
+       if (v_copy == NULL)
+       {
+               sfree (k_copy);
+               return ENOMEM;
+       }
+       *v_copy = v;
+
+       e = llentry_create (k_copy, v_copy);
+       if (e == NULL)
+       {
+               sfree (v_copy);
+               sfree (k_copy);
+               return ENOMEM;
+       }
+
+       llist_append (ksp, e);
+       return 0;
+}
+
+static long long get_zfs_value(kstat_t *ksp, const char *key)
 {
        llentry_t *e;
+       value_t *v;
 
-       e = llist_search (zfs_stats, name);
+       e = llist_search (ksp, key);
        if (e == NULL)
        {
-               ERROR ("zfs_arc plugin: `llist_search` failed for key: '%s'.", name);
+               ERROR ("zfs_arc plugin: `llist_search` failed for key: '%s'.", key);
                return (-1);
        }
 
-       return (*(long long int*)e->value);
+       v = e->value;
+       return ((long long) v->derive);
+}
+
+static void free_zfs_values (kstat_t *ksp)
+{
+       if (ksp == NULL)
+               return;
+
+       for (llentry_t *e = llist_head (ksp); e != NULL; e = e->next)
+       {
+               sfree (e->key);
+               sfree (e->value);
+       }
+
+       llist_destroy (ksp);
 }
 
-#elif !defined(__FreeBSD__) // Solaris
+#elif defined(KERNEL_SOLARIS)
 extern kstat_ctl_t *kc;
 
 static long long get_zfs_value(kstat_t *ksp, char *name)
@@ -64,7 +110,7 @@ static long long get_zfs_value(kstat_t *ksp, char *name)
 
        return (get_kstat_value(ksp, name));
 }
-#else // FreeBSD
+#elif defined(KERNEL_FREEBSD)
 #include <sys/types.h>
 #include <sys/sysctl.h>
 
@@ -172,81 +218,47 @@ static int za_read (void)
        value_t  l2_io[2];
        kstat_t  *ksp   = NULL;
 
-#if KERNEL_LINUX
-       long long int *llvalues = NULL;
-       char file_contents[1024 * 10];
-       char *fields[3];
-       int numfields;
-       ssize_t len;
+#if defined(KERNEL_LINUX)
+       FILE *fh;
+       char buffer[1024];
+
+       fh = fopen (ZOL_ARCSTATS_FILE, "r");
+       if (fh == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("zfs_arc plugin: Opening \"%s\" failed: %s", ZOL_ARCSTATS_FILE,
+                      sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
 
        ksp = llist_create ();
        if (ksp == NULL)
        {
                ERROR ("zfs_arc plugin: `llist_create' failed.");
+               fclose (fh);
                return (-1);
        }
 
-       len = read_file_contents (ZOL_ARCSTATS_FILE, file_contents, sizeof(file_contents) - 1);
-       if (len > 1)
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
        {
+               char *fields[3];
+               value_t v;
+               int status;
 
-               int i=0;
-               char *pnl = file_contents;
-               char *pnnl;
-
-               file_contents[len] = '\0';
-
-               while (pnl != NULL)
-               {
-                       pnl = strchr(pnl, '\n');
-                       i++;
-                       if (pnl && (*pnl != '\0'))
-                               pnl++;
-               }
-
-               if (i > 0)
-               {
-                       llentry_t *e;
-                       llvalues = malloc(sizeof(long long int) * i);
-                       if (llvalues == NULL)
-                       {
-                               ERROR ("zfs_arc plugin: `malloc' failed.");
-                               llist_destroy (ksp);
-                               return (-1);
-                       }
-                       int j = 0;
-
-                       pnl = file_contents;
-                       while (pnl != NULL)
-                       {
-                               pnnl = strchr(pnl, '\n');
-                               if (pnnl != NULL)
-                                       *pnnl = '\0';
-
-                               numfields = strsplit (pnl, fields, 4);
-                               if (numfields == 3)
-                               {
-                                       llvalues[j] = atoll (fields[2]);
-
-                                       e = llentry_create (fields[0], &llvalues[j]);
-                                       if (e == NULL)
-                                       {
-                                               ERROR ("zfs_arc plugin: `llentry_create' failed.");
-                                       }
-                                       else
-                                       {
-                                               llist_append (ksp, e);
-                                       }
-                                       j++;
-                               }
-                               pnl = pnnl;
-                               if (pnl != NULL)
-                                       pnl ++;
-                       }
-               }
+               status = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+               if (status != 3)
+                       continue;
+
+               status = parse_value (fields[2], &v, DS_TYPE_DERIVE);
+               if (status != 0)
+                       continue;
+
+               put_zfs_value (ksp, fields[0], v);
        }
 
-#elif !defined(__FreeBSD__) // Solaris
+       fclose (fh);
+
+#elif defined(KERNEL_SOLARIS)
        get_kstat (&ksp, "zfs", 0, "arcstats");
        if (ksp == NULL)
        {
@@ -256,7 +268,19 @@ static int za_read (void)
 #endif
 
        /* Sizes */
-       za_read_gauge (ksp, "size",    "cache_size", "arc");
+       za_read_gauge (ksp, "anon_size",      "cache_size", "anon_size");
+       za_read_gauge (ksp, "c",              "cache_size", "c");
+       za_read_gauge (ksp, "c_max",          "cache_size", "c_max");
+       za_read_gauge (ksp, "c_min",          "cache_size", "c_min");
+       za_read_gauge (ksp, "hdr_size",       "cache_size", "hdr_size");
+       za_read_gauge (ksp, "metadata_size",  "cache_size", "metadata_size");
+       za_read_gauge (ksp, "mfu_ghost_size", "cache_size", "mfu_ghost_size");
+       za_read_gauge (ksp, "mfu_size",       "cache_size", "mfu_size");
+       za_read_gauge (ksp, "mru_ghost_size", "cache_size", "mru_ghost_size");
+       za_read_gauge (ksp, "mru_size",       "cache_size", "mru_size");
+       za_read_gauge (ksp, "other_size",     "cache_size", "other_size");
+       za_read_gauge (ksp, "p",              "cache_size", "p");
+       za_read_gauge (ksp, "size",           "cache_size", "arc");
 
        /* The "l2_size" value has disappeared from Solaris some time in
         * early 2013, and has only reappeared recently in Solaris 11.2.
@@ -268,17 +292,14 @@ static int za_read (void)
 
        /* Operations */
        za_read_derive (ksp, "deleted",  "cache_operation", "deleted");
-#if __FreeBSD__
+#if defined(KERNEL_FREEBSD)
        za_read_derive (ksp, "allocated","cache_operation", "allocated");
-#if defined(__FreeBSD_version) && (__FreeBSD_version < 1002501)
-       /* stolen removed from sysctl kstat.zfs.misc.arcstats on FreeBSD 10.2+ */
-       za_read_derive (ksp, "stolen",   "cache_operation", "stolen");
-#endif
 #endif
 
        /* Issue indicators */
        za_read_derive (ksp, "mutex_miss", "mutex_operations", "miss");
        za_read_derive (ksp, "hash_collisions", "hash_collisions", "");
+       za_read_derive (ksp, "memory_throttle_count", "memory_throttle_count", "");
 
        /* Evictions */
        za_read_derive (ksp, "evict_l2_cached",     "cache_eviction", "cached");
@@ -294,6 +315,11 @@ static int za_read (void)
        za_read_derive (ksp, "demand_metadata_misses",   "cache_result", "demand_metadata-miss");
        za_read_derive (ksp, "prefetch_data_misses",     "cache_result", "prefetch_data-miss");
        za_read_derive (ksp, "prefetch_metadata_misses", "cache_result", "prefetch_metadata-miss");
+       za_read_derive (ksp, "mfu_hits",                 "cache_result", "mfu-hit");
+       za_read_derive (ksp, "mfu_ghost_hits",           "cache_result", "mfu_ghost-hit");
+       za_read_derive (ksp, "mru_hits",                 "cache_result", "mru-hit");
+       za_read_derive (ksp, "mru_ghost_hits",           "cache_result", "mru_ghost-hit");
+       za_read_derive (ksp, "prefetch_metadata_misses", "cache_result", "prefetch_metadata-miss");
 
        /* Ratios */
        arc_hits   = (gauge_t) get_zfs_value(ksp, "hits");
@@ -311,14 +337,7 @@ static int za_read (void)
        za_submit ("io_octets", "L2", l2_io, /* num values = */ 2);
 
 #if defined(KERNEL_LINUX)
-       if (llvalues != NULL)
-       {
-               free(llvalues);
-       }
-       if (ksp != NULL)
-       {
-               llist_destroy (ksp);
-       }
+       free_zfs_values (ksp);
 #endif
 
        return (0);
@@ -326,7 +345,7 @@ static int za_read (void)
 
 static int za_init (void) /* {{{ */
 {
-#if !defined(__FreeBSD__) && !defined(KERNEL_LINUX) // Solaris
+#if defined(KERNEL_SOLARIS)
        /* kstats chain already opened by update_kstat (using *kc), verify everything went fine. */
        if (kc == NULL)
        {
diff --git a/src/zone.c b/src/zone.c
new file mode 100644 (file)
index 0000000..3751bfd
--- /dev/null
@@ -0,0 +1,205 @@
+/**
+ * collectd - src/zone.c
+ * Copyright (C) 2011       Mathijs Mohlmann
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Mathijs Mohlmann
+ *   Dagobert Michelsen (forward-porting)
+ **/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+# undef HAVE_CONFIG_H
+#endif
+/* avoid procfs.h error "Cannot use procfs in the large file compilation environment" */
+#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
+#  undef _FILE_OFFSET_BITS
+#  undef _LARGEFILE64_SOURCE
+#endif
+
+#include "collectd.h"
+
+#include "common.h"
+#include "plugin.h"
+
+#include <procfs.h>
+#include <zone.h>
+
+#include "utils_avltree.h"
+
+#define        MAX_PROCFS_PATH 40
+#define FRC2PCT(pp)(((float)(pp))/0x8000*100)
+
+typedef struct zone_stats {
+       ushort_t      pctcpu;
+       ushort_t      pctmem;
+} zone_stats_t;
+
+static int
+zone_compare(const void *a, const void *b)
+{
+       if (*(const zoneid_t *)a == *(const zoneid_t *)b)
+               return(0);
+       if (*(const zoneid_t *)a < *(const zoneid_t *)b)
+               return(-1);
+       return(1);
+}
+
+static int
+zone_read_procfile(char const *pidstr, char const *name, void *buf, size_t bufsize)
+{
+       int fd;
+
+       char procfile[MAX_PROCFS_PATH];
+       (void)snprintf(procfile, sizeof(procfile), "/proc/%s/%s", pidstr, name);
+       if ((fd = open(procfile, O_RDONLY)) == -1) {
+               return (1);
+       }
+
+       if (sread(fd, buf, bufsize) != 0) {
+               char errbuf[1024];
+               ERROR ("zone plugin: Reading \"%s\" failed: %s", procfile,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               close(fd);
+               return (1);
+       }
+
+       close(fd);
+       return (0);
+}
+
+static int
+zone_submit_value(char *zone, gauge_t value)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+       value_t      values[1];
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1; /*STATIC_ARRAY_SIZE (values);*/
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "zone", sizeof (vl.plugin));
+       sstrncpy (vl.type, "percent", sizeof (vl.type));
+       sstrncpy (vl.type_instance, zone, sizeof (vl.type_instance));
+
+       return(plugin_dispatch_values (&vl));
+}
+
+static zone_stats_t *
+zone_find_stats(c_avl_tree_t *tree, zoneid_t zoneid)
+{
+       zone_stats_t *ret = NULL;
+       zoneid_t     *key = NULL;
+
+       if (c_avl_get(tree, (void **)&zoneid, (void **)&ret)) {
+               if (!(ret = malloc(sizeof(*ret)))) {
+                       WARNING("zone plugin: no memory");
+                       return(NULL);
+               }
+               if (!(key = malloc(sizeof(*key)))) {
+                       WARNING("zone plugin: no memory");
+                       free(ret);
+                       return(NULL);
+               }
+               *key = zoneid;
+               if (c_avl_insert(tree, key, ret)) {
+                       WARNING("zone plugin: error inserting into tree");
+                       return(NULL);
+               }
+       }
+       return(ret);
+}
+
+static void
+zone_submit_values(c_avl_tree_t *tree)
+{
+       char          zonename[ZONENAME_MAX];
+       zoneid_t     *zoneid = NULL;
+       zone_stats_t *stats  = NULL;
+
+       while (c_avl_pick (tree, (void **)&zoneid, (void **)&stats) == 0)
+       {
+               if (getzonenamebyid(*zoneid, zonename, sizeof( zonename )) == -1) {
+                       WARNING("zone plugin: error retreiving zonename");
+               } else {
+                       zone_submit_value(zonename, (gauge_t)FRC2PCT(stats->pctcpu));
+               }
+               free(stats);
+               free(zoneid);
+       }
+       c_avl_destroy(tree);
+}
+
+static c_avl_tree_t *
+zone_scandir(DIR *procdir)
+{
+       pid_t         pid;
+       dirent_t     *direntp;
+       psinfo_t      psinfo;
+       c_avl_tree_t *tree;
+       zone_stats_t *stats;
+
+       if (!(tree=c_avl_create(zone_compare))) {
+               WARNING("zone plugin: Failed to create tree");
+               return(NULL);
+       }
+
+       rewinddir(procdir);
+       while ((direntp = readdir(procdir))) {
+               char const *pidstr = direntp->d_name;
+               if (pidstr[0] == '.')   /* skip "." and ".."  */
+                       continue;
+
+               pid = atoi(pidstr);
+               if (pid == 0 || pid == 2 || pid == 3)
+                       continue;       /* skip sched, pageout and fsflush */
+
+               if (zone_read_procfile(pidstr, "psinfo", &psinfo, sizeof(psinfo_t)) != 0)
+                       continue;
+
+               stats = zone_find_stats(tree, psinfo.pr_zoneid);
+               if( stats ) {
+                       stats->pctcpu += psinfo.pr_pctcpu;
+                       stats->pctmem += psinfo.pr_pctmem;
+               }
+       }
+       return(tree);
+}
+
+static int zone_read (void)
+{
+       DIR          *procdir;
+       c_avl_tree_t *tree;
+
+       if ((procdir = opendir("/proc")) == NULL) {
+               ERROR("zone plugin: cannot open /proc directory\n");
+               return (-1);
+       }
+
+       tree=zone_scandir(procdir);
+       closedir(procdir);
+       if (tree == NULL) {
+               return (-1);
+       }
+       zone_submit_values(tree); /* this also frees tree */
+       return (0);
+}
+
+void module_register (void)
+{
+       plugin_register_read ("zone", zone_read);
+} /* void module_register */
index 5aa94e3..8417485 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
 #include <netdb.h>
-#include <sys/socket.h>
 #include <sys/un.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
@@ -106,18 +106,18 @@ static int zookeeper_connect (void)
 {
        int sk = -1;
        int status;
-       struct addrinfo ai_hints;
-       struct addrinfo *ai;
        struct addrinfo *ai_list;
-       char *host;
-       char *port;
-
-       memset ((void *) &ai_hints, '\0', sizeof (ai_hints));
-       ai_hints.ai_family   = AF_UNSPEC;
-       ai_hints.ai_socktype = SOCK_STREAM;
+       const char *host;
+       const char *port;
 
        host = (zk_host != NULL) ? zk_host : ZOOKEEPER_DEF_HOST;
        port = (zk_port != NULL) ? zk_port : ZOOKEEPER_DEF_PORT;
+
+       struct addrinfo ai_hints = {
+               .ai_family   = AF_UNSPEC,
+               .ai_socktype = SOCK_STREAM
+       };
+
        status = getaddrinfo (host, port, &ai_hints, &ai_list);
        if (status != 0)
        {
@@ -129,7 +129,7 @@ static int zookeeper_connect (void)
                return (-1);
        }
 
-       for (ai = ai_list; ai != NULL; ai = ai->ai_next)
+       for (struct addrinfo *ai = ai_list; ai != NULL; ai = ai->ai_next)
        {
                sk = socket (ai->ai_family, SOCK_STREAM, 0);
                if (sk < 0)
@@ -160,8 +160,7 @@ static int zookeeper_connect (void)
 
 static int zookeeper_query (char *buffer, size_t buffer_size)
 {
-       int sk = -1;
-       int status;
+       int sk, status;
        size_t buffer_fill;
 
        sk = zookeeper_connect();
diff --git a/testwrapper.sh b/testwrapper.sh
new file mode 100755 (executable)
index 0000000..a86705f
--- /dev/null
@@ -0,0 +1,30 @@
+#! /bin/sh
+#
+# collectd -- testwrapper.sh
+#
+# A wrapper script for running tests. If valgrind is available, memory
+# checking will be enabled for all tests.
+
+set -e
+
+MEMCHECK=""
+
+if test -n "$VALGRIND"; then
+       MEMCHECK="$VALGRIND --quiet --tool=memcheck --error-exitcode=1"
+       MEMCHECK="$MEMCHECK --trace-children=yes"
+       MEMCHECK="$MEMCHECK --leak-check=full"
+       MEMCHECK="$MEMCHECK --gen-suppressions=all"
+
+       for f in "valgrind.$( uname -s ).suppress" "valgrind.suppress"; do
+               filename="$( dirname "$0" )/src/$f"
+               if test -e "$filename"; then
+                       # Valgrind supports up to 100 suppression files.
+                       MEMCHECK="$MEMCHECK --suppressions=$filename"
+               fi
+       done
+fi
+
+exec $MEMCHECK "$@"
+
+# vim: set tw=78 sw=4 ts=4 noexpandtab :
+
index f0f8dca..70b8c26 100755 (executable)
@@ -2,12 +2,12 @@
 
 DEFAULT_VERSION="5.5.2.git"
 
-VERSION="`git describe 2> /dev/null | grep collectd | sed -e 's/^collectd-//'`"
+if [ -d .git ]; then
+       VERSION="`git describe --dirty=+ --abbrev=7 2> /dev/null | grep collectd | sed -e 's/^collectd-//' -e 's/-/./g'`"
+fi
 
 if test -z "$VERSION"; then
        VERSION="$DEFAULT_VERSION"
 fi
 
-VERSION="`echo \"$VERSION\" | sed -e 's/-/./g'`"
-
 printf "%s" "$VERSION"