Merge remote-tracking branch 'origin/pr/1346'
authorMarc Fournier <marc.fournier@camptocamp.com>
Tue, 9 Aug 2016 11:14:04 +0000 (13:14 +0200)
committerMarc Fournier <marc.fournier@camptocamp.com>
Tue, 9 Aug 2016 11:14:04 +0000 (13:14 +0200)
 Conflicts:
README
configure.ac
src/Makefile.am
src/collectd.conf.in
src/collectd.conf.pod
src/types.db

273 files changed:
.clang-format [new file with mode: 0644]
.gitignore
.travis.yml
AUTHORS
CONTRIBUTING.md [new file with mode: 0644]
ChangeLog
Makefile.am
README
bindings/java/org/collectd/java/GenericJMXConfConnection.java
bindings/java/org/collectd/java/GenericJMXConfValue.java
bindings/perl/lib/Collectd/Unixsock.pm
build.sh
configure.ac
contrib/collection3/lib/Collectd/Graph/Common.pm
contrib/examples/myplugin.c
contrib/redhat/collectd.spec
contrib/systemd.collectd.service
contrib/wiki2changelog.pl
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 [new file with mode: 0644]
src/cgroups.c
src/chrony.c [new file with mode: 0644]
src/collectd-email.pod
src/collectd-exec.pod
src/collectd-java.pod
src/collectd-nagios.c
src/collectd-perl.pod
src/collectd-python.pod
src/collectd-tg.c
src/collectd.conf.in
src/collectd.conf.pod
src/collectd.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
src/daemon/plugin.c
src/daemon/plugin.h
src/daemon/plugin_mock.c
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_ignorelist.h
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
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
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 [changed mode: 0755->0644]
src/fhcount.c
src/filecount.c
src/fscache.c
src/gmond.c
src/gps.c
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/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
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
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_riemann_threshold.h [new file with mode: 0644]
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
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 cf4ad15..b85dc48 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,28 +75,20 @@ 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
-src/test_utils_latency
-src/test_utils_mount
-src/test_utils_vl_lookup
-test*.log
-*.trs
 
-# new daemon repo
-src/daemon/.deps/
-src/daemon/.dirstamp
+# lint stuff
+*.ln
+
+#ide stuff
+.vscode
+
+# Unit tests
+src/daemon/test-suite.log
+src/tests/
+src/test-suite.log
+test_*
+
+# src/daemon/...
 src/daemon/collectd
-src/daemon/test_common
-src/daemon/test_meta_data
-src/daemon/test_utils_avltree
-src/daemon/test_utils_heap
-src/daemon/test_utils_subst
index 09adb4d..03d9dde 100644 (file)
@@ -1,25 +1,56 @@
-sudo: false
+sudo: required
+dist: trusty
 compiler:
   - gcc
   - clang
-addons:
-  apt:
-    packages:
-      - iptables-dev
-      - libcap-dev
-      - libdbi-dev
-      - libhiredis-dev
-      - libnfnetlink-dev
-      - libnotify-dev
-      - libpcap-dev
-      - libperl-dev
-      - libprotobuf-c0-dev
-      - librrd-dev
-      - libsnmp-dev
-      - libudev-dev
-      - libvarnishapi-dev
-      - libyajl-dev
-      - linux-libc-dev
-      - protobuf-c-compiler
 language: c
-script: sh build.sh && ./configure && make distcheck
+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 882b5ba..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,11 +97,15 @@ 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.
@@ -118,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.
 
@@ -165,13 +194,6 @@ 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.
@@ -224,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.
@@ -234,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 b0a997c..25257d7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,123 @@
+2016-07-25, Version 5.5.2
+       * collectd: A division by zero has been fixed in the
+         "plugin_dispatch_multivalue()" function. Thanks to Corey Kosak.
+       * collectd: The address of the Free Software Foundation has been fixed
+         in GPL license headers. Thanks to Ruben Kerkhof.
+       * Build system: Detection and handling of librrd 1.6 and later has been
+         fixed. Thanks to Ruben Kerkof.
+       * Apache plugin: A warning about a possible misconfiguration has been
+         added. Thanks to Marc Fournier.
+       * cURL, cURL-JSON and cURL-XML plugins: A memory leak when allocating
+         more memory fails has been fixed. Thanks to Brandon Arp.
+       * DF plugin: A build issue on DragonFlyBSD has been fixed. Thanks to
+         Ruben Kerkhof. #1575
+       * Ethstat plugin: Code to strip leading whitespace from device names.
+         This works around an issue in the VMXNet3 driver. Thanks to Thomas
+         Guthmann. #1059
+       * Exec plugin: A problem in the error handling of an fdopen() failure
+         has been fixed. Thanks to @ciomaire.
+       * Modbus plugin: The debug output has been disabled by default. It is
+         now only enabled when building with "--enable-debug". Thanks to Eric
+         Sandeen and Marc Fournier.
+       * Network plugin: A check for the initialization of secure memory has
+         been added. Previously, failure to initialize this memory was
+         ignored. Thanks to @yujokang. #1665
+       * Network plugin: A heap overflow has been fixed in the server code.
+         This issue can be triggered remotely and is potentially exploitable.
+         Thanks to Emilien Gaspar. CVE-2016-6254
+       * Perl plugin: Init callbacks have been changed to run essentially
+         single-threaded to avoid race conditions by init functions which
+         create additional threads. Thanks to Pavel Rochnyack. #1706
+       * Processes plugin: A warning about too long process names has been
+         added. Thanks to Marc Fournier. #1284
+       * Redis plugin: A memory leak in an error handling code path has been
+         fixed. Thanks to Andrés J. Díaz.
+       * Redis plugin: The data source type of the expired_keys metric has been
+         corrected to "DERIVE". Thanks to Marc Falzon and Marc Fournier. #1483.
+       * SMART plugin: A build dependency on libudev has been added. Thanks to
+         Pavel Rochnyack. #1724
+       * StatsD plugin: A deadlock on plugin shutdown has been fixed. Thanks to
+         Pavel Rochnyack #1703
+       * Write HTTP plugin: Freeing of memory holding HTTP headers during
+         shutdown has been fixed. Thanks to Tolga Ceylan.
+       * Write Sensu plugin: A segfault when the Tag was unset has been fixed.
+         Thanks to Marc Fournier.
+       * ZFS ARC plugin: The cache_operation-stolen metric has been removed for
+         FreeBSD 10.2 and later. Thanks to Ruben Kerkhof. #1580
+
+2016-01-22, Version 5.5.1
+       * Build system: Compilation errors have been avoided by correctly
+         defining package name and version used by autoconf. Thanks to Nathan
+         Berkley. #1063
+       * Build system: Dependency ordering was fixed to ensure parallel builds
+         work reliably. Thanks to Gustavo Zacarias. #1125
+       * Build system: Error messages have been improved and building the unit
+         tests has been fixed on Solaris. Thanks to Florian Forster and
+         Dagobert Michelsen. #1077
+       * Build system: The move of the "utils_ignorelist" functions has been
+         reverted. This fixes build issues of numerous plugins. Thanks to
+         Benjamin Drung;. #1323
+       * Build system: The fhcount plugin has been restricted to Linux. Thanks
+         to Ruben Kerkhof. #1195
+       * Build system: Detection of header files for the turbostat plugin has
+         been fixed. Thanks to Marc Fournier. #1075
+       * collectd: The "LC_NUMERIC" locale is now forced, to prevent issues
+         with some plugins on environments using a comma as decimal separator.
+         Thanks to Florian Forster. #1237
+       * Documentation: Some precisions related to the virt plugin have beed
+         added. Thanks to Wojtek Bocer and Ruben Kerkhof.
+       * Documentation: The CollectdInternalStats documentation has been
+         improved. Thanks to Yves Mettier and Florian Forster.
+       * Battery plugin: A missing Type has been added. Thanks to Marc
+         Fournier. #1338
+       * Bind plugin: An off-by-one error has been fixed: an index was checked
+         against a wrong variable, which may lead to an out-of-bounds read.
+         Thanks to Michal Humpula. #1123
+       * Ceph plugin: JSON parsing has been refactored to support ceph 10.0.0
+         and fixes several buffer overflows. Thanks to Florian Forster. #1350
+       * CPU plugin: A Mac OS X specific bug has been fixed: the plugin
+         expected an incorrect number of CPU states, resulting in failing read
+         callbacks. This regression was introduced in 5.5.0. Thanks to Robert
+         Viduya.
+       * Disk plugin: Support for Mac OS X 10.10 has been added. Thanks to
+         Robert Viduya. #1065
+       * IPC plugin: Support for building with musl-libc has been added. Thanks
+         to Natanael Copa. #1147
+       * Log Logstash plugin: A segfault when using libyajl, version 1 was
+         fixed. Thanks to Vincent Bernat. #1190
+       * Log Logstash plugin: The timestamp is now ISO 8601 compliant. Thanks
+         to Marc Fournier. #1132
+       * memcached plugin: The Type of the listen-disabled metric was fixed.
+         Thanks to Florian Forster. #1356
+       * MySQL plugin: The Type used by Innodb_buffer_pool_pages_flushed was
+         fixed. Thanks to Marek Becka. #1085
+       * OpenLDAP plugin: A crash when using LDAPI (LDAP-over-IPC) got fixed.
+         Thanks to Marek Becka. #1080
+       * OpenLDAP plugin: Support for Mac OS X has been added. Thanks to Ruben
+         Kerkhof. #1489
+       * SMART plugin: A memory leak has been fixed. Thanks to Florian
+         Schüller and Pierre-Yves Ritschard. #1076
+       * Swap plugin: A regression that would lead to swap usage being reported
+         in kilobytes (instead of bytes) has been fixed. Thanks to Marek Becka.
+         #1071
+       * Varnish plugin: Support for FreeBSD has been added. Thanks to Ruben
+         Kerkhof. #1182
+       * Varnish plugin: Support for versions 3 and 4 has been made more
+         tolerant to minor changes in Varnish point releases. Thanks to Marc
+         Fournier. #1302
+       * virt plugin: A copy-and-paste mistake in an error message has been
+         fixed. Thanks to Ruben Kerkhof. #1101
+       * Write Kafka plugin: Support for Solaris has been added. Thanks to
+         Shahul Hameed. #1171
+       * Write Redis plugin: Dead code has been removed. Thanks to Brian Kelly.
+         #1143
+       * 27 patches have been applied to numerous plugins and core components,
+         fixing various programming errors which were reported by scan-build,
+         libasan, FBInfer, coverity-scan and clang: Thanks to Ruben Kerkhof,
+         Florian Forster and Marek Becka.
+       * Collectd::Unixsock: A Perl error got corrected. Thanks to Ciaran Mac
+         An Iomaire. #1295
+
 2015-05-27, Version 5.5.0
        * Build system: Ability to make out-of-tree builds has been fixed.
          Thanks to Vincent Bernat. #792
          Marc Fournier and Wilfried Goesgens. #552
        * Zookeeper plugin: This new plugin reads data from the Apache Zookeeper
          "MNTR" command. Thanks to Jeremy Katz. #826
+=======
+       * Processes plugin and Swap plugin: These plugins have been corrected to
+         also work inside FreeBSD jails. Thanks to biancalana. #1019
+       * Processes plugin: A warning about too long process names has been
+         added. Thanks to Marc Fournier. #1284
+       * Processes plugin: Process counting on the FreeBSD and OpenBSD
+         platforms has been fixed. Thanks to Herve COMMOWICK. #1298
+       * Processes plugin: The plugin was fixed to work properly on Solaris.
+         Thanks to Jan Andres. #919
+       * Python plugin: A double-free bug got fixed. Thanks to Sven Trenkel.
+         #1285
+       * RRDtool plugin: A race condition leading to corrupt RRD file creation
+         has been fixed. Thanks to Manuel Luis Sanmartín Rozada. #1031
+       * SNMP plugin: The "Gauge32" signedness was corrected to match RFC1902.
+         Thanks to Nathan Ward. #1325
+       * StatsD plugin: A deadlock on plugin shutdown has been fixed. Thanks to
+         Pavel Rochnyack #1703
+       * StatsD plugin: A memory leak was corrected. Thanks to Florian Forster.
+         #997
+       * StatsD plugin: A symbol lookup error was fixed by properly linking the
+         plugin against libm. Thanks to Florian Forster.
+       * StatsD plugin: "utils_latency": Support for including values above
+         1000 in percentile calculation has been added. Thanks to Yoga
+         Ramalingam. #401
+       * StatsD plugin: "utils_latency": Two division by zero error conditions
+         have been corrected. Thanks to Wilfried Goesgens. #655
+       * StatsD plugin: Counters absolute counts are now also reported. Thanks
+         to Pierre-Yves Ritschard. #1311
+       * StatsD plugin: The plugin now emits NaN values when no timer event is
+         recorded. Thanks to Florian Forster. #1038, #1039
+       * StatsD plugin: The plugin was corrected to avoid crashing when
+         negative timer values are submitted. Thanks to Florian Forster. #1131
+       * Tail CSV plugin: The plugin was fixed to work properly with multiple
+         "Collect" options and a bug got fixed when no "TimeFrom" is specified.
+         Thanks to Manuel Luis Sanmartín Rozada and Florian Forster. #1032
+       * TCPConns plugin: A memory leak was fixed. Thanks to Florian Forster.
+         #1074
+       * TCPConns plugin: An bug causing collectd to enter an inifinite loop on
+         OpenBSD was fixed. Thanks to Landry Breuil. #1094
+       * Threshold plugin: Threshold configuration blocks can now be defined in
+         different files. Thanks to Michael Salmon. #551
+       * vmem plugin: Support for pgsteal in recent Linux kernels has been
+         added. Thanks to Jakub Jankowski. #1307
+       * vmem plugin: The DSType for nr_dirtied and nr_written was corrected to
+         report a derive. Thanks to Marek Becka. #1072
+       * Write Graphite plugin: Error handling when submitting metrics to the
+         server is now more robust. Thanks to Sam Pointer. #1364
+       * Write HTTP plugin: Freeing of memory holding HTTP headers during
+         shutdown has been fixed. Thanks to Tolga Ceylan.
+       * Write Redis plugin: Multi-Valued key was made easier to parse by
+         adding a "|" character as a delimiter. Thanks to brianpkelly and
+         Florian Forster. #1070
+       * Write Redis plugin: The timestamp format was corrected. Thanks to
+         Florian Forster.
+       * ZFS ARC plugin: The plugin was will not emit warning about missing
+         "l2_size" stats anymore. Thanks to Jan Andres. #919
+       * 152 patches have been applied to numerous plugins and core components,
+         fixing various programming errors which were reported by scan-build,
+         libasan, FBInfer, coverity-scan, clang and gcc-6: Thanks to Ruben
+         Kerkhof, Florian Forster, Marc Fournier, Corey Kosak, Laurent,
+         Claudius Zingerli and Fabien Wernli.
+>>>>>>> collectd-5.4
 
 2015-02-26, Version 5.4.2
        * Build system: Numerous fixes. Thanks to Bjørn Nordbø, Jim Radford,
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 a55b2a2..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.
 
@@ -122,6 +128,9 @@ Features
     - gps
       Monitor gps related data through gpsd.
 
+    - grpc
+      Receive values over the network using the gRPC framework.
+
     - hddtemp
       Hard disk temperatures using hddtempd.
 
@@ -385,6 +394,9 @@ Features
     - wireless
       Link quality of wireless cards. Linux only.
 
+    - xencpu
+      XEN Hypervisor CPU stats.
+
     - xmms
       Bitrate and frequency of music played with XMMS.
 
@@ -505,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).
@@ -679,6 +694,11 @@ 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/>
@@ -772,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)
@@ -837,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/>
 
@@ -850,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
 ------------------------------------
 
@@ -903,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
@@ -931,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 d927d13..304bbbc 100644 (file)
@@ -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 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 08496dc..1bacddd 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,8 +43,12 @@ 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
 AC_PROG_LN_S
 AC_PROG_MAKE_SET
@@ -54,17 +59,53 @@ AC_DISABLE_STATIC
 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])
+
 PKG_PROG_PKG_CONFIG
 
-AC_CHECK_PROG([have_protoc_c], [protoc-c], [yes], [no])
-AC_CHECK_HEADERS([google/protobuf-c/protobuf-c.h],
-                 [have_protobuf_c_h="yes"],
-                 [have_protobuf_c_h="no"])
-if test "x$have_protoc_c" = "xyes" && test "x$have_protobuf_c_h" != "xyes"
+AC_CACHE_CHECK([if bison is the parser generator],
+       [collectd_cv_prog_bison],
+       [AS_IF([$YACC --version 2>/dev/null | $EGREP -q '^bison '],
+               [collectd_cv_prog_bison=yes], [collectd_cv_prog_bison=no]
+       )]
+)
+
+if test "x$collectd_cv_prog_bison" = "xno" && test ! -f "${srcdir}/src/liboconfig/parser.c"
 then
-       have_protoc_c="no (unable to find <google/protobuf-c/protobuf-c.h>)"
+       AC_MSG_ERROR([bison is missing and you do not have ${srcdir}/src/liboconfig/parser.c. Please install bison])
+fi
+
+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")
+
+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
@@ -84,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"
@@ -97,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
@@ -171,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
@@ -385,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])
@@ -398,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)
 
@@ -416,7 +490,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
@@ -583,7 +657,35 @@ AC_CHECK_HEADERS(linux/un.h, [], [],
 #endif
 ])
 
-AC_CHECK_HEADERS(pwd.h grp.h sys/un.h ctype.h limits.h xfs/xqm.h fs_info.h fshelp.h paths.h mntent.h mnttab.h sys/fstyp.h sys/fs_types.h sys/mntent.h sys/mnttab.h sys/statfs.h sys/statvfs.h sys/vfs.h sys/vfstab.h sys/vmmeter.h kvm.h wordexp.h locale.h)
+AC_CHECK_HEADERS([ \
+  ctype.h \
+  fs_info.h \
+  fshelp.h \
+  grp.h \
+  kvm.h \
+  limits.h \
+  locale.h \
+  mntent.h \
+  mnttab.h \
+  paths.h \
+  pwd.h \
+  sys/fs_types.h \
+  sys/fstyp.h \
+  sys/mntent.h \
+  sys/mnttab.h \
+  sys/statfs.h \
+  sys/statvfs.h \
+  sys/un.h \
+  sys/vfs.h \
+  sys/vfstab.h \
+  sys/vmmeter.h \
+  wordexp.h \
+])
+
+AC_CHECK_HEADERS([xfs/xqm.h], [], [],
+[
+#define _GNU_SOURCE
+])
 
 # For the dns plugin
 AC_CHECK_HEADERS(arpa/nameser.h)
@@ -623,8 +725,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"],
@@ -648,6 +748,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"])
@@ -679,23 +796,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"
@@ -795,8 +919,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"
@@ -1248,12 +1370,28 @@ 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"
 AC_CHECK_FUNCS(getvfsstat, [have_getvfsstat="yes"])
 have_listmntent="no"
 AC_CHECK_FUNCS(listmntent, [have_listmntent="yes"])
+have_getmntent_r="no"
+AC_CHECK_FUNCS(getmntent_r, [have_getmntent_r="yes"])
 
 have_getmntent="no"
 AC_CHECK_FUNCS(getmntent, [have_getmntent="c"])
@@ -1323,15 +1461,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
@@ -1422,6 +1560,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
@@ -1489,18 +1645,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:])
@@ -1800,6 +1986,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)
@@ -1815,7 +2031,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 {{{
@@ -2023,12 +2238,6 @@ then
                GCRYPT_CPPFLAGS=`"$with_libgcrypt_config" --cflags 2>/dev/null`
        fi
 
-       if test "x$GCRYPT_LDFLAGS" = "x"
-       then
-               gcrypt_exec_prefix=`"$with_libgcrypt_config" --exec-prefix 2>/dev/null`
-               GCRYPT_LDFLAGS="-L$gcrypt_exec_prefix/lib"
-       fi
-
        if test "x$GCRYPT_LIBS" = "x"
        then
                GCRYPT_LIBS=`"$with_libgcrypt_config" --libs 2>/dev/null`
@@ -2037,8 +2246,10 @@ fi
 
 SAVE_CPPFLAGS="$CPPFLAGS"
 SAVE_LDFLAGS="$LDFLAGS"
+SAVE_LIBS="$LIBS"
 CPPFLAGS="$CPPFLAGS $GCRYPT_CPPFLAGS"
 LDFLAGS="$LDFLAGS $GCRYPT_LDFLAGS"
+LIBS="$LIBS $GCRYPT_LIBS"
 
 if test "x$with_libgcrypt" = "xyes"
 then
@@ -2053,23 +2264,14 @@ fi
 
 if test "x$with_libgcrypt" = "xyes"
 then
-       if test "x$GCRYPT_LDFLAGS" != "x"
-       then
-               AC_MSG_NOTICE([gcrypt LDFLAGS: $GCRYPT_LDFLAGS])
-       fi
        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"
 LDFLAGS="$SAVE_LDFLAGS"
+LIBS="$SAVE_LIBS"
 
 if test "x$with_libgcrypt" = "xyes"
 then
@@ -2082,8 +2284,6 @@ AC_SUBST(GCRYPT_LIBS)
 AM_CONDITIONAL(BUILD_WITH_LIBGCRYPT, test "x$with_libgcrypt" = "xyes")
 # }}}
 
-
-###
 # --with-libgps {{{
 with_libgps_cflags=""
 with_libgps_ldflags=""
@@ -2134,6 +2334,92 @@ 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="$with_libgrpcpp_cppflags $GRPCPP_CFLAGS $CPPFLAGS -std=c++11"
+  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_LDFLAGS="$LDFLAGS"
+  SAVE_LIBS="$LIBS"
+  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)"]
+  )
+  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.])],
@@ -2159,11 +2445,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
@@ -2236,9 +2517,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.])],
@@ -2280,7 +2558,7 @@ then
                fi
 
                AC_MSG_CHECKING([for libjvm.so])
-               TMPVAR=`find -L "$with_java_home" -name libjvm.so -type f -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1`
+               TMPVAR=`find -L "$with_java_home" -type f \( -name libjvm.so -o -name libjvm.dylib \) -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1`
                if test "x$TMPVAR" != "x"
                then
                        AC_MSG_RESULT([found in $TMPVAR])
@@ -2331,6 +2609,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"
@@ -2371,9 +2653,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
@@ -2383,8 +2667,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
@@ -2395,6 +2679,7 @@ fi
 CPPFLAGS="$SAVE_CPPFLAGS"
 CFLAGS="$SAVE_CFLAGS"
 LDFLAGS="$SAVE_LDFLAGS"
+LIBS="$SAVE_LIBS"
 
 AC_SUBST(JAVA_CPPFLAGS)
 AC_SUBST(JAVA_CFLAGS)
@@ -2466,17 +2751,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
@@ -2589,13 +2882,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
@@ -2721,13 +3007,13 @@ AM_CONDITIONAL(BUILD_WITH_LIBMONGOC, test "x$with_libmongoc" = "xyes")
 
 # --with-libmosquitto {{{
 with_libmosquitto_cppflags=""
-with_libmosquitto_libs="-lmosquitto"
+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_libs="-L$withval/lib -lmosquitto"
+               with_libmosquitto_ldflags="-L$withval/lib"
                with_libmosquitto="yes"
        else
                with_libmosquitto="$withval"
@@ -2739,7 +3025,7 @@ AC_ARG_WITH(libmosquitto, [AS_HELP_STRING([--with-libmosquitto@<:@=PREFIX@:>@],
 if test "x$with_libmosquitto" = "xyes"
 then
        SAVE_CPPFLAGS="$CPPFLAGS"
-       CPPFLAGS="$with_libmosquitto_cppflags"
+       CPPFLAGS="$CPPFLAGS $with_libmosquitto_cppflags"
 
        AC_CHECK_HEADERS(mosquitto.h, [with_libmosquitto="yes"], [with_libmosquitto="no (mosquitto.h not found)"])
 
@@ -2749,8 +3035,8 @@ if test "x$with_libmosquitto" = "xyes"
 then
        SAVE_LDFLAGS="$LDFLAGS"
        SAVE_CPPFLAGS="$CPPFLAGS"
-       LDFLAGS="$with_libmosquitto_libs"
-       CPPFLAGS="$with_libmosquitto_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)"])
 
@@ -2760,8 +3046,10 @@ fi
 if test "x$with_libmosquitto" = "xyes"
 then
        BUILD_WITH_LIBMOSQUITTO_CPPFLAGS="$with_libmosquitto_cppflags"
-       BUILD_WITH_LIBMOSQUITTO_LIBS="$with_libmosquitto_libs"
+       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
 # }}}
@@ -2884,10 +3172,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
@@ -3018,7 +3302,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])
 
@@ -3277,22 +3561,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"
@@ -3304,7 +3588,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)"])
 
@@ -3314,7 +3598,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)"])
@@ -3325,8 +3609,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
 # }}}
@@ -3421,7 +3707,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=""
@@ -4032,76 +4354,102 @@ AM_CONDITIONAL(BUILD_WITH_LIBROUTEROS, test "x$with_librouteros" = "xyes")
 # }}}
 
 # --with-librrd {{{
-# AC_ARG_WITH (package, help-string, [action-if-given], [action-if-not-given])
 librrd_cflags=""
 librrd_ldflags=""
-librrd_threadsafe="yes"
+librrd_threadsafe="no"
 librrd_rrdc_update="no"
-AC_ARG_WITH(librrd, [AS_HELP_STRING([--with-librrd@<:@=PREFIX@:>@], [Path to rrdtool.])],
-[      if test "x$withval" != "xno" && test "x$withval" != "xyes"
-       then
-               librrd_cflags="-I$withval/include"
-               librrd_ldflags="-L$withval/lib"
-               with_librrd="yes"
-       else
-               with_librrd="$withval"
-       fi
-], [with_librrd="yes"])
+AC_ARG_WITH(librrd,
+  [AS_HELP_STRING([--with-librrd@<:@=PREFIX@:>@], [Path to rrdtool.])],
+  [
+    if test "x$withval" != "xno" && test "x$withval" != "xyes"
+    then
+      librrd_cflags="-I$withval/include"
+      librrd_ldflags="-L$withval/lib"
+      with_librrd="yes"
+    else
+      with_librrd="$withval"
+    fi
+  ],
+  [with_librrd="yes"]
+)
+
 if test "x$with_librrd" = "xyes"
 then
-       SAVE_CPPFLAGS="$CPPFLAGS"
-       SAVE_LDFLAGS="$LDFLAGS"
+  SAVE_LDFLAGS="$LDFLAGS"
+  LDFLAGS="$LDFLAGS $librrd_ldflags"
+  PKG_CHECK_MODULES([RRD], [librrd >= 1.6.0],
+    [
+      AC_CHECK_LIB([rrd], [rrd_update_r],
+        [librrd_threadsafe="yes"],
+        [:]
+      )
+      AC_CHECK_LIB([rrd], [rrdc_update],
+        [librrd_rrdc_update="yes"],
+        [:]
+      )
+    ],[:]
+  )
+  LDFLAGS="$SAVE_LDFLAGS"
 
-       CPPFLAGS="$CPPFLAGS $librrd_cflags"
-       LDFLAGS="$LDFLAGS $librrd_ldflags"
+  SAVE_CPPFLAGS="$CPPFLAGS"
+  CPPFLAGS="$CPPFLAGS $RRD_CFLAGS $librrd_cflags"
 
-       AC_CHECK_HEADERS(rrd.h,, [with_librrd="no (rrd.h not found)"])
+  AC_CHECK_HEADERS([rrd.h],, [with_librrd="no (rrd.h not found)"])
 
-       CPPFLAGS="$SAVE_CPPFLAGS"
-       LDFLAGS="$SAVE_LDFLAGS"
+  CPPFLAGS="$SAVE_CPPFLAGS"
 fi
-if test "x$with_librrd" = "xyes"
-then
-       SAVE_CPPFLAGS="$CPPFLAGS"
-       SAVE_LDFLAGS="$LDFLAGS"
 
-       CPPFLAGS="$CPPFLAGS $librrd_cflags"
-       LDFLAGS="$LDFLAGS $librrd_ldflags"
+if test "x$with_librrd" = "xyes" && test "x$librrd_threadsafe" = "xno"
+then
+  SAVE_LDFLAGS="$LDFLAGS"
+  LDFLAGS="$LDFLAGS $librrd_ldflags"
 
-       AC_CHECK_LIB(rrd_th, rrd_update_r,
-       [with_librrd="yes"
-        librrd_ldflags="$librrd_ldflags -lrrd_th -lm"
-       ],
-       [librrd_threadsafe="no"
-        AC_CHECK_LIB(rrd, rrd_update,
-        [with_librrd="yes"
-         librrd_ldflags="$librrd_ldflags -lrrd -lm"
-        ],
-        [with_librrd="no (symbol 'rrd_update' not found)"],
-        [-lm])
-       ],
-       [-lm])
+  AC_CHECK_LIB([rrd_th], [rrd_update_r],
+    [
+      librrd_ldflags="$librrd_ldflags -lrrd_th"
+      librrd_threadsafe="yes"
+      AC_CHECK_LIB([rrd_th], [rrdc_update],
+        [librrd_rrdc_update="yes"],
+        [:],
+      )
+    ],
+    [:]
+  )
+  LDFLAGS="$SAVE_LDFLAGS"
+fi
 
-       if test "x$librrd_threadsafe" = "xyes"
-       then
-               AC_CHECK_LIB(rrd_th, rrdc_update, [librrd_rrdc_update="yes"], [librrd_rrdc_update="no"])
-       else
-               AC_CHECK_LIB(rrd, rrdc_update, [librrd_rrdc_update="yes"], [librrd_rrdc_update="no"])
-       fi
+if test "x$with_librrd" = "xyes" && test "x$librrd_threadsafe" = "xno"
+then
+  SAVE_LDFLAGS="$LDFLAGS"
+  LDFLAGS="$LDFLAGS $librrd_ldflags"
 
-       CPPFLAGS="$SAVE_CPPFLAGS"
-       LDFLAGS="$SAVE_LDFLAGS"
+  AC_CHECK_LIB([rrd], [rrd_update],
+    [
+      librrd_ldflags="$librrd_ldflags -lrrd"
+      AC_CHECK_LIB([rrd], [rrdc_update],
+        [librrd_rrdc_update="yes"],
+        [:]
+      )
+    ],
+    [with_librrd="no (symbol 'rrd_update' not found)"]
+  )
+  LDFLAGS="$SAVE_LDFLAGS"
 fi
+
 if test "x$with_librrd" = "xyes"
 then
-       BUILD_WITH_LIBRRD_CFLAGS="$librrd_cflags"
-       BUILD_WITH_LIBRRD_LDFLAGS="$librrd_ldflags"
-       AC_SUBST(BUILD_WITH_LIBRRD_CFLAGS)
-       AC_SUBST(BUILD_WITH_LIBRRD_LDFLAGS)
+  BUILD_WITH_LIBRRD_CFLAGS="$RRD_CFLAGS $librrd_cflags"
+  BUILD_WITH_LIBRRD_LDFLAGS="$librrd_ldflags"
+  BUILD_WITH_LIBRRD_LIBS="$RRD_LIBS"
+  AC_SUBST(BUILD_WITH_LIBRRD_CFLAGS)
+  AC_SUBST(BUILD_WITH_LIBRRD_LDFLAGS)
+  AC_SUBST(BUILD_WITH_LIBRRD_LIBS)
 fi
 if test "x$librrd_threadsafe" = "xyes"
 then
-       AC_DEFINE(HAVE_THREADSAFE_LIBRRD, 1, [Define to 1 if you have the threadsafe rrd library (-lrrd_th).])
+  AC_DEFINE([HAVE_THREADSAFE_LIBRRD], [1],
+    [Define to 1 if the rrd library is thread-safe]
+  )
 fi
 # }}}
 
@@ -4136,11 +4484,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"
@@ -4171,74 +4514,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 {{{
@@ -4266,23 +4548,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" \
@@ -4348,6 +4623,7 @@ fi
 if test "x$with_libstatgrab" = "xyes"
 then
   SAVE_CFLAGS="$CFLAGS"
+  SAVE_LDFLAGS="$LDFLAGS"
   SAVE_LIBS="$LIBS"
 
   CFLAGS="$CFLAGS $with_libstatgrab_cflags"
@@ -4518,8 +4794,10 @@ if test "x$with_libudev" = "xyes"
 then
        BUILD_WITH_LIBUDEV_CFLAGS="$with_libudev_cflags"
        BUILD_WITH_LIBUDEV_LDFLAGS="$with_libudev_ldflags"
+       BUILD_WITH_LIBUDEV_LIBS="-ludev"
        AC_SUBST(BUILD_WITH_LIBUDEV_CFLAGS)
        AC_SUBST(BUILD_WITH_LIBUDEV_LDFLAGS)
+       AC_SUBST(BUILD_WITH_LIBUDEV_LIBS)
 fi
 AM_CONDITIONAL(BUILD_WITH_LIBUDEV, test "x$with_libudev" = "xyes")
 # }}}
@@ -4578,13 +4856,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
@@ -4657,6 +4928,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=""
@@ -4796,7 +5112,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
 ],
@@ -4818,8 +5134,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"
@@ -4861,13 +5177,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
@@ -4927,23 +5236,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
@@ -5042,17 +5348,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])
@@ -5176,11 +5471,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
 #
@@ -5273,7 +5569,7 @@ AC_DEFUN(
             then
                     enable_plugin="yes"
             else
-                    enable_plugin="no"
+                    enable_plugin="$2"
             fi
         else
             enable_plugin="$enable_all_plugins"
@@ -5290,7 +5586,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")
@@ -5319,6 +5615,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"
@@ -5329,6 +5626,7 @@ plugin_ethstat="no"
 plugin_fhcount="no"
 plugin_fscache="no"
 plugin_gps="no"
+plugin_grpc="no"
 plugin_interface="no"
 plugin_ipmi="no"
 plugin_ipvs="no"
@@ -5340,9 +5638,12 @@ 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"
 plugin_tape="no"
 plugin_tcpconns="no"
@@ -5355,6 +5656,7 @@ 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"
@@ -5363,9 +5665,9 @@ plugin_zookeeper="no"
 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"
@@ -5401,6 +5703,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"
@@ -5408,6 +5715,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
@@ -5419,8 +5734,8 @@ fi
 
 if test "x$ac_system" = "xAIX"
 then
-       plugin_tcpconns="yes"
        plugin_ipc="yes"
+       plugin_tcpconns="yes"
 fi
 
 # FreeBSD
@@ -5434,13 +5749,13 @@ 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
 
@@ -5469,7 +5784,6 @@ then
 fi
 
 # libi2c-dev
-with_libi2c="no"
 if test "x$ac_system" = "xLinux"
 then
 AC_CHECK_DECL(i2c_smbus_read_i2c_block_data,
@@ -5477,6 +5791,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,6 +5885,11 @@ then
        plugin_df="yes"
 fi
 
+if test "x$c_cv_have_getmntent_r" = "xyes"
+then
+       plugin_df="yes"
+fi
+
 # Df plugin: Check if we have either `statfs' or `statvfs' second.
 if test "x$plugin_df" = "xyes"
 then
@@ -5588,12 +5909,17 @@ 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" && test "x$with_libpthread" = "xyes"
+if test "x$with_libgps" = "xyes"
 then
        plugin_gps="yes"
 fi
@@ -5613,6 +5939,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
@@ -5643,6 +5974,16 @@ 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"
+fi
+
 if test "x$with_kvm_getswapinfo" = "xyes"
 then
        plugin_swap="yes"
@@ -5653,6 +5994,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"
@@ -5672,6 +6018,10 @@ then
        plugin_virt="yes"
 fi
 
+if test "x$with_libxenctrl" = "xyes"
+then
+  plugin_xencpu="yes"
+fi
 
 m4_divert_once([HELP_ENABLE], [
 collectd plugins:])
@@ -5693,144 +6043,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([gps],         [$plugin_gps],        [GPS 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([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([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],       [$with_libatasmart],  [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([zone],        [$plugin_zone],       [Solaris container 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
@@ -5982,13 +6337,16 @@ AC_SUBST(LCC_VERSION_STRING)
 AC_CONFIG_FILES(src/libcollectdclient/collectd/lcc_features.h)
 
 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 src/Makefile src/daemon/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile])
+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" \
@@ -6015,224 +6373,235 @@ then
        with_perl_bindings="yes ($PERL_BINDINGS_OPTIONS)"
 fi
 
-cat <<EOF;
-
-Configuration:
-  Build:
-    Platform  . . . . . . $ac_system
-    CC  . . . . . . . . . $CC
-    CFLAGS  . . . . . . . $AM_CFLAGS $CFLAGS
-    CPP . . . . . . . . . $CPP
-    CPPFLAGS  . . . . . . $CPPFLAGS
-    LD  . . . . . . . . . $LD
-    LDFLAGS . . . . . . . $LDFLAGS
-    YACC  . . . . . . . . $YACC
-    YFLAGS  . . . . . . . $YFLAGS
-
-  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
-    libgps  . . . . . . . $with_libgps
-    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
-    libmosquitto  . . . . $with_libmosquitto
-    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
-    gps . . . . . . . . . $enable_gps
-    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
-    mqtt  . . . . . . . . $enable_mqtt
-    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
-    zone  . . . . . . . . $enable_zone
-    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 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>
 
index 2252181..bb27aa3 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_varnish4 1}
-%{?el7:%global _has_broken_libmemcached 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_libmosquitto 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_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:0%{!?_has_broken_libmemcached: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_mqtt 0%{!?_without_mqtt:0%{?_has_libmosquitto}}
 %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:0%{!?_has_varnish4: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_zfs_arc 0%{!?_without_zfs_arc:1}
 %define with_zookeeper 0%{!?_without_zookeeper:1}
 
 %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}
-# plugin xmms disabled, requires xmms
-%define with_xmms 0%{!?_without_xmms:0}
+# plugin write_riemann disabled, requires a new enough riemann_c_client
+%define with_write_riemann 0%{!?_without_write_riemann:0}
+# plugin xencpu disabled, requires xen-devel from non-default repo
+%define with_xencpu 0%{!?_without_xencpu:0}
 # plugin zone disabled, requires Solaris
 %define with_zone 0%{!?_without_zone:0}
 
-Summary:       statistics collection and monitoring daemon
+# 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_mqtt 0
+%define with_rrdcached 0
+%define with_xmms 0
+%endif
+
+Summary:       Statistics collection and monitoring daemon
 Name:          collectd
-Version:       5.5.0
+Version:       5.5.2
 Release:       1%{?dist}
-URL:           http://collectd.org
-Source:                http://collectd.org/files/%{name}-%{version}.tar.bz2
+URL:           https://collectd.org
+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
@@ -322,6 +322,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
@@ -409,6 +418,16 @@ The gmond plugin subscribes to a Multicast group to receive data from gmond,
 the client daemon of the Ganglia project.
 %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
@@ -596,10 +615,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
@@ -644,10 +663,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
@@ -764,7 +783,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
@@ -789,6 +808,26 @@ 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
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: xmms-devel
+%description xmms
+The xmms plugin collects information from the XMMS music player.
+%endif
+
 %package collection3
 Summary:       Web-based viewer for collectd
 Group:         System Environment/Daemons
@@ -909,6 +948,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
@@ -933,6 +978,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
@@ -1041,6 +1092,12 @@ Collectd utilities
 %define _with_gmond --disable-gmond
 %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
@@ -1233,6 +1290,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
@@ -1330,10 +1393,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
@@ -1579,6 +1643,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
@@ -1604,6 +1674,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 \
@@ -1629,14 +1700,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} \
@@ -1650,100 +1723,103 @@ Collectd utilities
        %{?_with_filecount} \
        %{?_with_fscache} \
        %{?_with_gmond} \
+       %{?_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_multimeter} \
        %{?_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_zone} \
-       %{?_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}
@@ -1752,7 +1828,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
@@ -1808,26 +1884,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
@@ -1838,7 +1903,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
@@ -1854,7 +1919,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
@@ -1908,6 +1973,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
@@ -1977,6 +2045,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
@@ -2083,9 +2154,9 @@ fi
 %{_includedir}/collectd/network_buffer.h
 %{_includedir}/collectd/lcc_features.h
 %{_libdir}/pkgconfig/libcollectdclient.pc
+%{_libdir}/libcollectdclient.so
 
 %files -n libcollectdclient
-%{_libdir}/libcollectdclient.so
 %{_libdir}/libcollectdclient.so.*
 
 %files -n collectd-utils
@@ -2131,6 +2202,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
@@ -2171,6 +2247,11 @@ fi
 %{_libdir}/%{name}/gmond.so
 %endif
 
+%if %{with_grpc}
+%files grpc
+%{_libdir}/%{name}/grpc.so
+%endif
+
 %if %{with_hddtemp}
 %files hddtemp
 %{_libdir}/%{name}/hddtemp.so
@@ -2356,6 +2437,16 @@ 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
+%endif
+
 %files collection3
 %{_localstatedir}/www/collection3
 %{_sysconfdir}/httpd/conf.d/collection3.conf
@@ -2368,11 +2459,16 @@ fi
 %doc contrib/
 
 %changelog
-#* TODO: next feature release changelog
-#- New upstream version
-#- New plugins enabled by default: mqtt
-#- New plugins disabled by default: zone
-#
+* Tue Jul 26 2016 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.5.2-1
+- New upstream version
+- Contains fix for CVE-2016-6254
+- Change collectd.org url to https
+
+* Sat Jun 04 2016 Ruben Kerkhof <ruben@rubenkerkhof.com> 5.5.1-1
+- New upstream version
+- New plugins enabled by default: chrony, mqtt, notify_nagios
+- New plugins disabled by default: grpc, zone, xencpu
+
 * Wed May 27 2015 Marc Fournier <marc.fournier@camptocamp.com> 5.5.0-1
 - New upstream version
 - New plugins enabled by default: ceph, drbd, log_logstash, write_tsdb, smart,
@@ -2385,11 +2481,12 @@ fi
 - Install collectdctl, collectd-tg and collectd-nagios in collectd-utils.rpm
 - Add build-dependency on libcap-devel
 
-* Mon Aug 19 2013 Marc Fournier <marc.fournier@camptocamp.com> 5.4.0-1
+* Mon Aug 19 2013 Marc Fournier <marc.fournier@camptocamp.com> 5.4.2-1
 - New upstream version
 - Build netlink plugin by default
 - Enable cgroups, lvm and statsd plugins
 - Enable (but don't build by default) mic, aquaero and sigrok plugins
+- Enable modbus, memcachec and xmms plugins on RHEL7
 
 * Tue Aug 06 2013 Marc Fournier <marc.fournier@camptocamp.com> 5.3.1-1
 - New upstream version
index 0e758e4..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
@@ -10,12 +11,22 @@ EnvironmentFile=-/etc/default/collectd
 ProtectSystem=full
 ProtectHome=true
 
-# drop all capabilities:
-CapabilityBoundingSet=
-# use this instead if you use the dns or ping plugin
-#CapabilityBoundingSet=CAP_NET_RAW
-# turn this on if you use the iptables next to the dns or ping plugin
+# A few plugins won't work without some privileges, which you'll have to
+# specify using the CapabilityBoundingSet directive below.
+#
+# Here's a (incomplete) list of the plugins known capability requirements:
+#   ceph            CAP_DAC_OVERRIDE
+#   dns             CAP_NET_RAW
+#   exec            CAP_SETUID CAP_SETGID
+#   iptables        CAP_NET_ADMIN
+#   ping            CAP_NET_RAW
+#   turbostat       CAP_SYS_RAWIO
+#
+# Example, if you use the iptables plugin alongside the dns or ping plugin:
 #CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN
+#
+# By default, drop all capabilities:
+CapabilityBoundingSet=
 
 NoNewPrivileges=true
 
@@ -23,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]
index b8fc965..e6affa5 100755 (executable)
@@ -64,8 +64,8 @@ while (<>)
 
        $line =~ s#\{\{Plugin\|([^}]+)\}\}#$1 plugin#g;
        $line =~ s@\{\{Issue\|([^}]+)\}\}@#$1@g;
-       $line =~ s#\[\[[^|]+\|([^\]]+)\]\]#$1#g;
-       $line =~ s#\[\[([^|]+)\]\]#$1#g;
+       $line =~ s#\[\[[^|\]]+\|([^\]]+)\]\]#$1#g;
+       $line =~ s#\[\[([^|\]]+)\]\]#$1#g;
 
        $line =~ s#'''(.*?)'''#*$1*#g;
        $line =~ s#''(.*?)''#$1#g;
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 68ee552..12c7730 100644 (file)
@@ -17,18 +17,37 @@ endif
 AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"'
 AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
 
-AUTOMAKE_OPTIONS = subdir-objects
+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/libcommon.la daemon/libplugin_mock.la -lm
+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
@@ -36,7 +55,7 @@ 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/libcommon.la daemon/libplugin_mock.la
+test_utils_vl_lookup_LDADD = liblookup.la daemon/libplugin_mock.la
 if BUILD_WITH_LIBKSTAT
 test_utils_vl_lookup_LDADD += -lkstat
 endif
@@ -46,7 +65,7 @@ libmount_la_SOURCES = utils_mount.c utils_mount.h
 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/libcommon.la daemon/libplugin_mock.la
+test_utils_mount_LDADD = libmount.la daemon/libplugin_mock.la
 if BUILD_WITH_LIBKSTAT
 test_utils_mount_LDADD += -lkstat
 endif
@@ -55,11 +74,12 @@ 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
@@ -67,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
@@ -96,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 =
@@ -108,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 \
@@ -120,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
@@ -153,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
@@ -185,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
@@ -216,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
@@ -259,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
@@ -267,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)
@@ -335,7 +370,9 @@ disk_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
 disk_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
 endif
 if BUILD_WITH_LIBUDEV
-disk_la_LIBADD += -ludev
+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
@@ -349,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
@@ -379,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
@@ -412,10 +446,19 @@ 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 = -module -avoid-version $(BUILD_WITH_LIBGPS_LDFLAGS)
+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
@@ -451,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
 
@@ -474,10 +516,9 @@ endif
 if BUILD_PLUGIN_IPVS
 pkglib_LTLIBRARIES += ipvs.la
 ipvs_la_SOURCES = ipvs.c
-if IP_VS_H_NEEDS_KERNEL_CFLAGS
-ipvs_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
-else
 ipvs_la_CFLAGS = $(AM_CFLAGS)
+if IP_VS_H_NEEDS_KERNEL_CFLAGS
+ipvs_la_CFLAGS += $(KERNEL_CFLAGS)
 endif
 ipvs_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 endif
@@ -521,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)
@@ -537,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
 
@@ -651,8 +692,8 @@ endif
 if BUILD_PLUGIN_MQTT
 pkglib_LTLIBRARIES += mqtt.la
 mqtt_la_SOURCES = mqtt.c
-mqtt_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 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
 
@@ -665,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
@@ -696,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
@@ -722,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
@@ -743,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
@@ -767,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
@@ -783,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
 
@@ -808,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
@@ -820,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)\"
@@ -843,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
@@ -874,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
@@ -918,17 +957,17 @@ endif
 if BUILD_PLUGIN_RRDCACHED
 pkglib_LTLIBRARIES += rrdcached.la
 rrdcached_la_SOURCES = rrdcached.c utils_rrdcreate.c utils_rrdcreate.h
-rrdcached_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+rrdcached_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRRD_LDFLAGS)
 rrdcached_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS)
-rrdcached_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS)
+rrdcached_la_LIBADD = $(BUILD_WITH_LIBRRD_LIBS)
 endif
 
 if BUILD_PLUGIN_RRDTOOL
 pkglib_LTLIBRARIES += rrdtool.la
 rrdtool_la_SOURCES = rrdtool.c utils_rrdcreate.c utils_rrdcreate.h
-rrdtool_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+rrdtool_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRRD_LDFLAGS)
 rrdtool_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS)
-rrdtool_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS)
+rrdtool_la_LIBADD = $(BUILD_WITH_LIBRRD_LIBS)
 endif
 
 if BUILD_PLUGIN_SENSORS
@@ -948,18 +987,18 @@ 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
 if BUILD_WITH_LIBUDEV
 pkglib_LTLIBRARIES += smart.la
 smart_la_SOURCES = smart.c
-smart_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBATASMART_CPPFLAGS)
-smart_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBATASMART_LDFLAGS)
-smart_la_LIBADD = $(BUILD_WITH_LIBATASMART_LIBS) -ludev
+smart_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBATASMART_CPPFLAGS) $(BUILD_WITH_LIBUDEV_CFLAGS)
+smart_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBATASMART_LDFLAGS) $(BUILD_WITH_LIBUDEV_LDFLAGS)
+smart_la_LIBADD = $(BUILD_WITH_LIBATASMART_LIBS) $(BUILD_WITH_LIBUDEV_LIBS)
 endif
 endif
 
@@ -973,16 +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
 statsd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-statsd_la_LIBADD = liblatency.la -lpthread -lm
+statsd_la_LIBADD = liblatency.la -lm
 endif
 
 if BUILD_PLUGIN_SWAP
@@ -1133,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
@@ -1208,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
@@ -1257,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
-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_SOURCES = write_riemann.c write_riemann_threshold.c write_riemann_threshold.h
+write_riemann_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBRIEMANN_CLIENT_LIBS)
+write_riemann_la_CFLAGS = $(AM_CFLAGS) $(LIBRIEMANN_CLIENT_CFLAGS)
 endif
 
 if BUILD_PLUGIN_WRITE_SENSU
@@ -1281,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
@@ -1292,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
 
@@ -1317,7 +1349,6 @@ BUILT_SOURCES += $(dist_man_MANS)
 if BUILD_PLUGIN_ZONE
 pkglib_LTLIBRARIES += zone.la
 zone_la_SOURCES = zone.c
-zone_la_CFLAGS = $(AM_CFLAGS)
 zone_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 endif
 
@@ -1337,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 \
@@ -1356,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 \
@@ -1367,32 +1401,26 @@ 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 \
                echo "$@ has some POD errors!"; false; \
        fi
 
+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_1 =
+
 # Protocol buffer for the "pinba" plugin.
 EXTRA_DIST += pinba.proto
-if HAVE_PROTOC_C
+if BUILD_PLUGIN_PINBA
 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
-       protoc-c -I$(srcdir) --c_out . $(srcdir)/pinba.proto
-endif
-
-# Protocol buffer for the "write_riemann" plugin.
-EXTRA_DIST += riemann.proto
-if HAVE_PROTOC_C
-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
-       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:
@@ -1413,4 +1441,11 @@ uninstall-hook:
        rm -f $(DESTDIR)$(sysconfdir)/collectd.conf
        rm -f $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
 
-
+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/libplugin_mock.la $(BUILD_WITH_LIBYAJL_LIBS)
+check_PROGRAMS += test_plugin_ceph
+TESTS += test_plugin_ceph
+endif
index 8175c66..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,13 +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); \
-      ERROR ("aggregation plugin: malloc() failed."); \
+      free (inst); \
+      ERROR ("aggregation plugin: calloc() failed."); \
       return (NULL); \
     } \
-    memset (inst->state_ ## field, 0, sizeof (*inst->state_ ## field)); \
   } \
 } while (0)
 
@@ -349,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)
   {
@@ -487,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;
 
@@ -525,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));
@@ -543,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;
 
@@ -681,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)
@@ -699,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;
 
@@ -717,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;
 
@@ -738,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 aba4f01..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>
 
@@ -199,11 +198,11 @@ static char *camqp_strerror (camqp_config_t *conf, /* {{{ */
     switch (r.reply_type)
     {
         case AMQP_RESPONSE_NORMAL:
-            sstrncpy (buffer, "Success", sizeof (buffer));
+            sstrncpy (buffer, "Success", buffer_size);
             break;
 
         case AMQP_RESPONSE_NONE:
-            sstrncpy (buffer, "Missing RPC reply type", sizeof (buffer));
+            sstrncpy (buffer, "Missing RPC reply type", buffer_size);
             break;
 
         case AMQP_RESPONSE_LIBRARY_EXCEPTION:
@@ -215,7 +214,7 @@ static char *camqp_strerror (camqp_config_t *conf, /* {{{ */
                 return (sstrerror (r.library_error, buffer, buffer_size));
 #endif
             else
-                sstrncpy (buffer, "End of stream", sizeof (buffer));
+                sstrncpy (buffer, "End of stream", buffer_size);
             break;
 
         case AMQP_RESPONSE_SERVER_EXCEPTION:
@@ -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 41b807a..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,
@@ -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;
 
@@ -464,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++;
@@ -519,12 +517,9 @@ static void submit_scoreboard (char *buf, apache_t *st)
 
 static int apache_read_host (user_data_t *user_data) /* {{{ */
 {
-       int i;
-
        char *ptr;
        char *saveptr;
-       char *lines[16];
-       int   lines_num = 0;
+       char *line;
 
        char *fields[4];
        int   fields_num;
@@ -533,13 +528,16 @@ static int apache_read_host (user_data_t *user_data) /* {{{ */
 
        st = user_data->data;
 
+       int status;
+
+       char *content_type;
+       static const char *text_plain = "text/plain";
+
        assert (st->url != NULL);
        /* (Assured by `config_add') */
 
        if (st->curl == NULL)
        {
-               int status;
-
                status = init_host (st);
                if (status != 0)
                        return (-1);
@@ -562,31 +560,29 @@ static int apache_read_host (user_data_t *user_data) /* {{{ */
                st->server_type = APACHE;
        }
 
-       ptr = st->apache_buffer;
-       saveptr = NULL;
-       while ((lines[lines_num] = strtok_r (ptr, "\n\r", &saveptr)) != NULL)
+       status = curl_easy_getinfo (st->curl, CURLINFO_CONTENT_TYPE, &content_type);
+       if ((status == CURLE_OK) && (content_type != NULL) &&
+           (strncasecmp (content_type, text_plain, strlen (text_plain)) != 0))
        {
-               ptr = NULL;
-               lines_num++;
-
-               if (lines_num >= 16)
-                       break;
+               WARNING ("apache plugin: `Content-Type' response header is not `%s' "
+                       "(received: `%s'). Expecting unparseable data. Please check `URL' "
+                       "parameter (missing `?auto' suffix ?)",
+                       text_plain, content_type);
        }
 
-       for (i = 0; i < lines_num; i++)
+       ptr = st->apache_buffer;
+       saveptr = NULL;
+       while ((line = strtok_r (ptr, "\n\r", &saveptr)) != NULL)
        {
-               fields_num = strsplit (lines[i], fields, 4);
+               ptr = NULL;
+               fields_num = strsplit (line, fields, STATIC_ARRAY_SIZE (fields));
 
                if (fields_num == 3)
                {
-                       if ((strcmp (fields[0], "Total") == 0)
-                                       && (strcmp (fields[1], "Accesses:") == 0))
-                               submit_derive ("apache_requests", "",
-                                               atoll (fields[2]), st);
-                       else if ((strcmp (fields[0], "Total") == 0)
-                                       && (strcmp (fields[1], "kBytes:") == 0))
-                               submit_derive ("apache_bytes", "",
-                                               1024LL * atoll (fields[2]), st);
+                       if ((strcmp (fields[0], "Total") == 0) && (strcmp (fields[1], "Accesses:") == 0))
+                               submit_derive ("apache_requests", "", atoll (fields[2]), st);
+                       else if ((strcmp (fields[0], "Total") == 0) && (strcmp (fields[1], "kBytes:") == 0))
+                               submit_derive ("apache_bytes", "", 1024LL * atoll (fields[2]), st);
                }
                else if (fields_num == 2)
                {
index 29d58c3..cc20357 100644 (file)
@@ -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 */
 # include <netinet/in.h>
 #endif
 
+#ifndef APCUPS_SERVER_TIMEOUT
+# define APCUPS_SERVER_TIMEOUT 15.0
+#endif
+
 #ifndef APCUPS_DEFAULT_NODE
 # define APCUPS_DEFAULT_NODE "localhost"
 #endif
@@ -85,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;
 
@@ -111,15 +116,14 @@ static int net_open (char const *node, char const *service)
 {
        int              sd;
        int              status;
-       struct addrinfo  ai_hints;
        struct addrinfo *ai_return;
        struct addrinfo *ai_list;
 
-       /* Resolve name */
-       memset (&ai_hints, 0, sizeof (ai_hints));
        /* TODO: Change this to `AF_UNSPEC' if apcupsd can handle IPv6 */
-       ai_hints.ai_family   = AF_INET;
-       ai_hints.ai_socktype = SOCK_STREAM;
+       struct addrinfo ai_hints = {
+               .ai_family = AF_INET,
+               .ai_socktype = SOCK_STREAM
+       };
 
        status = getaddrinfo (node, service, &ai_hints, &ai_return);
        if (status != 0)
@@ -220,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;
 
@@ -322,9 +326,6 @@ static int apc_query_server (char const *node, char const *service,
                printf ("net_recv = `%s';\n", recvline);
 #endif /* if APCMAIN */
 
-               if (strncmp ("END APC", recvline, strlen ("END APC")) == 0)
-                       break;
-
                toksaveptr = NULL;
                tokptr = strtok_r (recvline, " :\t", &toksaveptr);
                while (tokptr != NULL)
@@ -380,9 +381,9 @@ static int apc_query_server (char const *node, char const *service,
 
 static int apcups_config (oconfig_item_t *ci)
 {
-       int i;
+       _Bool persistent_conn_set = 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;
 
@@ -392,16 +393,29 @@ static int apcups_config (oconfig_item_t *ci)
                        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)
+               else if (strcasecmp (child->key, "PersistentConnection") == 0) {
                        cf_util_get_boolean (child, &conf_persistent_conn);
+                       persistent_conn_set = 1;
+               }
                else
                        ERROR ("apcups plugin: Unknown config option \"%s\".", child->key);
        }
 
+       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;
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 2ba3c77..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))
index c5e7f77..fba3450 100644 (file)
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "utils_cache.h"
 #include "plugin.h"
 /* ------------ MPL115 defines ------------ */
 /* I2C address of the MPL115 sensor */
 #define MPL115_I2C_ADDRESS          0x60
-                                    
-/* register addresses */            
+
+/* register addresses */
 #define MPL115_ADDR_CONV            0x00
 #define MPL115_ADDR_COEFFS          0x04
-                                    
-/* register sizes */                
+
+/* register sizes */
 #define MPL115_NUM_CONV             4
 #define MPL115_NUM_COEFFS           12
-                                    
-/* commands / addresses */          
+
+/* commands / addresses */
 #define MPL115_CMD_CONVERT_PRESS    0x10
 #define MPL115_CMD_CONVERT_TEMP     0x11
 #define MPL115_CMD_CONVERT_BOTH     0x12
-                                    
+
 #define MPL115_CONVERSION_RETRIES   5
 
 
 #define MPL3115_PT_DATA_DREM        0x04
 #define MPL3115_PT_DATA_PDEF        0x02
 #define MPL3115_PT_DATA_TDEF        0x01
-                                    
+
 #define MPL3115_DR_STATUS_TDR       0x02
 #define MPL3115_DR_STATUS_PDR       0x04
 #define MPL3115_DR_STATUS_PTDR      0x08
 #define MPL3115_DR_STATUS_DR        (MPL3115_DR_STATUS_TDR | MPL3115_DR_STATUS_PDR | MPL3115_DR_STATUS_PTDR)
-                                    
+
 #define MPL3115_DR_STATUS_TOW       0x20
 #define MPL3115_DR_STATUS_POW       0x40
 #define MPL3115_DR_STATUS_PTOW      0x80
 /* I2C address of the BMP085 sensor */
 #define BMP085_I2C_ADDRESS          0x77
 
-/* register addresses */            
+/* register addresses */
 #define BMP085_ADDR_ID_REG          0xD0
 #define BMP085_ADDR_VERSION         0xD1
 
 #define BMP085_ADDR_CTRL_REG        0xF4
 #define BMP085_ADDR_COEFFS          0xAA
 
-/* register sizes */                
+/* register sizes */
 #define BMP085_NUM_COEFFS           22
 
 /* commands, values */
@@ -178,7 +179,7 @@ static const char *config_keys[] =
 };
 
 static int    config_keys_num     = STATIC_ARRAY_SIZE(config_keys);
-                                  
+
 static char * config_device       = NULL;  /**< I2C bus device */
 static int    config_oversample   = 1;     /**< averaging window */
 
@@ -187,9 +188,9 @@ static double config_temp_offset  = 0.0;   /**< temperature offset */
 
 static double config_altitude     = NAN;   /**< altitude */
 static int    config_normalize    = 0;     /**< normalization method */
-                                  
+
 static _Bool  configured          = 0;     /**< the whole plugin config status */
-                                  
+
 static int    i2c_bus_fd          = -1;    /**< I2C bus device FD */
 
 static enum Sensor_type sensor_type = Sensor_none; /**< detected/used sensor type */
@@ -243,7 +244,7 @@ static averaging_t pressure_averaging    = { NULL, 0, 0L, 0 };
 static averaging_t temperature_averaging = { NULL, 0, 0L, 0 };
 
 
-/** 
+/**
  * Create / allocate averaging buffer
  *
  * The buffer is initialized with zeros.
@@ -309,9 +310,9 @@ static double averaging_add_sample(averaging_t * avg, long int sample)
     avg->ring_buffer[avg->ring_buffer_head] = sample;
     avg->ring_buffer_head = (avg->ring_buffer_head+1) % avg->ring_buffer_size;
     result = (double)(avg->ring_buffer_sum) / (double)(avg->ring_buffer_size);
-    
-    DEBUG ("barometer: averaging_add_sample - added %ld, result = %lf", 
-           sample, 
+
+    DEBUG ("barometer: averaging_add_sample - added %ld, result = %lf",
+           sample,
            result);
 
     return result;
@@ -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 */
-    size_t i;
 
     gauge_t values_history[REF_TEMP_AVG_NUM];
 
@@ -445,7 +445,7 @@ 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 %zu: %lf **",
                        i, values[i]);
@@ -473,8 +473,8 @@ static int get_reference_temperature(double * result)
             list = list->next;
             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 %zu: %lf",
                    i, values_history[i]);
@@ -499,7 +499,7 @@ 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 %zu: %lf **",
                        i, values[i]);
@@ -530,7 +530,7 @@ static int get_reference_temperature(double * result)
         }
         list = list->next;
     }  /* while sensor list */
-    
+
     if(*result == NAN)
     {
         ERROR("barometer: get_reference_temperature - no sensor available (yet?)");
@@ -543,7 +543,7 @@ static int get_reference_temperature(double * result)
 
 /* ------------------------ MPL115 access ------------------------ */
 
-/** 
+/**
  * Detect presence of a MPL115 pressure sensor.
  *
  * Unfortunately there seems to be no ID register so we just try to read first
@@ -551,7 +551,7 @@ static int get_reference_temperature(double * result)
  * MPL115. We should use this check as the last resort (which would be the typical
  * case anyway since MPL115 is the least accurate sensor).
  * As a sideeffect will leave set I2C slave address.
- * 
+ *
  * @return 1 if MPL115, 0 otherwise
  */
 static int MPL115_detect(void)
@@ -687,7 +687,7 @@ static void MPL115_convert_adc_to_real(double   adc_pressure,
     Pcomp = mpl115_coeffA0 +                                            \
         (mpl115_coeffB1 + mpl115_coeffC11*adc_pressure + mpl115_coeffC12*adc_temp) * adc_pressure + \
         (mpl115_coeffB2 + mpl115_coeffC22*adc_temp) * adc_temp;
-    
+
     *pressure = ((1150.0-500.0) * Pcomp / 1023.0) + 500.0;
     *temperature = (472.0 - adc_temp) / 5.35 + 25.0;
     DEBUG ("barometer: MPL115_convert_adc_to_real - got %lf hPa, %lf C",
@@ -799,11 +799,11 @@ static int MPL115_read_averaged(double * pressure, double * temperature)
 
 /* ------------------------ MPL3115 access ------------------------ */
 
-/** 
+/**
  * Detect presence of a MPL3115 pressure sensor by checking register "WHO AM I"
  *
  * As a sideeffect will leave set I2C slave address.
- * 
+ *
  * @return 1 if MPL3115, 0 otherwise
  */
 static int MPL3115_detect(void)
@@ -830,10 +830,10 @@ static int MPL3115_detect(void)
     return 0;
 }
 
-/** 
+/**
  * Adjusts oversampling to values supported by MPL3115
  *
- * MPL3115 supports only power of 2 in the range 1 to 128. 
+ * MPL3115 supports only power of 2 in the range 1 to 128.
  */
 static void MPL3115_adjust_oversampling(void)
 {
@@ -881,13 +881,13 @@ static void MPL3115_adjust_oversampling(void)
     }
 
     DEBUG("barometer: MPL3115_adjust_oversampling - correcting oversampling from %d to %d",
-          config_oversample, 
+          config_oversample,
           new_val);
     config_oversample = new_val;
 }
 
-/** 
- * Read sensor averegaed measurements
+/**
+ * Read sensor averaged measurements
  *
  * @param pressure    averaged measured pressure
  * @param temperature averaged measured temperature
@@ -901,7 +901,7 @@ static int MPL3115_read(double * pressure, double * temperature)
     __u8 data[MPL3115_NUM_CONV_VALS];
     long int tmp_value = 0;
     char errbuf[1024];
-    
+
     /* Set Active - activate the device from standby */
     res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1);
     if (res < 0)
@@ -911,8 +911,8 @@ static int MPL3115_read(double * pressure, double * temperature)
         return 1;
     }
     ctrl = res;
-    res = i2c_smbus_write_byte_data(i2c_bus_fd, 
-                                    MPL3115_REG_CTRL_REG1, 
+    res = i2c_smbus_write_byte_data(i2c_bus_fd,
+                                    MPL3115_REG_CTRL_REG1,
                                     ctrl | MPL3115_CTRL_REG1_SBYB);
     if (res < 0)
     {
@@ -920,10 +920,10 @@ static int MPL3115_read(double * pressure, double * temperature)
                sstrerror (errno, errbuf, sizeof (errbuf)));
         return 1;
     }
-    
+
     /* base sleep is 5ms x OST */
     usleep(5000 * config_oversample);
-      
+
     /* check the flags/status if ready */
     res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
     if (res < 0)
@@ -932,12 +932,12 @@ static int MPL3115_read(double * pressure, double * temperature)
                sstrerror (errno, errbuf, sizeof (errbuf)));
         return 1;
     }
-    
+
     while ((res & MPL3115_DR_STATUS_DR) != MPL3115_DR_STATUS_DR)
     {
         /* try some extra sleep... */
         usleep(10000);
-        
+
         /* ... and repeat the check. The conversion has to finish sooner or later. */
         res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
         if (res < 0)
@@ -947,10 +947,10 @@ static int MPL3115_read(double * pressure, double * temperature)
             return 1;
         }
     }
-    
+
     /* Now read all the data in one block. There is address autoincrement. */
-    res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, 
-                                        MPL3115_REG_OUT_P_MSB, 
+    res = i2c_smbus_read_i2c_block_data(i2c_bus_fd,
+                                        MPL3115_REG_OUT_P_MSB,
                                         MPL3115_NUM_CONV_VALS,
                                         data);
     if (res < 0)
@@ -959,11 +959,11 @@ static int MPL3115_read(double * pressure, double * temperature)
                sstrerror (errno, errbuf, sizeof (errbuf)));
         return 1;
     }
-    
+
     tmp_value = (data[0] << 16) | (data[1] << 8) | data[2];
     *pressure = ((double) tmp_value) / 4.0 / 16.0 / 100.0;
     DEBUG ("barometer: MPL3115_read - absolute pressure = %lf hPa", *pressure);
-    
+
     if(data[3] > 0x7F)
     {
         data[3] = ~data[3] + 1;
@@ -974,16 +974,16 @@ static int MPL3115_read(double * pressure, double * temperature)
     {
         *temperature = data[3];
     }
-    
+
     *temperature += (double)(data[4]) / 256.0;
     DEBUG ("barometer: MPL3115_read - temperature = %lf C", *temperature);
-    
+
     return 0;
 }
 
-/** 
+/**
  * Initialize MPL3115 for barometeric measurements
- * 
+ *
  * @return 0 if successful
  */
 static int MPL3115_init_sensor(void)
@@ -991,18 +991,18 @@ static int MPL3115_init_sensor(void)
     __s32 res;
     __s8 offset;
     char errbuf[1024];
-    
+
     /* Reset the sensor. It will reset immediately without ACKing */
     /* the transaction, so no error handling here. */
-    i2c_smbus_write_byte_data(i2c_bus_fd, 
-                              MPL3115_REG_CTRL_REG1, 
+    i2c_smbus_write_byte_data(i2c_bus_fd,
+                              MPL3115_REG_CTRL_REG1,
                               MPL3115_CTRL_REG1_RST);
-    
+
     /* wait some time for the reset to finish */
     usleep(100000);
 
     /* now it should be in standby already so we can go and configure it */
-    
+
     /*  Set temperature offset. */
     /*  result = ADCtemp + offset [C] */
     offset = (__s8) (config_temp_offset * 16.0);
@@ -1013,7 +1013,7 @@ static int MPL3115_init_sensor(void)
                sstrerror (errno, errbuf, sizeof (errbuf)));
         return -1;
     }
-    
+
     /*  Set pressure offset. */
     /*  result = ADCpress + offset [hPa] */
     offset = (__s8) (config_press_offset * 100.0 / 4.0);
@@ -1026,7 +1026,7 @@ static int MPL3115_init_sensor(void)
     }
 
     /* Enable Data Flags in PT_DATA_CFG - flags on both pressure and temp */
-    res = i2c_smbus_write_byte_data(i2c_bus_fd, 
+    res = i2c_smbus_write_byte_data(i2c_bus_fd,
                                     MPL3115_REG_PT_DATA_CFG,
                                     MPL3115_PT_DATA_DREM        \
                                     | MPL3115_PT_DATA_PDEF      \
@@ -1038,9 +1038,9 @@ static int MPL3115_init_sensor(void)
         return -1;
     }
 
-    /* Set to barometer with an OSR */ 
-    res = i2c_smbus_write_byte_data(i2c_bus_fd, 
-                                    MPL3115_REG_CTRL_REG1, 
+    /* Set to barometer with an OSR */
+    res = i2c_smbus_write_byte_data(i2c_bus_fd,
+                                    MPL3115_REG_CTRL_REG1,
                                     mpl3115_oversample);
     if (res < 0)
     {
@@ -1054,11 +1054,11 @@ static int MPL3115_init_sensor(void)
 
 /* ------------------------ BMP085 access ------------------------ */
 
-/** 
+/**
  * Detect presence of a BMP085 pressure sensor by checking its ID register
  *
  * As a sideeffect will leave set I2C slave address.
- * 
+ *
  * @return 1 if BMP085, 0 otherwise
  */
 static int BMP085_detect(void)
@@ -1098,10 +1098,10 @@ static int BMP085_detect(void)
 }
 
 
-/** 
+/**
  * Adjusts oversampling settings to values supported by BMP085
  *
- * BMP085 supports only 1,2,4 or 8 samples. 
+ * BMP085 supports only 1,2,4 or 8 samples.
  */
 static void BMP085_adjust_oversampling(void)
 {
@@ -1137,13 +1137,13 @@ static void BMP085_adjust_oversampling(void)
     }
 
     DEBUG("barometer: BMP085_adjust_oversampling - correcting oversampling from %d to %d",
-          config_oversample, 
+          config_oversample,
           new_val);
     config_oversample = new_val;
 }
 
 
-/** 
+/**
  * Read the BMP085 sensor conversion coefficients.
  *
  * These are (device specific) constants so we can read them just once.
@@ -1153,12 +1153,12 @@ static void BMP085_adjust_oversampling(void)
 static int BMP085_read_coeffs(void)
 {
     __s32 res;
-    __u8 coeffs[BMP085_NUM_COEFFS]; 
+    __u8 coeffs[BMP085_NUM_COEFFS];
     char errbuf[1024];
 
-    res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, 
+    res = i2c_smbus_read_i2c_block_data(i2c_bus_fd,
                                         BMP085_ADDR_COEFFS,
-                                        BMP085_NUM_COEFFS, 
+                                        BMP085_NUM_COEFFS,
                                         coeffs);
     if (res < 0)
     {
@@ -1166,7 +1166,7 @@ static int BMP085_read_coeffs(void)
                sstrerror (errno, errbuf, sizeof (errbuf)));
         return -1;
     }
-    
+
     bmp085_AC1 = ((int16_t)  coeffs[0]  <<8) | (int16_t)  coeffs[1];
     bmp085_AC2 = ((int16_t)  coeffs[2]  <<8) | (int16_t)  coeffs[3];
     bmp085_AC3 = ((int16_t)  coeffs[4]  <<8) | (int16_t)  coeffs[5];
@@ -1237,13 +1237,13 @@ static void BMP085_convert_adc_to_real(long adc_pressure,
     X2 = (((long)bmp085_AC2 * B6) >> 11);
     X3 = X1 + X2;
     B3 = (((((long)bmp085_AC1 * 4) + X3) << bmp085_oversampling) + 2) >> 2;
-    
+
     /* B4 */
     X1 = (((long)bmp085_AC3*B6) >> 13);
     X2 = (bmp085_B1*((B6*B6) >> 12) ) >> 16;
     X3 = ((X1 + X2) + 2 ) >> 2;
     B4 = ((long)bmp085_AC4* (unsigned long)(X3 + 32768)) >> 15;
-    
+
     /* B7, P */
     B7 =  (unsigned long)(adc_pressure - B3)*(50000>>bmp085_oversampling);
     if( B7 < 0x80000000 )
@@ -1258,15 +1258,15 @@ static void BMP085_convert_adc_to_real(long adc_pressure,
     X1 = (X1 * 3038) >> 16;
     X2 = ((-7357) * P) >> 16;
     P = P + ( ( X1 + X2 + 3791 ) >> 4);
-    
-    *pressure = P / 100.0; // in [hPa] 
+
+    *pressure = P / 100.0; // in [hPa]
     DEBUG ("barometer: BMP085_convert_adc_to_real - got %lf hPa, %lf C",
            *pressure,
            *temperature);
 }
 
-    
-/** 
+
+/**
  * Read compensated sensor measurements
  *
  * @param pressure    averaged measured pressure
@@ -1298,9 +1298,9 @@ static int BMP085_read(double * pressure, double * temperature)
     usleep(BMP085_TIME_CNV_TEMP); /* wait for the conversion */
 
     res = i2c_smbus_read_i2c_block_data( i2c_bus_fd,
-                                         BMP085_ADDR_CONV, 
+                                         BMP085_ADDR_CONV,
                                          2,
-                                         measBuff); 
+                                         measBuff);
     if (res < 0)
     {
         ERROR ("barometer: BMP085_read - problem reading temperature data: %s",
@@ -1308,12 +1308,12 @@ static int BMP085_read(double * pressure, double * temperature)
         return 1;
     }
 
-    adc_temperature = ( (unsigned short)measBuff[0] << 8 ) + measBuff[1]; 
-    
+    adc_temperature = ( (unsigned short)measBuff[0] << 8 ) + measBuff[1];
+
 
     /* get presure */
     res = i2c_smbus_write_byte_data( i2c_bus_fd,
-                                     BMP085_ADDR_CTRL_REG, 
+                                     BMP085_ADDR_CTRL_REG,
                                      bmp085_cmdCnvPress );
     if (res < 0)
     {
@@ -1325,7 +1325,7 @@ static int BMP085_read(double * pressure, double * temperature)
     usleep(bmp085_timeCnvPress); /* wait for the conversion */
 
     res = i2c_smbus_read_i2c_block_data( i2c_bus_fd,
-                                         BMP085_ADDR_CONV, 
+                                         BMP085_ADDR_CONV,
                                          3,
                                          measBuff );
     if (res < 0)
@@ -1336,7 +1336,7 @@ static int BMP085_read(double * pressure, double * temperature)
     }
 
     adc_pressure = (long)((((ulong)measBuff[0]<<16) | ((ulong)measBuff[1]<<8) | (ulong)measBuff[2] ) >> (8 - bmp085_oversampling));
-    
+
 
     DEBUG ("barometer: BMP085_read - raw pressure ADC value = %ld, " \
            "raw temperature ADC value = %ld",
@@ -1351,16 +1351,16 @@ static int BMP085_read(double * pressure, double * temperature)
 
 
 /* ------------------------ Sensor detection ------------------------ */
-/** 
+/**
  * Detect presence of a supported sensor.
  *
  * As a sideeffect will leave set I2C slave address.
  * The detection is done in the order BMP085, MPL3115, MPL115 and stops after
  * first sensor beeing found.
- * 
+ *
  * @return detected sensor type
  */
-enum Sensor_type Detect_sensor_type(void)
+static enum Sensor_type detect_sensor_type(void)
 {
     if(BMP085_detect())
         return Sensor_BMP085;
@@ -1385,7 +1385,7 @@ enum Sensor_type Detect_sensor_type(void)
  * - MSLP_INTERNATIONAL - see http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation
  *           Requires #config_altitude
  *
- * - MSLP_DEU_WETT - formula as recommended by the Deutsche Wetterdienst. See 
+ * - MSLP_DEU_WETT - formula as recommended by the Deutsche Wetterdienst. See
  *                http://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Theorie
  *           Requires both #config_altitude and temperature reference(s).
  *
@@ -1413,12 +1413,12 @@ static double abs_to_mean_sea_level_pressure(double abs_pressure)
     case MSLP_NONE:
         mean = abs_pressure;
         break;
-        
+
     case MSLP_INTERNATIONAL:
         mean = abs_pressure / \
             pow(1.0 - 0.0065*config_altitude/288.15, 9.80665*0.0289644/(8.31447*0.0065));
         break;
-        
+
     case MSLP_DEU_WETT:
     {
         double E; /* humidity */
@@ -1433,7 +1433,7 @@ static double abs_to_mean_sea_level_pressure(double abs_pressure)
     break;
 
     default:
-        ERROR ("barometer: abs_to_mean_sea_level_pressure: wrong conversion method %d", 
+        ERROR ("barometer: abs_to_mean_sea_level_pressure: wrong conversion method %d",
                config_normalize);
         mean = abs_pressure;
         break;
@@ -1444,17 +1444,17 @@ static double abs_to_mean_sea_level_pressure(double abs_pressure)
            config_normalize,
            mean);
 
-    return mean; 
+    return mean;
 }
 
 /* ------------------------ main plugin callbacks ------------------------ */
 
-/** 
+/**
  * Main plugin configuration callback (using simple config)
- * 
+ *
  * @param key   configuration key we should process
  * @param value configuration value we should process
- * 
+ *
  * @return Zero when successful.
  */
 static int collectd_barometer_config (const char *key, const char *value)
@@ -1508,7 +1508,7 @@ static int collectd_barometer_config (const char *key, const char *value)
     {
         config_temp_offset = atof(value);
     }
-    else 
+    else
     {
         return -1;
     }
@@ -1517,11 +1517,11 @@ static int collectd_barometer_config (const char *key, const char *value)
 }
 
 
-/** 
+/**
  * Shutdown callback.
- * 
+ *
  * Close I2C and delete all the buffers.
- * 
+ *
  * @return Zero when successful (at the moment the only possible outcome)
  */
 static int collectd_barometer_shutdown(void)
@@ -1547,9 +1547,9 @@ static int collectd_barometer_shutdown(void)
 }
 
 
-/** 
+/**
  * Plugin read callback for MPL115.
- * 
+ *
  *  Dispatching will create values:
  *  - <hostname>/barometer-mpl115/pressure-normalized
  *  - <hostname>/barometer-mpl115/pressure-absolute
@@ -1567,7 +1567,7 @@ static int MPL115_collectd_barometer_read (void)
 
     value_list_t vl = VALUE_LIST_INIT;
     value_t      values[1];
-    
+
     DEBUG("barometer: MPL115_collectd_barometer_read");
 
     if (!configured)
@@ -1580,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)
@@ -1629,9 +1628,9 @@ static int MPL115_collectd_barometer_read (void)
 }
 
 
-/** 
+/**
  * Plugin read callback for MPL3115.
- * 
+ *
  *  Dispatching will create values:
  *  - <hostname>/barometer-mpl3115/pressure-normalized
  *  - <hostname>/barometer-mpl3115/pressure-absolute
@@ -1642,21 +1641,21 @@ static int MPL115_collectd_barometer_read (void)
 static int MPL3115_collectd_barometer_read (void)
 {
     int result = 0;
-    
+
     double pressure        = 0.0;
     double temperature     = 0.0;
     double norm_pressure   = 0.0;
-    
+
     value_list_t vl = VALUE_LIST_INIT;
     value_t      values[1];
-    
+
     DEBUG("barometer: MPL3115_collectd_barometer_read");
-    
+
     if (!configured)
     {
         return -1;
     }
-    
+
     result = MPL3115_read(&pressure, &temperature);
     if(result)
         return result;
@@ -1692,9 +1691,9 @@ static int MPL3115_collectd_barometer_read (void)
 }
 
 
-/** 
+/**
  * Plugin read callback for BMP085.
- * 
+ *
  *  Dispatching will create values:
  *  - <hostname>/barometer-bmp085/pressure-normalized
  *  - <hostname>/barometer-bmp085/pressure-absolute
@@ -1705,21 +1704,21 @@ static int MPL3115_collectd_barometer_read (void)
 static int BMP085_collectd_barometer_read (void)
 {
     int result = 0;
-    
+
     double pressure        = 0.0;
     double temperature     = 0.0;
     double norm_pressure   = 0.0;
-    
+
     value_list_t vl = VALUE_LIST_INIT;
     value_t      values[1];
-    
+
     DEBUG("barometer: BMP085_collectd_barometer_read");
-    
+
     if (!configured)
     {
         return -1;
     }
-    
+
     result = BMP085_read(&pressure, &temperature);
     if(result)
         return result;
@@ -1755,12 +1754,12 @@ static int BMP085_collectd_barometer_read (void)
 }
 
 
-/** 
+/**
  * Initialization callback
- * 
+ *
  * Check config, initialize I2C bus access, conversion coefficients and averaging
  * ring buffers
- * 
+ *
  * @return Zero when successful.
  */
 static int collectd_barometer_init (void)
@@ -1802,7 +1801,7 @@ static int collectd_barometer_init (void)
     }
 
     /* detect sensor type - this will also set slave address */
-    sensor_type = Detect_sensor_type();
+    sensor_type = detect_sensor_type();
 
     /* init correct sensor type */
     switch(sensor_type)
@@ -1811,10 +1810,10 @@ static int collectd_barometer_init (void)
     case Sensor_MPL3115:
     {
         MPL3115_adjust_oversampling();
-        
+
         if(MPL3115_init_sensor())
             return -1;
-        
+
         plugin_register_read ("barometer", MPL3115_collectd_barometer_read);
     }
     break;
@@ -1827,16 +1826,16 @@ static int collectd_barometer_init (void)
             ERROR("barometer: collectd_barometer_init pressure averaging init failed");
             return -1;
         }
-        
+
         if (averaging_create (&temperature_averaging, config_oversample))
         {
             ERROR("barometer: collectd_barometer_init temperature averaging init failed");
             return -1;
         }
-        
+
         if (MPL115_read_coeffs() < 0)
             return -1;
-        
+
         plugin_register_read ("barometer", MPL115_collectd_barometer_read);
     }
     break;
@@ -1858,7 +1857,7 @@ static int collectd_barometer_init (void)
         ERROR("barometer: collectd_barometer_init - no supported sensor found");
         return -1;
     }
-        
+
 
     configured = 1;
     return 0;
@@ -1866,15 +1865,15 @@ static int collectd_barometer_init (void)
 
 /* ------------------------ plugin register / entry point ------------------------ */
 
-/** 
+/**
  * Plugin "entry" - register all callback.
- * 
+ *
  */
 void module_register (void)
 {
-    plugin_register_config ("barometer", 
-                            collectd_barometer_config, 
-                            config_keys, 
+    plugin_register_config ("barometer",
+                            collectd_barometer_config,
+                            config_keys,
                             config_keys_num);
     plugin_register_init ("barometer", collectd_barometer_init);
     plugin_register_shutdown ("barometer", collectd_barometer_shutdown);
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 06b4ace..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,10 +823,8 @@ 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++)
   {
-    xmlNode *node;
-
     node = zone_nodes->nodesetval->nodeTab[i];
     assert (node != NULL);
 
@@ -857,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)
@@ -889,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);
@@ -957,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
@@ -1012,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)
@@ -1029,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;
 
@@ -1443,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)
@@ -1473,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;
@@ -1535,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;
@@ -1615,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)
   {
@@ -1638,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))
   {
@@ -1646,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.");
@@ -1666,11 +1649,11 @@ static int bind_config_add_view (oconfig_item_t *ci) /* {{{ */
   if (tmp->name == NULL)
   {
     ERROR ("bind plugin: strdup failed.");
-    free (tmp);
+    sfree (views);
     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;
 
@@ -1695,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;
 
@@ -1709,6 +1690,7 @@ static int bind_config (oconfig_item_t *ci) /* {{{ */
         return (-1);
       }
 
+      sfree (url);
       url = strdup (child->values[0].value.string);
     } else if (strcasecmp ("OpCodes", child->key) == 0)
       bind_config_set_bool ("OpCodes", &global_opcodes, child);
index 419ca6e..cbfdd22 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * collectd - src/ceph.c
  * Copyright (C) 2011  New Dream Network
+ * Copyright (C) 2015  Florian octo Forster
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  *
  * Authors:
- *   Colin McCabe <cmccabe@alumni.cmu.edu>
- *   Dennis Zou <yunzou@cisco.com>
- *   Dan Ryder <daryder@cisco.com>
+ *   Colin McCabe <cmccabe at alumni.cmu.edu>
+ *   Dennis Zou <yunzou at cisco.com>
+ *   Dan Ryder <daryder at cisco.com>
+ *   Florian octo Forster <octo at collectd.org>
  **/
 
 #define _DEFAULT_SOURCE
 #define _BSD_SOURCE
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -94,7 +97,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 *******/
@@ -132,11 +135,10 @@ struct yajl_struct
 {
     node_handler_t handler;
     void * handler_arg;
-    struct {
-      char key[DATA_MAX_NAME_LEN];
-      int key_len;
-    } state[YAJL_MAX_DEPTH];
-    int depth;
+
+    char *key;
+    char *stack[YAJL_MAX_DEPTH];
+    size_t depth;
 };
 typedef struct yajl_struct yajl_struct;
 
@@ -255,68 +257,80 @@ static int ceph_cb_boolean(void *ctx, int bool_val)
     return CEPH_CB_CONTINUE;
 }
 
+#define BUFFER_ADD(dest, src) do { \
+    size_t dest_size = sizeof (dest); \
+    strncat ((dest), (src), dest_size - strlen (dest)); \
+    (dest)[dest_size - 1] = '\0'; \
+} while (0)
+
 static int
 ceph_cb_number(void *ctx, const char *number_val, yajl_len_t number_len)
 {
-    yajl_struct *yajl = (yajl_struct*)ctx;
+    yajl_struct *state = (yajl_struct*) ctx;
     char buffer[number_len+1];
-    int i, latency_type = 0, result;
-    char key[128];
+    char key[2 * DATA_MAX_NAME_LEN];
+    _Bool latency_type = 0;
+    int status;
 
+    key[0] = '\0';
     memcpy(buffer, number_val, number_len);
-    buffer[sizeof(buffer) - 1] = 0;
+    buffer[sizeof(buffer) - 1] = '\0';
+
+    for (size_t i = 0; i < state->depth; i++)
+    {
+        if (state->stack[i] == NULL)
+            continue;
+
+        if (strlen (key) != 0)
+            BUFFER_ADD (key, ".");
+        BUFFER_ADD (key, state->stack[i]);
+    }
 
-    ssnprintf(key, yajl->state[0].key_len, "%s", yajl->state[0].key);
-    for(i = 1; i < yajl->depth; i++)
+    /* Special case for latency metrics. */
+    if ((strcmp ("avgcount", state->key) == 0)
+        || (strcmp ("sum", state->key) == 0))
     {
-        if((i == yajl->depth-1) && ((strcmp(yajl->state[i].key,"avgcount") == 0)
-                || (strcmp(yajl->state[i].key,"sum") == 0)))
+        latency_type = 1;
+
+        /* Super-special case for filestore.journal_wr_bytes.avgcount: For
+         * some reason, Ceph schema encodes this as a count/sum pair while all
+         * other "Bytes" data (excluding used/capacity bytes for OSD space) uses
+         * a single "Derive" type. To spare further confusion, keep this KPI as
+         * the same type of other "Bytes". Instead of keeping an "average" or
+         * "rate", use the "sum" in the pair and assign that to the derive
+         * value. */
+        if (convert_special_metrics && (state->depth >= 2)
+            && (strcmp("filestore", state->stack[state->depth - 2]) == 0)
+            && (strcmp("journal_wr_bytes", state->stack[state->depth - 1]) == 0)
+            && (strcmp("avgcount", state->key) == 0))
         {
-            if(convert_special_metrics)
-            {
-                /**
-                 * Special case for filestore:JournalWrBytes. For some reason,
-                 * Ceph schema encodes this as a count/sum pair while all
-                 * other "Bytes" data (excluding used/capacity bytes for OSD
-                 * space) uses a single "Derive" type. To spare further
-                 * confusion, keep this KPI as the same type of other "Bytes".
-                 * Instead of keeping an "average" or "rate", use the "sum" in
-                 * the pair and assign that to the derive value.
-                 */
-                if((strcmp(yajl->state[i-1].key, "journal_wr_bytes") == 0) &&
-                        (strcmp(yajl->state[i-2].key,"filestore") == 0) &&
-                        (strcmp(yajl->state[i].key,"avgcount") == 0))
-                {
-                    DEBUG("ceph plugin: Skipping avgcount for filestore.JournalWrBytes");
-                    yajl->depth = (yajl->depth - 1);
-                    return CEPH_CB_CONTINUE;
-                }
-            }
-            //probably a avgcount/sum pair. if not - we'll try full key later
-            latency_type = 1;
-            break;
+            DEBUG("ceph plugin: Skipping avgcount for filestore.JournalWrBytes");
+            return CEPH_CB_CONTINUE;
         }
-        strncat(key, ".", 1);
-        strncat(key, yajl->state[i].key, yajl->state[i].key_len+1);
+    }
+    else /* not a latency type */
+    {
+        BUFFER_ADD (key, ".");
+        BUFFER_ADD (key, state->key);
     }
 
-    result = yajl->handler(yajl->handler_arg, buffer, key);
-
-    if((result == RETRY_AVGCOUNT) && latency_type)
+    status = state->handler(state->handler_arg, buffer, key);
+    if((status == RETRY_AVGCOUNT) && latency_type)
     {
-        strncat(key, ".", 1);
-        strncat(key, yajl->state[yajl->depth-1].key,
-                yajl->state[yajl->depth-1].key_len+1);
-        result = yajl->handler(yajl->handler_arg, buffer, key);
+        /* Add previously skipped part of the key, either "avgcount" or "sum",
+         * and try again. */
+        BUFFER_ADD (key, ".");
+        BUFFER_ADD (key, state->key);
+
+        status = state->handler(state->handler_arg, buffer, key);
     }
 
-    if(result == -ENOMEM)
+    if (status != 0)
     {
-        ERROR("ceph plugin: memory allocation failed");
+        ERROR("ceph plugin: JSON handler failed with status %d.", status);
         return CEPH_CB_ABORT;
     }
 
-    yajl->depth = (yajl->depth - 1);
     return CEPH_CB_CONTINUE;
 }
 
@@ -328,37 +342,52 @@ static int ceph_cb_string(void *ctx, const unsigned char *string_val,
 
 static int ceph_cb_start_map(void *ctx)
 {
+    yajl_struct *state = (yajl_struct*) ctx;
+
+    /* Push key to the stack */
+    if (state->depth == YAJL_MAX_DEPTH)
+        return CEPH_CB_ABORT;
+
+    state->stack[state->depth] = state->key;
+    state->depth++;
+    state->key = NULL;
+
     return CEPH_CB_CONTINUE;
 }
 
-static int
-ceph_cb_map_key(void *ctx, const unsigned char *key, yajl_len_t string_len)
+static int ceph_cb_end_map(void *ctx)
 {
-    yajl_struct *yajl = (yajl_struct*)ctx;
+    yajl_struct *state = (yajl_struct*) ctx;
 
-    if((yajl->depth+1)  >= YAJL_MAX_DEPTH)
-    {
-        ERROR("ceph plugin: depth exceeds max, aborting.");
+    /* Pop key from the stack */
+    if (state->depth == 0)
         return CEPH_CB_ABORT;
-    }
-
-    char buffer[string_len+1];
 
-    memcpy(buffer, key, string_len);
-    buffer[sizeof(buffer) - 1] = 0;
-
-    snprintf(yajl->state[yajl->depth].key, sizeof(buffer), "%s", buffer);
-    yajl->state[yajl->depth].key_len = sizeof(buffer);
-    yajl->depth = (yajl->depth + 1);
+    sfree (state->key);
+    state->depth--;
+    state->key = state->stack[state->depth];
+    state->stack[state->depth] = NULL;
 
     return CEPH_CB_CONTINUE;
 }
 
-static int ceph_cb_end_map(void *ctx)
+static int
+ceph_cb_map_key(void *ctx, const unsigned char *key, yajl_len_t string_len)
 {
-    yajl_struct *yajl = (yajl_struct*)ctx;
+    yajl_struct *state = (yajl_struct*) ctx;
+    size_t sz = ((size_t) string_len) + 1;
+
+    sfree (state->key);
+    state->key = malloc (sz);
+    if (state->key == NULL)
+    {
+        ERROR ("ceph plugin: malloc failed.");
+        return CEPH_CB_ABORT;
+    }
+
+    memmove (state->key, key, sz - 1);
+    state->key[sz - 1] = 0;
 
-    yajl->depth = (yajl->depth - 1);
     return CEPH_CB_CONTINUE;
 }
 
@@ -393,8 +422,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]);
     }
@@ -402,15 +430,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]);
     }
@@ -419,140 +447,139 @@ static void ceph_daemon_free(struct ceph_daemon *d)
     sfree(d);
 }
 
-/**
- * Compact ds name by removing special characters and trimming length to
- * DATA_MAX_NAME_LEN if necessary
- */
-static void compact_ds_name(char *source, char *dest)
+/* compact_ds_name removed the special characters ":", "_", "-" and "+" from the
+ * intput string. Characters following these special characters are capitalized.
+ * Trailing "+" and "-" characters are replaces with the strings "Plus" and
+ * "Minus". */
+static int compact_ds_name (char *buffer, size_t buffer_size, char const *src)
 {
-    int keys_num = 0, i;
-    char *save_ptr = NULL, *tmp_ptr = source;
-    char *keys[16];
-    char len_str[3];
-    char tmp[DATA_MAX_NAME_LEN];
-    size_t key_chars_remaining = (DATA_MAX_NAME_LEN-1);
-    int reserved = 0;
-    int offset = 0;
-    memset(tmp, 0, sizeof(tmp));
-    if(source == NULL || dest == NULL || source[0] == '\0' || dest[0] != '\0')
-    {
-        return;
-    }
-    size_t src_len = strlen(source);
-    snprintf(len_str, sizeof(len_str), "%zu", src_len);
-    unsigned char append_status = 0x0;
-    append_status |= (source[src_len - 1] == '-') ? 0x1 : 0x0;
-    append_status |= (source[src_len - 1] == '+') ? 0x2 : 0x0;
-    while ((keys[keys_num] = strtok_r(tmp_ptr, ":_-+", &save_ptr)) != NULL)
-    {
-        tmp_ptr = NULL;
-        /** capitalize 1st char **/
-        keys[keys_num][0] = toupper(keys[keys_num][0]);
-        keys_num++;
-        if(keys_num >= 16)
-        {
-            break;
-        }
-    }
-    /** concatenate each part of source string **/
-    for(i = 0; i < keys_num; i++)
+    char *src_copy;
+    size_t src_len;
+    char *ptr = buffer;
+    size_t ptr_size = buffer_size;
+    _Bool append_plus = 0;
+    _Bool append_minus = 0;
+
+    if ((buffer == NULL) || (buffer_size <= strlen ("Minus")) || (src == NULL))
+      return EINVAL;
+
+    src_copy = strdup (src);
+    src_len = strlen(src);
+
+    /* Remove trailing "+" and "-". */
+    if (src_copy[src_len - 1] == '+')
     {
-        strncat(tmp, keys[i], key_chars_remaining);
-        key_chars_remaining -= strlen(keys[i]);
+        append_plus = 1;
+        src_len--;
+        src_copy[src_len] = 0;
     }
-    tmp[DATA_MAX_NAME_LEN - 1] = '\0';
-    /** to coordinate limitation of length of type_instance
-     *  we will truncate ds_name
-     *  when the its length is more than
-     *  DATA_MAX_NAME_LEN
-     */
-    if(strlen(tmp) > DATA_MAX_NAME_LEN - 1)
+    else if (src_copy[src_len - 1] == '-')
     {
-        append_status |= 0x4;
-        /** we should reserve space for
-         * len_str
-         */
-        reserved += 2;
+        append_minus = 1;
+        src_len--;
+        src_copy[src_len] = 0;
     }
-    if(append_status & 0x1)
-    {
-        /** we should reserve space for
-         * "Minus"
-         */
-        reserved += 5;
-    }
-    if(append_status & 0x2)
+
+    /* Split at special chars, capitalize first character, append to buffer. */
+    char *dummy = src_copy;
+    char *token;
+    char *save_ptr = NULL;
+    while ((token = strtok_r (dummy, ":_-+", &save_ptr)) != NULL)
     {
-        /** we should reserve space for
-         * "Plus"
-         */
-        reserved += 4;
+        size_t len;
+
+        dummy = NULL;
+
+        token[0] = toupper ((int) token[0]);
+
+        assert (ptr_size > 1);
+
+        len = strlen (token);
+        if (len >= ptr_size)
+            len = ptr_size - 1;
+
+        assert (len > 0);
+        assert (len < ptr_size);
+
+        sstrncpy (ptr, token, len + 1);
+        ptr += len;
+        ptr_size -= len;
+
+        assert (*ptr == 0);
+        if (ptr_size <= 1)
+            break;
     }
-    snprintf(dest, DATA_MAX_NAME_LEN - reserved, "%s", tmp);
-    offset = strlen(dest);
-    switch (append_status)
+
+    /* Append "Plus" or "Minus" if "+" or "-" has been stripped above. */
+    if (append_plus || append_minus)
     {
-        case 0x1:
-            memcpy(dest + offset, "Minus", 5);
-            break;
-        case 0x2:
-            memcpy(dest + offset, "Plus", 5);
-            break;
-        case 0x4:
-            memcpy(dest + offset, len_str, 2);
-            break;
-        case 0x5:
-            memcpy(dest + offset, "Minus", 5);
-            memcpy(dest + offset + 5, len_str, 2);
-            break;
-        case 0x6:
-            memcpy(dest + offset, "Plus", 4);
-            memcpy(dest + offset + 4, len_str, 2);
-            break;
-        default:
-            break;
+        char const *append = "Plus";
+        if (append_minus)
+            append = "Minus";
+
+        size_t offset = buffer_size - (strlen (append) + 1);
+        if (offset > strlen (buffer))
+            offset = strlen (buffer);
+
+        sstrncpy (buffer + offset, append, buffer_size - offset);
     }
+
+    sfree (src_copy);
+    return 0;
+}
+
+static _Bool has_suffix (char const *str, char const *suffix)
+{
+    size_t str_len = strlen (str);
+    size_t suffix_len = strlen (suffix);
+    size_t offset;
+
+    if (suffix_len > str_len)
+        return 0;
+    offset = str_len - suffix_len;
+
+    if (strcmp (str + offset, suffix) == 0)
+        return 1;
+
+    return 0;
+}
+
+/* count_parts returns the number of elements a "foo.bar.baz" style key has. */
+static size_t count_parts (char const *key)
+{
+    size_t parts_num = 0;
+
+    for (const char *ptr = key; ptr != NULL; ptr = strchr (ptr + 1, '.'))
+        parts_num++;
+
+    return parts_num;
 }
 
 /**
  * Parse key to remove "type" if this is for schema and initiate compaction
  */
-static int parse_keys(const char *key_str, char *ds_name)
+static int parse_keys (char *buffer, size_t buffer_size, const char *key_str)
 {
-    char *ptr, *rptr;
-    size_t ds_name_len = 0;
-    /**
-     * allow up to 100 characters before compaction - compact_ds_name will not
-     * allow more than DATA_MAX_NAME_LEN chars
-     */
-    int max_str_len = 100;
-    char tmp_ds_name[max_str_len];
-    memset(tmp_ds_name, 0, sizeof(tmp_ds_name));
-    if(ds_name == NULL || key_str == NULL ||  key_str[0] == '\0' ||
-                                                            ds_name[0] != '\0')
-    {
-        return -1;
-    }
-    if((ptr = strchr(key_str, '.')) == NULL
-            || (rptr = strrchr(key_str, '.')) == NULL)
+    char tmp[2 * buffer_size];
+
+    if (buffer == NULL || buffer_size == 0 || key_str == NULL || strlen (key_str) == 0)
+        return EINVAL;
+
+    if ((count_parts (key_str) > 2) && has_suffix (key_str, ".type"))
     {
-        memcpy(tmp_ds_name, key_str, max_str_len - 1);
-        goto compact;
-    }
+        /* strip ".type" suffix iff the key has more than two parts. */
+        size_t sz = strlen (key_str) - strlen (".type") + 1;
 
-    ds_name_len = (rptr - ptr) > max_str_len ? max_str_len : (rptr - ptr);
-    if((ds_name_len == 0) || strncmp(rptr + 1, "type", 4))
-    { /** copy whole key **/
-        memcpy(tmp_ds_name, key_str, max_str_len - 1);
+        if (sz > sizeof (tmp))
+            sz = sizeof (tmp);
+        sstrncpy (tmp, key_str, sz);
     }
     else
-    {/** more than two keys **/
-        memcpy(tmp_ds_name, key_str, ((rptr - key_str) > (max_str_len - 1) ?
-                (max_str_len - 1) : (rptr - key_str)));
+    {
+        sstrncpy (tmp, key_str, sizeof (tmp));
     }
 
-    compact: compact_ds_name(tmp_ds_name, ds_name);
-    return 0;
+    return compact_ds_name (buffer, buffer_size, tmp);
 }
 
 /**
@@ -564,7 +591,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)
     {
@@ -594,7 +620,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;
@@ -604,7 +630,7 @@ static int ceph_daemon_add_ds_entry(struct ceph_daemon *d, const char *name,
             ((pc_type & PERFCOUNTER_LATENCY) ? DSET_LATENCY : DSET_BYTES);
     d->ds_types[d->ds_num] = type;
 
-    if(parse_keys(name, ds_name))
+    if (parse_keys(ds_name, sizeof (ds_name), name))
     {
         return 1;
     }
@@ -655,10 +681,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))
     {
@@ -673,7 +698,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;
 
@@ -718,7 +743,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;
@@ -730,9 +755,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)
@@ -816,7 +841,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;
@@ -844,7 +869,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;
@@ -869,8 +894,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)
         {
@@ -930,12 +954,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;
@@ -954,9 +977,8 @@ 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(key, ds_name))
+    if (parse_keys (ds_name, sizeof (ds_name), key))
     {
         return 1;
     }
@@ -1057,7 +1079,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)
     {
@@ -1067,12 +1089,11 @@ static int cconn_connect(struct cconn *io)
     fd = socket(PF_UNIX, SOCK_STREAM, 0);
     if(fd < 0)
     {
-        int err = -errno;
+        err = -errno;
         ERROR("ceph plugin: cconn_connect: socket(PF_UNIX, SOCK_STREAM, 0) "
             "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);
@@ -1082,6 +1103,7 @@ static int cconn_connect(struct cconn *io)
     {
         ERROR("ceph plugin: cconn_connect: connect(%d) failed: error %d",
             fd, err);
+        close(fd);
         return err;
     }
 
@@ -1091,6 +1113,7 @@ static int cconn_connect(struct cconn *io)
         err = -errno;
         ERROR("ceph plugin: cconn_connect: fcntl(%d, O_NONBLOCK) error %d",
             fd, err);
+        close(fd);
         return err;
     }
     io->asok = fd;
@@ -1430,7 +1453,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];
 
@@ -1438,7 +1461,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;
@@ -1457,7 +1480,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);
@@ -1495,7 +1518,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;
@@ -1514,7 +1537,7 @@ static int cconn_main_loop(uint32_t request_type)
             }
             else
             {
-                int ret = cconn_handle_event(io);
+                ret = cconn_handle_event(io);
                 if(ret)
                 {
                     WARNING("ceph plugin: cconn_handle_event(name=%s,"
@@ -1526,7 +1549,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);
     }
@@ -1559,8 +1582,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]);
     }
@@ -1578,3 +1600,4 @@ void module_register(void)
     plugin_register_read("ceph", ceph_read);
     plugin_register_shutdown("ceph", ceph_shutdown);
 }
+/* vim: set sw=4 sts=4 et : */
diff --git a/src/ceph_test.c b/src/ceph_test.c
new file mode 100644 (file)
index 0000000..91f084f
--- /dev/null
@@ -0,0 +1,189 @@
+/**
+ * collectd - src/ceph_test.c
+ * Copyright (C) 2015      Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "ceph.c" /* sic */
+#include "testing.h"
+
+struct case_s
+{
+  const char *key;
+  const char *value;
+};
+typedef struct case_s case_t;
+
+struct test_s
+{
+  case_t *cases;
+  size_t  cases_num;
+};
+typedef struct test_s test_t;
+
+static int test_handler(void *user, char const *val, char const *key)
+{
+  test_t *t = user;
+  size_t i;
+
+  char status[1024];
+  _Bool ok;
+
+  /* special case for latency metrics. */
+  if (strcmp ("filestore.example_latency", key) == 0)
+    return RETRY_AVGCOUNT;
+
+  snprintf (status, sizeof (status), "unexpected call: test_handler(\"%s\") = \"%s\"", key, val);
+  ok = 0;
+
+  for (i = 0; i < t->cases_num; i++)
+  {
+    if (strcmp (key, t->cases[i].key) != 0)
+      continue;
+
+    if (strcmp (val, t->cases[i].value) != 0)
+    {
+      snprintf (status, sizeof (status), "test_handler(\"%s\") = \"%s\", want \"%s\"", key, val, t->cases[i].value);
+      ok = 0;
+      break;
+    }
+
+    snprintf (status, sizeof (status), "test_handler(\"%s\") = \"%s\"", key, val);
+    ok = 1;
+    break;
+  }
+
+  OK1(ok, status);
+  return ok ? 0 : -1;
+}
+
+DEF_TEST(traverse_json)
+{
+  char const *json = "{\n"
+      "    \"WBThrottle\": {\n"
+      "        \"bytes_dirtied\": {\n"
+      "            \"type\": 2,\n"
+      "            \"description\": \"Dirty data\",\n"
+      "            \"nick\": \"\"\n"
+      "        },\n"
+      "        \"bytes_wb\": {\n"
+      "            \"type\": 2,\n"
+      "            \"description\": \"Written data\",\n"
+      "            \"nick\": \"\"\n"
+      "        },\n"
+      "        \"ios_dirtied\": {\n"
+      "            \"type\": 2,\n"
+      "            \"description\": \"Dirty operations\",\n"
+      "            \"nick\": \"\"\n"
+      "        },\n"
+      "        \"ios_wb\": {\n"
+      "            \"type\": 2,\n"
+      "            \"description\": \"Written operations\",\n"
+      "            \"nick\": \"\"\n"
+      "        },\n"
+      "        \"inodes_dirtied\": {\n"
+      "            \"type\": 2,\n"
+      "            \"description\": \"Entries waiting for write\",\n"
+      "            \"nick\": \"\"\n"
+      "        },\n"
+      "        \"inodes_wb\": {\n"
+      "            \"type\": 10,\n"
+      "            \"description\": \"Written entries\",\n"
+      "            \"nick\": \"\"\n"
+      "        }\n"
+      "    },\n"
+      "    \"filestore\": {\n"
+      "        \"journal_wr_bytes\": {\n"
+      "            \"avgcount\": 23,\n"
+      "            \"sum\": 3117\n"
+      "        },\n"
+      "        \"example_latency\": {\n"
+      "            \"avgcount\": 42,\n"
+      "            \"sum\": 4711\n"
+      "        }\n"
+      "    }\n"
+      "}\n";
+  case_t cases[] = {
+    {"WBThrottle.bytes_dirtied.type", "2"},
+    {"WBThrottle.bytes_wb.type", "2"},
+    {"WBThrottle.ios_dirtied.type", "2"},
+    {"WBThrottle.ios_wb.type", "2"},
+    {"WBThrottle.inodes_dirtied.type", "2"},
+    {"WBThrottle.inodes_wb.type", "10"},
+    {"filestore.journal_wr_bytes", "3117"},
+    {"filestore.example_latency.avgcount", "42"},
+    {"filestore.example_latency.sum", "4711"},
+  };
+  test_t t = {cases, STATIC_ARRAY_SIZE (cases)};
+
+  yajl_struct ctx = {test_handler, &t};
+
+  yajl_handle hndl;
+#if HAVE_YAJL_V2
+  hndl = yajl_alloc (&callbacks, NULL, &ctx);
+  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 ((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 {
+    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"},
+    {"foo:bar", "FooBar"},
+    {"foo:bar+", "FooBarPlus"},
+    {"foo:bar-", "FooBarMinus"},
+    {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+", "AaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaPlus"},
+    {"aa.bb.cc.dd.ee.ff", "Aa.bb.cc.dd.ee.ff"},
+    {"aa.bb.cc.dd.ee.ff.type", "Aa.bb.cc.dd.ee.ff"},
+    {"aa.type", "Aa.type"},
+    {"WBThrottle.bytes_dirtied.type", "WBThrottle.bytesDirtied"},
+  };
+  size_t i;
+
+  for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+  {
+    char got[64];
+
+    CHECK_ZERO (parse_keys (got, sizeof (got), cases[i].str));
+    EXPECT_EQ_STR (cases[i].want, got);
+  }
+
+  return 0;
+}
+
+int main (void)
+{
+  RUN_TEST(traverse_json);
+  RUN_TEST(parse_keys);
+
+  END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
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..0485036
--- /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 %lds. Errno = %d",
+          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 282098e..20375e2 100644 (file)
@@ -33,7 +33,7 @@ with the plugin:
 
 =over 4
 
-=item
+=item *
 
 E-Mail type (e.g. "ham", "spam", "virus", ...) and size (bytes):
 
@@ -41,13 +41,13 @@ E-Mail type (e.g. "ham", "spam", "virus", ...) and size (bytes):
 
 If C<size> is less than or equal to zero, C<size> is ignored.
 
-=item
+=item *
 
 Spam score:
 
   s:<value>
 
-=item
+=item *
 
 Successful spam checks (e.g. "BAYES_99", "SUBJECT_DRUG_GAP_C", ...):
 
index 0e4cd53..c65966b 100644 (file)
@@ -94,7 +94,7 @@ I<Valuelist> is a colon-separated list of the time and the values, each either
 an integer if the data-source is a counter, or a double if the data-source is
 of type "gauge". You can submit an undefined gauge-value by using B<U>. When
 submitting B<U> to a counter the behavior is undefined. The time is given as
-epoch (i.E<nbsp>e. standard UNIX time).
+epoch (i.E<nbsp>e. standard UNIX time) or B<N> to use the current time.
 
 You can mix options and values, but the order is important: Options only
 effect following values, so specifying an option as last field is allowed, but
@@ -281,12 +281,12 @@ to make use of collectd's more powerful interface.
 
 =over 4
 
-=item
+=item *
 
 The user, the binary is executed as, may not have root privileges, i.E<nbsp>e.
 must have an UID that is non-zero. This is for your own good.
 
-=item
+=item *
 
 Early versions of the plugin did not use a command but treated all lines as if
 they were arguments to the I<PUTVAL> command. When the I<PUTNOTIF> command was
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 b17e47e..12187f3 100644 (file)
@@ -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 < 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 7308648..0102e92 100644 (file)
@@ -705,7 +705,7 @@ types used by the read, write and match functions.
 
 =over 4
 
-=item
+=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,
@@ -721,7 +721,7 @@ L<http://collectd.org/dev-info.shtml>.
 
 =over 4
 
-=item
+=item *
 
 collectd is heavily multi-threaded. Each collectd thread accessing the perl
 plugin will be mapped to a Perl interpreter thread (see L<threads(3perl)>).
@@ -733,7 +733,7 @@ registered callback may be called more than once in parallel). Please note
 that no data is shared between threads by default. You have to use the
 B<threads::shared> module to do so.
 
-=item
+=item *
 
 Each function name registered with collectd has to be available before the
 first thread has been created (i.E<nbsp>e. basically at compile time). This
@@ -742,14 +742,14 @@ C<*foo = \&bar; plugin_register (TYPE_READ, "plugin", "foo");> most likely
 will not work. This is due to the fact that the symbol table is not shared
 across different threads.
 
-=item
+=item *
 
 Each plugin is usually only loaded once and kept in memory for performance
 reasons. Therefore, END blocks are only executed once when collectd shuts
 down. You should not rely on END blocks anyway - use B<shutdown functions>
 instead.
 
-=item
+=item *
 
 The perl plugin exports the internal API of collectd which is considered
 unstable and subject to change at any time. We try hard to not break backwards
@@ -763,7 +763,7 @@ dispatched by the perl plugin after upgrades.
 
 =over 4
 
-=item
+=item *
 
 Currently, it is not possible to flush a single Perl plugin only. You can
 either flush all Perl plugins or none at all and you have to use C<perl> as
index 0da891f..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
 
@@ -87,22 +87,23 @@ collectd script as well as from a normal Python interpreter:
 
 =over 4
 
-=item
+=item *
 
 B<1.> collectd will try to import the B<readline> module to give you a decent
 way of entering your commands. The daemonized collectd won't do that.
 
-=item
+=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).
 
-=item
+=item *
 
 B<3.> collectd handles I<SIGCHLD>. This means that Python won't be able to
 determine the return code of spawned processes with system(), popen() and
@@ -515,18 +516,18 @@ different events. With one exception all of them are called as shown above.
 
 =over 4
 
-=item
+=item *
 
 I<callback> is a callable object that will be called every time the event is
 triggered.
 
-=item
+=item *
 
 I<data> is an optional object that will be passed back to the callback function
 every time it is called. If you omit this parameter no object is passed back to
 your callback, not even None.
 
-=item
+=item *
 
 I<name> is an optional identifier for this callback. The default name is
 B<python>.I<module>. I<module> is taken from the B<__module__> attribute of
@@ -534,7 +535,7 @@ your callback function. Every callback needs a unique identifier, so if you
 want to register the same callback multiple times in the same module you need to
 specify a name here. Otherwise it's safe to ignore this parameter.
 
-=item
+=item *
 
 I<identifier> is the full identifier assigned to this callback.
 
@@ -637,7 +638,7 @@ A float or None, the maximum value.
 
 =back
 
-=item B<flush>(I<plugin>[, I<timeout>][, I<identifier>]) -> None
+=item B<flush>(I<plugin[, timeout][, identifier]) -> None
 
 Flush one or all plugins. I<timeout> and the specified I<identifiers> are
 passed on to the registered flush-callbacks. If omitted, the timeout defaults
@@ -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,33 +674,17 @@ 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
 
-=item
+=item *
 
 collectd is heavily multi-threaded. Each collectd thread accessing the Python
 plugin will be mapped to a Python interpreter thread. Any such thread will be
@@ -707,13 +694,13 @@ Hence, any plugin has to be thread-safe if it provides several entry points
 from collectd (i.E<nbsp>e. if it registers more than one callback or if a
 registered callback may be called more than once in parallel).
 
-=item
+=item *
 
 The Python thread module is initialized just before calling the init callbacks.
 This means you must not use Python's threading module prior to this point. This
 includes all config and possibly other callback as well.
 
-=item
+=item *
 
 The python plugin exports the internal API of collectd which is considered
 unstable and subject to change at any time. We try hard to not break backwards
@@ -727,7 +714,7 @@ dispatched by the python plugin after upgrades.
 
 =over 4
 
-=item
+=item *
 
 Not all aspects of the collectd API are accessible from Python. This includes
 but is not limited to filters and data sets.
index 9bd65bc..7db9fe7 100644 (file)
@@ -46,7 +46,6 @@
 
 #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
@@ -156,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)
@@ -201,6 +199,7 @@ static lcc_value_list_t *create_value_list (void) /* {{{ */
   strncpy (vl->identifier.type,
       (vl->values_types[0] == LCC_TYPE_GAUGE) ? "gauge" : "derive",
       sizeof (vl->identifier.type));
+  vl->identifier.type[sizeof (vl->identifier.type) - 1] = 0;
   snprintf (vl->identifier.type_instance, sizeof (vl->identifier.type_instance),
       "ti%li", random ());
 
@@ -338,7 +337,6 @@ static int read_options (int argc, char **argv) /* {{{ */
 
 int main (int argc, char **argv) /* {{{ */
 {
-  int i;
   double last_time;
   int values_sent = 0;
 
@@ -367,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)
     {
@@ -384,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;
 
@@ -451,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 21cb111..e3f2aa3 100644 (file)
@@ -84,7 +84,7 @@
 # Lines beginning with a single `#' belong to plugins which have been built  #
 # but are disabled by default.                                               #
 #                                                                            #
-# Lines begnning with `##' belong to plugins which have not been built due   #
+# Lines beginning with `##' belong to plugins which have not been built due  #
 # to missing dependencies or because they have been deactivated explicitly.  #
 ##############################################################################
 
 #@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_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@@BUILD_PLUGIN_IPC_TRUE@LoadPlugin ipc
+#@BUILD_PLUGIN_IPC_TRUE@LoadPlugin ipc
 #@BUILD_PLUGIN_IPMI_TRUE@LoadPlugin ipmi
 #@BUILD_PLUGIN_IPTABLES_TRUE@LoadPlugin iptables
 #@BUILD_PLUGIN_IPVS_TRUE@LoadPlugin ipvs
 #@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
 #  </Daemon>
 #</Plugin>
 
+#<Plugin chrony>
+#      Host    "localhost"
+#      Port    "323"
+#      Timeout "2"
+#</Plugin>
+
 #<Plugin cgroups>
 #  CGroup "libvirt"
 #  IgnoreSelected false
 #      FSType "ext3"
 #      IgnoreSelected false
 #      ReportByDevice false
-#      ReportReserved false
 #      ReportInodes false
 #      ValuesAbsolute true
 #      ValuesPercentage false
 #  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>
 
 #<Plugin iptables>
 #      Chain table chain
+#      Chain6 table chain
 #</Plugin>
 
 #<Plugin irq>
 #              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"
 #              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
index bbee6b1..6ada5f1 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,13 +127,13 @@ 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 the interval, in seconds, to call the flush callback if it's
-defined in this plugin. By default, this is disabled
+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>
 
@@ -159,12 +159,27 @@ plugins that don't provide any configuration, e.g. the I<Load plugin>.
 When set to B<true>, various statistics about the I<collectd> daemon will be
 collected, with "collectd" as the I<plugin name>. Defaults to B<false>.
 
-The "write_queue" I<plugin instance> reports the number of elements currently
-queued and the number of elements dropped off the queue by the
-B<WriteQueueLimitLow>/B<WriteQueueLimitHigh> mechanism.
+The following metrics are reported:
 
-The "cache" I<plugin instance> reports the number of elements in the value list
-cache (the cache you can interact with using L<collectd-unixsock(5)>).
+=over 4
+
+=item C<collectd-write_queue/queue_length>
+
+The number of metrics currently in the write queue. You can limit the queue
+length with the B<WriteQueueLimitLow> and B<WriteQueueLimitHigh> options.
+
+=item C<collectd-write_queue/derive-dropped>
+
+The number of metrics dropped due to a queue length limitation.
+If this value is non-zero, your system can't handle all incoming metrics and
+protects itself against overload by dropping metrics.
+
+=item C<collectd-cache/cache_size>
+
+The number of elements in the metric cache (the cache you can interact with
+using L<collectd-unixsock(5)>).
+
+=back
 
 =item B<Include> I<Path> [I<pattern>]
 
@@ -193,13 +208,11 @@ I<pattern> may be specified to filter which files to include. This may be used
 in combination with recursively including a directory to easily be able to
 arbitrarily mix configuration files and other documents (e.g. README files).
 The given example is similar to the first example above but includes all files
-matching C<*.conf> in any subdirectory of C</etc/collectd.d>:
-
-  Include "/etc/collectd.d" "*.conf"
+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.
@@ -240,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
@@ -391,13 +404,13 @@ There are a couple of limitations you should be aware of:
 
 =over 4
 
-=item
+=item *
 
 The I<Type> cannot be left unspecified, because it is not reasonable to add
 apples to oranges. Also, the internal lookup structure won't work if you try
 to group by type.
 
-=item
+=item *
 
 There must be at least one unspecified, ungrouped field. Otherwise nothing
 will be aggregated.
@@ -472,19 +485,19 @@ This will create the files:
 
 =over 4
 
-=item
+=item *
 
 foo.example.com/cpu-even-average/cpu-idle
 
-=item
+=item *
 
 foo.example.com/cpu-even-average/cpu-system
 
-=item
+=item *
 
 foo.example.com/cpu-even-average/cpu-user
 
-=item
+=item *
 
 ...
 
@@ -821,13 +834,15 @@ default for backwards compatibility, the time will be reported in minutes.
 
 =item B<PersistentConnection> B<true>|B<false>
 
-By default, the plugin will try to keep the connection to UPS open between
-reads. Since this appears to be somewhat brittle (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 in such cases.
+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>.
+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
 
@@ -1346,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.
@@ -1366,11 +1407,11 @@ as Jiffies, using the C<cpu> type. Two aggregations are available:
 
 =over 4
 
-=item
+=item *
 
 Sum, per-state, over all CPUs installed in the system; and
 
-=item
+=item *
 
 Sum, per-CPU, over all non-idle states of a CPU, creating an "active" state.
 
@@ -1416,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
@@ -1436,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
@@ -1536,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
@@ -1653,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:
@@ -1755,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
@@ -2252,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
@@ -2539,11 +2698,11 @@ Port to connect to gpsd on the host machine. Defaults to B<2947>.
 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 
+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 
+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 
+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.
@@ -2554,6 +2713,51 @@ 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),
@@ -2588,7 +2792,7 @@ a more detailed description see B<IgnoreSelected> below.
 
 =item B<IgnoreSelected> I<true>|I<false>
 
-If no configuration if given, the B<traffic>-plugin will collect data from
+If no configuration if given, the B<interface>-plugin will collect data from
 all interfaces. This may not be practical, especially for loopback- and
 similar interfaces. Thus, you can use the B<Interface>-option to pick the
 interfaces you're interested in. Sometimes, however, it's easier/preferred
@@ -2597,6 +2801,46 @@ do that: By setting B<IgnoreSelected> to I<true> the effect of
 B<Interface> is inverted: All selected interfaces are ignored and all
 other interfaces are collected.
 
+It is possible to use regular expressions to match interface names, if the
+name is surrounded by I</.../> and collectd was compiled with support for
+regexps. This is useful if there's a need to collect (or ignore) data
+for a group of interfaces that are similarly named, without the need to
+explicitly list all of them (especially useful if the list is dynamic).
+Example:
+
+ Interface "lo"
+ Interface "/^veth/"
+ Interface "/^tun[0-9]+/"
+ IgnoreSelected "true"
+
+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
 
 =head2 Plugin C<ipmi>
@@ -2637,9 +2881,13 @@ a notification is sent.
 
 =item B<Chain> I<Table> I<Chain> [I<Comment|Number> [I<Name>]]
 
-Select the rules to count. If only I<Table> and I<Chain> are given, this plugin
-will collect the counters of all rules which have a comment-match. The comment
-is then used as type-instance.
+=item B<Chain6> I<Table> I<Chain> [I<Comment|Number> [I<Name>]]
+
+Select the iptables/ip6tables filter rules to count packets and bytes from.
+
+If only I<Table> and I<Chain> are given, this plugin will collect the counters
+of all rules which have a comment-match. The comment is then used as
+type-instance.
 
 If I<Comment> or I<Number> is given, only the rule with the matching comment or
 the I<n>th rule will be collected. Again, the comment (or the number) will be
@@ -3419,6 +3667,38 @@ 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>
@@ -3463,6 +3743,13 @@ 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
@@ -3533,6 +3820,12 @@ 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.
@@ -4476,8 +4769,35 @@ 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
+dispersion.
+
+For talking to B<ntpd>, it mimics what the B<ntpdc> control program does on
+the wire - using B<mode 7> specific requests. This mode is deprecated with
+newer B<ntpd> releases (4.2.7p230 and later). For the C<ntpd> plugin to work
+correctly with them, the ntp daemon must be explicitly configured to
+enable B<mode 7> (which is disabled by default). Refer to the I<ntp.conf(5)>
+manual page for details.
+
+Available configuration options for the C<ntpd> plugin:
+
 =over 4
 
 =item B<Host> I<Hostname>
@@ -4703,12 +5023,12 @@ I<mandatory>.
 
 =item B<BindDN> I<BindDN>
 
-Name in the form of an LDAP distinguished name intended to be used for 
+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, 
+Password for simple bind authentication. If this option is not set,
 unauthenticated bind operation is used.
 
 =item B<StartTLS> B<true|false>
@@ -4732,8 +5052,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>
 
@@ -4982,6 +5303,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
@@ -5089,13 +5417,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
 
@@ -5113,7 +5440,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
@@ -5150,6 +5477,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
@@ -5157,7 +5512,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>
 
@@ -5193,20 +5548,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
@@ -5376,6 +5717,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>
 
@@ -5630,6 +5973,9 @@ collected for these selected processes are size of the resident segment size
 (RSS), user- and system-time used, number of processes and number of threads,
 io data (where available) and minor and major pagefaults.
 
+Some platforms have a limit on the length of process names. I<Name> must stay
+below this limit.
+
 =item B<ProcessMatch> I<name> I<regex>
 
 Similar to the B<Process> option this allows to select more detailed
@@ -6109,6 +6455,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>
@@ -6211,6 +6563,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>
@@ -6257,6 +6625,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
@@ -6770,7 +7144,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
 
@@ -6865,13 +7239,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>
@@ -6942,20 +7316,20 @@ The following methods are used to find the machine's UUID, in order:
 
 =over 4
 
-=item
+=item *
 
 Check I</etc/uuid> (or I<UUIDFile>).
 
-=item
+=item *
 
 Check for UUID from HAL (L<http://www.freedesktop.org/wiki/Software/hal>) if
 present.
 
-=item
+=item *
 
 Check for UUID from C<dmidecode> / SMBIOS.
 
-=item
+=item *
 
 Check for UUID from Xen hypervisor.
 
@@ -7296,6 +7670,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>.
@@ -7522,20 +7904,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
@@ -7808,11 +8205,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>,
@@ -7832,6 +8244,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
@@ -7998,6 +8415,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
@@ -8895,6 +9320,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 fb0403b..8e68fc0 100644 (file)
@@ -72,7 +72,7 @@ There are two big groups of plugins, B<input> and B<output> plugins:
 
 =over 4
 
-=item
+=item *
 
 Input plugins are queried periodically. They somehow acquire the current value
 of whatever they where designed to work with and submit these values back to
@@ -80,7 +80,7 @@ the daemon, i. e. they "dispatch" the values. As an example, the C<cpu plugin>
 reads the current cpu-counters of time spent in the various modes (user,
 system, nice, ...) and dispatches these counters to the daemon.
 
-=item
+=item *
 
 Output plugins get the dispatched values from the daemon and does something
 with them. Common applications are writing to RRD-files, CSV-files or sending
index febc998..e60781a 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"
@@ -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
@@ -235,7 +234,6 @@ static int flush (lcc_connection_t *c, int argc, char **argv)
   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 (int 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 (int 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)':');
@@ -565,7 +559,6 @@ int main (int argc, char **argv) {
         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 bcaea38..8002966 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -28,6 +28,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -221,15 +222,25 @@ static int init (void)
 
        port_host = mach_host_self ();
 
-       /* FIXME: Free `cpu_list' if it's not NULL */
-       if ((status = host_processors (port_host, &cpu_list, &cpu_list_len)) != KERN_SUCCESS)
+       status = host_processors (port_host, &cpu_list, &cpu_list_len);
+       if (status == KERN_INVALID_ARGUMENT)
+       {
+               ERROR ("cpu plugin: Don't have a privileged host control port. "
+                               "The most common cause for this problem is "
+                               "that collectd is running without root "
+                               "privileges, which are required to read CPU "
+                               "load information. "
+                               "<https://collectd.org/bugs/22>");
+               cpu_list_len = 0;
+               return (-1);
+       }
+       if (status != KERN_SUCCESS)
        {
-               ERROR ("cpu plugin: host_processors returned %i", (int) status);
+               ERROR ("cpu plugin: host_processors() failed with status %d.", (int) status);
                cpu_list_len = 0;
                return (-1);
        }
 
-       DEBUG ("host_processors returned %i %s", (int) cpu_list_len, cpu_list_len == 1 ? "processor" : "processors");
        INFO ("cpu plugin: Found %i processor%s.", (int) cpu_list_len, cpu_list_len == 1 ? "" : "s");
 /* #endif PROCESSOR_CPU_LOAD_INFO */
 
@@ -395,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;
@@ -432,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];
@@ -445,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);
@@ -456,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;
@@ -467,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);
 
@@ -491,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)
        {
@@ -507,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;
 
@@ -559,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;
@@ -568,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;
@@ -643,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? */
@@ -665,7 +661,6 @@ static int cpu_read (void)
        uint64_t cpuinfo[numcpu][CPUSTATES];
        size_t cpuinfo_size;
        int status;
-       int i;
 
        if (numcpu < 1)
        {
@@ -678,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]);
@@ -711,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);
@@ -728,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));
 
@@ -741,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);
@@ -791,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)
@@ -804,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;
@@ -819,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 15494f4..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;
-       size_t i;
        gauge_t *rates = NULL;
 
        assert (0 == strcmp (ds->type, vl->type));
@@ -58,19 +58,22 @@ 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)
                                && (ds->ds[i].type != DS_TYPE_DERIVE)
                                && (ds->ds[i].type != DS_TYPE_ABSOLUTE))
+               {
+                       sfree (rates);
                        return (-1);
+               }
 
-               if (ds->ds[i].type == DS_TYPE_GAUGE) 
+               if (ds->ds[i].type == DS_TYPE_GAUGE)
                {
                        status = ssnprintf (buffer + offset, buffer_len - offset,
                                        ",%lf", vl->values[i].gauge);
-               } 
+               }
                else if (store_rates != 0)
                {
                        if (rates == NULL)
@@ -184,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;
-       size_t i;
 
        if (check_create_dir (filename))
                return (-1);
@@ -200,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");
@@ -266,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)) {
@@ -285,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;
@@ -339,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 16ae3ab..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);
 
@@ -167,16 +171,19 @@ static void cc_web_page_free (web_page_t *wp) /* {{{ */
 static int cc_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 ("curl plugin: `%s' needs exactly one string argument.", name);
     return (-1);
   }
 
-  *dest = curl_slist_append(*dest, ci->values[0].value.string);
-  if (*dest == NULL)
+  temp = curl_slist_append(*dest, ci->values[0].value.string);
+  if (temp == NULL)
     return (-1);
 
+  *dest = temp;
+
   return (0);
 } /* }}} int cc_config_append_string */
 
@@ -263,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;
 
@@ -336,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);
   }
@@ -388,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.");
@@ -428,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))
   {
@@ -436,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;
@@ -452,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)
@@ -463,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;
 
@@ -494,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);
@@ -513,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;
     }
 
@@ -542,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;
   }
@@ -555,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;
 
@@ -656,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;
 
@@ -674,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)
   {
@@ -687,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;
 
@@ -714,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 510d9b6..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/types.h>
 #include <sys/un.h>
@@ -78,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];
@@ -116,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;
@@ -131,17 +134,11 @@ static size_t cj_curl_callback (void *buf, /* {{{ */
     return (len);
 #endif
 
-  if (status != yajl_status_ok)
-  {
-    unsigned char *msg =
-      yajl_get_error(db->yajl, /* verbose = */ 1,
-          /* jsonText = */ (unsigned char *) buf, (unsigned int) len);
-    ERROR ("curl_json plugin: yajl_parse failed: %s", msg);
-    yajl_free_error(db->yajl, msg);
-    return (0); /* abort write callback */
-  }
-
-  return (len);
+  unsigned char *msg = yajl_get_error(db->yajl, /* verbose = */ 1,
+        /* jsonText = */ (unsigned char *) buf, (unsigned int) len);
+  ERROR ("curl_json plugin: yajl_parse failed: %s", msg);
+  yajl_free_error(db->yajl, msg);
+  return (0); /* abort write callback */
 } /* }}} size_t cj_curl_callback */
 
 static int cj_get_type (cj_key_t *key)
@@ -438,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 */
@@ -452,16 +450,19 @@ static c_avl_tree_t *cj_avl_create(void)
 static int cj_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 ("curl_json plugin: `%s' needs exactly one string argument.", name);
     return (-1);
   }
 
-  *dest = curl_slist_append(*dest, ci->values[0].value.string);
-  if (*dest == NULL)
+  temp = curl_slist_append(*dest, ci->values[0].value.string);
+  if (temp == NULL)
     return (-1);
 
+  *dest = temp;
+
   return (0);
 } /* }}} int cj_config_append_string */
 
@@ -470,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))
@@ -480,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)
@@ -507,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;
 
@@ -525,71 +524,68 @@ static int cj_config_add_key (cj_t *db, /* {{{ */
       break;
   } /* for (i = 0; i < ci->children_num; i++) */
 
-  while (status == 0)
+  if (status != 0)
   {
-    if (key->type == NULL)
-    {
-      WARNING ("curl_json plugin: `Type' missing in `Key' block.");
-      status = -1;
-    }
+    cj_key_free (key);
+    return (-1);
+  }
 
-    break;
-  } /* while (status == 0) */
+  if (key->type == NULL)
+  {
+    WARNING ("curl_json plugin: `Type' missing in `Key' block.");
+    cj_key_free (key);
+    return (-1);
+  }
 
   /* store path in a tree that will match the json map structure, example:
    * "httpd/requests/count",
    * "httpd/requests/current" ->
    * { "httpd": { "requests": { "count": $key, "current": $key } } }
    */
-  if (status == 0)
+  char *ptr;
+  char *name;
+  c_avl_tree_t *tree;
+
+  if (db->tree == NULL)
+    db->tree = cj_avl_create();
+
+  tree = db->tree;
+  ptr = key->path;
+  if (*ptr == '/')
+    ++ptr;
+
+  name = ptr;
+  while ((ptr = strchr (name, '/')) != NULL)
   {
-    char *ptr;
-    char *name;
     char ent[PATH_MAX];
-    c_avl_tree_t *tree;
+    c_avl_tree_t *value;
+    size_t len;
 
-    if (db->tree == NULL)
-      db->tree = cj_avl_create();
+    len = ptr - name;
+    if (len == 0)
+      break;
 
-    tree = db->tree;
-    ptr = key->path;
-    if (*ptr == '/')
-      ++ptr;
+    len = COUCH_MIN(len, sizeof (ent)-1);
+    sstrncpy (ent, name, len+1);
 
-    name = ptr;
-    while (*ptr)
+    if (c_avl_get (tree, ent, (void *) &value) != 0)
     {
-      if (*ptr == '/')
-      {
-        c_avl_tree_t *value;
-        size_t len;
-
-        len = ptr-name;
-        if (len == 0)
-          break;
-        len = COUCH_MIN(len, sizeof (ent)-1);
-        sstrncpy (ent, name, len+1);
-
-        if (c_avl_get (tree, ent, (void *) &value) != 0)
-        {
-          value = cj_avl_create ();
-          c_avl_insert (tree, strdup (ent), value);
-        }
-
-        tree = value;
-        name = ptr+1;
-      }
-      ++ptr;
-    }
-    if (*name)
-      c_avl_insert (tree, strdup(name), key);
-    else
-    {
-      ERROR ("curl_json plugin: invalid key: %s", key->path);
-      status = -1;
+      value = cj_avl_create ();
+      c_avl_insert (tree, strdup (ent), value);
     }
+
+    tree = value;
+    name = ptr + 1;
   }
 
+  if (strlen (name) == 0)
+  {
+    ERROR ("curl_json plugin: invalid key: %s", key->path);
+    cj_key_free (key);
+    return (-1);
+  }
+
+  c_avl_insert (tree, strdup (name), key);
   return (status);
 } /* }}} int cj_config_add_key */
 
@@ -624,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.");
@@ -666,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))
@@ -676,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;
 
@@ -704,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;
 
@@ -734,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);
@@ -759,7 +759,7 @@ 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;
 
     if (db->instance == NULL)
@@ -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;
 
@@ -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 5a1f2ba..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>
@@ -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,19 +216,29 @@ 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)
 {
+  struct curl_slist *temp = NULL;
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
   {
     WARNING ("curl_xml plugin: `%s' needs exactly one string argument.", name);
     return (-1);
   }
 
-  *dest = curl_slist_append(*dest, ci->values[0].value.string);
-  if (*dest == NULL)
+  temp = curl_slist_append(*dest, ci->values[0].value.string);
+  if (temp == NULL)
     return (-1);
 
+  *dest = temp;
+
   return (0);
 } /* }}} int cx_config_append_string */
 
@@ -248,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;
@@ -315,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);
@@ -336,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);
   }
@@ -356,14 +368,13 @@ static int cx_handle_all_value_xpaths (xmlXPathContextPtr xpath_ctx, /* {{{ */
 {
   value_t values[xpath->values_len];
   int status;
-  size_t 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)
@@ -472,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 */
 
@@ -500,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: "
@@ -513,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;
 
@@ -534,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)
@@ -556,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 */
 
@@ -571,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);
@@ -589,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,
@@ -620,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)
   {
@@ -628,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);
@@ -668,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.");
@@ -686,53 +695,53 @@ 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 = (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));
   }
 
-  return (0); 
+  return (0);
 } /* }}} cx_config_add_values */
 
-static int cx_config_add_xpath (cx_t *db, /* {{{ */
-                                   oconfig_item_t *ci)
+static int cx_config_add_xpath (cx_t *db, oconfig_item_t *ci) /* {{{ */
 {
   cx_xpath_t *xpath;
+  char *name;
+  llentry_t *le;
   int status;
-  int i;
 
-  xpath = (cx_xpath_t *) 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)
   {
-    sfree (xpath);
+    cx_xpath_free (xpath);
     return (status);
   }
 
   /* error out if xpath->path is an empty string */
-  if (*xpath->path == 0)
+  if (strlen (xpath->path) == 0)
   {
     ERROR ("curl_xml plugin: invalid xpath. "
            "xpath value can't be an empty string");
+    cx_xpath_free (xpath);
     return (-1);
   }
 
   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;
 
@@ -754,45 +763,49 @@ static int cx_config_add_xpath (cx_t *db, /* {{{ */
       break;
   } /* for (i = 0; i < ci->children_num; i++) */
 
-  if (status == 0 && xpath->type == NULL)
+  if (status != 0)
   {
-    WARNING ("curl_xml plugin: `Type' missing in `xpath' block.");
-    status = -1;
+    cx_xpath_free (xpath);
+    return status;
   }
 
-  if (status == 0)
+  if (xpath->type == NULL)
   {
-    char *name;
-    llentry_t *le;
+    WARNING ("curl_xml plugin: `Type' missing in `xpath' block.");
+    cx_xpath_free (xpath);
+    return -1;
+  }
 
+  if (db->list == NULL)
+  {
+    db->list = llist_create();
     if (db->list == NULL)
     {
-      db->list = llist_create();
-      if (db->list == NULL)
-      {
-        ERROR ("curl_xml plugin: list creation failed.");
-        return (-1);
-      }
-    }
-
-    name = strdup(xpath->path);
-    if (name == NULL)
-    {
-        ERROR ("curl_xml plugin: strdup failed.");
-        return (-1);
-    }
-
-    le = llentry_create (name, xpath);
-    if (le == NULL)
-    {
-      ERROR ("curl_xml plugin: llentry_create failed.");
+      ERROR ("curl_xml plugin: list creation failed.");
+      cx_xpath_free (xpath);
       return (-1);
     }
+  }
 
-    llist_append (db->list, le);
+  name = strdup (xpath->path);
+  if (name == NULL)
+  {
+    ERROR ("curl_xml plugin: strdup failed.");
+    cx_xpath_free (xpath);
+    return (-1);
+  }
+
+  le = llentry_create (name, xpath);
+  if (le == NULL)
+  {
+    ERROR ("curl_xml plugin: llentry_create failed.");
+    cx_xpath_free (xpath);
+    sfree (name);
+    return (-1);
   }
 
-  return (status);
+  llist_append (db->list, le);
+  return (0);
 } /* }}} int cx_config_add_xpath */
 
 static int cx_config_add_namespace (cx_t *db, /* {{{ */
@@ -867,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.");
@@ -907,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))
@@ -917,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;
 
@@ -945,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;
 
@@ -975,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);
@@ -1000,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)
@@ -1009,7 +1026,6 @@ 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;
 
@@ -1034,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 3d50029..632872a 100644 (file)
@@ -10,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
@@ -23,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
@@ -33,8 +30,6 @@ if BUILD_WITH_LIBDEVINFO
 COMMON_LIBS += -ldevinfo
 endif
 
-AUTOMAKE_OPTIONS = subdir-objects
-
 sbin_PROGRAMS = collectd
 
 noinst_LTLIBRARIES = libavltree.la libcommon.la libheap.la libmetadata.la libplugin_mock.la
@@ -48,8 +43,10 @@ libheap_la_SOURCES = utils_heap.c utils_heap.h
 
 libmetadata_la_SOURCES = meta_data.c meta_data.h
 
-libplugin_mock_la_SOURCES = plugin_mock.c utils_cache_mock.c utils_time_mock.c
-libplugin_mock_la_LIBADD = $(COMMON_LIBS)
+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 \
@@ -90,11 +87,13 @@ else
 collectd_LDADD += -loconfig
 endif
 
+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
+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
@@ -109,4 +108,4 @@ 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 = libcommon.la libplugin_mock.la
+test_utils_subst_LDADD = libplugin_mock.la
index fc52933..8573579 100644 (file)
@@ -26,8 +26,8 @@
  **/
 
 #include "collectd.h"
-#include "common.h"
 
+#include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
@@ -35,8 +35,6 @@
 #include <sys/un.h>
 #include <netdb.h>
 
-#include <pthread.h>
-
 #if HAVE_LOCALE_H
 # include <locale.h>
 #endif
@@ -54,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;
@@ -100,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");
@@ -123,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)
@@ -137,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;
@@ -196,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);
        }
@@ -269,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"
@@ -301,6 +298,11 @@ static int do_init (void)
 #if HAVE_SETLOCALE
        if (setlocale (LC_NUMERIC, COLLECTD_LOCALE) == NULL)
                WARNING ("setlocale (\"%s\") failed.", COLLECTD_LOCALE);
+
+       /* Update the environment, so that libraries that are calling
+        * setlocale(LC_NUMERIC, "") don't accidentally revert these changes. */
+       unsetenv ("LC_ALL");
+       setenv ("LC_NUMERIC", COLLECTD_LOCALE, /* overwrite = */ 1);
 #endif
 
 #if HAVE_LIBKSTAT
@@ -326,9 +328,7 @@ static int do_init (void)
        }
 #endif
 
-       plugin_init_all ();
-
-       return (0);
+       return plugin_init_all ();
 } /* int do_init () */
 
 
@@ -382,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
@@ -417,7 +416,7 @@ static int pidfile_remove (void)
 #endif /* COLLECT_DAEMON */
 
 #ifdef KERNEL_LINUX
-int notify_upstart (void)
+static int notify_upstart (void)
 {
     char const *upstart_job = getenv("UPSTART_JOB");
 
@@ -437,11 +436,11 @@ int notify_upstart (void)
     return 1;
 }
 
-int notify_systemd (void)
+static int notify_systemd (void)
 {
     int                  fd;
     const char          *notifysocket;
-    struct sockaddr_un   su;
+    struct sockaddr_un   su = { 0 };
     size_t               su_size;
     char                 buffer[] = "READY=1\n";
 
@@ -471,7 +470,6 @@ int notify_systemd (void)
         return 0;
     }
 
-    memset (&su, 0, sizeof (su));
     su.sun_family = AF_UNIX;
     if (notifysocket[0] != '@')
     {
@@ -509,16 +507,11 @@ 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
@@ -548,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;
@@ -619,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);
 
     /*
@@ -633,6 +627,8 @@ int main (int argc, char **argv)
 #endif
        )
        {
+               int status;
+
                if ((pid = fork ()) == -1)
                {
                        /* error */
@@ -661,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",
@@ -695,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",
@@ -704,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",
@@ -716,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
        {
@@ -732,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 66b4856..3cb0c1b 100644 (file)
@@ -227,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
@@ -270,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__
@@ -294,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
@@ -316,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 8f22011..b60530a 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
@@ -48,6 +45,8 @@
 #include <sys/types.h>
 #include <netdb.h>
 
+#include <poll.h>
+
 #if HAVE_NETINET_IN_H
 # include <netinet/in.h>
 #endif
@@ -113,10 +112,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);
@@ -142,7 +140,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.");
@@ -269,9 +267,26 @@ ssize_t swrite (int fd, const void *buf, size_t count)
        const char *ptr;
        size_t      nleft;
        ssize_t     status;
+       struct      pollfd pfd;
 
        ptr   = (const char *) buf;
        nleft = count;
+       
+       if (fd < 0)
+               return (-1);
+
+       /* checking for closed peer connection */
+       pfd.fd = fd;
+       pfd.events = POLLIN | POLLHUP;
+       pfd.revents = 0;
+       if (poll(&pfd, 1, 0) > 0) {
+               char buffer[32];
+               if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
+                       // if recv returns zero (even though poll() said there is data to be read),
+                       // that means the connection has been closed
+                       return -1;
+               }
+       }
 
        while (nleft > 0)
        {
@@ -318,9 +333,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);
@@ -331,7 +345,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;
 
@@ -358,31 +372,9 @@ int strjoin (char *buffer, size_t buffer_size,
        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 */
@@ -393,15 +385,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)
     {
@@ -435,9 +426,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;
@@ -491,7 +480,6 @@ size_t strstripnewline (char *buffer)
 int escape_slashes (char *buffer, size_t buffer_size)
 {
        size_t buffer_len;
-       size_t i;
 
        buffer_len = strlen (buffer);
 
@@ -513,7 +501,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] = '_';
@@ -524,9 +512,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;
@@ -600,7 +586,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
@@ -646,7 +631,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
@@ -945,7 +930,6 @@ int format_values (char *ret, size_t ret_len, /* {{{ */
 {
         size_t offset = 0;
         int status;
-        size_t i;
         gauge_t *rates = NULL;
 
         assert (0 == strcmp (ds->type, vl->type));
@@ -971,7 +955,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);
@@ -1153,6 +1137,9 @@ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
        char *ptr;
        char *saveptr;
 
+       if ((buffer == NULL) || (vl == NULL) || (ds == NULL))
+               return EINVAL;
+
        i = 0;
        dummy = buffer;
        saveptr = NULL;
@@ -1522,17 +1509,15 @@ int value_to_rate (gauge_t *ret_rate, /* {{{ */
 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);
@@ -1544,7 +1529,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)
                {
@@ -1635,9 +1620,7 @@ 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 */
index c3f7f54..8079661 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
index 399f8b5..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;
@@ -90,7 +90,6 @@ DEF_TEST(sstrdup)
   EXPECT_EQ_STR ("collectd", ptr);
 
   sfree(ptr);
-  OK(ptr == NULL);
 
   ptr = sstrdup (NULL);
   OK(ptr == NULL);
@@ -204,9 +203,8 @@ DEF_TEST(escape_slashes)
     {"trailing/slash/", "trailing_slash_"},
     {"foo//bar", "foo__bar"},
   };
-  size_t i;
 
-  for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
     char buffer[32];
 
     strncpy (buffer, cases[i].str, sizeof (buffer));
@@ -231,9 +229,8 @@ DEF_TEST(escape_string)
     {"012345 78901234", "\"012345 789012\""},
     {"012345 78901\"34", "\"012345 78901\""},
   };
-  size_t i;
 
-  for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
     char buffer[16];
 
     strncpy (buffer, cases[i].str, sizeof (buffer));
@@ -302,8 +299,7 @@ DEF_TEST(parse_values)
     {"T:42.0",           -1,  NAN},
   };
 
-  size_t i;
-  for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
   {
     data_source_t dsrc = {
       .name = "value",
@@ -362,9 +358,8 @@ DEF_TEST(value_to_rate)
     /* 64bit wrap-around. */
     {30, 40, DS_TYPE_COUNTER, {.counter = 18446744073709551558ULL}, {.counter =   42}, 10.0},
   };
-  size_t i;
 
-  for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+  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;
 
index ae9ab3a..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,12 +286,11 @@ 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)
+       for (int i = 0; i < ci->children_num; ++i)
        {
                oconfig_item_t *child = ci->children + i;
 
@@ -325,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;
 
@@ -358,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);
@@ -380,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);
@@ -405,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);
@@ -427,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)
                {
@@ -442,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);
@@ -478,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);
@@ -486,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)
                {
@@ -514,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)
@@ -562,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)
@@ -587,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;
 
@@ -610,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;
 
@@ -704,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);
 
@@ -717,13 +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)
        {
@@ -740,7 +725,8 @@ static oconfig_item_t *cf_read_dir (const char *dir,
                        ERROR ("configfile: Not including `%s/%s' because its"
                                        " name is too long.",
                                        dir, de->d_name);
-                       for (i = 0; i < filenames_num; ++i)
+                       closedir (dh);
+                       for (int i = 0; i < filenames_num; ++i)
                                free (filenames[i]);
                        free (filenames);
                        free (root);
@@ -748,11 +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.");
-                       for (i = 0; i < filenames_num - 1; ++i)
+                       closedir (dh);
+                       for (int i = 0; i < filenames_num - 1; ++i)
                                free (filenames[i]);
                        free (filenames);
                        free (root);
@@ -764,12 +751,15 @@ static oconfig_item_t *cf_read_dir (const char *dir,
        }
 
        if (filenames == NULL)
+       {
+               closedir (dh);
                return (root);
+       }
 
        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];
@@ -789,11 +779,12 @@ static oconfig_item_t *cf_read_dir (const char *dir,
                free (name);
        }
 
+       closedir (dh);
        free(filenames);
        return (root);
 } /* oconfig_item_t *cf_read_dir */
 
-/* 
+/*
  * cf_read_generic
  *
  * Path is stat'ed and either cf_read_file or cf_read_dir is called
@@ -801,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
@@ -812,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)
        {
@@ -828,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;
@@ -919,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++)
@@ -933,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);
        }
 
@@ -949,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);
@@ -1013,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)
@@ -1032,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)
@@ -1060,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;
@@ -1077,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);
 
@@ -1108,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)
@@ -1126,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 5042913..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,19 +880,18 @@ 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;
+  int status = FC_TARGET_CONTINUE;
 
   if (chain == NULL)
     return (-1);
 
   DEBUG ("fc_process_chain (chain = %s);", chain->name);
 
-  status = FC_TARGET_CONTINUE;
-  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;
 
     if (rule->name[0] != 0)
     {
@@ -976,8 +953,7 @@ int fc_process_chain (const data_set_t *ds, value_list_t *vl, /* {{{ */
       }
     }
 
-    if ((status == FC_TARGET_STOP)
-        || (status == FC_TARGET_RETURN))
+    if ((status == FC_TARGET_STOP) || (status == FC_TARGET_RETURN))
     {
       if (rule->name[0] != 0)
       {
@@ -988,20 +964,10 @@ int fc_process_chain (const data_set_t *ds, value_list_t *vl, /* {{{ */
       }
       break;
     }
-    else
-    {
-      status = FC_TARGET_CONTINUE;
-    }
   } /* for (rule) */
 
-  if (status == FC_TARGET_STOP)
-    return (FC_TARGET_STOP);
-  else if (status == FC_TARGET_RETURN)
-    return (FC_TARGET_CONTINUE);
-
-  /* for-loop has been aborted: A target returned `FC_TARGET_STOP' */
-  if (rule != NULL)
-    return (FC_TARGET_CONTINUE);
+  if ((status == FC_TARGET_STOP) || (status == FC_TARGET_RETURN))
+    return (status);
 
   DEBUG ("fc_process_chain (%s): Executing the default targets.",
       chain->name);
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 6ee8446..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,20 +104,37 @@ 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)
+    return (NULL);
   copy->type = orig->type;
   if (copy->type == MD_TYPE_STRING)
     copy->value.mv_string = strdup (orig->value.mv_string);
   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 */
@@ -196,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)
 {
@@ -212,21 +284,30 @@ static meta_entry_t *md_entry_lookup (meta_data_t *md, /* {{{ */
 } /* }}} meta_entry_t *md_entry_lookup */
 
 /*
+ * Each value_list_t*, as it is going through the system, is handled by exactly
+ * one thread. Plugins which pass a value_list_t* to another thread, e.g. the
+ * rrdtool plugin, must create a copy first. The meta data within a
+ * value_list_t* is not thread safe and doesn't need to be.
+ *
+ * The meta data associated with cache entries are a different story. There, we
+ * need to ensure exclusive locking to prevent leaks and other funky business.
+ * This is ensured by the uc_meta_data_get_*() functions.
+ */
+
+/*
  * Public functions
  */
 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);
@@ -250,12 +331,31 @@ 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)
     return;
 
-  pthread_mutex_destroy(&md->lock);
   md_entry_free (md->head);
   pthread_mutex_destroy (&md->lock);
   free (md);
@@ -263,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)
     {
@@ -285,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)
     {
@@ -308,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)
   {
@@ -325,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 */
@@ -506,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);
index b4c0e27..35cfe71 100644 (file)
  *   Florian octo Forster <octo at collectd.org>
  */
 
-#include "testing.h"
-#include "collectd.h"
 #include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "collectd.h"
+
+#include "testing.h"
 #include "meta_data.h"
 
 DEF_TEST(base)
index 831e3fb..1bee8cd 100644 (file)
@@ -26,6 +26,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -288,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);
                }
@@ -318,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;
 
@@ -358,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, /* {{{ */
@@ -368,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)
@@ -483,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;
@@ -562,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)
@@ -605,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));
 
@@ -623,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));
 
@@ -637,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;
 
@@ -650,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)
@@ -667,8 +683,6 @@ static void start_read_threads (int num)
 
 static void stop_read_threads (void)
 {
-       int i;
-
        if (read_threads == NULL)
                return;
 
@@ -680,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)
                {
@@ -852,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;
 
@@ -865,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;
 
@@ -941,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)
@@ -959,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);
@@ -980,7 +992,7 @@ static int plugin_mark_loaded (char const *name)
        return (status);
 }
 
-static void plugin_free_loaded ()
+static void plugin_free_loaded (void)
 {
        void *key;
        void *value;
@@ -1226,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;
@@ -1260,14 +1271,13 @@ int plugin_register_complex_read (const char *group, const char *name,
        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));
@@ -1319,13 +1329,13 @@ static void plugin_flush_timeout_callback_free (void *data)
 
        if (cb == NULL) return;
 
-       sfree(cb->name);
-       sfree(cb);
+       sfree (cb->name);
+       sfree (cb);
 } /* static void plugin_flush_callback_free */
 
 static char *plugin_flush_callback_name (const char *name)
 {
-       char *flush_prefix = "flush/";
+       const char *flush_prefix = "flush/";
        size_t prefix_size;
        char *flush_name;
        size_t name_size;
@@ -1333,7 +1343,7 @@ static char *plugin_flush_callback_name (const char *name)
        prefix_size = strlen(flush_prefix);
        name_size = strlen(name);
 
-       flush_name = malloc (sizeof(char) * (name_size + prefix_size + 1));
+       flush_name = malloc (name_size + prefix_size + 1);
        if (flush_name == NULL)
        {
                ERROR ("plugin_flush_callback_name: malloc failed.");
@@ -1360,18 +1370,17 @@ int plugin_register_flush (const char *name,
        if (ctx.flush_interval != 0)
        {
                char *flush_name;
-               user_data_t ud;
                flush_callback_t *cb;
 
                flush_name = plugin_flush_callback_name (name);
                if (flush_name == NULL)
                        return (-1);
 
-               cb = malloc(sizeof(flush_callback_t));
+               cb = malloc(sizeof (*cb));
                if (cb == NULL)
                {
                        ERROR ("plugin_register_flush: malloc failed.");
-                       sfree(flush_name);
+                       sfree (flush_name);
                        return (-1);
                }
 
@@ -1379,27 +1388,27 @@ int plugin_register_flush (const char *name,
                if (cb->name == NULL)
                {
                        ERROR ("plugin_register_flush: strdup failed.");
-                       sfree(cb);
-                       sfree(flush_name);
+                       sfree (cb);
+                       sfree (flush_name);
                        return (-1);
                }
                cb->timeout = ctx.flush_timeout;
 
-               ud.data = cb;
-               ud.free_func = plugin_flush_timeout_callback_free;
+               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);
+                       /* user data = */ ud);
 
-               sfree(flush_name);
+               sfree (flush_name);
                if (status != 0)
                {
-                       sfree(cb->name);
-                       sfree(cb);
+                       sfree (cb->name);
+                       sfree (cb);
                        return status;
                }
        }
@@ -1445,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;
-       size_t i;
 
        if ((data_sets != NULL)
                        && (c_avl_get (data_sets, ds->type, NULL) == 0))
@@ -1460,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));
@@ -1633,7 +1641,7 @@ int plugin_unregister_flush (const char *name)
                if (flush_name != NULL)
                {
                        plugin_unregister_read(flush_name);
-                       sfree(flush_name);
+                       sfree (flush_name);
                }
        }
 
@@ -1676,12 +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;
-       long write_threads_num;
        llentry_t *le;
        int status;
+       int ret = 0;
 
        /* Init the value cache */
        uc_init ();
@@ -1726,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
@@ -1755,6 +1763,7 @@ void plugin_init_all (void)
                         * handling themselves. */
                        /* FIXME: Unload _all_ functions */
                        plugin_unregister_read (le->key);
+                       ret = -1;
                }
 
                le = le->next;
@@ -1776,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. */
@@ -1959,14 +1969,15 @@ 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;
-
-       stop_read_threads ();
+       int ret = 0;  // Assume success.
 
        destroy_all_callbacks (&list_init);
 
+       stop_read_threads ();
+
        pthread_mutex_lock (&read_lock);
        llist_destroy (read_list);
        read_list = NULL;
@@ -1974,6 +1985,10 @@ void plugin_shutdown_all (void)
 
        destroy_read_heap ();
 
+       /* blocks until all write threads have shut down. */
+       stop_write_threads ();
+
+       /* ask all plugins to write out the state they kept. */
        plugin_flush (/* plugin = */ NULL,
                        /* timeout = */ 0,
                        /* identifier = */ NULL);
@@ -1998,13 +2013,12 @@ void plugin_shutdown_all (void)
                 * after callback returns. */
                le = le->next;
 
-               (*callback) ();
+               if ((*callback) () != 0)
+                       ret = -1;
 
                plugin_set_ctx (old_ctx);
        }
 
-       stop_write_threads ();
-
        /* Write plugins which use the `user_data' pointer usually need the
         * same data available to the flush callback. If this is the case, set
         * the free_function to NULL when registering the flush callback and to
@@ -2020,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) /* {{{ */
@@ -2075,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);
@@ -2197,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;
                        }
@@ -2226,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;
        }
@@ -2341,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)
@@ -2384,7 +2401,7 @@ int plugin_dispatch_multivalue (value_list_t const *template, /* {{{ */
                case DS_TYPE_GAUGE:
                        vl->values[0].gauge = va_arg (ap, gauge_t);
                        if (store_percentage)
-                               vl->values[0].gauge *= 100.0 / sum;
+                               vl->values[0].gauge *= sum ? (100.0 / sum) : 0;
                        break;
                case DS_TYPE_ABSOLUTE:
                        vl->values[0].absolute = va_arg (ap, absolute_t);
@@ -2562,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;
@@ -2665,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,
@@ -2712,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);
@@ -2819,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 b1adb52..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
@@ -240,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
@@ -334,7 +335,7 @@ int plugin_unregister_notification (const char *name);
  *  Since some writers dynamically build their name it can be hard for
  *  the configuring person to know it. This function will fill this gap.
  */
-void plugin_log_available_writers ();
+void plugin_log_available_writers (void);
 
 /*
  * NAME
@@ -459,4 +460,10 @@ cdtime_t plugin_get_interval (void);
 int plugin_thread_create (pthread_t *thread, const pthread_attr_t *attr,
                void *(*start_routine) (void *), void *arg);
 
+/*
+ * Plugins need to implement this
+ */
+
+void module_register (void);
+
 #endif /* PLUGIN_H */
index f7bf1c0..b6efa3a 100644 (file)
 kstat_ctl_t *kc = NULL;
 #endif /* HAVE_LIBKSTAT */
 
+char hostname_g[] = "example.com";
+
+int plugin_register_complex_config (const char *type, int (*callback) (oconfig_item_t *))
+{
+  return ENOTSUP;
+}
+
+int plugin_register_init (const char *name, plugin_init_cb callback)
+{
+  return ENOTSUP;
+}
+
+int plugin_register_read (const char *name, int (*callback) (void))
+{
+  return ENOTSUP;
+}
+
+int plugin_register_shutdown (const char *name, int (*callback) (void))
+{
+  return ENOTSUP;
+}
+
+int plugin_dispatch_values (value_list_t const *vl)
+{
+  return ENOTSUP;
+}
+
 void plugin_log (int level, char const *format, ...)
 {
   char buffer[1024];
@@ -42,4 +69,9 @@ void plugin_log (int level, char const *format, ...)
   printf ("plugin_log (%i, \"%s\");\n", level, buffer);
 }
 
+cdtime_t plugin_get_interval (void)
+{
+  return TIME_T_TO_CDTIME_T (10);
+}
+
 /* vim: set sw=2 sts=2 et : */
index 75a980a..34c222c 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 
 #include "plugin.h"
 #include "configfile.h"
+#include "types_list.h"
 
 static int parse_ds (data_source_t *dsrc, char *buf, size_t buf_len)
 {
@@ -101,7 +103,6 @@ static void parse_line (char *buf)
   char  *fields[64];
   size_t fields_num;
   data_set_t *ds;
-  size_t i;
 
   fields_num = strsplit (buf, fields, 64);
   if (fields_num < 2)
@@ -111,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 #%zu "
          "of data set %s", i, ds->type);
+      sfree (ds->ds);
+      sfree (ds);
       return;
     }
 
index e251975..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"
@@ -245,7 +241,7 @@ static void rebalance (c_avl_tree_t *t, c_avl_node_t *n)
                {
                        assert (n->right != NULL);
                        b_bottom = BALANCE (n->right);
-                       assert ((b_bottom >= -1) || (b_bottom <= 1));
+                       assert ((b_bottom >= -1) && (b_bottom <= 1));
                        if (b_bottom == 1)
                                n = rotate_right_left (t, n);
                        else
@@ -255,7 +251,7 @@ static void rebalance (c_avl_tree_t *t, c_avl_node_t *n)
                {
                        assert (n->left != NULL);
                        b_bottom = BALANCE (n->left);
-                       assert ((b_bottom >= -1) || (b_bottom <= 1));
+                       assert ((b_bottom >= -1) && (b_bottom <= 1));
                        if (b_bottom == -1)
                                n = rotate_left_right (t, n);
                        else
@@ -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;
@@ -652,6 +648,7 @@ int c_avl_pick (c_avl_tree_t *t, void **key, void **value)
        *value = n->value;
 
        free_node (n);
+       --t->size;
        rebalance (t, p);
 
        return (0);
@@ -664,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 3f7a596..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"
@@ -32,7 +35,6 @@
 #include "meta_data.h"
 
 #include <assert.h>
-#include <pthread.h>
 
 typedef struct cache_entry_s
 {
@@ -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;
 
@@ -83,13 +92,12 @@ 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)
 {
-  size_t 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;
@@ -146,7 +152,6 @@ static int uc_insert (const data_set_t *ds, const value_list_t *vl,
 {
   char *key_copy;
   cache_entry_t *ce;
-  size_t i;
 
   /* `cache_lock' has been locked by `uc_update' */
 
@@ -167,7 +172,7 @@ static int uc_insert (const data_set_t *ds, const value_list_t *vl,
 
   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)
     {
@@ -193,12 +198,13 @@ static int uc_insert (const data_set_t *ds, const value_list_t *vl,
            / CDTIME_T_TO_DOUBLE (vl->interval);
        ce->values_raw[i].absolute = vl->values[i].absolute;
        break;
-       
+
       default:
        /* This shouldn't happen. */
        ERROR ("uc_insert: Don't know how to handle data source type %i.",
            ds->ds[i].type);
        sfree (key_copy);
+       cache_free (ce);
        return (-1);
     } /* switch (ds->ds[i].type) */
   } /* for (i) */
@@ -245,8 +251,7 @@ int uc_check_timeout (void)
   c_avl_iterator_t *iter;
 
   int status;
-  int i;
-  
+
   pthread_mutex_lock (&cache_lock);
 
   now = cdtime ();
@@ -263,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)
     {
@@ -317,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;
 
@@ -342,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;
@@ -374,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;
-  size_t i;
 
   if (FORMAT_VL (name, sizeof (name), vl) != 0)
   {
@@ -406,7 +410,7 @@ 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)
     {
@@ -455,7 +459,7 @@ int uc_update (const data_set_t *ds, const value_list_t *vl)
   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];
@@ -498,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.");
@@ -558,7 +562,7 @@ gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl)
   return (ret);
 } /* gauge_t *uc_get_rate */
 
-size_t uc_get_size() {
+size_t uc_get_size (void) {
   size_t size_arrays = 0;
 
   pthread_mutex_lock (&cache_lock);
@@ -635,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]);
     }
@@ -690,7 +692,7 @@ int uc_set_state (const data_set_t *ds, const value_list_t *vl, int state)
 
   if (FORMAT_VL (name, sizeof (name), vl) != 0)
   {
-    ERROR ("uc_get_state: FORMAT_VL failed.");
+    ERROR ("uc_set_state: FORMAT_VL failed.");
     return (STATE_ERROR);
   }
 
@@ -712,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);
@@ -735,7 +736,6 @@ int uc_get_history_by_name (const char *name,
   if (ce->history_length < num_steps)
   {
     gauge_t *tmp;
-    size_t i;
 
     tmp = realloc (ce->history, sizeof (*ce->history)
        * num_steps * ce->values_num);
@@ -745,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;
@@ -755,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;
@@ -799,7 +799,7 @@ int uc_get_hits (const data_set_t *ds, const value_list_t *vl)
 
   if (FORMAT_VL (name, sizeof (name), vl) != 0)
   {
-    ERROR ("uc_get_state: FORMAT_VL failed.");
+    ERROR ("uc_get_hits: FORMAT_VL failed.");
     return (STATE_ERROR);
   }
 
@@ -824,7 +824,7 @@ int uc_set_hits (const data_set_t *ds, const value_list_t *vl, int hits)
 
   if (FORMAT_VL (name, sizeof (name), vl) != 0)
   {
-    ERROR ("uc_get_state: FORMAT_VL failed.");
+    ERROR ("uc_set_hits: FORMAT_VL failed.");
     return (STATE_ERROR);
   }
 
@@ -850,7 +850,7 @@ int uc_inc_hits (const data_set_t *ds, const value_list_t *vl, int step)
 
   if (FORMAT_VL (name, sizeof (name), vl) != 0)
   {
-    ERROR ("uc_get_state: FORMAT_VL failed.");
+    ERROR ("uc_inc_hits: FORMAT_VL failed.");
     return (STATE_ERROR);
   }
 
@@ -869,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 ea3eb2f..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
@@ -40,7 +42,7 @@ int uc_update (const data_set_t *ds, const value_list_t *vl);
 int uc_get_rate_by_name (const char *name, gauge_t **ret_values, size_t *ret_values_num);
 gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl);
 
-size_t uc_get_size();
+size_t uc_get_size (void);
 int uc_get_names (char ***ret_names, cdtime_t **ret_times, size_t *ret_number);
 
 int uc_get_state (const data_set_t *ds, const value_list_t *vl);
@@ -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 37f21ed..1080c80 100644 (file)
@@ -26,8 +26,8 @@
 
 #include "utils_cache.h"
 
-gauge_t *uc_get_rate (__attribute((unused)) data_set_t const *ds,
-                      __attribute((unused)) value_list_t const *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 a8ca7db..ff73ad7 100644 (file)
  * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  * See the GNU General Public Licence for more details.
  *
- * You should have received a copy of the GNU General Public
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
+ * 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:
  *   Lubos Stanek <lubek at users.sourceforge.net>
@@ -28,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),
@@ -95,34 +94,32 @@ static int ignorelist_append_regex(ignorelist_t *il, const char *re_str)
        ignorelist_item_t *entry;
        int status;
 
-       re = malloc (sizeof (*re));
+       re = calloc (1, sizeof (*re));
        if (re == NULL)
        {
-               ERROR ("utils_ignorelist: malloc failed");
+               ERROR ("ignorelist_append_regex: calloc failed.");
                return (ENOMEM);
        }
-       memset (re, 0, sizeof (*re));
 
        status = regcomp (re, re_str, REG_EXTENDED);
        if (status != 0)
        {
-               char errbuf[1024] = "";
-               regerror (status, re, errbuf, sizeof (errbuf));
+               char errbuf[1024];
+               (void) regerror (status, re, errbuf, sizeof (errbuf));
                ERROR ("utils_ignorelist: regcomp failed: %s", errbuf);
-               regfree (re);
+               ERROR ("ignorelist_append_regex: Compiling regular expression \"%s\" failed: %s", re_str, errbuf);
                sfree (re);
                return (status);
        }
 
-       entry = malloc (sizeof (*entry));
+       entry = calloc (1, sizeof (*entry));
        if (entry == NULL)
        {
-               ERROR ("utils_ignorelist: malloc failed");
+               ERROR ("ignorelist_append_regex: calloc failed.");
                regfree (re);
                sfree (re);
                return (ENOMEM);
        }
-       memset (entry, 0, sizeof (*entry));
        entry->rmatch = re;
 
        ignorelist_append (il, entry);
@@ -135,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 */
@@ -195,9 +191,9 @@ ignorelist_t *ignorelist_create (int invert)
 {
        ignorelist_t *il;
 
-       /* smalloc exits if it failes */
-       il = (ignorelist_t *) smalloc (sizeof (ignorelist_t));
-       memset (il, '\0', sizeof (ignorelist_t));
+       il = calloc (1, sizeof (*il));
+       if (il == NULL)
+               return NULL;
 
        /*
         * ->ignore == 0  =>  collect
@@ -239,7 +235,6 @@ void ignorelist_free (ignorelist_t *il)
        }
 
        sfree (il);
-       il = NULL;
 } /* void ignorelist_destroy (ignorelist_t *il) */
 
 /*
@@ -262,7 +257,7 @@ void ignorelist_set_invert (ignorelist_t *il, int invert)
  */
 int ignorelist_add (ignorelist_t *il, const char *entry)
 {
-       size_t entry_len;
+       size_t len;
 
        if (il == NULL)
        {
@@ -270,10 +265,10 @@ int ignorelist_add (ignorelist_t *il, const char *entry)
                return (1);
        }
 
-       entry_len = strlen (entry);
+       len = strlen (entry);
 
        /* append nothing */
-       if (entry_len == 0)
+       if (len == 0)
        {
                DEBUG("not appending: empty entry");
                return (1);
@@ -281,19 +276,21 @@ int ignorelist_add (ignorelist_t *il, const char *entry)
 
 #if HAVE_REGEX_H
        /* regex string is enclosed in "/.../" */
-       if ((entry_len > 2) && (entry[0] == '/') && entry[entry_len - 1] == '/')
+       if ((len > 2) && (entry[0] == '/') && entry[len - 1] == '/')
        {
-               char *entry_copy;
-               size_t entry_copy_size;
+               char *copy;
                int status;
 
-               /* We need to copy `entry' since it's const */
-               entry_copy_size = entry_len - 1;
-               entry_copy = smalloc (entry_copy_size);
-               sstrncpy (entry_copy, entry + 1, entry_copy_size);
+               /* skip leading slash */
+               copy = strdup (entry + 1);
+               if (copy == NULL)
+                       return ENOMEM;
 
-               status = ignorelist_append_regex(il, entry_copy);
-               sfree (entry_copy);
+               /* trim trailing slash */
+               copy[strlen (copy) - 1] = 0;
+
+               status = ignorelist_append_regex (il, copy);
+               sfree (copy);
                return status;
        }
 #endif
@@ -307,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);
@@ -317,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 b47b55a..db7535f 100644 (file)
  * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  * See the GNU General Public Licence for more details.
  *
- * You should have received a copy of the GNU General Public
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
+ * 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:
  *   Lubos Stanek <lubek at users.sourceforge.net>
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 5083b05..5273c90 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 b873845..0488f91 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "utils_time.h"
+#include "utils_random.h"
 
 #include <pthread.h>
 
+
 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
 static _Bool have_seed = 0;
 static unsigned short seed[3];
index 43634df..1bc28f7 100644 (file)
@@ -29,7 +29,9 @@
  */
 
 #include "collectd.h"
+
 #include "common.h"
+#include "utils_subst.h"
 
 char *subst (char *buf, size_t buflen, const char *string, size_t off1, size_t off2,
                const char *replacement)
@@ -101,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;
 
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);
 
 /*
index c12aa10..c6caba2 100644 (file)
  *   Florian octo Forster <octo at collectd.org>
  */
 
-#include "testing.h"
-#include "collectd.h"
 #include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "collectd.h"
+
+#include "testing.h"
 #include "utils_subst.h"
 
 #if HAVE_LIBKSTAT
@@ -36,11 +37,11 @@ kstat_ctl_t *kc;
 DEF_TEST(subst)
 {
   struct {
-    char *str;
+    const char *str;
     int off1;
     int off2;
-    char *rplmt;
-    char *want;
+    const char *rplmt;
+    const char *want;
   } cases[] = {
     {"foo_____bar", 3, 8, " - ", "foo - bar"}, /* documentation example */
     {"foo bar", 0, 2, "m",     "mo bar"},    /* beginning, shorten */
@@ -75,9 +76,8 @@ DEF_TEST(subst)
     {"foo bar",  4,  3, "_",  NULL}, /* off1 > off2 */
     {"foo bar",  3,  4, NULL, NULL}, /* no replacement */
   };
-  size_t i;
 
-  for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
     char buffer[16] = "!!!!!!!!!!!!!!!";
 
     if (cases[i].want == NULL) {
@@ -95,7 +95,10 @@ DEF_TEST(subst)
 DEF_TEST(subst_string)
 {
   struct {
-    char *str;          char *srch; char *rplmt; char *want;
+    const char *str;
+    const char *srch;
+    const char *rplmt;
+    const char *want;
   } cases[] = {
     {"Hello %{name}",    "%{name}", "world", "Hello world"},
     {"abcccccc",         "abc",     "cab",   "ccccccab"},
@@ -105,9 +108,8 @@ DEF_TEST(subst_string)
     {"foo bar",          "oo",      "oo",    "foo bar"},
     {"sixteen chars",    "chars",   "characters", "sixteen charact"},
   };
-  size_t i;
 
-  for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
     char buffer[16];
 
     if (cases[i].want == NULL) {
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 5d905d9..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,43 +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 < 0) ? 0
-      : (((size_t) n) < (max - len)) ? ((size_t) 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) {
-    size_t 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 6566a73..4d88dcc 100644 (file)
 
 #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
@@ -37,7 +43,7 @@
  * 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; */
 
 #define CDTIME_T_TO_DOUBLE(t) (((double) (t)) / 1073741824.0)
 #define DOUBLE_TO_CDTIME_T(d) ((cdtime_t) ((d) * 1073741824.0))
 
-#define CDTIME_T_TO_TIMEVAL(cdt,tvp) do {                                    \
-        (tvp)->tv_sec = CDTIME_T_TO_TIME_T (cdt);                            \
-        (tvp)->tv_usec = (suseconds_t) CDTIME_T_TO_US ((cdt) & 0x3fffffff);  \
+#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) 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 = (long) CDTIME_T_TO_NS ((cdt) & 0x3fffffff);               \
+#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) 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 217515e..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 ((cdtime_t) 1542455354518929408ULL);
-}
-
index 8eac0b6..9f04368 100644 (file)
@@ -26,8 +26,9 @@
 
 #define DBL_PRECISION 1e-3
 
-#include "testing.h"
 #include "collectd.h"
+
+#include "testing.h"
 #include "utils_time.h"
 
 DEF_TEST(conversion)
@@ -62,11 +63,10 @@ DEF_TEST(conversion)
     // 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}, {1439981005,  47589622}},
+    {1546167986577716567ULL, 1439981150.048, 1439981150, 1439981150048ULL, {1439981150,  47590}, {1439981150,  47589622}},
   };
-  size_t i;
 
-  for (i = 0; i < (sizeof (cases) / sizeof (cases[0])); i++) {
+  for (size_t i = 0; i < (sizeof (cases) / sizeof (cases[0])); i++) {
     struct timeval tv;
     struct timespec ts;
 
@@ -78,10 +78,12 @@ DEF_TEST(conversion)
 
     // 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
@@ -105,9 +107,8 @@ DEF_TEST(ns_to_cdtime)
     // 1439981880053705608 * 2^30 / 10^9 = 1546168770415815077.4
     {1439981880053705608ULL, 1546168770415815077ULL},
   };
-  size_t i;
 
-  for (i = 0; i < (sizeof (cases) / sizeof (cases[0])); i++) {
+  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));
   }
 
index 94d0762..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"
@@ -148,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);
@@ -178,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)
@@ -195,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);
 
@@ -214,7 +213,7 @@ static void cdbi_database_free (cdbi_database_t *db) /* {{{ */
  *     </Result>
  *     ...
  *   </Query>
- *     
+ *
  *   <Database "plugin_instance1">
  *     Driver "mysql"
  *     Interval 120
@@ -240,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)
   {
@@ -284,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))
@@ -294,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)
@@ -310,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;
 
@@ -356,23 +353,20 @@ static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
 
   while ((status == 0) && (db->queries_num > 0))
   {
-    size_t j;
-    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 (j = 0; j < db->queries_num; ++j)
+    for (size_t i = 0; i < db->queries_num; ++i)
     {
-      db->q_prep_areas[j]
-        = udb_query_allocate_preparation_area (db->queries[j]);
+      db->q_prep_areas[i]
+        = udb_query_allocate_preparation_area (db->queries[i]);
 
-      if (db->q_prep_areas[j] == NULL)
+      if (db->q_prep_areas[i] == NULL)
       {
         WARNING ("dbi plugin: udb_query_allocate_preparation_area failed");
         status = -1;
@@ -388,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)
     {
@@ -397,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);
@@ -429,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)
@@ -500,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. */
@@ -512,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);
@@ -548,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;
 
@@ -624,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);
@@ -680,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)
@@ -722,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)
     {
@@ -755,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))
       {
@@ -804,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;
 
@@ -819,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. */
@@ -844,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 cb0ff2f..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"
@@ -53,7 +54,6 @@ static const char *config_keys[] =
        "FSType",
        "IgnoreSelected",
        "ReportByDevice",
-       "ReportReserved",
        "ReportInodes",
        "ValuesAbsolute",
        "ValuesPercentage"
@@ -191,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)
@@ -200,10 +199,11 @@ 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];
+               cu_mount_t *dup_ptr;
                uint64_t blk_free;
                uint64_t blk_reserved;
                uint64_t blk_used;
@@ -219,6 +219,27 @@ static int df_read (void)
                if (ignorelist_match (il_fstype, mnt_ptr->type))
                        continue;
 
+               /* search for duplicates *in front of* the current mnt_ptr. */
+               for (dup_ptr = mnt_list; dup_ptr != NULL; dup_ptr = dup_ptr->next)
+               {
+                       /* No duplicate found: mnt_ptr is the first of its kind. */
+                       if (dup_ptr == mnt_ptr)
+                       {
+                               dup_ptr = NULL;
+                               break;
+                       }
+
+                       /* Duplicate found: leave non-NULL dup_ptr. */
+                       if (by_device && (strcmp (mnt_ptr->spec_device, dup_ptr->spec_device) == 0))
+                               break;
+                       else if (!by_device && (strcmp (mnt_ptr->dir, dup_ptr->dir) == 0))
+                               break;
+               }
+
+               /* ignore duplicates */
+               if (dup_ptr != NULL)
+                       continue;
+
                if (STATANYFS (mnt_ptr->dir, &statbuf) < 0)
                {
                        char errbuf[1024];
@@ -249,19 +270,15 @@ static int df_read (void)
                else
                {
                        if (strcmp (mnt_ptr->dir, "/") == 0)
-                       {
-                               if (strcmp (mnt_ptr->type, "rootfs") == 0)
-                                       continue;
                                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 8f8f370..d7eb0a5 100644 (file)
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_ignorelist.h"
@@ -106,6 +107,10 @@ 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;
 
@@ -226,7 +231,16 @@ 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
@@ -268,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)
@@ -275,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;
 
@@ -293,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);
 }
@@ -389,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);
 
@@ -504,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);
@@ -515,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))
@@ -536,7 +561,7 @@ static int disk_read (void)
        struct gident *geom_id;
 
        const char *disk_name;
-       long double read_time, write_time;
+       long double read_time, write_time, busy_time, total_duration;
 
        for (retry = 0, dirty = 1; retry < 5 && dirty == 1; retry++) {
                if (snap != NULL)
@@ -613,6 +638,9 @@ static int disk_read (void)
 
                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],
@@ -631,13 +659,23 @@ static int disk_read (void)
                        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;
@@ -673,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);
 
@@ -819,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.. */
@@ -841,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",
@@ -863,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) */
@@ -899,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",
@@ -921,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",
@@ -936,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++;
        }
@@ -959,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",
@@ -970,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",
@@ -985,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);
@@ -1011,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..15fa15a 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>
@@ -94,11 +94,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 +211,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 +238,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)
        {
@@ -392,7 +390,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 +411,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 +427,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 +443,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 cc306dc..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;
@@ -142,8 +142,12 @@ static int drbd_read (void)
                                fields, STATIC_ARRAY_SIZE (fields));
 
                /* ignore headers (first two iterations) */
-               if (fields_num < 4)
+               if ((strcmp(fields[0], "version:") == 0) ||
+                               (strcmp(fields[0], "srcversion:") == 0) ||
+                               (strcmp(fields[0], "GIT-hash:") == 0))
+               {
                        continue;
+               }
 
                if (isdigit(fields[0][0]))
                {
index 1bf9add..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/un.h>
 #include <sys/select.h>
 
@@ -219,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;
@@ -236,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);
@@ -305,8 +302,11 @@ static void *collect (void *arg)
                                                break;
                                continue;
                        }
+                       if (len < 3) { /* [a-z] ':' '\n' */
+                               continue;
+                       }
 
-                       line[len - 1] = '\0';
+                       line[len - 1] = 0;
 
                        log_debug ("collect: line = '%s'", line);
 
@@ -329,12 +329,12 @@ static void *collect (void *arg)
                                bytes = atoi (tmp);
 
                                pthread_mutex_lock (&count_mutex);
-                               type_list_incr (&list_count, type, 1);
+                               type_list_incr (&list_count, type, /* increment = */ 1);
                                pthread_mutex_unlock (&count_mutex);
 
                                if (bytes > 0) {
                                        pthread_mutex_lock (&size_mutex);
-                                       type_list_incr (&list_size, type, bytes);
+                                       type_list_incr (&list_size, type, /* increment = */ bytes);
                                        pthread_mutex_unlock (&size_mutex);
                                }
                        }
@@ -346,14 +346,17 @@ static void *collect (void *arg)
                                pthread_mutex_unlock (&score_mutex);
                        }
                        else if ('c' == line[0]) { /* c:<type1>[,<type2>,...] */
-                               char *ptr  = NULL;
-                               char *type = strtok_r (line + 2, ",", &ptr);
-
-                               do {
-                                       pthread_mutex_lock (&check_mutex);
-                                       type_list_incr (&list_check, type, 1);
-                                       pthread_mutex_unlock (&check_mutex);
-                               } while (NULL != (type = strtok_r (NULL, ",", &ptr)));
+                               char *dummy = line + 2;
+                               char *endptr = NULL;
+                               char *type;
+
+                               pthread_mutex_lock (&check_mutex);
+                               while ((type = strtok_r (dummy, ",", &endptr)) != NULL)
+                               {
+                                       dummy = NULL;
+                                       type_list_incr (&list_check, type, /* increment = */ 1);
+                               }
+                               pthread_mutex_unlock (&check_mutex);
                        }
                        else {
                                log_err ("collect: unknown type '%c'", line[0]);
@@ -383,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;
@@ -462,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;
@@ -476,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;
                        }
@@ -509,28 +509,41 @@ static void *open_connection (void __attribute__((unused)) *arg)
 
                pthread_mutex_unlock (&available_mutex);
 
-               do {
+               while (42) {
                        errno = 0;
-                       if (-1 == (remote = accept (connector_socket, NULL, NULL))) {
-                               if (EINTR != errno) {
-                                       char errbuf[1024];
-                                       disabled = 1;
-                                       close (connector_socket);
-                                       connector_socket = -1;
-                                       log_err ("accept() failed: %s",
-                                                       sstrerror (errno, errbuf, sizeof (errbuf)));
-                                       pthread_exit ((void *)1);
-                               }
+
+                       remote = accept (connector_socket, NULL, NULL);
+                       if (remote == -1) {
+                               char errbuf[1024];
+
+                               if (errno == EINTR)
+                                       continue;
+
+                               disabled = 1;
+                               close (connector_socket);
+                               connector_socket = -1;
+                               log_err ("accept() failed: %s",
+                                                sstrerror (errno, errbuf, sizeof (errbuf)));
+                               pthread_exit ((void *)1);
                        }
-               } while (EINTR == errno);
 
-               connection = (conn_t *)smalloc (sizeof (conn_t));
+                       /* access() succeeded. */
+                       break;
+               }
+
+               connection = calloc (1, sizeof (*connection));
+               if (connection == NULL)
+               {
+                       close (remote);
+                       continue;
+               }
 
                connection->socket = fdopen (remote, "r");
                connection->next   = NULL;
 
                if (NULL == connection->socket) {
                        close (remote);
+                       sfree (connection);
                        continue;
                }
 
@@ -556,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);
        }
@@ -591,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;
@@ -609,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;
 
@@ -667,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;
 
@@ -701,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;
 
@@ -716,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);
        }
 
@@ -727,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);
        }
 
@@ -751,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 dec14f3..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,11 +309,15 @@ 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++)
   {
-    const char *stat_name;
+    char *stat_name;
 
     stat_name = (void *) &strings->data[i * ETH_GSTRING_LEN];
+    /* Remove leading spaces in key name */
+    while (isspace ((int) *stat_name))
+        stat_name++;
+
     DEBUG("ethstat plugin: device = \"%s\": %s = %"PRIu64,
         device, stat_name, (uint64_t) stats->data[i]);
     ethstat_submit_value (device,
@@ -330,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;
old mode 100755 (executable)
new mode 100644 (file)
index f080ad6..e90f83c
@@ -27,6 +27,7 @@
 #define _BSD_SOURCE /* For setgroups */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -38,8 +39,6 @@
 #include <grp.h>
 #include <signal.h>
 
-#include <pthread.h>
-
 #define PL_NORMAL        0x01
 #define PL_NOTIF_ACTION  0x02
 
@@ -126,13 +125,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 +161,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 +181,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 +246,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 +345,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 +469,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 +718,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;
@@ -744,8 +736,7 @@ static void *exec_notification_one (void *arg) /* {{{ */
     char errbuf[1024];
     ERROR ("exec plugin: fdopen (%i) failed: %s", fd,
         sstrerror (errno, errbuf, sizeof (errbuf)));
-    kill (pl->pid, SIGTERM);
-    pl->pid = 0;
+    kill (pid, SIGTERM);
     close (fd);
     sfree (arg);
     pthread_exit ((void *) 1);
@@ -774,7 +765,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);
@@ -809,10 +800,10 @@ 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);
 
   return (0);
@@ -820,9 +811,7 @@ static int exec_init (void) /* {{{ */
 
 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;
@@ -853,10 +842,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;
@@ -869,8 +857,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 4c409b5..c7603c7 100644 (file)
@@ -18,6 +18,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -98,6 +99,7 @@ static int fhcount_read(void) {
   }
   if (fgets(buffer, buffer_len, fp) == NULL) {
     ERROR("fhcount: fgets: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
+    fclose(fp);
     return(EXIT_FAILURE);
   }
   fclose(fp);
index 47caf93..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,18 +344,18 @@ 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)
   {
     ERROR ("filecount plugin: strdup failed.");
+    sfree (dir);
     return (-1);
   }
 
@@ -368,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;
 
@@ -399,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)
     {
@@ -428,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)
@@ -541,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)
@@ -557,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 c778d48..2b299ca 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/gmond.c
- * Copyright (C) 2009,2010  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 "plugin.h"
 #include "common.h"
 #include "configfile.h"
 #include "utils_avltree.h"
 
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
 #if HAVE_NETDB_H
 # include <netdb.h>
 #endif
@@ -214,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;
@@ -227,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)
@@ -252,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;
 
@@ -288,8 +279,14 @@ static int create_sockets (socket_entry_t **ret_sockets, /* {{{ */
     {
       int yes = 1;
 
-      setsockopt (sockets[sockets_num].fd, SOL_SOCKET, SO_REUSEADDR,
+      status = setsockopt (sockets[sockets_num].fd, SOL_SOCKET, SO_REUSEADDR,
           (void *) &yes, sizeof (yes));
+      if (status != 0)
+      {
+        char errbuf[1024];
+        WARNING ("gmond plugin: setsockopt(2) failed: %s",
+                 sstrerror (errno, errbuf, sizeof (errbuf)));
+      }
     }
 
     status = bind (sockets[sockets_num].fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
@@ -305,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;
@@ -317,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;
@@ -341,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++;
@@ -370,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);
@@ -390,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))
@@ -406,11 +425,20 @@ 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++)
-    sendto (mc_send_sockets[i].fd, buffer, (size_t) buffer_size,
+  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,
         (struct sockaddr *) &mc_send_sockets[i].addr,
         mc_send_sockets[i].addrlen);
+    if (status == -1)
+    {
+      char errbuf[1024];
+      ERROR ("gmond plugin: sendto(2) failed: %s",
+             sstrerror (errno, errbuf, sizeof (errbuf)));
+      continue;
+    }
+  }
   pthread_mutex_unlock (&mc_send_sockets_lock);
 
   sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.host);
@@ -439,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;
@@ -476,36 +503,6 @@ static staging_entry_t *staging_entry_get (const char *host, /* {{{ */
   return (se);
 } /* }}} staging_entry_t *staging_entry_get */
 
-static int staging_entry_submit (const char *host, const char *name, /* {{{ */
-    staging_entry_t *se)
-{
-  value_list_t vl;
-  value_t values[se->vl.values_len];
-
-  if (se->vl.interval == 0)
-  {
-    /* No meta data has been received for this metric yet. */
-    se->flags = 0;
-    pthread_mutex_unlock (&staging_lock);
-    request_meta_data (host, name);
-    return (0);
-  }
-
-  se->flags = 0;
-
-  memcpy (values, se->vl.values, sizeof (values));
-  memcpy (&vl, &se->vl, sizeof (vl));
-
-  /* Unlock before calling `plugin_dispatch_values'.. */
-  pthread_mutex_unlock (&staging_lock);
-
-  vl.values = values;
-
-  plugin_dispatch_values (&vl);
-
-  return (0);
-} /* }}} int staging_entry_submit */
-
 static int staging_entry_update (const char *host, const char *name, /* {{{ */
     const char *type, const char *type_instance,
     size_t ds_index, int ds_type, value_t value)
@@ -555,17 +552,30 @@ static int staging_entry_update (const char *host, const char *name, /* {{{ */
 
   se->flags |= (0x01 << ds_index);
 
-  /* Check if all values have been set and submit if so. */
-  if (se->flags == ((0x01 << se->vl.values_len) - 1))
+  /* Check if all data sources have been set. If not, return here. */
+  if (se->flags != ((0x01 << se->vl.values_len) - 1))
   {
-    /* `staging_lock' is unlocked in `staging_entry_submit'. */
-    staging_entry_submit (host, name, se);
+    pthread_mutex_unlock (&staging_lock);
+    return (0);
   }
-  else
+
+  /* Check if the interval of this metric is known. If not, request meta data
+   * and return. */
+  if (se->vl.interval == 0)
   {
+    /* No meta data has been received for this metric yet. */
+    se->flags = 0;
     pthread_mutex_unlock (&staging_lock);
+
+    request_meta_data (host, name);
+    return (0);
   }
 
+  plugin_dispatch_values (&se->vl);
+
+  se->flags = 0;
+  pthread_mutex_unlock (&staging_lock);
+
   return (0);
 } /* }}} int staging_entry_update */
 
@@ -695,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);
@@ -763,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;
@@ -774,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;
@@ -819,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,
@@ -837,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;
@@ -845,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;
@@ -865,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);
@@ -915,7 +922,7 @@ static int mc_receive_thread_stop (void) /* {{{ */
   return (0);
 } /* }}} int mc_receive_thread_stop */
 
-/* 
+/*
  * Config:
  *
  * <Plugin gmond>
@@ -953,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))
   {
@@ -985,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)
@@ -1062,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)
@@ -1088,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.");
@@ -1102,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;
index e43af4a..04de5aa 100644 (file)
--- a/src/gps.c
+++ b/src/gps.c
@@ -285,14 +285,14 @@ static int cgps_config (oconfig_item_t *ci)
     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).", 
+    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);
 }
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 3de18fd..8213e97 100644 (file)
@@ -30,6 +30,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -88,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;
@@ -109,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];
@@ -121,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,
@@ -252,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)
@@ -273,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 e17711e..a74699e 100644 (file)
@@ -23,6 +23,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -84,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)
@@ -113,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);
@@ -125,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;
 
@@ -142,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;
        }
@@ -178,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
@@ -208,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);
@@ -265,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)
        {
@@ -348,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;
 
@@ -363,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 );
@@ -383,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 806b7a4..e035a88 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -61,14 +62,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,
@@ -76,6 +73,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
@@ -85,14 +85,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;
@@ -102,147 +102,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;
-
-       if (( ip_version == IPV4 ) || ( ip_version == IPV6 ))
-       {
-               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);
-       }
-       else 
-       {
-               return (-1);
-       }
-
-       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];
@@ -259,7 +253,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);
     }
 
@@ -269,7 +263,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);
 
@@ -281,10 +275,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));
@@ -301,9 +295,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];
@@ -312,16 +306,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;
@@ -330,22 +324,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));
@@ -361,7 +355,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;
@@ -393,102 +387,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);
@@ -496,15 +488,11 @@ 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);
 
@@ -514,11 +502,8 @@ static int iptables_shutdown (void)
 void module_register (void)
 {
     plugin_register_config ("iptables", iptables_config,
-           config_keys, config_keys_num);
+                             config_keys, config_keys_num);
     plugin_register_read ("iptables", iptables_read);
     plugin_register_shutdown ("iptables", iptables_shutdown);
 } /* void module_register */
 
-/*
- * vim:shiftwidth=4:softtabstop=4:tabstop=8
- */
index 4345a46..92690e8 100644 (file)
@@ -31,6 +31,7 @@
  */
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 
@@ -224,7 +225,8 @@ static int get_ti (struct ip_vs_dest_entry *de, char *ti, size_t size)
        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;
@@ -245,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];
@@ -268,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];
@@ -289,8 +292,6 @@ static void cipvs_submit_service (struct ip_vs_service_entry *se)
 
        char pi[DATA_MAX_NAME_LEN];
 
-       size_t i;
-
        if (0 != get_pi (se, pi, sizeof (pi)))
        {
                free (dests);
@@ -301,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);
@@ -311,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;
-       size_t i;
 
        if (sockfd < 0)
                return (-1);
@@ -319,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 6afacf0..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"
@@ -120,6 +121,7 @@ static int irq_read (void)
        } else {
                ERROR ("irq plugin: unable to get CPU count from first line "
                                "of /proc/interrupts");
+               fclose (fh);
                return (-1);
        }
 
index 6b92f54..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;
-  size_t 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;
-  size_t 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,7 +1426,6 @@ 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;
 
@@ -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 eaee9c0..a15e0aa 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdarg.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/socket.h>
   (c)->errbuf[sizeof ((c)->errbuf) - 1] = 0; \
 } while (0)
 
-#if COLLECT_DEBUG
-# define LCC_DEBUG(...) printf (__VA_ARGS__)
-#else
-# define LCC_DEBUG(...) /**/
-#endif
-
 /*
  * Types
  */
@@ -118,6 +113,22 @@ typedef struct lcc_response_s lcc_response_t;
 /*
  * Private functions
  */
+static int lcc_tracef(char const *format, ...)
+{
+  va_list ap;
+  int status;
+
+  char const *trace = getenv (LCC_TRACE_ENV);
+  if (!trace || (strcmp ("", trace) == 0) || (strcmp ("0", trace) == 0))
+    return 0;
+
+  va_start (ap, format);
+  status = vprintf (format, ap);
+  va_end (ap);
+
+  return status;
+}
+
 /* Even though Posix requires "strerror_r" to return an "int",
  * some systems (e.g. the GNU libc) return a "char *" _and_
  * ignore the second argument ... -tokkee */
@@ -235,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;
@@ -250,7 +259,7 @@ static int lcc_send (lcc_connection_t *c, const char *command) /* {{{ */
 {
   int status;
 
-  LCC_DEBUG ("send:    --> %s\n", command);
+  lcc_tracef ("send:    --> %s\n", command);
 
   status = fprintf (c->fh, "%s\r\n", command);
   if (status < 0)
@@ -266,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)
@@ -281,7 +288,7 @@ static int lcc_receive (lcc_connection_t *c, /* {{{ */
     return (-1);
   }
   lcc_chomp (buffer);
-  LCC_DEBUG ("receive: <-- %s\n", buffer);
+  lcc_tracef ("receive: <-- %s\n", buffer);
 
   /* Convert the leading status to an integer and make `ptr' to point to the
    * beginning of the message. */
@@ -312,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);
@@ -329,7 +336,7 @@ static int lcc_receive (lcc_connection_t *c, /* {{{ */
       break;
     }
     lcc_chomp (buffer);
-    LCC_DEBUG ("receive: <-- %s\n", buffer);
+    lcc_tracef ("receive: <-- %s\n", buffer);
 
     res.lines[i] = strdup (buffer);
     if (res.lines[i] == NULL)
@@ -358,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)
@@ -371,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));
@@ -381,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;
 
@@ -398,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);
 
@@ -424,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;
@@ -441,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 */
   {
@@ -484,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);
@@ -494,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)
@@ -526,9 +526,11 @@ static int lcc_open_netsocket (lcc_connection_t *c, /* {{{ */
   if (status != 0)
   {
     lcc_set_errno (c, status);
+    freeaddrinfo (ai_res);
     return (-1);
   }
 
+  freeaddrinfo (ai_res);
   return (0);
 } /* }}} int lcc_open_netsocket */
 
@@ -582,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)
@@ -685,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);
   }
@@ -748,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))
@@ -773,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);
@@ -865,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;
@@ -892,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);
@@ -900,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;
@@ -1061,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))
@@ -1100,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 6ae8598..47462a6 100644 (file)
 
 #include "lcc_features.h"
 
+/* COLLECTD_TRACE is the environment variable used to control trace output. When
+ * set to something non-zero, all lines sent to / received from the daemon are
+ * printed to STDOUT. */
+#ifndef LCC_TRACE_ENV
+# define LCC_TRACE_ENV "COLLECTD_TRACE"
+#endif
+
 /*
  * Includes (for data types)
  */
@@ -124,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 0539cd0..16293ca 100644 (file)
@@ -89,6 +89,7 @@ static int server_close_socket (lcc_server_t *srv) /* {{{ */
     return (0);
 
   close (srv->fd);
+  srv->fd = -1;
   free (srv->sa);
   srv->sa = NULL;
   srv->sa_len = 0;
@@ -107,12 +108,6 @@ static void int_server_destroy (lcc_server_t *srv) /* {{{ */
 
   next = srv->next;
 
-  if (srv->fd >= 0)
-  {
-    close (srv->fd);
-    srv->fd = -1;
-  }
-
   free (srv->node);
   free (srv->service);
   free (srv->username);
@@ -124,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)
@@ -135,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)
@@ -154,7 +147,6 @@ static int server_open_socket (lcc_server_t *srv) /* {{{ */
 
     if (ai_ptr->ai_family == AF_INET)
     {
-
       struct sockaddr_in *addr = (struct sockaddr_in *) ai_ptr->ai_addr;
       int optname;
 
@@ -163,9 +155,8 @@ static int server_open_socket (lcc_server_t *srv) /* {{{ */
       else
         optname = IP_TTL;
 
-      setsockopt (srv->fd, IPPROTO_IP, optname,
-          &srv->ttl,
-          sizeof (srv->ttl));
+      status = setsockopt (srv->fd, IPPROTO_IP, optname,
+          &srv->ttl, sizeof (srv->ttl));
     }
     else if (ai_ptr->ai_family == AF_INET6)
     {
@@ -178,9 +169,15 @@ static int server_open_socket (lcc_server_t *srv) /* {{{ */
       else
         optname = IPV6_UNICAST_HOPS;
 
-      setsockopt (srv->fd, IPPROTO_IPV6, optname,
-          &srv->ttl,
-          sizeof (srv->ttl));
+      status = setsockopt (srv->fd, IPPROTO_IPV6, optname,
+          &srv->ttl, sizeof (srv->ttl));
+    }
+    if (status != 0)
+    {
+      /* setsockopt failed. */
+      close (srv->fd);
+      srv->fd = -1;
+      continue;
     }
 
     srv->sa = malloc (ai_ptr->ai_addrlen);
@@ -205,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;
 
@@ -216,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);
@@ -272,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;
 
@@ -300,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;
@@ -416,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 = (int) 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,
@@ -477,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 343c285..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.
@@ -134,13 +133,16 @@ static _Bool have_gcrypt (void) /* {{{ */
 
 #if HAVE_LIBGCRYPT
 # if GCRYPT_VERSION_NUMBER < 0x010600
-  gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+  if (gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread))
+    return (0);
 # endif
 
   if (!gcry_check_version (GCRYPT_VERSION))
     return (0);
 
-  gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0);
+  if (!gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0))
+    return (0);
+
   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
 
   result = 1;
@@ -272,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)
@@ -286,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])
@@ -651,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;
@@ -761,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;
@@ -769,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 d01c79d..319aae8 100644 (file)
@@ -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,8 +126,6 @@ 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 ((size_t) ci_orig->values_num,
         sizeof (*ci_copy->values));
     if (ci_copy->values == NULL)
@@ -140,7 +137,7 @@ 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)
@@ -162,8 +159,6 @@ oconfig_item_t *oconfig_clone (const oconfig_item_t *ci_orig)
 
   if (ci_orig->children_num > 0) /* {{{ */
   {
-    int i;
-
     ci_copy->children = (oconfig_item_t *) calloc ((size_t) ci_orig->children_num,
         sizeof (*ci_copy->children));
     if (ci_copy->children == NULL)
@@ -174,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)
       {
@@ -193,17 +188,15 @@ oconfig_item_t *oconfig_clone (const oconfig_item_t *ci_orig)
   return (ci_copy);
 } /* oconfig_item_t *oconfig_clone */
 
-void oconfig_free_all (oconfig_item_t *ci)
+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);
@@ -211,7 +204,7 @@ 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)
@@ -222,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 b75ecb8..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
@@ -201,7 +200,7 @@ static int logfile_notification (const notification_t *n,
 
 #define APPEND(bufptr, buflen, key, value) \
        if ((buflen > 0) && (strlen (value) > 0)) { \
-               int status = ssnprintf (bufptr, buflen, ", %s = %s", key, value); \
+               status = ssnprintf (bufptr, buflen, ", %s = %s", key, value); \
                if (status > 0) { \
                        bufptr += status; \
                        buflen -= status; \
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 bb33b15..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"
@@ -367,35 +368,34 @@ static int init_state = 0;
 static inline int item_watched(int i)
 {
        assert (i >= 0);
-       assert (((size_t) 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 (((size_t) 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;
 }
 
@@ -403,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,15 +419,14 @@ static int watchitem_find (const char *name)
 static int madwifi_real_init (void)
 {
        size_t max = STATIC_ARRAY_SIZE (specs);
-       size_t i;
 
-       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;
 
@@ -439,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);
@@ -589,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;
@@ -614,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 (((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) ;
 
@@ -629,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);
 
@@ -699,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;
@@ -714,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)
@@ -750,17 +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 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)
@@ -821,15 +818,16 @@ check_devname (const char *dev)
 
        if (dev[0] == '.')
                return 0;
-       
+
        ssnprintf (buf, sizeof (buf), "/sys/class/net/%s/device/driver", dev);
-       buf[sizeof (buf) - 1] = 0;
+       buf[sizeof (buf) - 1] = '\0';
 
-       memset (buf2, 0, sizeof (buf2));
        i = readlink (buf, buf2, sizeof (buf2) - 1);
        if (i < 0)
                return 0;
 
+       buf2[i] = '\0';
+
        if (strstr (buf2, "/drivers/ath_") == NULL)
                return 0;
        return 1;
@@ -890,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");
@@ -952,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 e30ff91..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;
-  size_t 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 9ffceca..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) /* {{{ */
 {
-  size_t 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;
-  size_t 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 5e87f00..184bb99 100644 (file)
@@ -24,6 +24,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -84,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;
@@ -105,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];
@@ -117,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)
@@ -239,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';
 }
 
@@ -260,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 3725f9a..6a96a90 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 f684abf..42882ae 100644 (file)
@@ -29,6 +29,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -52,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;
 
@@ -66,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));
@@ -98,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)
   {
@@ -132,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);
@@ -173,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);
@@ -245,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,
@@ -439,7 +437,7 @@ static int memcached_read (user_data_t *user_data)
     }
     else if (FIELD_IS ("listen_disabled_num"))
     {
-      submit_derive ("memcached_connections", "listen_disabled", atof (fields[2]), st);
+      submit_derive ("connections", "listen_disabled", atof (fields[2]), st);
     }
 
     /*
@@ -551,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);
@@ -581,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;
@@ -611,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;
 
@@ -648,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;
 
@@ -685,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 ea16ce3..16b8e09 100644 (file)
@@ -24,6 +24,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -98,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)
@@ -237,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",
@@ -250,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);
@@ -270,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];
 
@@ -456,13 +453,12 @@ static int memory_read_internal (value_list_t *vl)
 
 #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) {
@@ -495,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 cfc6331..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)
@@ -310,7 +309,9 @@ static int mb_init_connection (mb_host_t *host) /* {{{ */
   if (host == NULL)
     return (EINVAL);
 
+#if COLLECT_DEBUG
   modbus_set_debug (&host->connection, 1);
+#endif
 
   /* We'll do the error handling ourselves. */
   modbus_set_error_handling (&host->connection, NOP_ON_ERROR);
@@ -390,7 +391,9 @@ static int mb_init_connection (mb_host_t *host) /* {{{ */
     }
   }
 
+#if COLLECT_DEBUG
   modbus_set_debug (host->connection, 1);
+#endif
 
   /* We'll do the error handling ourselves. */
   modbus_set_error_recovery (host->connection, 0);
@@ -423,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;
@@ -455,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))
@@ -499,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". */
@@ -618,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;
 
@@ -626,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)
@@ -642,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;
 
@@ -652,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)
@@ -691,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 */
@@ -716,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;
@@ -729,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;
 
@@ -815,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)
@@ -845,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),
@@ -872,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);
@@ -889,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;
 
@@ -932,21 +920,25 @@ 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));
   if (status != 0)
+  {
+    sfree (host);
     return (status);
+  }
   if (host->host[0] == 0)
+  {
+    sfree (host);
     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;
@@ -1035,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;
 
index 1b71d42..a7a0b86 100644 (file)
  * 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_cache.h"
 #include "utils_complain.h"
 
-#include <pthread.h>
-
 #include <mosquitto.h>
 
 #define MQTT_MAX_TOPIC_SIZE         1024
@@ -48,6 +47,9 @@
 #ifndef MQTT_KEEPALIVE
 # define MQTT_KEEPALIVE 60
 #endif
+#ifndef SSL_VERIFY_PEER
+# define SSL_VERIFY_PEER  1
+#endif
 
 
 /*
@@ -67,6 +69,11 @@ struct mqtt_client_conf
     char               *username;
     char               *password;
     int                 qos;
+    char                *cacertificatefile;
+    char                *certificatefile;
+    char                *certificatekeyfile;
+    char                *tlsprotocol;
+    char                *ciphersuite;
 
     /* For publishing */
     char               *topic_prefix;
@@ -138,11 +145,9 @@ static void mqtt_free (mqtt_client_conf_t *conf)
 
 static char *strip_prefix (char *topic)
 {
-    size_t num;
-    size_t i;
+    size_t num = 0;
 
-    num = 0;
-    for (i = 0; topic[i] != 0; i++)
+    for (size_t i = 0; topic[i] != 0; i++)
         if (topic[i] == '/')
             num++;
 
@@ -176,9 +181,10 @@ static void on_message (
     char *payload;
     int status;
 
-    if ((msg->payloadlen <= 0)
-            || (((uint8_t *) msg->payload)[msg->payloadlen - 1] != 0))
+    if (msg->payloadlen <= 0) {
+        DEBUG ("mqtt plugin: message has empty payload");
         return;
+    }
 
     topic = strdup (msg->topic);
     name = strip_prefix (topic);
@@ -207,7 +213,16 @@ static void on_message (
     }
     vl.values_len = ds->ds_num;
 
-    payload = strdup ((void *) msg->payload);
+    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)
@@ -277,6 +292,35 @@ static int mqtt_connect (mqtt_client_conf_t *conf)
         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);
@@ -494,20 +538,23 @@ static int mqtt_write (const data_set_t *ds, const value_list_t *vl,
  *   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;
+    user_data_t user_data = { 0 };
     int status;
-    int i;
 
     conf = calloc (1, sizeof (*conf));
     if (conf == NULL)
     {
-        ERROR ("mqtt plugin: malloc failed.");
+        ERROR ("mqtt plugin: calloc failed.");
         return (-1);
     }
     conf->publish = 1;
@@ -536,7 +583,7 @@ static int mqtt_config_publisher (oconfig_item_t *ci)
 
     C_COMPLAIN_INIT (&conf->complaint_cantpublish);
 
-    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 ("Host", child->key) == 0)
@@ -570,12 +617,21 @@ static int mqtt_config_publisher (oconfig_item_t *ci)
             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);
-    memset (&user_data, 0, sizeof (user_data));
     user_data.data = conf;
 
     plugin_register_write (cb_name, mqtt_write, &user_data);
@@ -590,19 +646,18 @@ static int mqtt_config_publisher (oconfig_item_t *ci)
  *   User "guest"
  *   Password "secret"
  *   Topic "collectd/#"
- * </Publish>
+ * </Subscribe>
  */
 static int mqtt_config_subscriber (oconfig_item_t *ci)
 {
     mqtt_client_conf_t **tmp;
     mqtt_client_conf_t *conf;
     int status;
-    int i;
 
     conf = calloc (1, sizeof (*conf));
     if (conf == NULL)
     {
-        ERROR ("mqtt plugin: malloc failed.");
+        ERROR ("mqtt plugin: calloc failed.");
         return (-1);
     }
     conf->publish = 0;
@@ -631,18 +686,18 @@ static int mqtt_config_subscriber (oconfig_item_t *ci)
 
     C_COMPLAIN_INIT (&conf->complaint_cantpublish);
 
-    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 ("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)
+            status = cf_util_get_port_number (child);
+            if (status < 0)
                 ERROR ("mqtt plugin: Invalid port number.");
             else
-                conf->port = tmp;
+                conf->port = status;
         }
         else if (strcasecmp ("ClientId", child->key) == 0)
             cf_util_get_string (child, &conf->client_id);
@@ -652,12 +707,12 @@ static int mqtt_config_subscriber (oconfig_item_t *ci)
             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))
+            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 = tmp;
+                conf->qos = qos;
         }
         else if (strcasecmp ("Topic", child->key) == 0)
             cf_util_get_string (child, &conf->topic);
@@ -667,7 +722,7 @@ static int mqtt_config_subscriber (oconfig_item_t *ci)
             ERROR ("mqtt plugin: Unknown config option: %s", child->key);
     }
 
-    tmp = realloc (subscribers, sizeof (*subscribers) * subscribers_num);
+    tmp = realloc (subscribers, sizeof (*subscribers) * (subscribers_num + 1) );
     if (tmp == NULL)
     {
         ERROR ("mqtt plugin: realloc failed.");
@@ -693,9 +748,7 @@ static int mqtt_config_subscriber (oconfig_item_t *ci)
  */
 static int mqtt_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;
 
@@ -712,11 +765,9 @@ static int mqtt_config (oconfig_item_t *ci)
 
 static int mqtt_init (void)
 {
-    size_t i;
-
     mosquitto_lib_init ();
 
-    for (i = 0; i < subscribers_num; i++)
+    for (size_t i = 0; i < subscribers_num; i++)
     {
         int status;
 
index 775eb57..02fe1ad 100644 (file)
@@ -23,6 +23,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -148,22 +149,21 @@ 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'; 
+               device[strlen(device)-1] = i + '0';
 
-               if ((fd = open(device, O_RDWR | O_NOCTTY)) > 0)
+               if ((fd = open(device, O_RDWR | O_NOCTTY)) != -1)
                {
-                       struct termios tios;
+                       struct termios tios = { 0 };
                        int rts = TIOCM_RTS;
                        double value;
 
                        tios.c_cflag = B1200 | CS7 | CSTOPB | CREAD | CLOCAL;
                        tios.c_iflag = IGNBRK | IGNPAR;
-                       tios.c_oflag = 0;
+                       tios.c_oflag = 0;
                        tios.c_lflag = 0;
                        tios.c_cc[VTIME] = 3;
                        tios.c_cc[VMIN]  = LINE_LENGTH;
@@ -171,7 +171,7 @@ static int multimeter_init (void)
                        tcflush(fd, TCIFLUSH);
                        tcsetattr(fd, TCSANOW, &tios);
                        ioctl(fd, TIOCMBIC, &rts);
-                       
+
                        if (multimeter_read_value (&value) < -1)
                        {
                                close (fd);
index a8a8e86..6ba3005 100644 (file)
@@ -28,6 +28,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -53,6 +54,7 @@ struct mysql_database_s /* {{{ */
        _Bool master_stats;
        _Bool slave_stats;
        _Bool innodb_stats;
+       _Bool wsrep_stats;
 
        _Bool slave_notif;
        _Bool slave_io_running;
@@ -65,16 +67,13 @@ typedef struct mysql_database_s mysql_database_t; /* }}} */
 
 static int mysql_read (user_data_t *ud);
 
-void mysql_read_default_options(struct st_mysql_options *options,
-               const char *filename,const char *group);
-
 static void mysql_database_free (void *arg) /* {{{ */
 {
        mysql_database_t *db;
 
        DEBUG ("mysql plugin: mysql_database_free (arg = %p);", arg);
 
-       db = (mysql_database_t *) arg;
+       db = arg;
 
        if (db == NULL)
                return;
@@ -106,7 +105,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))
@@ -116,13 +114,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;
@@ -147,7 +144,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;
 
@@ -182,6 +179,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);
@@ -195,13 +194,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;
 
@@ -226,13 +224,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;
 
@@ -403,8 +399,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";
@@ -449,8 +445,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 ... :-/ */
@@ -572,84 +568,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'";
 
@@ -659,45 +624,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;
@@ -712,7 +762,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))
        {
@@ -726,7 +776,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)
@@ -744,7 +794,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)
@@ -752,18 +802,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_",
@@ -780,7 +830,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)
@@ -788,7 +838,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)
@@ -832,6 +882,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)
@@ -856,6 +908,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)
@@ -900,8 +954,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;
@@ -940,7 +1005,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);
@@ -948,6 +1013,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 020bfba..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,7 +2872,7 @@ static int cna_read (user_data_t *ud);
 static int cna_register_host (host_config_t *host) /* {{{ */
 {
        char cb_name[256];
-       user_data_t ud;
+       user_data_t ud = { 0 };
 
        if (host->vfiler)
                ssnprintf (cb_name, sizeof (cb_name), "netapp-%s-%s",
@@ -2914,7 +2880,6 @@ static int cna_register_host (host_config_t *host) /* {{{ */
        else
                ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name);
 
-       memset (&ud, 0, sizeof (ud));
        ud.data = host;
        ud.free_func = (void (*) (void *)) free_host_config;
 
@@ -2932,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;
@@ -2946,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;
@@ -3085,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);
@@ -3156,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 e1f378d..cfca46f 100644 (file)
@@ -26,6 +26,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 
@@ -109,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);
@@ -158,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)
@@ -246,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.");
@@ -470,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;
@@ -726,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" };
 
@@ -762,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 9169000..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_NETDB_H
 # include <netdb.h>
 #endif
@@ -56,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.
@@ -374,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);
@@ -414,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))
@@ -496,13 +490,15 @@ static int network_dispatch_notification (notification_t *n) /* {{{ */
 } /* }}} int network_dispatch_notification */
 
 #if HAVE_LIBGCRYPT
-static void network_init_gcrypt (void) /* {{{ */
+static int network_init_gcrypt (void) /* {{{ */
 {
+  gcry_error_t err;
+
   /* http://lists.gnupg.org/pipermail/gcrypt-devel/2003-August/000458.html
    * Because you can't know in a library whether another library has
    * already initialized the library */
   if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P))
-    return;
+    return (0);
 
  /* http://www.gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html
   * To ensure thread-safety, it's important to set GCRYCTL_SET_THREAD_CBS
@@ -512,12 +508,26 @@ static void network_init_gcrypt (void) /* {{{ */
   *
   * tl;dr: keep all these gry_* statements in this exact order please. */
 # if GCRYPT_VERSION_NUMBER < 0x010600
-  gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+  err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+  if (err)
+  {
+    ERROR ("network plugin: gcry_control (GCRYCTL_SET_THREAD_CBS) failed: %s", gcry_strerror (err));
+    return (-1);
+  }
 # endif
+
   gcry_check_version (NULL);
-  gcry_control (GCRYCTL_INIT_SECMEM, 32768);
+
+  err = gcry_control (GCRYCTL_INIT_SECMEM, 32768);
+  if (err)
+  {
+    ERROR ("network plugin: gcry_control (GCRYCTL_INIT_SECMEM) failed: %s", gcry_strerror (err));
+    return (-1);
+  }
+
   gcry_control (GCRYCTL_INITIALIZATION_FINISHED);
-} /* }}} void network_init_gcrypt */
+  return (0);
+} /* }}} int network_init_gcrypt */
 
 static gcry_cipher_hd_t network_get_aes256_cypher (sockent_t *se, /* {{{ */
     const void *iv, size_t iv_size, const char *username)
@@ -595,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;
@@ -607,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)
@@ -618,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);
@@ -638,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)
@@ -696,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);
 
@@ -731,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)
@@ -776,11 +785,10 @@ static int parse_part_values (void **ret_buffer, size_t *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;
@@ -802,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);
 
@@ -817,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)
        {
@@ -826,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])
                {
@@ -873,7 +882,7 @@ static int parse_part_values (void **ret_buffer, size_t *ret_buffer_len,
 
        *ret_buffer     = buffer;
        *ret_buffer_len = buffer_len - pkg_length;
-       *ret_num_values = (size_t) pkg_numval;
+       *ret_num_values = pkg_numval;
        *ret_values     = pkg_values;
 
        sfree (pkg_types);
@@ -933,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)
@@ -1140,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
   {
@@ -1216,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;
@@ -1249,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: "
@@ -1275,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);
   }
@@ -1290,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);
   }
 
@@ -1303,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);
   }
 
@@ -1368,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);
@@ -1384,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)
@@ -1407,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);
@@ -1442,6 +1450,7 @@ static int parse_packet (sockent_t *se, /* {{{ */
                                printed_ignore_warning = 1;
                        }
                        buffer = ((char *) buffer) + pkg_length;
+                       buffer_size -= (size_t) pkg_length;
                        continue;
                }
 #endif /* HAVE_LIBGCRYPT */
@@ -1469,6 +1478,7 @@ static int parse_packet (sockent_t *se, /* {{{ */
                                printed_ignore_warning = 1;
                        }
                        buffer = ((char *) buffer) + pkg_length;
+                       buffer_size -= (size_t) pkg_length;
                        continue;
                }
 #endif /* HAVE_LIBGCRYPT */
@@ -1580,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 "
@@ -1610,6 +1620,7 @@ static int parse_packet (sockent_t *se, /* {{{ */
                        DEBUG ("network plugin: parse_packet: Unknown part"
                                        " type: 0x%04hx", pkg_type);
                        buffer = ((char *) buffer) + pkg_length;
+                       buffer_size -= (size_t) pkg_length;
                }
        } /* while (buffer_size > sizeof (part_header_t)) */
 
@@ -1638,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)
     {
@@ -1765,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,
@@ -2011,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;
@@ -2057,7 +2063,12 @@ static int sockent_init_crypto (sockent_t *se) /* {{{ */
        {
                if (se->data.client.security_level > SECURITY_LEVEL_NONE)
                {
-                       network_init_gcrypt ();
+                       if (network_init_gcrypt () < 0)
+                       {
+                               ERROR ("network plugin: Cannot configure client socket with "
+                                               "security: Failed to initialize crypto library.");
+                               return (-1);
+                       }
 
                        if ((se->data.client.username == NULL)
                                        || (se->data.client.password == NULL))
@@ -2077,7 +2088,12 @@ static int sockent_init_crypto (sockent_t *se) /* {{{ */
        {
                if (se->data.server.security_level > SECURITY_LEVEL_NONE)
                {
-                       network_init_gcrypt ();
+                       if (network_init_gcrypt () < 0)
+                       {
+                               ERROR ("network plugin: Cannot configure server socket with "
+                                               "security: Failed to initialize crypto library.");
+                               return (-1);
+                       }
 
                        if (se->data.server.auth_file == NULL)
                        {
@@ -2130,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;
@@ -2151,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,
@@ -2178,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);
@@ -2195,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;
@@ -2229,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;
@@ -2251,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)
@@ -2273,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;
 
@@ -2312,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 */
@@ -2328,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
@@ -2341,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];
@@ -2440,7 +2446,6 @@ static int network_receive (void) /* {{{ */
        char buffer[network_config_packet_size];
        int  buffer_len;
 
-       size_t i;
        int status = 0;
 
        receive_list_entry_t *private_list_head;
@@ -2466,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;
 
@@ -2494,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)
                        {
@@ -2586,7 +2591,7 @@ static void network_init_buffer (void)
        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;
@@ -2616,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 { \
@@ -2624,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;
@@ -2669,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,
@@ -2698,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;
@@ -2714,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)
@@ -2731,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
@@ -2778,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)
 {
@@ -2890,6 +2892,11 @@ static int network_write (const data_set_t *ds, const value_list_t *vl,
 {
        int status;
 
+       /* listen_loop is set to non-zero in the shutdown callback, which is
+        * guaranteed to be called *after* all the write threads have been shut
+        * down. */
+       assert (listen_loop == 0);
+
        if (!check_send_okay (vl))
        {
 #if COLLECT_DEBUG
@@ -3036,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)
@@ -3058,7 +3064,7 @@ 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;
 
@@ -3122,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)
@@ -3144,7 +3149,7 @@ 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;
 
@@ -3191,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)
@@ -3206,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;
 
@@ -3246,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);
@@ -3319,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 */
@@ -3351,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);
 
@@ -3450,7 +3451,11 @@ static int network_init (void)
        have_init = 1;
 
 #if HAVE_LIBGCRYPT
-       network_init_gcrypt ();
+       if (network_init_gcrypt () < 0)
+       {
+               ERROR ("network plugin: Failed to initialize crypto library.");
+               return (-1);
+       }
 #endif
 
        if (network_config_stats)
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 69ec06d..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);
@@ -195,7 +196,7 @@ static int init (void)
   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;
@@ -224,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;
@@ -263,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 24c66ec..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);
@@ -293,7 +292,6 @@ static int notify_email_notification (const notification_t *n,
 
   /* Initiate a connection to the SMTP server and transfer the message. */
   if (!smtp_start_session (session)) {
-    char buf[MAXSTRING];
     ERROR ("notify_email plugin: SMTP server problem: %s",
         smtp_strerror (smtp_errno (), buf, sizeof buf));
     pthread_mutex_unlock (&session_lock);
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 dbde660..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"
 # include <poll.h>
 #endif
 
+#ifndef STA_NANO
+# define STA_NANO 0x2000
+#endif
+
 static const char *config_keys[] =
 {
        "Host",
@@ -163,16 +168,16 @@ struct resp_pkt
 /* l_fp to double */
 #define M_LFPTOD(r_i, r_uf, d) \
        do { \
-               register int32_t  i; \
-               register uint32_t f; \
+               register int32_t  ri; \
+               register uint32_t rf; \
                \
-               i = (r_i); \
-               f = (r_uf); \
-               if (i < 0) { \
-                       M_NEG(i, f); \
-                       (d) = -((double) i + ((double) f) / 4294967296.0); \
+               ri = (r_i); \
+               rf = (r_uf); \
+               if (ri < 0) { \
+                       M_NEG(ri, rf); \
+                       (d) = -((double) ri + ((double) rf) / 4294967296.0); \
                } else { \
-                       (d) = (double) i + ((double) f) / 4294967296.0; \
+                       (d) = (double) ri + ((double) rf) / 4294967296.0; \
                } \
        } while (0)
 
@@ -247,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 */
@@ -307,7 +312,7 @@ static int ntpd_config (const char *key, const char *value)
        return (0);
 }
 
-static void ntpd_submit (char *type, char *type_inst, double 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;
@@ -328,8 +333,8 @@ static void ntpd_submit (char *type, char *type_inst, double 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,
-               double value)
+static void ntpd_submit_reach (const char *type, const char *type_inst,
+               uint8_t reach, gauge_t value)
 {
        if (!(reach & 1))
                value = NAN;
@@ -339,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)
@@ -360,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)
        {
@@ -380,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,
@@ -418,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;
@@ -427,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);
@@ -441,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;
 
@@ -505,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)))
@@ -663,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)
                {
@@ -673,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
@@ -710,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;
 
@@ -720,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;
@@ -801,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,
@@ -825,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,
@@ -902,8 +896,16 @@ static int ntpd_read (void)
        int                       ps_num;
        int                       ps_size;
 
+       gauge_t offset_loop;
+       gauge_t freq_loop;
+       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. */
+       double scale_loop  = 1e-6;
+       double scale_error = 1e-6;
 
        ik      = NULL;
        ik_num  = 0;
@@ -926,19 +928,25 @@ 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);
+       offset_error = scale_error * ((gauge_t) ntohl (ik->esterror));
 
        DEBUG ("info_kernel:\n"
-                       "  pll offset    = %.8f\n"
-                       "  pll frequency = %.8f\n" /* drift compensation */
-                       "  est error     = %.8f\n",
-                       ntpd_read_fp (ik->offset),
-                       ntpd_read_fp (ik->freq),
-                       ntpd_read_fp (ik->esterror));
+                       "  pll offset    = %.8g\n"
+                       "  pll frequency = %.8g\n" /* drift compensation */
+                       "  est error     = %.8g\n",
+                       offset_loop, freq_loop, offset_error);
 
-       ntpd_submit ("frequency_offset", "loop",  ntpd_read_fp (ik->freq));
-       ntpd_submit ("time_offset",      "loop",  ntpd_read_fp (ik->offset));
-       ntpd_submit ("time_offset",      "error", ntpd_read_fp (ik->esterror));
+       ntpd_submit ("frequency_offset", "loop",  freq_loop);
+       ntpd_submit ("time_offset",      "loop",  offset_loop);
+       ntpd_submit ("time_offset",      "error", offset_error);
 
        free (ik);
        ik = NULL;
@@ -960,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 bbf387f..899ad3e 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -149,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)
@@ -176,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;
@@ -557,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);
@@ -581,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);
@@ -611,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;
@@ -622,7 +617,7 @@ static int olsrd_read_table (FILE *fh, /* {{{ */
     (*callback) (lineno, fields_num, fields);
     lineno++;
   } /* while (fgets) */
-  
+
   return (0);
 } /* }}} int olsrd_read_table */
 
@@ -663,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)
@@ -690,7 +685,7 @@ static int olsrd_read (void) /* {{{ */
   } /* while (fgets) */
 
   fclose (fh);
-  
+
   return (0);
 } /* }}} int olsrd_read */
 
index 58c35e1..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++)
index ffcdb94..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"),
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
+#if defined(__APPLE__)
+#pragma clang diagnostic push
+#pragma clang diagnostic warning "-Wdeprecated-declarations"
+#endif
+
 #include <lber.h>
 #include <ldap.h>
 
@@ -53,6 +59,9 @@ 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)
@@ -74,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)
        {
@@ -91,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);
 
@@ -125,7 +143,7 @@ static int cldap_init_host (cldap_t *st) /* {{{ */
                cred.bv_len = 0;
        }
 
-       rc = ldap_sasl_bind_s (st->ld, st->binddn, LDAP_SASL_SIMPLE, &cred, 
+       rc = ldap_sasl_bind_s (st->ld, st->binddn, LDAP_SASL_SIMPLE, &cred,
                        NULL, NULL, NULL);
        if (rc != LDAP_SUCCESS)
        {
@@ -155,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)
@@ -195,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;
@@ -231,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)
@@ -528,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 */
 
@@ -545,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)
@@ -564,11 +576,11 @@ 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;
 
@@ -612,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'",
@@ -623,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  = */ 0,
-                               /* 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)
@@ -662,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;
 
@@ -693,8 +716,24 @@ 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__)
+#pragma clang diagnostic pop
+#endif
index 663a82d..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,22 +700,32 @@ 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];
+                       ERROR ("openvpn plugin: malloc failed: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       sfree (status_file);
+                       return (1);
+               }
                temp->file = status_file;
                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: malloc failed: %s",
+                       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++;
@@ -764,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 0a98684..48374b6 100644 (file)
  * interface for collectd plugins written in perl.
  */
 
-/* do not automatically get the thread specific perl interpreter */
+/* do not automatically get the thread specific Perl interpreter */
 #define PERL_NO_GET_CONTEXT
 
 #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) */
@@ -123,6 +122,9 @@ static XS (Collectd_call_by_name);
 typedef struct c_ithread_s {
        /* the thread's Perl interpreter */
        PerlInterpreter *interp;
+       _Bool running;  /* thread is inside Perl interpreter */
+       _Bool shutdown;
+       pthread_t pthread;
 
        /* double linked list of threads */
        struct c_ithread_s *prev;
@@ -139,6 +141,7 @@ typedef struct {
 #endif /* COLLECT_DEBUG */
 
        pthread_mutex_t mutex;
+       pthread_mutexattr_t mutexattr;
 } c_ithread_list_t;
 
 /* name / user_data for Perl matches / targets */
@@ -306,7 +309,6 @@ static int hv2data_source (pTHX_ HV *hash, data_source_t *ds)
 static size_t av2value (pTHX_ char *name, AV *array, value_t *value, size_t array_len)
 {
        const data_set_t *ds;
-       size_t i;
 
        if ((NULL == name) || (NULL == array) || (NULL == value) || (array_len == 0))
                return 0;
@@ -326,7 +328,7 @@ static size_t av2value (pTHX_ char *name, AV *array, value_t *value, size_t arra
                                name, array_len, ds->ds_num);
        }
 
-       for (i = 0; i < ds->ds_num; ++i) {
+       for (size_t i = 0; i < ds->ds_num; ++i) {
                SV **tmp = av_fetch (array, i, 0);
 
                if (NULL != tmp) {
@@ -425,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;
@@ -437,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) {
@@ -484,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;
 
@@ -501,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 "
@@ -602,14 +603,12 @@ static int hv2notification (pTHX_ HV *hash, notification_t *n)
 
 static int data_set2av (pTHX_ data_set_t *ds, AV *array)
 {
-       size_t i;
-
        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,
@@ -709,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;
@@ -718,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;
 
@@ -805,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;
 
@@ -823,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) {
@@ -860,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)) {
@@ -981,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;
 
@@ -999,6 +993,32 @@ static int pplugin_dispatch_notification (pTHX_ HV *notif)
 } /* static int pplugin_dispatch_notification (HV *) */
 
 /*
+ * Call perl sub with thread locking flags handled.
+ */
+static int call_pv_locked (pTHX_ const char* sub_name)
+{
+       _Bool old_running;
+       int ret;
+
+       c_ithread_t *t = (c_ithread_t *)pthread_getspecific(perl_thr_key);
+       if (t == NULL) /* thread destroyed */
+               return 0;
+
+       old_running = t->running;
+       t->running = 1;
+
+       if (t->shutdown) {
+               t->running = old_running;
+               return 0;
+       }
+
+       ret = call_pv (sub_name, G_SCALAR);
+
+       t->running = old_running;
+       return ret;
+} /* static int call_pv_locked (pTHX, *sub_name) */
+
+/*
  * Call all working functions of the given type.
  */
 static int pplugin_call_all (pTHX_ int type, ...)
@@ -1127,7 +1147,7 @@ static int pplugin_call_all (pTHX_ int type, ...)
 
        PUTBACK;
 
-       retvals = call_pv ("Collectd::plugin_call_all", G_SCALAR);
+       retvals = call_pv_locked (aTHX_ "Collectd::plugin_call_all");
 
        SPAGAIN;
        if (0 < retvals) {
@@ -1145,7 +1165,7 @@ static int pplugin_call_all (pTHX_ int type, ...)
 } /* static int pplugin_call_all (int, ...) */
 
 /*
- * collectd's perl interpreter based thread implementation.
+ * collectd's Perl interpreter based thread implementation.
  *
  * This has been inspired by Perl's ithreads introduced in version 5.6.0.
  */
@@ -1199,7 +1219,10 @@ static void c_ithread_destructor (void *arg)
 
        /* the ithread no longer exists */
        if (NULL == t)
+       {
+               pthread_mutex_unlock (&perl_threads->mutex);
                return;
+       }
 
        c_ithread_destroy (ithread);
 
@@ -1215,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)
@@ -1245,6 +1268,9 @@ static c_ithread_t *c_ithread_create (PerlInterpreter *base)
                t->prev = perl_threads->tail;
        }
 
+       t->pthread = pthread_self();
+       t->running = 0;
+       t->shutdown = 0;
        perl_threads->tail = t;
 
        pthread_setspecific (perl_thr_key, (const void *)t);
@@ -1365,7 +1391,7 @@ static int fc_call (pTHX_ int type, int cb_type, pfc_user_data_t *data, ...)
 
        PUTBACK;
 
-       retvals = call_pv ("Collectd::fc_call", G_SCALAR);
+       retvals = call_pv_locked (aTHX_ "Collectd::fc_call");
 
        if ((FC_CB_EXEC == cb_type) && (meta != NULL)) {
                assert (pmeta != NULL);
@@ -1425,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);
 
@@ -1640,15 +1666,15 @@ static XS (Collectd_plugin_dispatch_values)
 
        values = ST (/* stack index = */ 0);
 
+       if (NULL == values)
+               XSRETURN_EMPTY;
+
        /* Make sure the argument is a hash reference. */
        if (! (SvROK (values) && (SVt_PVHV == SvTYPE (SvRV (values))))) {
                log_err ("Collectd::plugin_dispatch_values: Invalid values.");
                XSRETURN_EMPTY;
        }
 
-       if (NULL == values)
-               XSRETURN_EMPTY;
-
        ret = pplugin_dispatch_values (aTHX_ (HV *)SvRV (values));
 
        if (0 == ret)
@@ -1905,6 +1931,7 @@ static XS (Collectd_call_by_name)
 
 static int perl_init (void)
 {
+       int status;
        dTHX;
 
        if (NULL == perl_threads)
@@ -1922,7 +1949,19 @@ static int perl_init (void)
 
        log_debug ("perl_init: c_ithread: interp = %p (active threads: %i)",
                        aTHX, perl_threads->number_of_threads);
-       return pplugin_call_all (aTHX_ PLUGIN_INIT);
+
+       /* Lock the base thread to avoid race conditions with c_ithread_create().
+        * See https://github.com/collectd/collectd/issues/9 and
+        *     https://github.com/collectd/collectd/issues/1706 for details.
+       */
+       assert (aTHX == perl_threads->head->interp);
+       pthread_mutex_lock (&perl_threads->mutex);
+
+       status = pplugin_call_all (aTHX_ PLUGIN_INIT);
+
+       pthread_mutex_unlock (&perl_threads->mutex);
+
+       return status;
 } /* static int perl_init (void) */
 
 static int perl_read (void)
@@ -2007,7 +2046,9 @@ static void perl_log (int level, const char *msg,
 
        /* Lock the base thread if this is not called from one of the read threads
         * to avoid race conditions with c_ithread_create(). See
-        * https://github.com/collectd/collectd/issues/9 for details. */
+        * https://github.com/collectd/collectd/issues/9 for details.
+       */
+
        if (aTHX == perl_threads->head->interp)
                pthread_mutex_lock (&perl_threads->mutex);
 
@@ -2061,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;
 
@@ -2073,8 +2113,6 @@ static int perl_shutdown (void)
                return 0;
 
        if (NULL == aTHX) {
-               c_ithread_t *t = NULL;
-
                pthread_mutex_lock (&perl_threads->mutex);
                t = c_ithread_create (perl_threads->head->interp);
                pthread_mutex_unlock (&perl_threads->mutex);
@@ -2098,17 +2136,31 @@ static int perl_shutdown (void)
        t = perl_threads->tail;
 
        while (NULL != t) {
+               struct timespec ts_wait;
                c_ithread_t *thr = t;
 
                /* the pointer has to be advanced before destroying
                 * the thread as this will free the memory */
                t = t->prev;
 
+               thr->shutdown = 1;
+               if (thr->running) {
+                       /* Give some time to thread to exit from Perl interpreter */
+                       WARNING ("perl shutdown: Thread is running inside Perl. Waiting.");
+                       ts_wait.tv_sec = 0;
+                       ts_wait.tv_nsec = 500000;
+                       nanosleep (&ts_wait, NULL);
+               }
+               if (thr->running) {
+                       pthread_kill (thr->pthread, SIGTERM);
+                       ERROR ("perl shutdown: Thread hangs inside Perl. Thread killed.");
+               }
                c_ithread_destroy (thr);
        }
 
        pthread_mutex_unlock (&perl_threads->mutex);
        pthread_mutex_destroy (&perl_threads->mutex);
+       pthread_mutexattr_destroy (&perl_threads->mutexattr);
 
        sfree (perl_threads);
 
@@ -2180,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
@@ -2203,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);
@@ -2228,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 */
@@ -2249,10 +2297,12 @@ 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_mutex_init (&perl_threads->mutex, NULL);
+       pthread_mutexattr_init(&perl_threads->mutexattr);
+       pthread_mutexattr_settype(&perl_threads->mutexattr, PTHREAD_MUTEX_RECURSIVE);
+       pthread_mutex_init (&perl_threads->mutex, &perl_threads->mutexattr);
        /* locking the mutex should not be necessary at this point
         * but let's just do it for the sake of completeness */
        pthread_mutex_lock (&perl_threads->mutex);
@@ -2333,7 +2383,7 @@ static int perl_config_loadplugin (pTHX_ oconfig_item_t *ci)
 
        aTHX = perl_threads->head->interp;
 
-       log_debug ("perl_config: loading perl plugin \"%s\"", value);
+       log_debug ("perl_config: Loading Perl plugin \"%s\"", value);
        load_module (PERL_LOADMOD_NOIMPORT,
                        newSVpv (module_name, strlen (module_name)), Nullsv);
        return 0;
@@ -2379,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) {
@@ -2391,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);
        }
@@ -2416,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) {
@@ -2424,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);
 
@@ -2497,16 +2547,18 @@ 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;
 
                if (NULL != perl_threads)
-                       aTHX = PERL_GET_CONTEXT;
+               {
+                       if ((aTHX = PERL_GET_CONTEXT) == NULL)
+                               return -1;
+               }
 
                if (0 == strcasecmp (c->key, "LoadPlugin"))
                        current_status = perl_config_loadplugin (aTHX_ c);
@@ -2539,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 a2bd549..d7a5a15 100644 (file)
--- a/src/pf.c
+++ b/src/pf.c
@@ -20,6 +20,7 @@
  */
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 
@@ -82,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)
@@ -94,7 +94,6 @@ static int pf_read (void)
                return (-1);
        }
 
-       memset (&state, 0, sizeof (state));
        status = ioctl (fd, DIOCGETSTATUS, &state);
        if (status != 0)
        {
@@ -106,7 +105,6 @@ static int pf_read (void)
        }
 
        close (fd);
-       fd = -1;
 
        if (!state.running)
        {
@@ -114,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 b6e7b15..b9eed68 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
-#include <pthread.h>
 #include <netdb.h>
 #include <poll.h>
 
@@ -171,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)
@@ -183,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;
@@ -191,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 */
@@ -209,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)
   {
@@ -229,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 */
 
@@ -252,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))
@@ -272,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 */
 
@@ -335,6 +333,7 @@ static int pb_add_socket (pinba_socket_t *s, /* {{{ */
     char errbuf[1024];
     ERROR ("pinba plugin: bind(2) failed: %s",
         sstrerror (errno, errbuf, sizeof (errbuf)));
+    close (fd);
     return (0);
   }
 
@@ -351,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)
@@ -380,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)
@@ -410,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 */
 
@@ -506,7 +497,6 @@ static int receive_loop (void) /* {{{ */
   while (!collector_thread_do_shutdown)
   {
     int status;
-    nfds_t i;
 
     if (s->fd_num < 1)
       break;
@@ -529,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))
       {
@@ -569,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;
 
@@ -608,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;
 
@@ -629,7 +616,7 @@ static int plugin_config (oconfig_item_t *ci) /* {{{ */
   }
 
   pthread_mutex_unlock(&stat_nodes_lock);
-  
+
   return (0);
 } /* }}} int pinba_config */
 
@@ -693,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));
@@ -701,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);
@@ -734,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 df2f6da..4932bae 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 */
@@ -73,6 +73,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 +92,7 @@ static const char *config_keys[] =
 #ifdef HAVE_OPING_1_3
   "Device",
 #endif
+  "Size",
   "TTL",
   "Interval",
   "Timeout",
@@ -150,11 +152,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))
   { /* {{{ */
@@ -242,14 +243,13 @@ static int ping_dispatch_all (pingobj_t *pingobj) /* {{{ */
 
 static void *ping_thread (void *arg) /* {{{ */
 {
-  static pingobj_t *pingobj = NULL;
+  pingobj_t *pingobj = NULL;
 
   struct timeval  tv_begin;
   struct timeval  tv_end;
   struct timespec ts_wait;
   struct timespec ts_int;
 
-  hostlist_t *hl;
   int count;
 
   c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
@@ -280,9 +280,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);
@@ -380,7 +383,7 @@ static int start_thread (void) /* {{{ */
   if (ping_thread_loop != 0)
   {
     pthread_mutex_unlock (&ping_lock);
-    return (-1);
+    return (0);
   }
 
   ping_thread_loop = 1;
@@ -394,7 +397,7 @@ static int start_thread (void) /* {{{ */
     pthread_mutex_unlock (&ping_lock);
     return (-1);
   }
-    
+
   pthread_mutex_unlock (&ping_lock);
   return (0);
 } /* }}} int start_thread */
@@ -422,8 +425,10 @@ static int stop_thread (void) /* {{{ */
     status = -1;
   }
 
+  pthread_mutex_lock (&ping_lock);
   memset (&ping_thread_id, 0, sizeof (ping_thread_id));
   ping_thread_error = 0;
+  pthread_mutex_unlock (&ping_lock);
 
   return (status);
 } /* }}} int stop_thread */
@@ -443,10 +448,7 @@ static int ping_init (void) /* {{{ */
         "Will use a timeout of %gs.", ping_timeout);
   }
 
-  if (start_thread () != 0)
-    return (-1);
-
-  return (0);
+  return (start_thread ());
 } /* }}} int ping_init */
 
 static int config_set_string (const char *name, /* {{{ */
@@ -476,7 +478,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];
@@ -537,6 +539,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;
@@ -583,15 +616,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;
@@ -604,7 +635,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;
@@ -688,6 +719,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 bef3490..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;
-       size_t 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;
@@ -663,12 +656,11 @@ static char *values_name_to_sqlarray (const data_set_t *ds,
 {
        char  *str_ptr;
        size_t str_len;
-       size_t 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)
@@ -701,12 +693,11 @@ static char *values_type_to_sqlarray (const data_set_t *ds,
 {
        char  *str_ptr;
        size_t str_len;
-       size_t 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)
@@ -749,12 +740,11 @@ static char *values_to_sqlarray (const data_set_t *ds, const value_list_t *vl,
        size_t str_len;
 
        gauge_t *rates = NULL;
-       size_t 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)
@@ -826,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];
@@ -834,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;
-       size_t i;
 
        if ((ud == NULL) || (ud->data == NULL)) {
                log_err ("c_psql_write: Invalid user data.");
@@ -845,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;
        }
 
@@ -867,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;
         }
@@ -883,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;
 
@@ -971,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
@@ -992,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) {
@@ -1042,17 +1028,18 @@ 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 = (c_psql_user_data_t *) smalloc (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;
+
+               udb_query_set_user_data (q, data);
        }
 
-       tmp = (c_psql_param_t *) realloc (data->params,
-                       (data->params_num + 1) * sizeof (c_psql_param_t));
+       tmp = realloc (data->params, (data->params_num + 1) * sizeof (*data->params));
        if (NULL == tmp) {
                log_err ("Out of memory.");
                return -1;
@@ -1076,8 +1063,6 @@ static int config_query_param_add (udb_query_t *q, oconfig_item_t *ci)
        }
 
        data->params_num++;
-       udb_query_set_user_data (q, data);
-
        return (0);
 } /* config_query_param_add */
 
@@ -1116,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.");
@@ -1144,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)) {
@@ -1152,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.");
@@ -1161,13 +1145,13 @@ static int c_psql_config_writer (oconfig_item_t *ci)
 
        writers = tmp;
        writer  = writers + writers_num;
-       ++writers_num;
+       memset (writer, 0, sizeof (*writer));
 
        writer->name = sstrdup (ci->values[0].value.string);
        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)
@@ -1181,10 +1165,10 @@ static int c_psql_config_writer (oconfig_item_t *ci)
        if (status != 0) {
                sfree (writer->statement);
                sfree (writer->name);
-               sfree (writer);
                return status;
        }
 
+       ++writers_num;
        return 0;
 } /* c_psql_config_writer */
 
@@ -1193,25 +1177,21 @@ static int c_psql_config_database (oconfig_item_t *ci)
        c_psql_database_t *db;
 
        char cb_name[DATA_MAX_NAME_LEN];
-       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"))
@@ -1248,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);
@@ -1265,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))
@@ -1318,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;
 
@@ -1336,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 1050e7f..e215a8c 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -75,9 +76,9 @@ 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;
 
@@ -143,9 +144,9 @@ 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"
+  "latency",
   "packetcache-hit",
   "packetcache-miss",
   "packetcache-size",
@@ -158,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 *
@@ -285,7 +286,7 @@ statname_lookup_t lookup_table[] = /* {{{ */
   {"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;
 
@@ -375,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;
@@ -387,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,
@@ -465,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");
@@ -542,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");
@@ -631,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, '=');
@@ -646,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;
@@ -781,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)
@@ -791,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 "
@@ -799,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)
   {
@@ -808,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)
@@ -831,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))
   {
@@ -840,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)
@@ -881,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;
 
@@ -941,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)
@@ -956,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;
 
@@ -989,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);
@@ -1002,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 d094e73..d34fe40 100644 (file)
@@ -35,6 +35,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 #  undef SAVE_FOB_64
 #endif
 
+# include <sys/user.h>
 # include <dirent.h>
+
+#ifndef MAXCOMLEN
+#  define MAXCOMLEN 16
+#endif
+
 /* #endif KERNEL_SOLARIS */
 
 #else
@@ -262,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.");
@@ -287,7 +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->re);
+                       sfree (new);
                        return;
                }
        }
@@ -313,7 +320,9 @@ static void ps_list_register (const char *name, const char *regexp)
                                        "`ProcessMatch' with the same name. "
                                        "All but the first setting will be "
                                        "ignored.");
+#if HAVE_REGEX_H
                        sfree (new->re);
+#endif
                        sfree (new);
                        return;
                }
@@ -358,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;
 
@@ -380,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)
@@ -425,90 +455,37 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t
                ps->cswitch_vol   += ((pse->cswitch_vol == -1)?0:pse->cswitch_vol);
                ps->cswitch_invol += ((pse->cswitch_invol == -1)?0:pse->cswitch_invol);
 
-               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;
+               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;
@@ -560,9 +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)
@@ -582,6 +563,15 @@ static int ps_config (oconfig_item_t *ci)
                                                c->children_num, c->values[0].value.string);
                        }
 
+#if KERNEL_LINUX || KERNEL_SOLARIS || KERNEL_FREEBSD
+                       if (strlen (c->values[0].value.string) > max_procname_len) {
+                               WARNING ("processes plugin: this platform has a %zu character limit "
+                                               "to process names. The `Process \"%s\"' option will "
+                                               "not work as expected.",
+                                               max_procname_len, c->values[0].value.string);
+                       }
+#endif
+
                        ps_list_register (c->values[0].value.string, NULL);
                }
                else if (strcasecmp (c->key, "ProcessMatch") == 0)
@@ -814,7 +804,7 @@ static void ps_submit_fork_rate (derive_t value)
 
 /* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
 #if KERNEL_LINUX
-static procstat_t *ps_read_tasks_status (int pid, procstat_t *ps)
+static procstat_t *ps_read_tasks_status (long pid, procstat_t *ps)
 {
        char           dirname[64];
        DIR           *dh;
@@ -827,7 +817,7 @@ static procstat_t *ps_read_tasks_status (int pid, procstat_t *ps)
        char *fields[8];
        int numfields;
 
-       ssnprintf (dirname, sizeof (dirname), "/proc/%i/task", pid);
+       ssnprintf (dirname, sizeof (dirname), "/proc/%li/task", pid);
 
        if ((dh = opendir (dirname)) == NULL)
        {
@@ -844,7 +834,7 @@ static procstat_t *ps_read_tasks_status (int pid, procstat_t *ps)
 
                tpid = ent->d_name;
 
-               ssnprintf (filename, sizeof (filename), "/proc/%i/task/%s/status", pid, tpid);
+               ssnprintf (filename, sizeof (filename), "/proc/%li/task/%s/status", pid, tpid);
                if ((fh = fopen (filename, "r")) == NULL)
                {
                        DEBUG ("Failed to open file `%s'", filename);
@@ -885,8 +875,8 @@ static procstat_t *ps_read_tasks_status (int pid, procstat_t *ps)
                if (fclose (fh))
                {
                        char errbuf[1024];
-                               WARNING ("processes: fclose: %s",
-                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       WARNING ("processes: fclose: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
                }
        }
        closedir (dh);
@@ -898,7 +888,7 @@ static procstat_t *ps_read_tasks_status (int pid, procstat_t *ps)
 } /* int *ps_read_tasks_status */
 
 /* Read data from /proc/pid/status */
-static procstat_t *ps_read_status (int pid, procstat_t *ps)
+static procstat_t *ps_read_status (long pid, procstat_t *ps)
 {
        FILE *fh;
        char buffer[1024];
@@ -910,7 +900,7 @@ static procstat_t *ps_read_status (int pid, procstat_t *ps)
        char *fields[8];
        int numfields;
 
-       ssnprintf (filename, sizeof (filename), "/proc/%i/status", pid);
+       ssnprintf (filename, sizeof (filename), "/proc/%li/status", pid);
        if ((fh = fopen (filename, "r")) == NULL)
                return (NULL);
 
@@ -968,7 +958,7 @@ static procstat_t *ps_read_status (int pid, procstat_t *ps)
        return (ps);
 } /* procstat_t *ps_read_vmem */
 
-static procstat_t *ps_read_io (int pid, procstat_t *ps)
+static procstat_t *ps_read_io (long pid, procstat_t *ps)
 {
        FILE *fh;
        char buffer[1024];
@@ -977,7 +967,7 @@ static procstat_t *ps_read_io (int pid, procstat_t *ps)
        char *fields[8];
        int numfields;
 
-       ssnprintf (filename, sizeof (filename), "/proc/%i/io", pid);
+       ssnprintf (filename, sizeof (filename), "/proc/%li/io", pid);
        if ((fh = fopen (filename, "r")) == NULL)
                return (NULL);
 
@@ -1023,7 +1013,7 @@ static procstat_t *ps_read_io (int pid, procstat_t *ps)
        return (ps);
 } /* procstat_t *ps_read_io */
 
-int ps_read_process (int pid, procstat_t *ps, char *state)
+static int ps_read_process (long pid, procstat_t *ps, char *state)
 {
        char  filename[64];
        char  buffer[1024];
@@ -1048,7 +1038,7 @@ int ps_read_process (int pid, procstat_t *ps, char *state)
 
        memset (ps, 0, sizeof (procstat_t));
 
-       ssnprintf (filename, sizeof (filename), "/proc/%i/stat", pid);
+       ssnprintf (filename, sizeof (filename), "/proc/%li/stat", pid);
 
        status = read_file_contents (filename, buffer, sizeof(buffer) - 1);
        if (status <= 0)
@@ -1062,13 +1052,11 @@ int ps_read_process (int 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.
@@ -1093,9 +1081,9 @@ int ps_read_process (int pid, procstat_t *ps, char *state)
        fields_len = strsplit (buffer_ptr, fields, STATIC_ARRAY_SIZE (fields));
        if (fields_len < 22)
        {
-               DEBUG ("processes plugin: ps_read_process (pid = %i):"
+               DEBUG ("processes plugin: ps_read_process (pid = %li):"
                                " `%s' has only %i fields..",
-                               (int) pid, filename, fields_len);
+                               pid, filename, fields_len);
                return (-1);
        }
 
@@ -1114,9 +1102,9 @@ int ps_read_process (int pid, procstat_t *ps, char *state)
                        /* No VMem data */
                        ps->vmem_data = -1;
                        ps->vmem_code = -1;
-                       DEBUG("ps_read_process: did not get vmem data for pid %i",pid);
+                       DEBUG("ps_read_process: did not get vmem data for pid %li", pid);
                }
-               if (ps->num_lwp <= 0)
+               if (ps->num_lwp == 0)
                        ps->num_lwp = 1;
                ps->num_proc = 1;
        }
@@ -1124,7 +1112,7 @@ int ps_read_process (int pid, procstat_t *ps, char *state)
        /* Leave the rest at zero if this is only a zombi */
        if (ps->num_proc == 0)
        {
-               DEBUG ("processes plugin: This is only a zombi: pid = %i; "
+               DEBUG ("processes plugin: This is only a zombie: pid = %li; "
                                "name = %s;", pid, ps->name);
                return (0);
        }
@@ -1164,7 +1152,7 @@ int ps_read_process (int pid, procstat_t *ps, char *state)
                ps->io_syscr = -1;
                ps->io_syscw = -1;
 
-               DEBUG("ps_read_process: not get io data for pid %i",pid);
+               DEBUG("ps_read_process: not get io data for pid %li", pid);
        }
 
        if ( report_ctx_switch )
@@ -1175,7 +1163,7 @@ int ps_read_process (int pid, procstat_t *ps, char *state)
                        ps->cswitch_invol = -1;
 
                        DEBUG("ps_read_tasks_status: not get context "
-                                       "switch data for pid %i",pid);
+                                       "switch data for pid %li", pid);
                }
        }
 
@@ -1183,7 +1171,7 @@ int ps_read_process (int pid, procstat_t *ps, char *state)
        return (0);
 } /* int ps_read_process (...) */
 
-static char *ps_get_cmdline (pid_t pid, char *name, char *buf, size_t buf_len)
+static char *ps_get_cmdline (long pid, char *name, char *buf, size_t buf_len)
 {
        char  *buf_ptr;
        size_t len;
@@ -1196,8 +1184,7 @@ static char *ps_get_cmdline (pid_t pid, char *name, char *buf, size_t buf_len)
        if ((pid < 1) || (NULL == buf) || (buf_len < 2))
                return NULL;
 
-       ssnprintf (file, sizeof (file), "/proc/%u/cmdline",
-                       (unsigned int) pid);
+       ssnprintf (file, sizeof (file), "/proc/%li/cmdline", pid);
 
        errno = 0;
        fd = open (file, O_RDONLY);
@@ -1241,7 +1228,7 @@ static char *ps_get_cmdline (pid_t pid, char *name, char *buf, size_t buf_len)
                buf_ptr += status;
                len     -= status;
 
-               if (len <= 0)
+               if (len == 0)
                        break;
        }
 
@@ -1278,7 +1265,7 @@ static char *ps_get_cmdline (pid_t pid, char *name, char *buf, size_t buf_len)
        return buf;
 } /* char *ps_get_cmdline (...) */
 
-static int read_fork_rate ()
+static int read_fork_rate (void)
 {
        FILE *proc_stat;
        char buffer[1024];
@@ -1325,8 +1312,8 @@ static int read_fork_rate ()
 #endif /*KERNEL_LINUX */
 
 #if KERNEL_SOLARIS
-static const char *ps_get_cmdline (long pid, /* {{{ */
-               char *buffer, size_t buffer_size)
+static char *ps_get_cmdline (long pid, char *name __attribute__((unused)), /* {{{ */
+    char *buffer, size_t buffer_size)
 {
        char path[PATH_MAX];
        psinfo_t info;
@@ -1371,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;
 
@@ -1392,6 +1376,10 @@ static int ps_read_process(long pid, procstat_t *ps, char *state)
                ps->num_proc = 0;
                ps->num_lwp = 0;
                *state = (char) 'Z';
+
+               sfree(myStatus);
+               sfree(myInfo);
+               sfree(myUsage);
                return (0);
        } else {
                ps->num_proc = 1;
@@ -1436,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
@@ -1467,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)
        {
@@ -1542,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;
@@ -1577,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],
@@ -1598,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],
@@ -1673,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,
@@ -1692,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],
@@ -1814,7 +1808,7 @@ static int ps_read (void)
 
        struct dirent *ent;
        DIR           *proc;
-       int            pid;
+       long           pid;
 
        char cmdline[CMDLINE_BUFFER_SIZE];
 
@@ -1823,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 ();
 
@@ -1841,7 +1833,7 @@ static int ps_read (void)
                if (!isdigit (ent->d_name[0]))
                        continue;
 
-               if ((pid = atoi (ent->d_name)) < 1)
+               if ((pid = atol (ent->d_name)) < 1)
                        continue;
 
                status = ps_read_process (pid, &ps, &state);
@@ -1905,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();
@@ -1925,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 ();
@@ -1952,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). */
@@ -2026,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)
@@ -2051,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 */
 
@@ -2069,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 ();
@@ -2096,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). */
@@ -2159,7 +2151,8 @@ static int ps_read (void)
                        pse.io_syscr = -1;
                        pse.io_syscw = -1;
 
-                       pse.cswitch_vol = -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);
@@ -2187,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 */
 
@@ -2203,7 +2196,6 @@ static int ps_read (void)
        pid_t pindex = 0;
        int nprocs;
 
-       procstat_t *ps;
        procstat_entry_t pse;
 
        ps_list_reset ();
@@ -2211,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;
@@ -2308,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) */
 
@@ -2321,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 */
 
@@ -2345,7 +2338,6 @@ static int ps_read (void)
        DIR *proc;
 
        int status;
-       procstat_t *ps_ptr;
        char state;
 
        char cmdline[PRARGSZ];
@@ -2421,7 +2413,7 @@ static int ps_read (void)
 
 
                ps_list_add (ps.name,
-                               ps_get_cmdline (pid, cmdline, sizeof (cmdline)),
+                               ps_get_cmdline (pid, ps.name, cmdline, sizeof (cmdline)),
                                &pse);
        } /* while(readdir) */
        closedir (proc);
@@ -2435,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 210d785..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;
@@ -305,21 +305,34 @@ void cpy_log_exception(const char *context) {
        list = PyObject_CallFunction(cpy_format_exception, "NNN", type, value, traceback); /* New reference. Steals references from "type", "value" and "traceback". */
        if (list)
                l = PyObject_Length(list);
-       for (i = 0; i < l; ++i) {
-               char *s;
+
+       for (int i = 0; i < l; ++i) {
                PyObject *line;
-               
+               char const *msg;
+               char *cpy;
+
                line = PyList_GET_ITEM(list, i); /* Borrowed reference. */
                Py_INCREF(line);
-               s = strdup(cpy_unicode_or_bytes_to_string(&line));
+
+               msg = cpy_unicode_or_bytes_to_string(&line);
                Py_DECREF(line);
-               if (s[strlen(s) - 1] == '\n')
-                       s[strlen(s) - 1] = 0;
+               if (msg == NULL)
+                       continue;
+
+               cpy = strdup(msg);
+               if (cpy == NULL)
+                       continue;
+
+               if (cpy[strlen(cpy) - 1] == '\n')
+                       cpy[strlen(cpy) - 1] = 0;
+
                Py_BEGIN_ALLOW_THREADS
-               ERROR("%s", s);
+               ERROR("%s", cpy);
                Py_END_ALLOW_THREADS
-               free(s);
+
+               free(cpy);
        }
+
        Py_XDECREF(list);
        PyErr_Clear();
 }
@@ -342,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) {
-       size_t i;
        cpy_callback_t *c = data->data;
        PyObject *ret, *list, *temp, *dict = NULL;
        Values *v;
@@ -353,7 +365,7 @@ 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) {
                                PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
                        } else if (ds->ds[i].type == DS_TYPE_GAUGE) {
@@ -377,19 +389,19 @@ static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_li
                }
                dict = PyDict_New();  /* New reference. */
                if (value_list->meta) {
-                       int i, num;
+                       int num;
                        char **table;
                        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))
@@ -527,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);
@@ -538,7 +550,11 @@ 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;
+
        c->name = strdup(buf);
        c->callback = callback;
        c->data = data;
@@ -557,7 +573,6 @@ static PyObject *float_or_none(float number) {
 }
 
 static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
-       size_t i;
        char *name;
        const data_set_t *ds;
        PyObject *list, *tuple;
@@ -570,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)));
@@ -585,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);
@@ -609,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 = NULL;
+       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);
@@ -622,30 +637,35 @@ 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;
+
        c->name = strdup(buf);
        c->callback = callback;
        c->data = data;
        c->next = NULL;
-       user_data = malloc(sizeof(*user_data));
-       user_data->free_func = cpy_destroy_user_data;
-       user_data->data = c;
-       register_function(buf, handler, user_data);
+
+       user_data.free_func = cpy_destroy_user_data;
+       user_data.data = c;
+
+       register_function(buf, handler, &user_data);
        return cpy_string_to_unicode_or_bytes(buf);
 }
 
 static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwds) {
        char buf[512];
        cpy_callback_t *c = NULL;
-       user_data_t *user_data = NULL;
+       user_data_t user_data = { 0 };
        double interval = 0;
        char *name = NULL;
        PyObject *callback = NULL, *data = NULL;
        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);
@@ -654,19 +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;
+
        c->name = strdup(buf);
        c->callback = callback;
        c->data = data;
        c->next = NULL;
-       user_data = malloc(sizeof(*user_data));
-       user_data->free_func = cpy_destroy_user_data;
-       user_data->data = c;
-       plugin_register_complex_read(/* group = */ NULL, buf,
-                       cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), user_data);
+
+       user_data.free_func = cpy_destroy_user_data;
+       user_data.data = c;
+
+       plugin_register_complex_read(/* group = */ "python", buf,
+                       cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), &user_data);
        return cpy_string_to_unicode_or_bytes(buf);
 }
 
@@ -766,7 +791,7 @@ static PyObject *cpy_unregister_generic(cpy_callback_t **list_head, PyObject *ar
        for (tmp = *list_head; tmp; prev = tmp, tmp = tmp->next)
                if (strcmp(name, tmp->name) == 0)
                        break;
-       
+
        Py_DECREF(arg);
        if (tmp == NULL) {
                PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
@@ -869,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");
@@ -888,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");
@@ -952,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.");
@@ -973,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) {
@@ -989,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;
@@ -1018,7 +1028,8 @@ PyMODINIT_FUNC PyInit_collectd(void) {
 }
 #endif
 
-static int cpy_init_python() {
+static int cpy_init_python(void) {
+       PyOS_sighandler_t cur_sig;
        PyObject *sys;
        PyObject *module;
 
@@ -1029,9 +1040,12 @@ static int cpy_init_python() {
 #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;
@@ -1082,8 +1096,8 @@ static int cpy_init_python() {
 }
 
 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
@@ -1094,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;
@@ -1124,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);
@@ -1168,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;
@@ -1189,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 4417601..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);
@@ -504,13 +505,13 @@ static meta_data_t *cpy_build_meta(PyObject *meta) {
 static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
        int ret;
        const data_set_t *ds;
-       size_t size, i;
+       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,
@@ -548,22 +549,25 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
                return NULL;
        }
        value = calloc(size, sizeof(*value));
-       for (i = 0; i < size; ++i) {
+       for (size_t i = 0; i < size; ++i) {
                PyObject *item, *num;
                item = PySequence_Fast_GET_ITEM(values, (int) i); /* Borrowed reference. */
-               if (ds->ds->type == DS_TYPE_COUNTER) {
+               switch (ds->ds[i].type) {
+               case DS_TYPE_COUNTER:
                        num = PyNumber_Long(item); /* New reference. */
                        if (num != NULL) {
                                value[i].counter = PyLong_AsUnsignedLongLong(num);
                                Py_XDECREF(num);
                        }
-               } else if (ds->ds->type == DS_TYPE_GAUGE) {
+                       break;
+               case DS_TYPE_GAUGE:
                        num = PyNumber_Float(item); /* New reference. */
                        if (num != NULL) {
                                value[i].gauge = PyFloat_AsDouble(num);
                                Py_XDECREF(num);
                        }
-               } else if (ds->ds->type == DS_TYPE_DERIVE) {
+                       break;
+               case DS_TYPE_DERIVE:
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
                        num = PyNumber_Long(item); /* New reference. */
@@ -571,7 +575,8 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
                                value[i].derive = PyLong_AsLongLong(num);
                                Py_XDECREF(num);
                        }
-               } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
+                       break;
+               case DS_TYPE_ABSOLUTE:
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
                        num = PyNumber_Long(item); /* New reference. */
@@ -579,9 +584,10 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
                                value[i].absolute = PyLong_AsUnsignedLongLong(num);
                                Py_XDECREF(num);
                        }
-               } else {
+                       break;
+               default:
                        free(value);
-                       PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, value_list.type);
+                       PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds[i].type, value_list.type);
                        return NULL;
                }
                if (PyErr_Occurred() != NULL) {
@@ -613,13 +619,13 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
 static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
        int ret;
        const data_set_t *ds;
-       size_t size, i;
+       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,
@@ -652,22 +658,25 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
                return NULL;
        }
        value = calloc(size, sizeof(*value));
-       for (i = 0; i < size; ++i) {
+       for (size_t i = 0; i < size; ++i) {
                PyObject *item, *num;
                item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
-               if (ds->ds->type == DS_TYPE_COUNTER) {
+               switch (ds->ds[i].type) {
+               case DS_TYPE_COUNTER:
                        num = PyNumber_Long(item); /* New reference. */
                        if (num != NULL) {
                                value[i].counter = PyLong_AsUnsignedLongLong(num);
                                Py_XDECREF(num);
                        }
-               } else if (ds->ds->type == DS_TYPE_GAUGE) {
+                       break;
+               case DS_TYPE_GAUGE:
                        num = PyNumber_Float(item); /* New reference. */
                        if (num != NULL) {
                                value[i].gauge = PyFloat_AsDouble(num);
                                Py_XDECREF(num);
                        }
-               } else if (ds->ds->type == DS_TYPE_DERIVE) {
+                       break;
+               case DS_TYPE_DERIVE:
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
                        num = PyNumber_Long(item); /* New reference. */
@@ -675,7 +684,8 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
                                value[i].derive = PyLong_AsLongLong(num);
                                Py_XDECREF(num);
                        }
-               } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
+                       break;
+               case DS_TYPE_ABSOLUTE:
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
                        num = PyNumber_Long(item); /* New reference. */
@@ -683,9 +693,10 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
                                value[i].absolute = PyLong_AsUnsignedLongLong(num);
                                Py_XDECREF(num);
                        }
-               } else {
+                       break;
+               default:
                        free(value);
-                       PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, value_list.type);
+                       PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds[i].type, value_list.type);
                        return NULL;
                }
                if (PyErr_Occurred() != NULL) {
@@ -697,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)
@@ -718,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)
@@ -727,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);
@@ -844,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();
@@ -879,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,
@@ -927,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;
@@ -940,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;
@@ -961,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 7864ead..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));
@@ -141,10 +140,10 @@ static redis_query_t *redis_config_query (oconfig_item_t *ci) /* {{{ */
      * Default to a gauge type.
      */
     (void)strncpy(rq->type, "gauge", sizeof(rq->type));
-    (void)strncpy(rq->instance, rq->query, sizeof(rq->instance));
+    (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;
 
@@ -294,7 +290,7 @@ static int redis_init (void) /* {{{ */
   return (0);
 } /* }}} int redis_init */
 
-int redis_handle_info (char *node, char const *info_line, char const *type, char const *type_instance, char const *field_name, int ds_type) /* {{{ */
+static int redis_handle_info (char *node, char const *info_line, char const *type, char const *type_instance, char const *field_name, int ds_type) /* {{{ */
 {
   char *str = strstr (info_line, field_name);
   static char buf[MAX_REDIS_VAL_SIZE];
@@ -304,7 +300,7 @@ int redis_handle_info (char *node, char const *info_line, char const *type, char
     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';
 
@@ -321,7 +317,7 @@ int redis_handle_info (char *node, char const *info_line, char const *type, char
 
 } /* }}} int redis_handle_info */
 
-int redis_handle_query (redisContext *rh, redis_node_t *rn, redis_query_t *rq) /* {{{ */
+static int redis_handle_query (redisContext *rh, redis_node_t *rn, redis_query_t *rq) /* {{{ */
 {
     redisReply *rr;
     const data_set_t *ds;
@@ -376,14 +372,11 @@ int redis_handle_query (redisContext *rh, redis_node_t *rn, redis_query_t *rq) /
     redis_submit(rn->name, rq->type, (strlen(rq->instance) >0)?rq->instance:NULL, val);
     freeReplyObject (rr);
     return 0;
-} /* }}} int redis_handle_info */
+} /* }}} int redis_handle_query */
 
 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;
@@ -399,25 +392,27 @@ static int redis_read (void) /* {{{ */
 
     if (strlen (rn->passwd) > 0)
     {
-      DEBUG ("redis plugin: authenticanting node `%s' passwd(%s).", rn->name, rn->passwd);
-      rr = redisCommand (rh, "AUTH %s", rn->passwd);
+      DEBUG ("redis plugin: authenticating node `%s' passwd(%s).", rn->name, rn->passwd);
 
-      if (rr == NULL || rr->type != REDIS_REPLY_STATUS)
+      if ((rr = redisCommand (rh, "AUTH %s", rn->passwd)) == NULL)
       {
         WARNING ("redis plugin: unable to authenticate on node `%s'.", rn->name);
-        if (rr != NULL)
-          freeReplyObject (rr);
+        goto redis_fail;
+      }
 
-        redisFree (rh);
-        continue;
+      if (rr->type != REDIS_REPLY_STATUS)
+      {
+        WARNING ("redis plugin: invalid authentication on node `%s'.", rn->name);
+        goto redis_fail;
       }
+
+      freeReplyObject (rr);
     }
 
     if ((rr = redisCommand(rh, "INFO")) == NULL)
     {
-      WARNING ("redis plugin: unable to connect to node `%s'.", rn->name);
-      redisFree (rh);
-      continue;
+      WARNING ("redis plugin: unable to get info from node `%s'.", rn->name);
+      goto redis_fail;
     }
 
     redis_handle_info (rn->name, rr->str, "uptime", NULL, "uptime_in_seconds", DS_TYPE_GAUGE);
@@ -429,16 +424,23 @@ 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, "expired_keys", NULL, "expired_keys", DS_TYPE_GAUGE);
+    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);
 
-    freeReplyObject (rr);
-
-    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:
+    if (rr != NULL)
+      freeReplyObject (rr);
     redisFree (rh);
   }
 
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 667c2fa..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;
 
@@ -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 5d98de8..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;
-  size_t 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 764d6d6..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;
-       size_t 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. */
@@ -733,7 +727,10 @@ static int rrd_cache_insert (const char *filename,
        {
                rc = malloc (sizeof (*rc));
                if (rc == NULL)
+               {
+                       pthread_mutex_unlock (&cache_lock);
                        return (-1);
+               }
                rc->values_num = 0;
                rc->values = NULL;
                rc->first_value = 0;
@@ -753,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)
        {
@@ -857,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;
@@ -868,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);
@@ -1005,23 +1001,36 @@ static int rrd_config (const char *key, const char *value)
        }
        else if (strcasecmp ("DataDir", key) == 0)
        {
-               if (datadir != NULL)
-                       free (datadir);
-               datadir = strdup (value);
+               char *tmp;
+               size_t len;
+
+               tmp = strdup (value);
+               if (tmp == NULL)
+               {
+                       ERROR ("rrdtool plugin: strdup failed.");
+                       return (1);
+               }
+
+               len = strlen (tmp);
+               while ((len > 0) && (tmp[len - 1] == '/'))
+               {
+                       len--;
+                       tmp[len] = 0;
+               }
+
+               if (len == 0)
+               {
+                       ERROR ("rrdtool plugin: Invalid \"DataDir\" option.");
+                       sfree (tmp);
+                       return (1);
+               }
+
                if (datadir != NULL)
                {
-                       int len = strlen (datadir);
-                       while ((len > 0) && (datadir[len - 1] == '/'))
-                       {
-                               len--;
-                               datadir[len] = '\0';
-                       }
-                       if (len <= 0)
-                       {
-                               free (datadir);
-                               datadir = NULL;
-                       }
+                       sfree (datadir);
                }
+
+               datadir = tmp;
        }
        else if (strcasecmp ("StepSize", key) == 0)
        {
@@ -1071,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)
@@ -1204,6 +1213,7 @@ static int rrd_init (void)
        cache = c_avl_create ((int (*) (const void *, const void *)) strcmp);
        if (cache == NULL)
        {
+               pthread_mutex_unlock (&cache_lock);
                ERROR ("rrdtool plugin: c_avl_create failed.");
                return (-1);
        }
index f5b09bd..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);
@@ -265,9 +272,8 @@ static int sensors_config (const char *key, const char *value)
        return (0);
 }
 
-void sensors_free_features (void)
+static void sensors_free_features (void)
 {
-       featurelist_t *thisft;
        featurelist_t *nextft;
 
        if (first_feature == NULL)
@@ -275,7 +281,7 @@ 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 0878d3c..cf7ad2a 100644 (file)
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -73,7 +74,6 @@ static int serial_read (void)
 
                char *fields[16];
                int numfields;
-               int i;
 
                numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
                if (numfields < 6)
@@ -90,7 +90,7 @@ static int serial_read (void)
                        continue;
                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)
index eecb54c..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);
@@ -360,10 +355,13 @@ static int sigrok_init(void)
                return -1;
        }
 
-       if ((status = plugin_thread_create(&sr_thread, NULL, sigrok_read_thread,
-                       NULL)) != 0) {
+       status = plugin_thread_create(&sr_thread, NULL, sigrok_read_thread,
+                       NULL);
+       if (status != 0)
+       {
+               char errbuf[1024];
                ERROR("sigrok plugin: Failed to create thread: %s.",
-                               strerror(status));
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
                return -1;
        }
        sr_thread_running = TRUE;
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 6a03a19..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>
 
@@ -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 = (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;
 
@@ -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,27 +631,28 @@ 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;
+  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);
 
   status = cf_util_get_string(ci, &hd->name);
   if (status != 0)
+  {
+    sfree (hd);
     return status;
+  }
 
   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;
@@ -773,7 +765,6 @@ 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;
 
@@ -791,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)
@@ -943,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);
 
@@ -1057,14 +1045,13 @@ static int csnmp_strvbcopy_hexstring (char *dst, /* {{{ */
 {
   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;
 
@@ -1097,12 +1084,19 @@ static int csnmp_strvbcopy (char *dst, /* {{{ */
 {
   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;
@@ -1113,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)
@@ -1138,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 */
@@ -1151,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);
@@ -1168,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)
@@ -1270,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;
@@ -1369,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;
@@ -1387,7 +1382,7 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
 static int csnmp_read_table (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;
@@ -1596,14 +1591,13 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
           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);
@@ -1666,7 +1660,7 @@ 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;
@@ -1699,7 +1693,7 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
   }
 
   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++)
@@ -1728,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))
@@ -1741,9 +1734,9 @@ 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);
     csnmp_host_close_session (host);
 
     return (-1);
@@ -1766,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);
@@ -1780,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;
@@ -1791,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);
 
@@ -1813,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 3ec1d9e..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 <netdb.h>
 #include <poll.h>
@@ -64,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;
@@ -88,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;
@@ -125,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;
@@ -261,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 */
@@ -355,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)
   {
@@ -500,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)
@@ -525,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;
@@ -561,6 +558,7 @@ static int statsd_network_init (struct pollfd **ret_fds, /* {{{ */
     if (tmp == NULL)
     {
       ERROR ("statsd plugin: realloc failed.");
+      close (fd);
       continue;
     }
     fds = tmp;
@@ -591,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)
@@ -615,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;
@@ -626,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);
 
@@ -666,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;
 
@@ -684,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)
@@ -706,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)
   {
@@ -754,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;
@@ -780,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. */
@@ -820,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]);
@@ -851,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);
 
-      sstrncpy(vl.type, "gauge", sizeof (vl.type));
-      values[0].gauge = (gauge_t) metric->value;
+      /* 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;
+
+    values[0].derive = metric->counter;
   }
 
   return (plugin_dispatch_values (&vl));
@@ -875,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);
 
@@ -910,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;
 
@@ -939,8 +944,6 @@ static int statsd_shutdown (void) /* {{{ */
   void *key;
   void *value;
 
-  pthread_mutex_lock (&metrics_lock);
-
   if (network_thread_running)
   {
     network_thread_shutdown = 1;
@@ -949,10 +952,12 @@ static int statsd_shutdown (void) /* {{{ */
   }
   network_thread_running = 0;
 
+  pthread_mutex_lock (&metrics_lock);
+
   while (c_avl_pick (metrics_tree, &key, &value) == 0)
   {
     sfree (key);
-    sfree (value);
+    statsd_metric_free (value);
   }
   c_avl_destroy (metrics_tree);
   metrics_tree = NULL;
index cfde4ea..15eca9a 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;
@@ -521,10 +523,10 @@ static int swap_read (void) /* {{{ */
                 return (0);
 
        /* Allocate and initialize the swaptbl_t structure */
-        s = (swaptbl_t *) smalloc (swap_num * sizeof (swapent_t) + sizeof (struct swaptable));
+        s = malloc (swap_num * sizeof (swapent_t) + sizeof (struct swaptable));
         if (s == NULL)
         {
-                ERROR ("swap plugin: smalloc failed.");
+                ERROR ("swap plugin: malloc failed.");
                 return (-1);
         }
 
@@ -534,11 +536,11 @@ static int swap_read (void) /* {{{ */
        s_paths = calloc (swap_num, PATH_MAX);
        if (s_paths == NULL)
        {
-               ERROR ("swap plugin: malloc failed.");
+               ERROR ("swap plugin: calloc failed.");
                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;
@@ -757,14 +758,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 b0bc95f..ba65f41 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include "collectd.h"
+
 #include "common.h"
 
 #include "configfile.h"
@@ -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;
@@ -144,7 +143,6 @@ static int tbl_config_append_array_i (char *name, size_t **var, size_t *len,
 {
        size_t *tmp;
        size_t num;
-       size_t i;
 
        if (1 > ci->values_num) {
                log_err ("\"%s\" expects at least one argument.", name);
@@ -152,7 +150,7 @@ static int tbl_config_append_array_i (char *name, size_t **var, size_t *len,
        }
 
        num = (size_t) ci->values_num;
-       for (i = 0; i < num; ++i) {
+       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;
@@ -168,7 +166,7 @@ static int tbl_config_append_array_i (char *name, size_t **var, size_t *len,
        }
        *var = tmp;
 
-       for (i = 0; i < num; ++i) {
+       for (size_t i = 0; i < num; ++i) {
                (*var)[*len] = (size_t) ci->values[i].value.number;
                (*len)++;
        }
@@ -181,16 +179,15 @@ static int tbl_config_result (tbl_t *tbl, oconfig_item_t *ci)
        tbl_result_t *res;
 
        int status = 0;
-       int 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 (NULL == tbl) {
+       if (res == NULL) {
                char errbuf[1024];
                log_err ("realloc failed: %s.",
                                sstrerror (errno, errbuf, sizeof (errbuf)));
@@ -203,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"))
@@ -246,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)) {
@@ -254,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.",
@@ -268,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 < ((size_t) 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"))
@@ -306,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];
        }
@@ -323,9 +318,7 @@ static int tbl_config_table (oconfig_item_t *ci)
 
 static int tbl_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 *c = ci->children + i;
 
                if (0 == strcasecmp (c->key, "Table"))
@@ -342,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);
@@ -367,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 */
@@ -380,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);
@@ -412,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]];
                }
@@ -444,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))) {
@@ -458,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;
@@ -490,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;
                }
        }
@@ -518,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)) {
@@ -541,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 751243b..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))
   {
@@ -236,11 +233,11 @@ static int ctail_config_add_file (oconfig_item_t *ci)
   if (tm == NULL)
   {
     ERROR ("tail plugin: tail_match_create (%s) failed.",
-       ci->values[0].value.string);
+        ci->values[0].value.string);
     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;
@@ -253,7 +250,7 @@ static int ctail_config_add_file (oconfig_item_t *ci)
     {
       status = ctail_config_add_match (tm, plugin_instance, option, interval);
       if (status == 0)
-       num_matches++;
+        num_matches++;
       /* Be mild with failed matches.. */
       status = 0;
     }
@@ -266,10 +263,12 @@ static int ctail_config_add_file (oconfig_item_t *ci)
       break;
   } /* for (i = 0; i < ci->children_num; i++) */
 
+  sfree (plugin_instance);
+
   if (num_matches == 0)
   {
     ERROR ("tail plugin: No (valid) matches found for file `%s'.",
-       ci->values[0].value.string);
+        ci->values[0].value.string);
     tail_match_destroy (tm);
     return (-1);
   }
@@ -277,8 +276,8 @@ static int ctail_config_add_file (oconfig_item_t *ci)
   {
     cu_tail_match_t **temp;
 
-    temp = (cu_tail_match_t **) realloc (tail_match_list,
-       sizeof (cu_tail_match_t *) * (tail_match_list_num + 1));
+    temp = realloc (tail_match_list,
+        sizeof (cu_tail_match_t *) * (tail_match_list_num + 1));
     if (temp == NULL)
     {
       ERROR ("tail plugin: realloc failed.");
@@ -297,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;
 
@@ -331,8 +328,7 @@ static int ctail_read (user_data_t *ud)
 static int ctail_init (void)
 {
   char str[255];
-  user_data_t ud;
-  size_t i;
+  user_data_t ud = { 0 };
 
   if (tail_match_list_num == 0)
   {
@@ -340,9 +336,7 @@ 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);
@@ -354,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 bb9b58a..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"
@@ -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);
@@ -288,12 +289,10 @@ static int tcsv_config_get_index(oconfig_item_t *ci, ssize_t *ret_index) {
 static int tcsv_config_add_metric(oconfig_item_t *ci){
     metric_definition_t *md;
     int status;
-    int i;
 
-    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;
@@ -307,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)
@@ -377,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.");
@@ -390,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) {
@@ -420,16 +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;
+    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;
@@ -445,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;
 
@@ -486,7 +482,6 @@ 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;
     status = plugin_register_complex_read(NULL, cb_name, tcsv_read, id->interval, &cb_data);
@@ -502,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);
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 14fb541..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;
 
-  size_t 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 bd8f9e5..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;
@@ -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 6169fa0..22af4e3 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "filter_chain.h"
 
@@ -302,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)
@@ -313,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;
@@ -328,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)
        {
@@ -338,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;
 
@@ -369,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);
        }
@@ -385,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;
 
@@ -447,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;
-       size_t i;
 
        if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
                return (-EINVAL);
@@ -459,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) {
@@ -491,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 8f40be6..e74e4bc 100644 (file)
@@ -58,6 +58,7 @@
  */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -283,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,
@@ -304,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);
 
@@ -314,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];
 
@@ -329,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];
 
@@ -344,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];
 
@@ -362,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 */
 
@@ -385,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;
@@ -486,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];
 
@@ -504,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)
   {
@@ -832,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.");
@@ -1017,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;
@@ -1059,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 56e8d14..a1cde32 100644 (file)
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -83,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;
@@ -140,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 */
 
@@ -199,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;
 
@@ -217,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,
@@ -236,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,
@@ -257,6 +254,7 @@ static int tss2_get_socket (FILE **ret_read_fh, FILE **ret_write_fh)
                        WARNING ("teamspeak2 plugin: connect failed: %s",
                                        sstrerror (errno, errbuf, sizeof (errbuf)));
                        close (sd);
+                       sd = -1;
                        continue;
                }
 
@@ -351,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
@@ -434,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)
                {
@@ -445,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)
                {
@@ -461,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)
                        {
@@ -488,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 */
@@ -511,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;
@@ -527,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
@@ -558,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)
@@ -723,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;
 
@@ -753,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);
@@ -773,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;
 
@@ -789,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)
@@ -803,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)
@@ -832,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 e76b3c9..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);
@@ -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 0c415e4..1bcc276 100644 (file)
@@ -24,6 +24,9 @@
  *   Florian octo Forster <octo at collectd.org>
  */
 
+#ifndef TESTING_H
+#define TESTING_H 1
+
 #include <inttypes.h>
 
 static int fail_count__ = 0;
@@ -33,7 +36,7 @@ static int check_count__ = 0;
 # define DBL_PRECISION 1e-12
 #endif
 
-#define DEF_TEST(func) static int test_##func ()
+#define DEF_TEST(func) static int test_##func (void)
 
 #define RUN_TEST(func) do { \
   int status; \
@@ -53,12 +56,14 @@ static int check_count__ = 0;
 #define OK(cond) OK1(cond, #cond)
 
 #define EXPECT_EQ_STR(expect, actual) do { \
-  if (strcmp (expect, actual) != 0) { \
+  /* 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, actual, expect); \
+        ++check_count__, #actual, got__, expect); \
     return (-1); \
   } \
-  printf ("ok %i - %s = \"%s\"\n", ++check_count__, #actual, actual); \
+  printf ("ok %i - %s = \"%s\"\n", ++check_count__, #actual, got__); \
 } while (0)
 
 #define EXPECT_EQ_INT(expect, actual) do { \
@@ -109,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 38c7efb..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;
-      size_t 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;
-  size_t 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;
 
@@ -868,16 +860,14 @@ static int ut_missing (const value_list_t *vl,
   return (0);
 } /* }}} int ut_missing */
 
-int ut_config (oconfig_item_t *ci)
+static int ut_config (oconfig_item_t *ci)
 { /* {{{ */
-  int i;
   int status = 0;
-
-  threshold_t th;
+  int old_size = c_avl_size (threshold_tree);
 
   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.");
@@ -885,17 +875,15 @@ 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;
 
@@ -915,7 +903,9 @@ int ut_config (oconfig_item_t *ci)
       break;
   }
 
-  if (c_avl_size (threshold_tree) > 0) {
+  /* register callbacks if this is the first time we see a valid config */
+  if ((old_size == 0) && (c_avl_size (threshold_tree) > 0))
+  {
     plugin_register_missing ("threshold", ut_missing,
         /* user data = */ NULL);
     plugin_register_write ("threshold", ut_check_threshold,
index 7fa621b..7c6d912 100644 (file)
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "utils_cache.h"
@@ -78,7 +79,7 @@ static int tt_config (const char *key, const char *value)
        return (0);
 }
 
-static void printerr()
+static void printerr (void)
 {
        int ecode = tcrdbecode(rdb);
        ERROR ("tokyotyrant plugin: error: %d, %s",
@@ -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 42fed52..913511f 100644 (file)
@@ -36,6 +36,7 @@
 #define _GNU_SOURCE
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_time.h"
@@ -457,7 +458,7 @@ delta_core(struct core_data *delta, const struct core_data *new, const struct co
  */
 static inline int __attribute__((warn_unused_result))
 delta_thread(struct thread_data *delta, const struct thread_data *new, const struct thread_data *old,
-       const struct core_data *core_delta)
+       const struct core_data *cdelta)
 {
        delta->tsc = new->tsc - old->tsc;
 
@@ -491,12 +492,12 @@ delta_thread(struct thread_data *delta, const struct thread_data *new, const str
         * it is possible for mperf's non-halted cycles + idle states
         * to exceed TSC's all cycles: show c1 = 0% in that case.
         */
-       if ((delta->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > delta->tsc)
+       if ((delta->mperf + cdelta->c3 + cdelta->c6 + cdelta->c7) > delta->tsc)
                delta->c1 = 0;
        else {
                /* normal case, derive c1 */
-               delta->c1 = delta->tsc - delta->mperf - core_delta->c3
-                       - core_delta->c6 - core_delta->c7;
+               delta->c1 = delta->tsc - delta->mperf - cdelta->c3
+                       - cdelta->c6 - cdelta->c7;
        }
 
        if (delta->mperf == 0) {
@@ -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;
@@ -805,7 +804,7 @@ guess:
  * Identify the functionality of the CPU
  */
 static int __attribute__((warn_unused_result))
-probe_cpu()
+probe_cpu(void)
 {
        unsigned int eax, ebx, ecx, edx, max_level;
        unsigned int fms, family, model;
@@ -1037,6 +1036,7 @@ parse_int_file(const char *fmt, ...)
        }
        if (fscanf(filep, "%d", &value) != 1) {
                ERROR("turbostat plugin: Failed to parse number from '%s'", path);
+               fclose(filep);
                return -1;
        }
        fclose(filep);
@@ -1146,9 +1146,8 @@ allocate_cpu_set(cpu_set_t ** set, size_t * size) {
  * Build a local representation of the cpu distribution
  */
 static int __attribute__((warn_unused_result))
-topology_probe()
+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;
@@ -1185,7 +1184,7 @@ topology_probe()
         * 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];
 
@@ -1250,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)
@@ -1270,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;
@@ -1320,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);
@@ -1341,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;
@@ -1515,7 +1511,7 @@ check_permissions(void)
        }
 
        if (euidaccess("/dev/cpu/0/msr", R_OK)) {
-               WARNING("turbostat plugin: Collectd cannot open"
+               WARNING("turbostat plugin: Collectd cannot open "
                        "/dev/cpu/0/msr. If you don't want to run collectd as "
                        "root, you need to change the ownership (chown) and "
                        "permissions on /dev/cpu/*/msr to allow such access");
@@ -1538,8 +1534,8 @@ turbostat_init(void)
        int ret;
 
        if (stat("/dev/cpu/0/msr", &sb)) {
-               ERROR("turbostat plugin: Initialization failed: /dev/cpu/0/msr"
-                     " does not exist while the CPU supports MSR. You may be "
+               ERROR("turbostat plugin: Initialization failed: /dev/cpu/0/msr "
+                     "does not exist while the CPU supports MSR. You may be "
                      "missing the corresponding kernel module, please try '# "
                      "modprobe msr'");
                return -1;
index e722ce6..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: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
-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:GAUGE: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
-satellites             value:GAUGE:0:U
-dilution_of_precision  value:GAUGE:0: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 e6c75a6..1faeff9 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -36,9 +37,6 @@
 #include "utils_cmd_putval.h"
 #include "utils_cmd_putnotif.h"
 
-/* Folks without pthread will need to disable this plugin. */
-#include <pthread.h>
-
 #include <sys/stat.h>
 #include <sys/un.h>
 
@@ -79,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);
@@ -91,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));
@@ -127,7 +124,16 @@ static int us_open_socket (void)
                return (-1);
        }
 
-       chmod (sa.sun_path, sock_perms);
+       status = chmod (sa.sun_path, sock_perms);
+       if (status == -1)
+       {
+               char errbuf[1024];
+               ERROR ("unixsock plugin: chmod failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               close (sock_fd);
+               sock_fd = -1;
+               return (-1);
+       }
 
        status = listen (sock_fd, 8);
        if (status != 0)
@@ -142,7 +148,7 @@ static int us_open_socket (void)
 
        do
        {
-               char *grpname;
+               const char *grpname;
                struct group *g;
                struct group sg;
                char grbuf[2048];
@@ -359,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 8b34a75..1876150 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_parse_option.h"
+#include "utils_cmd_flush.h"
 
 int handle_flush (FILE *fh, char *buffer)
 {
@@ -42,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) { \
@@ -121,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;
-               size_t 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 8cbb9b2..cd88760 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
 #include "utils_cache.h"
 #include "utils_parse_option.h"
+#include "utils_cmd_getval.h"
 
 #define print_to_socket(fh, ...) \
   do { \
@@ -59,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);
@@ -144,7 +145,7 @@ int handle_getval (FILE *fh, char *buffer)
 
   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 530d153..669ef83 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
 #include "utils_parse_option.h"
+#include "utils_cmd_putnotif.h"
 
 #define print_to_socket(fh, ...) \
   do { \
@@ -118,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))
@@ -142,8 +144,6 @@ int handle_putnotif (FILE *fh, char *buffer)
     return (-1);
   }
 
-  memset (&n, '\0', sizeof (n));
-
   status = 0;
   while (*buffer != 0)
   {
index 7b0258c..bf3e2b6 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
 #include "utils_parse_option.h"
+#include "utils_cmd_putval.h"
 
 #define print_to_socket(fh, ...) \
     do { \
@@ -162,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");
@@ -217,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 d2b8117..8eae6b8 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,7 +199,6 @@ 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);
@@ -204,15 +206,15 @@ static int udb_result_submit (udb_result_t *r, /* {{{ */
   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 +223,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 +233,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;
@@ -246,15 +256,27 @@ static int udb_result_submit (udb_result_t *r, /* {{{ */
   {
     if (r->instance_prefix == NULL)
     {
-      strjoin (vl.type_instance, sizeof (vl.type_instance),
+      int status = strjoin (vl.type_instance, sizeof (vl.type_instance),
           r_area->instances_buffer, r->instances_num, "-");
+      if (status != 0)
+      {
+        ERROR ("udb_result_submit: creating type_instance failed with status %d.",
+            status);
+        return (status);
+      }
     }
     else
     {
       char tmp[DATA_MAX_NAME_LEN];
 
-      strjoin (tmp, sizeof (tmp), r_area->instances_buffer,
+      int status = strjoin (tmp, sizeof (tmp), r_area->instances_buffer,
           r->instances_num, "-");
+      if (status != 0)
+      {
+        ERROR ("udb_result_submit: creating type_instance failed with status %d.",
+            status);
+        return (status);
+      }
       tmp[sizeof (tmp) - 1] = 0;
 
       snprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s",
@@ -274,7 +296,7 @@ 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],
           r_area->metadata_buffer[i]);
@@ -320,19 +342,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 */
 
@@ -340,8 +363,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);
 
@@ -390,7 +411,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);
     }
 
@@ -398,7 +419,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) */
@@ -407,7 +428,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);
   }
 
@@ -415,7 +436,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);
   }
 
@@ -423,7 +444,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);
   }
 
@@ -431,14 +452,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;
 
@@ -460,8 +481,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;
 
@@ -484,7 +506,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;
 
@@ -512,22 +534,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);
 
@@ -541,7 +562,6 @@ static int udb_result_create (const char *query_name, /* {{{ */
 {
   udb_result_t *r;
   int status;
-  int i;
 
   if (ci->values_num != 0)
   {
@@ -550,13 +570,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;
@@ -566,7 +585,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;
 
@@ -638,13 +657,14 @@ static int udb_result_create (const char *query_name, /* {{{ */
 /*
  * Query private functions
  */
-void udb_query_free_one (udb_query_t *q) /* {{{ */
+static void udb_query_free_one (udb_query_t *q) /* {{{ */
 {
   if (q == NULL)
     return;
 
   sfree (q->name);
   sfree (q->statement);
+  sfree (q->plugin_instance_from);
 
   udb_result_free (q->results);
 
@@ -663,7 +683,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);
@@ -678,15 +697,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)
@@ -696,7 +717,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;
 
@@ -708,6 +729,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)
@@ -752,7 +775,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)
     {
@@ -781,12 +804,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);
@@ -796,7 +817,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)
@@ -808,7 +828,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;
@@ -817,7 +837,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)
     {
@@ -969,9 +989,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;",
@@ -1032,9 +1050,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;",
@@ -1043,6 +1059,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)
   {
@@ -1072,17 +1113,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;
@@ -1098,8 +1138,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 4c763a1..f38a7bd 100644 (file)
@@ -37,6 +37,7 @@
 #define _BSD_SOURCE
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 
@@ -62,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
@@ -159,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;
@@ -200,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);
@@ -215,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");
@@ -231,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;
 
@@ -239,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)
        {
@@ -289,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;
@@ -298,7 +289,7 @@ 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) >= ((off_t) sz))
@@ -330,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;
@@ -421,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);
 
@@ -764,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");
@@ -841,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)
@@ -852,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)
@@ -913,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 70b8908..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"
@@ -41,7 +40,7 @@ struct fbhash_s
   c_avl_tree_t *tree;
 };
 
-/* 
+/*
  * Private functions
  */
 static void fbh_free_tree (c_avl_tree_t *tree) /* {{{ */
@@ -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);
@@ -198,7 +192,7 @@ static int fbh_check_file (fbhash_t *h) /* {{{ */
   return (status);
 } /* }}} int fbh_check_file */
 
-/* 
+/*
  * Public functions
  */
 fbhash_t *fbh_create (const char *file) /* {{{ */
@@ -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)
@@ -228,6 +221,7 @@ fbhash_t *fbh_create (const char *file) /* {{{ */
   if (status != 0)
   {
     fbh_destroy (h);
+    free (h);
     return (NULL);
   }
 
index eb5b4b3..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;
-    size_t 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 122c7f8..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;
-  size_t 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;
-  size_t 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;
-  size_t 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 (",");
@@ -230,20 +238,14 @@ static int dsnames_to_json (char *buffer, size_t buffer_size, /* {{{ */
   return (0);
 } /* }}} int dsnames_to_json */
 
-static int meta_data_to_json (char *buffer, size_t buffer_size, /* {{{ */
-    meta_data_t *meta)
+static int meta_data_keys_to_json (char *buffer, size_t buffer_size, /* {{{ */
+    meta_data_t *meta, char **keys, size_t keys_num)
 {
   size_t offset = 0;
-  char **keys = NULL;
-  int keys_num;
   int status;
-  int i;
 
   buffer[0] = 0;
 
-  if (meta == NULL)
-    return (EINVAL);
-
 #define BUFFER_ADD(...) do { \
   status = ssnprintf (buffer + offset, buffer_size - offset, \
       __VA_ARGS__); \
@@ -255,14 +257,7 @@ static int meta_data_to_json (char *buffer, size_t buffer_size, /* {{{ */
     offset += ((size_t) status); \
 } while (0)
 
-  keys_num = meta_data_toc (meta, &keys);
-  if (keys_num == 0)
-  {
-    sfree (keys);
-    return (0);
-  }
-
-  for (i = 0; i < keys_num; ++i)
+  for (size_t i = 0; i < keys_num; ++i)
   {
     int type;
     char *key = keys[i];
@@ -274,8 +269,12 @@ static int meta_data_to_json (char *buffer, size_t buffer_size, /* {{{ */
       if (meta_data_get_string (meta, key, &value) == 0)
       {
         char temp[512] = "";
-        json_escape_string (temp, sizeof (temp), value);
+
+        status = json_escape_string (temp, sizeof (temp), value);
         sfree (value);
+        if (status != 0)
+          return status;
+
         BUFFER_ADD (",\"%s\":%s", key, temp);
       }
     }
@@ -303,12 +302,9 @@ static int meta_data_to_json (char *buffer, size_t buffer_size, /* {{{ */
       if (meta_data_get_boolean (meta, key, &value) == 0)
         BUFFER_ADD (",\"%s\":%s", key, value ? "true" : "false");
     }
-
-    free (key);
   } /* for (keys) */
-  free (keys);
 
-  if (offset <= 0)
+  if (offset == 0)
     return (ENOENT);
 
   buffer[0] = '{'; /* replace leading ',' */
@@ -317,6 +313,30 @@ static int meta_data_to_json (char *buffer, size_t buffer_size, /* {{{ */
 #undef BUFFER_ADD
 
   return (0);
+} /* }}} int meta_data_keys_to_json */
+
+static int meta_data_to_json (char *buffer, size_t buffer_size, /* {{{ */
+    meta_data_t *meta)
+{
+  char **keys = NULL;
+  size_t keys_num;
+  int status;
+
+  if ((buffer == NULL) || (buffer_size == 0) || (meta == NULL))
+    return (EINVAL);
+
+  status = meta_data_toc (meta, &keys);
+  if (status <= 0)
+    return (status);
+  keys_num = (size_t) status;
+
+  status = meta_data_keys_to_json (buffer, buffer_size, meta, keys, keys_num);
+
+  for (size_t i = 0; i < keys_num; ++i)
+    sfree (keys[i]);
+  sfree (keys);
+
+  return status;
 } /* }}} int meta_data_to_json */
 
 static int value_list_to_json (char *buffer, size_t buffer_size, /* {{{ */
@@ -484,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 12fc9b8..bfb9292 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "utils_latency.h"
 #include "common.h"
@@ -76,7 +77,7 @@ struct latency_counter_s
 * So, if the required bin width is 300, then new bin width will be 512 as it is
 * the next nearest power of 2.
 */
-void change_bin_width (latency_counter_t *lc, cdtime_t latency) /* {{{ */
+static void change_bin_width (latency_counter_t *lc, cdtime_t latency) /* {{{ */
 {
   /* This function is called because the new value is above histogram's range.
    * First find the required bin width:
@@ -96,9 +97,8 @@ 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)
@@ -117,14 +117,13 @@ void change_bin_width (latency_counter_t *lc, cdtime_t latency) /* {{{ */
       CDTIME_T_TO_DOUBLE (new_bin_width));
 } /* }}} void change_bin_width */
 
-latency_counter_t *latency_counter_create () /* {{{ */
+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;
index 9930b72..cb56b08 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "utils_time.h"
 
 struct latency_counter_s;
 typedef struct latency_counter_s latency_counter_t;
 
-latency_counter_t *latency_counter_create ();
+latency_counter_t *latency_counter_create (void);
 void latency_counter_destroy (latency_counter_t *lc);
 
 void latency_counter_add (latency_counter_t *lc, cdtime_t latency);
index 5769ec9..9c3b0ad 100644 (file)
 
 #define DBL_PRECISION 1e-9
 
-#include "testing.h"
-#include "collectd.h"
 #include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "collectd.h"
+
+#include "testing.h"
 #include "utils_time.h"
 #include "utils_latency.h"
 
@@ -49,12 +50,11 @@ DEF_TEST(simple)
     { 99, 0.3,  99, 103, 20.6},
     /* { -1, 0.3,  99, 103, 20.6}, see issue #1139 */
   };
-  size_t i;
   latency_counter_t *l;
 
   CHECK_NOT_NULL (l = latency_counter_create ());
 
-  for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+  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));
@@ -71,12 +71,11 @@ DEF_TEST(simple)
 
 DEF_TEST(percentile)
 {
-  size_t i;
   latency_counter_t *l;
 
   CHECK_NOT_NULL (l = latency_counter_create ());
 
-  for (i = 0; i < 100; i++) {
+  for (size_t i = 0; i < 100; i++) {
     latency_counter_add (l, TIME_T_TO_CDTIME_T (((time_t) i) + 1));
   }
 
index b63a81a..b8dabb1 100644 (file)
  * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  * See the GNU General Public Licence for more details.
  *
- * You should have received a copy of the GNU General Public
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
+ * 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
  *
  * Author:
  *   Niki W. Waibel <niki.waibel@gmx.net>
 **/
 
-#include "collectd.h"
-#include "utils_mount.h"
-
-#include "common.h" /* sstrncpy() et alii */
-#include "plugin.h" /* ERROR() macro */
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
 
 #if HAVE_XFS_XQM_H
+# define _GNU_SOURCE
 # include <xfs/xqm.h>
 #define XFS_SUPER_MAGIC_STR "XFSB"
 #define XFS_SUPER_MAGIC2_STR "BSFX"
 #endif
 
+#include "collectd.h"
+
+#include "utils_mount.h"
+
+#include "common.h" /* sstrncpy() et alii */
+#include "plugin.h" /* ERROR() macro */
+
+
 #if HAVE_GETVFSSTAT
 #  if HAVE_SYS_TYPES_H
 #    include <sys/types.h>
@@ -210,7 +216,6 @@ uuidcache_init(void)
        FILE *procpt;
        char uuid[16], *label = NULL;
        char device[110];
-       int firstPass;
        int handleOnFirst;
 
        if(uuidCache) {
@@ -222,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 ]",
@@ -312,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++;
                }
@@ -376,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;
@@ -388,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;
@@ -430,22 +433,21 @@ static cu_mount_t *cu_mount_listmntent (void)
 #elif HAVE_GETVFSSTAT || HAVE_GETFSSTAT
 static cu_mount_t *cu_mount_getfsstat (void)
 {
-#if HAVE_GETVFSSTAT
-#  define STRUCT_STATFS struct statvfs
-#  define CMD_STATFS    getvfsstat
-#  define FLAGS_STATFS  ST_NOWAIT
-/* #endif HAVE_GETVFSSTAT */
-#elif HAVE_GETFSSTAT
+#if HAVE_GETFSSTAT
 #  define STRUCT_STATFS struct statfs
 #  define CMD_STATFS    getfsstat
 #  define FLAGS_STATFS  MNT_NOWAIT
-#endif /* HAVE_GETFSSTAT */
+/* #endif HAVE_GETFSSTAT */
+#elif HAVE_GETVFSSTAT
+#  define STRUCT_STATFS struct statvfs
+#  define CMD_STATFS    getvfsstat
+#  define FLAGS_STATFS  ST_NOWAIT
+#endif /* HAVE_GETVFSSTAT */
 
        int bufsize;
        STRUCT_STATFS *buf;
 
        int num;
-       int i;
 
        cu_mount_t *first = NULL;
        cu_mount_t *last  = NULL;
@@ -462,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 */
@@ -480,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);
@@ -536,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);
@@ -571,6 +569,63 @@ static cu_mount_t *cu_mount_gen_getmntent (void)
 #warn "This version of `getmntent' hat not yet been implemented!"
 /* #endif HAVE_SEQ_GETMNTENT */
 
+#elif HAVE_GETMNTENT_R
+static cu_mount_t *cu_mount_getmntent (void)
+{
+       FILE *fp;
+       struct mntent me;
+       char mntbuf[1024];
+
+       cu_mount_t *first = NULL;
+       cu_mount_t *last  = NULL;
+       cu_mount_t *new   = NULL;
+
+       DEBUG ("utils_mount: (void); COLLECTD_MNTTAB = %s", COLLECTD_MNTTAB);
+
+       if ((fp = setmntent (COLLECTD_MNTTAB, "r")) == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("setmntent (%s): %s", COLLECTD_MNTTAB,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (NULL);
+       }
+
+       while (getmntent_r (fp, &me, mntbuf, sizeof (mntbuf) ))
+       {
+               if ((new = calloc (1, sizeof (*new))) == NULL)
+                       break;
+
+               /* Copy values from `struct mntent *' */
+               new->dir         = sstrdup (me.mnt_dir);
+               new->spec_device = sstrdup (me.mnt_fsname);
+               new->type        = sstrdup (me.mnt_type);
+               new->options     = sstrdup (me.mnt_opts);
+               new->device      = get_device_name (new->options);
+               new->next        = NULL;
+
+               DEBUG ("utils_mount: new = {dir = %s, spec_device = %s, type = %s, options = %s, device = %s}",
+                               new->dir, new->spec_device, new->type, new->options, new->device);
+
+               /* Append to list */
+               if (first == NULL)
+               {
+                       first = new;
+                       last  = new;
+               }
+               else
+               {
+                       last->next = new;
+                       last       = new;
+               }
+       }
+
+       endmntent (fp);
+
+       DEBUG ("utils_mount: return (0x%p)", (void *) first);
+
+       return (first);
+} /* HAVE_GETMNTENT_R */
+
 #elif HAVE_ONE_GETMNTENT
 static cu_mount_t *cu_mount_getmntent (void)
 {
@@ -593,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);
@@ -683,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;
 
@@ -700,15 +753,15 @@ 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;
-       int l = strlen(keyword);
-       char *p1, *p2;
+       char *line2, *l2, *p1, *p2;
+       int l;
 
        if(line == NULL || keyword == NULL) {
                return NULL;
        }
+
        if(full != 0) {
                full = 1;
        }
@@ -722,6 +775,7 @@ cu_mount_checkoption(char *line, char *keyword, int full)
                l2++;
        }
 
+       l = strlen(keyword);
        p1 = line - 1;
        p2 = strchr(line, ',');
        do {
@@ -740,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;
 
@@ -756,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 bc0077f..0a5c980 100644 (file)
  * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  * See the GNU General Public Licence for more details.
  *
- * You should have received a copy of the GNU General Public
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
+ * 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
  *
  * Author:
  *   Niki W. Waibel <niki.waibel@gmx.net>
@@ -114,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
@@ -154,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 b4cb432..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";
-
-  EXPECT_EQ_STR ("one", cu_mount_getoptionvalue (line_opts, "foo="));
-  EXPECT_EQ_STR ("two", cu_mount_getoptionvalue (line_opts, "bar="));
-  EXPECT_EQ_STR ("three", cu_mount_getoptionvalue (line_opts, "qux="));
-  OK (NULL == cu_mount_getoptionvalue (line_opts, "unknown="));
-
-  EXPECT_EQ_STR ("", cu_mount_getoptionvalue (line_bool, "one"));
-  EXPECT_EQ_STR ("", cu_mount_getoptionvalue (line_bool, "two"));
-  EXPECT_EQ_STR ("", 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 39f42b2..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);
@@ -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 41cc0a4..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;
@@ -68,7 +69,7 @@ static void *lookup_class_callback (data_set_t const *ds,
   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));
@@ -90,7 +91,6 @@ static int 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));
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 c6c4df0..bc6d294 100644 (file)
@@ -24,6 +24,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -135,6 +136,397 @@ static int varnish_submit_derive (const char *plugin_instance, /* {{{ */
        return (varnish_submit (plugin_instance, category, type, type_instance, value));
 } /* }}} int varnish_submit_derive */
 
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+static int varnish_monitor (void *priv, const struct VSC_point * const pt) /* {{{ */
+{
+       uint64_t val;
+       const user_config_t *conf;
+       const char *class;
+       const char *name;
+
+       if (pt == NULL)
+               return (0);
+
+       conf = priv;
+
+#if HAVE_VARNISH_V4
+       class = pt->section->fantom->type;
+       name  = pt->desc->name;
+
+       if (strcmp(class, "MAIN") != 0)
+               return (0);
+
+#elif HAVE_VARNISH_V3
+       class = pt->class;
+       name  = pt->name;
+
+       if (strcmp(class, "") != 0)
+               return (0);
+#endif
+
+       val = *(const volatile uint64_t*) pt->ptr;
+
+       if (conf->collect_cache)
+       {
+               if (strcmp(name, "cache_hit") == 0)
+                       return varnish_submit_derive (conf->instance, "cache", "cache_result", "hit",     val);
+               else if (strcmp(name, "cache_miss") == 0)
+                       return varnish_submit_derive (conf->instance, "cache", "cache_result", "miss",    val);
+               else if (strcmp(name, "cache_hitpass") == 0)
+                       return varnish_submit_derive (conf->instance, "cache", "cache_result", "hitpass", val);
+       }
+
+       if (conf->collect_connections)
+       {
+               if (strcmp(name, "client_conn") == 0)
+                       return varnish_submit_derive (conf->instance, "connections", "connections", "accepted", val);
+               else if (strcmp(name, "client_drop") == 0)
+                       return varnish_submit_derive (conf->instance, "connections", "connections", "dropped" , val);
+               else if (strcmp(name, "client_req") == 0)
+                       return varnish_submit_derive (conf->instance, "connections", "connections", "received", val);
+       }
+
+#ifdef HAVE_VARNISH_V3
+       if (conf->collect_dirdns)
+       {
+               if (strcmp(name, "dir_dns_lookups") == 0)
+                       return varnish_submit_derive (conf->instance, "dirdns", "cache_operation", "lookups",    val);
+               else if (strcmp(name, "dir_dns_failed") == 0)
+                       return varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "failed",     val);
+               else if (strcmp(name, "dir_dns_hit") == 0)
+                       return varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "hits",       val);
+               else if (strcmp(name, "dir_dns_cache_full") == 0)
+                       return varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "cache_full", val);
+       }
+#endif
+
+       if (conf->collect_esi)
+       {
+               if (strcmp(name, "esi_errors") == 0)
+                       return varnish_submit_derive (conf->instance, "esi", "total_operations", "error",   val);
+               else if (strcmp(name, "esi_parse") == 0)
+                       return varnish_submit_derive (conf->instance, "esi", "total_operations", "parsed",  val);
+               else if (strcmp(name, "esi_warnings") == 0)
+                       return varnish_submit_derive (conf->instance, "esi", "total_operations", "warning", val);
+       }
+
+       if (conf->collect_backend)
+       {
+               if (strcmp(name, "backend_conn") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "success",       val);
+               else if (strcmp(name, "backend_unhealthy") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "not-attempted", val);
+               else if (strcmp(name, "backend_busy") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "too-many",      val);
+               else if (strcmp(name, "backend_fail") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "failures",      val);
+               else if (strcmp(name, "backend_reuse") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "reuses",        val);
+               else if (strcmp(name, "backend_toolate") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "was-closed",    val);
+               else if (strcmp(name, "backend_recycle") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "recycled",      val);
+               else if (strcmp(name, "backend_unused") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "unused",        val);
+               else if (strcmp(name, "backend_retry") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "connections", "retries",       val);
+               else if (strcmp(name, "backend_req") == 0)
+                       return varnish_submit_derive (conf->instance, "backend", "http_requests", "requests",    val);
+               else if (strcmp(name, "n_backend") == 0)
+                       return varnish_submit_gauge  (conf->instance, "backend", "backends", "n_backends",       val);
+       }
+
+       if (conf->collect_fetch)
+       {
+               if (strcmp(name, "fetch_head") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "head",        val);
+               else if (strcmp(name, "fetch_length") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "length",      val);
+               else if (strcmp(name, "fetch_chunked") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "chunked",     val);
+               else if (strcmp(name, "fetch_eof") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "eof",         val);
+               else if (strcmp(name, "fetch_bad") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "bad_headers", val);
+               else if (strcmp(name, "fetch_close") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "close",       val);
+               else if (strcmp(name, "fetch_oldhttp") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "oldhttp",     val);
+               else if (strcmp(name, "fetch_zero") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "zero",        val);
+               else if (strcmp(name, "fetch_failed") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "failed",      val);
+               else if (strcmp(name, "fetch_1xx") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_1xx", val);
+               else if (strcmp(name, "fetch_204") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_204", val);
+               else if (strcmp(name, "fetch_304") == 0)
+                       return varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_304", val);
+       }
+
+       if (conf->collect_hcb)
+       {
+               if (strcmp(name, "hcb_nolock") == 0)
+                       return varnish_submit_derive (conf->instance, "hcb", "cache_operation", "lookup_nolock", val);
+               else if (strcmp(name, "hcb_lock") == 0)
+                       return varnish_submit_derive (conf->instance, "hcb", "cache_operation", "lookup_lock",   val);
+               else if (strcmp(name, "hcb_insert") == 0)
+                       return varnish_submit_derive (conf->instance, "hcb", "cache_operation", "insert",        val);
+       }
+
+       if (conf->collect_objects)
+       {
+               if (strcmp(name, "n_expired") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "expired",            val);
+               else if (strcmp(name, "n_lru_nuked") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_nuked",          val);
+               else if (strcmp(name, "n_lru_saved") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_saved",          val);
+               else if (strcmp(name, "n_lru_moved") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_moved",          val);
+               else if (strcmp(name, "n_deathrow") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "deathrow",           val);
+               else if (strcmp(name, "losthdr") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "header_overflow",    val);
+               else if (strcmp(name, "n_obj_purged") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "purged",             val);
+               else if (strcmp(name, "n_objsendfile") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_sendfile",      val);
+               else if (strcmp(name, "n_objwrite") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_write",         val);
+               else if (strcmp(name, "n_objoverflow") == 0)
+                       return varnish_submit_derive (conf->instance, "objects", "total_objects", "workspace_overflow", val);
+       }
+
+#if HAVE_VARNISH_V3
+       if (conf->collect_ban)
+       {
+               if (strcmp(name, "n_ban") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "total",          val);
+               else if (strcmp(name, "n_ban_add") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "added",          val);
+               else if (strcmp(name, "n_ban_retire") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "deleted",        val);
+               else if (strcmp(name, "n_ban_obj_test") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "objects_tested", val);
+               else if (strcmp(name, "n_ban_re_test") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "regexps_tested", val);
+               else if (strcmp(name, "n_ban_dups") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "duplicate",      val);
+       }
+#endif
+#if HAVE_VARNISH_V4
+       if (conf->collect_ban)
+       {
+               if (strcmp(name, "bans") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "total",     val);
+               else if (strcmp(name, "bans_added") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "added",     val);
+               else if (strcmp(name, "bans_obj") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "obj",       val);
+               else if (strcmp(name, "bans_req") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "req",       val);
+               else if (strcmp(name, "bans_completed") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "completed", val);
+               else if (strcmp(name, "bans_deleted") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "deleted",   val);
+               else if (strcmp(name, "bans_tested") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "tested",    val);
+               else if (strcmp(name, "bans_dups") == 0)
+                       return varnish_submit_derive (conf->instance, "ban", "total_operations", "duplicate", val);
+       }
+#endif
+
+       if (conf->collect_session)
+       {
+               if (strcmp(name, "sess_closed") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "closed",    val);
+               else if (strcmp(name, "sess_pipeline") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "pipeline",  val);
+               else if (strcmp(name, "sess_readahead") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "readahead", val);
+               else if (strcmp(name, "sess_conn") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "accepted",  val);
+               else if (strcmp(name, "sess_drop") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "dropped",   val);
+               else if (strcmp(name, "sess_fail") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "failed",    val);
+               else if (strcmp(name, "sess_pipe_overflow") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "overflow",  val);
+               else if (strcmp(name, "sess_queued") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "queued",    val);
+               else if (strcmp(name, "sess_linger") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "linger",    val);
+               else if (strcmp(name, "sess_herd") == 0)
+                       return varnish_submit_derive (conf->instance, "session", "total_operations", "herd",      val);
+       }
+
+       if (conf->collect_shm)
+       {
+               if (strcmp(name, "shm_records") == 0)
+                       return varnish_submit_derive (conf->instance, "shm", "total_operations", "records",    val);
+               else if (strcmp(name, "shm_writes") == 0)
+                       return varnish_submit_derive (conf->instance, "shm", "total_operations", "writes",     val);
+               else if (strcmp(name, "shm_flushes") == 0)
+                       return varnish_submit_derive (conf->instance, "shm", "total_operations", "flushes",    val);
+               else if (strcmp(name, "shm_cont") == 0)
+                       return varnish_submit_derive (conf->instance, "shm", "total_operations", "contention", val);
+               else if (strcmp(name, "shm_cycles") == 0)
+                       return varnish_submit_derive (conf->instance, "shm", "total_operations", "cycles",     val);
+       }
+
+       if (conf->collect_sms)
+       {
+               if (strcmp(name, "sms_nreq") == 0)
+                       return varnish_submit_derive (conf->instance, "sms", "total_requests", "allocator", val);
+               else if (strcmp(name, "sms_nobj") == 0)
+                       return varnish_submit_gauge (conf->instance,  "sms", "requests", "outstanding",     val);
+               else if (strcmp(name, "sms_nbytes") == 0)
+                       return varnish_submit_gauge (conf->instance,  "sms", "bytes", "outstanding",        val);
+               else if (strcmp(name, "sms_balloc") == 0)
+                       return varnish_submit_derive (conf->instance,  "sms", "total_bytes", "allocated",   val);
+               else if (strcmp(name, "sms_bfree") == 0)
+                       return varnish_submit_derive (conf->instance,  "sms", "total_bytes", "free",        val);
+       }
+
+       if (conf->collect_struct)
+       {
+               if (strcmp(name, "n_sess_mem") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess_mem",  val);
+               else if (strcmp(name, "n_sess") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess",      val);
+               else if (strcmp(name, "n_object") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "object",             val);
+               else if (strcmp(name, "n_vampireobject") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "vampireobject",      val);
+               else if (strcmp(name, "n_objectcore") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "objectcore",         val);
+               else if (strcmp(name, "n_waitinglist") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "waitinglist",        val);
+               else if (strcmp(name, "n_objecthead") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "objecthead",         val);
+               else if (strcmp(name, "n_smf") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "smf",                val);
+               else if (strcmp(name, "n_smf_frag") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "smf_frag",           val);
+               else if (strcmp(name, "n_smf_large") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "smf_large",          val);
+               else if (strcmp(name, "n_vbe_conn") == 0)
+                       return varnish_submit_gauge (conf->instance, "struct", "objects", "vbe_conn",           val);
+       }
+
+       if (conf->collect_totals)
+       {
+               if (strcmp(name, "s_sess") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_sessions", "sessions",  val);
+               else if (strcmp(name, "s_req") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_requests", "requests",  val);
+               else if (strcmp(name, "s_pipe") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_operations", "pipe",    val);
+               else if (strcmp(name, "s_pass") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_operations", "pass",    val);
+               else if (strcmp(name, "s_fetch") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_operations", "fetches", val);
+               else if (strcmp(name, "s_synth") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "synth",        val);
+               else if (strcmp(name, "s_req_hdrbytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "req_header",   val);
+               else if (strcmp(name, "s_req_bodybytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "req_body",     val);
+               else if (strcmp(name, "s_resp_hdrbytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "resp_header",  val);
+               else if (strcmp(name, "s_resp_bodybytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "resp_body",    val);
+               else if (strcmp(name, "s_pipe_hdrbytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_header",  val);
+               else if (strcmp(name, "s_pipe_in") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_in",      val);
+               else if (strcmp(name, "s_pipe_out") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_out",     val);
+               else if (strcmp(name, "n_purges") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_operations", "purges",  val);
+               else if (strcmp(name, "s_hdrbytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "header-bytes", val);
+               else if (strcmp(name, "s_bodybytes") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_bytes", "body-bytes",   val);
+               else if (strcmp(name, "n_gzip") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_operations", "gzip",    val);
+               else if (strcmp(name, "n_gunzip") == 0)
+                       return varnish_submit_derive (conf->instance, "totals", "total_operations", "gunzip",  val);
+       }
+
+       if (conf->collect_uptime)
+       {
+               if (strcmp(name, "uptime") == 0)
+                       return varnish_submit_gauge (conf->instance, "uptime", "uptime", "client_uptime", val);
+       }
+
+       if (conf->collect_vcl)
+       {
+               if (strcmp(name, "n_vcl") == 0)
+                       return varnish_submit_gauge (conf->instance, "vcl", "vcl", "total_vcl",     val);
+               else if (strcmp(name, "n_vcl_avail") == 0)
+                       return varnish_submit_gauge (conf->instance, "vcl", "vcl", "avail_vcl",     val);
+               else if (strcmp(name, "n_vcl_discard") == 0)
+                       return varnish_submit_gauge (conf->instance, "vcl", "vcl", "discarded_vcl", val);
+               else if (strcmp(name, "vmods") == 0)
+                       return varnish_submit_gauge (conf->instance, "vcl", "objects", "vmod",      val);
+       }
+
+       if (conf->collect_workers)
+       {
+               if (strcmp(name, "threads") == 0)
+                       return varnish_submit_gauge (conf->instance, "workers", "threads", "worker",               val);
+               else if (strcmp(name, "threads_created") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "created",       val);
+               else if (strcmp(name, "threads_failed") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "failed",        val);
+               else if (strcmp(name, "threads_limited") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",       val);
+               else if (strcmp(name, "threads_destroyed") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "dropped",       val);
+               else if (strcmp(name, "thread_queue_len") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "queue_length",  "threads",       val);
+               else if (strcmp(name, "n_wrk") == 0)
+                       return varnish_submit_gauge (conf->instance, "workers", "threads", "worker",               val);
+               else if (strcmp(name, "n_wrk_create") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "created",       val);
+               else if (strcmp(name, "n_wrk_failed") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "failed",        val);
+               else if (strcmp(name, "n_wrk_max") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",       val);
+               else if (strcmp(name, "n_wrk_drop") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_threads", "dropped",       val);
+               else if (strcmp(name, "n_wrk_queue") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",       val);
+               else if (strcmp(name, "n_wrk_overflow") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_requests", "overflowed",   val);
+               else if (strcmp(name, "n_wrk_queued") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",       val);
+               else if (strcmp(name, "n_wrk_lqueue") == 0)
+                       return varnish_submit_derive (conf->instance, "workers", "total_requests", "queue_length", val);
+       }
+
+#if HAVE_VARNISH_V4
+       if (conf->collect_vsm)
+       {
+               if (strcmp(name, "vsm_free") == 0)
+                       return varnish_submit_gauge (conf->instance, "vsm", "bytes", "free",              val);
+               else if (strcmp(name, "vsm_used") == 0)
+                       return varnish_submit_gauge (conf->instance, "vsm", "bytes", "used",              val);
+               else if (strcmp(name, "vsm_cooling") == 0)
+                       return varnish_submit_gauge (conf->instance, "vsm", "bytes", "cooling",           val);
+               else if (strcmp(name, "vsm_overflow") == 0)
+                       return varnish_submit_gauge (conf->instance, "vsm", "bytes", "overflow",          val);
+               else if (strcmp(name, "vsm_overflowed") == 0)
+                       return varnish_submit_derive (conf->instance, "vsm", "total_bytes", "overflowed", val);
+       }
+#endif
+
+       return (0);
+
+} /* }}} static int varnish_monitor */
+#else /* if HAVE_VARNISH_V2 */
 static void varnish_monitor (const user_config_t *conf, /* {{{ */
                const c_varnish_stats_t *stats)
 {
@@ -150,41 +542,20 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
 
        if (conf->collect_connections)
        {
-#ifndef HAVE_VARNISH_V4
                /* Client connections accepted */
                varnish_submit_derive (conf->instance, "connections", "connections", "accepted", stats->client_conn);
                /* Connection dropped, no sess */
                varnish_submit_derive (conf->instance, "connections", "connections", "dropped" , stats->client_drop);
-#endif
                /* Client requests received    */
                varnish_submit_derive (conf->instance, "connections", "connections", "received", stats->client_req);
        }
 
-#ifdef HAVE_VARNISH_V3
-       if (conf->collect_dirdns)
-       {
-               /* DNS director lookups */
-               varnish_submit_derive (conf->instance, "dirdns", "cache_operation", "lookups",    stats->dir_dns_lookups);
-               /* DNS director failed lookups */
-               varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "failed",     stats->dir_dns_failed);
-               /* DNS director cached lookups hit */
-               varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "hits",       stats->dir_dns_hit);
-               /* DNS director full dnscache */
-               varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "cache_full", stats->dir_dns_cache_full);
-       }
-#endif
-
        if (conf->collect_esi)
        {
                /* ESI parse errors (unlock)   */
                varnish_submit_derive (conf->instance, "esi", "total_operations", "error",   stats->esi_errors);
-#if HAVE_VARNISH_V2
                /* Objects ESI parsed (unlock) */
                varnish_submit_derive (conf->instance, "esi", "total_operations", "parsed",  stats->esi_parse);
-#else
-               /* ESI parse warnings (unlock) */
-               varnish_submit_derive (conf->instance, "esi", "total_operations", "warning", stats->esi_warnings);
-#endif
        }
 
        if (conf->collect_backend)
@@ -203,13 +574,8 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "backend", "connections", "was-closed"   , stats->backend_toolate);
                /* Backend conn. recycles      */
                varnish_submit_derive (conf->instance, "backend", "connections", "recycled"     , stats->backend_recycle);
-#if HAVE_VARNISH_V2
                /* Backend conn. unused        */
                varnish_submit_derive (conf->instance, "backend", "connections", "unused"       , stats->backend_unused);
-#else
-               /* Backend conn. retry         */
-               varnish_submit_derive (conf->instance, "backend", "connections", "retries"      , stats->backend_retry);
-#endif
                /* Backend requests mades      */
                varnish_submit_derive (conf->instance, "backend", "http_requests", "requests"   , stats->backend_req);
                /* N backends                  */
@@ -236,14 +602,6 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "fetch", "http_requests", "zero"       , stats->fetch_zero);
                /* Fetch failed              */
                varnish_submit_derive (conf->instance, "fetch", "http_requests", "failed"     , stats->fetch_failed);
-#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
-               /* Fetch no body (1xx)       */
-               varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_1xx", stats->fetch_1xx);
-               /* Fetch no body (204)       */
-               varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_204", stats->fetch_204);
-               /* Fetch no body (304)       */
-               varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_304", stats->fetch_304);
-#endif
        }
 
        if (conf->collect_hcb)
@@ -262,32 +620,22 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "objects", "total_objects", "expired",            stats->n_expired);
                /* N LRU nuked objects           */
                varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_nuked",          stats->n_lru_nuked);
-#if HAVE_VARNISH_V2
                /* N LRU saved objects           */
                varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_saved",          stats->n_lru_saved);
-#endif
                /* N LRU moved objects           */
                varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_moved",          stats->n_lru_moved);
-#if HAVE_VARNISH_V2
                /* N objects on deathrow         */
                varnish_submit_derive (conf->instance, "objects", "total_objects", "deathrow",           stats->n_deathrow);
-#endif
                /* HTTP header overflows         */
                varnish_submit_derive (conf->instance, "objects", "total_objects", "header_overflow",    stats->losthdr);
-#if HAVE_VARNISH_V4
-               /* N purged objects              */
-               varnish_submit_derive (conf->instance, "objects", "total_objects", "purged",             stats->n_obj_purged);
-#else
                /* Objects sent with sendfile    */
                varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_sendfile",      stats->n_objsendfile);
                /* Objects sent with write       */
                varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_write",         stats->n_objwrite);
                /* Objects overflowing workspace */
                varnish_submit_derive (conf->instance, "objects", "total_objects", "workspace_overflow", stats->n_objoverflow);
-#endif
        }
 
-#if HAVE_VARNISH_V2
        if (conf->collect_purge)
        {
                /* N total active purges      */
@@ -303,45 +651,6 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                /* N duplicate purges removed */
                varnish_submit_derive (conf->instance, "purge", "total_operations", "duplicate",        stats->n_purge_dups);
        }
-#endif
-#if HAVE_VARNISH_V3
-       if (conf->collect_ban)
-       {
-               /* N total active bans      */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "total",          stats->n_ban);
-               /* N new bans added         */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "added",          stats->n_ban_add);
-               /* N old bans deleted       */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "deleted",        stats->n_ban_retire);
-               /* N objects tested         */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "objects_tested", stats->n_ban_obj_test);
-               /* N regexps tested against */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "regexps_tested", stats->n_ban_re_test);
-               /* N duplicate bans removed */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "duplicate",      stats->n_ban_dups);
-       }
-#endif
-#if HAVE_VARNISH_V4
-       if (conf->collect_ban)
-       {
-               /* N total active bans      */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "total",          stats->bans);
-               /* N new bans added         */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "added",          stats->bans_added);
-               /* N bans using obj */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "obj",            stats->bans_obj);
-               /* N bans using req */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "req",            stats->bans_req);
-               /* N new bans completed     */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "completed",      stats->bans_completed);
-               /* N old bans deleted       */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "deleted",        stats->bans_deleted);
-               /* N objects tested         */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "tested",         stats->bans_tested);
-               /* N duplicate bans removed */
-               varnish_submit_derive (conf->instance, "ban", "total_operations", "duplicate",      stats->bans_dups);
-       }
-#endif
 
        if (conf->collect_session)
        {
@@ -351,21 +660,8 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "session", "total_operations", "pipeline",  stats->sess_pipeline);
                /* Session Read Ahead */
                varnish_submit_derive (conf->instance, "session", "total_operations", "readahead", stats->sess_readahead);
-#if HAVE_VARNISH_V4
-               /* Sessions accepted */
-               varnish_submit_derive (conf->instance, "session", "total_operations", "accepted",  stats->sess_conn);
-               /* Sessions dropped for thread */
-               varnish_submit_derive (conf->instance, "session", "total_operations", "dropped",   stats->sess_drop);
-               /* Sessions accept failure */
-               varnish_submit_derive (conf->instance, "session", "total_operations", "failed",    stats->sess_fail);
-               /* Sessions pipe overflow */
-               varnish_submit_derive (conf->instance, "session", "total_operations", "overflow",  stats->sess_pipe_overflow);
-               /* Sessions queued for thread */
-               varnish_submit_derive (conf->instance, "session", "total_operations", "queued",    stats->sess_queued);
-#else
                /* Session Linger     */
                varnish_submit_derive (conf->instance, "session", "total_operations", "linger",    stats->sess_linger);
-#endif
                /* Session herd       */
                varnish_submit_derive (conf->instance, "session", "total_operations", "herd",      stats->sess_herd);
        }
@@ -384,7 +680,6 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "shm", "total_operations", "cycles"    , stats->shm_cycles);
        }
 
-#if HAVE_VARNISH_V2
        if (conf->collect_sm)
        {
                /* allocator requests */
@@ -410,7 +705,6 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                /* SMA bytes free */
                varnish_submit_derive (conf->instance,  "sma", "total_bytes", "free" ,     stats->sma_bfree);
        }
-#endif
 
        if (conf->collect_sms)
        {
@@ -428,25 +722,14 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
 
        if (conf->collect_struct)
        {
-#if !HAVE_VARNISH_V4
                /* N struct sess_mem       */
                varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess_mem",  stats->n_sess_mem);
                /* N struct sess           */
                varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess",      stats->n_sess);
-#endif
                /* N struct object         */
                varnish_submit_gauge (conf->instance, "struct", "objects", "object",             stats->n_object);
-#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
-               /* N unresurrected objects */
-               varnish_submit_gauge (conf->instance, "struct", "objects", "vampireobject",      stats->n_vampireobject);
-               /* N struct objectcore     */
-               varnish_submit_gauge (conf->instance, "struct", "objects", "objectcore",         stats->n_objectcore);
-               /* N struct waitinglist    */
-               varnish_submit_gauge (conf->instance, "struct", "objects", "waitinglist",        stats->n_waitinglist);
-#endif
                /* N struct objecthead     */
                varnish_submit_gauge (conf->instance, "struct", "objects", "objecthead",         stats->n_objecthead);
-#ifdef HAVE_VARNISH_V2
                /* N struct smf            */
                varnish_submit_gauge (conf->instance, "struct", "objects", "smf",                stats->n_smf);
                /* N small free smf         */
@@ -455,7 +738,6 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_gauge (conf->instance, "struct", "objects", "smf_large",          stats->n_smf_large);
                /* N struct vbe_conn        */
                varnish_submit_gauge (conf->instance, "struct", "objects", "vbe_conn",           stats->n_vbe_conn);
-#endif
        }
 
        if (conf->collect_totals)
@@ -470,46 +752,11 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "totals", "total_operations", "pass",    stats->s_pass);
                /* Total fetch */
                varnish_submit_derive (conf->instance, "totals", "total_operations", "fetches", stats->s_fetch);
-#if HAVE_VARNISH_V4
-               /* Total synth */
-               varnish_submit_derive (conf->instance, "totals", "total_bytes", "synth",       stats->s_synth);
-               /* Request header bytes */
-               varnish_submit_derive (conf->instance, "totals", "total_bytes", "req_header",  stats->s_req_hdrbytes);
-               /* Request body byte */
-               varnish_submit_derive (conf->instance, "totals", "total_bytes", "req_body",    stats->s_req_bodybytes);
-               /* Response header bytes */
-               varnish_submit_derive (conf->instance, "totals", "total_bytes", "resp_header", stats->s_resp_hdrbytes);
-               /* Response body byte */
-               varnish_submit_derive (conf->instance, "totals", "total_bytes", "resp_body",   stats->s_resp_bodybytes);
-               /* Pipe request header bytes */
-               varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_header", stats->s_pipe_hdrbytes);
-               /* Piped bytes from client */
-               varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_in",     stats->s_pipe_in);
-               /* Piped bytes to client */
-               varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_out",    stats->s_pipe_out);
-               /* Number of purge operations */
-               varnish_submit_derive (conf->instance, "totals", "total_operations", "purges", stats->n_purges);
-#else
                /* Total header bytes */
                varnish_submit_derive (conf->instance, "totals", "total_bytes", "header-bytes", stats->s_hdrbytes);
                /* Total body byte */
                varnish_submit_derive (conf->instance, "totals", "total_bytes", "body-bytes",   stats->s_bodybytes);
-#endif
-#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
-               /* Gzip operations */
-               varnish_submit_derive (conf->instance, "totals", "total_operations", "gzip",    stats->n_gzip);
-               /* Gunzip operations */
-               varnish_submit_derive (conf->instance, "totals", "total_operations", "gunzip",  stats->n_gunzip);
-#endif
-       }
-
-#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
-       if (conf->collect_uptime)
-       {
-               /* Client uptime */
-               varnish_submit_gauge (conf->instance, "uptime", "uptime", "client_uptime", stats->uptime);
        }
-#endif
 
        if (conf->collect_vcl)
        {
@@ -519,28 +766,10 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_gauge (conf->instance, "vcl", "vcl", "avail_vcl",     stats->n_vcl_avail);
                /* N vcl discarded */
                varnish_submit_gauge (conf->instance, "vcl", "vcl", "discarded_vcl", stats->n_vcl_discard);
-#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
-               /* Loaded VMODs */
-               varnish_submit_gauge (conf->instance, "vcl", "objects", "vmod",      stats->vmods);
-#endif
        }
 
        if (conf->collect_workers)
        {
-#ifdef HAVE_VARNISH_V4
-               /* total number of threads */
-               varnish_submit_gauge (conf->instance, "workers", "threads", "worker",             stats->threads);
-               /* threads created */
-               varnish_submit_derive (conf->instance, "workers", "total_threads", "created",     stats->threads_created);
-               /* thread creation failed */
-               varnish_submit_derive (conf->instance, "workers", "total_threads", "failed",      stats->threads_failed);
-               /* threads hit max */
-               varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",     stats->threads_limited);
-               /* threads destroyed */
-               varnish_submit_derive (conf->instance, "workers", "total_threads", "dropped",     stats->threads_destroyed);
-               /* length of session queue */
-               varnish_submit_derive (conf->instance, "workers", "queue_length",  "threads",     stats->thread_queue_len);
-#else
                /* worker threads */
                varnish_submit_gauge (conf->instance, "workers", "threads", "worker",             stats->n_wrk);
                /* worker threads created */
@@ -551,43 +780,21 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",     stats->n_wrk_max);
                /* dropped work requests */
                varnish_submit_derive (conf->instance, "workers", "total_threads", "dropped",     stats->n_wrk_drop);
-#ifdef HAVE_VARNISH_V2
                /* queued work requests */
                varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",     stats->n_wrk_queue);
                /* overflowed work requests */
                varnish_submit_derive (conf->instance, "workers", "total_requests", "overflowed", stats->n_wrk_overflow);
-#else /* HAVE_VARNISH_V3 */
-               /* queued work requests */
-               varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",       stats->n_wrk_queued);
-               /* work request queue length */
-               varnish_submit_derive (conf->instance, "workers", "total_requests", "queue_length", stats->n_wrk_lqueue);
-#endif
-#endif
-       }
-
-#if HAVE_VARNISH_V4
-       if (conf->collect_vsm)
-       {
-               /* Free VSM space */
-               varnish_submit_gauge (conf->instance, "vsm", "bytes", "free",              stats->vsm_free);
-               /* Used VSM space */
-               varnish_submit_gauge (conf->instance, "vsm", "bytes", "used",              stats->vsm_used);
-               /* Cooling VSM space */
-               varnish_submit_gauge (conf->instance, "vsm", "bytes", "cooling",           stats->vsm_cooling);
-               /* Overflow VSM space */
-               varnish_submit_gauge (conf->instance, "vsm", "bytes", "overflow",          stats->vsm_overflow);
-               /* Total overflowed VSM space */
-               varnish_submit_derive (conf->instance, "vsm", "total_bytes", "overflowed", stats->vsm_overflowed);
        }
-#endif
 
 } /* }}} void varnish_monitor */
+#endif
 
 #if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
 static int varnish_read (user_data_t *ud) /* {{{ */
 {
        struct VSM_data *vd;
        const c_varnish_stats_t *stats;
+       _Bool ok;
 
        user_config_t *conf;
 
@@ -617,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.");
@@ -641,8 +849,11 @@ static int varnish_read (user_data_t *ud) /* {{{ */
                return (-1);
        }
 
-
-       varnish_monitor (conf, stats);
+#if HAVE_VARNISH_V3
+       VSC_Iter (vd, varnish_monitor, conf);
+#else /* if HAVE_VARNISH_V4 */
+       VSC_Iter (vd, NULL, varnish_monitor, conf);
+#endif
        VSM_Delete (vd);
 
        return (0);
@@ -733,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;
@@ -760,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);
@@ -792,10 +1000,11 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
        {
                WARNING ("Varnish plugin: \"Instance\" blocks accept only "
                                "one argument.");
+               sfree (conf);
                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;
 
@@ -805,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);
@@ -817,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)
@@ -830,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
                {
@@ -899,6 +1125,7 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
                WARNING ("Varnish plugin: No metric has been configured for "
                                "instance \"%s\". Disabling this instance.",
                                (conf->instance == NULL) ? "localhost" : conf->instance);
+               sfree (conf);
                return (EINVAL);
        }
 
@@ -921,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 6824b13..7df51c1 100644 (file)
@@ -20,6 +20,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
@@ -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;
 
@@ -327,8 +328,8 @@ lv_init (void)
 {
     if (virInitialize () != 0)
         return -1;
-
-       return 0;
+    else
+        return 0;
 }
 
 static int
@@ -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,7 +449,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], "none") == 0) {
                 plugin_instance_format[i] = plginst_none;
                 break;
@@ -464,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;
@@ -492,7 +493,6 @@ static int
 lv_read (void)
 {
     time_t t;
-    int i;
 
     if (conn == NULL) {
         /* `conn_string == NULL' is acceptable. */
@@ -522,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)
@@ -575,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");
 
@@ -587,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.",
@@ -596,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);
         }
 
@@ -605,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,
@@ -624,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;
 
@@ -682,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;
         }
@@ -704,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) {
@@ -758,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;
 
@@ -787,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")) {
@@ -833,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);
     }
@@ -866,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);
     }
@@ -906,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 5e609e6..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)
@@ -227,6 +228,19 @@ static int vmem_read (void)
       value_t value  = { .derive = counter };
       submit_one (inst, "vmpage_action", "refill", value);
     }
+    else if (strncmp ("pgsteal_kswapd_", key, strlen ("pgsteal_kswapd_")) == 0)
+    {
+      char *inst = key + strlen ("pgsteal_kswapd_");
+      value_t value  = { .derive = counter };
+      submit_one (inst, "vmpage_action", "steal_kswapd", value);
+    }
+    else if (strncmp ("pgsteal_direct_", key, strlen ("pgsteal_direct_")) == 0)
+    {
+      char *inst = key + strlen ("pgsteal_direct_");
+      value_t value  = { .derive = counter };
+      submit_one (inst, "vmpage_action", "steal_direct", value);
+    }
+    /* For backwards compatibility (somewhen before 4.2.3) */
     else if (strncmp ("pgsteal_", key, strlen ("pgsteal_")) == 0)
     {
       char *inst = key + strlen ("pgsteal_");
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 7fc9eb9..2dce2d7 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 <netdb.h>
 
 #define WG_DEFAULT_NODE "localhost"
@@ -94,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
@@ -110,10 +135,13 @@ 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)
+    if (status != 0)
     {
         if (cb->log_send_errors)
         {
@@ -152,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);
@@ -166,9 +194,7 @@ 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;
 
@@ -184,19 +210,16 @@ 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", cb->protocol))
         ai_hints.ai_socktype = SOCK_STREAM;
     else
         ai_hints.ai_socktype = SOCK_DGRAM;
 
-    ai_list = NULL;
-
     status = getaddrinfo (cb->node, cb->service, &ai_hints, &ai_list);
     if (status != 0)
     {
@@ -206,7 +229,7 @@ static int wg_callback_init (struct wg_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);
@@ -250,7 +273,13 @@ static int wg_callback_init (struct wg_callback *cb)
                 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);
 }
@@ -326,6 +355,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);
@@ -371,7 +402,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))
@@ -381,7 +412,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. */
@@ -414,11 +444,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);
@@ -445,23 +473,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 = 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;
@@ -482,7 +511,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;
 
@@ -502,6 +531,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)
@@ -544,7 +575,6 @@ static int wg_config_node (oconfig_item_t *ci)
         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);
@@ -557,9 +587,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 868bca8..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>
 
@@ -64,11 +61,15 @@ struct wh_callback_s
         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;
         char curl_errbuf[CURL_ERROR_SIZE];
 
         char  *send_buffer;
@@ -96,12 +97,15 @@ static void wh_log_http_error (wh_callback_t *cb)
 
 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,
@@ -109,11 +113,12 @@ 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);
@@ -125,12 +130,10 @@ 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) /* {{{ */
 {
-        struct curl_slist *headers;
-
         if (cb->curl != NULL)
                 return (0);
 
@@ -157,14 +160,13 @@ 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);
 
-        headers = NULL;
-        headers = curl_slist_append (headers, "Accept:  */*");
-        if (cb->format == WH_FORMAT_JSON)
-                headers = curl_slist_append (headers, "Content-Type: application/json");
+        cb->headers = curl_slist_append (cb->headers, "Accept:  */*");
+        if (cb->format == WH_FORMAT_JSON || cb->format == WH_FORMAT_KAIROSDB)
+                cb->headers = curl_slist_append (cb->headers, "Content-Type: application/json");
         else
-                headers = curl_slist_append (headers, "Content-Type: text/plain");
-        headers = curl_slist_append (headers, "Expect:");
-        curl_easy_setopt (cb->curl, CURLOPT_HTTPHEADER, headers);
+                cb->headers = curl_slist_append (cb->headers, "Content-Type: text/plain");
+        cb->headers = curl_slist_append (cb->headers, "Expect:");
+        curl_easy_setopt (cb->curl, CURLOPT_HTTPHEADER, cb->headers);
 
         curl_easy_setopt (cb->curl, CURLOPT_ERRORBUFFER, cb->curl_errbuf);
         curl_easy_setopt (cb->curl, CURLOPT_URL, cb->location);
@@ -184,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.");
@@ -242,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)
                 {
@@ -270,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
@@ -298,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);
@@ -324,13 +322,21 @@ 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)
         {
                 curl_easy_cleanup (cb->curl);
                 cb->curl = NULL;
         }
+
+        if (cb->headers != NULL)
+        {
+                curl_slist_free_all (cb->headers);
+                cb->headers = NULL;
+        }
+
         sfree (cb->name);
         sfree (cb->location);
         sfree (cb->user);
@@ -391,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)
@@ -439,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)
         {
@@ -451,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)
@@ -465,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);
@@ -485,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)
@@ -497,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)
 {
@@ -524,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",
@@ -534,21 +626,39 @@ 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;
@@ -556,6 +666,9 @@ static int wh_config_node (oconfig_item_t *ci) /* {{{ */
         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);
 
@@ -565,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;
@@ -612,28 +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)
-                        cf_util_get_boolean (child, &cb->log_http_error);
+                        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)
@@ -644,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());
 
@@ -671,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 ebf0e12..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 <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))
@@ -51,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 1eb082f..135a458 100644 (file)
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "configfile.h"
 
-#include <pthread.h>
 #include <sys/time.h>
 #include <hiredis/hiredis.h>
 
@@ -64,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;
@@ -79,14 +79,14 @@ static int wr_write (const data_set_t *ds, /* {{{ */
       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, node->store_rates);
-  pthread_mutex_lock (&node->lock);
   if (status != 0)
     return (status);
 
+  pthread_mutex_lock (&node->lock);
+
   if (node->conn == NULL)
   {
     node->conn = redisConnectWithTimeout ((char *)node->host, node->port, node->timeout);
@@ -168,12 +168,10 @@ 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;
@@ -192,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;
 
@@ -252,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 73d202c..10f8958 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 "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"
 
-#include <arpa/inet.h>
 #include <errno.h>
-#include <netdb.h>
-#include <inttypes.h>
-#include <pthread.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
-
-int write_riemann_threshold_check(const data_set_t *, const value_list_t *, int *);
+#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);
-
-       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;
+static char **riemann_tags;
+static size_t riemann_tags_num;
+static char **riemann_attrs;
+static size_t riemann_attrs_num;
 
-       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;
-       }
-
-       sfree (msg->events);
-       msg->n_events = 0;
+  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);
-} /* }}} 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;
-       size_t 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;
-       size_t 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 = 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);
+  }
+  wrr_send_nolock(host, host->batch_msg);
+  riemann_message_free(host->batch_msg);
 
-       if (host->use_tcp && ((status = riemann_recv_ack(host)) != 0))
-        riemann_disconnect (host);
-
-    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 ((host->batch_max < 0) || (((size_t) host->batch_max) <= len)) {
-           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;
+  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->notifications)
-               return 0;
+    status = wrr_send(host, msg);
 
-    /*
-     * 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;
-
-       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->use_tcp == 1 && host->batch_mode) {
-               riemann_batch_add_value_list (host, ds, vl, statuses);
-       } else {
-               Msg *msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
-               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_write */
-
-static void riemann_free(void *p) /* {{{ */
+    riemann_message_free(msg);
+  }
+  return status;
+} /* }}} int wrr_write */
+
+static void wrr_free(void *p) /* {{{ */
 {
-       struct riemann_host     *host = p;
+  struct riemann_host *host = p;
 
-       if (host == NULL)
-               return;
+  if (host == NULL)
+    return;
 
-       pthread_mutex_lock (&host->lock);
+  pthread_mutex_lock(&host->lock);
 
-       host->reference_count--;
-       if (host->reference_count > 0)
-       {
-               pthread_mutex_unlock (&host->lock);
-               return;
-       }
+  host->reference_count--;
+  if (host->reference_count > 0) {
+    pthread_mutex_unlock(&host->lock);
+    return;
+  }
 
-       riemann_disconnect (host);
+  wrr_disconnect(host);
 
-       sfree(host->service);
-       pthread_mutex_destroy (&host->lock);
-       sfree(host);
-} /* }}} void riemann_free */
+  pthread_mutex_destroy(&host->lock);
+  sfree(host);
+} /* }}} void wrr_free */
 
-static int riemann_config_node(oconfig_item_t *ci) /* {{{ */
+static int wrr_config_node(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);
+  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)
-               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.");
-                               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)
+  }
+  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);
+  }
+
+  host->reference_count--;
+  pthread_mutex_unlock(&host->lock);
+
+  return status;
+} /* }}} int wrr_config_node */
+
+static int wrr_config(oconfig_item_t *ci) /* {{{ */
 {
-       plugin_register_complex_config ("write_riemann", riemann_config);
+  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);
+    }
+  }
+  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 5c8559e..f2ba9dc 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 <ltdl.h>
-#include <pthread.h>
+#include "write_riemann_threshold.h"
 
 /*
  * Threshold management
@@ -133,7 +131,6 @@ static int ut_check_one_threshold (const data_set_t *ds,
     int *statuses)
 { /* {{{ */
   int ret = -1;
-  size_t i;
   int status;
   gauge_t values_copy[ds->ds_num];
 
@@ -153,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++;
@@ -163,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) {
diff --git a/src/write_riemann_threshold.h b/src/write_riemann_threshold.h
new file mode 100644 (file)
index 0000000..d3b3fe9
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef WRITE_RIEMANN_THRESHOLD_H
+#define WRITE_RIEMANN_THRESHOLD_H
+
+int write_riemann_threshold_check(const data_set_t *, const value_list_t *, int *);
+
+#endif
index 67c0496..b07b3bf 100644 (file)
  *   Fabrice A. Marie <fabrice at kibinlabs.com>
  */
 
+#define _GNU_SOURCE
+
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 #include "configfile.h"
 #include <errno.h>
 #include <netdb.h>
 #include <inttypes.h>
-#include <pthread.h>
 #include <stddef.h>
 
 #include <stdlib.h>
-#ifndef HAVE_ASPRINTF
+#define SENSU_HOST             "localhost"
+#define SENSU_PORT             "3030"
+
+#ifdef HAVE_ASPRINTF
+#define my_asprintf asprintf
+#define my_vasprintf vasprintf
+#else
 /*
- * Uses asprintf() portable implementation from
+ * 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.
  */
-#include <stdio.h>
-#include <stdarg.h>
-
-int 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_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;
 }
 
-int asprintf(char **str, const char *fmt, ...) {
-       int size = 0;
-       va_list args;
-       // init variadic argumens
-       va_start(args, fmt);
-       // format and get size
-       size = vasprintf(str, fmt, args);
-       // toss args
-       va_end(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
 
-#define SENSU_HOST             "localhost"
-#define SENSU_PORT             "3030"
-
 struct str_list {
        int nb_strs;
        char **strs;
@@ -140,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);
 }
@@ -150,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;
@@ -180,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,
@@ -222,9 +224,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) {
@@ -234,13 +235,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");
@@ -248,7 +250,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");
@@ -258,7 +260,7 @@ static char *build_json_str_list(const char *tag, struct str_list const *list) /
        return ret_str;
 } /* }}} char *build_json_str_list*/
 
-int sensu_format_name2(char *ret, int ret_len,
+static int sensu_format_name2(char *ret, int ret_len,
                const char *hostname,
                const char *plugin, const char *plugin_instance,
                const char *type, const char *type_instance,
@@ -305,9 +307,8 @@ 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;
@@ -328,7 +329,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];
-       size_t i;
        char *ret_str;
        char *temp_str;
        char *value_str;
@@ -352,7 +352,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");
@@ -361,7 +361,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");
@@ -370,7 +370,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");
@@ -380,7 +380,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");
@@ -391,7 +391,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");
@@ -404,7 +404,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");
@@ -412,7 +412,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");
@@ -422,7 +422,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");
@@ -434,7 +434,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");
@@ -444,8 +444,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");
@@ -455,8 +455,8 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
        }
 
        // incorporate sensu tags from config if any
-       if (strlen(sensu_tags) != 0) {
-               res = asprintf(&temp_str, "%s, %s", ret_str, sensu_tags);
+       if ((sensu_tags != NULL) && (strlen(sensu_tags) != 0)) {
+               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");
@@ -467,14 +467,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");
@@ -482,7 +482,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");
@@ -490,7 +490,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");
@@ -498,7 +498,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");
@@ -530,7 +530,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 %ld\"}\n", ret_str, service_buffer, value_str, CDTIME_T_TO_TIME_T(vl->time));
        free(ret_str);
        free(value_str);
        if (res == -1) {
@@ -550,7 +550,7 @@ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
  * http://creativeandcritical.net/str-replace-c/
  * copyright (c) Laird Shaw, under public domain.
  */
-char *replace_str(const char *str, const char *old, /* {{{ */
+static char *replace_str(const char *str, const char *old, /* {{{ */
                const char *new)
 {
        char *ret, *r;
@@ -569,11 +569,10 @@ 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;
@@ -636,7 +635,6 @@ 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;
@@ -660,7 +658,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;
@@ -668,7 +666,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\": %ld", ret_str, CDTIME_T_TO_TIME_T(n->time));
        free(ret_str);
        if (res == -1) {
                ERROR("write_sensu plugin: Unable to alloc memory");
@@ -679,11 +677,12 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
        char *handlers_str = build_json_str_list("handlers", &(host->notification_handlers));
        if (handlers_str == NULL) {
                ERROR("write_sensu plugin: Unable to alloc memory");
+               free(ret_str);
                return NULL;
        }
        // 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) {
@@ -697,7 +696,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");
@@ -708,7 +707,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");
@@ -719,7 +718,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");
@@ -730,7 +729,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");
@@ -741,7 +740,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");
@@ -751,8 +750,8 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
        }
 
        // incorporate sensu tags from config if any
-       if (strlen(sensu_tags) != 0) {
-               res = asprintf(&temp_str, "%s, %s", ret_str, sensu_tags);
+       if ((sensu_tags != NULL) && (strlen(sensu_tags) != 0)) {
+               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");
@@ -767,7 +766,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");
@@ -780,9 +779,10 @@ static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
                char *msg = replace_json_reserved(n->message);
                if (msg == NULL) {
                        ERROR("write_sensu plugin: Unable to alloc memory");
+                       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) {
@@ -793,9 +793,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");
@@ -804,7 +804,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");
@@ -815,7 +815,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");
@@ -882,7 +882,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;
-       size_t i;
        char *msg;
 
        pthread_mutex_lock(&host->lock);
@@ -896,7 +895,7 @@ static int sensu_write(const data_set_t *ds, /* {{{ */
                        return -1;
                }
        }
-       for (i = 0; i < 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);
@@ -976,7 +975,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;
@@ -1011,7 +1009,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;
 
@@ -1152,7 +1150,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;
@@ -1160,7 +1157,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 4a62614..309418a 100644 (file)
  */
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
 
 #include "utils_cache.h"
 
-#include <pthread.h>
 #include <netdb.h>
 
 #ifndef WT_DEFAULT_NODE
@@ -142,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;
@@ -156,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;
@@ -167,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)
@@ -185,7 +180,7 @@ 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);
@@ -211,7 +206,6 @@ static int wt_callback_init(struct wt_callback *cb)
         ERROR("write_tsdb plugin: Connecting to %s:%s failed. "
               "The last error was: %s", node, service,
               sstrerror (errno, errbuf, sizeof(errbuf)));
-        close(cb->sock_fd);
         return -1;
     }
 
@@ -347,7 +341,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) {
@@ -412,9 +406,9 @@ static int wt_send_message (const char* key, const char* value,
     int status;
     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 */
@@ -508,7 +502,6 @@ static int wt_write_messages(const data_set_t *ds, const value_list_t *vl,
     char values[512];
 
     int status;
-    size_t i;
 
     if (0 != strcmp(ds->type, vl->type))
     {
@@ -517,7 +510,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;
 
@@ -576,17 +569,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;
@@ -595,7 +586,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;
 
@@ -620,7 +611,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);
@@ -633,9 +623,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 a423bb6..3535995 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "plugin.h"
 #include "common.h"
 
@@ -48,7 +49,7 @@ static void cxmms_submit (const char *type, gauge_t value)
        plugin_dispatch_values (&vl);
 } /* void cxmms_submit */
 
-int cxmms_read (void)
+static int cxmms_read (void)
 {
   gint rate;
   gint freq;
index dd633d5..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);
 }
 
-#elif !defined(__FreeBSD__) // Solaris
+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(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,75 +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));
-       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);
-                       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)
        {
@@ -250,10 +268,19 @@ static int za_read (void)
 #endif
 
        /* Sizes */
-       za_read_gauge (ksp, "size",    "cache_size", "arc");
-       za_read_gauge (ksp, "c",    "cache_size", "c");
-       za_read_gauge (ksp, "c_min",    "cache_size", "c_min");
-       za_read_gauge (ksp, "c_max",    "cache_size", "c_max");
+       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.
@@ -265,14 +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");
-       za_read_derive (ksp, "stolen",   "cache_operation", "stolen");
 #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");
@@ -288,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");
@@ -305,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);
@@ -320,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)
        {
index 15eae6a..3751bfd 100644 (file)
 #endif
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
-#include <sys/types.h>
-#include <sys/vm_usage.h>
 #include <procfs.h>
 #include <zone.h>
 
@@ -49,20 +48,12 @@ typedef struct zone_stats {
        ushort_t      pctmem;
 } zone_stats_t;
 
-static long pagesize;
-
-static int zone_init (void)
-{
-       pagesize = sysconf(_SC_PAGESIZE);
-       return (0);
-}
-
 static int
-zone_compare(const zoneid_t *a, const zoneid_t *b)
+zone_compare(const void *a, const void *b)
 {
-       if (*a == *b)
+       if (*(const zoneid_t *)a == *(const zoneid_t *)b)
                return(0);
-       if (*a < *b)
+       if (*(const zoneid_t *)a < *(const zoneid_t *)b)
                return(-1);
        return(1);
 }
@@ -115,12 +106,13 @@ zone_find_stats(c_avl_tree_t *tree, zoneid_t zoneid)
        zoneid_t     *key = NULL;
 
        if (c_avl_get(tree, (void **)&zoneid, (void **)&ret)) {
-               if (!(ret = malloc(sizeof(zone_stats_t)))) {
+               if (!(ret = malloc(sizeof(*ret)))) {
                        WARNING("zone plugin: no memory");
                        return(NULL);
                }
-               if (!(key = malloc(sizeof(zoneid_t)))) {
+               if (!(key = malloc(sizeof(*key)))) {
                        WARNING("zone plugin: no memory");
+                       free(ret);
                        return(NULL);
                }
                *key = zoneid;
@@ -161,7 +153,7 @@ zone_scandir(DIR *procdir)
        c_avl_tree_t *tree;
        zone_stats_t *stats;
 
-       if (!(tree=c_avl_create((void *) zone_compare))) {
+       if (!(tree=c_avl_create(zone_compare))) {
                WARNING("zone plugin: Failed to create tree");
                return(NULL);
        }
@@ -209,6 +201,5 @@ static int zone_read (void)
 
 void module_register (void)
 {
-       plugin_register_init ("zone", zone_init);
        plugin_register_read ("zone", zone_read);
 } /* void module_register */
index abdbf20..8417485 100644 (file)
@@ -25,6 +25,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 
@@ -105,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)
        {
@@ -128,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)
@@ -159,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();
@@ -198,11 +198,6 @@ static int zookeeper_query (char *buffer, size_t buffer_size)
                }
 
                buffer_fill += (size_t) status;
-               if (status == 0)
-               {
-                       /* done reading from the socket */
-                       break;
-               }
        } /* while (recv) */
 
        status = 0;
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 b09be8e..70b8c26 100755 (executable)
@@ -1,13 +1,13 @@
 #!/bin/sh
 
-DEFAULT_VERSION="5.5.0.git"
+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"