Merge branch 'collectd-4.10' into collectd-5.0
authorFlorian Forster <octo@collectd.org>
Fri, 2 Sep 2011 01:28:05 +0000 (21:28 -0400)
committerFlorian Forster <octo@collectd.org>
Fri, 2 Sep 2011 01:28:05 +0000 (21:28 -0400)
Conflicts:
src/irq.c

Change-Id: Ie6c78234f07cc5b7bac7e6914813e9545ce1b1af

1  2 
.gitignore
src/irq.c
src/plugin.c
src/processes.c
src/utils_rrdcreate.c

diff --combined .gitignore
@@@ -33,6 -33,7 +33,7 @@@ src/stamp-h
  .libs/
  src/collectd
  src/collectd-nagios
+ src/collectdctl
  src/collectdmon
  src/*.1
  src/*.5
@@@ -65,9 -66,3 +66,9 @@@ bindings/java/org/collectd/java/*.clas
  
  # python stuff
  *.pyc
 +
 +# tag stuff
 +src/tags
 +
 +# backup stuff
 +*~
diff --combined src/irq.c
+++ b/src/irq.c
@@@ -29,8 -29,6 +29,6 @@@
  # error "No applicable input method."
  #endif
  
- #define BUFSIZE 128
  /*
   * (Module-)Global variables
   */
@@@ -41,8 -39,8 +39,8 @@@ static const char *config_keys[] 
  };
  static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
  
- static unsigned int *irq_list;
- static unsigned int irq_list_num;
+ static char         **irq_list;
+ static unsigned int   irq_list_num = 0;
  
  /* 
   * irq_list_action:
@@@ -55,11 -53,9 +53,9 @@@ static int irq_config (const char *key
  {
        if (strcasecmp (key, "Irq") == 0)
        {
-               unsigned int *temp;
-               unsigned int irq;
-               char *endptr;
+               char **temp;
  
-               temp = (unsigned int *) realloc (irq_list, (irq_list_num + 1) * sizeof (unsigned int *));
+               temp = realloc (irq_list, (irq_list_num + 1) * sizeof (*irq_list));
                if (temp == NULL)
                {
                        fprintf (stderr, "irq plugin: Cannot allocate more memory.\n");
                }
                irq_list = temp;
  
-               /* Clear errno, because we need it to see if an error occured. */
-               errno = 0;
-               irq = strtol(value, &endptr, 10);
-               if ((endptr == value) || (errno != 0))
+               irq_list[irq_list_num] = strdup (value);
+               if (irq_list[irq_list_num] == NULL)
                {
-                       fprintf (stderr, "irq plugin: Irq value is not a "
-                                       "number: `%s'\n", value);
-                       ERROR ("irq plugin: Irq value is not a "
-                                       "number: `%s'", value);
+                       ERROR ("irq plugin: strdup(3) failed.");
                        return (1);
                }
-               irq_list[irq_list_num] = irq;
                irq_list_num++;
        }
        else if (strcasecmp (key, "IgnoreSelected") == 0)
   * both, `submit' and `write' to give client and server the ability to
   * ignore certain stuff..
   */
- static int check_ignore_irq (const unsigned int irq)
+ static int check_ignore_irq (const char *irq)
  {
-       int i;
+       unsigned int i;
  
        if (irq_list_num < 1)
                return (0);
  
-       for (i = 0; (unsigned int)i < irq_list_num; i++)
-               if (irq == irq_list[i])
+       for (i = 0; i < irq_list_num; i++)
+               if (strcmp (irq, irq_list[i]) == 0)
                        return (irq_list_action);
  
        return (1 - irq_list_action);
  }
  
- static void irq_submit (unsigned int irq, derive_t value)
 -static void irq_submit (const char *irq_name, counter_t value)
++static void irq_submit (const char *irq_name, derive_t value)
  {
        value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
-       int status;
  
-       if (check_ignore_irq (irq))
+       if (check_ignore_irq (irq_name))
                return;
  
 -      values[0].counter = value;
 +      values[0].derive = value;
  
        vl.values = values;
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "irq", sizeof (vl.plugin));
        sstrncpy (vl.type, "irq", sizeof (vl.type));
