Merge branch 'collectd-5.5'
authorMarc Fournier <marc.fournier@camptocamp.com>
Sun, 8 Nov 2015 20:26:26 +0000 (21:26 +0100)
committerMarc Fournier <marc.fournier@camptocamp.com>
Sun, 8 Nov 2015 20:26:26 +0000 (21:26 +0100)
1  2 
src/Makefile.am
src/daemon/Makefile.am
src/daemon/plugin.c
src/daemon/utils_ignorelist.c
src/snmp.c

diff --combined src/Makefile.am
@@@ -6,6 -6,10 +6,6 @@@ SUBDIRS += daemo
  
  PLUGIN_LDFLAGS = -module -avoid-version -export-symbols-regex '\<module_register\>'
  
 -if COMPILER_IS_GCC
 -AM_CFLAGS = -Wall -Werror
 -endif
 -
  AM_CPPFLAGS = -I$(srcdir)/daemon
  AM_CPPFLAGS += -DPREFIX='"${prefix}"'
  AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
@@@ -19,37 -23,13 +19,37 @@@ AM_CPPFLAGS += -DPKGDATADIR='"${pkgdata
  
  AUTOMAKE_OPTIONS = subdir-objects
  
 -noinst_LTLIBRARIES = libmount.la liblookup.la
 +noinst_LTLIBRARIES =
 +check_PROGRAMS =
 +TESTS =
  
 -libmount_la_SOURCES = utils_mount.c utils_mount.h
 -libmount_la_LIBADD = daemon/libcommon.la
 +noinst_LTLIBRARIES += liblatency.la
 +liblatency_la_SOURCES = utils_latency.c utils_latency.h
 +check_PROGRAMS += test_utils_latency
 +TESTS += test_utils_latency
 +test_utils_latency_SOURCES = utils_latency_test.c testing.h
 +test_utils_latency_LDADD = liblatency.la daemon/libcommon.la daemon/libplugin_mock.la -lm
  
 +noinst_LTLIBRARIES += liblookup.la
  liblookup_la_SOURCES = utils_vl_lookup.c utils_vl_lookup.h
 -liblookup_la_LIBADD = daemon/libavltree.la daemon/libcommon.la
 +liblookup_la_LIBADD = daemon/libavltree.la
 +check_PROGRAMS += test_utils_vl_lookup
 +TESTS += test_utils_vl_lookup
 +test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h
 +test_utils_vl_lookup_LDADD = liblookup.la daemon/libcommon.la daemon/libplugin_mock.la
 +if BUILD_WITH_LIBKSTAT
 +test_utils_vl_lookup_LDADD += -lkstat
 +endif
 +
 +noinst_LTLIBRARIES += libmount.la
 +libmount_la_SOURCES = utils_mount.c utils_mount.h
 +check_PROGRAMS += test_utils_mount
 +TESTS += test_utils_mount
 +test_utils_mount_SOURCES = utils_mount_test.c testing.h
 +test_utils_mount_LDADD = libmount.la daemon/libcommon.la daemon/libplugin_mock.la
 +if BUILD_WITH_LIBKSTAT
 +test_utils_mount_LDADD += -lkstat
 +endif
  
  sbin_PROGRAMS = collectdmon
  bin_PROGRAMS = collectd-nagios collectdctl collectd-tg
@@@ -84,8 -64,7 +84,8 @@@ collectdctl_LDADD += libcollectdclient/
  collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la
  
  collectd_tg_SOURCES = collectd-tg.c
 -collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
 +collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) \
 +                     -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
  collectd_tg_LDADD = daemon/libheap.la
  if BUILD_WITH_LIBSOCKET
  collectd_tg_LDADD += -lsocket
@@@ -211,8 -190,7 +211,7 @@@ endi
  
  if BUILD_PLUGIN_CGROUPS
  pkglib_LTLIBRARIES += cgroups.la
- cgroups_la_SOURCES = cgroups.c \
-                    utils_ignorelist.c utils_ignorelist.h
+ cgroups_la_SOURCES = cgroups.c
  cgroups_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  cgroups_la_LIBADD = libmount.la
  endif
@@@ -311,16 -289,14 +310,14 @@@ endi
  
  if BUILD_PLUGIN_DF
  pkglib_LTLIBRARIES += df.la
- df_la_SOURCES = df.c \
-               utils_ignorelist.c utils_ignorelist.h
+ df_la_SOURCES = df.c
  df_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  df_la_LIBADD = libmount.la
  endif
  
  if BUILD_PLUGIN_DISK
  pkglib_LTLIBRARIES += disk.la
- disk_la_SOURCES = disk.c \
-                 utils_ignorelist.c utils_ignorelist.h
+ disk_la_SOURCES = disk.c
  disk_la_CFLAGS = $(AM_CFLAGS)
  disk_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  disk_la_LIBADD =
@@@ -340,9 -316,6 +337,9 @@@ endi
  if BUILD_WITH_LIBUDEV
  disk_la_LIBADD += -ludev
  endif
 +if BUILD_FREEBSD
 +disk_la_LIBADD += -ldevstat -lgeom
 +endif
  if BUILD_WITH_PERFSTAT
  disk_la_LIBADD += -lperfstat
  endif
@@@ -423,8 -396,7 +420,7 @@@ endi
  
  if BUILD_PLUGIN_INTERFACE
  pkglib_LTLIBRARIES += interface.la
- interface_la_SOURCES = interface.c \
-                      utils_ignorelist.c utils_ignorelist.h
+ interface_la_SOURCES = interface.c
  interface_la_CFLAGS = $(AM_CFLAGS)
  interface_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  interface_la_LIBADD =
@@@ -461,8 -433,7 +457,7 @@@ endi
  
  if BUILD_PLUGIN_IPMI
  pkglib_LTLIBRARIES += ipmi.la
