Merge branch 'collectd-4.4' into collectd-4.5
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>
Thu, 16 Oct 2008 20:13:33 +0000 (22:13 +0200)
committerFlorian Forster <octo@leeloo.lan.home.verplant.org>
Thu, 16 Oct 2008 20:13:33 +0000 (22:13 +0200)
Conflicts:

ChangeLog
version-gen.sh

1  2 
ChangeLog
contrib/collection.cgi
src/Makefile.am
src/collectd.h
src/perl.c
src/types.db

diff --combined ChangeLog
+++ b/ChangeLog
@@@ -1,34 -1,26 +1,57 @@@
 +2008-09-04, Version 4.5.0
 +      * collectd: Added the ability to flush certain identifiers.
 +      * collectd: The concept of `notification meta data' has been
 +        introduced.
 +      * filecount plugin: The new filecount plugin counts the number of
 +        files in a directory and its subdirectories.
 +      * ipmi plugin: Sensor names have been changed to ensure unique names.
 +        Notifications upon added and removed sensors can now be generated.
 +      * notify_desktop plugin: This new plugin sends notifications to the
 +        X desktop using the structure defined in the `Desktop Notification
 +        Specification'.
 +      * notify_email plugin: This new plugin sends out notifications via
 +        email, using the `esmtp' library.
 +      * onewire plugin: The new experimental(!) onewire plugin reads values,
 +        such as temperatures, from sensors connected to the computer via the
 +        onewire bus.
 +      * perl plugin: Improved synchronized access to internal data structures
 +        and fixed a possible dead-lock.
 +      * perl plugin: Added the ability to flush certain identifiers and marked
 +        plugin_flush_all() and plugin_flush_one() as deprecated in favor of
 +        plugin_flush().
 +      * perl plugin: Added the ability to configure Perl plugins.
 +      * postgresql plugin: The new postgresql plugin collects statistics
 +        about or from a PostgreSQL database.
 +      * processes plugin: The `ProcessMatch' option has been added.
 +      * rrdtool plugin: Implement throttling of the `update queue' to lessen
 +        IO load.
 +      * tcpconns plugin: This plugin has been ported to OpenBSD.
 +      * thermal plugin: The new thermal plugin collects system temperatures
 +        using Linux ACPI thermal zone data.
 +
+ 2008-10-16, Version 4.4.4
+       * build system: Change `--enable-<plugin>' to abort with an error if
+         dependencies are not met. Thanks to Bruno PrĂ©mont for the patch.
+         Also, the poisoning of various string functions has been restricted
+         to debug builds.
+       * collectd: Fix a memory leak in the global value cache. With every
+         *missing* value a couple of bytes would be leaked. Another memory
+         leak in the configuration handling code has been fixed. Thanks to
+         Niraj Tolia for reporting these issues.
+       * collectd: Fix an off-by-one error in the ignorelist functionality.
+         When using regular expressions, the last character would be missing,
+         possibly matching differently from what one would expect.
+       * collectdmon: Don't block SIGCHLD. This fixes a potential portability
+         problem.
+       * collectd-nagios: Fix handling of the `-d' option. Thanks to Fabian
+         Linzberger for reporting the but.
+       * network plugin: Fix a memory leak in the configuration handling
+         code. Thanks to Niraj Tolia for reporting this issue.
+       * perl plugin: Log an error message if bootstrapping `Collectd' fails.
+       * tail plugin: Call `clearerr' after reading an EOF. This fixes
+         problems with some `libc's. Thanks to Matthias Lay for reporting the
+         bug.
  2008-09-01, Version 4.4.3
        * collectd: Fix a memory leak in the threshold checking code.
        * memcached plugin: Fix a too short timeout and a related file
diff --combined contrib/collection.cgi
@@@ -1016,6 -1016,18 +1016,18 @@@ sub load_graph_definition
      'GPRINT:max:MAX:%5.1lf%sAh Max,',
      'GPRINT:avg:LAST:%5.1lf%sAh Last\l'
      ],
