Merge branch 'collectd-4.7' into collectd-4.8
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>
Sun, 13 Sep 2009 12:32:34 +0000 (14:32 +0200)
committerFlorian Forster <octo@leeloo.lan.home.verplant.org>
Sun, 13 Sep 2009 12:32:34 +0000 (14:32 +0200)
Conflicts:
ChangeLog
contrib/collection3/etc/collection.conf
src/df.c
version-gen.sh

12 files changed:
1  2 
ChangeLog
README
configure.in
contrib/collection3/etc/collection.conf
contrib/cussh.pl
src/Makefile.am
src/collectd.conf.in
src/curl.c
src/df.c
src/network.c
src/plugin.c
src/powerdns.c

diff --combined ChangeLog
+++ b/ChangeLog
@@@ -1,51 -1,35 +1,83 @@@
 +2009-09-13, Version 4.8.0
 +
 +      * collectd: Two new data source types, “DERIVE” and “ABSOLUTE”, have
 +        been added. “DERIVE” can be used for counters that are reset
 +        occasionally. Thanks to Mariusz Gronczewski for implementing this.
 +      * thresholds: The advanced threshold options “Percentage”, “Hits”, and
 +        “Hysteresis” have been added. Thanks to Andrés J. Díaz for hit
 +        patches.
 +      * curl_json plugin: The new cURL-JSON plugin reads JSON files using
 +        the cURL library and parses the contents according to user
 +        specification. Among other things, this allows to read statistics
 +        from a CouchDB instance. Thanks to Doug MacEachern for the patch.
 +      * df plugin: Using the new “ReportByDevice” option the device rather
 +        than the mount point can be used to identify partitions. Thanks to
 +        Paul Sadauskas for the patch.
 +      * dns plugin: The possibility to ignore numeric QTypes has been added.
 +        Thanks to Mirko Buffoni for the patch.
 +      * GenericJMX plugin: The new, Java-based GenericJMX plugin allows to
 +        query arbitrary data from a Java process using the “Java Management
 +        Extensions” (JMX).
 +      * madwifi plugin: The new MadWifi plugin collects information about
 +        Atheros wireless LAN chipsets from the MadWifi driver. Thanks to
 +        Ondrej Zajicek for his patches.
 +      * network plugin: The receive- and send-buffer-sizes have been made
 +        configurable, allowing for bigger and smaller packets. Thanks to
 +        Aman Gupta for the patch.
 +      * olsrd plugin: The new OLSRd plugin queries routing information from
 +        the “Optimized Link State Routing” daemon.
 +      * rrdtool plugin: A new configuration option allows to define a random
 +        write delay when writing RRD files. This spreads the load created by
 +        writing RRD files more evenly. Thanks to Mariusz Gronczewski for the
 +        patch.
 +      * swap plugin: The possibility to collect swapped in/out pages has
 +        been added to the Swap plugin. Thanks to Stefan Völkel for the
 +        patch.
 +      * tokyotyrant plugin: The new TokyoTyrant plugin reads the number of
 +        records and file size from a running Tokyo Tyrant server. Thanks to
 +        Paul Sadauskas for the patch.
 +      * write_http plugin: The new Write HTTP plugin sends the values
 +        collected by collectd to a web-server using HTTP POST requests.
 +        Thanks to Paul Sadauskas for the patch.
 +      * zfs_arc plugin: The new ZFS ARC plugin collects information about
 +        the “Adaptive Replacement Cache” (ARC) of the “Zeta File-System”
 +        (ZFS). Thanks to Anthony Dewhurst for the patch.
 +      * empty_counter match: The new Empty Counter match matches value
 +        lists, where at least one data source is of type COUNTER and the
 +        counter value of all counter data sources is zero.
 +