- ipmi_la_SOURCES = ipmi.c \
-                 utils_ignorelist.c utils_ignorelist.h
+ ipmi_la_SOURCES = ipmi.c
  ipmi_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_OPENIPMI_CFLAGS)
  ipmi_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  ipmi_la_LIBADD = $(BUILD_WITH_OPENIPMI_LIBS)
@@@ -473,16 -444,13 +468,15 @@@ pkglib_LTLIBRARIES += ipvs.l
  ipvs_la_SOURCES = ipvs.c
  if IP_VS_H_NEEDS_KERNEL_CFLAGS
  ipvs_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
 +else
 +ipvs_la_CFLAGS = $(AM_CFLAGS)
  endif
  ipvs_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_IRQ
  pkglib_LTLIBRARIES += irq.la
- irq_la_SOURCES = irq.c \
-                utils_ignorelist.c utils_ignorelist.h
+ irq_la_SOURCES = irq.c
  irq_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
@@@ -541,8 -509,7 +535,7 @@@ endi
  
  if BUILD_PLUGIN_MADWIFI
  pkglib_LTLIBRARIES += madwifi.la
- madwifi_la_SOURCES = madwifi.c madwifi.h \
-                    utils_ignorelist.c utils_ignorelist.h
+ madwifi_la_SOURCES = madwifi.c madwifi.h
  madwifi_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
@@@ -588,8 -555,7 +581,7 @@@ endi
  
  if BUILD_PLUGIN_MD
  pkglib_LTLIBRARIES += md.la
- md_la_SOURCES = md.c \
-               utils_ignorelist.c utils_ignorelist.h
+ md_la_SOURCES = md.c
  md_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
@@@ -634,8 -600,7 +626,7 @@@ endi
  
  if BUILD_PLUGIN_MIC
  pkglib_LTLIBRARIES += mic.la
- mic_la_SOURCES = mic.c \
-                utils_ignorelist.c utils_ignorelist.h
+ mic_la_SOURCES = mic.c
  mic_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_MIC_LIBPATH)
  mic_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_MIC_CPPFLAGS)
  mic_la_LIBADD = $(BUILD_WITH_MIC_LDADD)
@@@ -649,14 -614,6 +640,14 @@@ modbus_la_CFLAGS = $(AM_CFLAGS) $(BUILD
  modbus_la_LIBADD = $(BUILD_WITH_LIBMODBUS_LIBS)
  endif
  
 +if BUILD_PLUGIN_MQTT
 +pkglib_LTLIBRARIES += mqtt.la
 +mqtt_la_SOURCES = mqtt.c
 +mqtt_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 +mqtt_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMOSQUITTO_CPPFLAGS)
 +mqtt_la_LIBADD = $(BUILD_WITH_LIBMOSQUITTO_LIBS)
 +endif
 +
  if BUILD_PLUGIN_MULTIMETER
  pkglib_LTLIBRARIES += multimeter.la
  multimeter_la_SOURCES = multimeter.c
@@@ -677,8 -634,7 +668,7 @@@ endi
  
  if BUILD_PLUGIN_NETAPP
  pkglib_LTLIBRARIES += netapp.la
- netapp_la_SOURCES = netapp.c \
-                   utils_ignorelist.c utils_ignorelist.h
+ netapp_la_SOURCES = netapp.c
  netapp_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBNETAPP_CPPFLAGS)
  netapp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBNETAPP_LDFLAGS)
  netapp_la_LIBADD = $(LIBNETAPP_LIBS)
@@@ -784,8 -740,7 +774,7 @@@ endi
  
  if BUILD_PLUGIN_ONEWIRE
  pkglib_LTLIBRARIES += onewire.la
- onewire_la_SOURCES = onewire.c \
-                    utils_ignorelist.c utils_ignorelist.h
+ onewire_la_SOURCES = onewire.c
  onewire_la_CFLAGS = $(AM_CFLAGS)
  onewire_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
  onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS)
@@@ -898,8 -853,7 +887,7 @@@ endi
  
  if BUILD_PLUGIN_PROTOCOLS
  pkglib_LTLIBRARIES += protocols.la
- protocols_la_SOURCES = protocols.c \
-                      utils_ignorelist.c utils_ignorelist.h
+ protocols_la_SOURCES = protocols.c
  protocols_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
@@@ -937,8 -891,7 +925,7 @@@ endi
  
  if BUILD_PLUGIN_SENSORS
  pkglib_LTLIBRARIES += sensors.la
- sensors_la_SOURCES = sensors.c \
-                    utils_ignorelist.c utils_ignorelist.h
+ sensors_la_SOURCES = sensors.c
  sensors_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSENSORS_CFLAGS)
  sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSENSORS_LDFLAGS)
  sensors_la_LIBADD = -lsensors
@@@ -961,8 -914,7 +948,7 @@@ endi
  if BUILD_PLUGIN_SMART
  if BUILD_WITH_LIBUDEV
  pkglib_LTLIBRARIES += smart.la
- smart_la_SOURCES = smart.c \
-                  utils_ignorelist.c utils_ignorelist.h
+ smart_la_SOURCES = smart.c
  smart_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBATASMART_CPPFLAGS)
  smart_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBATASMART_LDFLAGS)
  smart_la_LIBADD = $(BUILD_WITH_LIBATASMART_LIBS) -ludev
@@@ -986,9 -938,10 +972,9 @@@ endi
  
  if BUILD_PLUGIN_STATSD
  pkglib_LTLIBRARIES += statsd.la
 -statsd_la_SOURCES = statsd.c \
 -                    utils_latency.h utils_latency.c
 +statsd_la_SOURCES = statsd.c
  statsd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 -statsd_la_LIBADD = -lpthread -lm
 +statsd_la_LIBADD = liblatency.la -lpthread -lm
  endif
  
  if BUILD_PLUGIN_SWAP