-       status = ssnprintf (vl.type_instance, sizeof (vl.type_instance),
-                       "%u", irq);
-       if ((status < 1) || ((unsigned int)status >= sizeof (vl.type_instance)))
-               return;
+       sstrncpy (vl.type_instance, irq_name, sizeof (vl.type_instance));
  
        plugin_dispatch_values (&vl);
  } /* void irq_submit */
@@@ -145,54 -130,63 +130,62 @@@ static int irq_read (void
  {
        FILE *fh;
        char buffer[1024];
 -      unsigned long long irq_value;
 -      unsigned long long value;
 -      char *endptr;
 -      int i;
  
 -      char *fields[64];
 -      int fields_num;
 -
 -      if ((fh = fopen ("/proc/interrupts", "r")) == NULL)
 +      fh = fopen ("/proc/interrupts", "r");
 +      if (fh == NULL)
        {
                char errbuf[1024];
 -              WARNING ("irq plugin: fopen (/proc/interrupts): %s",
 +              ERROR ("irq plugin: fopen (/proc/interrupts): %s",
                                sstrerror (errno, errbuf, sizeof (errbuf)));
                return (-1);
        }
-       while (fgets (buffer, BUFSIZE, fh) != NULL)
 +
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
        {
-               unsigned int irq;
+               char *irq_name;
+               size_t irq_name_len;
 +              derive_t irq_value;
-               char *endptr;
 +              int i;
 +
 +              char *fields[64];
 +              int fields_num;
  
                fields_num = strsplit (buffer, fields, 64);
                if (fields_num < 2)
                        continue;
  
-               errno = 0;    /* To distinguish success/failure after call */
-               irq = (unsigned int) strtoul (fields[0], &endptr, /* base = */ 10);
+               irq_name = fields[0];
+               irq_name_len = strlen (irq_name);
+               if (irq_name_len < 2)
+                       continue;
  
-               if ((endptr == fields[0]) || (errno != 0) || (*endptr != ':'))
+               /* Check if irq name ends with colon.
+                * Otherwise it's a header. */
+               if (irq_name[irq_name_len - 1] != ':')
                        continue;
  
+               irq_name[irq_name_len - 1] = 0;
+               irq_name_len--;
                irq_value = 0;
                for (i = 1; i < fields_num; i++)
                {
 -                      errno = 0;
 -                      endptr = NULL;
 -                      value = strtoull (fields[i], &endptr, 10);
 +                      /* Per-CPU value */
 +                      value_t v;
 +                      int status;
  
 -                      /* Ignore all fields following a non-numeric field. */
 -                      if ((errno != 0) || (endptr == NULL) || (*endptr != 0))
 +                      status = parse_value (fields[i], &v, DS_TYPE_DERIVE);
 +                      if (status != 0)
                                break;
  
 -                      irq_value += value;
 +                      irq_value += v.derive;
                } /* for (i) */
  
-               if (i < fields_num)
+               /* No valid fields -> do not submit anything. */
+               if (i <= 1)
                        continue;
  
-               irq_submit (irq, irq_value);
 -              /* Force 32bit wrap-around */
 -              irq_submit (irq_name, irq_value % 4294967296ULL);
++              irq_submit (irq_name, irq_value);
        }
  
        fclose (fh);
@@@ -206,5 -200,3 +199,3 @@@ void module_register (void
                        config_keys, config_keys_num);
        plugin_register_read ("irq", irq_read);
  } /* void module_register */
- #undef BUFSIZE
diff --combined src/plugin.c
@@@ -1,6 -1,6 +1,6 @@@
  /**
   * collectd - src/plugin.c
 - * Copyright (C) 2005-2009  Florian octo Forster
 + * Copyright (C) 2005-2011  Florian octo Forster
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the
@@@ -16,7 -16,7 +16,7 @@@
   * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
   *
   * Authors:
 - *   Florian octo Forster <octo at verplant.org>
 + *   Florian octo Forster <octo at collectd.org>
   *   Sebastian Harl <sh at tokkee.org>
   **/
  
@@@ -36,6 -36,7 +36,6 @@@
  #include "utils_llist.h"
  #include "utils_heap.h"
  #include "utils_cache.h"
 -#include "utils_threshold.h"
  #include "filter_chain.h"
  
  /*
@@@ -73,7 -74,6 +73,7 @@@ typedef struct read_func_s read_func_t
  static llist_t *list_init;
  static llist_t *list_write;
  static llist_t *list_flush;
 +static llist_t *list_missing;
  static llist_t *list_shutdown;
  static llist_t *list_log;
  static llist_t *list_notification;
@@@ -346,7 -346,7 +346,7 @@@ static void *plugin_read_thread (void _
        while (read_loop != 0)
        {
                read_func_t *rf;
 -              struct timeval now;
 +              cdtime_t now;
                int status;
                int rf_type;
                int rc;
                {
                        struct timespec abstime;
  
 -                      gettimeofday (&now, /* timezone = */ NULL);
 +                      now = cdtime ();
  
 -                      abstime.tv_sec = now.tv_sec + interval_g;
 -                      abstime.tv_nsec = 1000 * now.tv_usec;
 +                      CDTIME_T_TO_TIMESPEC (now + interval_g, &abstime);
  
                        pthread_mutex_lock (&read_lock);
                        pthread_cond_timedwait (&read_cond, &read_lock,
  
                if ((rf->rf_interval.tv_sec == 0) && (rf->rf_interval.tv_nsec == 0))
                {
 -                      gettimeofday (&now, /* timezone = */ NULL);
 +                      now = cdtime ();
  
 -                      rf->rf_interval.tv_sec = interval_g;
 -                      rf->rf_interval.tv_nsec = 0;
 +                      CDTIME_T_TO_TIMESPEC (interval_g, &rf->rf_interval);
  
                        rf->rf_effective_interval = rf->rf_interval;
  
 -                      rf->rf_next_read.tv_sec = now.tv_sec;
 -                      rf->rf_next_read.tv_nsec = 1000 * now.tv_usec;
 +                      CDTIME_T_TO_TIMESPEC (now, &rf->rf_next_read);
                }
  
                /* sleep until this entry is due,
                }
  
                /* update the ``next read due'' field */
 -              gettimeofday (&now, /* timezone = */ NULL);
 +              now = cdtime ();
  
                DEBUG ("plugin_read_thread: Effective interval of the "
                                "%s plugin is %i.%09i.",
                NORMALIZE_TIMESPEC (rf->rf_next_read);
  
                /* Check, if `rf_next_read' is in the past. */
 -              if ((rf->rf_next_read.tv_sec < now.tv_sec)
 -                              || ((rf->rf_next_read.tv_sec == now.tv_sec)
 -                                      && (rf->rf_next_read.tv_nsec < (1000 * now.tv_usec))))
 +              if (TIMESPEC_TO_CDTIME_T (&rf->rf_next_read) < now)
                {
                        /* `rf_next_read' is in the past. Insert `now'
                         * so this value doesn't trail off into the
                         * past too much. */
 -                      rf->rf_next_read.tv_sec = now.tv_sec;
 -                      rf->rf_next_read.tv_nsec = 1000 * now.tv_usec;
 +                      CDTIME_T_TO_TIMESPEC (now, &rf->rf_next_read);
                }
  
                DEBUG ("plugin_read_thread: Next read of the %s plugin at %i.%09i.",
@@@ -738,17 -744,6 +738,17 @@@ static int plugin_insert_read (read_fun
                }
        }
  
 +      le = llist_search (read_list, rf->rf_name);
 +      if (le != NULL)
 +      {
 +              pthread_mutex_unlock (&read_lock);
 +              WARNING ("The read function \"%s\" is already registered. "
 +                              "Check for duplicate \"LoadPlugin\" lines "
 +                              "in your configuration!",
 +                              rf->rf_name);
 +              return (EINVAL);
 +      }
 +
        le = llentry_create (rf->rf_name, rf);
        if (le == NULL)
        {
@@@ -777,13 -772,14 +777,13 @@@ int plugin_register_read (const char *n
                int (*callback) (void))
  {
        read_func_t *rf;
 +      int status;
  
 -      rf = (read_func_t *) malloc (sizeof (read_func_t));
 +      rf = malloc (sizeof (*rf));
        if (rf == NULL)
        {
 -              char errbuf[1024];
 -              ERROR ("plugin_register_read: malloc failed: %s",
 -                              sstrerror (errno, errbuf, sizeof (errbuf)));
 -              return (-1);
 +              ERROR ("plugin_register_read: malloc failed.");
 +              return (ENOMEM);
        }
  
        memset (rf, 0, sizeof (read_func_t));
        rf->rf_interval.tv_nsec = 0;
        rf->rf_effective_interval = rf->rf_interval;
  
 -      return (plugin_insert_read (rf));
 +      status = plugin_insert_read (rf);
 +      if (status != 0)
 +              sfree (rf);
 +
 +      return (status);
  } /* int plugin_register_read */
  
  int plugin_register_complex_read (const char *group, const char *name,
                user_data_t *user_data)
  {
        read_func_t *rf;
 +      int status;
  
 -      rf = (read_func_t *) malloc (sizeof (read_func_t));
 +      rf = malloc (sizeof (*rf));
        if (rf == NULL)
        {
                ERROR ("plugin_register_complex_read: malloc failed.");
 -              return (-1);
 +              return (ENOMEM);
        }
  
        memset (rf, 0, sizeof (read_func_t));
                rf->rf_udata = *user_data;
        }
  
 -      return (plugin_insert_read (rf));
 +      status = plugin_insert_read (rf);
 +      if (status != 0)
 +              sfree (rf);
 +
 +      return (status);
  } /* int plugin_register_complex_read */
  
  int plugin_register_write (const char *name,
@@@ -865,13 -852,6 +865,13 @@@ int plugin_register_flush (const char *
                                (void *) callback, ud));
  } /* int plugin_register_flush */
  
 +int plugin_register_missing (const char *name,
 +              plugin_missing_cb callback, user_data_t *ud)
 +{
 +      return (create_register_callback (&list_missing, name,
 +                              (void *) callback, ud));
 +} /* int plugin_register_missing */
 +
  int plugin_register_shutdown (const char *name,
                int (*callback) (void))
  {
@@@ -1058,11 -1038,6 +1058,11 @@@ int plugin_unregister_flush (const cha
        return (plugin_unregister (list_flush, name));
  }
  
 +int plugin_unregister_missing (const char *name)
 +{
 +      return (plugin_unregister (list_missing, name));
 +}
 +
  int plugin_unregister_shutdown (const char *name)
  {
        return (plugin_unregister (list_shutdown, name));
@@@ -1286,7 -1261,7 +1286,7 @@@ int plugin_write (const char *plugin, /
    return (status);
  } /* }}} int plugin_write */
  
 -int plugin_flush (const char *plugin, int timeout, const char *identifier)
 +int plugin_flush (const char *plugin, cdtime_t timeout, const char *identifier)
  {
    llentry_t *le;
  
@@@ -1331,8 -1306,7 +1331,8 @@@ void plugin_shutdown_all (void
  
        destroy_read_heap ();
  
 -      plugin_flush (/* plugin = */ NULL, /* timeout = */ -1,
 +      plugin_flush (/* plugin = */ NULL,
 +                      /* timeout = */ 0,
                        /* identifier = */ NULL);
  
        le = NULL;
         * the real free function when registering the write callback. This way
         * the data isn't freed twice. */
        destroy_all_callbacks (&list_flush);
 +      destroy_all_callbacks (&list_missing);
        destroy_all_callbacks (&list_write);
  
        destroy_all_callbacks (&list_notification);
        destroy_all_callbacks (&list_log);
  } /* void plugin_shutdown_all */
  
 +int plugin_dispatch_missing (const value_list_t *vl) /* {{{ */
 +{
 +  llentry_t *le;
 +
 +  if (list_missing == NULL)
 +    return (0);
 +
 +  le = llist_head (list_missing);
 +  while (le != NULL)
 +  {
 +    callback_func_t *cf;
 +    plugin_missing_cb callback;
 +    int status;
 +
 +    cf = le->value;
 +    callback = cf->cf_callback;
 +
 +    status = (*callback) (vl, &cf->cf_udata);
 +    if (status != 0)
 +    {
 +      if (status < 0)
 +      {
 +        ERROR ("plugin_dispatch_missing: Callback function \"%s\" "
 +            "failed with status %i.",
 +            le->key, status);
 +        return (status);
 +      }
 +      else
 +      {
 +        return (0);
 +      }
 +    }
 +
 +    le = le->next;
 +  }
 +  return (0);
 +} /* int }}} plugin_dispatch_missing */
 +
  int plugin_dispatch_values (value_list_t *vl)
  {
        int status;
        if ((vl == NULL) || (vl->type[0] == 0)
                        || (vl->values == NULL) || (vl->values_len < 1))
        {
-               ERROR ("plugin_dispatch_values: Invalid value list.");
+               ERROR ("plugin_dispatch_values: Invalid value list "
+                               "from plugin %s.", vl->plugin);
                return (-1);
        }
  
        }
  
        if (vl->time == 0)
 -              vl->time = time (NULL);
 +              vl->time = cdtime ();
  
        if (vl->interval <= 0)
                vl->interval = interval_g;
  
 -      DEBUG ("plugin_dispatch_values: time = %u; interval = %i; "
 +      DEBUG ("plugin_dispatch_values: time = %.3f; interval = %.3f; "
                        "host = %s; "
                        "plugin = %s; plugin_instance = %s; "
                        "type = %s; type_instance = %s;",
 -                      (unsigned int) vl->time, vl->interval,
 +                      CDTIME_T_TO_DOUBLE (vl->time),
 +                      CDTIME_T_TO_DOUBLE (vl->interval),
                        vl->host,
                        vl->plugin, vl->plugin_instance,
                        vl->type, vl->type_instance);
        /* Update the value cache */
        uc_update (ds, vl);
  
 -      /* Initiate threshold checking */
 -      ut_check_threshold (ds, vl);
 -
        if (post_cache_chain != NULL)
        {
                status = fc_process_chain (ds, vl, post_cache_chain);
@@@ -1591,9 -1529,9 +1592,9 @@@ int plugin_dispatch_notification (cons
        /* Possible TODO: Add flap detection here */
  
        DEBUG ("plugin_dispatch_notification: severity = %i; message = %s; "
 -                      "time = %u; host = %s;",
 +                      "time = %.3f; host = %s;",
                        notif->severity, notif->message,
 -                      (unsigned int) notif->time, notif->host);
 +                      CDTIME_T_TO_DOUBLE (notif->time), notif->host);
  
        /* Nobody cares for notifications */
        if (list_notification == NULL)
@@@ -1727,7 -1665,7 +1728,7 @@@ static int plugin_notification_meta_ad
      }
      case NM_TYPE_BOOLEAN:
      {
 -      meta->nm_value.nm_boolean = *((bool *) value);
 +      meta->nm_value.nm_boolean = *((_Bool *) value);
        break;
      }
      default:
@@@ -1781,7 -1719,7 +1782,7 @@@ int plugin_notification_meta_add_doubl
  
  int plugin_notification_meta_add_boolean (notification_t *n,
      const char *name,
 -    bool value)
 +    _Bool value)
  {
    return (plugin_notification_meta_add (n, name, NM_TYPE_BOOLEAN, &value));
  }
diff --combined src/processes.c
@@@ -1,7 -1,7 +1,7 @@@
  /**
   * collectd - src/processes.c
   * Copyright (C) 2005       Lyonel Vincent
 - * Copyright (C) 2006-2008  Florian octo Forster
 + * Copyright (C) 2006-2010  Florian octo Forster
   * Copyright (C) 2008       Oleg King
   * Copyright (C) 2009       Sebastian Harl
   * Copyright (C) 2009       Andrés J. Díaz
  #  define ARG_MAX 4096
  #endif
  
- static const char *config_keys[] =
- {
-       "Process",
-       "ProcessMatch"
- };
- static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
  typedef struct procstat_entry_s
  {
        unsigned long id;
  
        unsigned long vmem_minflt;
        unsigned long vmem_majflt;
 -      unsigned long vmem_minflt_counter;
 -      unsigned long vmem_majflt_counter;
 +      derive_t      vmem_minflt_counter;
 +      derive_t      vmem_majflt_counter;
  
        unsigned long cpu_user;
        unsigned long cpu_system;
 -      unsigned long cpu_user_counter;
 -      unsigned long cpu_system_counter;
 +      derive_t      cpu_user_counter;
 +      derive_t      cpu_system_counter;
  
        /* io data */
        derive_t io_rchar;
@@@ -176,11 -169,11 +169,11 @@@ typedef struct procsta
        unsigned long vmem_code;
        unsigned long stack_size;
  
 -      unsigned long vmem_minflt_counter;
 -      unsigned long vmem_majflt_counter;
 +      derive_t vmem_minflt_counter;
 +      derive_t vmem_majflt_counter;
  
 -      unsigned long cpu_user_counter;
 -      unsigned long cpu_system_counter;
 +      derive_t cpu_user_counter;
 +      derive_t cpu_system_counter;
  
        /* io data */
        derive_t io_rchar;
@@@ -520,42 -513,61 +513,61 @@@ static void ps_list_reset (void
  }
  
  /* put all pre-defined 'Process' names from config to list_head_g tree */
- static int ps_config (const char *key, const char *value)
+ static int ps_config (oconfig_item_t *ci)
  {
-       if (strcasecmp (key, "Process") == 0)
-       {
-               ps_list_register (value, NULL);
-       }
-       else if (strcasecmp (key, "ProcessMatch") == 0)
-       {
-               char *new_val;
-               char *fields[3];
-               int fields_num;
-               new_val = strdup (value);
-               if (new_val == NULL) {
-                       ERROR ("processes plugin: strdup failed when processing "
-                                       "`ProcessMatch %s'.", value);
-                       return (1);
+       int i;
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *c = ci->children + i;
+               if (strcasecmp (c->key, "Process") == 0)
+               {
+                       if ((c->values_num != 1)
+                                       || (OCONFIG_TYPE_STRING != c->values[0].type)) {
+                               ERROR ("processes plugin: `Process' expects exactly "
+                                               "one string argument (got %i).",
+                                               c->values_num);
+                               continue;
+                       }
+                       if (c->children_num != 0) {
+                               WARNING ("processes plugin: the `Process' config option "
+                                               "does not expect any child elements -- ignoring "
+                                               "content (%i elements) of the <Process '%s'> block.",
+                                               c->children_num, c->values[0].value.string);
+                       }
+                       ps_list_register (c->values[0].value.string, NULL);
                }
+               else if (strcasecmp (c->key, "ProcessMatch") == 0)
+               {
+                       if ((c->values_num != 2)
+                                       || (OCONFIG_TYPE_STRING != c->values[0].type)
+                                       || (OCONFIG_TYPE_STRING != c->values[1].type))
+                       {
+                               ERROR ("processes plugin: `ProcessMatch' needs exactly "
+                                               "two string arguments (got %i).",
+                                               c->values_num);
+                               continue;
+                       }
  
-               fields_num = strsplit (new_val, fields,
-                               STATIC_ARRAY_SIZE (fields));
-               if (fields_num != 2)
+                       if (c->children_num != 0) {
+                               WARNING ("processes plugin: the `ProcessMatch' config option "
+                                               "does not expect any child elements -- ignoring "
+                                               "content (%i elements) of the <ProcessMatch '%s' '%s'> "
+                                               "block.", c->children_num, c->values[0].value.string,
+                                               c->values[1].value.string);
+                       }
+                       ps_list_register (c->values[0].value.string,
+                                       c->values[1].value.string);
+               }
+               else
                {
-                       ERROR ("processes plugin: `ProcessMatch' needs exactly "
-                                       "two string arguments.");
-                       sfree (new_val);
-                       return (1);
+                       ERROR ("processes plugin: The `%s' configuration option is not "
+                                       "understood and will be ignored.", c->key);
+                       continue;
                }
-               ps_list_register (fields[0], fields[1]);
-               sfree (new_val);
-       }
-       else
-       {
-               ERROR ("processes plugin: The `%s' configuration option is not "
-                               "understood and will be ignored.", key);
-               return (-1);
        }
  
        return (0);
@@@ -664,8 -676,8 +676,8 @@@ static void ps_submit_proc_list (procst
        plugin_dispatch_values (&vl);
  
        sstrncpy (vl.type, "ps_cputime", sizeof (vl.type));
 -      vl.values[0].counter = ps->cpu_user_counter;
 -      vl.values[1].counter = ps->cpu_system_counter;
 +      vl.values[0].derive = ps->cpu_user_counter;
 +      vl.values[1].derive = ps->cpu_system_counter;
        vl.values_len = 2;
        plugin_dispatch_values (&vl);
  
        plugin_dispatch_values (&vl);
  
        sstrncpy (vl.type, "ps_pagefaults", sizeof (vl.type));
 -      vl.values[0].counter = ps->vmem_minflt_counter;
 -      vl.values[1].counter = ps->vmem_majflt_counter;
 +      vl.values[0].derive = ps->vmem_minflt_counter;
 +      vl.values[1].derive = ps->vmem_majflt_counter;
        vl.values_len = 2;
        plugin_dispatch_values (&vl);
  
        DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; "
                          "vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
                        "vmem_code = %lu; "
 -                      "vmem_minflt_counter = %lu; vmem_majflt_counter = %lu; "
 -                      "cpu_user_counter = %lu; cpu_system_counter = %lu; "
 +                      "vmem_minflt_counter = %"PRIi64"; vmem_majflt_counter = %"PRIi64"; "
 +                      "cpu_user_counter = %"PRIi64"; cpu_system_counter = %"PRIi64"; "
                        "io_rchar = %"PRIi64"; io_wchar = %"PRIi64"; "
                        "io_syscr = %"PRIi64"; io_syscw = %"PRIi64";",
                        ps->name, ps->num_proc, ps->num_lwp,
@@@ -873,8 -885,8 +885,8 @@@ int ps_read_process (int pid, procstat_
  
        int   name_len;
  
 -      long long unsigned cpu_user_counter;
 -      long long unsigned cpu_system_counter;
 +      derive_t cpu_user_counter;
 +      derive_t cpu_system_counter;
        long long unsigned vmem_size;
        long long unsigned vmem_rss;
        long long unsigned stack_size;
        cpu_system_counter = atoll (fields[14]);
        vmem_size          = atoll (fields[22]);
        vmem_rss           = atoll (fields[23]);
 -      ps->vmem_minflt_counter = atol (fields[9]);
 -      ps->vmem_majflt_counter = atol (fields[11]);
 +      ps->vmem_minflt_counter = atoll (fields[9]);
 +      ps->vmem_majflt_counter = atoll (fields[11]);
  
        {
                unsigned long long stack_start = atoll (fields[27]);
                DEBUG("ps_read_process: did not get vmem data for pid %i",pid);
        }
  
 -      ps->cpu_user_counter = (unsigned long) cpu_user_counter;
 -      ps->cpu_system_counter = (unsigned long) cpu_system_counter;
 +      ps->cpu_user_counter = cpu_user_counter;
 +      ps->cpu_system_counter = cpu_system_counter;
        ps->vmem_size = (unsigned long) vmem_size;
        ps->vmem_rss = (unsigned long) vmem_rss;
        ps->stack_size = (unsigned long) stack_size;
@@@ -1827,8 -1839,7 +1839,7 @@@ static int ps_read (void
  
  void module_register (void)
  {
-       plugin_register_config ("processes", ps_config,
-                       config_keys, config_keys_num);
+       plugin_register_complex_config ("processes", ps_config);
        plugin_register_init ("processes", ps_init);
        plugin_register_read ("processes", ps_read);
  } /* void module_register */
diff --combined src/utils_rrdcreate.c
@@@ -103,10 -103,7 +103,10 @@@ static int rra_get (char ***ret, const 
      return (-1);
    }
  
 -  ss = (cfg->stepsize > 0) ? cfg->stepsize : vl->interval;
 +  if (cfg->stepsize > 0)
 +    ss = cfg->stepsize;
 +  else
 +    ss = (int) CDTIME_T_TO_TIME_T (vl->interval);
    if (ss <= 0)
    {
      *ret = NULL;
        if (rra_num >= rra_max)
          break;
  
-       status = ssnprintf (buffer, sizeof (buffer), "RRA:%s:%3.1f:%u:%u",
+       status = ssnprintf (buffer, sizeof (buffer), "RRA:%s:%.10f:%u:%u",
            rra_types[j], cfg->xff, cdp_len, cdp_num);
  
        if ((status < 0) || ((size_t) status >= sizeof (buffer)))
@@@ -244,9 -241,7 +244,9 @@@ static int ds_get (char ***ret, /* {{{ 
      status = ssnprintf (buffer, sizeof (buffer),
          "DS:%s:%s:%i:%s:%s",
          d->name, type,
 -        (cfg->heartbeat > 0) ? cfg->heartbeat : (2 * vl->interval),
 +        (cfg->heartbeat > 0)
 +        ? cfg->heartbeat
 +        : (int) CDTIME_T_TO_TIME_T (2 * vl->interval),
          min, max);
      if ((status < 1) || ((size_t) status >= sizeof (buffer)))
        break;
@@@ -328,7 -323,7 +328,7 @@@ static int srrd_create (const char *fil
      last_up = time (NULL) - 10;
  
    ssnprintf (pdp_step_str, sizeof (pdp_step_str), "%lu", pdp_step);
 -  ssnprintf (last_up_str, sizeof (last_up_str), "%u", (unsigned int) last_up);
 +  ssnprintf (last_up_str, sizeof (last_up_str), "%lu", (unsigned long) last_up);
  
    new_argv[0] = "create";
    new_argv[1] = (void *) filename;
@@@ -373,8 -368,6 +373,8 @@@ int cu_rrd_create_file (const char *fil
    char **ds_def;
    int ds_num;
    int status = 0;
 +  time_t last_up;
 +  unsigned long stepsize;
  
    if (check_create_dir (filename))
      return (-1);
    memcpy (argv + ds_num, rra_def, rra_num * sizeof (char *));
    argv[ds_num + rra_num] = NULL;
  
 -  status = srrd_create (filename,
 -      (cfg->stepsize > 0) ? cfg->stepsize : vl->interval,
 -      (vl->time > 10) ? (vl->time - 10) : vl->time,
 +  last_up = CDTIME_T_TO_TIME_T (vl->time);
 +  if (last_up <= 10)
 +    last_up = time (NULL);
 +  last_up -= 10;
 +
 +  if (cfg->stepsize > 0)
 +    stepsize = cfg->stepsize;
 +  else
 +    stepsize = (unsigned long) CDTIME_T_TO_TIME_T (vl->interval);
 +
 +  status = srrd_create (filename, stepsize, last_up,
        argc, (const char **) argv);
  
    free (argv);