Merge branch 'collectd-4.10' into collectd-5.0
authorFlorian Forster <octo@collectd.org>
Fri, 7 Sep 2012 09:05:48 +0000 (11:05 +0200)
committerFlorian Forster <octo@collectd.org>
Fri, 7 Sep 2012 09:05:48 +0000 (11:05 +0200)
1  2 
src/Makefile.am
src/collectd.c
src/collectd.conf.pod
src/common.c
src/df.c
src/memcachec.c
src/netapp.c
src/oracle.c
src/rrdtool.c
src/snmp.c
src/utils_dns.c

diff --combined src/Makefile.am
@@@ -21,7 -21,7 +21,7 @@@ AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdi
  AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
  
  sbin_PROGRAMS = collectd collectdmon
 -bin_PROGRAMS = collectd-nagios
 +bin_PROGRAMS = collectd-nagios collectdctl
  
  collectd_SOURCES = collectd.c collectd.h \
                   common.c common.h \
                   utils_match.c utils_match.h \
                   utils_subst.c utils_subst.h \
                   utils_tail.c utils_tail.h \
 -                 utils_threshold.c utils_threshold.h \
 +                 utils_time.c utils_time.h \
                   types_list.c types_list.h
  
  collectd_CPPFLAGS =  $(AM_CPPFLAGS) $(LTDLINCL)
  collectd_CFLAGS = $(AM_CFLAGS)
  collectd_LDFLAGS = -export-dynamic
- collectd_LDADD =
+ collectd_LDADD = -lm
  collectd_DEPENDENCIES =
  
  # Link to these libraries..
@@@ -73,7 -73,6 +73,6 @@@ collectd_LDADD += -ldevinf
  endif
  if BUILD_AIX
  collectd_LDFLAGS += -Wl,-bexpall,-brtllib
- collectd_LDADD += -lm
  endif
  
  # The daemon needs to call sg_init, so we need to link it against libstatgrab,
@@@ -105,36 -104,11 +104,36 @@@ endi
  collectd_nagios_LDADD += libcollectdclient/libcollectdclient.la
  collectd_nagios_DEPENDENCIES = libcollectdclient/libcollectdclient.la
  
 +
 +collectdctl_SOURCES = collectdctl.c
 +collectdctl_LDADD =
 +if BUILD_WITH_LIBSOCKET
 +collectdctl_LDADD += -lsocket
 +endif
 +if BUILD_AIX
 +collectdctl_LDADD += -lm
 +endif
 +collectdctl_LDADD += libcollectdclient/libcollectdclient.la
 +collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la
 +
 +
  pkglib_LTLIBRARIES = 
  
  BUILT_SOURCES = 
  CLEANFILES = 
  
 +if BUILD_PLUGIN_AMQP
 +pkglib_LTLIBRARIES += amqp.la
 +amqp_la_SOURCES = amqp.c \
 +                utils_cmd_putval.c utils_cmd_putval.h \
 +                utils_format_json.c utils_format_json.h
 +amqp_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBRABBITMQ_LDFLAGS)
 +amqp_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRABBITMQ_CPPFLAGS)
 +amqp_la_LIBADD = $(BUILD_WITH_LIBRABBITMQ_LIBS)
 +collectd_LDADD += "-dlopen" amqp.la
 +collectd_DEPENDENCIES += amqp.la
 +endif
 +
  if BUILD_PLUGIN_APACHE
  pkglib_LTLIBRARIES += apache.la
  apache_la_SOURCES = apache.c
@@@ -526,15 -500,6 +525,15 @@@ collectd_LDADD += "-dlopen" logfile.l
  collectd_DEPENDENCIES += logfile.la
  endif
  
 +if BUILD_PLUGIN_LPAR
 +pkglib_LTLIBRARIES += lpar.la
 +lpar_la_SOURCES = lpar.c
 +lpar_la_LDFLAGS = -module -avoid-version
 +collectd_LDADD += "-dlopen" lpar.la
 +collectd_DEPENDENCIES += lpar.la
 +lpar_la_LIBADD = -lperfstat
 +endif
 +
  if BUILD_PLUGIN_MADWIFI
  pkglib_LTLIBRARIES += madwifi.la
  madwifi_la_SOURCES = madwifi.c madwifi.h
@@@ -921,16 -886,6 +920,16 @@@ collectd_LDADD += "-dlopen" protocols.l
  collectd_DEPENDENCIES += protocols.la
  endif
  
 +if BUILD_PLUGIN_REDIS
 +pkglib_LTLIBRARIES += redis.la
 +redis_la_SOURCES = redis.c
 +redis_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBCREDIS_LDFLAGS)
 +redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCREDIS_CPPFLAGS)
 +redis_la_LIBADD = -lcredis
 +collectd_LDADD += "-dlopen" redis.la
 +collectd_DEPENDENCIES += redis.la
 +endif
 +
  if BUILD_PLUGIN_ROUTEROS
  pkglib_LTLIBRARIES += routeros.la
  routeros_la_SOURCES = routeros.c
@@@ -1088,14 -1043,6 +1087,14 @@@ collectd_LDADD += "-dlopen" target_set.
  collectd_DEPENDENCIES += target_set.la
  endif
  
 +if BUILD_PLUGIN_TARGET_V5UPGRADE
 +pkglib_LTLIBRARIES += target_v5upgrade.la
 +target_v5upgrade_la_SOURCES = target_v5upgrade.c
 +target_v5upgrade_la_LDFLAGS = -module -avoid-version
 +collectd_LDADD += "-dlopen" target_v5upgrade.la
 +collectd_DEPENDENCIES += target_v5upgrade.la
 +endif
 +
  if BUILD_PLUGIN_TCPCONNS
  pkglib_LTLIBRARIES += tcpconns.la
  tcpconns_la_SOURCES = tcpconns.c
@@@ -1132,14 -1079,6 +1131,14 @@@ collectd_LDADD += "-dlopen" thermal.l
  collectd_DEPENDENCIES += thermal.la
  endif
  
 +if BUILD_PLUGIN_THRESHOLD
 +pkglib_LTLIBRARIES += threshold.la
 +threshold_la_SOURCES = threshold.c
 +threshold_la_LDFLAGS = -module -avoid-version
 +collectd_LDADD += "-dlopen" threshold.la
 +collectd_DEPENDENCIES += threshold.la
 +endif
 +
  if BUILD_PLUGIN_TOKYOTYRANT
  pkglib_LTLIBRARIES += tokyotyrant.la
  tokyotyrant_la_SOURCES = tokyotyrant.c
@@@ -1158,6 -1097,7 +1157,6 @@@ pkglib_LTLIBRARIES += unixsock.l
  unixsock_la_SOURCES = unixsock.c \
                      utils_cmd_flush.h utils_cmd_flush.c \
                      utils_cmd_getval.h utils_cmd_getval.c \
 -                    utils_cmd_getthreshold.h utils_cmd_getthreshold.c \
                      utils_cmd_listval.h utils_cmd_listval.c \
                      utils_cmd_putval.h utils_cmd_putval.c \
                      utils_cmd_putnotif.h utils_cmd_putnotif.c
@@@ -1204,16 -1144,6 +1203,16 @@@ collectd_LDADD += "-dlopen" uuid.l
  collectd_DEPENDENCIES += uuid.la
  endif
  
 +if BUILD_PLUGIN_VARNISH
 +pkglib_LTLIBRARIES += varnish.la
 +varnish_la_SOURCES = varnish.c
 +varnish_la_LDFLAGS = -module -avoid-version
 +varnish_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBVARNISH_CFLAGS)
 +varnish_la_LIBADD = $(BUILD_WITH_LIBVARNISH_LIBS)
 +collectd_LDADD += "-dlopen" varnish.la
 +collectd_DEPENDENCIES += varnish.la
 +endif
 +
  if BUILD_PLUGIN_VMEM
  pkglib_LTLIBRARIES += vmem.la
  vmem_la_SOURCES = vmem.c
@@@ -1253,16 -1183,6 +1252,16 @@@ endi
  collectd_DEPENDENCIES += write_http.la
  endif
  
 +if BUILD_PLUGIN_WRITE_REDIS
 +pkglib_LTLIBRARIES += write_redis.la
 +write_redis_la_SOURCES = write_redis.c
 +write_redis_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBCREDIS_LDFLAGS)
 +write_redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCREDIS_CPPFLAGS)
 +write_redis_la_LIBADD = -lcredis
 +collectd_LDADD += "-dlopen" write_redis.la
 +collectd_DEPENDENCIES += write_redis.la
 +endif
 +
  if BUILD_PLUGIN_XMMS
  pkglib_LTLIBRARIES += xmms.la
  xmms_la_SOURCES = xmms.c
@@@ -1287,14 -1207,12 +1286,14 @@@ dist_man_MANS = collectd.1 
                collectd.conf.5 \
                collectd-email.5 \
                collectd-exec.5 \
 +              collectdctl.1 \
                collectd-java.5 \
                collectdmon.1 \
                collectd-nagios.1 \
                collectd-perl.5 \
                collectd-python.5 \
                collectd-snmp.5 \
 +              collectd-threshold.5 \
                collectd-unixsock.5 \
                types.db.5
  
@@@ -1305,7 -1223,6 +1304,7 @@@ EXTRA_DIST = types.db pinba.prot
  EXTRA_DIST +=   collectd.conf.pod \
                collectd-email.pod \
                collectd-exec.pod \
 +              collectdctl.pod \
                collectd-java.pod \
                collectdmon.pod \
                collectd-nagios.pod \
                collectd-python.pod \
                collectd.pod \
                collectd-snmp.pod \
 +              collectd-threshold.pod \
                collectd-unixsock.pod \
                postgresql_default.conf \
                types.db.pod
        fi
  
  pinba.pb-c.c pinba.pb-c.h: pinba.proto
 -      protoc-c --c_out $(builddir) pinba.proto
 +      protoc-c --c_out . pinba.proto
  
  install-exec-hook:
        $(mkinstalldirs) $(DESTDIR)$(sysconfdir)
diff --combined src/collectd.c
@@@ -40,7 -40,7 +40,7 @@@
   * Global variables
   */
  char hostname_g[DATA_MAX_NAME_LEN];
 -int  interval_g;
 +cdtime_t interval_g;
  int  timeout_g;
  #if HAVE_LIBKSTAT
  kstat_ctl_t *kc;