@@@ -1101,8 -1054,7 +1087,7 @@@ endi
  
  if BUILD_PLUGIN_THERMAL
  pkglib_LTLIBRARIES += thermal.la
- thermal_la_SOURCES = thermal.c \
-                    utils_ignorelist.c utils_ignorelist.h
+ thermal_la_SOURCES = thermal.c
  thermal_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
@@@ -1187,8 -1139,7 +1172,7 @@@ endi
  
  if BUILD_PLUGIN_VIRT
  pkglib_LTLIBRARIES += virt.la
- virt_la_SOURCES = virt.c \
-                 utils_ignorelist.c utils_ignorelist.h
+ virt_la_SOURCES = virt.c
  virt_la_CFLAGS = $(AM_CFLAGS) \
                $(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
  virt_la_LIBADD = $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
@@@ -1322,13 -1273,6 +1306,13 @@@ endi
  
  BUILT_SOURCES += $(dist_man_MANS)
  
 +if BUILD_PLUGIN_ZONE
 +pkglib_LTLIBRARIES += zone.la
 +zone_la_SOURCES = zone.c
 +zone_la_CFLAGS = $(AM_CFLAGS)
 +zone_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 +endif
 +
  dist_man_MANS = collectd.1 \
                collectd.conf.5 \
                collectd-email.5 \
@@@ -1421,4 -1365,12 +1405,4 @@@ uninstall-hook
        rm -f $(DESTDIR)$(sysconfdir)/collectd.conf
        rm -f $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
  
 -check_PROGRAMS = test_utils_mount test_utils_vl_lookup
 -
 -test_utils_mount_SOURCES = utils_mount_test.c testing.h
 -test_utils_mount_LDADD = libmount.la daemon/libplugin_mock.la
 -
 -test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h
 -test_utils_vl_lookup_LDADD = liblookup.la daemon/libplugin_mock.la
  
 -TESTS = test_utils_mount test_utils_vl_lookup
diff --combined src/daemon/Makefile.am
@@@ -1,3 -1,7 +1,3 @@@
 -if COMPILER_IS_GCC
 -AM_CFLAGS = -Wall -Werror
 -endif
 -
  AM_CPPFLAGS = -I$(top_srcdir)/src
  AM_CPPFLAGS += -DPREFIX='"${prefix}"'
  AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
@@@ -37,19 -41,15 +37,19 @@@ AUTOMAKE_OPTIONS = subdir-object
  
  sbin_PROGRAMS = collectd
  
 -noinst_LTLIBRARIES = libavltree.la libcommon.la libheap.la libplugin_mock.la
 +noinst_LTLIBRARIES = libavltree.la libcommon.la libheap.la libmetadata.la libplugin_mock.la
  
  libavltree_la_SOURCES = utils_avltree.c utils_avltree.h
  
  libcommon_la_SOURCES = common.c common.h
 +libcommon_la_LIBADD = $(COMMON_LIBS)
  
  libheap_la_SOURCES = utils_heap.c utils_heap.h
  
 +libmetadata_la_SOURCES = meta_data.c meta_data.h
 +
  libplugin_mock_la_SOURCES = plugin_mock.c utils_cache_mock.c utils_time_mock.c
 +libplugin_mock_la_LIBADD = $(COMMON_LIBS)
  
  collectd_SOURCES = collectd.c collectd.h \
                   configfile.c configfile.h \
@@@ -58,6 -58,7 +58,7 @@@
                   plugin.c plugin.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_random.c utils_random.h \
                   utils_tail_match.c utils_tail_match.h \
@@@ -73,7 -74,7 +74,7 @@@ collectd_CPPFLAGS =  $(AM_CPPFLAGS) $(L
  collectd_CFLAGS = $(AM_CFLAGS)
  collectd_LDFLAGS = -export-dynamic
  collectd_LDADD = libavltree.la libcommon.la libheap.la -lm $(COMMON_LIBS)
 -collectd_DEPENDENCIES = libavltree.la libcommon.la libheap.la
 +collectd_DEPENDENCIES = libavltree.la libcommon.la libheap.la libmetadata.la
  
  # The daemon needs to call sg_init, so we need to link it against libstatgrab,
  # too. -octo
@@@ -89,23 -90,14 +90,23 @@@ els
  collectd_LDADD += -loconfig
  endif
  
 -check_PROGRAMS = test_common test_utils_avltree test_utils_heap
 -TESTS = test_common test_utils_avltree test_utils_heap
 +check_PROGRAMS = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_time test_utils_subst
 +TESTS          = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_time test_utils_subst
  
  test_common_SOURCES = common_test.c ../testing.h
 -test_common_LDADD = libcommon.la libplugin_mock.la $(COMMON_LIBS)
 +test_common_LDADD = libcommon.la libplugin_mock.la
 +
 +test_meta_data_SOURCES = meta_data_test.c ../testing.h
 +test_meta_data_LDADD = libmetadata.la libplugin_mock.la
  
  test_utils_avltree_SOURCES = utils_avltree_test.c ../testing.h
  test_utils_avltree_LDADD = libavltree.la $(COMMON_LIBS)
  
  test_utils_heap_SOURCES = utils_heap_test.c ../testing.h
  test_utils_heap_LDADD = libheap.la $(COMMON_LIBS)
 +
 +test_utils_time_SOURCES = utils_time_test.c ../testing.h
 +
 +test_utils_subst_SOURCES = utils_subst_test.c ../testing.h \
 +                         utils_subst.c utils_subst.h
 +test_utils_subst_LDADD = libcommon.la libplugin_mock.la
diff --combined src/daemon/plugin.c
@@@ -80,12 -80,6 +80,12 @@@ struct write_queue_
        write_queue_t *next;
  };
  
 +struct flush_callback_s {
 +      char *name;
 +      cdtime_t timeout;
 +};
 +typedef struct flush_callback_s flush_callback_t;
 +
  /*
   * Private variables
   */
@@@ -889,7 -883,7 +889,7 @@@ static void start_write_threads (size_
  static void stop_write_threads (void) /* {{{ */
  {
        write_queue_t *q;
 -      int i;
 +      size_t i;
  
        if (write_threads == NULL)
                return;
  
        if (i > 0)
        {
 -              WARNING ("plugin: %i value list%s left after shutting down "
 +              WARNING ("plugin: %zu value list%s left after shutting down "
                                "the write threads.",
                                i, (i == 1) ? " was" : "s were");
        }
@@@ -1089,7 -1083,6 +1089,7 @@@ int plugin_load (char const *plugin_nam
                        /* success */
                        plugin_mark_loaded (plugin_name);
                        ret = 0;
 +                      INFO ("plugin_load: plugin \"%s\" successfully loaded.", plugin_name);
                        break;
                }
                else
@@@ -1254,7 -1247,7 +1254,7 @@@ int plugin_register_read (const char *n
  
  int plugin_register_complex_read (const char *group, const char *name,
                plugin_read_cb callback,
 -              const struct timespec *interval,
 +              cdtime_t interval,
                user_data_t *user_data)
  {
        read_func_t *rf;
                rf->rf_group[0] = '\0';
        rf->rf_name = strdup (name);
        rf->rf_type = RF_COMPLEX;
 -      if (interval != NULL)
 -              rf->rf_interval = TIMESPEC_TO_CDTIME_T (interval);
 -      else
 -              rf->rf_interval = plugin_get_interval ();
 +      rf->rf_interval = (interval != 0) ? interval : plugin_get_interval ();
  
        /* Set user data */
        if (user_data == NULL)
@@@ -1306,105 -1302,11 +1306,105 @@@ int plugin_register_write (const char *
                                (void *) callback, ud));
  } /* int plugin_register_write */
  
 +static int plugin_flush_timeout_callback (user_data_t *ud)
 +{
 +      flush_callback_t *cb = ud->data;
 +
 +      return plugin_flush (cb->name, cb->timeout, /* identifier = */ NULL);
 +} /* static int plugin_flush_callback */
 +
 +static void plugin_flush_timeout_callback_free (void *data)
 +{
 +      flush_callback_t *cb = data;
 +
 +      if (cb == NULL) return;
 +
 +      sfree(cb->name);
 +      sfree(cb);
 +} /* static void plugin_flush_callback_free */
 +
 +static char *plugin_flush_callback_name (const char *name)
 +{
 +      char *flush_prefix = "flush/";
 +      size_t prefix_size;
 +      char *flush_name;
 +      size_t name_size;
 +
 +      prefix_size = strlen(flush_prefix);
 +      name_size = strlen(name);
 +
 +      flush_name = malloc (sizeof(char) * (name_size + prefix_size + 1));
 +      if (flush_name == NULL)
 +      {
 +              ERROR ("plugin_flush_callback_name: malloc failed.");
 +              return (NULL);
 +      }
 +
 +      sstrncpy (flush_name, flush_prefix, prefix_size + 1);
 +      sstrncpy (flush_name + prefix_size, name, name_size + 1);
 +
 +      return flush_name;
 +} /* static char *plugin_flush_callback_name */
 +
  int plugin_register_flush (const char *name,
                plugin_flush_cb callback, user_data_t *ud)
  {
 -      return (create_register_callback (&list_flush, name,
 -                              (void *) callback, ud));
 +      int status;
 +      plugin_ctx_t ctx = plugin_get_ctx ();
 +
 +      status = create_register_callback (&list_flush, name,
 +              (void *) callback, ud);
 +      if (status != 0)
 +              return status;
 +
 +      if (ctx.flush_interval != 0)
 +      {
 +              char *flush_name;
 +              user_data_t ud;
 +              flush_callback_t *cb;
 +
 +              flush_name = plugin_flush_callback_name (name);
 +              if (flush_name == NULL)
 +                      return (-1);
 +
 +              cb = malloc(sizeof(flush_callback_t));
 +              if (cb == NULL)
 +              {
 +                      ERROR ("plugin_register_flush: malloc failed.");
 +                      sfree(flush_name);
 +                      return (-1);
 +              }
 +
 +              cb->name = strdup (name);
 +              if (cb->name == NULL)
 +              {
 +                      ERROR ("plugin_register_flush: strdup failed.");
 +                      sfree(cb);
 +                      sfree(flush_name);
 +                      return (-1);
 +              }
 +              cb->timeout = ctx.flush_timeout;
 +
 +              ud.data = cb;
 +              ud.free_func = plugin_flush_timeout_callback_free;
 +
 +              status = plugin_register_complex_read (
 +                      /* group     = */ "flush",
 +                      /* name      = */ flush_name,
 +                      /* callback  = */ plugin_flush_timeout_callback,
 +                      /* interval  = */ ctx.flush_interval,
 +                      /* user data = */ &ud);
 +
 +              sfree(flush_name);
 +              if (status != 0)
 +              {
 +                      sfree(cb->name);
 +                      sfree(cb);
 +                      return status;
 +              }
 +      }
 +
 +      return 0;
  } /* int plugin_register_flush */
  
  int plugin_register_missing (const char *name,
@@@ -1445,7 -1347,7 +1445,7 @@@ static void plugin_free_data_sets (void
  int plugin_register_data_set (const data_set_t *ds)
  {
        data_set_t *ds_copy;
 -      int i;
 +      size_t i;
  
        if ((data_sets != NULL)
                        && (c_avl_get (data_sets, ds->type, NULL) == 0))
@@@ -1623,21 -1525,7 +1623,21 @@@ int plugin_unregister_write (const cha
  
  int plugin_unregister_flush (const char *name)
  {
 -      return (plugin_unregister (list_flush, name));
 +      plugin_ctx_t ctx = plugin_get_ctx ();
 +
 +      if (ctx.flush_interval != 0)
 +      {
 +              char *flush_name;
 +
 +              flush_name = plugin_flush_callback_name (name);
 +              if (flush_name != NULL)
 +              {
 +                      plugin_unregister_read(flush_name);
 +                      sfree(flush_name);
 +              }
 +      }
 +
 +      return plugin_unregister (list_flush, name);
  }
  
  int plugin_unregister_missing (const char *name)
@@@ -1725,8 -1613,6 +1725,6 @@@ void plugin_init_all (void
                write_threads_num = 5;
        }
  
-       start_write_threads ((size_t) write_threads_num);
        if ((list_init == NULL) && (read_heap == NULL))
                return;
  
                le = le->next;
        }
  
+       start_write_threads ((size_t) write_threads_num);
        max_read_interval = global_option_get_time ("MaxReadInterval",
                        DEFAULT_MAX_READ_INTERVAL);
  
@@@ -2143,8 -2031,8 +2143,8 @@@ static int plugin_dispatch_values_inter
        if (ds->ds_num != vl->values_len)
        {
                ERROR ("plugin_dispatch_values: ds->type = %s: "
 -                              "(ds->ds_num = %i) != "
 -                              "(vl->values_len = %i)",
 +                              "(ds->ds_num = %zu) != "
 +                              "(vl->values_len = %zu)",
                                ds->type, ds->ds_num, vl->values_len);
                return (-1);
        }
index 0000000,7b1c7d2..a8ca7db
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,367 +1,338 @@@
 -static int ignorelist_append_regex(ignorelist_t *il, const char *entry)
+ /**
+  * collectd - src/utils_ignorelist.c
+  * Copyright (C) 2006 Lubos Stanek <lubek at users.sourceforge.net>
+  * Copyright (C) 2008 Florian Forster <octo at collectd.org>
+  *
+  * This program is free software; you can redistribute it and/
+  * or modify it under the terms of the GNU General Public Li-
+  * cence as published by the Free Software Foundation; either
+  * version 2 of the Licence, or any later version.
+  *
+  * This program is distributed in the hope that it will be use-
+  * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+  * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  * See the GNU General Public Licence for more details.
+  *
+  * You should have received a copy of the GNU General Public
+  * Licence along with this program; if not, write to the Free
+  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+  * USA.
+  *
+  * Authors:
+  *   Lubos Stanek <lubek at users.sourceforge.net>
+  *   Florian Forster <octo at collectd.org>
+  **/
+ /**
+  * ignorelist handles plugin's list of configured collectable
+  * entries with global ignore action
+  **/
+ /**
+  * Usage:
+  * 
+  * Define plugin's global pointer variable of type ignorelist_t:
+  *   ignorelist_t *myconfig_ignore;
+  * If you know the state of the global ignore (IgnoreSelected),
+  * allocate the variable with:
+  *   myconfig_ignore = ignorelist_create (YourKnownIgnore);
+  * If you do not know the state of the global ignore,
+  * initialize the global variable and set the ignore flag later:
+  *   myconfig_ignore = ignorelist_init ();
+  * Append single entries in your cf_register'ed callback function:
+  *   ignorelist_add (myconfig_ignore, newentry);
+  * When you hit the IgnoreSelected config option,
+  * offer it to the list:
+  *   ignorelist_ignore (myconfig_ignore, instantly_got_value_of_ignore);
+  * That is all for the ignorelist initialization.
+  * Later during read and write (plugin's registered functions) get
+  * the information whether this entry would be collected or not:
+  *   if (ignorelist_match (myconfig_ignore, thisentry))
+  *     return;
+  **/
+ #if HAVE_CONFIG_H
+ # include "config.h"
+ #endif
+ #include "common.h"
+ #include "plugin.h"
+ #include "utils_ignorelist.h"
+ /*
+  * private prototypes
+  */
+ struct ignorelist_item_s
+ {
+ #if HAVE_REGEX_H
+       regex_t *rmatch;        /* regular expression entry identification */
+ #endif
+       char *smatch;           /* string entry identification */
+       struct ignorelist_item_s *next;
+ };
+ typedef struct ignorelist_item_s ignorelist_item_t;
+ struct ignorelist_s
+ {
+       int ignore;             /* ignore entries */
+       ignorelist_item_t *head;        /* pointer to the first entry */
+ };
+ /* *** *** *** ********************************************* *** *** *** */
+ /* *** *** *** *** *** ***   private functions   *** *** *** *** *** *** */
+ /* *** *** *** ********************************************* *** *** *** */
+ static inline void ignorelist_append (ignorelist_t *il, ignorelist_item_t *item)
+ {
+       assert ((il != NULL) && (item != NULL));
+       item->next = il->head;
+       il->head = item;
+ }
+ #if HAVE_REGEX_H
 -      int rcompile;
 -      regex_t *regtemp;
 -      int errsize;
 -      char *regerr = NULL;
 -      ignorelist_item_t *new;
++static int ignorelist_append_regex(ignorelist_t *il, const char *re_str)
+ {
 -      /* create buffer */
 -      if ((regtemp = malloc(sizeof(regex_t))) == NULL)
++      regex_t *re;
++      ignorelist_item_t *entry;
++      int status;
 -              ERROR ("cannot allocate new config entry");
 -              return (1);
++      re = malloc (sizeof (*re));
++      if (re == NULL)
+       {
 -      memset (regtemp, '\0', sizeof(regex_t));
++              ERROR ("utils_ignorelist: malloc failed");
++              return (ENOMEM);
+       }
 -      /* compile regex */
 -      if ((rcompile = regcomp (regtemp, entry, REG_EXTENDED)) != 0)
++      memset (re, 0, sizeof (*re));
 -              /* prepare message buffer */
 -              errsize = regerror(rcompile, regtemp, NULL, 0);
 -              if (errsize)
 -                      regerr = smalloc(errsize);
 -              /* get error message */
 -              if (regerror (rcompile, regtemp, regerr, errsize))
 -              {
 -                      fprintf (stderr, "Cannot compile regex %s: %i/%s",
 -                                      entry, rcompile, regerr);
 -                      ERROR ("Cannot compile regex %s: %i/%s",
 -                                      entry, rcompile, regerr);
 -              }
 -              else
 -              {
 -                      fprintf (stderr, "Cannot compile regex %s: %i",
 -                                      entry, rcompile);
 -                      ERROR ("Cannot compile regex %s: %i",
 -                                      entry, rcompile);
 -              }
 -
 -              if (errsize)
 -                      sfree (regerr);
 -              regfree (regtemp);
 -              sfree (regtemp);
 -              return (1);
++      status = regcomp (re, re_str, REG_EXTENDED);
++      if (status != 0)
+       {
 -      DEBUG("regex compiled: %s - %i", entry, rcompile);
++              char errbuf[1024] = "";
++              regerror (status, re, errbuf, sizeof (errbuf));
++              ERROR ("utils_ignorelist: regcomp failed: %s", errbuf);
++              regfree (re);
++              sfree (re);
++              return (status);
+       }
 -      /* create new entry */
 -      if ((new = malloc(sizeof(ignorelist_item_t))) == NULL)
 -              ERROR ("cannot allocate new config entry");
 -              regfree (regtemp);
 -              sfree (regtemp);
 -              return (1);
++      entry = malloc (sizeof (*entry));
++      if (entry == NULL)
+       {
 -      memset (new, '\0', sizeof(ignorelist_item_t));
 -      new->rmatch = regtemp;
 -
 -      /* append new entry */
 -      ignorelist_append (il, new);
++              ERROR ("utils_ignorelist: malloc failed");
++              regfree (re);
++              sfree (re);
++              return (ENOMEM);
+       }
 -} /* int ignorelist_append_regex(ignorelist_t *il, const char *entry) */
++      memset (entry, 0, sizeof (*entry));
++      entry->rmatch = re;
++      ignorelist_append (il, entry);
+       return (0);
 - * return 1 for success
++} /* int ignorelist_append_regex */
+ #endif
+ static int ignorelist_append_string(ignorelist_t *il, const char *entry)
+ {
+       ignorelist_item_t *new;
+       /* create new entry */
+       if ((new = malloc(sizeof(ignorelist_item_t))) == NULL )
+       {
+               ERROR ("cannot allocate new entry");
+               return (1);
+       }
+       memset (new, '\0', sizeof(ignorelist_item_t));
+       new->smatch = sstrdup(entry);
+       /* append new entry */
+       ignorelist_append (il, new);
+       return (0);
+ } /* int ignorelist_append_string(ignorelist_t *il, const char *entry) */
+ #if HAVE_REGEX_H
+ /*
+  * check list for entry regex match
+  * return 1 if found
+  */
+ static int ignorelist_match_regex (ignorelist_item_t *item, const char *entry)
+ {
+       assert ((item != NULL) && (item->rmatch != NULL)
+                       && (entry != NULL) && (strlen (entry) > 0));
+       /* match regex */
+       if (regexec (item->rmatch, entry, 0, NULL, 0) == 0)
+               return (1);
+       return (0);
+ } /* int ignorelist_match_regex (ignorelist_item_t *item, const char *entry) */
+ #endif
+ /*
+  * check list for entry string match
+  * return 1 if found
+  */
+ static int ignorelist_match_string (ignorelist_item_t *item, const char *entry)
+ {
+       assert ((item != NULL) && (item->smatch != NULL)
+                       && (entry != NULL) && (strlen (entry) > 0));
+       if (strcmp (entry, item->smatch) == 0)
+               return (1);
+       return (0);
+ } /* int ignorelist_match_string (ignorelist_item_t *item, const char *entry) */
+ /* *** *** *** ******************************************** *** *** *** */
+ /* *** *** *** *** *** ***   public functions   *** *** *** *** *** *** */
+ /* *** *** *** ******************************************** *** *** *** */
+ /*
+  * create the ignorelist_t with known ignore state
+  * return pointer to ignorelist_t
+  */
+ ignorelist_t *ignorelist_create (int invert)
+ {
+       ignorelist_t *il;
+       /* smalloc exits if it failes */
+       il = (ignorelist_t *) smalloc (sizeof (ignorelist_t));
+       memset (il, '\0', sizeof (ignorelist_t));
+       /*
+        * ->ignore == 0  =>  collect
+        * ->ignore == 1  =>  ignore
+        */
+       il->ignore = invert ? 0 : 1;
+       return (il);
+ } /* ignorelist_t *ignorelist_create (int ignore) */
+ /*
+  * free memory used by ignorelist_t
+  */
+ void ignorelist_free (ignorelist_t *il)
+ {
+       ignorelist_item_t *this;
+       ignorelist_item_t *next;
+       if (il == NULL)
+               return;
+       for (this = il->head; this != NULL; this = next)
+       {
+               next = this->next;
+ #if HAVE_REGEX_H
+               if (this->rmatch != NULL)
+               {
+                       regfree (this->rmatch);
+                       sfree (this->rmatch);
+                       this->rmatch = NULL;
+               }
+ #endif
+               if (this->smatch != NULL)
+               {
+                       sfree (this->smatch);
+                       this->smatch = NULL;
+               }
+               sfree (this);
+       }
+       sfree (il);
+       il = NULL;
+ } /* void ignorelist_destroy (ignorelist_t *il) */
+ /*
+  * set ignore state of the ignorelist_t
+  */
+ void ignorelist_set_invert (ignorelist_t *il, int invert)
+ {
+       if (il == NULL)
+       {
+               DEBUG("ignore call with ignorelist_t == NULL");
+               return;
+       }
+       il->ignore = invert ? 0 : 1;
+ } /* void ignorelist_set_invert (ignorelist_t *il, int ignore) */
+ /*
+  * append entry into ignorelist_t
 -      int ret;
++ * return 0 for success
+  */
+ int ignorelist_add (ignorelist_t *il, const char *entry)
+ {
 -              DEBUG("I'm about to add regex entry: %s", entry_copy);
 -              ret = ignorelist_append_regex(il, entry_copy);
+       size_t entry_len;
+       if (il == NULL)
+       {
+               DEBUG ("add called with ignorelist_t == NULL");
+               return (1);
+       }
+       entry_len = strlen (entry);
+       /* append nothing */
+       if (entry_len == 0)
+       {
+               DEBUG("not appending: empty entry");
+               return (1);
+       }
+ #if HAVE_REGEX_H
+       /* regex string is enclosed in "/.../" */
+       if ((entry_len > 2) && (entry[0] == '/') && entry[entry_len - 1] == '/')
+       {
+               char *entry_copy;
+               size_t entry_copy_size;
++              int status;
+               /* We need to copy `entry' since it's const */
+               entry_copy_size = entry_len - 1;
+               entry_copy = smalloc (entry_copy_size);
+               sstrncpy (entry_copy, entry + 1, entry_copy_size);
 -      else
++              status = ignorelist_append_regex(il, entry_copy);
+               sfree (entry_copy);
++              return status;
+       }
 -      {
 -              DEBUG("to add entry: %s", entry);
 -              ret = ignorelist_append_string(il, entry);
 -      }
+ #endif
 -      return (ret);
++      return ignorelist_append_string(il, entry);
+ } /* int ignorelist_add (ignorelist_t *il, const char *entry) */
+ /*
+  * check list for entry
+  * return 1 for ignored entry
+  */
+ int ignorelist_match (ignorelist_t *il, const char *entry)
+ {
+       ignorelist_item_t *traverse;
+       /* if no entries, collect all */
+       if ((il == NULL) || (il->head == NULL))
+               return (0);
+       if ((entry == NULL) || (strlen (entry) == 0))
+               return (0);
+       /* traverse list and check entries */
+       for (traverse = il->head; traverse != NULL; traverse = traverse->next)
+       {
+ #if HAVE_REGEX_H
+               if (traverse->rmatch != NULL)
+               {
+                       if (ignorelist_match_regex (traverse, entry))
+                               return (il->ignore);
+               }
+               else
+ #endif
+               {
+                       if (ignorelist_match_string (traverse, entry))
+                               return (il->ignore);
+               }
+       } /* for traverse */
+       return (1 - il->ignore);
+ } /* int ignorelist_match (ignorelist_t *il, const char *entry) */
diff --combined src/snmp.c
@@@ -61,7 -61,7 +61,7 @@@ struct data_definition_
    instance_t instance;
    char *instance_prefix;
    oid_t *values;
 -  int values_len;
 +  size_t values_len;
    double scale;
    double shift;
    struct data_definition_s *next;
@@@ -313,7 -313,7 +313,7 @@@ static int csnmp_config_add_data_value
    dd->values = (oid_t *) malloc (sizeof (oid_t) * ci->values_num);
    if (dd->values == NULL)
      return (-1);
 -  dd->values_len = ci->values_num;
 +  dd->values_len = (size_t) ci->values_num;
  
    for (i = 0; i < ci->values_num; i++)
    {
@@@ -459,7 -459,7 +459,7 @@@ static int csnmp_config_add_data (oconf
      return (-1);
    }
  
 -  DEBUG ("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = %i }",
 +  DEBUG ("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = %zu }",
        dd->name, dd->type, (dd->is_table != 0) ? "true" : "false", dd->values_len);
  
    if (data_head == NULL)
@@@ -645,6 -645,7 +645,6 @@@ static int csnmp_config_add_host (oconf
    /* Registration stuff. */
    char cb_name[DATA_MAX_NAME_LEN];
    user_data_t cb_data;
 -  struct timespec cb_interval;
  
    hd = (host_definition_t *) malloc (sizeof (host_definition_t));
    if (hd == NULL)
    cb_data.data = hd;
    cb_data.free_func = csnmp_host_definition_destroy;
  
 -  CDTIME_T_TO_TIMESPEC (hd->interval, &cb_interval);
 -
    status = plugin_register_complex_read (/* group = */ NULL, cb_name,
 -      csnmp_read_host, /* interval = */ &cb_interval,
 -      /* user_data = */ &cb_data);
 +      csnmp_read_host, hd->interval, /* user_data = */ &cb_data);
    if (status != 0)
    {
      ERROR ("snmp plugin: Registering complex read function failed.");
@@@ -924,8 -928,7 +924,7 @@@ static value_t csnmp_value_list_to_valu
      tmp_unsigned = (uint32_t) *vl->val.integer;
      tmp_signed = (int32_t) *vl->val.integer;
  
-     if ((vl->type == ASN_INTEGER)
-         || (vl->type == ASN_GAUGE))
+     if (vl->type == ASN_INTEGER)
        prefer_signed = 1;
  
      DEBUG ("snmp plugin: Parsed int32 value is %"PRIu64".", tmp_unsigned);
    return (ret);
  } /* value_t csnmp_value_list_to_value */
  
 +/* csnmp_strvbcopy_hexstring converts the bit string contained in "vb" to a hex
 + * representation and writes it to dst. Returns zero on success and ENOMEM if
 + * dst is not large enough to hold the string. dst is guaranteed to be
 + * nul-terminated. */
  static int csnmp_strvbcopy_hexstring (char *dst, /* {{{ */
      const struct variable_list *vb, size_t dst_size)
  {
    size_t buffer_free;
    size_t i;
  
 +  dst[0] = 0;
 +
    buffer_ptr = dst;
    buffer_free = dst_size;
  
  
      status = snprintf (buffer_ptr, buffer_free,
          (i == 0) ? "%02x" : ":%02x", (unsigned int) vb->val.bitstring[i]);
 +    assert (status >= 0);
  
 -    if (status >= buffer_free)
 +    if (((size_t) status) >= buffer_free) /* truncated */
      {
 -      buffer_ptr += (buffer_free - 1);
 -      *buffer_ptr = 0;
 -      return (dst_size + (buffer_free - status));
 +      dst[dst_size - 1] = 0;
 +      return ENOMEM;
      }
      else /* if (status < buffer_free) */
      {
 -      buffer_ptr += status;
 -      buffer_free -= status;
 +      buffer_ptr  += (size_t) status;
 +      buffer_free -= (size_t) status;
      }
    }
  
 -  return ((int) (dst_size - buffer_free));
 +  return 0;
  } /* }}} int csnmp_strvbcopy_hexstring */
  
 +/* csnmp_strvbcopy copies the octet string or bit string contained in vb to
 + * dst. If non-printable characters are detected, it will switch to a hex
 + * representation of the string. Returns zero on success, EINVAL if vb does not
 + * contain a string and ENOMEM if dst is not large enough to contain the
 + * string. */
  static int csnmp_strvbcopy (char *dst, /* {{{ */
      const struct variable_list *vb, size_t dst_size)
  {
      dst[i] = src[i];
    }
    dst[num_chars] = 0;
 +  dst[dst_size - 1] = 0;
  
 -  return ((int) vb->val_len);
 +  if (dst_size <= vb->val_len)
 +    return ENOMEM;
 +
 +  return 0;
  } /* }}} int csnmp_strvbcopy */
  
  static int csnmp_instance_list_add (csnmp_list_instances_t **head,
@@@ -1235,7 -1223,7 +1234,7 @@@ static int csnmp_dispatch_table (host_d
    csnmp_list_instances_t *instance_list_ptr;
    csnmp_table_values_t **value_table_ptr;
  
 -  int i;
 +  size_t i;
    _Bool have_more;
    oid_t current_suffix;
  
  
    instance_list_ptr = instance_list;
  
 -  value_table_ptr = calloc ((size_t) data->values_len, sizeof (*value_table_ptr));
 +  value_table_ptr = calloc (data->values_len, sizeof (*value_table_ptr));
    if (value_table_ptr == NULL)
      return (-1);
    for (i = 0; i < data->values_len; i++)
@@@ -1393,7 -1381,7 +1392,7 @@@ static int csnmp_read_table (host_defin
  
    const data_set_t *ds;
  
 -  uint32_t oid_list_len = (uint32_t) (data->values_len + 1);
 +  size_t oid_list_len = data->values_len + 1;
    /* Holds the last OID returned by the device. We use this in the GETNEXT
     * request to proceed. */
    oid_t oid_list[oid_list_len];
    _Bool oid_list_todo[oid_list_len];
  
    int status;
 -  int i;
 -  uint32_t j;
 +  size_t i;
  
    /* `value_list_head' and `value_list_tail' implement a linked list for each
     * value. `instance_list_head' and `instance_list_tail' implement a linked list of
  
    if (ds->ds_num != data->values_len)
    {
 -    ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i",
 +    ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu",
          data->type, ds->ds_num, data->values_len);
      return (-1);
    }
    else /* no InstanceFrom option specified. */
      oid_list_len--;
  
 -  for (j = 0; j < oid_list_len; j++)
 -    oid_list_todo[j] = 1;
 +  for (i = 0; i < oid_list_len; i++)
 +    oid_list_todo[i] = 1;
  
    /* We're going to construct n linked lists, one for each "value".
     * value_list_head will contain pointers to the heads of these linked lists,
      }
  
      oid_list_todo_num = 0;
 -    for (j = 0; j < oid_list_len; j++)
 +    for (i = 0; i < oid_list_len; i++)
      {
        /* Do not rerequest already finished OIDs */
 -      if (!oid_list_todo[j])
 +      if (!oid_list_todo[i])
          continue;
        oid_list_todo_num++;
 -      snmp_add_null_var (req, oid_list[j].oid, oid_list[j].oid_len);
 +      snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len);
      }
  
      if (oid_list_todo_num == 0)
          ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
          if (ret != 0)
          {
 -          DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
 +          DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; "
                "Value probably left its subtree.",
                host->name, data->name, i);
            oid_list_todo[i] = 0;
          if ((value_list_tail[i] != NULL)
              && (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0))
          {
 -          DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
 +          DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; "
                "Suffix is not increasing.",
                host->name, data->name, i);
            oid_list_todo[i] = 0;
@@@ -1674,7 -1663,7 +1673,7 @@@ static int csnmp_read_value (host_defin
    value_list_t vl = VALUE_LIST_INIT;
  
    int status;
 -  int i;
 +  size_t i;
  
    DEBUG ("snmp plugin: csnmp_read_value (host = %s, data = %s)",
        host->name, data->name);
  
    if (ds->ds_num != data->values_len)
    {
 -    ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i",
 +    ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu",
          data->type, ds->ds_num, data->values_len);
      return (-1);
    }