+     connections => ['-v', 'Connections',
+     'DEF:avg={file}:value:AVERAGE',
+     'DEF:min={file}:value:MIN',
+     'DEF:max={file}:value:MAX',
+     "AREA:max#$HalfBlue",
+     "AREA:min#$Canvas",
+     "LINE1:avg#$FullBlue:Connections",
+     'GPRINT:min:MIN:%4.1lf Min,',
+     'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+     'GPRINT:max:MAX:%4.1lf Max,',
+     'GPRINT:avg:LAST:%4.1lf Last\l'
+     ],
      cpu => ['-v', 'CPU load',
      'DEF:avg={file}:value:AVERAGE',
      'DEF:min={file}:value:MIN',
      'GPRINT:ping_avg:AVERAGE:%4.1lf ms Avg,',
      'GPRINT:ping_max:MAX:%4.1lf ms Max,',
      'GPRINT:ping_avg:LAST:%4.1lf ms Last'],
 +    pg_blks => ['DEF:pg_blks_avg={file}:value:AVERAGE',
 +    'DEF:pg_blks_min={file}:value:MIN',
 +    'DEF:pg_blks_max={file}:value:MAX',
 +    "AREA:pg_blks_max#$HalfBlue",
 +    "AREA:pg_blks_min#$Canvas",
 +    "LINE1:pg_blks_avg#$FullBlue:Blocks",
 +    'GPRINT:pg_blks_min:MIN:%4.1lf%s Min,',
 +    'GPRINT:pg_blks_avg:AVERAGE:%4.1lf%s Avg,',
 +    'GPRINT:pg_blks_max:MAX:%4.1lf%s Max,',
 +    'GPRINT:pg_blks_avg:LAST:%4.1lf%s Last'],
 +    pg_db_size => ['DEF:pg_db_size_avg={file}:value:AVERAGE',
 +    'DEF:pg_db_size_min={file}:value:MIN',
 +    'DEF:pg_db_size_max={file}:value:MAX',
 +    "AREA:pg_db_size_max#$HalfBlue",
 +    "AREA:pg_db_size_min#$Canvas",
 +    "LINE1:pg_db_size_avg#$FullBlue:Bytes",
 +    'GPRINT:pg_db_size_min:MIN:%4.1lf%s Min,',
 +    'GPRINT:pg_db_size_avg:AVERAGE:%4.1lf%s Avg,',
 +    'GPRINT:pg_db_size_max:MAX:%4.1lf%s Max,',
 +    'GPRINT:pg_db_size_avg:LAST:%4.1lf%s Last'],
 +    pg_n_tup_c => ['DEF:pg_n_tup_avg={file}:value:AVERAGE',
 +    'DEF:pg_n_tup_min={file}:value:MIN',
 +    'DEF:pg_n_tup_max={file}:value:MAX',
 +    "AREA:pg_n_tup_max#$HalfBlue",
 +    "AREA:pg_n_tup_min#$Canvas",
 +    "LINE1:pg_n_tup_avg#$FullBlue:Tuples",
 +    'GPRINT:pg_n_tup_min:MIN:%4.1lf%s Min,',
 +    'GPRINT:pg_n_tup_avg:AVERAGE:%4.1lf%s Avg,',
 +    'GPRINT:pg_n_tup_max:MAX:%4.1lf%s Max,',
 +    'GPRINT:pg_n_tup_avg:LAST:%4.1lf%s Last'],
 +    pg_n_tup_g => ['DEF:pg_n_tup_avg={file}:value:AVERAGE',
 +    'DEF:pg_n_tup_min={file}:value:MIN',
 +    'DEF:pg_n_tup_max={file}:value:MAX',
 +    "AREA:pg_n_tup_max#$HalfBlue",
 +    "AREA:pg_n_tup_min#$Canvas",
 +    "LINE1:pg_n_tup_avg#$FullBlue:Tuples",
 +    'GPRINT:pg_n_tup_min:MIN:%4.1lf%s Min,',
 +    'GPRINT:pg_n_tup_avg:AVERAGE:%4.1lf%s Avg,',
 +    'GPRINT:pg_n_tup_max:MAX:%4.1lf%s Max,',
 +    'GPRINT:pg_n_tup_avg:LAST:%4.1lf%s Last'],
 +    pg_numbackends => ['DEF:pg_numbackends_avg={file}:value:AVERAGE',
 +    'DEF:pg_numbackends_min={file}:value:MIN',
 +    'DEF:pg_numbackends_max={file}:value:MAX',
 +    "AREA:pg_numbackends_max#$HalfBlue",
 +    "AREA:pg_numbackends_min#$Canvas",
 +    "LINE1:pg_numbackends_avg#$FullBlue:Backends",
 +    'GPRINT:pg_numbackends_min:MIN:%4.1lf%s Min,',
 +    'GPRINT:pg_numbackends_avg:AVERAGE:%4.1lf%s Avg,',
 +    'GPRINT:pg_numbackends_max:MAX:%4.1lf%s Max,',
 +    'GPRINT:pg_numbackends_avg:LAST:%4.1lf%s Last'],
 +    pg_scan => ['DEF:pg_scan_avg={file}:value:AVERAGE',
 +    'DEF:pg_scan_min={file}:value:MIN',
 +    'DEF:pg_scan_max={file}:value:MAX',
 +    "AREA:pg_scan_max#$HalfBlue",
 +    "AREA:pg_scan_min#$Canvas",
 +    "LINE1:pg_scan_avg#$FullBlue:Scans",
 +    'GPRINT:pg_scan_min:MIN:%4.1lf%s Min,',
 +    'GPRINT:pg_scan_avg:AVERAGE:%4.1lf%s Avg,',
 +    'GPRINT:pg_scan_max:MAX:%4.1lf%s Max,',
 +    'GPRINT:pg_scan_avg:LAST:%4.1lf%s Last'],
 +    pg_xact => ['DEF:pg_xact_avg={file}:value:AVERAGE',
 +    'DEF:pg_xact_min={file}:value:MIN',
 +    'DEF:pg_xact_max={file}:value:MAX',
 +    "AREA:pg_xact_max#$HalfBlue",
 +    "AREA:pg_xact_min#$Canvas",
 +    "LINE1:pg_xact_avg#$FullBlue:Transactions",
 +    'GPRINT:pg_xact_min:MIN:%4.1lf%s Min,',
 +    'GPRINT:pg_xact_avg:AVERAGE:%4.1lf%s Avg,',
 +    'GPRINT:pg_xact_max:MAX:%4.1lf%s Max,',
 +    'GPRINT:pg_xact_avg:LAST:%4.1lf%s Last'],
      power => ['-v', 'Watt',
      'DEF:avg={file}:value:AVERAGE',
      'DEF:min={file}:value:MIN',
diff --combined src/Makefile.am
@@@ -21,7 -21,6 +21,7 @@@ if BUILD_FEATURE_DAEMO
  AM_CPPFLAGS += -DPIDFILE='"${localstatedir}/run/${PACKAGE_NAME}.pid"'
  endif
  AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"'
 +AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
  
  sbin_PROGRAMS = collectd collectdmon
  bin_PROGRAMS = collectd-nagios
@@@ -32,7 -31,6 +32,7 @@@ collectd_SOURCES = collectd.c collectd.
                   plugin.c plugin.h \
                   utils_avltree.c utils_avltree.h \
                   utils_cache.c utils_cache.h \
 +                 utils_complain.c utils_complain.h \
                   utils_ignorelist.c utils_ignorelist.h \
                   utils_llist.c utils_llist.h \
                   utils_tail_match.c utils_tail_match.h \
@@@ -43,7 -41,7 +43,7 @@@
                   types_list.c types_list.h
  
  collectd_CPPFLAGS =  $(AM_CPPFLAGS) $(LTDLINCL)
 -collectd_CFLAGS =
 +collectd_CFLAGS = $(AM_CFLAGS)
  collectd_LDFLAGS = -export-dynamic
  collectd_LDADD =
  collectd_DEPENDENCIES =
@@@ -97,7 -95,7 +97,7 @@@ if BUILD_PLUGIN_APACH
  pkglib_LTLIBRARIES += apache.la
  apache_la_SOURCES = apache.c
  apache_la_LDFLAGS = -module -avoid-version
 -apache_la_CFLAGS =
 +apache_la_CFLAGS = $(AM_CFLAGS)
  apache_la_LIBADD =
  collectd_LDADD += "-dlopen" apache.la
  if BUILD_WITH_LIBCURL
@@@ -130,10 -128,9 +130,10 @@@ if BUILD_PLUGIN_ASCEN
  pkglib_LTLIBRARIES += ascent.la
  ascent_la_SOURCES = ascent.c
  ascent_la_LDFLAGS = -module -avoid-version
 -ascent_la_CFLAGS = $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
 +ascent_la_CFLAGS = $(AM_CFLAGS) \
 +              $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
  ascent_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
- collectd_LDADD += "-dlopen" apache.la
+ collectd_LDADD += "-dlopen" ascent.la
  collectd_DEPENDENCIES += ascent.la
  endif
  
@@@ -151,7 -148,7 +151,7 @@@ endi
  if BUILD_PLUGIN_CPU
  pkglib_LTLIBRARIES += cpu.la
  cpu_la_SOURCES = cpu.c
 -cpu_la_CFLAGS =
 +cpu_la_CFLAGS = $(AM_CFLAGS)
  cpu_la_LDFLAGS = -module -avoid-version
  cpu_la_LIBADD = 
  if BUILD_WITH_LIBKSTAT
@@@ -195,7 -192,7 +195,7 @@@ endi
  if BUILD_PLUGIN_DISK
  pkglib_LTLIBRARIES += disk.la
  disk_la_SOURCES = disk.c
 -disk_la_CFLAGS =
 +disk_la_CFLAGS = $(AM_CFLAGS)
  disk_la_LDFLAGS = -module -avoid-version
  disk_la_LIBADD = 
  if BUILD_WITH_LIBKSTAT
@@@ -245,7 -242,6 +245,7 @@@ endi
  if BUILD_PLUGIN_EXEC
  pkglib_LTLIBRARIES += exec.la
  exec_la_SOURCES = exec.c \
 +                utils_parse_option.h utils_parse_option.c \
                  utils_cmd_putnotif.c utils_cmd_putnotif.h \
                  utils_cmd_putval.c utils_cmd_putval.h
  exec_la_LDFLAGS = -module -avoid-version
@@@ -256,14 -252,6 +256,14 @@@ collectd_LDADD += "-dlopen" exec.l
  collectd_DEPENDENCIES += exec.la
  endif
  
 +if BUILD_PLUGIN_FILECOUNT
 +pkglib_LTLIBRARIES += filecount.la
 +filecount_la_SOURCES = filecount.c
 +filecount_la_LDFLAGS = -module -avoid-version
 +collectd_LDADD += "-dlopen" filecount.la
 +collectd_DEPENDENCIES += filecount.la
 +endif
 +
  if BUILD_PLUGIN_HDDTEMP
  pkglib_LTLIBRARIES += hddtemp.la
  hddtemp_la_SOURCES = hddtemp.c
@@@ -278,7 -266,7 +278,7 @@@ endi
  if BUILD_PLUGIN_INTERFACE
  pkglib_LTLIBRARIES += interface.la
  interface_la_SOURCES = interface.c
 -interface_la_CFLAGS =
 +interface_la_CFLAGS = $(AM_CFLAGS)
  interface_la_LDFLAGS = -module -avoid-version
  interface_la_LIBADD =
  collectd_LDADD += "-dlopen" interface.la
@@@ -313,7 -301,7 +313,7 @@@ endi
  if BUILD_PLUGIN_IPMI
  pkglib_LTLIBRARIES += ipmi.la
  ipmi_la_SOURCES = ipmi.c
 -ipmi_la_CFLAGS = $(BUILD_WITH_OPENIPMI_CFLAGS)
 +ipmi_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_OPENIPMI_CFLAGS)
  ipmi_la_LDFLAGS = -module -avoid-version
  ipmi_la_LIBADD = $(BUILD_WITH_OPENIPMI_LIBS)
  collectd_LDADD += "-dlopen" ipmi.la