+ 2009-09-13, Version 4.7.3
+       * collectd: Fix a possible but very rare invalid “free” in the caching
+         code. Thanks to Sebastian Harl for the patch.
+       * collectd: Remove old values when a cache entry is marked as missing.
+         This way the “GETVAL” command of the UnixSock plugin doesn't return
+         old, no longer valid values when this happens. Thanks to Andrés J.
+         Díaz for the patch.
+       * collectd: The “plugin_unregister_read” function has been fixed.
+       * apache, ascent, bind, curl, nginx plugins: Advise the cURL library
+         to follow redirects. Thanks to Joey Hess for reporting this bug.
+       * df plugin: Check the ignorelist before stating the file system,
+         possibly reducing the number of stats considerably. Thanks to Joey
+         Hess for reporting this bug.
+       * iptables plugin: Support for the new libiptc API has been added.
+         Thanks to Sebastian Harl for the patch. The build system has been
+         updated to the plugin only includes the shipped header files when it
+         is linked with the shipped library, too.
+       * java plugin: Delay creating the JVM until after the daemon has
+         forked. The JVM internally creates threads that are lost when
+         forking. This means that Java-based plugins are now configured
+         during the init-phase, i. e. later than other plugins.
+       * libvirt plugin: Re-connect to libvirtd if connecting fails. Thanks
+         to Alan Pevec for the patch.
+       * network plugin: Fix the handling of the “CacheFlush” option: The
+         value was assigned to a wrong variable. The initialization of the
+         gcrypt library, which is used for signing / encrypting traffic, has
+         been fixed. Thanks to Luke Heberling for the patch.
+       * powerdns plugin: Set a timeout when reading data from the datagram
+         socket. Handling of the “LocalSocket” option has been fixed.  An
+         incorrectly used “type” has been corrected. Thanks to Luke Heberling
+         for his patches.
  2009-07-19, Version 4.7.2
        * Build system: Support for `DESTDIR' has been fixed in the Java
          bindings.
        * uptime plugin: The new uptime plugin can collect the server's
          uptime. Thanks to Marco Chiappero for the patch.
  
+ 2009-09-10, Version 4.6.5
+       * collectd: Remove old values when a cache entry is marked as missing.
+         This way the “GETVAL” command of the UnixSock plugin doesn't return
+         old, no longer valid values when this happens. Thanks to Andrés J.
+         Díaz for the patch.
+       * apache, ascent, bind, curl, nginx plugins: Advise the cURL library
+         to follow redirects. Thanks to Joey Hess for reporting this bug.
+       * df plugin: Check the ignorelist before stating the file system,
+         possibly reducing the number of stats considerably. Thanks to Joey
+         Hess for reporting this bug.
+       * iptables plugin: Support for the new libiptc API has been added.
+         Thanks to Sebastian Harl for the patch. The build system has been
+         updated to the plugin only includes the shipped header files when it
+         is linked with the shipped library, too.
+       * libvirt plugin: Re-connect to libvirtd if connecting fails. Thanks
+         to Alan Pevec for the patch.
+       * powerdns plugin: Set a timeout when reading data from the datagram
+         socket. Handling of the “LocalSocket” option has been fixed.  An
+         incorrectly used “type” has been corrected. Thanks to Luke Heberling
+         for his patches.
  2009-07-18, Version 4.6.4
        * collectd: Okay-notifications have been fixed. Thanks to Andrés J.
          Díaz for fixing this bug.
  2005-07-08, Version 1.3: CPU stats
        * Collecting CPU statistics now
  
- 2004-07-12, Version 1.2: Using syslog
+ 2005-07-12, Version 1.2: Using syslog
        * collectd is now using the syslog facility to report errors, warnings
          and the like..
        * The default directory is now /var/db/collectd
  
- 2004-07-10, Version 1.1: Minor changes
+ 2005-07-10, Version 1.1: Minor changes
        * Nothing really useful to say ;)
  
- 2004-07-09, Version 1.0: Initial Version
+ 2005-07-09, Version 1.0: Initial Version
        * The following modules are provided:
          * Load average
          * Ping time
diff --combined README
--- 1/README
--- 2/README
+++ b/README
@@@ -43,10 -43,6 +43,10 @@@ Feature
      - conntrack
        Number of nf_conntrack entries.
  
 +    - curl_json
 +      Retrieves JSON data via cURL and parses it according to user
 +      configuration.
 +
      - cpu
        CPU utilization: Time spent in the system, user, nice, idle, and related
        states.
      - libvirt
        CPU, disk and network I/O statistics from virtual machines.
  
 +    - madwifi
 +      Queries very detailed usage statistics from wireless LAN adapters and
 +      interfaces that use the Atheros chipset and the MadWifi driver.
 +
      - mbmon
        Motherboard sensors: temperature, fanspeed and voltage information,
        using mbmon(1).
        Network UPS tools: UPS current, voltage, power, charge, utilisation,
        temperature, etc. See upsd(8).
  
 +    - olsr
 +      Queries routing information from the “Optimized Link State Routing”
 +      daemon.
 +
      - onewire (EXPERIMENTAL!)
        Read onewire sensors using the owcapu library of the owfs project.
        Please read in collectd.conf(5) why this plugin is experimental.
      - thermal
        Linux ACPI thermal zone information.
  
 +    - tokyotyrant
 +      Reads the number of records and file size from a running Tokyo Tyrant
 +      server.
 +
      - uptime
        System uptime statistics.
  
      - xmms
        Bitrate and frequency of music played with XMMS.
  
 +    - zfs_arc
 +      Statistics for ZFS' “Adaptive Replacement Cache” (ARC).
 +
    * Output can be written or send to various destinations by the following
      plugins:
  
        needed. Please read collectd-unixsock(5) for a description on how that's
        done.
  
 +    - write_http
 +      Sends the values collected by collectd to a web-server using HTTP POST
 +      requests. The transmitted data is either in a form understood by the
 +      Exec plugin or formatted in JSON.
 +
    * Logging is, as everything in collectd, provided by plugins. The following
      plugins keep up informed about what's going on:
  
    * Value processing can be controlled using the "filter chain" infrastructure
      and "matches" and "targets". The following plugins are available:
  
 +    - match_empty_counter
 +      Match counter values which are currently zero.
 +
      - match_regex
        Match values by their identifier based on regular expressions.
  
@@@ -459,8 -432,7 +459,8 @@@ Prerequisite
      Used by the `oracle' plugin.
  
    * libcurl (optional)
 -    If you want to use the `apache', `ascent', `curl' or `nginx' plugin.
 +    If you want to use the `apache', `ascent', `curl', `nginx', or `write_http'
 +    plugin.
      <http://curl.haxx.se/>
  
    * libdbi (optional)
      For the `notify_desktop' plugin.
      <http://www.galago-project.org/>
  
-   * liboping (optional, if not found a version shipped with this distribution
-     can be used)
+   * liboping (optional)
      Used by the `ping' plugin to send and receive ICMP packets.
      <http://verplant.org/liboping/>
  
    * libxmms (optional)
      <http://www.xmms.org/>
  
 +  * libyajl (optional)
 +    Parse JSON data. This is needed for the `curl_json' plugin.
 +    <http://www.lloydforge.org/projects/yajl/>
  
  Configuring / Compiling / Installing
  ------------------------------------
diff --combined configure.in
@@@ -277,20 -277,6 +277,20 @@@ AC_CHECK_HEADERS(IOKit/ps/IOPowerSource
  ])
  
  # For the swap module
 +have_linux_wireless_h="no"
 +if test "x$ac_system" = "xLinux"
 +then
 +  AC_CHECK_HEADERS(linux/wireless.h,
 +                 [have_linux_wireless_h="yes"],
 +                 [have_linux_wireless_h="no"],
 +[
 +#include <dirent.h>
 +#include <sys/ioctl.h>
 +#include <sys/socket.h>
 +])
 +fi
 +
 +# For the swap module
  have_sys_swap_h="yes"
  AC_CHECK_HEADERS(sys/swap.h vm/anon.h, [], [have_sys_swap_h="no"],
  [
@@@ -1492,7 -1478,7 +1492,7 @@@ the
                with_own_libiptc="no"
        ],
        [
- #include "$srcdir/src/libiptc/ipt_kernel_headers.h"
+ #include "$srcdir/src/owniptc/ipt_kernel_headers.h"
        ])
  
        CFLAGS=$SAVE_CFLAGS
@@@ -1503,6 -1489,24 +1503,24 @@@ if test "x$with_own_libiptc" = "xyes
  then
        AC_DEFINE(OWN_LIBIPTC, 1, [Define to 1 if we use the shipped iptc library.])
  fi
+ if test "x$with_libiptc" = "xyes"
+ then
+       SAVE_CFLAGS=$CFLAGS
+       CFLAGS="$CFLAGS $KERNEL_CFLAGS"
+       AC_CHECK_TYPES([iptc_handle_t, ip6tc_handle_t], [], [],
+       [
+ #if OWN_LIBIPTC
+ # include "$srcdir/src/owniptc/libiptc.h"
+ # include "$srcdir/src/owniptc/libip6tc.h"
+ #else
+ # include <libiptc/libiptc.h>
+ # include <libiptc/libip6tc.h>
+ #endif
+       ])
+       CFLAGS=$SAVE_CFLAGS
+ fi
  # }}}
  
  # --with-java {{{
  fi
  # }}}
  
 +# --with-libtokyotyrant {{{
 +with_libtokyotyrant_cppflags=""
 +with_libtokyotyrant_ldflags=""
 +with_libtokyotyrant_libs=""
 +AC_ARG_WITH(libtokyotyrant, [AS_HELP_STRING([--with-libtokyotyrant@<:@=PREFIX@:>@], [Path to libtokyotyrant.])],
 +[
 +  if test "x$withval" = "xno"
 +  then
 +    with_libtokyotyrant="no"
 +  else if test "x$withval" = "xyes"
 +  then
 +    with_libtokyotyrant="yes"
 +  else
 +    with_libtokyotyrant_cppflags="-I$withval/include"
 +    with_libtokyotyrant_ldflags="-L$withval/include"
 +    with_libtokyotyrant_libs="-ltokyotyrant"
 +    with_libtokyotyrant="yes"
 +  fi; fi
 +],
 +[
 +  with_libtokyotyrant="yes"
 +])
 +
 +if test "x$with_libtokyotyrant" = "xyes"
 +then
 +  if $PKG_CONFIG --exists tokyotyrant
 +  then
 +    with_libtokyotyrant_cppflags="$with_libtokyotyrant_cppflags `$PKG_CONFIG --cflags tokyotyrant`"
 +    with_libtokyotyrant_ldflags="$with_libtokyotyrant_ldflags `pkg-config --libs-only-L tokyotyrant`"
 +    with_libtokyotyrant_libs="$with_libtokyotyrant_libs `pkg-config --libs-only-l tokyotyrant`"
 +  fi
 +fi
 +
 +SAVE_CPPFLAGS="$CPPFLAGS"
 +SAVE_LDFLAGS="$LDFLAGS"
 +CPPFLAGS="$CPPFLAGS $with_libtokyotyrant_cppflags"
 +LDFLAGS="$LDFLAGS $with_libtokyotyrant_ldflags"
 +
 +if test "x$with_libtokyotyrant" = "xyes"
 +then
 +  AC_CHECK_HEADERS(tcrdb.h,
 +  [
 +          AC_DEFINE(HAVE_TCRDB_H, 1,
 +                    [Define to 1 if you have the <tcrdb.h> header file.])
 +  ], [with_libtokyotyrant="no (tcrdb.h not found)"])
 +fi
 +
 +if test "x$with_libtokyotyrant" = "xyes"
 +then
 +  AC_CHECK_LIB(tokyotyrant, tcrdbrnum,
 +  [
 +          AC_DEFINE(HAVE_LIBTOKYOTYRANT, 1,
 +                    [Define to 1 if you have the tokyotyrant library (-ltokyotyrant).])
 +  ],
 +  [with_libtokyotyrant="no (symbol tcrdbrnum not found)"],
 +  [$with_libtokyotyrant_libs])
 +fi
 +
 +CPPFLAGS="$SAVE_CPPFLAGS"
 +LDFLAGS="$SAVE_LDFLAGS"
 +
 +if test "x$with_libtokyotyrant" = "xyes"
 +then 
 +  BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS="$with_libtokyotyrant_cppflags"
 +  BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS="$with_libtokyotyrant_ldflags"
 +  BUILD_WITH_LIBTOKYOTYRANT_LIBS="$with_libtokyotyrant_libs"
 +  AC_SUBST(BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS)
 +  AC_SUBST(BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS)
 +  AC_SUBST(BUILD_WITH_LIBTOKYOTYRANT_LIBS)
 +fi
 +AM_CONDITIONAL(BUILD_WITH_LIBTOKYOTYRANT, test "x$with_libtokyotyrant" = "xyes")
 +# }}}
 +
  # --with-libupsclient {{{
  with_libupsclient_config=""
  with_libupsclient_cflags=""
@@@ -3053,57 -2984,6 +3071,57 @@@ AC_DEFINE_UNQUOTED(HAVE_LIBXMMS, [$with
  AM_CONDITIONAL(BUILD_WITH_LIBXMMS, test "x$with_libxmms" = "xyes")
  # }}}
  
 +# --with-libyajl {{{
 +with_libyajl_cppflags=""
 +with_libyajl_ldflags=""
 +AC_ARG_WITH(libyajl, [AS_HELP_STRING([--with-libyajl@<:@=PREFIX@:>@], [Path to libyajl.])],
 +[
 +      if test "x$withval" != "xno" && test "x$withval" != "xyes"
 +      then
 +              with_libyajl_cppflags="-I$withval/include"
 +              with_libyajl_ldflags="-L$withval/lib"
 +              with_libyajl="yes"
 +      else
 +              with_libyajl="$withval"
 +      fi
 +],
 +[
 +      with_libyajl="yes"
 +])
 +if test "x$with_libyajl" = "xyes"
 +then
 +      SAVE_CPPFLAGS="$CPPFLAGS"
 +      CPPFLAGS="$CPPFLAGS $with_libyajl_cppflags"
 +
 +      AC_CHECK_HEADERS(yajl/yajl_parse.h, [with_libyajl="yes"], [with_libyajl="no (yajl/yajl_parse.h not found)"])
 +
 +      CPPFLAGS="$SAVE_CPPFLAGS"
 +fi
 +if test "x$with_libyajl" = "xyes"
 +then
 +      SAVE_CPPFLAGS="$CPPFLAGS"
 +      SAVE_LDFLAGS="$LDFLAGS"
 +      CPPFLAGS="$CPPFLAGS $with_libyajl_cppflags"
 +      LDFLAGS="$LDFLAGS $with_libyajl_ldflags"
 +
 +      AC_CHECK_LIB(yajl, yajl_alloc, [with_libyajl="yes"], [with_libyajl="no (Symbol 'yajl_alloc' not found)"])
 +
 +      CPPFLAGS="$SAVE_CPPFLAGS"
 +      LDFLAGS="$SAVE_LDFLAGS"
 +fi
 +if test "x$with_libyajl" = "xyes"
 +then
 +      BUILD_WITH_LIBYAJL_CPPFLAGS="$with_libyajl_cppflags"
 +      BUILD_WITH_LIBYAJL_LDFLAGS="$with_libyajl_ldflags"
 +      BUILD_WITH_LIBYAJL_LIBS="-lyajl"
 +      AC_SUBST(BUILD_WITH_LIBYAJL_CPPFLAGS)
 +      AC_SUBST(BUILD_WITH_LIBYAJL_LDFLAGS)
 +      AC_SUBST(BUILD_WITH_LIBYAJL_LIBS)
 +      AC_DEFINE(HAVE_LIBYAJL, 1, [Define if libyajl is present and usable.])
 +fi
 +AM_CONDITIONAL(BUILD_WITH_LIBYAJL, test "x$with_libyajl" = "xyes")
 +# }}}
 +
  # pkg-config --exists 'libxml-2.0'; pkg-config --exists libvirt {{{
  with_libxml2="no (pkg-config isn't available)"
  with_libxml2_cflags=""
@@@ -3438,7 -3318,6 +3456,7 @@@ plugin_bind="no
  plugin_conntrack="no"
  plugin_cpu="no"
  plugin_cpufreq="no"
 +plugin_curl_json="no"
  plugin_df="no"
  plugin_disk="no"
  plugin_entropy="no"
@@@ -3466,7 -3345,6 +3484,7 @@@ plugin_uptime="no
  plugin_vmem="no"
  plugin_vserver="no"
  plugin_wireless="no"
 +plugin_zfs_arc="no"
  
  # Linux
  if test "x$ac_system" = "xLinux"
  if test "x$with_kstat" = "xyes"
  then
        plugin_uptime="yes"
 +      plugin_zfs_arc="yes"
  fi
  
  if test "x$with_devinfo$with_kstat" = "xyesyes"
        plugin_ipmi="yes"
  fi
  
 +if test "x$with_libcurl" = "xyes" && test "x$with_libyajl" = "xyes"
 +then
 +      plugin_curl_json="yes"
 +fi
 +
  if test "x$have_processor_info" = "xyes"
  then
        plugin_cpu="yes"
@@@ -3712,7 -3584,6 +3730,7 @@@ AC_PLUGIN([cpufreq],     [$plugin_cpufr
  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([dbi],         [$with_libdbi],       [General database statistics])
  AC_PLUGIN([df],          [$plugin_df],         [Filesystem usage statistics])
  AC_PLUGIN([disk],        [$plugin_disk],       [Disk usage statistics])
@@@ -3733,8 -3604,6 +3751,8 @@@ AC_PLUGIN([java],        [$with_java]
  AC_PLUGIN([libvirt],     [$plugin_libvirt],    [Virtual machine statistics])
  AC_PLUGIN([load],        [$plugin_load],       [System load])
  AC_PLUGIN([logfile],     [yes],                [File logging plugin])
 +AC_PLUGIN([madwifi],     [$have_linux_wireless_h], [Madwifi wireless statistics])
 +AC_PLUGIN([match_empty_counter], [yes],        [The empty counter 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])
@@@ -3752,7 -3621,6 +3770,7 @@@ AC_PLUGIN([notify_desktop], [$with_libn
  AC_PLUGIN([notify_email], [$with_libesmtp],    [Email notifier])
  AC_PLUGIN([ntpd],        [yes],                [NTPd 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([openvpn],     [yes],                [OpenVPN client statistics])
  AC_PLUGIN([oracle],      [$with_oracle],       [Oracle plugin])
@@@ -3779,7 -3647,6 +3797,7 @@@ AC_PLUGIN([tcpconns],    [$plugin_tcpco
  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([tokyotyrant], [$with_libtokyotyrant],  [TokyoTyrant database statistics])
  AC_PLUGIN([unixsock],    [yes],                [Unixsock communication plugin])
  AC_PLUGIN([uptime],      [$plugin_uptime],     [Uptime statistics])
  AC_PLUGIN([users],       [$plugin_users],      [User statistics])
@@@ -3787,9 -3654,7 +3805,9 @@@ AC_PLUGIN([uuid],        [yes]
  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_http],  [$with_libcurl],      [HTTP output plugin])
  AC_PLUGIN([xmms],        [$with_libxmms],      [XMMS statistics])
 +AC_PLUGIN([zfs_arc],     [$plugin_zfs_arc],    [ZFS ARC statistics])
  
  dnl Default configuration file
  # Load either syslog or logfile
@@@ -3925,7 -3790,7 +3943,7 @@@ AC_SUBST(LCC_VERSION_STRING
  
  AC_CONFIG_FILES(src/libcollectdclient/lcc_features.h)
  
- AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/libiptc/Makefile src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile)
+ AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/owniptc/Makefile src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile)
  
  if test "x$with_librrd" = "xyes" \
        && test "x$librrd_threadsafe" != "xyes"
@@@ -3985,12 -3850,10 +4003,12 @@@ Configuration
      librrd  . . . . . . . $with_librrd
      libsensors  . . . . . $with_libsensors
      libstatgrab . . . . . $with_libstatgrab
 +    libtokyotyrant  . . . $with_libtokyotyrant
      libupsclient  . . . . $with_libupsclient
      libvirt . . . . . . . $with_libvirt
      libxml2 . . . . . . . $with_libxml2
      libxmms . . . . . . . $with_libxmms
 +    libyajl . . . . . . . $with_libyajl
      oracle  . . . . . . . $with_oracle
  
    Features:
      cpufreq . . . . . . . $enable_cpufreq
      csv . . . . . . . . . $enable_csv
      curl  . . . . . . . . $enable_curl
 +    curl_json . . . . . . $enable_curl_json
      dbi . . . . . . . . . $enable_dbi
      df  . . . . . . . . . $enable_df
      disk  . . . . . . . . $enable_disk
      libvirt . . . . . . . $enable_libvirt
      load  . . . . . . . . $enable_load
      logfile . . . . . . . $enable_logfile
 +    madwifi . . . . . . . $enable_madwifi
 +    match_empty_counter . $enable_match_empty_counter
      match_regex . . . . . $enable_match_regex
      match_timediff  . . . $enable_match_timediff
      match_value . . . . . $enable_match_value
      notify_email  . . . . $enable_notify_email
      ntpd  . . . . . . . . $enable_ntpd
      nut . . . . . . . . . $enable_nut
 +    olsrd . . . . . . . . $enable_olsrd
      onewire . . . . . . . $enable_onewire
      openvpn . . . . . . . $enable_openvpn
      oracle  . . . . . . . $enable_oracle
      teamspeak2  . . . . . $enable_teamspeak2
      ted . . . . . . . . . $enable_ted
      thermal . . . . . . . $enable_thermal
 +    tokyotyrant . . . . . $enable_tokyotyrant
      unixsock  . . . . . . $enable_unixsock
      uptime  . . . . . . . $enable_uptime
      users . . . . . . . . $enable_users
      vmem  . . . . . . . . $enable_vmem
      vserver . . . . . . . $enable_vserver
      wireless  . . . . . . $enable_wireless
 +    write_http  . . . . . $enable_write_http
      xmms  . . . . . . . . $enable_xmms
 +    zfs_arc . . . . . . . $enable_zfs_arc
  
  EOF
  
@@@ -47,52 -47,13 +47,59 @@@ GraphWidth 40
    Color starting     ff00ff
    Color waiting      ffb000
  </Type>
 +<Type arc_counts>
 +  Module ArcCounts
 +  RRDTitle "ARC {type_instance} on {hostname}"
 +# RRDOptions ...
 +</Type>
 +<Type arc_l2_bytes>
 +  Module GenericIO
 +  DataSources read write
 +  DSName  "read Read   "
 +  DSName "write Written"
 +  RRDTitle "L2ARC traffic"
 +  RRDVerticalLabel "Bytes per second"
 +# RRDOptions ...
 +  RRDFormat "%5.1lf%s"
 +</Type>
 +<Type arc_l2_size>
 +  RRDTitle "L2ARC size on {hostname}"
 +  RRDVerticalLabel "Size"
 +  RRDFormat "%4.0lf%s"
 +  RRDOptions -b 1024
 +  DSName "value Current size"
 +  Color value  00e000
 +</Type>
 +<Type arc_size>
 +  DataSources "current target minlimit maxlimit"
 +  RRDTitle "ARC size on {hostname}"
 +  RRDVerticalLabel "Size"
 +  RRDFormat "%4.0lf%s"
 +  RRDOptions -b 1024
 +  DSName  "current Current size"
 +  DSName   "target Target size "
 +  DSName "maxlimit Max size    "
 +  DSName "minlimit Min size    "
 +  Color current  00e000
 +  Color target   0000ff
 +  Color minlimit ff0000
 +  Color maxlimit ff00ff
 +</Type>
 +<Type arc_ratio>
 +  DataSources value
 +  RRDTitle "{type_instance}ARC ratio on {hostname}"
 +  RRDVerticalLabel "Ratio"
 +  RRDFormat "%4.1lf"
 +  RRDOptions -l 0
 +  DSName "value Hit ratio"
 +</Type>
+ <Type cache_ratio>
+   DataSources value
+   DSName value Percent
+   RRDTitle "Cache hit ratio for {plugin_instance} {type_instance}"
+   RRDVerticalLabel "Percent"
+   RRDFormat "%5.1lf %%"
+ </Type>
  <Type cpu>
    Module GenericStacked
    DataSources value
    Module Df
    DataSources free used
  </Type>
+ <Type df_complex>
+   Module GenericStacked
+   DataSources value
+   RRDTitle "disk usage on {plugin_instance}"
+   RRDVerticalLabel "Byte"
+   RRDFormat "%6.2lf%s"
+   DSName "snap_used    used for snapshots"
+   DSName "snap_reserved snapshot reserve "
+   DSName "used         in use            "
+   DSName "free         free              "
+   DSName "sis_saved    sis_saved         "
+   Order free snap_used snap_reserved sis_saved used
+   Color snap_reverse   ff8000
+   Color used  ff0000
+   Color snap_used   000080
+   Color snap_reserved   ff8000
+   Color free  00ff00
+   Color sis_saved 00e0e0
+ </Type>
+ <Type disk_latency>
+   Module GenericIO
+   DataSources read write
+   DSName "read Read "
+   DSName write Write
+   RRDTitle "Disk Latency for {plugin_instance}"
+   RRDVerticalLabel "microseconds"
+   Scale 0.000001
+   RRDFormat "%5.1lf %ss"
+ </Type>
  <Type disk_octets>
    Module GenericIO
    DataSources read write
  # RRDOptions ...
    RRDFormat "%5.1lf"
  </Type>
+ <Type disk_ops_complex>
+   Module GenericStacked
+   DataSources value
+   RRDTitle "Netapp disc ops on {plugin_instance}"
+   RRDVerticalLabel "Ops"
+   RRDFormat "%6.2lf"
+   DSName fcp_ops   FCP-Ops
+   DSName nfs_ops   NFS-Ops
+   DSName http_ops  HTTP-Ops
+   DSName cifs_ops  CIFS-Ops
+   DSName dafs_ops  DAFS-Ops
+   DSName iscsi_ops iSCSI-Ops
+   Order fcp_ops nfs_ops http_ops cifs_ops dafs_ops iscsi_ops
+   Color fcp_ops    000080
+   Color nfs_ops    ff0000
+   Color http_ops   ffb000
+   Color cifs_ops   00e0a0
+   Color dafs_ops   00e000
+   Color iscsi_ops  00e0ff
+ </Type>
  <Type disk_merged>
    Module GenericIO
    DataSources read write
  <Type load>
    Module Load
  </Type>
+ <Type java_memory>
+   Module JavaMemory
+   DataSources value
+ </Type>
  <Type memory>
    Module GenericStacked
    DataSources value
    RRDVerticalLabel "°Celsius"
    RRDFormat "%4.1lf°C"
  </Type>
+ <Type total_time_in_ms>
+   DataSources value
+   DSName "value Time"
+   RRDTitle "Time {instance}"
+   RRDVerticalLabel "Seconds"
+   RRDFormat "%6.2lf %ss"
+   Scale 0.001
+ </Type>
  <Type users>
    DataSources users
    DSName users Users
diff --combined contrib/cussh.pl
@@@ -60,7 -60,6 +60,7 @@@ use Collectd::Unixsock()
                HELP    => \&cmd_help,
                PUTVAL  => \&putval,
                GETVAL  => \&getval,
 +              GETTHRESHOLD  => \&getthreshold,
                FLUSH   => \&flush,
                LISTVAL => \&listval,
                PUTNOTIF => \&putnotif,
@@@ -187,12 -186,18 +187,19 @@@ sub putid 
  =cut
  
  sub cmd_help {
-       print <<HELP;
+       my $sock = shift;
+       my $line = shift || '';
+       my @line = tokenize($line);
+       my $cmd = shift (@line);
+       my %text = (
+               help => <<HELP,
  Available commands:
    HELP
    PUTVAL
    GETVAL
 +  GETTHRESHOLD
    FLUSH
    LISTVAL
    PUTNOTIF
  See the embedded Perldoc documentation for details. To do that, run:
    perldoc $0
  HELP
+               putval => <<HELP,
+ PUTVAL <id> <value0> [<value1> ...]
+ Submits a value to the daemon.
+ HELP
+               getval => <<HELP,
+ GETVAL <id>
+ Retrieves the current value or values from the daemon.
+ HELP
+               flush => <<HELP,
+ FLUSH [plugin=<plugin>] [timeout=<timeout>] [identifier=<id>] [...]
+ Sends a FLUSH command to the daemon.
+ HELP
+               listval => <<HELP,
+ LISTVAL
+ Prints a list of available values.
+ HELP
+               putnotif => <<HELP
+ PUTNOTIF severity=<severity> [...] message=<message>
+ Sends a notifications message to the daemon.
+ HELP
+       );
+       if (!$cmd)
+       {
+               $cmd = 'help';
+       }
+       if (!exists ($text{$cmd}))
+       {
+               print STDOUT "Unknown command: " . uc ($cmd) . "\n\n";
+               $cmd = 'help';
+       }
+       print STDOUT $text{$cmd};
        return 1;
  } # cmd_help
  
@@@ -283,48 -327,6 +329,48 @@@ sub getval 
        return 1;
  }
  
 +=item B<GETTHRESHOLD> I<Identifier>
 +
 +=cut
 +
 +sub getthreshold {
 +      my $sock = shift || return;
 +      my $line = shift || return;
 +
 +      my @line = tokenize($line);
 +
 +      my $id;
 +      my $vals;
 +
 +      if (! @line) {
 +              return;
 +      }
 +
 +      if (scalar(@line) < 1) {
 +              print STDERR "Synopsis: GETTHRESHOLD <id>" . $/;
 +              return;
 +      }
 +
 +      $id = getid($line[0]);
 +
 +      if (! $id) {
 +              print STDERR "Invalid id \"$line[0]\"." . $/;
 +              return;
 +      }
 +
 +      $vals = $sock->getthreshold(%$id);
 +
 +      if (! $vals) {
 +              print STDERR "socket error: " . $sock->{'error'} . $/;
 +              return;
 +      }
 +
 +      foreach my $key (keys %$vals) {
 +              print "\t$key: $vals->{$key}\n";
 +      }
 +      return 1;
 +}
 +
  =item B<FLUSH> [B<timeout>=I<$timeout>] [B<plugin>=I<$plugin>[ ...]]
  
  =cut
@@@ -354,7 -356,7 +400,7 @@@ sub flush 
                                $args{"timeout"} = $value;
                        }
                        elsif ($option eq "identifier") {
-                               my $id = getid (\$value);
+                               my $id = getid ($value);
                                if (!$id)
                                {
                                        print STDERR "Not a valid identifier: \"$value\"\n";
diff --combined src/Makefile.am
@@@ -1,6 -1,6 +1,6 @@@
  SUBDIRS = libcollectdclient
  if BUILD_WITH_OWN_LIBIPTC
- SUBDIRS += libiptc
+ SUBDIRS += owniptc
  endif
  if BUILD_WITH_OWN_LIBOCONFIG
  SUBDIRS += liboconfig
@@@ -223,21 -223,6 +223,21 @@@ endi
  collectd_DEPENDENCIES += curl.la
  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 = -module -avoid-version $(BUILD_WITH_LIBYAJL_LDFLAGS)
 +curl_json_la_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
 +collectd_LDADD += "-dlopen" curl_json.la
 +collectd_DEPENDENCIES += curl_json.la
 +endif
 +
  if BUILD_PLUGIN_DBI
  pkglib_LTLIBRARIES += dbi.la
  dbi_la_SOURCES = dbi.c \
@@@ -373,8 -358,8 +373,8 @@@ pkglib_LTLIBRARIES += iptables.l
  iptables_la_SOURCES = iptables.c
  iptables_la_LDFLAGS = -module -avoid-version
  if BUILD_WITH_OWN_LIBIPTC
- iptables_la_LIBADD  = libiptc/libiptc.la
- iptables_la_DEPENDENCIES = libiptc/libiptc.la
+ iptables_la_LIBADD  = owniptc/libiptc.la
+ iptables_la_DEPENDENCIES = owniptc/libiptc.la
  else
  iptables_la_LIBADD = -liptc
  endif
@@@ -453,22 -438,6 +453,22 @@@ collectd_LDADD += "-dlopen" logfile.l
  collectd_DEPENDENCIES += logfile.la
  endif
  
 +if BUILD_PLUGIN_MADWIFI
 +pkglib_LTLIBRARIES += madwifi.la
 +madwifi_la_SOURCES = madwifi.c madwifi.h
 +madwifi_la_LDFLAGS = -module -avoid-version
 +collectd_LDADD += "-dlopen" madwifi.la
 +collectd_DEPENDENCIES += madwifi.la
 +endif
 +
 +if BUILD_PLUGIN_MATCH_EMPTY_COUNTER
 +pkglib_LTLIBRARIES += match_empty_counter.la
 +match_empty_counter_la_SOURCES = match_empty_counter.c
 +match_empty_counter_la_LDFLAGS = -module -avoid-version
 +collectd_LDADD += "-dlopen" match_empty_counter.la
 +collectd_DEPENDENCIES += match_empty_counter.la
 +endif
 +
  if BUILD_PLUGIN_MATCH_REGEX
  pkglib_LTLIBRARIES += match_regex.la
  match_regex_la_SOURCES = match_regex.c
@@@ -669,18 -638,6 +669,18 @@@ collectd_LDADD += "-dlopen" nut.l
  collectd_DEPENDENCIES += nut.la
  endif
  
 +if BUILD_PLUGIN_OLSRD
 +pkglib_LTLIBRARIES += olsrd.la
 +olsrd_la_SOURCES = olsrd.c
 +olsrd_la_LDFLAGS = -module -avoid-version
 +olsrd_la_LIBADD = 
 +if BUILD_WITH_LIBSOCKET
 +olsrd_la_LIBADD += -lsocket
 +endif
 +collectd_LDADD += "-dlopen" olsrd.la
 +collectd_DEPENDENCIES += olsrd.la
 +endif
 +
  if BUILD_PLUGIN_ONEWIRE
  pkglib_LTLIBRARIES += onewire.la
  onewire_la_SOURCES = onewire.c
@@@ -954,25 -911,11 +954,25 @@@ collectd_LDADD += "-dlopen" thermal.l
  collectd_DEPENDENCIES += thermal.la
  endif
  
 +if BUILD_PLUGIN_TOKYOTYRANT
 +pkglib_LTLIBRARIES += tokyotyrant.la
 +tokyotyrant_la_SOURCES = tokyotyrant.c
 +tokyotyrant_la_CPPFLAGS  = $(AM_CPPFLAGS) $(BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS)
 +tokyotyrant_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS)
 +tokyotyrant_la_LIBADD  = $(BUILD_WITH_LIBTOKYOTYRANT_LIBS)
 +if BUILD_WITH_LIBSOCKET
 +tokyotyrant_la_LIBADD += -lsocket
 +endif
 +collectd_LDADD += "-dlopen" tokyotyrant.la
 +collectd_DEPENDENCIES += tokyotyrant.la
 +endif
 +
  if BUILD_PLUGIN_UNIXSOCK
  pkglib_LTLIBRARIES += unixsock.la
  unixsock_la_SOURCES = unixsock.c \
                      utils_cmd_flush.h utils_cmd_flush.c \
                      utils_cmd_getval.h utils_cmd_getval.c \
 +                    utils_cmd_getthreshold.h utils_cmd_getthreshold.c \
                      utils_cmd_listval.h utils_cmd_listval.c \
                      utils_cmd_putval.h utils_cmd_putval.c \
                      utils_cmd_putnotif.h utils_cmd_putnotif.c
@@@ -1043,21 -986,6 +1043,21 @@@ collectd_LDADD += "-dlopen" wireless.l
  collectd_DEPENDENCIES += wireless.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
 +write_http_la_LDFLAGS = -module -avoid-version
 +write_http_la_CFLAGS = $(AM_CFLAGS)
 +write_http_la_LIBADD =
 +collectd_LDADD += "-dlopen" write_http.la
 +if BUILD_WITH_LIBCURL
 +write_http_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
 +write_http_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
 +endif
 +collectd_DEPENDENCIES += write_http.la
 +endif
 +
  if BUILD_PLUGIN_XMMS
  pkglib_LTLIBRARIES += xmms.la
  xmms_la_SOURCES = xmms.c
@@@ -1068,16 -996,6 +1068,16 @@@ collectd_LDADD += "-dlopen" xmms.l
  collectd_DEPENDENCIES += xmms.la
  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 = -module -avoid-version
 +zfs_arc_la_LIBADD = -lkstat
 +collectd_LDADD += "-dlopen" zfs_arc.la
 +collectd_DEPENDENCIES += zfs_arc.la
 +endif
 +
  
  dist_man_MANS = collectd.1 \
                collectd.conf.5 \
diff --combined src/collectd.conf.in
@@@ -57,7 -57,6 +57,7 @@@ FQDNLookup   tru
  #@BUILD_PLUGIN_BATTERY_TRUE@LoadPlugin battery
  #@BUILD_PLUGIN_BIND_TRUE@LoadPlugin bind
  #@BUILD_PLUGIN_CONNTRACK_TRUE@LoadPlugin conntrack
 +#@BUILD_PLUGIN_COUCHDB_TRUE@LoadPlugin couchdb
  @BUILD_PLUGIN_CPU_TRUE@@BUILD_PLUGIN_CPU_TRUE@LoadPlugin cpu
  #@BUILD_PLUGIN_CPUFREQ_TRUE@LoadPlugin cpufreq
  @LOAD_PLUGIN_CSV@LoadPlugin csv
@@@ -73,7 -72,6 +73,7 @@@
  #@BUILD_PLUGIN_FSCACHE_TRUE@LoadPlugin fscache
  #@BUILD_PLUGIN_GMOND_TRUE@LoadPlugin gmond
  #@BUILD_PLUGIN_HDDTEMP_TRUE@LoadPlugin hddtemp
 +#@BUILD_PLUGIN_HTTP_TRUE@LoadPlugin http
  @BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_PLUGIN_INTERFACE_TRUE@LoadPlugin interface
  #@BUILD_PLUGIN_IPTABLES_TRUE@LoadPlugin iptables
  #@BUILD_PLUGIN_IPMI_TRUE@LoadPlugin ipmi
@@@ -96,7 -94,6 +96,7 @@@
  #@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@LoadPlugin notify_email
  #@BUILD_PLUGIN_NTPD_TRUE@LoadPlugin ntpd
  #@BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut
 +#@BUILD_PLUGIN_OLSRD_TRUE@LoadPlugin olsrd
  #@BUILD_PLUGIN_ONEWIRE_TRUE@LoadPlugin onewire
  #@BUILD_PLUGIN_OPENVPN_TRUE@LoadPlugin openvpn
  #@BUILD_PLUGIN_ORACLE_TRUE@LoadPlugin oracle
  #@BUILD_PLUGIN_TEAMSPEAK2_TRUE@LoadPlugin teamspeak2
  #@BUILD_PLUGIN_TED_TRUE@LoadPlugin ted
  #@BUILD_PLUGIN_THERMAL_TRUE@LoadPlugin thermal
 +#@BUILD_PLUGIN_TOKYOTYRANT_TRUE@LoadPlugin tokyotyrant
  #@BUILD_PLUGIN_UNIXSOCK_TRUE@LoadPlugin unixsock
  #@BUILD_PLUGIN_UPTIME_TRUE@LoadPlugin uptime
  #@BUILD_PLUGIN_USERS_TRUE@LoadPlugin users
  #@BUILD_PLUGIN_VMEM_TRUE@LoadPlugin vmem
  #@BUILD_PLUGIN_VSERVER_TRUE@LoadPlugin vserver
  #@BUILD_PLUGIN_WIRELESS_TRUE@LoadPlugin wireless
 +#@BUILD_PLUGIN_WRITE_HTTP_TRUE@LoadPlugin write_http
  #@BUILD_PLUGIN_XMMS_TRUE@LoadPlugin xmms
 +#@BUILD_PLUGIN_ZFS_ARC_TRUE@LoadPlugin zfs_arc
  
  ##############################################################################
  # Plugin configuration                                                       #
  #  </View>
  #</Plugin>
  
 +#<Plugin couchdb>
 +## See: http://wiki.apache.org/couchdb/Runtime_Statistics
 +#  <URL "http://localhost:5984/_stats">
 +#    Instance "httpd"
 +#    <Key "httpd/requests/count">
 +#      Type "http_requests"
 +#    </Key>
 +#
 +#    <Key "httpd_request_methods/*/count">
 +#      Type "http_request_methods"
 +#    </Key>
 +#
 +#    <Key "httpd_status_codes/*/count">
 +#      Type "http_response_codes"
 +#    </Key>
 +#  </URL>
 +## Database status metrics:
 +#  <URL "http://localhost:5984/_all_dbs">
 +#    Instance "dbs"
 +#    <Key "*/doc_count">
 +#      Type "gauge"
 +#    </Key>
 +#    <Key "*/doc_del_count">
 +#      Type "counter"
 +#    </Key>
 +#    <Key "*/disk_size">
 +#      Type "bytes"
 +#    </Key>
 +#  </URL>
 +#</Plugin>
 +
  #<Plugin csv>
  #     DataDir "@prefix@/var/lib/@PACKAGE_NAME@/csv"
  #     StoreRates false
  #     MountPoint "/home"
  #     FSType "ext3"
  #     IgnoreSelected false
 +#     ReportByDevice false
  #</Plugin>
  
  #<Plugin disk>
  #  TranslateDevicename false
  #</Plugin>
  
 +#<Plugin http>
 +#     URL "http://example.com/collectd-import"
 +#     User "www-user"
 +#     Password "secret"
 +#</Plugin>
 +
  #<Plugin interface>
  #     Interface "eth0"
  #     IgnoreSelected false
  
  #<Plugin "java">
  #     JVMArg "-verbose:jni"
 -#     JVMArg "-Djava.class.path=/opt/collectd/lib/collectd/bindings/java"
 +#     JVMArg "-Djava.class.path=@prefix@/share/collectd/java"
  #
  #     LoadPlugin "org.collectd.java.Foobar"
  #     <Plugin "org.collectd.java.Foobar">
  #     UPS "upsname@hostname:port"
  #</Plugin>
  
 +#<Plugin olsrd>
 +#     Host "127.0.0.1"
 +#     Port "2006"
 +#     CollectLinks "Summary"
 +#     CollectRoutes "Summary"
 +#     CollectTopology "Summary"
 +#</Plugin>
 +
  #<Plugin onewire>
  #     Device "-s localhost:4304"
  #     Sensor "F10FCA000800"
  #       Version 1
  #       Community "community_string"
  #       Collect "std_traffic"
 -#       Inverval 120
 +#       Interval 120
  #   </Host>
  #   <Host "some.server.mydomain.org">
  #       Address "192.168.0.42"
  #     IgnoreSelected false
  #</Plugin>
  
 +#<Plugin tokyotyrant>
 +#     Host "localhost"
 +#     Port "1978"
 +#</Plugin>
 +
  #<Plugin unixsock>
  #     SocketFile "@prefix@/var/run/@PACKAGE_NAME@-unixsock"
  #     SocketGroup "collectd"
  #     Verbose false
  #</Plugin>
  
 +#<Plugin write_http>
 +#     <URL "http://example.com/collectd-post">
 +#             User "collectd"
 +#             Password "weCh3ik0"
 +#     </URL>
 +#</Plugin>
 +
  ##############################################################################
  # Filter configuration                                                       #
  #----------------------------------------------------------------------------#
  # configured at all: All values will be sent to all available write plugins. #
  #----------------------------------------------------------------------------#
  
- #<Chain "Main">
+ #<Chain "PostCache">
  #  Target "write"
  #</Chain>
diff --combined src/curl.c
@@@ -222,29 -222,6 +222,29 @@@ static int cc_config_add_match_dstype (
      else
        dstype = 0;
    }
 +else if (strncasecmp ("Derive", ci->values[0].value.string,
 +        strlen ("Derive")) == 0)
 +  {
 +    dstype = UTILS_MATCH_DS_TYPE_DERIVE;
 +    if (strcasecmp ("DeriveSet", ci->values[0].value.string) == 0)
 +      dstype |= UTILS_MATCH_CF_DERIVE_SET;
 +    else if (strcasecmp ("DeriveAdd", ci->values[0].value.string) == 0)
 +      dstype |= UTILS_MATCH_CF_DERIVE_ADD;
 +    else if (strcasecmp ("DeriveInc", ci->values[0].value.string) == 0)
 +      dstype |= UTILS_MATCH_CF_DERIVE_INC;
 +    else
 +      dstype = 0;
 +  }
 +else if (strncasecmp ("Absolute", ci->values[0].value.string,
 +        strlen ("Absolute")) == 0)
 +  {
 +    dstype = UTILS_MATCH_DS_TYPE_ABSOLUTE;
 +    if (strcasecmp ("AbsoluteSet", ci->values[0].value.string) == 0) /* Absolute DS is reset-on-read so no sense doin anything else but set */
 +      dstype |= UTILS_MATCH_CF_ABSOLUTE_SET;
 +    else
 +      dstype = 0;
 +  }
 +
    else
    {
      dstype = 0;
@@@ -369,6 -346,7 +369,7 @@@ static int cc_page_init_curl (web_page_
        PACKAGE_NAME"/"PACKAGE_VERSION);
    curl_easy_setopt (wp->curl, CURLOPT_ERRORBUFFER, wp->curl_errbuf);
    curl_easy_setopt (wp->curl, CURLOPT_URL, wp->url);
+   curl_easy_setopt (wp->curl, CURLOPT_FOLLOWLOCATION, 1);
  
    if (wp->user != NULL)
    {
diff --combined src/df.c
+++ b/src/df.c
@@@ -1,7 -1,6 +1,7 @@@
  /**
   * collectd - src/df.c
   * Copyright (C) 2005-2007  Florian octo Forster
 + * Copyright (C) 2009       Paul Sadauskas
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the
@@@ -18,7 -17,6 +18,7 @@@
   *
   * Authors:
   *   Florian octo Forster <octo at verplant.org>
 + *   Paul Sadauskas <psadauskas at gmail.com>
   **/
  
  #include "collectd.h"
@@@ -50,16 -48,14 +50,16 @@@ static const char *config_keys[] 
        "MountPoint",
        "FSType",
        "IgnoreSelected",
 -      NULL
 +        "ReportByDevice"
  };
 -static int config_keys_num = 4;
 +static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
  
  static ignorelist_t *il_device = NULL;
  static ignorelist_t *il_mountpoint = NULL;
  static ignorelist_t *il_fstype = NULL;
  
 +static _Bool by_device = false;
 +
  static int df_init (void)
  {
        if (il_device == NULL)
@@@ -96,7 -92,9 +96,7 @@@ static int df_config (const char *key, 
        }
        else if (strcasecmp (key, "IgnoreSelected") == 0)
        {
 -              if ((strcasecmp (value, "True") == 0)
 -                              || (strcasecmp (value, "Yes") == 0)
 -                              || (strcasecmp (value, "On") == 0))
 +              if (IS_TRUE (value))
                {
                        ignorelist_set_invert (il_device, 0);
                        ignorelist_set_invert (il_mountpoint, 0);
                }
                return (0);
        }
 +      else if (strcasecmp (key, "ReportByDevice") == 0)
 +      {
 +              if (IS_TRUE (value))
 +                      by_device = true;
 +
 +              return (0);
 +      }
  
        return (-1);
  }
@@@ -156,7 -147,7 +156,7 @@@ static int df_read (void
        unsigned long long blocksize;
        gauge_t df_free;
        gauge_t df_used;
 -      char mnt_name[256];
 +      char disk_name[256];
  
        mnt_list = NULL;
        if (cu_mount_getlist (&mnt_list) == NULL)
  
        for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
        {
 -              if (strcmp (mnt_ptr->dir, "/") == 0)
 -              {
 -                      sstrncpy (mnt_name, "root", sizeof (mnt_name));
 -              }
 -              else
 -              {
 -                      int i, len;
 -
 -                      sstrncpy (mnt_name, mnt_ptr->dir + 1, sizeof (mnt_name));
 -                      len = strlen (mnt_name);
 -
 -                      for (i = 0; i < len; i++)
 -                              if (mnt_name[i] == '/')
 -                                      mnt_name[i] = '-';
 -              }
 -
+               if (ignorelist_match (il_device,
+                                       (mnt_ptr->spec_device != NULL)
+                                       ? mnt_ptr->spec_device
+                                       : mnt_ptr->device))
+                       continue;
+               if (ignorelist_match (il_mountpoint, mnt_ptr->dir))
+                       continue;
+               if (ignorelist_match (il_fstype, mnt_ptr->type))
+                       continue;
                if (STATANYFS (mnt_ptr->dir, &statbuf) < 0)
                {
                        char errbuf[1024];
                df_free = statbuf.f_bfree * blocksize;
                df_used = (statbuf.f_blocks - statbuf.f_bfree) * blocksize;
  
 -              df_submit (mnt_name, df_used, df_free);
 +              if (by_device) 
 +              {
 +                      /* eg, /dev/hda1  -- strip off the "/dev/" */
 +                      if (strncmp (mnt_ptr->spec_device, "/dev/", strlen ("/dev/")) == 0)
 +                              sstrncpy (disk_name, mnt_ptr->spec_device + strlen ("/dev/"), sizeof (disk_name));
 +                      else
 +                              sstrncpy (disk_name, mnt_ptr->spec_device, sizeof (disk_name));
 +
 +                      if (strlen(disk_name) < 1) 
 +                      {
 +                              DEBUG("df: no device name name for mountpoint %s, skipping", mnt_ptr->dir);
 +                              continue;
 +                      }
 +              } 
 +              else 
 +              {
 +                      if (strcmp (mnt_ptr->dir, "/") == 0)
 +                      {
 +                              sstrncpy (disk_name, "root", sizeof (disk_name));
 +                      }
 +                      else
 +                      {
 +                              int i, len;
 +
 +                              sstrncpy (disk_name, mnt_ptr->dir + 1, sizeof (disk_name));
 +                              len = strlen (disk_name);
 +
 +                              for (i = 0; i < len; i++)
 +                                      if (disk_name[i] == '/')
 +                                              disk_name[i] = '-';
 +                      }
 +              }
 +
-               if (ignorelist_match (il_device,
-                                       (mnt_ptr->spec_device != NULL)
-                                       ? mnt_ptr->spec_device
-                                       : mnt_ptr->device))
-                       continue;
-               if (ignorelist_match (il_mountpoint, mnt_ptr->dir))
-                       continue;
-               if (ignorelist_match (il_fstype, mnt_ptr->type))
-                       continue;
 +              df_submit (disk_name, df_used, df_free);
        }
  
        cu_mount_freelist (mnt_list);
diff --combined src/network.c
@@@ -27,7 -27,6 +27,7 @@@
  #include "configfile.h"
  #include "utils_fbhash.h"
  #include "utils_avltree.h"
 +#include "utils_cache.h"
  
  #include "network.h"
  
  
  #if HAVE_LIBGCRYPT
  # include <gcrypt.h>
+ GCRY_THREAD_OPTION_PTHREAD_IMPL;
  #endif
  
 -/* 1500 - 40 - 8  =  Ethernet packet - IPv6 header - UDP header */
 -/* #define BUFF_SIZE 1452 */
 -
  #ifndef IPV6_ADD_MEMBERSHIP
  # ifdef IPV6_JOIN_GROUP
  #  define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
@@@ -62,6 -65,9 +63,6 @@@
  # endif
  #endif /* !IP_ADD_MEMBERSHIP */
  
 -/* Buffer size to allocate. */
 -#define BUFF_SIZE 1024
 -
  /*
   * Maximum size required for encryption / signing:
   *
@@@ -239,7 -245,7 +240,7 @@@ typedef struct part_encryption_aes256_
  
  struct receive_list_entry_s
  {
 -  char data[BUFF_SIZE];
 +  char *data;
    int  data_len;
    int  fd;
    struct receive_list_entry_s *next;
@@@ -250,7 -256,6 +251,7 @@@ typedef struct receive_list_entry_s rec
   * Private variables
   */
  static int network_config_ttl = 0;
 +static size_t network_config_packet_size = 1024;
  static int network_config_forward = 0;
  
  static sockent_t *sending_sockets = NULL;
@@@ -273,104 -278,133 +274,104 @@@ static int       dispatch_thread_runnin
  static pthread_t dispatch_thread_id;
  
  /* Buffer in which to-be-sent network packets are constructed. */
 -static char             send_buffer[BUFF_SIZE];
 +static char            *send_buffer;
  static char            *send_buffer_ptr;
  static int              send_buffer_fill;
  static value_list_t     send_buffer_vl = VALUE_LIST_STATIC;
  static pthread_mutex_t  send_buffer_lock = PTHREAD_MUTEX_INITIALIZER;
  
 -/* In this cache we store all the values we received, so we can send out only
 - * those values which were *not* received via the network plugin, too. This is
 - * used for the `Forward false' option. */
 -static c_avl_tree_t    *cache_tree = NULL;
 -static pthread_mutex_t  cache_lock = PTHREAD_MUTEX_INITIALIZER;
 -static time_t           cache_flush_last = 0;
 -static int              cache_flush_interval = 1800;
 -
  /*
   * Private functions
   */
 -static int cache_flush (void)
 +static _Bool check_receive_okay (const value_list_t *vl) /* {{{ */
  {
 -      char **keys = NULL;
 -      int    keys_num = 0;
 +  uint64_t time_sent = 0;
 +  int status;
  
 -      char **tmp;
 -      int    i;
 +  status = uc_meta_data_get_unsigned_int (vl,
 +      "network:time_sent", &time_sent);
  
 -      char   *key;
 -      time_t *value;
 -      c_avl_iterator_t *iter;
 +  /* This is a value we already sent. Don't allow it to be received again in
 +   * order to avoid looping. */
 +  if ((status == 0) && (time_sent >= ((uint64_t) vl->time)))
 +    return (false);
  
 -      time_t curtime = time (NULL);
 +  return (true);
 +} /* }}} _Bool check_receive_okay */
  
 -      iter = c_avl_get_iterator (cache_tree);
 -      while (c_avl_iterator_next (iter, (void *) &key, (void *) &value) == 0)
 -      {
 -              if ((curtime - *value) <= cache_flush_interval)
 -                      continue;
 -              tmp = (char **) realloc (keys,
 -                              (keys_num + 1) * sizeof (char *));
 -              if (tmp == NULL)
 -              {
 -                      sfree (keys);
 -                      c_avl_iterator_destroy (iter);
 -                      ERROR ("network plugin: cache_flush: realloc"
 -                                      " failed.");
 -                      return (-1);
 -              }
 -              keys = tmp;
 -              keys[keys_num] = key;
 -              keys_num++;
 -      } /* while (c_avl_iterator_next) */
 -      c_avl_iterator_destroy (iter);
 +static _Bool check_send_okay (const value_list_t *vl) /* {{{ */
 +{
 +  _Bool received = false;
 +  int status;
  
 -      for (i = 0; i < keys_num; i++)
 -      {
 -              if (c_avl_remove (cache_tree, keys[i], (void *) &key,
 -                                      (void *) &value) != 0)
 -              {
 -                      WARNING ("network plugin: cache_flush: c_avl_remove"
 -                                      " (%s) failed.", keys[i]);
 -                      continue;
 -              }
 +  if (network_config_forward != 0)
 +    return (true);
  
 -              sfree (key);
 -              sfree (value);
 -      }
 +  if (vl->meta == NULL)
 +    return (true);
  
 -      sfree (keys);
 +  status = meta_data_get_boolean (vl->meta, "network:received", &received);
 +  if (status == -ENOENT)
 +    return (true);
 +  else if (status != 0)
 +  {
 +    ERROR ("network plugin: check_send_okay: meta_data_get_boolean failed "
 +      "with status %i.", status);
 +    return (true);
 +  }
  
 -      DEBUG ("network plugin: cache_flush: Removed %i %s",
 -                      keys_num, (keys_num == 1) ? "entry" : "entries");
 -      cache_flush_last = curtime;
 -      return (0);
 -} /* int cache_flush */
 +  /* By default, only *send* value lists that were not *received* by the
 +   * network plugin. */
 +  return (!received);
 +} /* }}} _Bool check_send_okay */
  
 -static int cache_check (const value_list_t *vl)
 +static int network_dispatch_values (value_list_t *vl) /* {{{ */
  {
 -      char key[1024];
 -      time_t *value = NULL;
 -      int retval = -1;
 +  int status;
  
 -      if (cache_tree == NULL)
 -              return (-1);
 +  if ((vl->time <= 0)
 +      || (strlen (vl->host) <= 0)
 +      || (strlen (vl->plugin) <= 0)
 +      || (strlen (vl->type) <= 0))
 +    return (-EINVAL);
  
 -      if (format_name (key, sizeof (key), vl->host, vl->plugin,
 -                              vl->plugin_instance, vl->type, vl->type_instance))
 -              return (-1);
 +  if (!check_receive_okay (vl))
 +  {
 +#if COLLECT_DEBUG
 +        char name[6*DATA_MAX_NAME_LEN];
 +        FORMAT_VL (name, sizeof (name), vl);
 +        name[sizeof (name) - 1] = 0;
 +        DEBUG ("network plugin: network_dispatch_values: "
 +            "NOT dispatching %s.", name);
 +#endif
 +    return (0);
 +  }
  
 -      pthread_mutex_lock (&cache_lock);
 +  assert (vl->meta == NULL);
  
 -      if (c_avl_get (cache_tree, key, (void *) &value) == 0)
 -      {
 -              if (*value < vl->time)
 -              {
 -                      *value = vl->time;
 -                      retval = 0;
 -              }
 -              else
 -              {
 -                      DEBUG ("network plugin: cache_check: *value = %i >= vl->time = %i",
 -                                      (int) *value, (int) vl->time);
 -                      retval = 1;
 -              }
 -      }
 -      else
 -      {
 -              char *key_copy = strdup (key);
 -              value = malloc (sizeof (time_t));
 -              if ((key_copy != NULL) && (value != NULL))
 -              {
 -                      *value = vl->time;
 -                      c_avl_insert (cache_tree, key_copy, value);
 -                      retval = 0;
 -              }
 -              else
 -              {
 -                      sfree (key_copy);
 -                      sfree (value);
 -              }
 -      }
 +  vl->meta = meta_data_create ();
 +  if (vl->meta == NULL)
 +  {
 +    ERROR ("network plugin: meta_data_create failed.");
 +    return (-ENOMEM);
 +  }
  
 -      if ((time (NULL) - cache_flush_last) > cache_flush_interval)
 -              cache_flush ();
 +  status = meta_data_add_boolean (vl->meta, "network:received", true);
 +  if (status != 0)
 +  {
 +    ERROR ("network plugin: meta_data_add_boolean failed.");
 +    meta_data_destroy (vl->meta);
 +    vl->meta = NULL;
 +    return (status);
 +  }
  
 -      pthread_mutex_unlock (&cache_lock);
 +  plugin_dispatch_values (vl);
  
 -      return (retval);
 -} /* int cache_check */
 +  meta_data_destroy (vl->meta);
 +  vl->meta = NULL;
 +
 +  return (0);
 +} /* }}} int network_dispatch_values */
  
  #if HAVE_LIBGCRYPT
  static gcry_cipher_hd_t network_get_aes256_cypher (sockent_t *se, /* {{{ */
@@@ -494,34 -528,17 +495,34 @@@ static int write_part_values (char **re
  
        for (i = 0; i < num_values; i++)
        {
 -              if (ds->ds[i].type == DS_TYPE_COUNTER)
 +              pkg_values_types[i] = (uint8_t) ds->ds[i].type;
 +              switch (ds->ds[i].type)
                {
 -                      pkg_values_types[i] = DS_TYPE_COUNTER;
 -                      pkg_values[i].counter = htonll (vl->values[i].counter);
 -              }
 -              else
 -              {
 -                      pkg_values_types[i] = DS_TYPE_GAUGE;
 -                      pkg_values[i].gauge = htond (vl->values[i].gauge);
 -              }
 -      }
 +                      case DS_TYPE_COUNTER:
 +                              pkg_values[i].counter = htonll (vl->values[i].counter);
 +                              break;
 +
 +                      case DS_TYPE_GAUGE:
 +                              pkg_values[i].gauge = htond (vl->values[i].gauge);
 +                              break;
 +
 +                      case DS_TYPE_DERIVE:
 +                              pkg_values[i].derive = htonll (vl->values[i].derive);
 +                              break;
 +
 +                      case DS_TYPE_ABSOLUTE:
 +                              pkg_values[i].absolute = htonll (vl->values[i].absolute);
 +                              break;
 +
 +                      default:
 +                              free (pkg_values_types);
 +                              free (pkg_values);
 +                              ERROR ("network plugin: write_part_values: "
 +                                              "Unknown data source type: %i",
 +                                              ds->ds[i].type);
 +                              return (-1);
 +              } /* switch (ds->ds[i].type) */
 +      } /* for (num_values) */
  
        /*
         * Use `memcpy' to write everything to the buffer, because the pointer
@@@ -697,32 -714,10 +698,32 @@@ static int parse_part_values (void **re
  
        for (i = 0; i < pkg_numval; i++)
        {
 -              if (pkg_types[i] == DS_TYPE_COUNTER)
 -                      pkg_values[i].counter = ntohll (pkg_values[i].counter);
 -              else if (pkg_types[i] == DS_TYPE_GAUGE)
 -                      pkg_values[i].gauge = ntohd (pkg_values[i].gauge);
 +              switch (pkg_types[i])
 +              {
 +                case DS_TYPE_COUNTER:
 +                  pkg_values[i].counter = (counter_t) ntohll (pkg_values[i].counter);
 +                  break;
 +
 +                case DS_TYPE_GAUGE:
 +                  pkg_values[i].gauge = (gauge_t) ntohd (pkg_values[i].gauge);
 +                  break;
 +
 +                case DS_TYPE_DERIVE:
 +                  pkg_values[i].derive = (derive_t) ntohll (pkg_values[i].derive);
 +                  break;
 +
 +                case DS_TYPE_ABSOLUTE:
 +                  pkg_values[i].absolute = (absolute_t) ntohll (pkg_values[i].absolute);
 +                  break;
 +
 +                default:
 +                  sfree (pkg_types);
 +                  sfree (pkg_values);
 +                  NOTICE ("network plugin: parse_part_values: "
 +                      "Don't know how to handle data source type %"PRIu8,
 +                      pkg_types[i]);
 +                  return (-1);
 +              } /* switch (pkg_types[i]) */
        }
  
        *ret_buffer     = buffer;