@@@ -51,9 -51,7 +51,9 @@@ static int loop = 0
  static void *do_flush (void __attribute__((unused)) *arg)
  {
        INFO ("Flushing all data.");
 -      plugin_flush (NULL, -1, NULL);
 +      plugin_flush (/* plugin = */ NULL,
 +                      /* timeout = */ 0,
 +                      /* ident = */ NULL);
        INFO ("Finished flushing all data.");
        pthread_exit (NULL);
        return NULL;
@@@ -141,25 -139,15 +141,25 @@@ static int init_global_variables (void
  
        str = global_option_get ("Interval");
        if (str == NULL)
 -              str = "10";
 -      interval_g = atoi (str);
 -      if (interval_g <= 0)
        {
 -              fprintf (stderr, "Cannot set the interval to a correct value.\n"
 -                              "Please check your settings.\n");
 -              return (-1);
 +              interval_g = TIME_T_TO_CDTIME_T (10);
 +      }
 +      else
 +      {
 +              double tmp;
 +
 +              tmp = atof (str);
 +              if (tmp <= 0.0)
 +              {
 +                      fprintf (stderr, "Cannot set the interval to a "
 +                                      "correct value.\n"
 +                                      "Please check your settings.\n");
 +                      return (-1);
 +              }
 +
 +              interval_g = DOUBLE_TO_CDTIME_T (tmp);
        }
 -      DEBUG ("interval_g = %i;", interval_g);
 +      DEBUG ("interval_g = %.3f;", CDTIME_T_TO_DOUBLE (interval_g));
  
        str = global_option_get ("Timeout");
        if (str == NULL)
  
  static int change_basedir (const char *orig_dir)
  {
-       char *dir = strdup (orig_dir);
-       int dirlen;
+       char *dir;
+       size_t dirlen;
        int status;
  
+       dir = strdup (orig_dir);
        if (dir == NULL)
        {
                char errbuf[1024];
                return (-1);
  
        status = chdir (dir);
-       free (dir);
+       if (status == 0)
+       {
+               free (dir);
+               return (0);
+       }
+       else if (errno != ENOENT)
+       {
+               char errbuf[1024];
+               ERROR ("change_basedir: chdir (%s): %s", dir,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               free (dir);
+               return (-1);
+       }
  
+       status = mkdir (dir, S_IRWXU | S_IRWXG | S_IRWXO);
        if (status != 0)
        {
-               if (errno == ENOENT)
-               {
-                       if (mkdir (orig_dir, 0755) == -1)
-                       {
-                               char errbuf[1024];
-                               ERROR ("change_basedir: mkdir (%s): %s", orig_dir,
-                                               sstrerror (errno, errbuf,
-                                                       sizeof (errbuf)));
-                               return (-1);
-                       }
-                       else if (chdir (orig_dir) == -1)
-                       {
-                               char errbuf[1024];
-                               ERROR ("chdir (%s): %s", orig_dir,
-                                               sstrerror (errno, errbuf,
-                                                       sizeof (errbuf)));
-                               return (-1);
-                       }
-               }
-               else
-               {
-                       char errbuf[1024];
-                       ERROR ("chdir (%s): %s", orig_dir,
-                                       sstrerror (errno, errbuf,
-                                               sizeof (errbuf)));
-                       return (-1);
-               }
+               char errbuf[1024];
+               ERROR ("change_basedir: mkdir (%s): %s", dir,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               free (dir);
+               return (-1);
        }
  
+       status = chdir (dir);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR ("change_basedir: chdir (%s): %s", dir,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               free (dir);
+               return (-1);
+       }
+       free (dir);
        return (0);
  } /* static int change_basedir (char *dir) */
  
@@@ -323,14 -314,22 +326,14 @@@ static int do_init (void
  
  static int do_loop (void)
  {
 -      struct timeval tv_now;
 -      struct timeval tv_next;
 -      struct timeval tv_wait;
 -      struct timespec ts_wait;
 +      cdtime_t wait_until;
 +
 +      wait_until = cdtime () + interval_g;
  
        while (loop == 0)
        {
 -              if (gettimeofday (&tv_next, NULL) < 0)
 -              {
 -                      char errbuf[1024];
 -                      ERROR ("gettimeofday failed: %s",
 -                                      sstrerror (errno, errbuf,
 -                                              sizeof (errbuf)));
 -                      return (-1);
 -              }
 -              tv_next.tv_sec += interval_g;
 +              struct timespec ts_wait = { 0, 0 };
 +              cdtime_t now;
  
  #if HAVE_LIBKSTAT
                update_kstat ();
                /* Issue all plugins */
                plugin_read_all ();
  
 -              if (gettimeofday (&tv_now, NULL) < 0)
 -              {
 -                      char errbuf[1024];
 -                      ERROR ("gettimeofday failed: %s",
 -                                      sstrerror (errno, errbuf,
 -                                              sizeof (errbuf)));
 -                      return (-1);
 -              }
 -
 -              if (timeval_cmp (tv_next, tv_now, &tv_wait) <= 0)
 +              now = cdtime ();
 +              if (now >= wait_until)
                {
                        WARNING ("Not sleeping because the next interval is "
 -                                      "%i.%06i seconds in the past!",
 -                                      (int) tv_wait.tv_sec, (int) tv_wait.tv_usec);
 +                                      "%.3f seconds in the past!",
 +                                      CDTIME_T_TO_DOUBLE (now - wait_until));
 +                      wait_until = now + interval_g;
                        continue;
                }
  
 -              ts_wait.tv_sec  = tv_wait.tv_sec;
 -              ts_wait.tv_nsec = (long) (1000 * tv_wait.tv_usec);
 +              CDTIME_T_TO_TIMESPEC (wait_until - now, &ts_wait);
 +              wait_until = wait_until + interval_g;
  
 -              while ((loop == 0) && (nanosleep (&ts_wait, &ts_wait) == -1))
 +              while ((loop == 0) && (nanosleep (&ts_wait, &ts_wait) != 0))
                {
                        if (errno != EINTR)
                        {
                }
        } /* while (loop == 0) */
  
 -      DEBUG ("return (0);");
        return (0);
  } /* int do_loop */
  
diff --combined src/collectd.conf.pod
@@@ -25,22 -25,32 +25,32 @@@ controls which plugins to load. These p
  behavior.
  
  The syntax of this config file is similar to the config file of the famous
- B<Apache Webserver>. Each line contains either a key-value-pair or a
- section-start or -end. Empty lines and everything after the hash-symbol `#' is
- ignored. Values are either string, enclosed in double-quotes,
- (floating-point-)numbers or a boolean expression, i.E<nbsp>e. either B<true> or
- B<false>. String containing of only alphanumeric characters and underscores do
- not need to be quoted. Lines may be wrapped by using `\' as the last character
- before the newline. This allows long lines to be split into multiple lines.
- Quoted strings may be wrapped as well. However, those are treated special in
- that whitespace at the beginning of the following lines will be ignored, which
- allows for nicely indenting the wrapped lines.
- The configuration is read and processed in order, i.E<nbsp>e. from top to
- bottom. So the plugins are loaded in the order listed in this config file. It
- is a good idea to load any logging plugins first in order to catch messages
- from plugins during configuration. Also, the C<LoadPlugin> option B<must> occur
- B<before> the C<E<lt>Plugin ...E<gt>> block.
+ I<Apache> webserver. Each line contains either an option (a key and a list of
+ one or more values) or a section-start or -end. Empty lines and everything
+ after a non-quoted hash-symbol (C<#>) is ignored. I<Keys> are unquoted
+ strings, consisting only of alphanumeric characters and the underscore (C<_>)
+ character. Keys are handled case insensitive by I<collectd> itself and all
+ plugins included with it. I<Values> can either be an I<unquoted string>, a
+ I<quoted string> (enclosed in double-quotes) a I<number> or a I<boolean>
+ expression. I<Unquoted strings> consist of only alphanumeric characters and
+ underscores (C<_>) and do not need to be quoted. I<Quoted strings> are
+ enclosed in double quotes (C<">). You can use the backslash character (C<\>)
+ to include double quotes as part of the string. I<Numbers> can be specified in
+ decimal and floating point format (using a dot C<.> as decimal separator),
+ hexadecimal when using the C<0x> prefix and octal with a leading zero (C<0>).
+ I<Boolean> values are either B<true> or B<false>.
+ Lines may be wrapped by using C<\> as the last character before the newline.
+ This allows long lines to be split into multiple lines. Quoted strings may be
+ wrapped as well. However, those are treated special in that whitespace at the
+ beginning of the following lines will be ignored, which allows for nicely
+ indenting the wrapped lines.
+ The configuration is read and processed in order, i.e. from top to bottom. So
+ the plugins are loaded in the order listed in this config file. It is a good
+ idea to load any logging plugins first in order to catch messages from plugins
+ during configuration. Also, the C<LoadPlugin> option B<must> occur B<before>
+ the appropriate C<E<lt>Plugin ...E<gt>> block.
  
  =head1 GLOBAL OPTIONS
  
@@@ -72,19 -82,15 +82,19 @@@ options are allowed inside a B<LoadPlug
  If enabled, collectd will export all global symbols of the plugin (and of all
  libraries loaded as dependencies of the plugin) and, thus, makes those symbols
  available for resolving unresolved symbols in subsequently loaded plugins if
 -that is supported by your system. By default, this is disabled.
 +that is supported by your system.
  
 -This is useful (or possibly even required), e.E<nbsp>g., when loading a plugin
 -that embeds some scripting language into the daemon (e.E<nbsp>g. the C<perl>
 -or C<python> plugins). Scripting languages usually provide means to load
 +This is useful (or possibly even required), e.g., when loading a plugin that
 +embeds some scripting language into the daemon (e.g. the I<Perl> and
 +I<Python plugins>). Scripting languages usually provide means to load
  extensions written in C. Those extensions require symbols provided by the
 -interpreter, which is loaded as a dependency of the respective collectd
 -plugin. See the documentation of those plugins (e.E<nbsp>g.,
 -L<collectd-perl(5)> or L<collectd-python(5)>) for details.
 +interpreter, which is loaded as a dependency of the respective collectd plugin.
 +See the documentation of those plugins (e.g., L<collectd-perl(5)> or
 +L<collectd-python(5)>) for details.
 +
 +By default, this is disabled. As a special exception, if the plugin name is
 +either C<perl> or C<python>, the default is changed to enabled in order to keep
 +the average user from ever having to deal with this low level linking stuff.
  
  =back
  
@@@ -145,7 -151,7 +155,7 @@@ missing when no update has been receive
  this setting uses iterations, the maximum allowed time without update depends
  on the I<Interval> information contained in each value list. This is used in
  the I<Threshold> configuration to dispatch notifications about missing values,
 -see L<"THRESHOLD CONFIGURATION"> below.
 +see L<collectd-threshold(5)> for details.
  
  =item B<ReadThreads> I<Num>
  
@@@ -163,8 -169,13 +173,8 @@@ hostname will be determined using the L
  
  If B<Hostname> is determined automatically this setting controls whether or not
  the daemon should try to figure out the "fully qualified domain name", FQDN.
 -This is done using a lookup of the name returned by C<gethostname>.
 -
 -Using this feature (i.E<nbsp>e. setting this option to B<true>) is recommended.
 -However, to preserve backwards compatibility the default is set to B<false>.
 -The sample config file that is installed with C<makeE<nbsp>install> includes a
 -line which sets this option, though, so that default installations will have
 -this setting enabled.
 +This is done using a lookup of the name returned by C<gethostname>. This option
 +is enabled by default.
  
  =item B<PreCacheChain> I<ChainName>
  
@@@ -189,143 -200,6 +199,143 @@@ A list of all plugins and a short summa
  F<README> file shipped with the sourcecode and hopefully binary packets as
  well.
  
 +=head2 Plugin C<amqp>
 +
 +The I<AMQMP plugin> can be used to communicate with other instances of
 +I<collectd> or third party applications using an AMQP message broker. Values
 +are sent to or received from the broker, which handles routing, queueing and
 +possibly filtering or messages.
 +
 + <Plugin "amqp">
 +   # Send values to an AMQP broker
 +   <Publish "some_name">
 +     Host "localhost"
 +     Port "5672"
 +     VHost "/"
 +     User "guest"
 +     Password "guest"
 +     Exchange "amq.fanout"
 + #   ExchangeType "fanout"
 + #   RoutingKey "collectd"
 + #   Persistent false
 + #   Format "command"
 + #   StoreRates false
 +   </Publish>
 +   
 +   # Receive values from an AMQP broker
 +   <Subscribe "some_name">
 +     Host "localhost"
 +     Port "5672"
 +     VHost "/"
 +     User "guest"
 +     Password "guest"
 +     Exchange "amq.fanout"
 + #   ExchangeType "fanout"
 + #   Queue "queue_name"
 + #   RoutingKey "collectd.#"
 +   </Subscribe>
 + </Plugin>
 +
 +The plugin's configuration consists of a number of I<Publish> and I<Subscribe>
 +blocks, which configure sending and receiving of values respectively. The two
 +blocks are very similar, so unless otherwise noted, an option can be used in
 +either block. The name given in the blocks starting tag is only used for
 +reporting messages, but may be used to support I<flushing> of certain
 +I<Publish> blocks in the future.
 +
 +=over 4
 +
 +=item B<Host> I<Host>
 +
 +Hostname or IP-address of the AMQP broker. Defaults to the default behavior of
 +the underlying communications library, I<rabbitmq-c>, which is "localhost".
 +
 +=item B<Port> I<Port>
 +
 +Service name or port number on which the AMQP broker accepts connections. This
 +argument must be a string, even if the numeric form is used. Defaults to
 +"5672".
 +
 +=item B<VHost> I<VHost>
 +
 +Name of the I<virtual host> on the AMQP broker to use. Defaults to "/".
 +
 +=item B<User> I<User>
 +
 +=item B<Password> I<Password>
 +
 +Credentials used to authenticate to the AMQP broker. By default "guest"/"guest"
 +is used.
 +
 +=item B<Exchange> I<Exchange>
 +
 +In I<Publish> blocks, this option specifies the I<exchange> to send values to.
 +By default, "amq.fanout" will be used.
 +
 +In I<Subscribe> blocks this option is optional. If given, a I<binding> between
 +the given exchange and the I<queue> is created, using the I<routing key> if
 +configured. See the B<Queue> and B<RoutingKey> options below.
 +
 +=item B<ExchangeType> I<Type>
 +
 +If given, the plugin will try to create the configured I<exchange> with this
 +I<type> after connecting. When in a I<Subscribe> block, the I<queue> will then
 +be bound to this exchange.
 +
 +=item B<Queue> I<Queue> (Subscribe only)
 +
 +Configures the I<queue> name to subscribe to. If no queue name was configures
 +explicitly, a unique queue name will be created by the broker.
 +
 +=item B<RoutingKey> I<Key>
 +
 +In I<Publish> blocks, this configures the routing key to set on all outgoing
 +messages. If not given, the routing key will be computed from the I<identifier>
 +of the value. The host, plugin, type and the two instances are concatenated
 +together using dots as the separator and all containing dots replaced with
 +slashes. For example "collectd.host/example/com.cpu.0.cpu.user". This makes it
 +possible to receive only specific values using a "topic" exchange.
 +
 +In I<Subscribe> blocks, configures the I<routing key> used when creating a
 +I<binding> between an I<exchange> and the I<queue>. The usual wildcards can be
 +used to filter messages when using a "topic" exchange. If you're only
 +interested in CPU statistics, you could use the routing key "collectd.*.cpu.#"
 +for example.
 +
 +=item B<Persistent> B<true>|B<false> (Publish only)
 +
 +Selects the I<delivery method> to use. If set to B<true>, the I<persistent>
 +mode will be used, i.e. delivery is guaranteed. If set to B<false> (the
 +default), the I<transient> delivery mode will be used, i.e. messages may be
 +lost due to high load, overflowing queues or similar issues.
 +
 +=item B<Format> B<Command>|B<JSON> (Publish only)
 +
 +Selects the format in which messages are sent to the broker. If set to
 +B<Command> (the default), values are sent as C<PUTVAL> commands which are
 +identical to the syntax used by the I<Exec> and I<UnixSock plugins>. In this
 +case, the C<Content-Type> header field will be set to C<text/collectd>.
 +
 +If set to B<JSON>, the values are encoded in the I<JavaScript Object Notation>,
 +an easy and straight forward exchange format. The C<Content-Type> header field
 +will be set to C<application/json>.
 +
 +A subscribing client I<should> use the C<Content-Type> header field to
 +determine how to decode the values. Currently, the I<AMQP plugin> itself can
 +only decode the B<Command> format.
 +
 +=item B<StoreRates> B<true>|B<false> (Publish only)
 +
 +Determines whether or not C<COUNTER>, C<DERIVE> and C<ABSOLUTE> data sources
 +are converted to a I<rate> (i.e. a C<GAUGE> value). If set to B<false> (the
 +default), no conversion is performed. Otherwise the conversion is performed
 +using the internal value cache.
 +
 +Please note that currently this option is only used if the B<Format> option has
 +been set to B<JSON>.
 +
 +=back
 +
  =head2 Plugin C<apache>
  
  To configure the C<apache>-plugin you first need to configure the Apache
@@@ -344,25 -218,7 +354,25 @@@ Since its C<mod_status> module is very 
  also supported. It introduces a new field, called C<BusyServers>, to count the
  number of currently connected clients. This field is also supported.
  
 -The following options are accepted by the C<apache>-plugin:
 +The configuration of the I<Apache> plugin consists of one or more
 +C<E<lt>InstanceE<nbsp>/E<gt>> blocks. Each block requires one string argument
 +as the instance name. For example:
 +
 + <Plugin "apache">
 +   <Instance "www1">
 +     URL "http://www1.example.com/mod_status?auto"
 +   </Instance>
 +   <Instance "www2">
 +     URL "http://www2.example.com/mod_status?auto"
 +   </Instance>
 + </Plugin>
 +
 +The instance name will be used as the I<plugin instance>. To emulate the old
 +(versionE<nbsp>4) behavior, you can use an empty string (""). In order for the
 +plugin to work correctly, each instance name must be unique. This is not
 +enforced by the plugin and it is your responsibility to ensure it.
 +
 +The following options are accepted within each I<Instance> block:
  
  =over 4
  
  
  Sets the URL of the C<mod_status> output. This needs to be the output generated
  by C<ExtendedStatus on> and it needs to be the machine readable output
 -generated by appending the C<?auto> argument.
 +generated by appending the C<?auto> argument. This option is I<mandatory>.
  
  =item B<User> I<Username>
  
@@@ -739,6 -595,22 +749,6 @@@ runtime statistics module of CouchD
      </URL>
    </Plugin>
  
 -Another CouchDB example:
 -The following example will collect the status values from each database:
 -
 -  <URL "http://localhost:5984/_all_dbs">
 -    Instance "dbs"
 -    <Key "*/doc_count">
 -      Type "gauge"
 -    </Key>
 -    <Key "*/doc_del_count">
 -      Type "counter"
 -    </Key>
 -    <Key "*/disk_size">
 -      Type "bytes"
 -    </Key>
 -  </URL>
 -
  In the B<Plugin> block, there may be one or more B<URL> blocks, each defining
  a URL to be fetched via HTTP (using libcurl) and one or more B<Key> blocks.
  The B<Key> string argument must be in a path format, which is used to collect a
@@@ -1168,6 -1040,22 +1178,6 @@@ Report using the device name rather tha
  (the default), it will report a disk as "root", but with it I<true>, it will be
  "sda1" (or whichever).
  
 -=item B<ReportReserved> B<true>|B<false>
 -
 -When enabled, the blocks reserved for root are reported separately. When
 -disabled (the default for backwards compatibility reasons) the reserved space
 -will be included in the "free" space.
 -
 -When disabled, the "df" type will be used to store "free" and "used" space. The
 -mount point or disk name (see option B<ReportByDevice>) is used as type
 -instance in this case (again: backwards compatibility).
 -
 -When enabled, the type "df_complex" is used and three files are created. The
 -mount point or disk name is used as plugin instance and the type instance is
 -set to "free", "reserved" and "used" as appropriate.
 -
 -Enabling this option is recommended.
 -
  =item B<ReportInodes> B<true>|B<false>
  
  Enables or disables reporting of free, reserved and used inodes. Defaults to
@@@ -1487,6 -1375,13 +1497,6 @@@ Hostname to connect to. Defaults to B<1
  
  TCP-Port to connect to. Defaults to B<7634>.
  
 -=item B<TranslateDevicename> I<true>|I<false>
 -
 -If enabled, translate the disk names to major/minor device numbers
 -(e.E<nbsp>g. "8-0" for /dev/sda). For backwards compatibility this defaults to
 -I<true> but it's recommended to disable it as it will probably be removed in
 -the next major version.
 -
  =back
  
  =head2 Plugin C<interface>
@@@ -1714,16 -1609,6 +1724,16 @@@ You can also specify combinations of th
  means to concatenate the guest name and UUID (with a literal colon character
  between, thus I<"foo:1234-1234-1234-1234">).
  
 +=item B<InterfaceFormat> B<name>|B<address>
 +
 +When the libvirt plugin logs interface data, it sets the name of the collected
 +data according to this setting. The default is to use the path as provided by
 +the hypervisor (the "dev" property of the target node), which is equal to
 +setting B<name>.
 +
 +B<address> means use the interface's mac address. This is useful since the
 +interface path might change between reboots of a guest or across migrations.
 +
  =back
  
  =head2 Plugin C<logfile>
@@@ -1742,8 -1627,8 +1752,8 @@@ debugging support
  
  Sets the file to write log messages to. The special strings B<stdout> and
  B<stderr> can be used to write to the standard output and standard error
 -channels, respectively. This, of course, only makes much sense when collectd is
 -running in foreground- or non-daemon-mode.
 +channels, respectively. This, of course, only makes much sense when I<collectd>
 +is running in foreground- or non-daemon-mode.
  
  =item B<Timestamp> B<true>|B<false>
  
@@@ -1760,33 -1645,6 +1770,33 @@@ B<Note>: There is no need to notify th
  log file (e.E<nbsp>g. when rotating the logs). The plugin reopens the file
  for each line it writes.
  
 +=head2 Plugin C<lpar>
 +
 +The I<LPAR plugin> reads CPU statistics of I<Logical Partitions>, a
 +virtualization technique for IBM POWER processors. It takes into account CPU
 +time stolen from or donated to a partition, in addition to the usual user,
 +system, I/O statistics.
 +
 +The following configuration options are available:
 +
 +=over 4
 +
 +=item B<CpuPoolStats> B<false>|B<true>
 +
 +When enabled, statistics about the processor pool are read, too. The partition
 +needs to have pool authority in order to be able to acquire this information.
 +Defaults to false.
 +
 +=item B<ReportBySerial> B<false>|B<true>
 +
 +If enabled, the serial of the physical machine the partition is currently
 +running on is reported as I<hostname> and the logical hostname of the machine
 +is reported in the I<plugin instance>. Otherwise, the logical hostname will be
 +used (just like other plugins) and the I<plugin instance> will be empty.
 +Defaults to false.
 +
 +=back
 +
  =head2 Plugin C<mbmon>
  
  The C<mbmon plugin> uses mbmon to retrieve temperature, voltage, etc.
@@@ -2012,7 -1870,7 +2022,7 @@@ B<Collect> option is mandatory
  The C<mysql plugin> requires B<mysqlclient> to be installed. It connects to
  one or more databases when started and keeps the connection up as long as
  possible. When the connection is interrupted for whatever reason it will try
 -to re-connect. The plugin will complaint loudly in case anything goes wrong.
 +to re-connect. The plugin will complain loudly in case anything goes wrong.
  
  This plugin issues the MySQL C<SHOW STATUS> / C<SHOW GLOBAL STATUS> command
  and collects information about MySQL network traffic, executed statements,
@@@ -2794,18 -2652,7 +2804,18 @@@ operating systems
  =item B<MaxPacketSize> I<1024-65535>
  
  Set the maximum size for datagrams received over the network. Packets larger
 -than this will be truncated.
 +than this will be truncated. Defaults to 1452E<nbsp>bytes, which is the maximum
 +payload size that can be transmitted in one Ethernet frame using IPv6E<nbsp>/
 +UDP.
 +
 +On the server side, this limit should be set to the largest value used on
 +I<any> client. Likewise, the value on the client must not be larger than the
 +value on the server, or data will be lost.
 +
 +B<Compatibility:> Versions prior to I<versionE<nbsp>4.8> used a fixed sized
 +buffer of 1024E<nbsp>bytes. Versions I<4.8>, I<4.9> and I<4.10> used a default
 +value of 1024E<nbsp>bytes to avoid problems when sending data to an older
 +server.
  
  =item B<Forward> I<true|false>
  
@@@ -2816,6 -2663,16 +2826,6 @@@ the same multicast group. While this re
  necessary it's not a huge problem since the plugin has a duplicate detection,
  so the values will not loop.
  
 -=item B<CacheFlush> I<Seconds>
 -
 -For each host/plugin/type combination the C<network plugin> caches the time of
 -the last value being sent or received. Every I<Seconds> seconds the plugin
 -searches and removes all entries that are older than I<Seconds> seconds, thus
 -freeing the unused memory again. Since this process is somewhat expensive and
 -normally doesn't do much, this value should not be too small. The default is
 -1800 seconds, but setting this to 86400 seconds (one day) will not do much harm
 -either.
 -
  =item B<ReportStats> B<true>|B<false>
  
  The network plugin cannot only receive and send statistics, it can also create
@@@ -3450,6 -3307,11 +3460,6 @@@ allowed as long as a single non-empty c
  
  The returned lines will be handled separately one after another.
  
 -=item B<Query> I<sql query statement>
 -
 -This is a deprecated synonym for B<Statement>. It will be removed in version 5
 -of collectd.
 -
  =item B<Param> I<hostname>|I<database>|I<username>|I<interval>
  
  Specify the parameters which should be passed to the SQL query. The parameters
@@@ -3525,6 -3387,21 +3535,6 @@@ This option is required inside a B<Resu
  times. If multiple B<ValuesFrom> options are specified, the columns are read
  in the given order.
  
 -=item B<Column> I<type> [I<type instance>]
 -
 -This is a deprecated alternative to a B<Result> block. It will be removed in
 -version 5 of collectd. It is equivalent to the following B<Result> block:
 -
 -  <Result>
 -    Type I<type>
 -    InstancePrefix I<type instance>
 -    ValuesFrom I<name of the x. column>
 -  </Result>
 -
 -The order of the B<Column> options defines which columns of the query result
 -should be used. The first option specifies the data found in the first column,
 -the second option that of the second column, and so on.
 -
  =item B<MinVersion> I<version>
  
  =item B<MaxVersion> I<version>
@@@ -3539,6 -3416,13 +3549,6 @@@ The I<version> has to be specified as t
  and patch-level versions, each represented as two-decimal-digit numbers. For
  example, version 8.2.3 will become 80203.
  
 -=item B<MinPGVersion> I<version>
 -
 -=item B<MaxPGVersion> I<version>
 -
 -These are deprecated synonyms for B<MinVersion> and B<MaxVersion>
 -respectively. They will be removed in version 5 of collectd.
 -
  =back
  
  The following predefined queries are available (the definitions can be found
@@@ -3949,52 -3833,6 +3959,52 @@@ Defaults to B<false>
  
  =back
  
 +=head2 Plugin C<redis>
 +
 +The I<Redis plugin> connects to one or more Redis servers and gathers
 +information about each server's state. For each server there is a I<Node> block
 +which configures the connection parameters for this node.
 +
 +  <Plugin redis>
 +    <Node "example">
 +        Host "localhost"
 +        Port "6379"
 +        Timeout 2000
 +    </Node>
 +  </Plugin>
 +
 +The information shown in the synopsis above is the I<default configuration>
 +which is used by the plugin if no configuration is present.
 +
 +=over 4
 +
 +=item B<Node> I<Nodename>
 +
 +The B<Node> block identifies a new Redis node, that is a new Redis instance
 +running in an specified host and port. The name for node is a canonical
 +identifier which is used as I<plugin instance>. It is limited to
 +64E<nbsp>characters in length.
 +
 +=item B<Host> I<Hostname>
 +
 +The B<Host> option is the hostname or IP-address where the Redis instance is
 +running on.
 +
 +=item B<Port> I<Port>
 +
 +The B<Port> option is the TCP port on which the Redis instance accepts
 +connections. Either a service name of a port number may be given. Please note
 +that numerical port numbers must be given as a string, too.
 +
 +=item B<Timeout> I<Timeout in miliseconds>
 +
 +The B<Timeout> option set the socket timeout for node response. Since the Redis
 +read function is blocking, you should keep this value as low as possible. Keep
 +in mind that the sum of all B<Timeout> values for all B<Nodes> should be lower
 +than B<Interval> defined globally.
 +
 +=back
 +
  =head2 Plugin C<rrdcached>
  
  The C<rrdcached> plugin uses the RRDtool accelerator daemon, L<rrdcached(1)>,
@@@ -4158,7 -3996,7 +4168,7 @@@ because all values were added to the in
  
  =head2 Plugin C<sensors>
  
 -The C<sensors plugin> uses B<lm_sensors> to retrieve sensor-values. This means
 +The I<Sensors plugin> uses B<lm_sensors> to retrieve sensor-values. This means
  that all the needed modules have to be loaded and lm_sensors has to be
  configured (most likely by editing F</etc/sensors.conf>. Read
  L<sensors.conf(5)> for details.
@@@ -4193,25 -4031,6 +4203,25 @@@ Since the configuration of the C<snmp p
  other plugins, its documentation has been moved to an own manpage,
  L<collectd-snmp(5)>. Please see there for details.
  
 +=head2 Plugin C<swap>
 +
 +The I<Swap plugin> collects information about used and available swap space. On
 +I<Solaris>, the following options are available:
 +
 +=over 4
 +
 +=item B<ReportByDevice> B<false>|B<true>
 +
 +Configures how to report physical swap devices. If set to B<false> is used (the
 +default), the summary over all swap devices is reported only, i.e. the globally
 +used and available space over all devices. If B<true> is configured, the used
 +and available space of each device will be reported separately.
 +
 +This option is only available if the I<Swap plugin> can use the L<swapctl(2)>
 +mechanism under I<Solaris>.
 +
 +=back
 +
  =head2 Plugin C<syslog>
  
  =over 4
@@@ -4561,7 -4380,7 +4571,7 @@@ port in numeric form
  
  =item B<ForceUseProcfs> I<true>|I<false>
  
 -By default, the C<thermal> plugin tries to read the statistics from the Linux
 +By default, the I<Thermal plugin> tries to read the statistics from the Linux
  C<sysfs> interface. If that is not available, the plugin falls back to the
  C<procfs> interface. By setting this option to I<true>, you can force the
  plugin to use the latter. This option defaults to I<false>.
@@@ -4581,18 -4400,9 +4591,18 @@@ selection is configured at all, B<all> 
  
  =back
  
 +=head2 Plugin C<threshold>
 +
 +The I<Threshold plugin> checks values collected or received by I<collectd>
 +against a configurable I<threshold> and issues I<notifications> if values are
 +out of bounds.
 +
 +Documentation for this plugin is available in the L<collectd-threshold(5)>
 +manual page.
 +
  =head2 Plugin C<tokyotyrant>
  
 -The C<tokyotyrant plugin> connects to a TokyoTyrant server and collects a
 +The I<TokyoTyrant plugin> connects to a TokyoTyrant server and collects a
  couple metrics: number of records, and database size on disk.
  
  =over 4
@@@ -4629,13 -4439,6 +4639,13 @@@ Change the file permissions of the UNIX
  permissions must be given as a numeric, octal value as you would pass to
  L<chmod(1)>. Defaults to B<0770>.
  
 +=item B<DeleteSocket> B<false>|B<true>
 +
 +If set to B<true>, delete the socket file before calling L<bind(2)>, if a file
 +with the given name already exists. If I<collectd> crashes a socket file may be
 +left over, preventing the daemon from opening a new socket when restarted.
 +Since this is potentially dangerous, this defaults to B<false>.
 +
  =back
  
  =head2 Plugin C<uuid>
@@@ -4679,68 -4482,6 +4689,68 @@@ Take the UUID from the given file (defa
  
  =back
  
 +=head2 Plugin C<varnish>
 +
 +The Varnish plugin collects information about Varnish, an HTTP accelerator.
 +
 +=over 4
 +
 +=item B<CollectCache> B<true>|B<false>
 +
 +Cache hits and misses. True by default.
 +
 +=item B<CollectConnections> B<true>|B<false>
 +
 +Number of client connections received, accepted and dropped. True by default.
 +
 +=item B<CollectBackend> B<true>|B<false>
 +
 +Back-end connection statistics, such as successful, reused,
 +and closed connections. True by default.
 +
 +=item B<CollectSHM> B<true>|B<false>
 +
 +Statistics about the shared memory log, a memory region to store
 +log messages which is flushed to disk when full. True by default.
 +
 +=item B<CollectESI> B<true>|B<false>
 +
 +Edge Side Includes (ESI) parse statistics. False by default.
 +
 +=item B<CollectFetch> B<true>|B<false>
 +
 +Statistics about fetches (HTTP requests sent to the backend). False by default.
 +
 +=item B<CollectHCB> B<true>|B<false>
 +
 +Inserts and look-ups in the crit bit tree based hash. Look-ups are
 +divided into locked and unlocked look-ups. False by default.
 +
 +=item B<CollectSMA> B<true>|B<false>
 +
 +malloc or umem (umem_alloc(3MALLOC) based) storage statistics.
 +The umem storage component is Solaris specific. False by default.
 +
 +=item B<CollectSMS> B<true>|B<false>
 +
 +synth (synthetic content) storage statistics. This storage
 +component is used internally only. False by default.
 +
 +=item B<CollectSM> B<true>|B<false>
 +
 +file (memory mapped file) storage statistics. False by default.
 +
 +=item B<CollectTotals> B<true>|B<false>
 +
 +Collects overview counters, such as the number of sessions created,
 +the number of requests and bytes transferred. False by default.
 +
 +=item B<CollectWorkers> B<true>|B<false>
 +
 +Collect statistics about worker threads. False by default.
 +
 +=back
 +
  =head2 Plugin C<vmem>
  
  The C<vmem> plugin collects information about the usage of virtual memory.
diff --combined src/common.c
@@@ -1,6 -1,6 +1,6 @@@
  /**
   * collectd - src/common.c
 - * Copyright (C) 2005-2009  Florian octo Forster
 + * Copyright (C) 2005-2010  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>
   *   Niki W. Waibel <niki.waibel@gmx.net>
   *   Sebastian Harl <sh at tokkee.org>
   *   MichaÅ‚ MirosÅ‚aw <mirq-linux at rere.qmqm.pl>
@@@ -29,7 -29,6 +29,7 @@@
  #include "collectd.h"
  #include "common.h"
  #include "plugin.h"
 +#include "utils_cache.h"
  
  #if HAVE_PTHREAD_H
  # include <pthread.h>
  # include <math.h>
  #endif
  
 -/* for ntohl and htonl */
 -#if HAVE_ARPA_INET_H
 -# include <arpa/inet.h>
 -#endif
 -
  /* for getaddrinfo */
  #include <sys/types.h>
  #include <sys/socket.h>
  # include <netinet/in.h>
  #endif
  
 +/* for ntohl and htonl */
 +#if HAVE_ARPA_INET_H
 +# include <arpa/inet.h>
 +#endif
 +
  #ifdef HAVE_LIBKSTAT
  extern kstat_ctl_t *kc;
  #endif
@@@ -548,7 -547,7 +548,7 @@@ int check_create_dir (const char *file_
                        {
                                if (errno == ENOENT)
                                {
-                                       if (mkdir (dir, 0755) == 0)
+                                       if (mkdir (dir, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
                                                break;
  
                                        /* this might happen, if a different thread created
@@@ -804,75 -803,6 +804,75 @@@ int format_name (char *ret, int ret_len
        return (0);
  } /* int format_name */
  
 +int format_values (char *ret, size_t ret_len, /* {{{ */
 +              const data_set_t *ds, const value_list_t *vl,
 +              _Bool store_rates)
 +{
 +        size_t offset = 0;
 +        int status;
 +        int i;
 +        gauge_t *rates = NULL;
 +
 +        assert (0 == strcmp (ds->type, vl->type));
 +
 +        memset (ret, 0, ret_len);
 +
 +#define BUFFER_ADD(...) do { \
 +        status = ssnprintf (ret + offset, ret_len - offset, \
 +                        __VA_ARGS__); \
 +        if (status < 1) \
 +        { \
 +                sfree (rates); \
 +                return (-1); \
 +        } \
 +        else if (((size_t) status) >= (ret_len - offset)) \
 +        { \
 +                sfree (rates); \
 +                return (-1); \
 +        } \
 +        else \
 +                offset += ((size_t) status); \
 +} while (0)
 +
 +        BUFFER_ADD ("%.3f", CDTIME_T_TO_DOUBLE (vl->time));
 +
 +        for (i = 0; i < ds->ds_num; i++)
 +        {
 +                if (ds->ds[i].type == DS_TYPE_GAUGE)
 +                        BUFFER_ADD (":%f", vl->values[i].gauge);
 +                else if (store_rates)
 +                {
 +                        if (rates == NULL)
 +                                rates = uc_get_rate (ds, vl);
 +                        if (rates == NULL)
 +                        {
 +                                WARNING ("format_values: "
 +                                              "uc_get_rate failed.");
 +                                return (-1);
 +                        }
 +                        BUFFER_ADD (":%g", rates[i]);
 +                }
 +                else if (ds->ds[i].type == DS_TYPE_COUNTER)
 +                        BUFFER_ADD (":%llu", vl->values[i].counter);
 +                else if (ds->ds[i].type == DS_TYPE_DERIVE)
 +                        BUFFER_ADD (":%"PRIi64, vl->values[i].derive);
 +                else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
 +                        BUFFER_ADD (":%"PRIu64, vl->values[i].absolute);
 +                else
 +                {
 +                        ERROR ("format_values plugin: Unknown data source type: %i",
 +                                        ds->ds[i].type);
 +                        sfree (rates);
 +                        return (-1);
 +                }
 +        } /* for ds->ds_num */
 +
 +#undef BUFFER_ADD
 +
 +        sfree (rates);
 +        return (0);
 +} /* }}} int format_values */
 +
  int parse_identifier (char *str, char **ret_host,
                char **ret_plugin, char **ret_plugin_instance,
                char **ret_type, char **ret_type_instance)
        return (0);
  } /* int parse_identifier */
  
 +int parse_identifier_vl (const char *str, value_list_t *vl) /* {{{ */
 +{
 +      char str_copy[6 * DATA_MAX_NAME_LEN];
 +      char *host = NULL;
 +      char *plugin = NULL;
 +      char *plugin_instance = NULL;
 +      char *type = NULL;
 +      char *type_instance = NULL;
 +      int status;
 +
 +      if ((str == NULL) || (vl == NULL))
 +              return (EINVAL);
 +
 +      sstrncpy (str_copy, str, sizeof (str_copy));
 +
 +      status = parse_identifier (str_copy, &host,
 +                      &plugin, &plugin_instance,
 +                      &type, &type_instance);
 +      if (status != 0)
 +              return (status);
 +
 +      sstrncpy (vl->host, host, sizeof (vl->host));
 +      sstrncpy (vl->plugin, plugin, sizeof (vl->plugin));
 +      sstrncpy (vl->plugin_instance,
 +                      (plugin_instance != NULL) ? plugin_instance : "",
 +                      sizeof (vl->plugin_instance));
 +      sstrncpy (vl->type, type, sizeof (vl->type));
 +      sstrncpy (vl->type_instance,
 +                      (type_instance != NULL) ? type_instance : "",
 +                      sizeof (vl->type_instance));
 +
 +      return (0);
 +} /* }}} int parse_identifier_vl */
 +
  int parse_value (const char *value_orig, value_t *ret_value, int ds_type)
  {
    char *value;
@@@ -1036,22 -932,9 +1036,22 @@@ int parse_values (char *buffer, value_l
                if (i == -1)
                {
                        if (strcmp ("N", ptr) == 0)
 -                              vl->time = time (NULL);
 +                              vl->time = cdtime ();
                        else
 -                              vl->time = (time_t) atoi (ptr);
 +                      {
 +                              char *endptr = NULL;
 +                              double tmp;
 +
 +                              errno = 0;
 +                              tmp = strtod (ptr, &endptr);
 +                              if ((errno != 0)                    /* Overflow */
 +                                              || (endptr == ptr)  /* Invalid string */
 +                                              || (endptr == NULL) /* This should not happen */
 +                                              || (*endptr != 0))  /* Trailing chars */
 +                                      return (-1);
 +
 +                              vl->time = DOUBLE_TO_CDTIME_T (tmp);
 +                      }
                }
                else
                {
diff --combined src/df.c
+++ b/src/df.c
@@@ -62,8 -62,9 +62,8 @@@ static ignorelist_t *il_device = NULL
  static ignorelist_t *il_mountpoint = NULL;
  static ignorelist_t *il_fstype = NULL;
  
 -static _Bool by_device = false;
 -static _Bool report_reserved = false;
 -static _Bool report_inodes = false;
 +static _Bool by_device = 0;
 +static _Bool report_inodes = 0;
  
  static int df_init (void)
  {
@@@ -118,16 -119,25 +118,16 @@@ static int df_config (const char *key, 
        else if (strcasecmp (key, "ReportByDevice") == 0)
        {
                if (IS_TRUE (value))
 -                      by_device = true;
 -
 -              return (0);
 -      }
 -      else if (strcasecmp (key, "ReportReserved") == 0)
 -      {
 -              if (IS_TRUE (value))
 -                      report_reserved = true;
 -              else
 -                      report_reserved = false;
 +                      by_device = 1;
  
                return (0);
        }
        else if (strcasecmp (key, "ReportInodes") == 0)
        {
                if (IS_TRUE (value))
 -                      report_inodes = true;
 +                      report_inodes = 1;
                else
 -                      report_inodes = false;
 +                      report_inodes = 0;
  
                return (0);
        }
        return (-1);
  }
  
 -static void df_submit_two (char *df_name,
 -              const char *type,
 -              gauge_t df_used,
 -              gauge_t df_free)
 -{
 -      value_t values[2];
 -      value_list_t vl = VALUE_LIST_INIT;
 -
 -      values[0].gauge = df_used;
 -      values[1].gauge = df_free;
 -
 -      vl.values = values;
 -      vl.values_len = 2;
 -      sstrncpy (vl.host, hostname_g, sizeof (vl.host));
 -      sstrncpy (vl.plugin, "df", sizeof (vl.plugin));
 -      sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
 -      sstrncpy (vl.type, type, sizeof (vl.type));
 -      sstrncpy (vl.type_instance, df_name, sizeof (vl.type_instance));
 -
 -      plugin_dispatch_values (&vl);
 -} /* void df_submit_two */
 -
  __attribute__ ((nonnull(2)))
  static void df_submit_one (char *plugin_instance,
                const char *type, const char *type_instance,
@@@ -183,9 -215,6 +183,9 @@@ static int df_read (void
        {
                unsigned long long blocksize;
                char disk_name[256];
 +              uint64_t blk_free;
 +              uint64_t blk_reserved;
 +              uint64_t blk_used;
  
                if (ignorelist_match (il_device,
                                        (mnt_ptr->spec_device != NULL)
                {
                        if (strcmp (mnt_ptr->dir, "/") == 0)
                        {
+                               if (strcmp (mnt_ptr->type, "rootfs") == 0)
+                                       continue;
                                sstrncpy (disk_name, "root", sizeof (disk_name));
                        }
                        else
  
                blocksize = BLOCKSIZE(statbuf);
  
 -              if (report_reserved)
 -              {
 -                      uint64_t blk_free;
 -                      uint64_t blk_reserved;
 -                      uint64_t blk_used;
 -
 -                      /*
 -                       * Sanity-check for the values in the struct
 -                       */
 -                      /* Check for negative "available" byes. For example UFS can
 -                       * report negative free space for user. Notice. blk_reserved
 -                       * will start to diminish after this. */
 +              /*
 +               * Sanity-check for the values in the struct
 +               */
 +              /* Check for negative "available" byes. For example UFS can
 +               * report negative free space for user. Notice. blk_reserved
 +               * will start to diminish after this. */
  #if HAVE_STATVFS
 -                      /* Cast and temporary variable are needed to avoid
 -                       * compiler warnings.
 -                       * ((struct statvfs).f_bavail is unsigned (POSIX)) */
 -                      int64_t signed_bavail = (int64_t) statbuf.f_bavail;
 -                      if (signed_bavail < 0)
 -                              statbuf.f_bavail = 0;
 +              /* Cast and temporary variable are needed to avoid
 +               * compiler warnings.
 +               * ((struct statvfs).f_bavail is unsigned (POSIX)) */
 +              int64_t signed_bavail = (int64_t) statbuf.f_bavail;
 +              if (signed_bavail < 0)
 +                      statbuf.f_bavail = 0;
  #elif HAVE_STATFS
 -                      if (statbuf.f_bavail < 0)
 -                              statbuf.f_bavail = 0;
 +              if (statbuf.f_bavail < 0)
 +                      statbuf.f_bavail = 0;
  #endif
 -                      /* Make sure that f_blocks >= f_bfree >= f_bavail */
 -                      if (statbuf.f_bfree < statbuf.f_bavail)
 -                              statbuf.f_bfree = statbuf.f_bavail;
 -                      if (statbuf.f_blocks < statbuf.f_bfree)
 -                              statbuf.f_blocks = statbuf.f_bfree;
 -
 -                      blk_free = (uint64_t) statbuf.f_bavail;
 -                      blk_reserved = (uint64_t) (statbuf.f_bfree - statbuf.f_bavail);
 -                      blk_used = (uint64_t) (statbuf.f_blocks - statbuf.f_bfree);
 -                      
 -                      df_submit_one (disk_name, "df_complex", "free",
 -                                      (gauge_t) (blk_free * blocksize));
 -                      df_submit_one (disk_name, "df_complex", "reserved",
 -                                      (gauge_t) (blk_reserved * blocksize));
 -                      df_submit_one (disk_name, "df_complex", "used",
 -                                      (gauge_t) (blk_used * blocksize));
 -              }
 -              else /* compatibility code */
 -              {
 -                      gauge_t df_free;
 -                      gauge_t df_used;
 -
 -                      df_free = statbuf.f_bfree * blocksize;
 -                      df_used = (statbuf.f_blocks - statbuf.f_bfree) * blocksize;
 -
 -                      df_submit_two (disk_name, "df", df_used, df_free);
 -              }
 +              /* Make sure that f_blocks >= f_bfree >= f_bavail */
 +              if (statbuf.f_bfree < statbuf.f_bavail)
 +                      statbuf.f_bfree = statbuf.f_bavail;
 +              if (statbuf.f_blocks < statbuf.f_bfree)
 +                      statbuf.f_blocks = statbuf.f_bfree;
 +
 +              blk_free     = (uint64_t) statbuf.f_bavail;
 +              blk_reserved = (uint64_t) (statbuf.f_bfree - statbuf.f_bavail);
 +              blk_used     = (uint64_t) (statbuf.f_blocks - statbuf.f_bfree);
 +
 +              df_submit_one (disk_name, "df_complex", "free",
 +                              (gauge_t) (blk_free * blocksize));
 +              df_submit_one (disk_name, "df_complex", "reserved",
 +                              (gauge_t) (blk_reserved * blocksize));
 +              df_submit_one (disk_name, "df_complex", "used",
 +                              (gauge_t) (blk_used * blocksize));
  
                /* inode handling */
                if (report_inodes)
diff --combined src/memcachec.c
@@@ -328,7 -328,7 +328,7 @@@ static int cmc_config_add_page (oconfig
  
      if (strcasecmp ("Server", child->key) == 0)
        status = cmc_config_add_string ("Server", &page->server, child);
-     if (strcasecmp ("Key", child->key) == 0)
+     else if (strcasecmp ("Key", child->key) == 0)
        status = cmc_config_add_string ("Key", &page->key, child);
      else if (strcasecmp ("Match", child->key) == 0)
        /* Be liberal with failing matches => don't set `status'. */
@@@ -452,6 -452,7 +452,6 @@@ static void cmc_submit (const web_page_
  
    vl.values = values;
    vl.values_len = 1;
 -  vl.time = time (NULL);
    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
    sstrncpy (vl.plugin, "memcachec", sizeof (vl.plugin));
    sstrncpy (vl.plugin_instance, wp->instance, sizeof (vl.plugin_instance));
diff --combined src/netapp.c
@@@ -1,6 -1,6 +1,6 @@@
  /**
   * collectd - src/netapp.c
-  * Copyright (C) 2009  Sven Trenkel
+  * Copyright (C) 2009,2010  Sven Trenkel
   *
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"),
@@@ -38,8 -38,8 +38,8 @@@ typedef void service_handler_t(host_con
  
  struct cna_interval_s
  {
 -      time_t interval;
 -      time_t last_read;
 +      cdtime_t interval;
 +      cdtime_t last_read;
  };
  typedef struct cna_interval_s cna_interval_t;
  
@@@ -79,7 -79,7 +79,7 @@@ typedef struct 
        cna_interval_t interval;
        na_elem_t *query;
  
 -      time_t timestamp;
 +      cdtime_t timestamp;
        uint64_t name_cache_hit;
        uint64_t name_cache_miss;
        uint64_t find_dir_hit;
  typedef struct disk_s {
        char *name;
        uint32_t flags;
 -      time_t timestamp;
 +      cdtime_t timestamp;
        uint64_t disk_busy;
        uint64_t base_for_disk_busy;
        double disk_busy_percent;
@@@ -153,7 -153,7 +153,7 @@@ typedef struct data_volume_perf_s data_
  struct data_volume_perf_s {
        char *name;
        uint32_t flags;
 -      time_t timestamp;
 +      cdtime_t timestamp;
  
        uint64_t read_bytes;
        uint64_t write_bytes;
@@@ -242,7 -242,7 +242,7 @@@ struct host_config_s 
        int port;
        char *username;
        char *password;
 -      int interval;
 +      cdtime_t interval;
  
        na_server_t *srv;
        cfg_wafl_t *cfg_wafl;
@@@ -566,7 -566,7 +566,7 @@@ static int submit_values (const char *h
                const char *plugin_inst,
                const char *type, const char *type_inst,
                value_t *values, int values_len,
 -              time_t timestamp, int interval)
 +              cdtime_t timestamp, cdtime_t interval)
  {
        value_list_t vl = VALUE_LIST_INIT;
  
        return (plugin_dispatch_values (&vl));
  } /* }}} int submit_uint64 */
  
 -static int submit_two_counters (const char *host, const char *plugin_inst, /* {{{ */
 -              const char *type, const char *type_inst, counter_t val0, counter_t val1,
 -              time_t timestamp, int interval)
 +static int submit_two_derive (const char *host, const char *plugin_inst, /* {{{ */
 +              const char *type, const char *type_inst, derive_t val0, derive_t val1,
 +              cdtime_t timestamp, cdtime_t interval)
  {
        value_t values[2];
  
 -      values[0].counter = val0;
 -      values[1].counter = val1;
 +      values[0].derive = val0;
 +      values[1].derive = val1;
  
        return (submit_values (host, plugin_inst, type, type_inst,
                                values, 2, timestamp, interval));
 -} /* }}} int submit_two_counters */
 +} /* }}} int submit_two_derive */
  
 -static int submit_counter (const char *host, const char *plugin_inst, /* {{{ */
 -              const char *type, const char *type_inst, counter_t counter, time_t timestamp, int interval)
 +static int submit_derive (const char *host, const char *plugin_inst, /* {{{ */
 +              const char *type, const char *type_inst, derive_t counter,
 +              cdtime_t timestamp, cdtime_t interval)
  {
        value_t v;
  
 -      v.counter = counter;
 +      v.derive = counter;
  
        return (submit_values (host, plugin_inst, type, type_inst,
                                &v, 1, timestamp, interval));
 -} /* }}} int submit_counter */
 +} /* }}} int submit_derive */
  
  static int submit_two_gauge (const char *host, const char *plugin_inst, /* {{{ */
                const char *type, const char *type_inst, gauge_t val0, gauge_t val1,
 -              time_t timestamp, int interval)
 +              cdtime_t timestamp, cdtime_t interval)
  {
        value_t values[2];
  
  } /* }}} int submit_two_gauge */
  
  static int submit_double (const char *host, const char *plugin_inst, /* {{{ */
 -              const char *type, const char *type_inst, double d, time_t timestamp, int interval)
 +              const char *type, const char *type_inst, double d,
 +              cdtime_t timestamp, cdtime_t interval)
  {
        value_t v;
  
@@@ -652,8 -650,8 +652,8 @@@ static int submit_cache_ratio (const ch
                uint64_t new_misses,
                uint64_t old_hits,
                uint64_t old_misses,
 -              time_t timestamp,
 -              int interval)
 +              cdtime_t timestamp,
 +              cdtime_t interval)
  {
        value_t v;
  
@@@ -744,16 -742,16 +744,16 @@@ static int submit_volume_perf_data (con
        if (HAS_ALL_FLAGS (old_data->flags, CFG_VOLUME_PERF_IO)
                        && HAS_ALL_FLAGS (new_data->flags, HAVE_VOLUME_PERF_BYTES_READ | HAVE_VOLUME_PERF_BYTES_WRITE))
        {
 -              submit_two_counters (hostname, plugin_instance, "disk_octets", /* type instance = */ NULL,
 -                              (counter_t) new_data->read_bytes, (counter_t) new_data->write_bytes, new_data->timestamp, interval);
 +              submit_two_derive (hostname, plugin_instance, "disk_octets", /* type instance = */ NULL,
 +                              (derive_t) new_data->read_bytes, (derive_t) new_data->write_bytes, new_data->timestamp, interval);
        }
  
        /* Check for and submit disk-operations values */
        if (HAS_ALL_FLAGS (old_data->flags, CFG_VOLUME_PERF_OPS)
                        && HAS_ALL_FLAGS (new_data->flags, HAVE_VOLUME_PERF_OPS_READ | HAVE_VOLUME_PERF_OPS_WRITE))
        {
 -              submit_two_counters (hostname, plugin_instance, "disk_ops", /* type instance = */ NULL,
 -                              (counter_t) new_data->read_ops, (counter_t) new_data->write_ops, new_data->timestamp, interval);
 +              submit_two_derive (hostname, plugin_instance, "disk_ops", /* type instance = */ NULL,
 +                              (derive_t) new_data->read_ops, (derive_t) new_data->write_ops, new_data->timestamp, interval);
        }
  
        /* Check for, calculate and submit disk-latency values */
        return (0);
  } /* }}} int submit_volume_perf_data */
  
 +static cdtime_t cna_child_get_cdtime (na_elem_t *data) /* {{{ */
 +{
 +      time_t t;
 +
 +      t = (time_t) na_child_get_uint64 (data, "timestamp", /* default = */ 0);
 +
 +      return (TIME_T_TO_CDTIME_T (t));
 +} /* }}} cdtime_t cna_child_get_cdtime */
 +
 +
  /* 
   * Query functions
   *
@@@ -847,7 -835,7 +847,7 @@@ static int cna_handle_wafl_data (const 
  
        memset (&perf_data, 0, sizeof (perf_data));
        
 -      perf_data.timestamp = (time_t) na_child_get_uint64 (data, "timestamp", 0);
 +      perf_data.timestamp = cna_child_get_cdtime (data);
  
        instances = na_elem_child(na_elem_child (data, "instances"), "instance-data");
        if (instances == NULL)
@@@ -962,7 -950,7 +962,7 @@@ static int cna_query_wafl (host_config_
  {
        na_elem_t *data;
        int status;
 -      time_t now;
 +      cdtime_t now;
  
        if (host == NULL)
                return (EINVAL);
        if (host->cfg_wafl == NULL)
                return (0);
  
 -      now = time (NULL);
 +      now = cdtime ();
        if ((host->cfg_wafl->interval.interval + host->cfg_wafl->interval.last_read) > now)
                return (0);
  
  
  /* Data corresponding to <Disks /> */
  static int cna_handle_disk_data (const char *hostname, /* {{{ */
 -              cfg_disk_t *cfg_disk, na_elem_t *data, int interval)
 +              cfg_disk_t *cfg_disk, na_elem_t *data, cdtime_t interval)
  {
 -      time_t timestamp;
 +      cdtime_t timestamp;
        na_elem_t *instances;
        na_elem_t *instance;
        na_elem_iter_t instance_iter;
        if ((cfg_disk == NULL) || (data == NULL))
                return (EINVAL);
        
 -      timestamp = (time_t) na_child_get_uint64(data, "timestamp", 0);
 +      timestamp = cna_child_get_cdtime (data);
  
        instances = na_elem_child (data, "instances");
        if (instances == NULL)
@@@ -1156,7 -1144,7 +1156,7 @@@ static int cna_query_disk (host_config_
  {
        na_elem_t *data;
        int status;
 -      time_t now;
 +      cdtime_t now;
  
        if (host == NULL)
                return (EINVAL);
        if (host->cfg_disk == NULL)
                return (0);
  
 -      now = time (NULL);
 +      now = cdtime ();
        if ((host->cfg_disk->interval.interval + host->cfg_disk->interval.last_read) > now)
                return (0);
  
  
  /* Data corresponding to <VolumePerf /> */
  static int cna_handle_volume_perf_data (const char *hostname, /* {{{ */
 -              cfg_volume_perf_t *cvp, na_elem_t *data, int interval)
 +              cfg_volume_perf_t *cvp, na_elem_t *data, cdtime_t interval)
  {
 -      time_t timestamp;
 +      cdtime_t timestamp;
        na_elem_t *elem_instances;
        na_elem_iter_t iter_instances;
        na_elem_t *elem_instance;
        
 -      timestamp = (time_t) na_child_get_uint64(data, "timestamp", 0);
 +      timestamp = cna_child_get_cdtime (data);
  
        elem_instances = na_elem_child(data, "instances");
        if (elem_instances == NULL)
@@@ -1327,7 -1315,7 +1327,7 @@@ static int cna_query_volume_perf (host_
  {
        na_elem_t *data;
        int status;
 -      time_t now;
 +      cdtime_t now;
  
        if (host == NULL)
                return (EINVAL);
        if (host->cfg_volume_perf == NULL)
                return (0);
  
 -      now = time (NULL);
 +      now = cdtime ();
        if ((host->cfg_volume_perf->interval.interval + host->cfg_volume_perf->interval.last_read) > now)
                return (0);
  
@@@ -1456,7 -1444,7 +1456,7 @@@ static int cna_change_volume_status (co
        notification_t n;
  
        memset (&n, 0, sizeof (&n));
 -      n.time = time (NULL);
 +      n.time = cdtime ();
        sstrncpy (n.host, hostname, sizeof (n.host));
        sstrncpy (n.plugin, "netapp", sizeof (n.plugin));
        sstrncpy (n.plugin_instance, v->name, sizeof (n.plugin_instance));
@@@ -1694,7 -1682,7 +1694,7 @@@ static int cna_query_volume_usage (host
  {
        na_elem_t *data;
        int status;
 -      time_t now;
 +      cdtime_t now;
  
        if (host == NULL)
                return (EINVAL);
        if (host->cfg_volume_usage == NULL)
                return (0);
  
 -      now = time (NULL);
 +      now = cdtime ();
        if ((host->cfg_volume_usage->interval.interval + host->cfg_volume_usage->interval.last_read) > now)
                return (0);
  
@@@ -1739,15 -1727,15 +1739,15 @@@ static int cna_handle_system_data (cons
        na_elem_t *counter;
        na_elem_iter_t counter_iter;
  
 -      counter_t disk_read = 0, disk_written = 0;
 -      counter_t net_recv = 0, net_sent = 0;
 -      counter_t cpu_busy = 0, cpu_total = 0;
 +      derive_t disk_read = 0, disk_written = 0;
 +      derive_t net_recv = 0, net_sent = 0;
 +      derive_t cpu_busy = 0, cpu_total = 0;
        uint32_t counter_flags = 0;
  
        const char *instance;
 -      time_t timestamp;
 +      cdtime_t timestamp;
        
 -      timestamp = (time_t) na_child_get_uint64 (data, "timestamp", 0);
 +      timestamp = cna_child_get_cdtime (data);
  
        instances = na_elem_child(na_elem_child (data, "instances"), "instance-data");
        if (instances == NULL)
                        continue;
  
                if (!strcmp(name, "disk_data_read")) {
 -                      disk_read = (counter_t) (value * 1024);
 +                      disk_read = (derive_t) (value * 1024);
                        counter_flags |= 0x01;
                } else if (!strcmp(name, "disk_data_written")) {
 -                      disk_written = (counter_t) (value * 1024);
 +                      disk_written = (derive_t) (value * 1024);
                        counter_flags |= 0x02;
                } else if (!strcmp(name, "net_data_recv")) {
 -                      net_recv = (counter_t) (value * 1024);
 +                      net_recv = (derive_t) (value * 1024);
                        counter_flags |= 0x04;
                } else if (!strcmp(name, "net_data_sent")) {
 -                      net_sent = (counter_t) (value * 1024);
 +                      net_sent = (derive_t) (value * 1024);
                        counter_flags |= 0x08;
                } else if (!strcmp(name, "cpu_busy")) {
 -                      cpu_busy = (counter_t) value;
 +                      cpu_busy = (derive_t) value;
                        counter_flags |= 0x10;
                } else if (!strcmp(name, "cpu_elapsed_time")) {
 -                      cpu_total = (counter_t) value;
 +                      cpu_total = (derive_t) value;
                        counter_flags |= 0x20;
                } else if ((cfg_system->flags & CFG_SYSTEM_OPS)
                                && (value > 0) && (strlen(name) > 4)
                                && (!strcmp(name + strlen(name) - 4, "_ops"))) {
 -                      submit_counter (hostname, instance, "disk_ops_complex", name,
 -                                      (counter_t) value, timestamp, interval);
 +                      submit_derive (hostname, instance, "disk_ops_complex", name,
 +                                      (derive_t) value, timestamp, interval);
                }
        } /* for (counter) */
  
        if ((cfg_system->flags & CFG_SYSTEM_DISK)
                        && (HAS_ALL_FLAGS (counter_flags, 0x01 | 0x02)))
 -              submit_two_counters (hostname, instance, "disk_octets", NULL,
 +              submit_two_derive (hostname, instance, "disk_octets", NULL,
                                disk_read, disk_written, timestamp, interval);
                                
        if ((cfg_system->flags & CFG_SYSTEM_NET)
                        && (HAS_ALL_FLAGS (counter_flags, 0x04 | 0x08)))
 -              submit_two_counters (hostname, instance, "if_octets", NULL,
 +              submit_two_derive (hostname, instance, "if_octets", NULL,
                                net_recv, net_sent, timestamp, interval);
  
        if ((cfg_system->flags & CFG_SYSTEM_CPU)
                        && (HAS_ALL_FLAGS (counter_flags, 0x10 | 0x20)))
        {
 -              submit_counter (hostname, instance, "cpu", "system",
 +              submit_derive (hostname, instance, "cpu", "system",
                                cpu_busy, timestamp, interval);
 -              submit_counter (hostname, instance, "cpu", "idle",
 +              submit_derive (hostname, instance, "cpu", "idle",
                                cpu_total - cpu_busy, timestamp, interval);
        }
  
@@@ -1854,7 -1842,7 +1854,7 @@@ static int cna_query_system (host_confi
  {
        na_elem_t *data;
        int status;
 -      time_t now;
 +      cdtime_t now;
  
        if (host == NULL)
                return (EINVAL);
        if (host->cfg_system == NULL)
                return (0);
  
 -      now = time (NULL);
 +      now = cdtime ();
        if ((host->cfg_system->interval.interval + host->cfg_system->interval.last_read) > now)
                return (0);
  
@@@ -1920,12 -1908,23 +1920,12 @@@ static int cna_config_bool_to_flag (con
  static int cna_config_get_interval (const oconfig_item_t *ci, /* {{{ */
                cna_interval_t *out_interval)
  {
 -      time_t tmp;
 -
 -      if ((ci == NULL) || (out_interval == NULL))
 -              return (EINVAL);
 -
 -      if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
 -      {
 -              WARNING ("netapp plugin: The `Interval' option needs exactly one numeric argument.");
 -              return (-1);
 -      }
 +      cdtime_t tmp = 0;
 +      int status;
  
 -      tmp = (time_t) (ci->values[0].value.number + .5);
 -      if (tmp < 1)
 -      {
 -              WARNING ("netapp plugin: The `Interval' option needs a positive integer argument.");
 -              return (-1);
 -      }
 +      status = cf_util_get_cdtime (ci, &tmp);
 +      if (status != 0)
 +              return (status);
  
        out_interval->interval = tmp;
        out_interval->last_read = 0;
@@@ -2425,7 -2424,11 +2425,7 @@@ static host_config_t *cna_config_host (
                } else if (!strcasecmp(item->key, "Password")) {
                        status = cf_util_get_string (item, &host->password);
                } else if (!strcasecmp(item->key, "Interval")) {
 -                      if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_NUMBER || item->values[0].value.number != (int) item->values[0].value.number || item->values[0].value.number < 2) {
 -                              WARNING("netapp plugin: \"Interval\" of host %s needs exactly one integer argument.", ci->values[0].value.string);
 -                              continue;
 -                      }
 -                      host->interval = item->values[0].value.number;
 +                      status = cf_util_get_cdtime (item, &host->interval);
                } else if (!strcasecmp(item->key, "WAFL")) {
                        cna_config_wafl(host, item);
                } else if (!strcasecmp(item->key, "Disks")) {
@@@ -2497,7 -2500,7 +2497,7 @@@ static int cna_init_host (host_config_
        na_server_adminuser(host->srv, host->username, host->password);
        na_server_set_timeout(host->srv, 5 /* seconds */);
  
-       return 0;
+       return (0);
  } /* }}} int cna_init_host */
  
  static int cna_init (void) /* {{{ */
        return (0);
  } /* }}} cna_init */
  
+ static int cna_read_internal (host_config_t *host) { /* {{{ */
+       int status;
+       status = cna_query_wafl (host);
+       if (status != 0)
+               return (status);
+       status = cna_query_disk (host);
+       if (status != 0)
+               return (status);
+       status = cna_query_volume_perf (host);
+       if (status != 0)
+               return (status);
+       status = cna_query_volume_usage (host);
+       if (status != 0)
+               return (status);
+       status = cna_query_system (host);
+       if (status != 0)
+               return (status);
+       return 0;
+ } /* }}} int cna_read_internal */
  static int cna_read (user_data_t *ud) { /* {{{ */
        host_config_t *host;
        int status;
        status = cna_init_host (host);
        if (status != 0)
                return (status);
-       
-       cna_query_wafl (host);
-       cna_query_disk (host);
-       cna_query_volume_perf (host);
-       cna_query_volume_usage (host);
-       cna_query_system (host);
+       status = cna_read_internal (host);
+       if (status != 0)
+       {
+               if (host->srv != NULL)
+                       na_server_close (host->srv);
+               host->srv = NULL;
+       }
  
        return 0;
  } /* }}} int cna_read */
@@@ -2556,7 -2587,8 +2584,7 @@@ static int cna_config (oconfig_item_t *
  
                        ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name);
  
 -                      memset (&interval, 0, sizeof (interval));
 -                      interval.tv_sec = host->interval;
 +                      CDTIME_T_TO_TIMESPEC (host->interval, &interval);
  
                        memset (&ud, 0, sizeof (ud));
                        ud.data = host;
diff --combined src/oracle.c
@@@ -86,6 -86,7 +86,7 @@@ OCIError *oci_error = NULL
   * Functions
   */
  static void o_report_error (const char *where, /* {{{ */
+     const char *db_name, const char *query_name,
      const char *what, OCIError *eh)
  {
    char buffer[2048];
    int status;
    unsigned int record_number;
  
+   if (db_name == NULL)
+     db_name = "(none)";
+   if (query_name == NULL)
+     query_name = "(none)";
    /* An operation may cause / return multiple errors. Loop until we have
     * handled all errors available (with a fail-save limit of 16). */
    for (record_number = 1; record_number <= 16; record_number++)
          buffer[buffer_length] = 0;
        }
  
-       ERROR ("oracle plugin: %s: %s failed: %s", where, what, buffer);
+       ERROR ("oracle plugin: %s (db = %s, query = %s): %s failed: %s",
+           where, db_name, query_name, what, buffer);
      }
      else
      {
-       ERROR ("oracle plugin: %s: %s failed. Additionally, OCIErrorGet failed with status %i.",
-           where, what, status);
+       ERROR ("oracle plugin: %s (db = %s, query = %s): %s failed. "
+           "Additionally, OCIErrorGet failed with status %i.",
+           where, db_name, query_name, what, status);
        return;
      }
    }
@@@ -344,7 -352,7 +352,7 @@@ static int o_config (oconfig_item_t *ci
      oconfig_item_t *child = ci->children + i;
      if (strcasecmp ("Query", child->key) == 0)
        udb_query_create (&queries, &queries_num, child,
 -          /* callback = */ NULL, /* legacy mode = */ 0);
 +          /* callback = */ NULL);
      else if (strcasecmp ("Database", child->key) == 0)
        o_config_add_database (child);
      else
@@@ -427,7 -435,8 +435,8 @@@ static int o_read_database_query (o_dat
          OCI_HTYPE_STMT, /* user_data_size = */ 0, /* user_data = */ NULL);
      if (status != OCI_SUCCESS)
      {
-       o_report_error ("o_read_database_query", "OCIHandleAlloc", oci_error);
+       o_report_error ("o_read_database_query", db->name,
+           udb_query_get_name (q), "OCIHandleAlloc", oci_error);
        oci_statement = NULL;
        return (-1);
      }
          /* mode     = */ OCI_DEFAULT);
      if (status != OCI_SUCCESS)
      {
-       o_report_error ("o_read_database_query", "OCIStmtPrepare", oci_error);
+       o_report_error ("o_read_database_query", db->name,
+           udb_query_get_name (q), "OCIStmtPrepare", oci_error);
        OCIHandleFree (oci_statement, OCI_HTYPE_STMT);
        oci_statement = NULL;
        return (-1);
        /* mode = */ OCI_DEFAULT);
    if (status != OCI_SUCCESS)
    {
-     DEBUG ("oracle plugin: o_read_database_query: status = %i (%#x)", status, status);
-     o_report_error ("o_read_database_query", "OCIStmtExecute", oci_error);
-     ERROR ("oracle plugin: o_read_database_query: "
-         "Failing statement was: %s", udb_query_get_statement (q));
+     o_report_error ("o_read_database_query", db->name, udb_query_get_name (q),
+         "OCIStmtExecute", oci_error);
      return (-1);
    } /* }}} */
  
          OCI_ATTR_PARAM_COUNT, oci_error);
      if (status != OCI_SUCCESS)
      {
-       o_report_error ("o_read_database_query", "OCIAttrGet", oci_error);
+       o_report_error ("o_read_database_query", db->name,
+           udb_query_get_name (q), "OCIAttrGet", oci_error);
        return (-1);
      } /* }}} */
  
      if (status != OCI_SUCCESS)
      {
        /* This is probably alright */
-       DEBUG ("oracle plugin: o_read_database_query: status = %#x (= %i);", status, status);
-       o_report_error ("o_read_database_query", "OCIParamGet", oci_error);
+       DEBUG ("oracle plugin: o_read_database_query: status = %#x (= %i);",
+           status, status);
+       o_report_error ("o_read_database_query", db->name,
+           udb_query_get_name (q), "OCIParamGet", oci_error);
        status = OCI_SUCCESS;
        break;
      }
      if (status != OCI_SUCCESS)
      {
        OCIDescriptorFree (oci_param, OCI_DTYPE_PARAM);
-       o_report_error ("o_read_database_query", "OCIAttrGet (OCI_ATTR_NAME)",
-           oci_error);
+       o_report_error ("o_read_database_query", db->name,
+           udb_query_get_name (q), "OCIAttrGet (OCI_ATTR_NAME)", oci_error);
        continue;
      }
  
          NULL, NULL, NULL, OCI_DEFAULT);
      if (status != OCI_SUCCESS)
      {
-       o_report_error ("o_read_database_query", "OCIDefineByPos", oci_error);
+       o_report_error ("o_read_database_query", db->name,
+           udb_query_get_name (q), "OCIDefineByPos", oci_error);
        continue;
      }
    } /* for (j = 1; j <= param_counter; j++) */
  
    status = udb_query_prepare_result (q, prep_area, hostname_g,
        /* plugin = */ "oracle", db->name, column_names, column_num,
 -      /* interval = */ -1);
 +      /* interval = */ 0);
    if (status != 0)
    {
      ERROR ("oracle plugin: o_read_database_query (%s, %s): "
      }
      else if ((status != OCI_SUCCESS) && (status != OCI_SUCCESS_WITH_INFO))
      {
-       o_report_error ("o_read_database_query", "OCIStmtFetch2", oci_error);
+       o_report_error ("o_read_database_query", db->name,
+           udb_query_get_name (q), "OCIStmtFetch2", oci_error);
        break;
      }
  
@@@ -663,7 -676,8 +676,8 @@@ static int o_read_database (o_database_
          OCI_ATTR_SERVER, oci_error);
      if (status != OCI_SUCCESS)
      {
-       o_report_error ("o_read_database", "OCIAttrGet", oci_error);
+       o_report_error ("o_read_database", db->name, NULL, "OCIAttrGet",
+           oci_error);
        return (-1);
      }
  
            OCI_ATTR_SERVER_STATUS, oci_error);
        if (status != OCI_SUCCESS)
        {
-         o_report_error ("o_read_database", "OCIAttrGet", oci_error);
+         o_report_error ("o_read_database", db->name, NULL, "OCIAttrGet",
+             oci_error);
          return (-1);
        }
      }
          (OraText *) db->connect_id, (ub4) strlen (db->connect_id));
      if ((status != OCI_SUCCESS) && (status != OCI_SUCCESS_WITH_INFO))
      {
-       o_report_error ("o_read_database", "OCILogon", oci_error);
+       char errfunc[256];
+       ssnprintf (errfunc, sizeof (errfunc), "OCILogon(\"%s\")", db->connect_id);
+       o_report_error ("o_read_database", db->name, NULL, errfunc, oci_error);
        DEBUG ("oracle plugin: OCILogon (%s): db->oci_service_context = %p;",
            db->connect_id, db->oci_service_context);
        db->oci_service_context = NULL;
diff --combined src/rrdtool.c
   */
  struct rrd_cache_s
  {
 -      int    values_num;
 -      char **values;
 -      time_t first_value;
 -      time_t last_value;
 -      int random_variation;
 +      int      values_num;
 +      char   **values;
 +      cdtime_t first_value;
 +      cdtime_t last_value;
 +      int64_t  random_variation;
        enum
        {
                FLAG_NONE   = 0x00,
@@@ -107,10 -107,10 +107,10 @@@ static rrdcreate_config_t rrdcreate_con
  
  /* XXX: If you need to lock both, cache_lock and queue_lock, at the same time,
   * ALWAYS lock `cache_lock' first! */
 -static int         cache_timeout = 0;
 -static int         cache_flush_timeout = 0;
 -static int         random_timeout = 1;
 -static time_t      cache_flush_last;
 +static cdtime_t    cache_timeout = 0;
 +static cdtime_t    cache_flush_timeout = 0;
 +static cdtime_t    random_timeout = TIME_T_TO_CDTIME_T (1);
 +static cdtime_t    cache_flush_last;
  static c_avl_tree_t *cache = NULL;
  static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
  
@@@ -185,7 -185,7 +185,7 @@@ static int srrd_update (char *filename
        if (status != 0)
        {
                WARNING ("rrdtool plugin: rrd_update_r failed: %s: %s",
-                               argv[1], rrd_get_error ());
+                               filename, rrd_get_error ());
        }
  
        sfree (new_argv);
@@@ -199,13 -199,11 +199,13 @@@ static int value_list_to_string (char *
  {
        int offset;
        int status;
 +      time_t tt;
        int i;
  
        memset (buffer, '\0', buffer_len);
  
 -      status = ssnprintf (buffer, buffer_len, "%u", (unsigned int) vl->time);
 +      tt = CDTIME_T_TO_TIME_T (vl->time);
 +      status = ssnprintf (buffer, buffer_len, "%u", (unsigned int) tt);
        if ((status < 1) || (status >= buffer_len))
                return (-1);
        offset = status;
@@@ -305,7 -303,7 +305,7 @@@ static void *rrd_queue_thread (void __a
  
                  pthread_mutex_lock (&queue_lock);
                  /* Wait for values to arrive */
 -                while (true)
 +                while (42)
                  {
                    struct timespec ts_wait;
  
                        &ts_wait);
                    if (status == ETIMEDOUT)
                      break;
 -                } /* while (true) */
 +                } /* while (42) */
  
                  /* XXX: If you need to lock both, cache_lock and queue_lock, at
                   * the same time, ALWAYS lock `cache_lock' first! */
@@@ -512,11 -510,10 +512,11 @@@ static int rrd_queue_dequeue (const cha
    return (0);
  } /* int rrd_queue_dequeue */
  
 -static void rrd_cache_flush (int timeout)
 +/* XXX: You must hold "cache_lock" when calling this function! */
 +static void rrd_cache_flush (cdtime_t timeout)
  {
        rrd_cache_t *rc;
 -      time_t       now;
 +      cdtime_t     now;
  
        char **keys = NULL;
        int    keys_num = 0;
        c_avl_iterator_t *iter;
        int i;
  
 -      DEBUG ("rrdtool plugin: Flushing cache, timeout = %i", timeout);
 +      DEBUG ("rrdtool plugin: Flushing cache, timeout = %.3f",
 +                      CDTIME_T_TO_DOUBLE (timeout));
  
 -      now = time (NULL);
 +      now = cdtime ();
 +      timeout = TIME_T_TO_CDTIME_T (timeout);
  
        /* Build a list of entries to be flushed */
        iter = c_avl_get_iterator (cache);
        {
                if (rc->flags != FLAG_NONE)
                        continue;
 -              else if ((now - rc->first_value) < timeout)
 +              /* timeout == 0  =>  flush everything */
 +              else if ((timeout != 0)
 +                              && ((now - rc->first_value) < timeout))
                        continue;
                else if (rc->values_num > 0)
                {
        cache_flush_last = now;
  } /* void rrd_cache_flush */
  
 -static int rrd_cache_flush_identifier (int timeout, const char *identifier)
 +static int rrd_cache_flush_identifier (cdtime_t timeout,
 +    const char *identifier)
  {
    rrd_cache_t *rc;
 -  time_t now;
 +  cdtime_t now;
    int status;
    char key[2048];
  
      return (0);
    }
  
 -  now = time (NULL);
 +  now = cdtime ();
  
    if (datadir == NULL)
      snprintf (key, sizeof (key), "%s.rrd",
    return (status);
  } /* int rrd_cache_flush_identifier */
  
 +static int64_t rrd_get_random_variation (void)
 +{
 +  double dbl_timeout;
 +  cdtime_t ctm_timeout;
 +  double rand_fact;
 +  _Bool negative;
 +  int64_t ret;
 +
 +  if (random_timeout <= 0)
 +    return (0);
 +
 +  /* Assure that "cache_timeout + random_variation" is never negative. */
 +  if (random_timeout > cache_timeout)
 +  {
 +        INFO ("rrdtool plugin: Adjusting \"RandomTimeout\" to %.3f seconds.",
 +                        CDTIME_T_TO_DOUBLE (cache_timeout));
 +        random_timeout = cache_timeout;
 +  }
 +
 +  /* This seems a bit complicated, but "random_timeout" is likely larger than
 +   * RAND_MAX, so we can't simply use modulo here. */
 +  dbl_timeout = CDTIME_T_TO_DOUBLE (random_timeout);
 +  rand_fact = ((double) random ())
 +    / ((double) RAND_MAX);
 +  negative = (_Bool) (random () % 2);
 +
 +  ctm_timeout = DOUBLE_TO_CDTIME_T (dbl_timeout * rand_fact);
 +
 +  ret = (int64_t) ctm_timeout;
 +  if (negative)
 +    ret *= -1;
 +
 +  return (ret);
 +} /* int64_t rrd_get_random_variation */
 +
  static int rrd_cache_insert (const char *filename,
 -              const char *value, time_t value_time)
 +              const char *value, cdtime_t value_time)
  {
        rrd_cache_t *rc = NULL;
        int new_rc = 0;
  
        if (rc == NULL)
        {
 -              rc = (rrd_cache_t *) malloc (sizeof (rrd_cache_t));
 +              rc = malloc (sizeof (*rc));
                if (rc == NULL)
                        return (-1);
                rc->values_num = 0;
                rc->values = NULL;
                rc->first_value = 0;
                rc->last_value = 0;
 -              rc->random_variation = 0;
 +              rc->random_variation = rrd_get_random_variation ();
                rc->flags = FLAG_NONE;
                new_rc = 1;
        }
        if (rc->last_value >= value_time)
        {
                pthread_mutex_unlock (&cache_lock);
 -              DEBUG ("rrdtool plugin: (rc->last_value = %u) >= (value_time = %u)",
 -                              (unsigned int) rc->last_value,
 -                              (unsigned int) value_time);
 +              DEBUG ("rrdtool plugin: (rc->last_value = %"PRIu64") "
 +                              ">= (value_time = %"PRIu64")",
 +                              rc->last_value, value_time);
                return (-1);
        }
  
        }
  
        DEBUG ("rrdtool plugin: rrd_cache_insert: file = %s; "
 -                      "values_num = %i; age = %lu;",
 +                      "values_num = %i; age = %.3f;",
                        filename, rc->values_num,
 -                      (unsigned long)(rc->last_value - rc->first_value));
 +                      CDTIME_T_TO_DOUBLE (rc->last_value - rc->first_value));
  
 -      if ((rc->last_value + rc->random_variation - rc->first_value) >= cache_timeout)
 +      if ((rc->last_value - rc->first_value) >= (cache_timeout + rc->random_variation))
        {
                /* XXX: If you need to lock both, cache_lock and queue_lock, at
                 * the same time, ALWAYS lock `cache_lock' first! */
                        if (status == 0)
                                rc->flags = FLAG_QUEUED;
  
 -                      /* Update the jitter value. Negative values are
 -                       * slightly preferred. */
 -                      if (random_timeout > 0)
 -                      {
 -                              rc->random_variation = (rand () % (2 * random_timeout))
 -                                      - random_timeout;
 -                      }
 -                      else
 -                      {
 -                              rc->random_variation = 0;
 -                      }
 +                        rc->random_variation = rrd_get_random_variation ();
                }
                else
                {
        }
  
        if ((cache_timeout > 0) &&
 -                      ((time (NULL) - cache_flush_last) > cache_flush_timeout))
 +                      ((cdtime () - cache_flush_last) > cache_flush_timeout))
                rrd_cache_flush (cache_flush_timeout);
  
        pthread_mutex_unlock (&cache_lock);
@@@ -932,8 -899,8 +932,8 @@@ static int rrd_write (const data_set_t 
        return (status);
  } /* int rrd_write */
  
 -static int rrd_flush (int timeout, const char *identifier,
 -              user_data_t __attribute__((unused)) *user_data)
 +static int rrd_flush (cdtime_t timeout, const char *identifier,
 +              __attribute__((unused)) user_data_t *user_data)
  {
        pthread_mutex_lock (&cache_lock);
  
@@@ -952,7 -919,7 +952,7 @@@ static int rrd_config (const char *key
  {
        if (strcasecmp ("CacheTimeout", key) == 0)
        {
 -              int tmp = atoi (value);
 +              double tmp = atof (value);
                if (tmp < 0)
                {
                        fprintf (stderr, "rrdtool: `CacheTimeout' must "
                                        "be greater than 0.\n");
                        return (1);
                }
 -              cache_timeout = tmp;
 +              cache_timeout = DOUBLE_TO_CDTIME_T (tmp);
        }
        else if (strcasecmp ("CacheFlush", key) == 0)
        {
        }
        else if (strcasecmp ("StepSize", key) == 0)
        {
 -              int temp = atoi (value);
 +              unsigned long temp = strtoul (value, NULL, 0);
                if (temp > 0)
                        rrdcreate_config.stepsize = temp;
        }
        }
        else if (strcasecmp ("RandomTimeout", key) == 0)
          {
 -              int tmp;
 +              double tmp;
  
 -              tmp = atoi (value);
 -              if (tmp < 0)
 +              tmp = atof (value);
 +              if (tmp < 0.0)
                {
                        fprintf (stderr, "rrdtool: `RandomTimeout' must "
                                        "be greater than or equal to zero.\n");
                }
                else
                {
 -                      random_timeout = tmp;
 +                      random_timeout = DOUBLE_TO_CDTIME_T (tmp);
                }
        }
        else
  static int rrd_shutdown (void)
  {
        pthread_mutex_lock (&cache_lock);
 -      rrd_cache_flush (-1);
 +      rrd_cache_flush (0);
        pthread_mutex_unlock (&cache_lock);
  
        pthread_mutex_lock (&queue_lock);
@@@ -1161,16 -1128,18 +1161,16 @@@ static int rrd_init (void
                return (0);
        init_once = 1;
  
 -      if (rrdcreate_config.stepsize < 0)
 -              rrdcreate_config.stepsize = 0;
        if (rrdcreate_config.heartbeat <= 0)
                rrdcreate_config.heartbeat = 2 * rrdcreate_config.stepsize;
  
        if ((rrdcreate_config.heartbeat > 0)
 -                      && (rrdcreate_config.heartbeat < interval_g))
 +                      && (rrdcreate_config.heartbeat < CDTIME_T_TO_TIME_T (interval_g)))
                WARNING ("rrdtool plugin: Your `heartbeat' is "
                                "smaller than your `interval'. This will "
                                "likely cause problems.");
        else if ((rrdcreate_config.stepsize > 0)
 -                      && (rrdcreate_config.stepsize < interval_g))
 +                      && (rrdcreate_config.stepsize < CDTIME_T_TO_TIME_T (interval_g)))
                WARNING ("rrdtool plugin: Your `stepsize' is "
                                "smaller than your `interval'. This will "
                                "create needlessly big RRD-files.");
                return (-1);
        }
  
 -      cache_flush_last = time (NULL);
 -      if (cache_timeout < 2)
 +      cache_flush_last = cdtime ();
 +      if (cache_timeout == 0)
        {
 -              cache_timeout = 0;
                cache_flush_timeout = 0;
        }
        else if (cache_flush_timeout < cache_timeout)
        }
        queue_thread_running = 1;
  
 -      DEBUG ("rrdtool plugin: rrd_init: datadir = %s; stepsize = %i;"
 +      DEBUG ("rrdtool plugin: rrd_init: datadir = %s; stepsize = %lu;"
                        " heartbeat = %i; rrarows = %i; xff = %lf;",
                        (datadir == NULL) ? "(null)" : datadir,
                        rrdcreate_config.stepsize,
diff --combined src/snmp.c
@@@ -69,7 -69,7 +69,7 @@@ struct host_definition_
    int version;
    void *sess_handle;
    c_complain_t complaint;
 -  uint32_t interval;
 +  cdtime_t interval;
    data_definition_t **data_list;
    int data_list_len;
  };
@@@ -159,6 -159,7 +159,6 @@@ static void csnmp_host_definition_destr
   *      +-> csnmp_config_add_host_community
   *      +-> csnmp_config_add_host_version
   *      +-> csnmp_config_add_host_collect
 - *      +-> csnmp_config_add_host_interval
   */
  static void call_snmp_init_once (void)
  {
@@@ -301,7 -302,7 +301,7 @@@ static int csnmp_config_add_data_shift 
    if ((ci->values_num != 1)
        || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
    {
-     WARNING ("snmp plugin: The `Scale' config option needs exactly one number argument.");
+     WARNING ("snmp plugin: The `Shift' config option needs exactly one number argument.");
      return (-1);
    }
  
@@@ -542,6 -543,22 +542,6 @@@ static int csnmp_config_add_host_collec
    return (0);
  } /* int csnmp_config_add_host_collect */
  
 -static int csnmp_config_add_host_interval (host_definition_t *hd, oconfig_item_t *ci)
 -{
 -  if ((ci->values_num != 1)
 -      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
 -  {
 -    WARNING ("snmp plugin: The `Interval' config option needs exactly one number argument.");
 -    return (-1);
 -  }
 -
 -  hd->interval = ci->values[0].value.number >= 0
 -    ? (uint32_t) ci->values[0].value.number
 -    : 0;
 -
 -  return (0);
 -} /* int csnmp_config_add_host_interval */
 -
  static int csnmp_config_add_host (oconfig_item_t *ci)
  {
    host_definition_t *hd;
      else if (strcasecmp ("Collect", option->key) == 0)
        csnmp_config_add_host_collect (hd, option);
      else if (strcasecmp ("Interval", option->key) == 0)
 -      csnmp_config_add_host_interval (hd, option);
 +      cf_util_get_cdtime (option, &hd->interval);
      else
      {
        WARNING ("snmp plugin: csnmp_config_add_host: Option `%s' not allowed here.", option->key);
    cb_data.data = hd;
    cb_data.free_func = csnmp_host_definition_destroy;
  
 -  memset (&cb_interval, 0, sizeof (cb_interval));
 -  if (hd->interval != 0)
 -    cb_interval.tv_sec = (time_t) hd->interval;
 +  CDTIME_T_TO_TIMESPEC (hd->interval, &cb_interval);
  
    status = plugin_register_complex_read (/* group = */ NULL, cb_name,
        csnmp_read_host, /* interval = */ &cb_interval,
@@@ -867,10 -886,12 +867,12 @@@ static int csnmp_check_res_left_subtre
        vb = vb->next_variable, i++)
    {
      num_checked++;
-     if (snmp_oid_ncompare (data->values[i].oid,
-         data->values[i].oid_len,
-         vb->name, vb->name_length,
-         data->values[i].oid_len) != 0)
+     if ((vb->type == SNMP_ENDOFMIBVIEW)
+       || (snmp_oid_ncompare (data->values[i].oid,
+           data->values[i].oid_len,
+           vb->name, vb->name_length,
+           data->values[i].oid_len) != 0))
        num_left_subtree++;
    }
  
@@@ -1527,8 -1548,8 +1529,8 @@@ static int csnmp_read_value (host_defin
  static int csnmp_read_host (user_data_t *ud)
  {
    host_definition_t *host;
 -  time_t time_start;
 -  time_t time_end;
 +  cdtime_t time_start;
 +  cdtime_t time_end;
    int status;
    int success;
    int i;
    if (host->interval == 0)
      host->interval = interval_g;
  
 -  time_start = time (NULL);
 -  DEBUG ("snmp plugin: csnmp_read_host (%s) started at %u;", host->name,
 -      (unsigned int) time_start);
 +  time_start = cdtime ();
  
    if (host->sess_handle == NULL)
      csnmp_host_open_session (host);
        success++;
    }
  
 -  time_end = time (NULL);
 -  DEBUG ("snmp plugin: csnmp_read_host (%s) finished at %u;", host->name,
 -      (unsigned int) time_end);
 -  if ((uint32_t) (time_end - time_start) > host->interval)
 +  time_end = cdtime ();
 +  if ((time_end - time_start) > host->interval)
    {
 -    WARNING ("snmp plugin: Host `%s' should be queried every %"PRIu32
 -      " seconds, but reading all values takes %u seconds.",
 -      host->name, host->interval, (unsigned int) (time_end - time_start));
 +    WARNING ("snmp plugin: Host `%s' should be queried every %.3f "
 +      "seconds, but reading all values takes %.3f seconds.",
 +      host->name,
 +      CDTIME_T_TO_DOUBLE (host->interval),
 +      CDTIME_T_TO_DOUBLE (time_end - time_start));
    }
  
    if (success == 0)
diff --combined src/utils_dns.c
  #if HAVE_NETINET_IN_H
  # include <netinet/in.h>
  #endif
 +#if HAVE_NETINET_IP6_H
 +# include <netinet/ip6.h>
 +#endif
 +#if HAVE_NETINET_IP_COMPAT_H
 +# include <netinet/ip_compat.h>
 +#endif
  #if HAVE_ARPA_INET_H
  # include <arpa/inet.h>
  #endif
  
  #if HAVE_STRUCT_UDPHDR_UH_DPORT && HAVE_STRUCT_UDPHDR_UH_SPORT
  # define UDP_DEST uh_dport
- # define UDP_SRC  uh_dport
+ # define UDP_SRC  uh_sport
  #elif HAVE_STRUCT_UDPHDR_DEST && HAVE_STRUCT_UDPHDR_SOURCE
  # define UDP_DEST dest
  # define UDP_SRC  source
@@@ -297,18 -291,13 +297,18 @@@ rfc1035NameUnpack(const char *buf, size
      off_t no = 0;
      unsigned char c;
      size_t len;
 -    assert(ns > 0);
 +    static int loop_detect = 0;
 +    if (loop_detect > 2)
 +      return 4;               /* compression loop */
 +    if (ns <= 0)
 +      return 4;               /* probably compression loop */
      do {
        if ((*off) >= sz)
            break;
        c = *(buf + (*off));
        if (c > 191) {
            /* blasted compression */
 +          int rc;
            unsigned short s;
            off_t ptr;
            memcpy(&s, buf + (*off), sizeof(s));
            (*off) += sizeof(s);
            /* Sanity check */
            if ((*off) >= sz)
 -              return 1;
 +              return 1;       /* message too short */
            ptr = s & 0x3FFF;
            /* Make sure the pointer is inside this message */
            if (ptr >= sz)
 -              return 2;
 -          return rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no);
 +              return 2;       /* bad compression ptr */
 +          if (ptr < DNS_MSG_HDR_SZ)
 +              return 2;       /* bad compression ptr */
 +          loop_detect++;
 +          rc = rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no);
 +          loop_detect--;
 +          return rc;
        } else if (c > RFC1035_MAXLABELSZ) {
            /*
             * "(The 10 and 01 combinations are reserved for future use.)"
             */
 +          return 3;           /* reserved label/compression flags */
            break;
 -          return 3;
        } else {
            (*off)++;
            len = (size_t) c;
                break;
            if (len > (ns - 1))
                len = ns - 1;
 -          if ((*off) + len > sz)      /* message is too short */
 -              return 4;
 +          if ((*off) + len > sz)
 +              return 4;       /* message is too short */
 +          if (no + len + 1 > ns)
 +              return 5;       /* qname would overflow name buffer */
            memcpy(name + no, buf + (*off), len);
            (*off) += len;
            no += len;
            *(name + (no++)) = '.';
        }
      } while (c > 0);
 -    *(name + no - 1) = '\0';
 +    if (no > 0)
 +      *(name + no - 1) = '\0';
      /* make sure we didn't allow someone to overflow the name buffer */
      assert(no <= ns);
      return 0;
@@@ -364,10 -345,10 +364,10 @@@ handle_dns(const char *buf, int len
      uint16_t us;
      off_t offset;
      char *t;
 -    int x;
 +    int status;
  
      /* The DNS header is 12 bytes long */
 -    if (len < 12)
 +    if (len < DNS_MSG_HDR_SZ)
        return 0;
  
      memcpy(&us, buf + 0, 2);
      memcpy(&us, buf + 10, 2);
      qh.arcount = ntohs(us);
  
 -    offset = 12;
 +    offset = DNS_MSG_HDR_SZ;
      memset(qh.qname, '\0', MAX_QNAME_SZ);
 -    x = rfc1035NameUnpack(buf, len, &offset, qh.qname, MAX_QNAME_SZ);
 -    if (0 != x)
 +    status = rfc1035NameUnpack(buf, len, &offset, qh.qname, MAX_QNAME_SZ);
 +    if (status != 0)
 +    {
 +      INFO ("utils_dns: handle_dns: rfc1035NameUnpack failed "
 +              "with status %i.", status);
        return 0;
 +    }
      if ('\0' == qh.qname[0])
        sstrncpy (qh.qname, ".", sizeof (qh.qname));
      while ((t = strchr(qh.qname, '\n')))
@@@ -447,7 -424,6 +447,7 @@@ handle_udp(const struct udphdr *udp, in
      return 1;
  }
  
 +#if HAVE_NETINET_IP6_H
  static int
  handle_ipv6 (struct ip6_hdr *ipv6, int len)
  {
      unsigned int offset;
      int nexthdr;
  
-     struct in6_addr s_addr;
+     struct in6_addr c_src_addr;
      uint16_t payload_len;
  
      if (0 > len)
  
      offset = sizeof (struct ip6_hdr);
      nexthdr = ipv6->ip6_nxt;
-     s_addr = ipv6->ip6_src;
+     c_src_addr = ipv6->ip6_src;
      payload_len = ntohs (ipv6->ip6_plen);
  
-     if (ignore_list_match (&s_addr))
+     if (ignore_list_match (&c_src_addr))
            return (0);
  
      /* Parse extension headers. This only handles the standard headers, as
            || (IPPROTO_HOPOPTS == nexthdr) /* Hop-by-Hop options. */
            || (IPPROTO_FRAGMENT == nexthdr) /* fragmentation header. */
            || (IPPROTO_DSTOPTS == nexthdr) /* destination options. */
-           || (IPPROTO_DSTOPTS == nexthdr) /* destination options. */
            || (IPPROTO_AH == nexthdr) /* destination options. */
            || (IPPROTO_ESP == nexthdr)) /* encapsulating security payload. */
      {
  
      return (1); /* Success */
  } /* int handle_ipv6 */
 +/* #endif HAVE_NETINET_IP6_H */
 +
 +#else /* if !HAVE_NETINET_IP6_H */
 +static int
 +handle_ipv6 (__attribute__((unused)) void *pkg,
 +      __attribute__((unused)) int len)
 +{
 +    return (0);
 +}
 +#endif /* !HAVE_NETINET_IP6_H */
  
  static int
  handle_ip(const struct ip *ip, int len)
  {
      char buf[PCAP_SNAPLEN];
      int offset = ip->ip_hl << 2;
-     struct in6_addr s_addr;
-     struct in6_addr d_addr;
+     struct in6_addr c_src_addr;
+     struct in6_addr c_dst_addr;
  
      if (ip->ip_v == 6)
 -      return (handle_ipv6 ((struct ip6_hdr *) ip, len));
 +      return (handle_ipv6 ((void *) ip, len));
  
-     in6_addr_from_buffer (&s_addr, &ip->ip_src.s_addr, sizeof (ip->ip_src.s_addr), AF_INET);
-     in6_addr_from_buffer (&d_addr, &ip->ip_dst.s_addr, sizeof (ip->ip_dst.s_addr), AF_INET);
-     if (ignore_list_match (&s_addr))
+     in6_addr_from_buffer (&c_src_addr, &ip->ip_src.s_addr, sizeof (ip->ip_src.s_addr), AF_INET);
+     in6_addr_from_buffer (&c_dst_addr, &ip->ip_dst.s_addr, sizeof (ip->ip_dst.s_addr), AF_INET);
+     if (ignore_list_match (&c_src_addr))
            return (0);
      if (IPPROTO_UDP != ip->ip_p)
        return 0;
@@@ -635,7 -600,7 +634,7 @@@ handle_ether(const u_char * pkt, int le
        return 0;
      memcpy(buf, pkt, len);
      if (ETHERTYPE_IPV6 == etype)
 -      return (handle_ipv6 ((struct ip6_hdr *) buf, len));
 +      return (handle_ipv6 ((void *) buf, len));
      else
        return handle_ip((struct ip *) buf, len);
  }
@@@ -668,7 -633,7 +667,7 @@@ handle_linux_sll (const u_char *pkt, in
        return 0;
  
      if (ETHERTYPE_IPV6 == etype)
 -      return (handle_ipv6 ((struct ip6_hdr *) pkt, len));
 +      return (handle_ipv6 ((void *) pkt, len));
      else
        return handle_ip((struct ip *) pkt, len);
  }
@@@ -679,6 -644,10 +678,6 @@@ void handle_pcap(u_char *udata, const s
  {
      int status;
  
 -    DEBUG ("handle_pcap (udata = %p, hdr = %p, pkt = %p): hdr->caplen = %i\n",
 -                  (void *) udata, (void *) hdr, (void *) pkt,
 -                  hdr->caplen);
 -
      if (hdr->caplen < ETHER_HDR_LEN)
        return;
  
            break;
  
        default:
 -          ERROR ("handle_pcap: unsupported data link type %d\n",
 +          ERROR ("handle_pcap: unsupported data link type %d",
                    pcap_datalink(pcap_obj));
            status = 0;
            break;