@@@ -340,8 -328,7 +340,8 @@@ endi
  if BUILD_PLUGIN_LIBVIRT
  pkglib_LTLIBRARIES += libvirt.la
  libvirt_la_SOURCES = libvirt.c
 -libvirt_la_CFLAGS = $(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
 +libvirt_la_CFLAGS = $(AM_CFLAGS) \
 +              $(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
  libvirt_la_LIBADD = $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
  libvirt_la_LDFLAGS = -module -avoid-version
  collectd_LDADD += "-dlopen" libvirt.la
@@@ -351,7 -338,7 +351,7 @@@ endi
  if BUILD_PLUGIN_LOAD
  pkglib_LTLIBRARIES += load.la
  load_la_SOURCES = load.c
 -load_la_CFLAGS =
 +load_la_CFLAGS = $(AM_CFLAGS)
  load_la_LDFLAGS = -module -avoid-version
  load_la_LIBADD =
  collectd_LDADD += "-dlopen" load.la
@@@ -385,6 -372,7 +385,6 @@@ if BUILD_PLUGIN_MEMCACHE
  pkglib_LTLIBRARIES += memcached.la
  memcached_la_SOURCES = memcached.c
  memcached_la_LDFLAGS = -module -avoid-version
 -memcached_la_CFLAGS =
  memcached_la_LIBADD =
  if BUILD_WITH_LIBSOCKET
  memcached_la_LDFLAGS += -lsocket
@@@ -396,7 -384,7 +396,7 @@@ endi
  if BUILD_PLUGIN_MEMORY
  pkglib_LTLIBRARIES += memory.la
  memory_la_SOURCES = memory.c
 -memory_la_CFLAGS =
 +memory_la_CFLAGS = $(AM_CFLAGS)
  memory_la_LDFLAGS = -module -avoid-version
  memory_la_LIBADD =
  collectd_LDADD += "-dlopen" memory.la
@@@ -425,7 -413,7 +425,7 @@@ if BUILD_PLUGIN_MYSQ
  pkglib_LTLIBRARIES += mysql.la
  mysql_la_SOURCES = mysql.c
  mysql_la_LDFLAGS = -module -avoid-version
 -mysql_la_CFLAGS =
 +mysql_la_CFLAGS = $(AM_CFLAGS)
  mysql_la_LIBADD =
  collectd_LDADD += "-dlopen" mysql.la
  if BUILD_WITH_LIBMYSQL
@@@ -439,7 -427,7 +439,7 @@@ if BUILD_PLUGIN_NETLIN
  pkglib_LTLIBRARIES += netlink.la
  netlink_la_SOURCES = netlink.c
  netlink_la_LDFLAGS = -module -avoid-version
 -netlink_la_CFLAGS = $(BUILD_WITH_LIBNETLINK_CFLAGS)
 +netlink_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBNETLINK_CFLAGS)
  netlink_la_LIBADD = $(BUILD_WITH_LIBNETLINK_LIBS)
  collectd_LDADD += "-dlopen" netlink.la
  collectd_DEPENDENCIES += netlink.la
@@@ -481,23 -469,6 +481,23 @@@ collectd_LDADD += "-dlopen" nginx.l
  collectd_DEPENDENCIES += nginx.la
  endif
  
 +if BUILD_PLUGIN_NOTIFY_DESKTOP
 +pkglib_LTLIBRARIES += notify_desktop.la
 +notify_desktop_la_SOURCES = notify_desktop.c
 +notify_desktop_la_CFLAGS = $(AM_CFLAGS) $(LIBNOTIFY_CFLAGS)
 +notify_desktop_la_LDFLAGS = -module -avoid-version $(LIBNOTIFY_LIBS)
 +collectd_LDADD += "-dlopen" notify_desktop.la
 +collectd_DEPENDENCIES += notify_desktop.la
 +endif
 +
 +if BUILD_PLUGIN_NOTIFY_EMAIL
 +pkglib_LTLIBRARIES += notify_email.la
 +notify_email_la_SOURCES = notify_email.c
 +notify_email_la_LDFLAGS = -L/usr/local/lib -lesmtp -lssl -lcrypto -pthread -module -avoid-version
 +collectd_LDADD += "-dlopen" notify_email.la
 +collectd_DEPENDENCIES += notify_email.la
 +endif
 +
  if BUILD_PLUGIN_NTPD
  pkglib_LTLIBRARIES += ntpd.la
  ntpd_la_SOURCES = ntpd.c
@@@ -518,28 -489,14 +518,28 @@@ collectd_LDADD += "-dlopen" nut.l
  collectd_DEPENDENCIES += nut.la
  endif
  
 +if BUILD_PLUGIN_ONEWIRE
 +pkglib_LTLIBRARIES += onewire.la
 +onewire_la_SOURCES = onewire.c
 +onewire_la_CFLAGS = $(AM_CFLAGS)
 +onewire_la_CPPFLAGS = $(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
 +onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS)
 +onewire_la_LDFLAGS = -module -avoid-version
 +collectd_LDADD += "-dlopen" onewire.la
 +collectd_DEPENDENCIES += onewire.la
 +endif
 +
  if BUILD_PLUGIN_PERL
  pkglib_LTLIBRARIES += perl.la
  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
  perl_la_CFLAGS  = $(AM_CFLAGS) \
 -                $(PERL_CFLAGS) \
 -                -DXS_VERSION=\"$(VERSION)\" -DVERSION=\"$(VERSION)\"
 +              $(PERL_CFLAGS) \
 +              -DXS_VERSION=\"$(VERSION)\" -DVERSION=\"$(VERSION)\"
  perl_la_LDFLAGS = -module -avoid-version \
 -                $(PERL_LDFLAGS)
 +              $(PERL_LDFLAGS)
  collectd_LDADD += "-dlopen" perl.la
  collectd_DEPENDENCIES += perl.la
  endif
@@@ -558,16 -515,6 +558,16 @@@ collectd_LDADD += "-dlopen" ping.l
  collectd_DEPENDENCIES += ping.la
  endif
  
 +if BUILD_PLUGIN_POSTGRESQL
 +pkglib_LTLIBRARIES += postgresql.la
 +postgresql_la_SOURCES = postgresql.c
 +postgresql_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBPQ_CPPFLAGS)
 +postgresql_la_LDFLAGS = -module -avoid-version \
 +              $(BUILD_WITH_LIBPQ_LDFLAGS) -lpq
 +collectd_LDADD += "-dlopen" postgresql.la
 +collectd_DEPENDENCIES += postgresql.la
 +endif
 +
  if BUILD_PLUGIN_POWERDNS
  pkglib_LTLIBRARIES += powerdns.la
  powerdns_la_SOURCES = powerdns.c