@@@ -1308,10 -1303,23 +1309,10 @@@ static int parse_packet (sockent_t *se
                {
                        status = parse_part_values (&buffer, &buffer_size,
                                        &vl.values, &vl.values_len);
 -
                        if (status != 0)
                                break;
  
 -                      if ((vl.time > 0)
 -                                      && (strlen (vl.host) > 0)
 -                                      && (strlen (vl.plugin) > 0)
 -                                      && (strlen (vl.type) > 0)
 -                                      && (cache_check (&vl) == 0))
 -                      {
 -                              plugin_dispatch_values (&vl);
 -                      }
 -                      else
 -                      {
 -                              DEBUG ("network plugin: parse_packet:"
 -                                              " NOT dispatching values");
 -                      }
 +                      network_dispatch_values (&vl);
  
                        sfree (vl.values);
                }
                }
        } /* while (buffer_size > sizeof (part_header_t)) */
  
 +      if (status == 0 && buffer_size > 0)
 +              WARNING ("network plugin: parse_packet: Received truncated "
 +                              "packet, try increasing `MaxPacketSize'");
 +
        return (status);
  } /* }}} int parse_packet */
  
@@@ -1958,7 -1962,7 +1959,7 @@@ static void *dispatch_thread (void __at
      /* Lock and wait for more data to come in */
      pthread_mutex_lock (&receive_list_lock);
      while ((listen_loop == 0)
 -      && (receive_list_head == NULL))
 +        && (receive_list_head == NULL))
        pthread_cond_wait (&receive_list_cond, &receive_list_lock);
  
      /* Remove the head entry and unlock */
  
      if (se == NULL)
      {
 -          ERROR ("network plugin: Got packet from FD %i, but can't "
 -                          "find an appropriate socket entry.",
 -                          ent->fd);
 -          sfree (ent);
 -          continue;
 +      ERROR ("network plugin: Got packet from FD %i, but can't "
 +          "find an appropriate socket entry.",
 +          ent->fd);
 +      sfree (ent->data);
 +      sfree (ent);
 +      continue;
      }
  
      parse_packet (se, ent->data, ent->data_len, /* flags = */ 0);
 +    sfree (ent->data);
      sfree (ent);
    } /* while (42) */
  
  
  static int network_receive (void) /* {{{ */
  {
 -      char buffer[BUFF_SIZE];
 +      char buffer[network_config_packet_size];
        int  buffer_len;
  
        int i;
                                return (-1);
                        }
                        memset (ent, 0, sizeof (receive_list_entry_t));
 +                      ent->data = malloc (network_config_packet_size);
 +                      if (ent->data == NULL)
 +                      {
 +                              ERROR ("network plugin: malloc failed.");
 +                              return (-1);
 +                      }
                        ent->fd = listen_sockets_pollfd[i].fd;
                        ent->next = NULL;
  
 -                      /* Hopefully this be optimized out by the compiler. It
 -                       * might help prevent stupid bugs in the future though.
 -                       */
 -                      assert (sizeof (ent->data) == sizeof (buffer));
 -
                        memcpy (ent->data, buffer, buffer_len);
                        ent->data_len = buffer_len;
  
