Merge branch 'collectd-5.5'
authorRuben Kerkhof <ruben@rubenkerkhof.com>
Fri, 5 Aug 2016 11:17:32 +0000 (13:17 +0200)
committerRuben Kerkhof <ruben@rubenkerkhof.com>
Fri, 5 Aug 2016 11:17:32 +0000 (13:17 +0200)
Conflicts:
src/pyvalues.c

1  2 
src/daemon/plugin.c
src/network.c
src/pyvalues.c

diff --combined src/daemon/plugin.c
@@@ -26,7 -26,6 +26,7 @@@
   **/
  
  #include "collectd.h"
 +
  #include "common.h"
  #include "plugin.h"
  #include "configfile.h"
@@@ -81,12 -80,6 +81,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
   */
@@@ -289,7 -282,7 +289,7 @@@ static int register_callback (llist_t *
                {
                        ERROR ("plugin: register_callback: "
                                        "llentry_create failed.");
 -                      free (key);
 +                      sfree (key);
                        destroy_callback (cf);
                        return (-1);
                }
@@@ -319,8 -312,8 +319,8 @@@ static void log_list_callbacks (llist_
  {
        char *str;
        int len;
 -      llentry_t *le;
        int i;
 +      llentry_t *le;
        int n;
        char **keys;
  
                *str = '\0';
                strjoin(str, len, keys, n, "', '");
                INFO("%s ['%s']", comment, str);
 -              free(str);
 +              sfree (str);
        }
 -      free(keys);
 +      sfree (keys);
  } /* }}} void log_list_callbacks */
  
  static int create_register_callback (llist_t **list, /* {{{ */
  {
        callback_func_t *cf;
  
 -      cf = (callback_func_t *) malloc (sizeof (*cf));
 +      cf = calloc (1, sizeof (*cf));
        if (cf == NULL)
        {
 -              ERROR ("plugin: create_register_callback: malloc failed.");
 +              ERROR ("plugin: create_register_callback: calloc failed.");
                return (-1);
        }
 -      memset (cf, 0, sizeof (*cf));
  
        cf->cf_callback = callback;
        if (ud == NULL)
@@@ -483,9 -477,7 +483,9 @@@ static void *plugin_read_thread (void _
        {
                read_func_t *rf;
                plugin_ctx_t old_ctx;
 +              cdtime_t start;
                cdtime_t now;
 +              cdtime_t elapsed;
                int status;
                int rf_type;
                int rc;
  
                DEBUG ("plugin_read_thread: Handling `%s'.", rf->rf_name);
  
 +              start = cdtime ();
 +
                old_ctx = plugin_set_ctx (rf->rf_ctx);
  
                if (rf_type == RF_SIMPLE)
                /* update the ``next read due'' field */
                now = cdtime ();
  
 +              /* calculate the time spent in the read function */
 +              elapsed = (now - start);
 +
 +              if (elapsed > rf->rf_effective_interval)
 +                      WARNING ("plugin_read_thread: read-function of the `%s' plugin took %.3f "
 +                              "seconds, which is above its read interval (%.3f seconds). You might "
 +                              "want to adjust the `Interval' or `ReadThreads' settings.",
 +                              rf->rf_name, CDTIME_T_TO_DOUBLE(elapsed),
 +                              CDTIME_T_TO_DOUBLE(rf->rf_effective_interval));
 +
 +              DEBUG ("plugin_read_thread: read-function of the `%s' plugin took "
 +                              "%.6f seconds.",
 +                              rf->rf_name, CDTIME_T_TO_DOUBLE(elapsed));
 +
                DEBUG ("plugin_read_thread: Effective interval of the "
 -                              "%s plugin is %.3f seconds.",
 +                              "`%s' plugin is %.3f seconds.",
                                rf->rf_name,
                                CDTIME_T_TO_DOUBLE (rf->rf_effective_interval));
  
                        rf->rf_next_read = now;
                }
  
 -              DEBUG ("plugin_read_thread: Next read of the %s plugin at %.3f.",
 +              DEBUG ("plugin_read_thread: Next read of the `%s' plugin at %.3f.",
                                rf->rf_name,
                                CDTIME_T_TO_DOUBLE (rf->rf_next_read));
  
  
  static void start_read_threads (int num)
  {
 -      int i;
 -
        if (read_threads != NULL)
                return;
  
        }
  
        read_threads_num = 0;
 -      for (i = 0; i < num; i++)
 +      for (int i = 0; i < num; i++)
        {
                if (pthread_create (read_threads + read_threads_num, NULL,
                                        plugin_read_thread, NULL) == 0)
  
  static void stop_read_threads (void)
  {
 -      int i;
 -
        if (read_threads == NULL)
                return;
  
        pthread_cond_broadcast (&read_cond);
        pthread_mutex_unlock (&read_lock);
  
 -      for (i = 0; i < read_threads_num; i++)
 +      for (int i = 0; i < read_threads_num; i++)
        {
                if (pthread_join (read_threads[i], NULL) != 0)
                {
@@@ -866,6 -846,8 +866,6 @@@ static void *plugin_write_thread (void 
  
  static void start_write_threads (size_t num) /* {{{ */
  {
 -      size_t i;
 -
        if (write_threads != NULL)
                return;
  
        }
  
        write_threads_num = 0;
 -      for (i = 0; i < num; i++)
 +      for (size_t i = 0; i < num; i++)
        {
                int status;
  
  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");
        }
   */
  void plugin_set_dir (const char *dir)
  {
 -      if (plugindir != NULL)
 -              free (plugindir);
 +      sfree (plugindir);
  
        if (dir == NULL)
 -              plugindir = NULL;
 -      else if ((plugindir = strdup (dir)) == NULL)
        {
 -              char errbuf[1024];
 -              ERROR ("strdup failed: %s",
 -                              sstrerror (errno, errbuf, sizeof (errbuf)));
 +              plugindir = NULL;
 +              return;
        }
 +
 +      plugindir = strdup (dir);
 +      if (plugindir == NULL)
 +              ERROR ("plugin_set_dir: strdup(\"%s\") failed", dir);
  }
  
  static _Bool plugin_is_loaded (char const *name)
        int status;
  
        if (plugins_loaded == NULL)
 -              plugins_loaded = c_avl_create ((void *) strcasecmp);
 +              plugins_loaded = c_avl_create ((int (*) (const void *, const void *)) strcasecmp);
        assert (plugins_loaded != NULL);
  
        status = c_avl_get (plugins_loaded, name, /* ret_value = */ NULL);
@@@ -1101,7 -1083,6 +1101,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
@@@ -1238,13 -1219,14 +1238,13 @@@ int plugin_register_read (const char *n
        read_func_t *rf;
        int status;
  
 -      rf = malloc (sizeof (*rf));
 +      rf = calloc (1, sizeof (*rf));
        if (rf == NULL)
        {
 -              ERROR ("plugin_register_read: malloc failed.");
 +              ERROR ("plugin_register_read: calloc failed.");
                return (ENOMEM);
        }
  
 -      memset (rf, 0, sizeof (read_func_t));
        rf->rf_callback = (void *) callback;
        rf->rf_udata.data = NULL;
        rf->rf_udata.free_func = NULL;
  
  int plugin_register_complex_read (const char *group, const char *name,
                plugin_read_cb callback,
 -              const struct timespec *interval,
 +              cdtime_t interval,
                user_data_t *user_data)
  {
        read_func_t *rf;
        int status;
  
 -      rf = malloc (sizeof (*rf));
 +      rf = calloc (1,sizeof (*rf));
        if (rf == NULL)
        {
 -              ERROR ("plugin_register_complex_read: malloc failed.");
 +              ERROR ("plugin_register_complex_read: calloc failed.");
                return (ENOMEM);
        }
  
 -      memset (rf, 0, sizeof (read_func_t));
        rf->rf_callback = (void *) callback;
        if (group != NULL)
                sstrncpy (rf->rf_group, group, sizeof (rf->rf_group));
                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)
@@@ -1316,104 -1302,11 +1316,104 @@@ 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)
 +{
 +      const char *flush_prefix = "flush/";
 +      size_t prefix_size;
 +      char *flush_name;
 +      size_t name_size;
 +
 +      prefix_size = strlen(flush_prefix);
 +      name_size = strlen(name);
 +
 +      flush_name = malloc (name_size + prefix_size + 1);
 +      if (flush_name == NULL)
 +      {
 +              ERROR ("plugin_flush_callback_name: malloc failed.");
 +              return (NULL);
 +      }
 +
 +      sstrncpy (flush_name, flush_prefix, prefix_size + 1);
 +      sstrncpy (flush_name + prefix_size, name, name_size + 1);
 +
 +      return flush_name;
 +} /* static char *plugin_flush_callback_name */
 +
  int plugin_register_flush (const char *name,
                plugin_flush_cb callback, user_data_t *ud)
  {
 -      return (create_register_callback (&list_flush, name,
 -                              (void *) callback, ud));
 +      int status;
 +      plugin_ctx_t ctx = plugin_get_ctx ();
 +
 +      status = create_register_callback (&list_flush, name,
 +              (void *) callback, ud);
 +      if (status != 0)
 +              return status;
 +
 +      if (ctx.flush_interval != 0)
 +      {
 +              char *flush_name;
 +              flush_callback_t *cb;
 +
 +              flush_name = plugin_flush_callback_name (name);
 +              if (flush_name == NULL)
 +                      return (-1);
 +
 +              cb = malloc(sizeof (*cb));
 +              if (cb == NULL)
 +              {
 +                      ERROR ("plugin_register_flush: malloc failed.");
 +                      sfree (flush_name);
 +                      return (-1);
 +              }
 +
 +              cb->name = strdup (name);
 +              if (cb->name == NULL)
 +              {
 +                      ERROR ("plugin_register_flush: strdup failed.");
 +                      sfree (cb);
 +                      sfree (flush_name);
 +                      return (-1);
 +              }
 +              cb->timeout = ctx.flush_timeout;
 +
 +              ud->data = cb;
 +              ud->free_func = plugin_flush_timeout_callback_free;
 +
 +              status = plugin_register_complex_read (
 +                      /* group     = */ "flush",
 +                      /* name      = */ flush_name,
 +                      /* callback  = */ plugin_flush_timeout_callback,
 +                      /* interval  = */ ctx.flush_interval,
 +                      /* user data = */ ud);
 +
 +              sfree (flush_name);
 +              if (status != 0)
 +              {
 +                      sfree (cb->name);
 +                      sfree (cb);
 +                      return status;
 +              }
 +      }
 +
 +      return 0;
  } /* int plugin_register_flush */
  
  int plugin_register_missing (const char *name,
@@@ -1454,6 -1347,7 +1454,6 @@@ static void plugin_free_data_sets (void
  int plugin_register_data_set (const data_set_t *ds)
  {
        data_set_t *ds_copy;
 -      int i;
  
        if ((data_sets != NULL)
                        && (c_avl_get (data_sets, ds->type, NULL) == 0))
                        return (-1);
        }
  
 -      ds_copy = (data_set_t *) malloc (sizeof (data_set_t));
 +      ds_copy = malloc (sizeof (*ds_copy));
        if (ds_copy == NULL)
                return (-1);
        memcpy(ds_copy, ds, sizeof (data_set_t));
  
 -      ds_copy->ds = (data_source_t *) malloc (sizeof (data_source_t)
 +      ds_copy->ds = malloc (sizeof (*ds_copy->ds)
                        * ds->ds_num);
        if (ds_copy->ds == NULL)
        {
 -              free (ds_copy);
 +              sfree (ds_copy);
                return (-1);
        }
  
 -      for (i = 0; i < ds->ds_num; i++)
 +      for (size_t i = 0; i < ds->ds_num; i++)
                memcpy (ds_copy->ds + i, ds->ds + i, sizeof (data_source_t));
  
        return (c_avl_insert (data_sets, (void *) ds_copy->type, (void *) ds_copy));
@@@ -1631,21 -1525,7 +1631,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)
@@@ -1684,12 -1564,11 +1684,12 @@@ int plugin_unregister_notification (con
        return (plugin_unregister (list_notification, name));
  }
  
 -void plugin_init_all (void)
 +int plugin_init_all (void)
  {
        char const *chain_name;
        llentry_t *le;
        int status;
 +      int ret = 0;
  
        /* Init the value cache */
        uc_init ();
        }
  
        if ((list_init == NULL) && (read_heap == NULL))
 -              return;
 +              return ret;
  
        /* Calling all init callbacks before checking if read callbacks
         * are available allows the init callbacks to register the read
                         * handling themselves. */
                        /* FIXME: Unload _all_ functions */
                        plugin_unregister_read (le->key);
 +                      ret = -1;
                }
  
                le = le->next;
                if (num != -1)
                        start_read_threads ((num > 0) ? num : 5);
        }
 +      return ret;
  } /* void plugin_init_all */
  
  /* TODO: Rename this function. */
@@@ -1969,15 -1846,14 +1969,15 @@@ int plugin_flush (const char *plugin, c
    return (0);
  } /* int plugin_flush */
  
 -void plugin_shutdown_all (void)
 +int plugin_shutdown_all (void)
  {
        llentry_t *le;
 +      int ret = 0;  // Assume success.
  
-       stop_read_threads ();
        destroy_all_callbacks (&list_init);
  
+       stop_read_threads ();
        pthread_mutex_lock (&read_lock);
        llist_destroy (read_list);
        read_list = NULL;
  
        destroy_read_heap ();
  
+       /* blocks until all write threads have shut down. */
+       stop_write_threads ();
+       /* ask all plugins to write out the state they kept. */
        plugin_flush (/* plugin = */ NULL,
                        /* timeout = */ 0,
                        /* identifier = */ NULL);
                 * after callback returns. */
                le = le->next;
  
 -              (*callback) ();
 +              if ((*callback) () != 0)
 +                      ret = -1;
  
                plugin_set_ctx (old_ctx);
        }
  
-       stop_write_threads ();
        /* Write plugins which use the `user_data' pointer usually need the
         * same data available to the flush callback. If this is the case, set
         * the free_function to NULL when registering the flush callback and to
  
        plugin_free_loaded ();
        plugin_free_data_sets ();
 +      return (ret);
  } /* void plugin_shutdown_all */
  
  int plugin_dispatch_missing (const value_list_t *vl) /* {{{ */
@@@ -2088,10 -1964,8 +2090,10 @@@ static int plugin_dispatch_values_inter
  
        int free_meta_data = 0;
  
 -      if ((vl == NULL) || (vl->type[0] == 0)
 -                      || (vl->values == NULL) || (vl->values_len < 1))
 +      assert(vl);
 +      assert(vl->plugin);
 +
 +      if (vl->type[0] == 0 || vl->values == NULL || vl->values_len < 1)
        {
                ERROR ("plugin_dispatch_values: Invalid value list "
                                "from plugin %s.", vl->plugin);
        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);
        }
                         * don't get confused.. */
                        if (saved_values != NULL)
                        {
 -                              free (vl->values);
 +                              sfree (vl->values);
                                vl->values     = saved_values;
                                vl->values_len = saved_values_len;
                        }
         * confused.. */
        if (saved_values != NULL)
        {
 -              free (vl->values);
 +              sfree (vl->values);
                vl->values     = saved_values;
                vl->values_len = saved_values_len;
        }
@@@ -2356,7 -2230,7 +2358,7 @@@ int plugin_dispatch_multivalue (value_l
  
        assert (template->values_len == 1);
  
 -  /* Calculate sum for Gauge to calculate percent if needed */
 +      /* Calculate sum for Gauge to calculate percent if needed */
        if (DS_TYPE_GAUGE == store_type)        {
                va_start (ap, store_type);
                while (42)
@@@ -2577,12 -2451,13 +2579,12 @@@ static int plugin_notification_meta_ad
      return (-1);
    }
  
 -  meta = (notification_meta_t *) malloc (sizeof (notification_meta_t));
 +  meta = calloc (1, sizeof (*meta));
    if (meta == NULL)
    {
 -    ERROR ("plugin_notification_meta_add: malloc failed.");
 +    ERROR ("plugin_notification_meta_add: calloc failed.");
      return (-1);
    }
 -  memset (meta, 0, sizeof (notification_meta_t));
  
    sstrncpy (meta->name, name, sizeof (meta->name));
    meta->type = type;
@@@ -2679,12 -2554,14 +2681,12 @@@ int plugin_notification_meta_add_boolea
  int plugin_notification_meta_copy (notification_t *dst,
      const notification_t *src)
  {
 -  notification_meta_t *meta;
 -
    assert (dst != NULL);
    assert (src != NULL);
    assert (dst != src);
    assert ((src->meta == NULL) || (src->meta != dst->meta));
  
 -  for (meta = src->meta; meta != NULL; meta = meta->next)
 +  for (notification_meta_t *meta = src->meta; meta != NULL; meta = meta->next)
    {
      if (meta->type == NM_TYPE_STRING)
        plugin_notification_meta_add_string (dst, meta->name,
@@@ -2724,11 -2601,7 +2726,11 @@@ int plugin_notification_meta_free (noti
  
      if (this->type == NM_TYPE_STRING)
      {
 -      free ((char *)this->nm_value.nm_string);
 +      /* Assign to a temporary variable to work around nm_string's const
 +       * modifier. */
 +      void *tmp = (void *) this->nm_value.nm_string;
 +
 +      sfree (tmp);
        this->nm_value.nm_string = NULL;
      }
      sfree (this);
@@@ -2835,7 -2708,7 +2837,7 @@@ static void *plugin_thread_start (void 
  
        plugin_set_ctx (plugin_thread->ctx);
  
 -      free (plugin_thread);
 +      sfree (plugin_thread);
  
        return start_routine (plugin_arg);
  } /* void *plugin_thread_start */
diff --combined src/network.c
  #define _BSD_SOURCE /* For struct ip_mreq */
  
  #include "collectd.h"
 +
  #include "plugin.h"
  #include "common.h"
  #include "configfile.h"
  #include "utils_fbhash.h"
 -#include "utils_avltree.h"
  #include "utils_cache.h"
  #include "utils_complain.h"
  
  #include "network.h"
  
 -#if HAVE_PTHREAD_H
 -# include <pthread.h>
 -#endif
 -#if HAVE_SYS_SOCKET_H
 -# include <sys/socket.h>
 -#endif
  #if HAVE_NETDB_H
  # include <netdb.h>
  #endif
@@@ -53,6 -59,7 +53,6 @@@
  #endif
  
  #if HAVE_LIBGCRYPT
 -# include <pthread.h>
  # if defined __APPLE__
  /* default xcode compiler throws warnings even when deprecated functionality
   * is not used. -Werror breaks the build because of erroneous warnings.
@@@ -276,8 -283,8 +276,8 @@@ typedef struct receive_list_entry_s rec
  static int network_config_ttl = 0;
  /* Ethernet - (IPv6 + UDP) = 1500 - (40 + 8) = 1452 */
  static size_t network_config_packet_size = 1452;
 -static int network_config_forward = 0;
 -static int network_config_stats = 0;
 +static _Bool network_config_forward = 0;
 +static _Bool network_config_stats = 0;
  
  static sockent_t *sending_sockets = NULL;
  
@@@ -303,7 -310,6 +303,7 @@@ static pthread_t dispatch_thread_id
  static char            *send_buffer;
  static char            *send_buffer_ptr;
  static int              send_buffer_fill;
 +static cdtime_t         send_buffer_last_update;
  static value_list_t     send_buffer_vl = VALUE_LIST_STATIC;
  static pthread_mutex_t  send_buffer_lock = PTHREAD_MUTEX_INITIALIZER;
  
@@@ -347,7 -353,7 +347,7 @@@ static _Bool check_send_okay (const val
    _Bool received = 0;
    int status;
  
 -  if (network_config_forward != 0)
 +  if (network_config_forward)
      return (1);
  
    if (vl->meta == NULL)
  
  static _Bool check_notify_received (const notification_t *n) /* {{{ */
  {
 -  notification_meta_t *ptr;
 -
 -  for (ptr = n->meta; ptr != NULL; ptr = ptr->next)
 +  for (notification_meta_t *ptr = n->meta; ptr != NULL; ptr = ptr->next)
      if ((strcmp ("network:received", ptr->name) == 0)
          && (ptr->type == NM_TYPE_BOOLEAN))
        return ((_Bool) ptr->nm_value.nm_boolean);
@@@ -408,10 -416,10 +408,10 @@@ static int network_dispatch_values (val
  {
    int status;
  
 -  if ((vl->time <= 0)
 -      || (strlen (vl->host) <= 0)
 -      || (strlen (vl->plugin) <= 0)
 -      || (strlen (vl->type) <= 0))
 +  if ((vl->time == 0)
 +      || (strlen (vl->host) == 0)
 +      || (strlen (vl->plugin) == 0)
 +      || (strlen (vl->type) == 0))
      return (-EINVAL);
  
    if (!check_receive_okay (vl))
@@@ -490,7 -498,7 +490,7 @@@ static int network_dispatch_notificatio
  } /* }}} int network_dispatch_notification */
  
  #if HAVE_LIBGCRYPT
- static void network_init_gcrypt (void) /* {{{ */
+ static int network_init_gcrypt (void) /* {{{ */
  {
    gcry_error_t err;
  
     * Because you can't know in a library whether another library has
     * already initialized the library */
    if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P))
-     return;
+     return (0);
  
   /* http://www.gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html
    * To ensure thread-safety, it's important to set GCRYCTL_SET_THREAD_CBS
    if (err)
    {
      ERROR ("network plugin: gcry_control (GCRYCTL_SET_THREAD_CBS) failed: %s", gcry_strerror (err));
-     abort ();
+     return (-1);
    }
  # endif
  
    if (err)
    {
      ERROR ("network plugin: gcry_control (GCRYCTL_INIT_SECMEM) failed: %s", gcry_strerror (err));
-     abort ();
+     return (-1);
    }
  
    gcry_control (GCRYCTL_INITIALIZATION_FINISHED);
- } /* }}} void network_init_gcrypt */
+   return (0);
+ } /* }}} int network_init_gcrypt */
  
  static gcry_cipher_hd_t network_get_aes256_cypher (sockent_t *se, /* {{{ */
      const void *iv, size_t iv_size, const char *username)
  } /* }}} int network_get_aes256_cypher */
  #endif /* HAVE_LIBGCRYPT */
  
 -static int write_part_values (char **ret_buffer, int *ret_buffer_len,
 +static int write_part_values (char **ret_buffer, size_t *ret_buffer_len,
                const data_set_t *ds, const value_list_t *vl)
  {
        char *packet_ptr;
 -      int packet_len;
 +      size_t packet_len;
        int num_values;
  
        part_header_t pkg_ph;
        uint8_t      *pkg_values_types;
        value_t      *pkg_values;
  
 -      int offset;
 -      int i;
 +      size_t offset;
  
        num_values = vl->values_len;
        packet_len = sizeof (part_header_t) + sizeof (uint16_t)
        if (*ret_buffer_len < packet_len)
                return (-1);
  
 -      pkg_values_types = (uint8_t *) malloc (num_values * sizeof (uint8_t));
 +      pkg_values_types = malloc (num_values * sizeof (*pkg_values_types));
        if (pkg_values_types == NULL)
        {
                ERROR ("network plugin: write_part_values: malloc failed.");
                return (-1);
        }
  
 -      pkg_values = (value_t *) malloc (num_values * sizeof (value_t));
 +      pkg_values = malloc (num_values * sizeof (*pkg_values));
        if (pkg_values == NULL)
        {
                free (pkg_values_types);
  
        pkg_num_values = htons ((uint16_t) vl->values_len);
  
 -      for (i = 0; i < num_values; i++)
 +      for (int i = 0; i < num_values; i++)
        {
                pkg_values_types[i] = (uint8_t) ds->ds[i].type;
                switch (ds->ds[i].type)
        return (0);
  } /* int write_part_values */
  
 -static int write_part_number (char **ret_buffer, int *ret_buffer_len,
 +static int write_part_number (char **ret_buffer, size_t *ret_buffer_len,
                int type, uint64_t value)
  {
        char *packet_ptr;
 -      int packet_len;
 +      size_t packet_len;
  
        part_header_t pkg_head;
        uint64_t pkg_value;
  
 -      int offset;
 +      size_t offset;
  
        packet_len = sizeof (pkg_head) + sizeof (pkg_value);
  
        return (0);
  } /* int write_part_number */
  
 -static int write_part_string (char **ret_buffer, int *ret_buffer_len,
 -              int type, const char *str, int str_len)
 +static int write_part_string (char **ret_buffer, size_t *ret_buffer_len,
 +              int type, const char *str, size_t str_len)
  {
        char *buffer;
 -      int buffer_len;
 +      size_t buffer_len;
  
        uint16_t pkg_type;
        uint16_t pkg_length;
  
 -      int offset;
 +      size_t offset;
  
        buffer_len = 2 * sizeof (uint16_t) + str_len + 1;
        if (*ret_buffer_len < buffer_len)
  } /* int write_part_string */
  
  static int parse_part_values (void **ret_buffer, size_t *ret_buffer_len,
 -              value_t **ret_values, int *ret_num_values)
 +              value_t **ret_values, size_t *ret_num_values)
  {
        char *buffer = *ret_buffer;
        size_t buffer_len = *ret_buffer_len;
  
        uint16_t tmp16;
        size_t exp_size;
 -      int   i;
  
        uint16_t pkg_length;
        uint16_t pkg_type;
 -      uint16_t pkg_numval;
 +      size_t pkg_numval;
  
        uint8_t *pkg_types;
        value_t *pkg_values;
  
        memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
        buffer += sizeof (tmp16);
 -      pkg_numval = ntohs (tmp16);
 +      pkg_numval = (size_t) ntohs (tmp16);
  
        assert (pkg_type == TYPE_VALUES);
  
                                exp_size, buffer_len);
                return (-1);
        }
 +      assert (pkg_numval <= ((buffer_len - 6) / 9));
  
        if (pkg_length != exp_size)
        {
                return (-1);
        }
  
 -      pkg_types = (uint8_t *) malloc (pkg_numval * sizeof (uint8_t));
 -      pkg_values = (value_t *) malloc (pkg_numval * sizeof (value_t));
 +      pkg_types = calloc (pkg_numval, sizeof (*pkg_types));
 +      pkg_values = calloc (pkg_numval, sizeof (*pkg_values));
        if ((pkg_types == NULL) || (pkg_values == NULL))
        {
                sfree (pkg_types);
                sfree (pkg_values);
 -              ERROR ("network plugin: parse_part_values: malloc failed.");
 +              ERROR ("network plugin: parse_part_values: calloc failed.");
                return (-1);
        }
  
 -      memcpy ((void *) pkg_types, (void *) buffer, pkg_numval * sizeof (uint8_t));
 -      buffer += pkg_numval * sizeof (uint8_t);
 -      memcpy ((void *) pkg_values, (void *) buffer, pkg_numval * sizeof (value_t));
 -      buffer += pkg_numval * sizeof (value_t);
 +      memcpy (pkg_types, buffer, pkg_numval * sizeof (*pkg_types));
 +      buffer += pkg_numval * sizeof (*pkg_types);
 +      memcpy (pkg_values, buffer, pkg_numval * sizeof (*pkg_values));
 +      buffer += pkg_numval * sizeof (*pkg_values);
  
 -      for (i = 0; i < pkg_numval; i++)
 +      for (size_t i = 0; i < pkg_numval; i++)
        {
                switch (pkg_types[i])
                {
@@@ -941,7 -951,7 +942,7 @@@ static int parse_part_string (void **re
        uint16_t pkg_length;
        size_t payload_size;
  
 -      if (output_len <= 0)
 +      if (output_len == 0)
                return (EINVAL);
  
        if (buffer_len < header_size)
@@@ -1224,7 -1234,7 +1225,7 @@@ static int parse_part_encr_aes256 (sock
    size_t buffer_offset;
    uint16_t username_len;
    part_encryption_aes256_t pea;
 -  unsigned char hash[sizeof (pea.hash)];
 +  unsigned char hash[sizeof (pea.hash)] = { 0 };
  
    gcry_cipher_hd_t cypher;
    gcry_error_t err;
    BUFFER_READ (&username_len, sizeof (username_len));
    username_len = ntohs (username_len);
  
 -  if ((username_len <= 0)
 +  if ((username_len == 0)
        || (username_len > (part_size - (PART_ENCRYPTION_AES256_SIZE + 1))))
    {
      NOTICE ("network plugin: parse_part_encr_aes256: "
    assert (buffer_offset == (part_size - payload_len));
  
    /* Check hash sum */
 -  memset (hash, 0, sizeof (hash));
    gcry_md_hash_buffer (GCRY_MD_SHA1, hash,
        buffer + buffer_offset, payload_len);
    if (memcmp (hash, pea.hash, sizeof (hash)) != 0)
@@@ -1375,7 -1386,7 +1376,7 @@@ static int parse_part_encr_aes256 (sock
      warning_has_been_printed = 1;
    }
  
 -  *ret_buffer += ph_length;
 +  *ret_buffer = (void *) (((char *) *ret_buffer) + ph_length);
    *ret_buffer_size -= ph_length;
  
    return (0);
@@@ -1391,7 -1402,7 +1392,7 @@@ static int parse_packet (sockent_t *se
        int status;
  
        value_list_t vl = VALUE_LIST_INIT;
 -      notification_t n;
 +      notification_t n = { 0 };
  
  #if HAVE_LIBGCRYPT
        int packet_was_signed = (flags & PP_SIGNED);
  
  
        memset (&vl, '\0', sizeof (vl));
 -      memset (&n, '\0', sizeof (n));
        status = 0;
  
        while ((status == 0) && (0 < buffer_size)
                                (void *) buffer,
                                sizeof (pkg_type));
                memcpy ((void *) &pkg_length,
 -                              (void *) (buffer + sizeof (pkg_type)),
 +                              (void *) (((char *) buffer) + sizeof (pkg_type)),
                                sizeof (pkg_length));
  
                pkg_length = ntohs (pkg_length);
                                                "unknown severity %i.",
                                                n.severity);
                        }
 -                      else if (n.time <= 0)
 +                      else if (n.time == 0)
                        {
                                INFO ("network plugin: "
                                                "Ignoring notification with "
                                                "time == 0.");
                        }
 -                      else if (strlen (n.message) <= 0)
 +                      else if (strlen (n.message) == 0)
                        {
                                INFO ("network plugin: "
                                                "Ignoring notification with "
@@@ -1647,7 -1659,9 +1648,7 @@@ static void free_sockent_client (struc
  
  static void free_sockent_server (struct sockent_server *ses) /* {{{ */
  {
 -  size_t i;
 -
 -  for (i = 0; i < ses->fd_num; i++)
 +  for (size_t i = 0; i < ses->fd_num; i++)
    {
      if (ses->fd[i] >= 0)
      {
@@@ -1772,16 -1786,18 +1773,16 @@@ static int network_set_interface (cons
                         * index is preferred here, because of its similarity
                         * to the way IPv6 handles this. Unfortunately, it
                         * appears not to be portable. */
 -                      struct ip_mreqn mreq;
 -
 -                      memset (&mreq, 0, sizeof (mreq));
 -                      mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
 -                      mreq.imr_address.s_addr = ntohl (INADDR_ANY);
 -                      mreq.imr_ifindex = se->interface;
 +                      struct ip_mreqn mreq = {
 +                              .imr_multiaddr.s_addr = addr->sin_addr.s_addr,
 +                              .imr_address.s_addr = ntohl (INADDR_ANY),
 +                              .imr_ifindex = se->interface
 +                      };
  #else
 -                      struct ip_mreq mreq;
 -
 -                      memset (&mreq, 0, sizeof (mreq));
 -                      mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
 -                      mreq.imr_interface.s_addr = ntohl (INADDR_ANY);
 +                      struct ip_mreq mreq = {
 +                              .imr_multiaddr.s_addr = addr->sin_addr.s_addr,
 +                              .imr_interface.s_addr = ntohl (INADDR_ANY)
 +                      };
  #endif
  
                        if (setsockopt (se->data.client.fd, IPPROTO_IP, IP_MULTICAST_IF,
@@@ -2016,9 -2032,10 +2017,9 @@@ static sockent_t *sockent_create (int t
        if ((type != SOCKENT_TYPE_CLIENT) && (type != SOCKENT_TYPE_SERVER))
                return (NULL);
  
 -      se = malloc (sizeof (*se));
 +      se = calloc (1, sizeof (*se));
        if (se == NULL)
                return (NULL);
 -      memset (se, 0, sizeof (*se));
  
        se->type = type;
        se->node = NULL;
@@@ -2061,7 -2078,12 +2062,12 @@@ static int sockent_init_crypto (sockent
        {
                if (se->data.client.security_level > SECURITY_LEVEL_NONE)
                {
-                       network_init_gcrypt ();
+                       if (network_init_gcrypt () < 0)
+                       {
+                               ERROR ("network plugin: Cannot configure client socket with "
+                                               "security: Failed to initialize crypto library.");
+                               return (-1);
+                       }
  
                        if ((se->data.client.username == NULL)
                                        || (se->data.client.password == NULL))
        {
                if (se->data.server.security_level > SECURITY_LEVEL_NONE)
                {
-                       network_init_gcrypt ();
+                       if (network_init_gcrypt () < 0)
+                       {
+                               ERROR ("network plugin: Cannot configure server socket with "
+                                               "security: Failed to initialize crypto library.");
+                               return (-1);
+                       }
  
                        if (se->data.server.auth_file == NULL)
                        {
@@@ -2134,7 -2161,8 +2145,7 @@@ static int sockent_client_connect (sock
        static c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
  
        struct sockent_client *client;
 -      struct addrinfo  ai_hints;
 -      struct addrinfo *ai_list = NULL, *ai_ptr;
 +      struct addrinfo *ai_list;
        int status;
        _Bool reconnect = 0;
        cdtime_t now;
        if (client->fd >= 0 && !reconnect) /* already connected and not stale*/
                return (0);
  
 -      memset (&ai_hints, 0, sizeof (ai_hints));
 -#ifdef AI_ADDRCONFIG
 -      ai_hints.ai_flags |= AI_ADDRCONFIG;
 -#endif
 -      ai_hints.ai_family   = AF_UNSPEC;
 -      ai_hints.ai_socktype = SOCK_DGRAM;
 -      ai_hints.ai_protocol = IPPROTO_UDP;
 +      struct addrinfo ai_hints = {
 +              .ai_family   = AF_UNSPEC,
 +              .ai_flags    = AI_ADDRCONFIG,
 +              .ai_protocol = IPPROTO_UDP,
 +              .ai_socktype = SOCK_DGRAM
 +      };
  
        status = getaddrinfo (se->node,
                        (se->service != NULL) ? se->service : NET_DEFAULT_PORT,
                                se->node);
        }
  
 -      for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
 +      for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
        {
                if (client->fd >= 0) /* when we reconnect */
                        sockent_client_disconnect(se);
                        continue;
                }
  
 -              client->addr = malloc (sizeof (*client->addr));
 +              client->addr = calloc (1, sizeof (*client->addr));
                if (client->addr == NULL)
                {
 -                      ERROR ("network plugin: malloc failed.");
 +                      ERROR ("network plugin: calloc failed.");
                        close (client->fd);
                        client->fd = -1;
                        continue;
                }
  
 -              memset (client->addr, 0, sizeof (*client->addr));
                assert (sizeof (*client->addr) >= ai_ptr->ai_addrlen);
                memcpy (client->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
                client->addrlen = ai_ptr->ai_addrlen;
  /* Open the file descriptors for a initialized sockent structure. */
  static int sockent_server_listen (sockent_t *se) /* {{{ */
  {
 -      struct addrinfo  ai_hints;
 -      struct addrinfo *ai_list, *ai_ptr;
 +      struct addrinfo *ai_list;
        int              status;
  
          const char *node;
          DEBUG ("network plugin: sockent_server_listen: node = %s; service = %s;",
              node, service);
  
 -      memset (&ai_hints, 0, sizeof (ai_hints));
 -      ai_hints.ai_flags  = 0;
 -#ifdef AI_PASSIVE
 -      ai_hints.ai_flags |= AI_PASSIVE;
 -#endif
 -#ifdef AI_ADDRCONFIG
 -      ai_hints.ai_flags |= AI_ADDRCONFIG;
 -#endif
 -      ai_hints.ai_family   = AF_UNSPEC;
 -      ai_hints.ai_socktype = SOCK_DGRAM;
 -      ai_hints.ai_protocol = IPPROTO_UDP;
 +      struct addrinfo ai_hints = {
 +              .ai_family   = AF_UNSPEC,
 +              .ai_flags    = AI_ADDRCONFIG | AI_PASSIVE,
 +              .ai_protocol = IPPROTO_UDP,
 +              .ai_socktype = SOCK_DGRAM
 +      };
  
        status = getaddrinfo (node, service, &ai_hints, &ai_list);
        if (status != 0)
                return (-1);
        }
  
 -      for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
 +      for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
        {
                int *tmp;
  
  
        freeaddrinfo (ai_list);
  
 -      if (se->data.server.fd_num <= 0)
 +      if (se->data.server.fd_num == 0)
                return (-1);
        return (0);
  } /* }}} int sockent_server_listen */
@@@ -2323,6 -2359,7 +2334,6 @@@ static int sockent_add (sockent_t *se) 
        if (se->type == SOCKENT_TYPE_SERVER)
        {
                struct pollfd *tmp;
 -              size_t i;
  
                tmp = realloc (listen_sockets_pollfd,
                                sizeof (*tmp) * (listen_sockets_num
                listen_sockets_pollfd = tmp;
                tmp = listen_sockets_pollfd + listen_sockets_num;
  
 -              for (i = 0; i < se->data.server.fd_num; i++)
 +              for (size_t i = 0; i < se->data.server.fd_num; i++)
                {
                        memset (tmp + i, 0, sizeof (*tmp));
                        tmp[i].fd = se->data.server.fd[i];
@@@ -2434,6 -2471,7 +2445,6 @@@ static int network_receive (void) /* {{
        char buffer[network_config_packet_size];
        int  buffer_len;
  
 -      int i;
        int status = 0;
  
        receive_list_entry_t *private_list_head;
                        break;
                }
  
 -              for (i = 0; (i < listen_sockets_num) && (status > 0); i++)
 +              for (size_t i = 0; (i < listen_sockets_num) && (status > 0); i++)
                {
                        receive_list_entry_t *ent;
  
                         * these entries in the dispatch thread but put them in
                         * another list, so we don't have to allocate more and
                         * more of these structures. */
 -                      ent = malloc (sizeof (receive_list_entry_t));
 +                      ent = calloc (1, sizeof (*ent));
                        if (ent == NULL)
                        {
 -                              ERROR ("network plugin: malloc failed.");
 +                              ERROR ("network plugin: calloc failed.");
                                status = ENOMEM;
                                break;
                        }
 -                      memset (ent, 0, sizeof (receive_list_entry_t));
 +
                        ent->data = malloc (network_config_packet_size);
                        if (ent->data == NULL)
                        {
@@@ -2574,12 -2612,11 +2585,12 @@@ static void network_init_buffer (void
        memset (send_buffer, 0, network_config_packet_size);
        send_buffer_ptr = send_buffer;
        send_buffer_fill = 0;
 +      send_buffer_last_update = 0;
  
        memset (&send_buffer_vl, 0, sizeof (send_buffer_vl));
  } /* int network_init_buffer */
  
 -static void networt_send_buffer_plain (sockent_t *se, /* {{{ */
 +static void network_send_buffer_plain (sockent_t *se, /* {{{ */
                const char *buffer, size_t buffer_size)
  {
        int status;
  
                break;
        } /* while (42) */
 -} /* }}} void networt_send_buffer_plain */
 +} /* }}} void network_send_buffer_plain */
  
  #if HAVE_LIBGCRYPT
  #define BUFFER_ADD(p,s) do { \
    buffer_offset += (s); \
  } while (0)
  
 -static void networt_send_buffer_signed (sockent_t *se, /* {{{ */
 +static void network_send_buffer_signed (sockent_t *se, /* {{{ */
                const char *in_buffer, size_t in_buffer_size)
  {
 -  part_signature_sha256_t ps;
    char buffer[BUFF_SIG_SIZE + in_buffer_size];
    size_t buffer_offset;
    size_t username_len;
        in_buffer, in_buffer_size);
  
    /* Initialize the `ps' structure. */
 -  memset (&ps, 0, sizeof (ps));
 -  ps.head.type = htons (TYPE_SIGN_SHA256);
 -  ps.head.length = htons (PART_SIGNATURE_SHA256_SIZE + username_len);
 +  part_signature_sha256_t ps = {
 +    .head.type = htons (TYPE_SIGN_SHA256),
 +    .head.length = htons (PART_SIGNATURE_SHA256_SIZE + username_len)
 +  };
  
    /* Calculate the hash value. */
    gcry_md_write (hd, buffer + PART_SIGNATURE_SHA256_SIZE,
    hd = NULL;
  
    buffer_offset = PART_SIGNATURE_SHA256_SIZE + username_len + in_buffer_size;
 -  networt_send_buffer_plain (se, buffer, buffer_offset);
 -} /* }}} void networt_send_buffer_signed */
 +  network_send_buffer_plain (se, buffer, buffer_offset);
 +} /* }}} void network_send_buffer_signed */
  
 -static void networt_send_buffer_encrypted (sockent_t *se, /* {{{ */
 +static void network_send_buffer_encrypted (sockent_t *se, /* {{{ */
                const char *in_buffer, size_t in_buffer_size)
  {
 -  part_encryption_aes256_t pea;
    char buffer[BUFF_SIG_SIZE + in_buffer_size];
    size_t buffer_size;
    size_t buffer_offset;
    gcry_cipher_hd_t cypher;
  
    /* Initialize the header fields */
 -  memset (&pea, 0, sizeof (pea));
 -  pea.head.type = htons (TYPE_ENCR_AES256);
 -
 -  pea.username = se->data.client.username;
 +  part_encryption_aes256_t pea = {
 +    .head.type = htons (TYPE_ENCR_AES256),
 +    .username = se->data.client.username
 +  };
  
    username_len = strlen (pea.username);
    if ((PART_ENCRYPTION_AES256_SIZE + username_len) > BUFF_SIG_SIZE)
      - sizeof (pea.hash);
  
    assert (buffer_size <= sizeof (buffer));
 -  DEBUG ("network plugin: networt_send_buffer_encrypted: "
 +  DEBUG ("network plugin: network_send_buffer_encrypted: "
        "buffer_size = %zu;", buffer_size);
  
    pea.head.length = htons ((uint16_t) (PART_ENCRYPTION_AES256_SIZE
    }
  
    /* Send it out without further modifications */
 -  networt_send_buffer_plain (se, buffer, buffer_size);
 -} /* }}} void networt_send_buffer_encrypted */
 +  network_send_buffer_plain (se, buffer, buffer_size);
 +} /* }}} void network_send_buffer_encrypted */
  #undef BUFFER_ADD
  #endif /* HAVE_LIBGCRYPT */
  
  static void network_send_buffer (char *buffer, size_t buffer_len) /* {{{ */
  {
 -  sockent_t *se;
 -
    DEBUG ("network plugin: network_send_buffer: buffer_len = %zu", buffer_len);
  
 -  for (se = sending_sockets; se != NULL; se = se->next)
 +  for (sockent_t *se = sending_sockets; se != NULL; se = se->next)
    {
  #if HAVE_LIBGCRYPT
      if (se->data.client.security_level == SECURITY_LEVEL_ENCRYPT)
 -      networt_send_buffer_encrypted (se, buffer, buffer_len);
 +      network_send_buffer_encrypted (se, buffer, buffer_len);
      else if (se->data.client.security_level == SECURITY_LEVEL_SIGN)
 -      networt_send_buffer_signed (se, buffer, buffer_len);
 +      network_send_buffer_signed (se, buffer, buffer_len);
      else /* if (se->data.client.security_level == SECURITY_LEVEL_NONE) */
  #endif /* HAVE_LIBGCRYPT */
 -      networt_send_buffer_plain (se, buffer, buffer_len);
 +      network_send_buffer_plain (se, buffer, buffer_len);
    } /* for (sending_sockets) */
  } /* }}} void network_send_buffer */
  
 -static int add_to_buffer (char *buffer, int buffer_size, /* {{{ */
 +static int add_to_buffer (char *buffer, size_t buffer_size, /* {{{ */
                value_list_t *vl_def,
                const data_set_t *ds, const value_list_t *vl)
  {
@@@ -2880,6 -2920,11 +2891,11 @@@ static int network_write (const data_se
  {
        int status;
  
+       /* listen_loop is set to non-zero in the shutdown callback, which is
+        * guaranteed to be called *after* all the write threads have been shut
+        * down. */
+       assert (listen_loop == 0);
        if (!check_send_okay (vl))
        {
  #if COLLECT_DEBUG
                /* status == bytes added to the buffer */
                send_buffer_fill += status;
                send_buffer_ptr  += status;
 +              send_buffer_last_update = cdtime();
  
                stats_values_sent++;
        }
        return ((status < 0) ? -1 : 0);
  } /* int network_write */
  
 -static int network_config_set_boolean (const oconfig_item_t *ci, /* {{{ */
 -    int *retval)
 -{
 -  if ((ci->values_num != 1)
 -      || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN)
 -        && (ci->values[0].type != OCONFIG_TYPE_STRING)))
 -  {
 -    ERROR ("network plugin: The `%s' config option needs "
 -        "exactly one boolean argument.", ci->key);
 -    return (-1);
 -  }
 -
 -  if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
 -  {
 -    if (ci->values[0].value.boolean)
 -      *retval = 1;
 -    else
 -      *retval = 0;
 -  }
 -  else
 -  {
 -    char *str = ci->values[0].value.string;
 -
 -    if (IS_TRUE (str))
 -      *retval = 1;
 -    else if (IS_FALSE (str))
 -      *retval = 0;
 -    else
 -    {
 -      ERROR ("network plugin: Cannot parse string value `%s' of the `%s' "
 -          "option as boolean value.",
 -          str, ci->key);
 -      return (-1);
 -    }
 -  }
 -
 -  return (0);
 -} /* }}} int network_config_set_boolean */
 -
  static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */
  {
 -  int tmp;
 -  if ((ci->values_num != 1)
 -      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
 -  {
 -    WARNING ("network plugin: The `TimeToLive' config option needs exactly "
 -        "one numeric argument.");
 -    return (-1);
 -  }
 +  int tmp = 0;
  
 -  tmp = (int) ci->values[0].value.number;
 -  if ((tmp > 0) && (tmp <= 255))
 +  if (cf_util_get_int (ci, &tmp) != 0)
 +    return (-1);
 +  else if ((tmp > 0) && (tmp <= 255))
      network_config_ttl = tmp;
    else {
      WARNING ("network plugin: The `TimeToLive' must be between 1 and 255.");
  static int network_config_set_interface (const oconfig_item_t *ci, /* {{{ */
      int *interface)
  {
 -  if ((ci->values_num != 1)
 -      || (ci->values[0].type != OCONFIG_TYPE_STRING))
 -  {
 -    WARNING ("network plugin: The `Interface' config option needs exactly "
 -        "one string argument.");
 -    return (-1);
 -  }
 +  char if_name[256];
  
 -  if (interface == NULL)
 +  if (cf_util_get_string_buffer (ci, if_name, sizeof (if_name)) != 0)
      return (-1);
  
 -  *interface = if_nametoindex (ci->values[0].value.string);
 -
 +  *interface = if_nametoindex (if_name);
    return (0);
  } /* }}} int network_config_set_interface */
  
  static int network_config_set_buffer_size (const oconfig_item_t *ci) /* {{{ */
  {
 -  int tmp;
 -  if ((ci->values_num != 1)
 -      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
 -  {
 -    WARNING ("network plugin: The `MaxPacketSize' config option needs exactly "
 -        "one numeric argument.");
 -    return (-1);
 -  }
 +  int tmp = 0;
  
 -  tmp = (int) ci->values[0].value.number;
 -  if ((tmp >= 1024) && (tmp <= 65535))
 +  if (cf_util_get_int (ci, &tmp) != 0)
 +    return (-1);
 +  else if ((tmp >= 1024) && (tmp <= 65535))
      network_config_packet_size = tmp;
 -
 -  return (0);
 -} /* }}} int network_config_set_buffer_size */
 -
 -#if HAVE_LIBGCRYPT
 -static int network_config_set_string (const oconfig_item_t *ci, /* {{{ */
 -    char **ret_string)
 -{
 -  char *tmp;
 -  if ((ci->values_num != 1)
 -      || (ci->values[0].type != OCONFIG_TYPE_STRING))
 -  {
 -    WARNING ("network plugin: The `%s' config option needs exactly "
 -        "one string argument.", ci->key);
 +  else {
 +    WARNING ("network plugin: The `MaxPacketSize' must be between 1024 and 65535.");
      return (-1);
    }
  
 -  tmp = strdup (ci->values[0].value.string);
 -  if (tmp == NULL)
 -    return (-1);
 -
 -  sfree (*ret_string);
 -  *ret_string = tmp;
 -
    return (0);
 -} /* }}} int network_config_set_string */
 -#endif /* HAVE_LIBGCRYPT */
 +} /* }}} int network_config_set_buffer_size */
  
  #if HAVE_LIBGCRYPT
  static int network_config_set_security_level (oconfig_item_t *ci, /* {{{ */
@@@ -3026,6 -3148,7 +3042,6 @@@ static int network_config_add_listen (c
  {
    sockent_t *se;
    int status;
 -  int i;
  
    if ((ci->values_num < 1) || (ci->values_num > 2)
        || (ci->values[0].type != OCONFIG_TYPE_STRING)
    if (ci->values_num >= 2)
      se->service = strdup (ci->values[1].value.string);
  
 -  for (i = 0; i < ci->children_num; i++)
 +  for (int i = 0; i < ci->children_num; i++)
    {
      oconfig_item_t *child = ci->children + i;
  
  #if HAVE_LIBGCRYPT
      if (strcasecmp ("AuthFile", child->key) == 0)
 -      network_config_set_string (child, &se->data.server.auth_file);
 +      cf_util_get_string (child, &se->data.server.auth_file);
      else if (strcasecmp ("SecurityLevel", child->key) == 0)
        network_config_set_security_level (child,
            &se->data.server.security_level);
      else
  #endif /* HAVE_LIBGCRYPT */
      if (strcasecmp ("Interface", child->key) == 0)
 -      network_config_set_interface (child,
 -          &se->interface);
 +      network_config_set_interface (child, &se->interface);
      else
      {
        WARNING ("network plugin: Option `%s' is not allowed here.",
    status = sockent_server_listen (se);
    if (status != 0)
    {
 -    ERROR ("network plugin: network_config_add_server: sockent_server_listen failed.");
 +    ERROR ("network plugin: network_config_add_listen: sockent_server_listen failed.");
      sockent_destroy (se);
      return (-1);
    }
@@@ -3111,6 -3235,7 +3127,6 @@@ static int network_config_add_server (c
  {
    sockent_t *se;
    int status;
 -  int i;
  
    if ((ci->values_num < 1) || (ci->values_num > 2)
        || (ci->values[0].type != OCONFIG_TYPE_STRING)
    if (ci->values_num >= 2)
      se->service = strdup (ci->values[1].value.string);
  
 -  for (i = 0; i < ci->children_num; i++)
 +  for (int i = 0; i < ci->children_num; i++)
    {
      oconfig_item_t *child = ci->children + i;
  
  #if HAVE_LIBGCRYPT
      if (strcasecmp ("Username", child->key) == 0)
 -      network_config_set_string (child, &se->data.client.username);
 +      cf_util_get_string (child, &se->data.client.username);
      else if (strcasecmp ("Password", child->key) == 0)
 -      network_config_set_string (child, &se->data.client.password);
 +      cf_util_get_string (child, &se->data.client.password);
      else if (strcasecmp ("SecurityLevel", child->key) == 0)
        network_config_set_security_level (child,
            &se->data.client.security_level);
      else
  #endif /* HAVE_LIBGCRYPT */
      if (strcasecmp ("Interface", child->key) == 0)
 -      network_config_set_interface (child,
 -          &se->interface);
 -              else if (strcasecmp ("ResolveInterval", child->key) == 0)
 -                      cf_util_get_cdtime(child, &se->data.client.resolve_interval);
 +      network_config_set_interface (child, &se->interface);
 +    else if (strcasecmp ("ResolveInterval", child->key) == 0)
 +      cf_util_get_cdtime(child, &se->data.client.resolve_interval);
      else
      {
        WARNING ("network plugin: Option `%s' is not allowed here.",
    }
  
    /* No call to sockent_client_connect() here -- it is called from
 -   * networt_send_buffer_plain(). */
 +   * network_send_buffer_plain(). */
  
    status = sockent_add (se);
    if (status != 0)
  
  static int network_config (oconfig_item_t *ci) /* {{{ */
  {
 -  int i;
 -
    /* The options need to be applied first */
 -  for (i = 0; i < ci->children_num; i++)
 +  for (int i = 0; i < ci->children_num; i++)
    {
      oconfig_item_t *child = ci->children + i;
      if (strcasecmp ("TimeToLive", child->key) == 0)
        network_config_set_ttl (child);
    }
  
 -  for (i = 0; i < ci->children_num; i++)
 +  for (int i = 0; i < ci->children_num; i++)
    {
      oconfig_item_t *child = ci->children + i;
  
      else if (strcasecmp ("MaxPacketSize", child->key) == 0)
        network_config_set_buffer_size (child);
      else if (strcasecmp ("Forward", child->key) == 0)
 -      network_config_set_boolean (child, &network_config_forward);
 +      cf_util_get_boolean (child, &network_config_forward);
      else if (strcasecmp ("ReportStats", child->key) == 0)
 -      network_config_set_boolean (child, &network_config_stats);
 +      cf_util_get_boolean (child, &network_config_stats);
      else
      {
        WARNING ("network plugin: Option `%s' is not allowed here.",
  static int network_notification (const notification_t *n,
      user_data_t __attribute__((unused)) *user_data)
  {
 -  char  buffer[network_config_packet_size];
 -  char *buffer_ptr = buffer;
 -  int   buffer_free = sizeof (buffer);
 -  int   status;
 +  char   buffer[network_config_packet_size];
 +  char  *buffer_ptr = buffer;
 +  size_t buffer_free = sizeof (buffer);
 +  int    status;
  
    if (!check_send_notify_okay (n))
      return (0);
  
  static int network_shutdown (void)
  {
 -      sockent_t *se;
 -
        listen_loop++;
  
        /* Kill the listening thread */
  
        sfree (send_buffer);
  
 -      for (se = sending_sockets; se != NULL; se = se->next)
 +      for (sockent_t *se = sending_sockets; se != NULL; se = se->next)
                sockent_client_disconnect (se);
        sockent_destroy (sending_sockets);
  
@@@ -3434,10 -3564,14 +3450,14 @@@ static int network_init (void
        have_init = 1;
  
  #if HAVE_LIBGCRYPT
-       network_init_gcrypt ();
+       if (network_init_gcrypt () < 0)
+       {
+               ERROR ("network plugin: Failed to initialize crypto library.");
+               return (-1);
+       }
  #endif
  
 -      if (network_config_stats != 0)
 +      if (network_config_stats)
                plugin_register_read ("network", network_stats_read);
  
        plugin_register_shutdown ("network", network_shutdown);
   * just send the buffer if `flush'  is called - if the requested value was in
   * there, good. If not, well, then there is nothing to flush.. -octo
   */
 -static int network_flush (__attribute__((unused)) cdtime_t timeout,
 +static int network_flush (cdtime_t timeout,
                __attribute__((unused)) const char *identifier,
                __attribute__((unused)) user_data_t *user_data)
  {
        pthread_mutex_lock (&send_buffer_lock);
  
        if (send_buffer_fill > 0)
 -        flush_buffer ();
 -
 +      {
 +              if (timeout > 0)
 +              {
 +                      cdtime_t now = cdtime ();
 +                      if ((send_buffer_last_update + timeout) > now)
 +                      {
 +                              pthread_mutex_unlock (&send_buffer_lock);
 +                              return (0);
 +                      }
 +              }
 +              flush_buffer ();
 +      }
        pthread_mutex_unlock (&send_buffer_lock);
  
        return (0);
diff --combined src/pyvalues.c
   * DEALINGS IN THE SOFTWARE.
   *
   * Authors:
 - *   Sven Trenkel <collectd at semidefinite.de>  
 + *   Sven Trenkel <collectd at semidefinite.de>
   **/
  
  #include <Python.h>
  #include <structmember.h>
  
  #include "collectd.h"
 +
  #include "common.h"
  
  #include "cpython.h"
@@@ -46,7 -45,7 +46,7 @@@ static PyObject *cpy_common_repr(PyObje
        static PyObject *l_type = NULL, *l_type_instance = NULL, *l_plugin = NULL, *l_plugin_instance = NULL;
        static PyObject *l_host = NULL, *l_time = NULL;
        PluginData *self = (PluginData *) s;
 -      
 +
        if (l_type == NULL)
                l_type = cpy_string_to_unicode_or_bytes("(type=");
        if (l_type_instance == NULL)
                l_host = cpy_string_to_unicode_or_bytes(",host=");
        if (l_time == NULL)
                l_time = cpy_string_to_unicode_or_bytes(",time=");
 -      
 +
        if (!l_type || !l_type_instance || !l_plugin || !l_plugin_instance || !l_host || !l_time)
                return NULL;
 -      
 +
        ret = cpy_string_to_unicode_or_bytes(s->ob_type->tp_name);
  
        CPY_STRCAT(&ret, l_type);
        return ret;
  }
  
 -static char time_doc[] = "This is the Unix timestap of the time this value was read.\n"
 +static char time_doc[] = "This is the Unix timestamp of the time this value was read.\n"
                "For dispatching values this can be set to 0 which means \"now\".\n"
                "This means the time the value is actually dispatched, not the time\n"
                "it was set to 0.";
  
  static char host_doc[] = "The hostname of the host this value was read from.\n"
                "For dispatching this can be set to an empty string which means\n"
 -              "the local hostname as defined in the collectd.conf.";
 +              "the local hostname as defined in collectd.conf.";
  
  static char type_doc[] = "The type of this value. This type has to be defined\n"
 -              "in your types.db. Attempting to set it to any other value will\n"
 -              "raise a TypeError exception.\n"
 -              "Assigning a type is mandetory, calling dispatch without doing\n"
 +              "in the types.db file. Attempting to set it to any other value\n"
 +              "will raise a TypeError exception.\n"
 +              "Assigning a type is mandatory, calling dispatch without doing\n"
                "so will raise a RuntimeError exception.";
  
  static char type_instance_doc[] = "";
@@@ -130,16 -129,16 +130,16 @@@ static char plugin_doc[] = "The name o
  static char plugin_instance_doc[] = "";
  
  static char PluginData_doc[] = "This is an internal class that is the base for Values\n"
 -              "and Notification. It is pretty useless by itself and was therefore not\n"
 +              "and Notification. It is pretty useless by itself and is therefore not\n"
                "exported to the collectd module.";
  
  static PyObject *PluginData_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
        PluginData *self;
 -      
 +
        self = (PluginData *) type->tp_alloc(type, 0);
        if (self == NULL)
                return NULL;
 -      
 +
        self->time = 0;
        self->host[0] = 0;
        self->plugin[0] = 0;
@@@ -155,11 -154,11 +155,11 @@@ static int PluginData_init(PyObject *s
        char *type = NULL, *plugin_instance = NULL, *type_instance = NULL, *plugin = NULL, *host = NULL;
        static char *kwlist[] = {"type", "plugin_instance", "type_instance",
                        "plugin", "host", "time", NULL};
 -      
 +
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetd", kwlist, NULL, &type,
                        NULL, &plugin_instance, NULL, &type_instance, NULL, &plugin, NULL, &host, &time))
                return -1;
 -      
 +
        if (type && plugin_get_ds(type) == NULL) {
                PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
                FreeAll();
  static PyObject *PluginData_repr(PyObject *s) {
        PyObject *ret;
        static PyObject *l_closing = NULL;
 -      
 +
        if (l_closing == NULL)
                l_closing = cpy_string_to_unicode_or_bytes(")");
 -      
 +
        if (l_closing == NULL)
                return NULL;
 -      
 +
        ret = cpy_common_repr(s);
        CPY_STRCAT(&ret, l_closing);
        return ret;
@@@ -200,14 -199,14 +200,14 @@@ static PyMemberDef PluginData_members[
  
  static PyObject *PluginData_getstring(PyObject *self, void *data) {
        const char *value = ((char *) self) + (intptr_t) data;
 -      
 +
        return cpy_string_to_unicode_or_bytes(value);
  }
  
  static int PluginData_setstring(PyObject *self, PyObject *value, void *data) {
        char *old;
        const char *new;
 -      
 +
        if (value == NULL) {
                PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
                return -1;
  static int PluginData_settype(PyObject *self, PyObject *value, void *data) {
        char *old;
        const char *new;
 -      
 +
        if (value == NULL) {
                PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
                return -1;
@@@ -313,8 -312,8 +313,8 @@@ static char interval_doc[] = "The inter
  static char values_doc[] = "These are the actual values that get dispatched to collectd.\n"
                "It has to be a sequence (a tuple or list) of numbers.\n"
                "The size of the sequence and the type of its content depend on the type\n"
 -              "member your types.db file. For more information on this read the types.db\n"
 -              "man page.\n"
 +              "member in the types.db file. For more information on this read the\n"
 +              "types.db man page.\n"
                "\n"
                "If the sequence does not have the correct size upon dispatch a RuntimeError\n"
                "exception will be raised. If the content of the sequence is not a number,\n"
  static char meta_doc[] = "These are the meta data for this Value object.\n"
                "It has to be a dictionary of numbers, strings or bools. All keys must be\n"
                "strings. int and long objects will be dispatched as signed integers unless\n"
 -              "they are between 2**63 and 2**64-1, which will result in a unsigned integer.\n"
 +              "they are between 2**63 and 2**64-1, which will result in an unsigned integer.\n"
                "You can force one of these storage classes by using the classes\n"
                "collectd.Signed and collectd.Unsigned. A meta object received by a write\n"
                "callback will always contain Signed or Unsigned objects.";
@@@ -341,7 -340,7 +341,7 @@@ static char dispatch_doc[] = "dispatch(
  static char write_doc[] = "write([destination][, type][, values][, plugin_instance][, type_instance]"
                "[, plugin][, host][, time][, interval]) -> None.  Dispatch a value list.\n"
                "\n"
 -              "Write this instance to a single plugin or all plugins if 'destination' is obmitted.\n"
 +              "Write this instance to a single plugin or all plugins if 'destination' is omitted.\n"
                "This will bypass the main collectd process and all filtering and caching.\n"
                "Other than that it works similar to 'dispatch'. In most cases 'dispatch' should be\n"
                "used instead of 'write'.\n";
@@@ -350,11 -349,11 +350,11 @@@ static char Values_doc[] = "A Values ob
  
  static PyObject *Values_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
        Values *self;
 -      
 +
        self = (Values *) PluginData_new(type, args, kwds);
        if (self == NULL)
                return NULL;
 -      
 +
        self->values = PyList_New(0);
        self->meta = PyDict_New();
        self->interval = 0;
@@@ -368,12 -367,12 +368,12 @@@ static int Values_init(PyObject *s, PyO
        char *type = NULL, *plugin_instance = NULL, *type_instance = NULL, *plugin = NULL, *host = NULL;
        static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "interval", "meta", NULL};
 -      
 +
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist,
                        NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance,
                        NULL, &plugin, NULL, &host, &time, &interval, &meta))
                return -1;
 -      
 +
        if (type && plugin_get_ds(type) == NULL) {
                PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
                FreeAll();
        } else {
                Py_INCREF(values);
        }
 -      
 +
        if (meta == NULL) {
                meta = PyDict_New();
                PyErr_Clear();
        } else {
                Py_INCREF(meta);
        }
 -      
 +
        tmp = self->values;
        self->values = values;
        Py_XDECREF(tmp);
 -      
 +
        tmp = self->meta;
        self->meta = meta;
        Py_XDECREF(tmp);
  }
  
  static meta_data_t *cpy_build_meta(PyObject *meta) {
 -      int i, s;
 +      int s;
        meta_data_t *m = NULL;
        PyObject *l;
 -      
 +
        if ((meta == NULL) || (meta == Py_None))
                return NULL;
  
        }
  
        m = meta_data_create();
 -      for (i = 0; i < s; ++i) {
 +      for (int i = 0; i < s; ++i) {
                const char *string, *keystring;
                PyObject *key, *value, *item, *tmp;
 -              
 +
                item = PyList_GET_ITEM(l, i);
                key = PyTuple_GET_ITEM(item, 0);
                Py_INCREF(key);
  }
  
  static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
 -      int i, ret;
 +      int ret;
        const data_set_t *ds;
 -      int size;
 +      size_t size;
        value_t *value;
        value_list_t value_list = VALUE_LIST_INIT;
        PyObject *values = self->values, *meta = self->meta;
        double time = self->data.time, interval = self->interval;
        char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL, *type_instance = NULL;
 -      
 +
        static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "interval", "meta", NULL};
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist,
                PyErr_Format(PyExc_TypeError, "meta must be a dict");
                return NULL;
        }
 -      size = (int) PySequence_Length(values);
 +      size = (size_t) PySequence_Length(values);
        if (size != ds->ds_num) {
 -              PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", value_list.type, ds->ds_num, size);
 +              PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu", value_list.type, ds->ds_num, size);
                return NULL;
        }
 -      value = malloc(size * sizeof(*value));
 -      for (i = 0; i < size; ++i) {
 +      value = calloc(size, sizeof(*value));
 +      for (size_t i = 0; i < size; ++i) {
                PyObject *item, *num;
 -              item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
 +              item = PySequence_Fast_GET_ITEM(values, (int) i); /* Borrowed reference. */
-               if (ds->ds->type == DS_TYPE_COUNTER) {
+               switch (ds->ds[i].type) {
+               case DS_TYPE_COUNTER:
                        num = PyNumber_Long(item); /* New reference. */
                        if (num != NULL) {
                                value[i].counter = PyLong_AsUnsignedLongLong(num);
                                Py_XDECREF(num);
                        }
-               } else if (ds->ds->type == DS_TYPE_GAUGE) {
+                       break;
+               case DS_TYPE_GAUGE:
                        num = PyNumber_Float(item); /* New reference. */
                        if (num != NULL) {
                                value[i].gauge = PyFloat_AsDouble(num);
                                Py_XDECREF(num);
                        }
-               } else if (ds->ds->type == DS_TYPE_DERIVE) {
+                       break;
+               case DS_TYPE_DERIVE:
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
                        num = PyNumber_Long(item); /* New reference. */
                                value[i].derive = PyLong_AsLongLong(num);
                                Py_XDECREF(num);
                        }
-               } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
+                       break;
+               case DS_TYPE_ABSOLUTE:
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
                        num = PyNumber_Long(item); /* New reference. */
                                value[i].absolute = PyLong_AsUnsignedLongLong(num);
                                Py_XDECREF(num);
                        }
-               } else {
+                       break;
+               default:
                        free(value);
-                       PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, value_list.type);
+                       PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds[i].type, value_list.type);
                        return NULL;
                }
                if (PyErr_Occurred() != NULL) {
  }
  
  static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
 -      int i, ret;
 +      int ret;
        const data_set_t *ds;
 -      int size;
 +      size_t size;
        value_t *value;
        value_list_t value_list = VALUE_LIST_INIT;
        PyObject *values = self->values, *meta = self->meta;
        double time = self->data.time, interval = self->interval;
        char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL, *type_instance = NULL, *dest = NULL;
 -      
 +
        static char *kwlist[] = {"destination", "type", "values", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "interval", "meta", NULL};
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|etOetetetetdiO", kwlist, NULL, &dest,
                PyErr_Format(PyExc_TypeError, "values must be list or tuple");
                return NULL;
        }
 -      size = (int) PySequence_Length(values);
 +      size = (size_t) PySequence_Length(values);
        if (size != ds->ds_num) {
 -              PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", value_list.type, ds->ds_num, size);
 +              PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu", value_list.type, ds->ds_num, size);
                return NULL;
        }
 -      value = malloc(size * sizeof(*value));
 -      for (i = 0; i < size; ++i) {
 +      value = calloc(size, sizeof(*value));
 +      for (size_t i = 0; i < size; ++i) {
                PyObject *item, *num;
                item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
-               if (ds->ds->type == DS_TYPE_COUNTER) {
+               switch (ds->ds[i].type) {
+               case DS_TYPE_COUNTER:
                        num = PyNumber_Long(item); /* New reference. */
                        if (num != NULL) {
                                value[i].counter = PyLong_AsUnsignedLongLong(num);
                                Py_XDECREF(num);
                        }
-               } else if (ds->ds->type == DS_TYPE_GAUGE) {
+                       break;
+               case DS_TYPE_GAUGE:
                        num = PyNumber_Float(item); /* New reference. */
                        if (num != NULL) {
                                value[i].gauge = PyFloat_AsDouble(num);
                                Py_XDECREF(num);
                        }
-               } else if (ds->ds->type == DS_TYPE_DERIVE) {
+                       break;
+               case DS_TYPE_DERIVE:
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
                        num = PyNumber_Long(item); /* New reference. */
                                value[i].derive = PyLong_AsLongLong(num);
                                Py_XDECREF(num);
                        }
-               } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
+                       break;
+               case DS_TYPE_ABSOLUTE:
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
                        num = PyNumber_Long(item); /* New reference. */
                                value[i].absolute = PyLong_AsUnsignedLongLong(num);
                                Py_XDECREF(num);
                        }
-               } else {
+                       break;
+               default:
                        free(value);
-                       PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, value_list.type);
+                       PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds[i].type, value_list.type);
                        return NULL;
                }
                if (PyErr_Occurred() != NULL) {
        value_list.values_len = size;
        value_list.time = DOUBLE_TO_CDTIME_T(time);
        value_list.interval = DOUBLE_TO_CDTIME_T(interval);
 -      value_list.meta = cpy_build_meta(meta);;
 +      value_list.meta = cpy_build_meta(meta);
        if (value_list.host[0] == 0)
                sstrncpy(value_list.host, hostname_g, sizeof(value_list.host));
        if (value_list.plugin[0] == 0)
@@@ -719,7 -728,7 +729,7 @@@ static PyObject *Values_repr(PyObject *
        PyObject *ret, *tmp;
        static PyObject *l_interval = NULL, *l_values = NULL, *l_meta = NULL, *l_closing = NULL;
        Values *self = (Values *) s;
 -      
 +
        if (l_interval == NULL)
                l_interval = cpy_string_to_unicode_or_bytes(",interval=");
        if (l_values == NULL)
                l_meta = cpy_string_to_unicode_or_bytes(",meta=");
        if (l_closing == NULL)
                l_closing = cpy_string_to_unicode_or_bytes(")");
 -      
 +
        if (l_interval == NULL || l_values == NULL || l_meta == NULL || l_closing == NULL)
                return NULL;
 -      
 +
        ret = cpy_common_repr(s);
        if (self->interval != 0) {
                CPY_STRCAT(&ret, l_interval);
@@@ -845,12 -854,12 +855,12 @@@ static int Notification_init(PyObject *
        char *type = NULL, *plugin_instance = NULL, *type_instance = NULL, *plugin = NULL, *host = NULL;
        static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "severity", NULL};
 -      
 +
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetetdi", kwlist,
                        NULL, &type, NULL, &message, NULL, &plugin_instance, NULL, &type_instance,
                        NULL, &plugin, NULL, &host, &time, &severity))
                return -1;
 -      
 +
        if (type && plugin_get_ds(type) == NULL) {
                PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
                FreeAll();
@@@ -880,7 -889,7 +890,7 @@@ static PyObject *Notification_dispatch(
        int severity = self->severity;
        char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL, *type_instance = NULL;
        char *message = NULL;
 -      
 +
        static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "severity", NULL};
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetetdi", kwlist,
  
  static PyObject *Notification_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
        Notification *self;
 -      
 +
        self = (Notification *) PluginData_new(type, args, kwds);
        if (self == NULL)
                return NULL;
 -      
 +
        self->message[0] = 0;
        self->severity = 0;
        return (PyObject *) self;
  static int Notification_setstring(PyObject *self, PyObject *value, void *data) {
        char *old;
        const char *new;
 -      
 +
        if (value == NULL) {
                PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
                return -1;
@@@ -962,17 -971,17 +972,17 @@@ static PyObject *Notification_repr(PyOb
        PyObject *ret, *tmp;
        static PyObject *l_severity = NULL, *l_message = NULL, *l_closing = NULL;
        Notification *self = (Notification *) s;
 -      
 +
        if (l_severity == NULL)
                l_severity = cpy_string_to_unicode_or_bytes(",severity=");
        if (l_message == NULL)
                l_message = cpy_string_to_unicode_or_bytes(",message=");
        if (l_closing == NULL)
                l_closing = cpy_string_to_unicode_or_bytes(")");
 -      
 +
        if (l_severity == NULL || l_message == NULL || l_closing == NULL)
                return NULL;
 -      
 +
        ret = cpy_common_repr(s);
        if (self->severity != 0) {
                CPY_STRCAT(&ret, l_severity);