@@@ -580,19 -527,15 +580,19 @@@ if BUILD_PLUGIN_PROCESSE
  pkglib_LTLIBRARIES += processes.la
  processes_la_SOURCES = processes.c
  processes_la_LDFLAGS = -module -avoid-version
 +processes_la_LIBADD =
  collectd_LDADD += "-dlopen" processes.la
  collectd_DEPENDENCIES += processes.la
 +if BUILD_WITH_LIBKVM_GETPROCS
 +processes_la_LIBADD += -lkvm
 +endif
  endif
  
  if BUILD_PLUGIN_RRDTOOL
  pkglib_LTLIBRARIES += rrdtool.la
  rrdtool_la_SOURCES = rrdtool.c
  rrdtool_la_LDFLAGS = -module -avoid-version
 -rrdtool_la_CFLAGS = $(BUILD_WITH_LIBRRD_CFLAGS)
 +rrdtool_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS)
  rrdtool_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS)
  collectd_LDADD += "-dlopen" rrdtool.la
  collectd_DEPENDENCIES += rrdtool.la
@@@ -601,7 -544,7 +601,7 @@@ endi
  if BUILD_PLUGIN_SENSORS
  pkglib_LTLIBRARIES += sensors.la
  sensors_la_SOURCES = sensors.c
 -sensors_la_CFLAGS = $(BUILD_WITH_LIBSENSORS_CFLAGS)
 +sensors_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSENSORS_CFLAGS)
  sensors_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBSENSORS_LDFLAGS)
  sensors_la_LIBADD = -lsensors
  collectd_LDADD += "-dlopen" sensors.la
@@@ -620,7 -563,7 +620,7 @@@ if BUILD_PLUGIN_SNM
  pkglib_LTLIBRARIES += snmp.la
  snmp_la_SOURCES = snmp.c
  snmp_la_LDFLAGS = -module -avoid-version
 -snmp_la_CFLAGS =
 +snmp_la_CFLAGS = $(AM_CFLAGS)
  snmp_la_LIBADD =
  if BUILD_WITH_LIBNETSNMP
  snmp_la_CFLAGS += $(BUILD_WITH_LIBSNMP_CFLAGS)
@@@ -636,7 -579,7 +636,7 @@@ endi
  if BUILD_PLUGIN_SWAP
  pkglib_LTLIBRARIES += swap.la
  swap_la_SOURCES = swap.c
 -swap_la_CFLAGS =
 +swap_la_CFLAGS = $(AM_CFLAGS)
  swap_la_LDFLAGS = -module -avoid-version
  swap_la_LIBADD =
  collectd_LDADD += "-dlopen" swap.la
@@@ -684,12 -627,8 +684,12 @@@ if BUILD_PLUGIN_TCPCONN
  pkglib_LTLIBRARIES += tcpconns.la
  tcpconns_la_SOURCES = tcpconns.c
  tcpconns_la_LDFLAGS = -module -avoid-version
 +tcpconns_la_LIBADD =
  collectd_LDADD += "-dlopen" tcpconns.la
  collectd_DEPENDENCIES += tcpconns.la
 +if BUILD_WITH_LIBKVM_NLIST
 +tcpconns_la_LIBADD += -lkvm
 +endif
  endif
  
  if BUILD_PLUGIN_TEAMSPEAK2
@@@ -700,18 -639,9 +700,18 @@@ collectd_LDADD += "-dlopen" teamspeak2.
  collectd_DEPENDENCIES += teamspeak2.la
  endif
  
 +if BUILD_PLUGIN_THERMAL
 +pkglib_LTLIBRARIES += thermal.la
 +thermal_la_SOURCES = thermal.c
 +thermal_la_LDFLAGS = -module -avoid-version
 +collectd_LDADD += "-dlopen" thermal.la
 +collectd_DEPENDENCIES += thermal.la
 +endif
 +
  if BUILD_PLUGIN_UNIXSOCK
  pkglib_LTLIBRARIES += unixsock.la
  unixsock_la_SOURCES = unixsock.c \
 +                    utils_parse_option.h utils_parse_option.c \
                      utils_cmd_flush.h utils_cmd_flush.c \
                      utils_cmd_getval.h utils_cmd_getval.c \
                      utils_cmd_listval.h utils_cmd_listval.c \
@@@ -725,7 -655,7 +725,7 @@@ endi
  if BUILD_PLUGIN_USERS
  pkglib_LTLIBRARIES += users.la
  users_la_SOURCES = users.c
 -users_la_CFLAGS =
 +users_la_CFLAGS = $(AM_CFLAGS)
  users_la_LDFLAGS = -module -avoid-version
  users_la_LIBADD =
  if BUILD_WITH_LIBSTATGRAB