@@@ -2133,7 -2134,7 +2134,7 @@@ static void *receive_thread (void __att
  
  static void network_init_buffer (void)
  {
 -      memset (send_buffer, 0, sizeof (send_buffer));
 +      memset (send_buffer, 0, network_config_packet_size);
        send_buffer_ptr = send_buffer;
        send_buffer_fill = 0;
  
@@@ -2434,25 -2435,18 +2435,25 @@@ static int network_write (const data_se
  {
        int status;
  
 -      /* If the value is already in the cache, we have received it via the
 -       * network. We write it again if forwarding is activated. It's then in
 -       * the cache and should we receive it again we will ignore it. */
 -      status = cache_check (vl);
 -      if ((network_config_forward == 0)
 -                      && (status != 0))
 -              return (0);
 +      if (!check_send_okay (vl))
 +      {
 +#if COLLECT_DEBUG
 +        char name[6*DATA_MAX_NAME_LEN];
 +        FORMAT_VL (name, sizeof (name), vl);
 +        name[sizeof (name) - 1] = 0;
 +        DEBUG ("network plugin: network_write: "
 +            "NOT sending %s.", name);
 +#endif
 +        return (0);
 +      }
 +
 +      uc_meta_data_add_unsigned_int (vl,
 +          "network:time_sent", (uint64_t) vl->time);
  
        pthread_mutex_lock (&send_buffer_lock);
  
        status = add_to_buffer (send_buffer_ptr,
 -                      sizeof (send_buffer) - (send_buffer_fill + BUFF_SIG_SIZE),
 +                      network_config_packet_size - (send_buffer_fill + BUFF_SIG_SIZE),
                        &send_buffer_vl,
                        ds, vl);
        if (status >= 0)
                flush_buffer ();
  
                status = add_to_buffer (send_buffer_ptr,
 -                              sizeof (send_buffer) - (send_buffer_fill + BUFF_SIG_SIZE),
 +                              network_config_packet_size - (send_buffer_fill + BUFF_SIG_SIZE),
                                &send_buffer_vl,
                                ds, vl);
  
                ERROR ("network plugin: Unable to append to the "
                                "buffer for some weird reason");
        }
 -      else if ((sizeof (send_buffer) - send_buffer_fill) < 15)
 +      else if ((network_config_packet_size - send_buffer_fill) < 15)
        {
                flush_buffer ();
        }
@@@ -2553,24 -2547,6 +2554,24 @@@ static int network_config_set_ttl (cons
    return (0);
  } /* }}} int network_config_set_ttl */
  
 +static int network_config_set_buffer_size (const oconfig_item_t *ci) /* {{{ */
 +{
 +  int tmp;
 +  if ((ci->values_num != 1)
 +      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
 +  {
 +    WARNING ("network plugin: The `MaxPacketSize' config option needs exactly "
 +        "one numeric argument.");
 +    return (-1);
 +  }
 +
 +  tmp = (int) ci->values[0].value.number;
 +  if ((tmp >= 1024) && (tmp <= 65535))
 +    network_config_packet_size = tmp;
 +
 +  return (0);
 +} /* }}} int network_config_set_buffer_size */
 +
  #if HAVE_LIBGCRYPT
  static int network_config_set_string (const oconfig_item_t *ci, /* {{{ */
      char **ret_string)
@@@ -2780,6 -2756,24 +2781,6 @@@ static int network_config_add_server (c
    return (0);
  } /* }}} int network_config_add_server */
  
 -static int network_config_set_cache_flush (const oconfig_item_t *ci) /* {{{ */
 -{
 -  int tmp;
 -  if ((ci->values_num != 1)
 -      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
 -  {
 -    WARNING ("network plugin: The `CacheFlush' config option needs exactly "
 -        "one numeric argument.");
 -    return (-1);
 -  }
 -
 -  tmp = (int) ci->values[0].value.number;
 -  if (tmp > 0)
 -    cache_flush_interval = tmp;
 -
 -  return (0);
 -} /* }}} int network_config_set_cache_flush */
 -
  static int network_config (oconfig_item_t *ci) /* {{{ */
  {
    int i;
        network_config_add_server (child);
      else if (strcasecmp ("TimeToLive", child->key) == 0)
        network_config_set_ttl (child);
 +    else if (strcasecmp ("MaxPacketSize", child->key) == 0)
 +      network_config_set_buffer_size (child);
      else if (strcasecmp ("Forward", child->key) == 0)
        network_config_set_boolean (child, &network_config_forward);
      else if (strcasecmp ("CacheFlush", child->key) == 0)
 -      network_config_set_cache_flush (child);
 +      /* no op for backwards compatibility only */;
      else
      {
        WARNING ("network plugin: Option `%s' is not allowed here.",
  static int network_notification (const notification_t *n,
                user_data_t __attribute__((unused)) *user_data)
  {
 -  char  buffer[BUFF_SIZE];
 +  char  buffer[network_config_packet_size];
    char *buffer_ptr = buffer;
    int   buffer_free = sizeof (buffer);
    int   status;
@@@ -2912,7 -2904,19 +2913,7 @@@ static int network_shutdown (void
        if (send_buffer_fill > 0)
                flush_buffer ();
  
 -      if (cache_tree != NULL)
 -      {
 -              void *key;
 -              void *value;
 -
 -              while (c_avl_pick (cache_tree, &key, &value) == 0)
 -              {
 -                      sfree (key);
 -                      sfree (value);
 -              }
 -              c_avl_destroy (cache_tree);
 -              cache_tree = NULL;
 -      }
 +      sfree (send_buffer);
  
        /* TODO: Close `sending_sockets' */
  
        plugin_unregister_write ("network");
        plugin_unregister_shutdown ("network");
  
 -      /* Let the init function do it's move again ;) */
 -      cache_flush_last = 0;
 -
        return (0);
  } /* int network_shutdown */
  
  static int network_init (void)
  {
 +      static _Bool have_init = false;
 +
        /* Check if we were already initialized. If so, just return - there's
         * nothing more to do (for now, that is). */
 -      if (cache_flush_last != 0)
 +      if (have_init)
                return (0);
 +      have_init = true;
  
+ #if HAVE_LIBGCRYPT
+       gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+       gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0);
+       gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+ #endif
        plugin_register_shutdown ("network", network_shutdown);
  
 +      send_buffer = malloc (network_config_packet_size);
 +      if (send_buffer == NULL)
 +      {
 +              ERROR ("network plugin: malloc failed.");
 +              return (-1);
 +      }
        network_init_buffer ();
  
 -      cache_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
 -      cache_flush_last = time (NULL);
 -
        /* setup socket(s) and so on */
        if (sending_sockets != NULL)
        {
@@@ -3015,8 -3022,11 +3022,8 @@@ static int network_flush (int timeout
  {
        pthread_mutex_lock (&send_buffer_lock);
  
 -      if (((time (NULL) - cache_flush_last) >= timeout)
 -                      && (send_buffer_fill > 0))
 -      {
 -              flush_buffer ();
 -      }
 +      if (send_buffer_fill > 0)
 +        flush_buffer ();
  
        pthread_mutex_unlock (&send_buffer_lock);
  
diff --combined src/plugin.c
@@@ -888,6 -888,14 +888,14 @@@ int plugin_unregister_read (const char 
        }
  
        le = llist_search (read_list, name);
+       if (le == NULL)
+       {
+               pthread_mutex_unlock (&read_lock);
+               WARNING ("plugin_unregister_read: No such read function: %s",
+                               name);
+               return (-ENOENT);
+       }
        llist_remove (read_list, le);
  
        rf = le->value;
@@@ -1205,14 -1213,8 +1213,14 @@@ void plugin_shutdown_all (void
                (*callback) ();
        }
  
 -      destroy_all_callbacks (&list_write);
 +      /* 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
 +       * the real free function when registering the write callback. This way
 +       * the data isn't freed twice. */
        destroy_all_callbacks (&list_flush);
 +      destroy_all_callbacks (&list_write);
 +
        destroy_all_callbacks (&list_notification);
        destroy_all_callbacks (&list_shutdown);
        destroy_all_callbacks (&list_log);
@@@ -1228,8 -1230,6 +1236,8 @@@ int plugin_dispatch_values (value_list_
  
        data_set_t *ds;
  
 +      int free_meta_data = 0;
 +
        if ((vl == NULL) || (vl->type[0] == 0)
                        || (vl->values == NULL) || (vl->values_len < 1))
        {
                return (-1);
        }
  
 +      /* Free meta data only if the calling function didn't specify any. In
 +       * this case matches and targets may add some and the calling function
 +       * may not expect (and therefore free) that data. */
 +      if (vl->meta == NULL)
 +              free_meta_data = 1;
 +
        if (list_write == NULL)
                c_complain_once (LOG_WARNING, &no_write_complaint,
                                "plugin_dispatch_values: No write callback has been "
                vl->values_len = saved_values_len;
        }
  
 +      if ((free_meta_data != 0) && (vl->meta != NULL))
 +      {
 +              meta_data_destroy (vl->meta);
 +              vl->meta = NULL;
 +      }
 +
        return (0);
  } /* int plugin_dispatch_values */
  
diff --combined src/powerdns.c
@@@ -164,13 -164,13 +164,13 @@@ statname_lookup_t lookup_table[] = /* {
    {"latency",                "latency",      NULL},
  
    /* Other stuff.. */
-   {"corrupt-packets",        "io_packets",   "corrupt"},
+   {"corrupt-packets",        "ipt_packets",  "corrupt"},
    {"deferred-cache-inserts", "counter",      "cache-deferred_insert"},
    {"deferred-cache-lookup",  "counter",      "cache-deferred_lookup"},
    {"qsize-a",                "cache_size",   "answers"},
    {"qsize-q",                "cache_size",   "questions"},
-   {"servfail-packets",       "io_packets",   "servfail"},
-   {"timedout-packets",       "io_packets",   "timeout"},
+   {"servfail-packets",       "ipt_packets",  "servfail"},
+   {"timedout-packets",       "ipt_packets",  "timeout"},
    {"udp4-answers",           "dns_answer",   "udp4"},
    {"udp4-queries",           "dns_question", "queries-udp4"},
    {"udp6-answers",           "dns_answer",   "udp6"},
@@@ -289,7 -289,7 +289,7 @@@ static void submit (const char *plugin_
      return;
    }
  
 -  if (0 != parse_value (value, &values[0], ds->ds[0]))
 +  if (0 != parse_value (value, &values[0], ds->ds[0].type))
    {
      ERROR ("powerdns plugin: Cannot convert `%s' "
          "to a number.", value);
@@@ -361,6 -361,18 +361,18 @@@ static int powerdns_get_data_dgram (lis
        break;
      }
  
+     struct timeval timeout;
+     timeout.tv_sec=2;
+     if (timeout.tv_sec < interval_g * 3 / 4)
+       timeout.tv_sec = interval_g * 3 / 4;
+     timeout.tv_usec=0;
+     status = setsockopt (sd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof (timeout));
+     if (status != 0)
+     {
+       FUNC_ERROR ("setsockopt");
+       break;
+     }
      status = connect (sd, (struct sockaddr *) &item->sockaddr,
          sizeof (item->sockaddr));
      if (status != 0)
@@@ -892,11 -904,18 +904,18 @@@ static int powerdns_config (oconfig_ite
        powerdns_config_add_server (option);
      else if (strcasecmp ("LocalSocket", option->key) == 0)
      {
-       char *temp = strdup (option->key);
-       if (temp == NULL)
-         return (1);
-       sfree (local_sockpath);
-       local_sockpath = temp;
+       if ((option->values_num != 1) || (option->values[0].type != OCONFIG_TYPE_STRING))
+       {
+         WARNING ("powerdns plugin: `%s' needs exactly one string argument.", option->key);
+       }
+       else
+       {
+         char *temp = strdup (option->values[0].value.string);
+         if (temp == NULL)
+           return (1);
+         sfree (local_sockpath);
+         local_sockpath = temp;
+       }
      }
      else
      {