@@@ -791,24 -721,13 +791,24 @@@ EXTRA_DIST = types.d
  
  EXTRA_DIST += collectd-email.pod collectd-exec.pod collectd-nagios.pod \
        collectd-perl.pod collectd-snmp.pod collectd-unixsock.pod \
 -      collectd.conf.pod collectd.pod collectdmon.pod types.db.pod
 +      collectd.conf.pod collectd.pod collectdmon.pod types.db.pod \
 +      postgresql_default.conf
  
  .pod.1:
 -      pod2man --release=$(VERSION) --center=$(PACKAGE) $< >.pod2man.tmp 2>/dev/null && mv -f .pod2man.tmp $@ || true
 +      pod2man --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
  
  .pod.5:
 -      pod2man --section=5 --release=$(VERSION) --center=$(PACKAGE) $< >.pod2man.tmp 2>/dev/null && mv -f .pod2man.tmp $@ || true
 +      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
  
  install-exec-hook:
        $(mkinstalldirs) $(DESTDIR)$(sysconfdir)
                $(INSTALL) -m 0640 collectd.conf $(DESTDIR)$(sysconfdir)/collectd.conf; \
        fi; \
        cp -f $(srcdir)/types.db $(DESTDIR)$(pkglibdir)/;
 +      $(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
 +      $(INSTALL) -m 0644 $(srcdir)/postgresql_default.conf \
 +              $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
diff --combined src/collectd.h
@@@ -56,9 -56,6 +56,9 @@@
  #if HAVE_STDINT_H
  # include <stdint.h>
  #endif
 +#if HAVE_STDBOOL_H
 +# include <stdbool.h>
 +#endif
  #if HAVE_UNISTD_H
  # include <unistd.h>
  #endif
  #define PLUGINDIR PREFIX "/lib/" PACKAGE_NAME
  #endif
  
 +#ifndef PKGDATADIR
 +#define PKGDATADIR PREFIX "/share/" PACKAGE_NAME
 +#endif
 +
  #ifndef COLLECTD_GRP_NAME
  # define COLLECTD_GRP_NAME "collectd"
  #endif
  # define __attribute__(x) /**/
  #endif
  
- #if __GNUC__
+ #if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__
  # pragma GCC poison strcpy strcat strtok
  #endif
  
   * included.
   */
  #ifndef DONT_POISON_SPRINTF_YET
- # if __GNUC__
+ # if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__
  #  pragma GCC poison sprintf
  # endif
  #endif
diff --combined src/perl.c
@@@ -36,7 -36,7 +36,7 @@@
  #include <EXTERN.h>
  #include <perl.h>
  
- #if __GNUC__
+ #if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__
  # pragma GCC poison sprintf
  #endif
  
@@@ -71,7 -71,6 +71,7 @@@
  
  #define PLUGIN_TYPES    7
  
 +#define PLUGIN_CONFIG   254
  #define PLUGIN_DATASET  255
  
  #define log_debug(...) DEBUG ("perl: " __VA_ARGS__)
@@@ -85,7 -84,8 +85,7 @@@ void boot_DynaLoader (PerlInterpreter *
  static XS (Collectd_plugin_register_ds);
  static XS (Collectd_plugin_unregister_ds);
  static XS (Collectd_plugin_dispatch_values);
 -static XS (Collectd_plugin_flush_one);
 -static XS (Collectd_plugin_flush_all);
 +static XS (Collectd__plugin_flush);
  static XS (Collectd_plugin_dispatch_notification);
  static XS (Collectd_plugin_log);
  static XS (Collectd_call_by_name);
@@@ -139,7 -139,8 +139,7 @@@ static struct 
        { "Collectd::plugin_register_data_set",   Collectd_plugin_register_ds },
        { "Collectd::plugin_unregister_data_set", Collectd_plugin_unregister_ds },
        { "Collectd::plugin_dispatch_values",     Collectd_plugin_dispatch_values },
 -      { "Collectd::plugin_flush_one",           Collectd_plugin_flush_one },
 -      { "Collectd::plugin_flush_all",           Collectd_plugin_flush_all },
 +      { "Collectd::_plugin_flush",              Collectd__plugin_flush },
        { "Collectd::plugin_dispatch_notification",
                Collectd_plugin_dispatch_notification },
        { "Collectd::plugin_log",                 Collectd_plugin_log },
@@@ -159,7 -160,6 +159,7 @@@ struct 
        { "Collectd::TYPE_LOG",        PLUGIN_LOG },
        { "Collectd::TYPE_NOTIF",      PLUGIN_NOTIF },
        { "Collectd::TYPE_FLUSH",      PLUGIN_FLUSH },
 +      { "Collectd::TYPE_CONFIG",     PLUGIN_CONFIG },
        { "Collectd::TYPE_DATASET",    PLUGIN_DATASET },
        { "Collectd::DS_TYPE_COUNTER", DS_TYPE_COUNTER },
        { "Collectd::DS_TYPE_GAUGE",   DS_TYPE_GAUGE },
@@@ -216,7 -216,8 +216,7 @@@ static int hv2data_source (pTHX_ HV *ha
                return -1;
  
        if (NULL != (tmp = hv_fetch (hash, "name", 4, 0))) {
 -              strncpy (ds->name, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
 -              ds->name[DATA_MAX_NAME_LEN - 1] = '\0';
 +              sstrncpy (ds->name, SvPV_nolen (*tmp), sizeof (ds->name));
        }
        else {
                log_err ("hv2data_source: No DS name given.");
@@@ -378,10 -379,6 +378,10 @@@ static int value_list2hv (pTHX_ value_l
                                newSVpv (vl->plugin_instance, 0), 0))
                        return -1;
  
 +      if ('\0' != vl->type[0])
 +              if (NULL == hv_store (hash, "type", 4, newSVpv (vl->type, 0), 0))
 +                      return -1;
 +
        if ('\0' != vl->type_instance[0])
                if (NULL == hv_store (hash, "type_instance", 13,
                                newSVpv (vl->type_instance, 0), 0))
@@@ -426,81 -423,6 +426,81 @@@ static int notification2hv (pTHX_ notif
        return 0;
  } /* static int notification2hv (notification_t *, HV *) */
  
 +static int oconfig_item2hv (pTHX_ oconfig_item_t *ci, HV *hash)
 +{
 +      int i;
 +
 +      AV *values;
 +      AV *children;
 +
 +      if (NULL == hv_store (hash, "key", 3, newSVpv (ci->key, 0), 0))
 +              return -1;
 +
 +      values = newAV ();
 +      if (0 < ci->values_num)
 +              av_extend (values, ci->values_num);
 +
 +      if (NULL == hv_store (hash, "values", 6, newRV_noinc ((SV *)values), 0)) {
 +              av_clear (values);
 +              av_undef (values);
 +              return -1;
 +      }
 +
 +      for (i = 0; i < ci->values_num; ++i) {
 +              SV *value;
 +
 +              switch (ci->values[i].type) {
 +                      case OCONFIG_TYPE_STRING:
 +                              value = newSVpv (ci->values[i].value.string, 0);
 +                              break;
 +                      case OCONFIG_TYPE_NUMBER:
 +                              value = newSVnv ((NV)ci->values[i].value.number);
 +                              break;
 +                      case OCONFIG_TYPE_BOOLEAN:
 +                              value = ci->values[i].value.boolean ? &PL_sv_yes : &PL_sv_no;
 +                              break;
 +                      default:
 +                              log_err ("oconfig_item2hv: Invalid value type %i.",
 +                                              ci->values[i].type);
 +                              value = &PL_sv_undef;
 +              }
 +
 +              if (NULL == av_store (values, i, value)) {
 +                      sv_free (value);
 +                      return -1;
 +              }
 +      }
 +
 +      /* ignoring 'parent' member which is uninteresting in this case */
 +
 +      children = newAV ();
 +      if (0 < ci->children_num)
 +              av_extend (children, ci->children_num);
 +
 +      if (NULL == hv_store (hash, "children", 8, newRV_noinc ((SV *)children), 0)) {
 +              av_clear (children);
 +              av_undef (children);
 +              return -1;
 +      }
 +
 +      for (i = 0; i < ci->children_num; ++i) {
 +              HV *child = newHV ();
 +
 +              if (0 != oconfig_item2hv (aTHX_ ci->children + i, child)) {
 +                      hv_clear (child);
 +                      hv_undef (child);
 +                      return -1;
 +              }
 +
 +              if (NULL == av_store (children, i, newRV_noinc ((SV *)child))) {
 +                      hv_clear (child);
 +                      hv_undef (child);
 +                      return -1;
 +              }
 +      }
 +      return 0;
 +} /* static int oconfig_item2hv (pTHX_ oconfig_item_t *, HV *) */
 +
  /*
   * Internal functions.
   */
  static char *get_module_name (char *buf, size_t buf_len, const char *module) {
        int status = 0;
        if (base_name[0] == '\0')
 -              status = snprintf (buf, buf_len, "%s", module);
 +              status = ssnprintf (buf, buf_len, "%s", module);
        else
 -              status = snprintf (buf, buf_len, "%s::%s", base_name, module);
 +              status = ssnprintf (buf, buf_len, "%s::%s", base_name, module);
        if ((status < 0) || ((unsigned int)status >= buf_len))
                return (NULL);
 -      buf[buf_len - 1] = '\0';
        return (buf);
  } /* char *get_module_name */
  
@@@ -558,7 -481,8 +558,7 @@@ static int pplugin_register_data_set (p
                                ds[i].name, ds[i].type, ds[i].min, ds[i].max);
        }
  
 -      strncpy (set->type, name, DATA_MAX_NAME_LEN);
 -      set->type[DATA_MAX_NAME_LEN - 1] = '\0';
 +      sstrncpy (set->type, name, sizeof (set->type));
  
        set->ds_num = len + 1;
        set->ds = ds;
@@@ -593,7 -517,7 +593,7 @@@ static int pplugin_unregister_data_set 
   *   type_instance   => $tinstance,
   * }
   */
 -static int pplugin_dispatch_values (pTHX_ char *name, HV *values)
 +static int pplugin_dispatch_values (pTHX_ HV *values)
  {
        value_list_t list = VALUE_LIST_INIT;
        value_t      *val = NULL;
  
        int ret = 0;
  
 -      if ((NULL == name) || (NULL == values))
 +      if (NULL == values)
                return -1;
  
 +      if (NULL == (tmp = hv_fetch (values, "type", 4, 0))) {
 +              log_err ("pplugin_dispatch_values: No type given.");
 +              return -1;
 +      }
 +
 +      sstrncpy (list.type, SvPV_nolen (*tmp), sizeof (list.type));
 +
        if ((NULL == (tmp = hv_fetch (values, "values", 6, 0)))
                        || (! (SvROK (*tmp) && (SVt_PVAV == SvTYPE (SvRV (*tmp)))))) {
                log_err ("pplugin_dispatch_values: No valid values given.");
  
                val = (value_t *)smalloc (len * sizeof (value_t));
  
 -              list.values_len = av2value (aTHX_ name, (AV *)SvRV (*tmp), val, len);
 +              list.values_len = av2value (aTHX_ list.type, (AV *)SvRV (*tmp),
 +                              val, len);
                list.values = val;
  
                if (-1 == list.values_len) {
        }
  
        if (NULL != (tmp = hv_fetch (values, "host", 4, 0))) {
 -              strncpy (list.host, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
 -              list.host[DATA_MAX_NAME_LEN - 1] = '\0';
 +              sstrncpy (list.host, SvPV_nolen (*tmp), sizeof (list.host));
        }
        else {
                sstrncpy (list.host, hostname_g, sizeof (list.host));
        }
  
 -      if (NULL != (tmp = hv_fetch (values, "plugin", 6, 0))) {
 -              strncpy (list.plugin, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
 -              list.plugin[DATA_MAX_NAME_LEN - 1] = '\0';
 -      }
 +      if (NULL != (tmp = hv_fetch (values, "plugin", 6, 0)))
 +              sstrncpy (list.plugin, SvPV_nolen (*tmp), sizeof (list.plugin));
  
 -      if (NULL != (tmp = hv_fetch (values, "plugin_instance", 15, 0))) {
 -              strncpy (list.plugin_instance, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
 -              list.plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
 -      }
 +      if (NULL != (tmp = hv_fetch (values, "plugin_instance", 15, 0)))
 +              sstrncpy (list.plugin_instance, SvPV_nolen (*tmp),
 +                              sizeof (list.plugin_instance));
  
 -      if (NULL != (tmp = hv_fetch (values, "type_instance", 13, 0))) {
 -              strncpy (list.type_instance, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
 -              list.type_instance[DATA_MAX_NAME_LEN - 1] = '\0';
 -      }
 +      if (NULL != (tmp = hv_fetch (values, "type_instance", 13, 0)))
 +              sstrncpy (list.type_instance, SvPV_nolen (*tmp),
 +                              sizeof (list.type_instance));
  
 -      ret = plugin_dispatch_values (name, &list);
 +      ret = plugin_dispatch_values (&list);
  
        sfree (val);
        return ret;
@@@ -705,25 -626,31 +705,25 @@@ static int pplugin_dispatch_notificatio
                n.time = time (NULL);
  
        if (NULL != (tmp = hv_fetch (notif, "message", 7, 0)))
 -              strncpy (n.message, SvPV_nolen (*tmp), sizeof (n.message));
 -      n.message[sizeof (n.message) - 1] = '\0';
 +              sstrncpy (n.message, SvPV_nolen (*tmp), sizeof (n.message));
  
        if (NULL != (tmp = hv_fetch (notif, "host", 4, 0)))
 -              strncpy (n.host, SvPV_nolen (*tmp), sizeof (n.host));
 +              sstrncpy (n.host, SvPV_nolen (*tmp), sizeof (n.host));
        else
 -              strncpy (n.host, hostname_g, sizeof (n.host));
 -      n.host[sizeof (n.host) - 1] = '\0';
 +              sstrncpy (n.host, hostname_g, sizeof (n.host));
  
        if (NULL != (tmp = hv_fetch (notif, "plugin", 6, 0)))
 -              strncpy (n.plugin, SvPV_nolen (*tmp), sizeof (n.plugin));
 -      n.plugin[sizeof (n.plugin) - 1] = '\0';
 +              sstrncpy (n.plugin, SvPV_nolen (*tmp), sizeof (n.plugin));
  
        if (NULL != (tmp = hv_fetch (notif, "plugin_instance", 15, 0)))
 -              strncpy (n.plugin_instance, SvPV_nolen (*tmp),
 +              sstrncpy (n.plugin_instance, SvPV_nolen (*tmp),
                                sizeof (n.plugin_instance));
 -      n.plugin_instance[sizeof (n.plugin_instance) - 1] = '\0';
  
        if (NULL != (tmp = hv_fetch (notif, "type", 4, 0)))
 -              strncpy (n.type, SvPV_nolen (*tmp), sizeof (n.type));
 -      n.type[sizeof (n.type) - 1] = '\0';
 +              sstrncpy (n.type, SvPV_nolen (*tmp), sizeof (n.type));
  
        if (NULL != (tmp = hv_fetch (notif, "type_instance", 13, 0)))
 -              strncpy (n.type_instance, SvPV_nolen (*tmp), sizeof (n.type_instance));
 -      n.type_instance[sizeof (n.type_instance) - 1] = '\0';
 +              sstrncpy (n.type_instance, SvPV_nolen (*tmp), sizeof (n.type_instance));
        return plugin_dispatch_notification (&n);
  } /* static int pplugin_dispatch_notification (HV *) */
  
@@@ -772,7 -699,6 +772,7 @@@ static int pplugin_call_all (pTHX_ int 
                 *   time   => $time,
                 *   host   => $hostname,
                 *   plugin => $plugin,
 +               *   type   => $type,
                 *   plugin_instance => $instance,
                 *   type_instance   => $type_instance
                 * };
        else if (PLUGIN_FLUSH == type) {
                /*
                 * $_[0] = $timeout;
 +               * $_[1] = $identifier;
                 */
                XPUSHs (sv_2mortal (newSViv (va_arg (ap, int))));
 +              XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0)));
        }
  
        PUTBACK;
@@@ -950,43 -874,33 +950,43 @@@ static XS (Collectd_plugin_unregister_d
   */
  static XS (Collectd_plugin_dispatch_values)
  {
 -      SV *values = NULL;
 +      SV *values     = NULL;
 +      int values_idx = 0;
  
        int ret = 0;
  
        dXSARGS;
  
 -      if (2 != items) {
 -              log_err ("Usage: Collectd::plugin_dispatch_values(name, values)");
 +      if (2 == items) {
 +              log_warn ("Collectd::plugin_dispatch_values with two arguments "
 +                              "is deprecated - pass the type through values->{type}.");
 +              values_idx = 1;
 +      }
 +      else if (1 != items) {
 +              log_err ("Usage: Collectd::plugin_dispatch_values(values)");
                XSRETURN_EMPTY;
        }
  
 -      log_debug ("Collectd::plugin_dispatch_values: "
 -                      "name = \"%s\", values=\"%s\"",
 -                      SvPV_nolen (ST (0)), SvPV_nolen (ST (1)));
 +      log_debug ("Collectd::plugin_dispatch_values: values=\"%s\"",
 +                      SvPV_nolen (ST (values_idx)));
  
 -      values = ST (1);
 +      values = ST (values_idx);
  
        if (! (SvROK (values) && (SVt_PVHV == SvTYPE (SvRV (values))))) {
                log_err ("Collectd::plugin_dispatch_values: Invalid values.");
                XSRETURN_EMPTY;
        }
  
 -      if ((NULL == ST (0)) || (NULL == values))
 +      if (((2 == items) && (NULL == ST (0))) || (NULL == values))
 +              XSRETURN_EMPTY;
 +
 +      if ((2 == items) && (NULL == hv_store ((HV *)SvRV (values), "type", 4,
 +                      newSVsv (ST (0)), 0))) {
 +              log_err ("Collectd::plugin_dispatch_values: Could not store type.");
                XSRETURN_EMPTY;
 +      }
  
 -      ret = pplugin_dispatch_values (aTHX_ SvPV_nolen (ST (0)),
 -                      (HV *)SvRV (values));
 +      ret = pplugin_dispatch_values (aTHX_ (HV *)SvRV (values));
  
        if (0 == ret)
                XSRETURN_YES;
  } /* static XS (Collectd_plugin_dispatch_values) */
  
  /*
 - * Collectd::plugin_flush_one (timeout, name).
 + * Collectd::_plugin_flush (plugin, timeout, identifier).
 + *
 + * plugin:
 + *   name of the plugin to flush
   *
   * timeout:
   *   timeout to use when flushing the data
   *
 - * name:
 - *   name of the plugin to flush
 + * identifier:
 + *   data-set identifier to flush
   */
 -static XS (Collectd_plugin_flush_one)
 +static XS (Collectd__plugin_flush)
  {
 +      char *plugin  = NULL;
 +      int   timeout = -1;
 +      char *id      = NULL;
 +
        dXSARGS;
  
 -      if (2 != items) {
 -              log_err ("Usage: Collectd::plugin_flush_one(timeout, name)");
 +      if (3 != items) {
 +              log_err ("Usage: Collectd::_plugin_flush(plugin, timeout, id)");
                XSRETURN_EMPTY;
        }
  
 -      log_debug ("Collectd::plugin_flush_one: timeout = %i, name = \"%s\"",
 -                      (int)SvIV (ST (0)), SvPV_nolen (ST (1)));
 +      if (SvOK (ST (0)))
 +              plugin = SvPV_nolen (ST (0));
  
 -      if (0 == plugin_flush_one ((int)SvIV (ST (0)), SvPV_nolen (ST (1))))
 -              XSRETURN_YES;
 -      else
 -              XSRETURN_EMPTY;
 -} /* static XS (Collectd_plugin_flush_one) */
 +      if (SvOK (ST (1)))
 +              timeout = (int)SvIV (ST (1));
  
 -/*
 - * Collectd::plugin_flush_all (timeout).
 - *
 - * timeout:
 - *   timeout to use when flushing the data
 - */
 -static XS (Collectd_plugin_flush_all)
 -{
 -      dXSARGS;
 -
 -      if (1 != items) {
 -              log_err ("Usage: Collectd::plugin_flush_all(timeout)");
 -              XSRETURN_EMPTY;
 -      }
 +      if (SvOK (ST (2)))
 +              id = SvPV_nolen (ST (2));
  
 -      log_debug ("Collectd::plugin_flush_all: timeout = %i", (int)SvIV (ST (0)));
 +      log_debug ("Collectd::_plugin_flush: plugin = \"%s\", timeout = %i, "
 +                      "id = \"%s\"", plugin, timeout, id);
  
 -      plugin_flush_all ((int)SvIV (ST (0)));
 -      XSRETURN_YES;
 -} /* static XS (Collectd_plugin_flush_all) */
 +      if (0 == plugin_flush (plugin, timeout, id))
 +              XSRETURN_YES;
 +      else
 +              XSRETURN_EMPTY;
 +} /* static XS (Collectd__plugin_flush) */
  
  /*
   * Collectd::plugin_dispatch_notification (notif).
@@@ -1342,7 -1261,7 +1342,7 @@@ static int perl_notify (const notificat
        return pplugin_call_all (aTHX_ PLUGIN_NOTIF, notif);
  } /* static int perl_notify (const notification_t *) */
  
 -static int perl_flush (const int timeout)
 +static int perl_flush (int timeout, const char *identifier)
  {
        dTHX;
  
  
                aTHX = t->interp;
        }
 -      return pplugin_call_all (aTHX_ PLUGIN_FLUSH, timeout);
 +      return pplugin_call_all (aTHX_ PLUGIN_FLUSH, timeout, identifier);
  } /* static int perl_flush (const int) */
  
  static int perl_shutdown (void)
@@@ -1439,7 -1358,8 +1439,7 @@@ static int g_pv_get (pTHX_ SV *var, MAG
  static int g_pv_set (pTHX_ SV *var, MAGIC *mg)
  {
        char *pv = mg->mg_ptr;
 -      strncpy (pv, SvPV_nolen (var), DATA_MAX_NAME_LEN);
 -      pv[DATA_MAX_NAME_LEN - 1] = '\0';
 +      sstrncpy (pv, SvPV_nolen (var), DATA_MAX_NAME_LEN);
        return 0;
  } /* static int g_pv_set (pTHX_ SV *, MAGIC *) */
  
@@@ -1642,7 -1562,8 +1642,7 @@@ static int perl_config_basename (pTHX_ 
        value = ci->values[0].value.string;
  
        log_debug ("perl_config: Setting plugin basename to \"%s\"", value);
 -      strncpy (base_name, value, sizeof (base_name));
 -      base_name[sizeof (base_name) - 1] = '\0';
 +      sstrncpy (base_name, value, sizeof (base_name));
        return 0;
  } /* static int perl_config_basename (oconfig_item_it *) */
  
@@@ -1725,99 -1646,30 +1725,99 @@@ static int perl_config_includedir (pTHX
        return 0;
  } /* static int perl_config_includedir (oconfig_item_it *) */
  
 +/*
 + * <Plugin> block
 + */
 +static int perl_config_plugin (pTHX_ oconfig_item_t *ci)
 +{
 +      int retvals = 0;
 +      int ret     = 0;
 +
 +      char *plugin;
 +      HV   *config;
 +
 +      dSP;
 +
 +      if ((1 != ci->values_num) || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
 +              log_err ("LoadPlugin expects a single string argument.");
 +              return 1;
 +      }
 +
 +      plugin = ci->values[0].value.string;
 +      config = newHV ();
 +
 +      if (0 != oconfig_item2hv (aTHX_ ci, config)) {
 +              hv_clear (config);
 +              hv_undef (config);
 +
 +              log_err ("Unable to convert configuration to a Perl hash value.");
 +              config = Nullhv;
 +      }
 +
 +      ENTER;
 +      SAVETMPS;
 +
 +      PUSHMARK (SP);
 +
 +      XPUSHs (sv_2mortal (newSVpv (plugin, 0)));
 +      XPUSHs (sv_2mortal (newRV_noinc ((SV *)config)));
 +
 +      PUTBACK;
 +
 +      retvals = call_pv ("Collectd::_plugin_dispatch_config", G_SCALAR);
 +
 +      SPAGAIN;
 +      if (0 < retvals) {
 +              SV *tmp = POPs;
 +              if (! SvTRUE (tmp))
 +                      ret = 1;
 +      }
 +      else
 +              ret = 1;
 +
 +      PUTBACK;
 +      FREETMPS;
 +      LEAVE;
 +      return ret;
 +} /* static int perl_config_plugin (oconfig_item_it *) */
 +
  static int perl_config (oconfig_item_t *ci)
  {
 +      int status = 0;
        int i = 0;
  
        dTHXa (NULL);
  
        for (i = 0; i < ci->children_num; ++i) {
                oconfig_item_t *c = ci->children + i;
 +              int current_status;
  
                if (NULL != perl_threads)
                        aTHX = PERL_GET_CONTEXT;
  
                if (0 == strcasecmp (c->key, "LoadPlugin"))
 -                      perl_config_loadplugin (aTHX_ c);
 +                      current_status = perl_config_loadplugin (aTHX_ c);
                else if (0 == strcasecmp (c->key, "BaseName"))
 -                      perl_config_basename (aTHX_ c);
 +                      current_status = perl_config_basename (aTHX_ c);
                else if (0 == strcasecmp (c->key, "EnableDebugger"))
 -                      perl_config_enabledebugger (aTHX_ c);
 +                      current_status = perl_config_enabledebugger (aTHX_ c);
                else if (0 == strcasecmp (c->key, "IncludeDir"))
 -                      perl_config_includedir (aTHX_ c);
 +                      current_status = perl_config_includedir (aTHX_ c);
 +              else if (0 == strcasecmp (c->key, "Plugin"))
 +                      current_status = perl_config_plugin (aTHX_ c);
                else
                        log_warn ("Ignoring unknown config key \"%s\".", c->key);
 +
 +              /* fatal error - it's up to perl_config_* to clean up */
 +              if (0 > current_status) {
 +                      log_err ("Configuration failed with a fatal error - "
 +                                      "plugin disabled!");
 +                      return current_status;
 +              }
 +
 +              status += current_status;
        }
 -      return 0;
 +      return status;
  } /* static int perl_config (oconfig_item_t *) */
  
  void module_register (void)
diff --combined src/types.db
@@@ -3,9 -3,8 +3,9 @@@ apache_connections       count:GAUGE:0:6553
  apache_requests               count:COUNTER:0:134217728
  apache_scoreboard     count:GAUGE:0:65535
  bitrate                       value:GAUGE:0:4294967295
 +bytes                 value:GAUGE:0:U
  cache_result          value:COUNTER:0:4294967295
 -cache_size              value:GAUGE:0:4294967295
 +cache_size            value:GAUGE:0:4294967295
  charge                        value:GAUGE:0:U
  connections           value:COUNTER:0:U
  counter                       value:COUNTER:U:U
@@@ -29,7 -28,6 +29,7 @@@ email_count           value:GAUGE:0:
  email_size            value:GAUGE:0:U
  entropy                       entropy:GAUGE:0:4294967295
  fanspeed              value:GAUGE:0:U
 +files                 value:GAUGE:0:U
  frequency             frequency:GAUGE:0:U
  frequency_offset      ppm:GAUGE:-1000000:1000000
  gauge                 value:GAUGE:U:U
@@@ -65,13 -63,6 +65,13 @@@ nfs_procedure               value:COUNTER:0:42949672
  nginx_connections     value:GAUGE:0:U
  nginx_requests                value:COUNTER:0:134217728
  percent                       percent:GAUGE:0:100.1
 +pg_blks                       value:COUNTER:0:U
 +pg_db_size            value:GAUGE:0:U
 +pg_n_tup_c            value:COUNTER:0:U
 +pg_n_tup_g            value:GAUGE:0:U
 +pg_numbackends                value:GAUGE:0:U
 +pg_scan                       value:COUNTER:0:U
 +pg_xact                       value:COUNTER:0:U
  ping                  ping:GAUGE:0:65535
  players                       value:GAUGE:0:1000000
  power                 value:GAUGE:0:U
@@@ -84,6 -75,7 +84,7 @@@ serial_octets         rx:COUNTER:0:4294967295
  signal_noise          value:GAUGE:U:0
  signal_power          value:GAUGE:U:0
  signal_quality                value:GAUGE:0:U
+ spam_check            value:GAUGE:0:U
  spam_score            value:GAUGE:U:U
  swap                  value:GAUGE:0:1099511627776
  tcp_connections               value:GAUGE:0:4294967295