Merge branch 'collectd-4.8' into collectd-4.9
authorFlorian Forster <octo@huhu.verplant.org>
Thu, 25 Feb 2010 22:55:25 +0000 (23:55 +0100)
committerFlorian Forster <octo@huhu.verplant.org>
Thu, 25 Feb 2010 22:55:25 +0000 (23:55 +0100)
Conflicts:

src/ping.c

1  2 
configure.in
src/apache.c
src/collectd.conf.in
src/collectd.conf.pod
src/exec.c
src/ping.c
src/plugin.c

diff --combined configure.in
@@@ -9,7 -9,6 +9,7 @@@ m4_ifdef([LT_PACKAGE_VERSION]
         LT_CONFIG_LTDL_DIR([libltdl])
         LT_INIT([dlopen])
         LTDL_INIT([convenience])
 +       AC_DEFINE(LIBTOOL_VERSION, 2, [Define to used libtool version.])
        ]
  ,
        # libtool <= 1.5
@@@ -19,7 -18,6 +19,7 @@@
         AC_SUBST(LIBLTDL)
         AC_LIBTOOL_DLOPEN
         AC_CONFIG_SUBDIRS(libltdl)
 +       AC_DEFINE(LIBTOOL_VERSION, 1, [Define to used libtool version.])
        ]
  )
  
@@@ -63,10 -61,6 +63,10 @@@ case $host_os i
        *openbsd*)
        ac_system="OpenBSD"
        ;;
 +      *aix*)
 +      AC_DEFINE([KERNEL_AIX], 1, [True if program is to be compiled for a AIX kernel])
 +      ac_system="AIX"
 +      ;;
        *)
        ac_system="unknown"
  esac
@@@ -268,22 -262,6 +268,22 @@@ AC_CHECK_HEADERS(sys/sysctl.h, [], []
  #endif
  ])
  
 +AC_MSG_CHECKING([for sysctl kern.cp_times])
 +if test -x /sbin/sysctl
 +then
 +      /sbin/sysctl kern.cp_times 2>/dev/null
 +      if test $? -eq 0
 +      then
 +              AC_MSG_RESULT([yes])
 +              AC_DEFINE(HAVE_SYSCTL_KERN_CP_TIMES, 1,
 +              [Define if sysctl supports kern.cp_times])
 +      else
 +              AC_MSG_RESULT([no])
 +      fi
 +else
 +      AC_MSG_RESULT([no])
 +fi
 +
  # For hddtemp module
  AC_CHECK_HEADERS(linux/major.h libgen.h)
  
@@@ -633,8 -611,6 +633,8 @@@ static float foo = NAN
    fi
  fi
  if test "x$nan_type" = "xnone"; then
 +  SAVE_LDFLAGS=$LDFLAGS
 +  LDFLAGS="$LDFLAGS -lm"
    AC_CACHE_CHECK([whether NAN can be defined by 0/0],
      [c_cv_have_nan_zero],
      AC_RUN_IFELSE(
@@@ -661,7 -637,6 +661,7 @@@ static float foo = NAN
        [c_cv_have_nan_zero="no"]
      )
    )
 +  LDFLAGS=$SAVE_LDFLAGS
    if test "x$c_cv_have_nan_zero" = "xyes"
    then
      nan_type="zero"
  m4_divert_once([HELP_WITH], [
  collectd additional packages:])
  
 +AM_CONDITIONAL([BUILD_AIX],[test "x$x$ac_system" = "xAIX"]) 
 +
 +if test "x$ac_system" = "xAIX"
 +then
 +      with_perfstat="yes"
 +      with_procinfo="yes"
 +else
 +      with_perfstat="no (AIX only)"
 +      with_procinfo="no (AIX only)"
 +fi
 +
 +if test "x$with_perfstat" = "xyes"
 +then
 +      AC_CHECK_LIB(perfstat, perfstat_reset, [with_perfstat="yes"], [with_perfstat="no (perfstat not found)"], [])
 +#     AC_CHECK_HEADERS(sys/protosw.h libperfstat.h,, [with_perfstat="no (perfstat not found)"])
 +fi
 +if test "x$with_perfstat" = "xyes"
 +then
 +       AC_DEFINE(HAVE_PERFSTAT, 1, [Define to 1 if you have the 'perfstat' library (-lperfstat)])
 +fi
 +AM_CONDITIONAL(BUILD_WITH_PERFSTAT, test "x$with_perfstat" = "xyes")
 +
 +# Processes plugin under AIX.
 +if test "x$with_procinfo" = "xyes"
 +then
 +      AC_CHECK_HEADERS(procinfo.h,, [with_procinfo="no (procinfo.h not found)"])
 +fi
 +if test "x$with_procinfo" = "xyes"
 +then
 +       AC_DEFINE(HAVE_PROCINFO_H, 1, [Define to 1 if you have the procinfo.h])
 +fi
 +
  if test "x$ac_system" = "xSolaris"
  then
        with_kstat="yes"
@@@ -1611,6 -1554,7 +1611,7 @@@ with_java_vmtype="client
  with_java_cflags=""
  with_java_libs=""
  JAVAC="$JAVAC"
+ JAR="$JAR"
  AC_ARG_WITH(java, [AS_HELP_STRING([--with-java@<:@=PREFIX@:>@], [Path to Java home.])],
  [
        if test "x$withval" = "xno"
                                AC_MSG_RESULT([not found])
                        fi
                fi
+               if test "x$JAR" = "x"
+               then
+                       AC_MSG_CHECKING([for jar])
+                       TMPDIR=`find "$with_java_home" -name jar -type f | head -n 1`
+                       if test "x$TMPDIR" != "x"
+                       then
+                               JAR="$TMPDIR"
+                               AC_MSG_RESULT([$JAR])
+                       else
+                               AC_MSG_RESULT([not found])
+                       fi
+               fi
        else if test "x$with_java_home" != "x"
        then
                AC_MSG_WARN([JAVA_HOME: No such directory: $with_java_home])
@@@ -1707,6 -1663,24 +1720,24 @@@ if test "x$JAVAC" = "x
  then
        with_java="no (javac not found)"
  fi
+ if test "x$JAR" = "x"
+ then
+       with_jar_path="$PATH"
+       if test "x$with_java_home" != "x"
+       then
+               with_jar_path="$with_java_home:$with_jar_path"
+               if test -d "$with_java_home/bin"
+               then
+                       with_jar_path="$with_java_home/bin:$with_jar_path"
+               fi
+       fi
+       AC_PATH_PROG(JAR, jar, [], "$with_jar_path")
+ fi
+ if test "x$JAR" = "x"
+ then
+       with_java="no (jar not found)"
+ fi
  
  SAVE_CPPFLAGS="$CPPFLAGS"
  SAVE_CFLAGS="$CFLAGS"
  AM_CONDITIONAL(BUILD_WITH_LIBNETLINK, test "x$with_libnetlink" = "xyes")
  # }}}
  
 +# --with-libnetapp {{{
 +AC_ARG_VAR([LIBNETAPP_CPPFLAGS], [C preprocessor flags required to build with libnetapp])
 +AC_ARG_VAR([LIBNETAPP_LDFLAGS],  [Linker flags required to build with libnetapp])
 +AC_ARG_VAR([LIBNETAPP_LIBS],     [Other libraries required to link against libnetapp])
 +LIBNETAPP_CPPFLAGS="$LIBNETAPP_CPPFLAGS"
 +LIBNETAPP_LDFLAGS="$LIBNETAPP_LDFLAGS"
 +LIBNETAPP_LIBS="$LIBNETAPP_LIBS"
 +AC_ARG_WITH(libnetapp, [AS_HELP_STRING([--with-libnetapp@<:@=PREFIX@:>@], [Path to libnetapp.])],
 +[
 + if test -d "$withval"
 + then
 +       LIBNETAPP_CPPFLAGS="$LIBNETAPP_CPPFLAGS -I$withval/include"
 +       LIBNETAPP_LDFLAGS="$LIBNETAPP_LDFLAGS -L$withval/lib"
 +       with_libnetapp="yes"
 + else
 +       with_libnetapp="$withval"
 + fi
 +],
 +[
 + with_libnetapp="yes"
 +])
 +
 +SAVE_CPPFLAGS="$CPPFLAGS"
 +SAVE_LDFLAGS="$LDFLAGS"
 +CPPFLAGS="$CPPFLAGS $LIBNETAPP_CPPFLAGS"
 +LDFLAGS="$LDFLAGS $LIBNETAPP_LDFLAGS"
 +
 +if test "x$with_libnetapp" = "xyes"
 +then
 +      if test "x$LIBNETAPP_CPPFLAGS" != "x"
 +      then
 +              AC_MSG_NOTICE([netapp CPPFLAGS: $LIBNETAPP_CPPFLAGS])
 +      fi
 +      AC_CHECK_HEADERS(netapp_api.h,
 +              [with_libnetapp="yes"],
 +              [with_libnetapp="no (netapp_api.h not found)"])
 +fi
 +
 +if test "x$with_libnetapp" = "xyes"
 +then
 +      if test "x$LIBNETAPP_LDFLAGS" != "x"
 +      then
 +              AC_MSG_NOTICE([netapp LDFLAGS: $LIBNETAPP_LDFLAGS])
 +      fi
 +
 +      if test "x$LIBNETAPP_LIBS" = "x"
 +      then
 +              LIBNETAPP_LIBS="-lpthread -lxml -ladt -lssl -lm -lcrypto -lz"
 +      fi
 +      AC_MSG_NOTICE([netapp LIBS: $LIBNETAPP_LIBS])
 +
 +      AC_CHECK_LIB(netapp, na_server_invoke_elem,
 +              [with_libnetapp="yes"],
 +              [with_libnetapp="no (symbol na_server_invoke_elem not found)"],
 +              [$LIBNETAPP_LIBS])
 +      LIBNETAPP_LIBS="-lnetapp $LIBNETAPP_LIBS"
 +fi
 +
 +CPPFLAGS="$SAVE_CPPFLAGS"
 +LDFLAGS="$SAVE_LDFLAGS"
 +
 +if test "x$with_libnetapp" = "xyes"
 +then
 +      AC_DEFINE(HAVE_LIBNETAPP, 1, [Define to 1 if you have the netapp library (-lnetapp).])
 +fi
 +
 +AC_SUBST(LIBNETAPP_CPPFLAGS)
 +AC_SUBST(LIBNETAPP_LDFLAGS)
 +AC_SUBST(LIBNETAPP_LIBS)
 +AM_CONDITIONAL(BUILD_WITH_LIBNETAPP, test "x$with_libnetapp" = "xyes")
 +# }}}
 +
  # --with-libnetsnmp {{{
  with_snmp_config="net-snmp-config"
  with_snmp_cflags=""
@@@ -2694,184 -2596,6 +2725,184 @@@ AC_DEFINE_UNQUOTED(HAVE_LIBPTHREAD, [$c
  AM_CONDITIONAL(BUILD_WITH_LIBPTHREAD, test "x$with_libpthread" = "xyes")
  # }}}
  
 +# --with-python {{{
 +with_python_prog=""
 +with_python_path="$PATH"
 +AC_ARG_WITH(python, [AS_HELP_STRING([--with-python@<:@=PREFIX@:>@], [Path to the python interpreter.])],
 +[
 + if test "x$withval" = "xyes" || test "x$withval" = "xno"
 + then
 +       with_python="$withval"
 + else if test -x "$withval"
 + then
 +       with_python_prog="$withval"
 +       with_python_path="`dirname \"$withval\"`$PATH_SEPARATOR$with_python_path"
 +       with_python="yes"
 + else if test -d "$withval"
 + then
 +       with_python_path="$withval$PATH_SEPARATOR$with_python_path"
 +       with_python="yes"
 + else
 +       AC_MSG_WARN([Argument not recognized: $withval])
 + fi; fi; fi
 +], [with_python="yes"])
 +
 +SAVE_PATH="$PATH"
 +SAVE_CPPFLAGS="$CPPFLAGS"
 +SAVE_LDFLAGS="$LDFLAGS"
 +SAVE_LIBS="$LIBS"
 +
 +PATH="$with_python_path"
 +
 +if test "x$with_python" = "xyes" && test "x$with_python_prog" = "x"
 +then
 +      AC_MSG_CHECKING([for python])
 +      with_python_prog="`which python 2>/dev/null`"
 +      if test "x$with_python_prog" = "x"
 +      then
 +              AC_MSG_RESULT([not found])
 +              with_python="no (interpreter not found)"
 +      else
 +              AC_MSG_RESULT([$with_python_prog])
 +      fi
 +fi
 +
 +if test "x$with_python" = "xyes"
 +then
 +      AC_MSG_CHECKING([for Python CPPFLAGS])
 +      python_include_path=`echo "import distutils.sysconfig;print distutils.sysconfig.get_python_inc()" | "$with_python_prog" 2>&1`
 +      python_config_status=$?
 +
 +      if test "$python_config_status" -ne 0 || test "x$python_include_path" = "x"
 +      then
 +              AC_MSG_RESULT([failed with status $python_config_status (output: $python_include_path)])
 +              with_python="no"
 +      else
 +              AC_MSG_RESULT([$python_include_path])
 +      fi
 +fi
 +
 +if test "x$with_python" = "xyes"
 +then
 +      CPPFLAGS="-I$python_include_path $CPPFLAGS"
 +      AC_CHECK_HEADERS(Python.h,
 +                       [with_python="yes"],
 +                       [with_python="no ('Python.h' not found)"])
 +fi
 +
 +if test "x$with_python" = "xyes"
 +then
 +      AC_MSG_CHECKING([for Python LDFLAGS])
 +      python_library_path=`echo "import distutils.sysconfig;print distutils.sysconfig.get_config_vars(\"LIBDIR\").__getitem__(0)" | "$with_python_prog" 2>&1`
 +      python_config_status=$?
 +
 +      if test "$python_config_status" -ne 0 || test "x$python_library_path" = "x"
 +      then
 +              AC_MSG_RESULT([failed with status $python_config_status (output: $python_library_path)])
 +              with_python="no"
 +      else
 +              AC_MSG_RESULT([$python_library_path])
 +      fi
 +fi
 +
 +if test "x$with_python" = "xyes"
 +then
 +      AC_MSG_CHECKING([for Python LIBS])
 +      python_library_flags=`echo "import distutils.sysconfig;print distutils.sysconfig.get_config_vars(\"BLDLIBRARY\").__getitem__(0)" | "$with_python_prog" 2>&1`
 +      python_config_status=$?
 +
 +      if test "$python_config_status" -ne 0 || test "x$python_library_flags" = "x"
 +      then
 +              AC_MSG_RESULT([failed with status $python_config_status (output: $python_library_flags)])
 +              with_python="no"
 +      else
 +              AC_MSG_RESULT([$python_library_flags])
 +      fi
 +fi
 +
 +if test "x$with_python" = "xyes"
 +then
 +      LDFLAGS="-L$python_library_path $LDFLAGS"
 +      LIBS="$python_library_flags $LIBS"
 +
 +      AC_CHECK_FUNC(PyObject_CallFunction,
 +                    [with_python="yes"],
 +                    [with_python="no (Symbol 'PyObject_CallFunction' not found)"])
 +fi
 +
 +PATH="$SAVE_PATH"
 +CPPFLAGS="$SAVE_CPPFLAGS"
 +LDFLAGS="$SAVE_LDFLAGS"
 +LIBS="$SAVE_LIBS"
 +
 +if test "x$with_python" = "xyes"
 +then
 +      BUILD_WITH_PYTHON_CPPFLAGS="-I$python_include_path"
 +      BUILD_WITH_PYTHON_LDFLAGS="-L$python_library_path"
 +      BUILD_WITH_PYTHON_LIBS="$python_library_flags"
 +      AC_SUBST(BUILD_WITH_PYTHON_CPPFLAGS)
 +      AC_SUBST(BUILD_WITH_PYTHON_LDFLAGS)
 +      AC_SUBST(BUILD_WITH_PYTHON_LIBS)
 +fi
 +# }}} --with-python
 +
 +# --with-librouteros {{{
 +AC_ARG_WITH(librouteros, [AS_HELP_STRING([--with-librouteros@<:@=PREFIX@:>@], [Path to librouteros.])],
 +[
 + if test "x$withval" = "xyes"
 + then
 +       with_librouteros="yes"
 + else if test "x$withval" = "xno"
 + then
 +       with_librouteros="no"
 + else
 +       with_librouteros="yes"
 +       LIBROUTEROS_CPPFLAGS="$LIBROUTEROS_CPPFLAGS -I$withval/include"
 +       LIBROUTEROS_LDFLAGS="$LIBROUTEROS_LDFLAGS -L$withval/lib"
 + fi; fi
 +],
 +[with_librouteros="yes"])
 +
 +SAVE_CPPFLAGS="$CPPFLAGS"
 +SAVE_LDFLAGS="$LDFLAGS"
 +
 +CPPFLAGS="$CPPFLAGS $LIBROUTEROS_CPPFLAGS"
 +LDFLAGS="$LDFLAGS $LIBROUTEROS_LDFLAGS"
 +
 +if test "x$with_librouteros" = "xyes"
 +then
 +      if test "x$LIBROUTEROS_CPPFLAGS" != "x"
 +      then
 +              AC_MSG_NOTICE([librouteros CPPFLAGS: $LIBROUTEROS_CPPFLAGS])
 +      fi
 +      AC_CHECK_HEADERS(routeros_api.h,
 +      [with_librouteros="yes"],
 +      [with_librouteros="no ('routeros_api.h' not found)"])
 +fi
 +if test "x$with_librouteros" = "xyes"
 +then
 +      if test "x$LIBROUTEROS_LDFLAGS" != "x"
 +      then
 +              AC_MSG_NOTICE([librouteros LDFLAGS: $LIBROUTEROS_LDFLAGS])
 +      fi
 +      AC_CHECK_LIB(routeros, ros_interface,
 +      [with_librouteros="yes"],
 +      [with_librouteros="no (symbol 'ros_interface' not found)"])
 +fi
 +
 +CPPFLAGS="$SAVE_CPPFLAGS"
 +LDFLAGS="$SAVE_LDFLAGS"
 +
 +if test "x$with_librouteros" = "xyes"
 +then
 +      BUILD_WITH_LIBROUTEROS_CPPFLAGS="$LIBROUTEROS_CPPFLAGS"
 +      BUILD_WITH_LIBROUTEROS_LDFLAGS="$LIBROUTEROS_LDFLAGS"
 +      AC_SUBST(BUILD_WITH_LIBROUTEROS_CPPFLAGS)
 +      AC_SUBST(BUILD_WITH_LIBROUTEROS_LDFLAGS)
 +fi
 +AM_CONDITIONAL(BUILD_WITH_LIBROUTEROS, test "x$with_librouteros" = "xyes")
 +# }}}
 +
  # --with-librrd {{{
  # AC_ARG_WITH (package, help-string, [action-if-given], [action-if-not-given])
  librrd_cflags=""
@@@ -3786,7 -3510,6 +3817,7 @@@ plugin_ascent="no
  plugin_battery="no"
  plugin_bind="no"
  plugin_conntrack="no"
 +plugin_contextswitch="no"
  plugin_cpu="no"
  plugin_cpufreq="no"
  plugin_curl_json="no"
@@@ -3824,7 -3547,6 +3855,7 @@@ if test "x$ac_system" = "xLinux
  then
        plugin_battery="yes"
        plugin_conntrack="yes"
 +      plugin_contextswitch="yes"
        plugin_cpu="yes"
        plugin_cpufreq="yes"
        plugin_disk="yes"
        plugin_disk="yes"
  fi
  
 +# AIX
 +if test "x$with_perfstat" = "xyes"
 +then
 +      plugin_cpu="yes"
 +      plugin_disk="yes"
 +      plugin_memory="yes"
 +      plugin_swap="yes"
 +      plugin_interface="yes"
 +      plugin_load="yes"
 +fi
 +
 +if test "x$with_procinfo" = "xyes"
 +then
 +      plugin_processes="yes"
 +fi
 +
  # Solaris
  if test "x$with_kstat" = "xyes"
  then
@@@ -4076,7 -3782,6 +4107,7 @@@ AC_PLUGIN([ascent],      [$plugin_ascen
  AC_PLUGIN([battery],     [$plugin_battery],    [Battery statistics])
  AC_PLUGIN([bind],        [$plugin_bind],       [ISC Bind nameserver statistics])
  AC_PLUGIN([conntrack],   [$plugin_conntrack],  [nf_conntrack statistics])
 +AC_PLUGIN([contextswitch], [$plugin_contextswitch], [context switch statistics])
  AC_PLUGIN([cpufreq],     [$plugin_cpufreq],    [CPU frequency statistics])
  AC_PLUGIN([cpu],         [$plugin_cpu],        [CPU usage statistics])
  AC_PLUGIN([csv],         [yes],                [CSV output plugin])
@@@ -4104,7 -3809,6 +4135,7 @@@ AC_PLUGIN([load],        [$plugin_load]
  AC_PLUGIN([logfile],     [yes],                [File logging plugin])
  AC_PLUGIN([madwifi],     [$have_linux_wireless_h], [Madwifi wireless statistics])
  AC_PLUGIN([match_empty_counter], [yes],        [The empty counter match])
 +AC_PLUGIN([match_hashed], [yes],               [The hashed match])
  AC_PLUGIN([match_regex], [yes],                [The regex match])
  AC_PLUGIN([match_timediff], [yes],             [The timediff match])
  AC_PLUGIN([match_value], [yes],                [The value match])
@@@ -4114,7 -3818,6 +4145,7 @@@ AC_PLUGIN([memcached],   [yes]
  AC_PLUGIN([memory],      [$plugin_memory],     [Memory usage])
  AC_PLUGIN([multimeter],  [$plugin_multimeter], [Read multimeter values])
  AC_PLUGIN([mysql],       [$with_libmysql],     [MySQL statistics])
 +AC_PLUGIN([netapp],      [$with_libnetapp],    [NetApp plugin])
  AC_PLUGIN([netlink],     [$with_libnetlink],   [Enhanced Linux network statistics])
  AC_PLUGIN([network],     [yes],                [Network communication plugin])
  AC_PLUGIN([nfs],         [$plugin_nfs],        [NFS statistics])
@@@ -4133,8 -3836,6 +4164,8 @@@ AC_PLUGIN([postgresql],  [$with_libpq]
  AC_PLUGIN([powerdns],    [yes],                [PowerDNS statistics])
  AC_PLUGIN([processes],   [$plugin_processes],  [Process statistics])
  AC_PLUGIN([protocols],   [$plugin_protocols],  [Protocol (IP, TCP, ...) statistics])
 +AC_PLUGIN([python],      [$with_python],       [Embed a Python interpreter])
 +AC_PLUGIN([routeros],    [$with_librouteros],  [RouterOS plugin])
  AC_PLUGIN([rrdcached],   [$librrd_rrdc_update], [RRDTool output plugin])
  AC_PLUGIN([rrdtool],     [$with_librrd],       [RRDTool output plugin])
  AC_PLUGIN([sensors],     [$with_libsensors],   [lm_sensors statistics])
@@@ -4147,7 -3848,6 +4178,7 @@@ AC_PLUGIN([tail],        [yes]
  AC_PLUGIN([tape],        [$plugin_tape],       [Tape drive statistics])
  AC_PLUGIN([target_notification], [yes],        [The notification target])
  AC_PLUGIN([target_replace], [yes],             [The replace target])
 +AC_PLUGIN([target_scale],[yes],                [The scale target])
  AC_PLUGIN([target_set],  [yes],                [The set target])
  AC_PLUGIN([tcpconns],    [$plugin_tcpconns],   [TCP connection statistics])
  AC_PLUGIN([teamspeak2],  [yes],                [TeamSpeak2 server statistics])
@@@ -4346,7 -4046,6 +4377,7 @@@ Configuration
      libkvm  . . . . . . . $with_libkvm
      libmemcached  . . . . $with_libmemcached
      libmysql  . . . . . . $with_libmysql
 +    libnetapp . . . . . . $with_libnetapp
      libnetlink  . . . . . $with_libnetlink
      libnetsnmp  . . . . . $with_libnetsnmp
      libnotify . . . . . . $with_libnotify
      libopenipmi . . . . . $with_libopenipmipthread
      liboping  . . . . . . $with_liboping
      libpcap . . . . . . . $with_libpcap
 +    libperfstat . . . . . $with_perfstat
      libperl . . . . . . . $with_libperl
      libpq . . . . . . . . $with_libpq
      libpthread  . . . . . $with_libpthread
 +    librouteros . . . . . $with_librouteros
      librrd  . . . . . . . $with_librrd
      libsensors  . . . . . $with_libsensors
      libstatgrab . . . . . $with_libstatgrab
      libxmms . . . . . . . $with_libxmms
      libyajl . . . . . . . $with_libyajl
      oracle  . . . . . . . $with_oracle
 +    python  . . . . . . . $with_python
  
    Features:
      daemon mode . . . . . $enable_daemon
      battery . . . . . . . $enable_battery
      bind  . . . . . . . . $enable_bind
      conntrack . . . . . . $enable_conntrack
 +    contextswitch . . . . $enable_contextswitch
      cpu . . . . . . . . . $enable_cpu
      cpufreq . . . . . . . $enable_cpufreq
      csv . . . . . . . . . $enable_csv
      logfile . . . . . . . $enable_logfile
      madwifi . . . . . . . $enable_madwifi
      match_empty_counter . $enable_match_empty_counter
 +    match_hashed  . . . . $enable_match_hashed
      match_regex . . . . . $enable_match_regex
      match_timediff  . . . $enable_match_timediff
      match_value . . . . . $enable_match_value
      memory  . . . . . . . $enable_memory
      multimeter  . . . . . $enable_multimeter
      mysql . . . . . . . . $enable_mysql
 +    netapp  . . . . . . . $enable_netapp
      netlink . . . . . . . $enable_netlink
      network . . . . . . . $enable_network
      nfs . . . . . . . . . $enable_nfs
      powerdns  . . . . . . $enable_powerdns
      processes . . . . . . $enable_processes
      protocols . . . . . . $enable_protocols
 +    python  . . . . . . . $enable_python
 +    routeros  . . . . . . $enable_routeros
      rrdcached . . . . . . $enable_rrdcached
      rrdtool . . . . . . . $enable_rrdtool
      sensors . . . . . . . $enable_sensors
      tape  . . . . . . . . $enable_tape
      target_notification . $enable_target_notification
      target_replace  . . . $enable_target_replace
 +    target_scale  . . . . $enable_target_scale
      target_set  . . . . . $enable_target_set
      tcpconns  . . . . . . $enable_tcpconns
      teamspeak2  . . . . . $enable_teamspeak2
diff --combined src/apache.c
@@@ -202,7 -202,7 +202,7 @@@ static int config_set_boolean (int *ret
                return (-1);
        }
  
 -      if (ci->values[0].type != OCONFIG_TYPE_BOOLEAN)
 +      if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
        {
                if (ci->values[0].value.boolean)
                        *ret_boolean = 1;
        else /* if (ci->values[0].type != OCONFIG_TYPE_STRING) */
        {
                char *string = ci->values[0].value.string;
 -              if ((strcasecmp ("true", string) == 0)
 -                              || (strcasecmp ("yes", string) == 0)
 -                              || (strcasecmp ("on", string) == 0))
 +              if (IS_TRUE (string))
                        *ret_boolean = 1;
 -              else if ((strcasecmp ("false", string) == 0)
 -                              || (strcasecmp ("no", string) == 0)
 -                              || (strcasecmp ("off", string) == 0))
 +              else if (IS_FALSE (string))
                        *ret_boolean = 0;
                else
                {
@@@ -685,7 -689,8 +685,8 @@@ static int apache_read_host (user_data_
                {
                        if (strcmp (fields[0], "Scoreboard:") == 0)
                                submit_scoreboard (fields[1], st);
-                       else if (strcmp (fields[0], "BusyServers:") == 0)
+                       else if ((strcmp (fields[0], "BusyServers:") == 0) /* Apache 1.* */
+                                       || (strcmp (fields[0], "BusyWorkers:") == 0) /* Apache 2.* */)
                                submit_gauge ("apache_connections", NULL, atol (fields[1]), st);
                }
        }
diff --combined src/collectd.conf.in
@@@ -57,7 -57,6 +57,7 @@@ FQDNLookup   tru
  #@BUILD_PLUGIN_BATTERY_TRUE@LoadPlugin battery
  #@BUILD_PLUGIN_BIND_TRUE@LoadPlugin bind
  #@BUILD_PLUGIN_CONNTRACK_TRUE@LoadPlugin conntrack
 +#@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@LoadPlugin contextswitch
  @BUILD_PLUGIN_CPU_TRUE@@BUILD_PLUGIN_CPU_TRUE@LoadPlugin cpu
  #@BUILD_PLUGIN_CPUFREQ_TRUE@LoadPlugin cpufreq
  @LOAD_PLUGIN_CSV@LoadPlugin csv
@@@ -89,7 -88,6 +89,7 @@@
  @BUILD_PLUGIN_MEMORY_TRUE@@BUILD_PLUGIN_MEMORY_TRUE@LoadPlugin memory
  #@BUILD_PLUGIN_MULTIMETER_TRUE@LoadPlugin multimeter
  #@BUILD_PLUGIN_MYSQL_TRUE@LoadPlugin mysql
 +#@BUILD_PLUGIN_NETAPP_TRUE@LoadPlugin netapp
  #@BUILD_PLUGIN_NETLINK_TRUE@LoadPlugin netlink
  @LOAD_PLUGIN_NETWORK@LoadPlugin network
  #@BUILD_PLUGIN_NFS_TRUE@LoadPlugin nfs
  #@BUILD_PLUGIN_POWERDNS_TRUE@LoadPlugin powerdns
  #@BUILD_PLUGIN_PROCESSES_TRUE@LoadPlugin processes
  #@BUILD_PLUGIN_PROTOCOLS_TRUE@LoadPlugin protocols
 +#@BUILD_PLUGIN_PYTHON_TRUE@LoadPlugin python
 +#@BUILD_PLUGIN_ROUTEROS_TRUE@LoadPlugin routeros
  #@BUILD_PLUGIN_RRDCACHED_TRUE@LoadPlugin rrdcached
  @LOAD_PLUGIN_RRDTOOL@LoadPlugin rrdtool
  #@BUILD_PLUGIN_SENSORS_TRUE@LoadPlugin sensors
  #    URL "http://finance.google.com/finance?q=NYSE%3AAMD"
  #    User "foo"
  #    Password "bar"
 +#    MeasureResponseTime false
  #    <Match>
  #      Regex "<span +class=\"pr\"[^>]*> *([0-9]*\\.[0-9]+) *</span>"
  #      DSType "GaugeAverage"
  #     FSType "ext3"
  #     IgnoreSelected false
  #     ReportByDevice false
 +#     ReportReserved false
 +#     ReportInodes false
  #</Plugin>
  
  #<Plugin disk>
  
  #<Plugin "java">
  #     JVMArg "-verbose:jni"
- #     JVMArg "-Djava.class.path=@prefix@/share/collectd/java"
+ #     JVMArg "-Djava.class.path=@prefix@/share/collectd/java/collectd-api.jar"
  #
  #     LoadPlugin "org.collectd.java.Foobar"
  #     <Plugin "org.collectd.java.Foobar">
  #     </Database>
  #</Plugin>
  
 +#<Plugin netapp>
 +#     <Host "netapp1.example.com">
 +#             Protocol      "https"
 +#             Address       "10.0.0.1"
 +#             Port          443
 +#             User          "username"
 +#             Password      "aef4Aebe"
 +#             Interval      30
 +#
 +#             <WAFL>
 +#                     Interval 30
 +#                     GetNameCache   true
 +#                     GetDirCache    true
 +#                     GetBufferCache true
 +#                     GetInodeCache  true
 +#             </WAFL>
 +#
 +#             <Disks>
 +#                     Interval 30
 +#                     GetBusy true
 +#             </Disks>
 +#
 +#             <VolumePerf>
 +#                     Interval 30
 +#                     GetIO      "volume0"
 +#                     IgnoreSelectedIO      false
 +#                     GetOps     "volume0"
 +#                     IgnoreSelectedOps     false
 +#                     GetLatency "volume0"
 +#                     IgnoreSelectedLatency false
 +#             </VolumePerf>
 +#
 +#             <VolumeUsage>
 +#                     Interval 30
 +#                     GetCapacity "vol0"
 +#                     GetCapacity "vol1"
 +#                     IgnoreSelectedCapacity false
 +#                     GetSnapshot "vol1"
 +#                     GetSnapshot "vol3"
 +#                     IgnoreSelectedSnapshot false
 +#             </VolumeUsage>
 +#
 +#             <System>
 +#                     Interval 30
 +#                     GetCPULoad     true
 +#                     GetInterfaces  true
 +#                     GetDiskOps     true
 +#                     GetDiskIO      true
 +#             </System>
 +#     </Host>
 +#</Plugin>
 +
  #<Plugin netlink>
  #     Interface "All"
  #     VerboseInterface "All"
  #     TimeToLive "128"
  #     Forward false
  #     CacheFlush 1800
 +#     ReportStats false
  @LOAD_PLUGIN_NETWORK@</Plugin>
  
  #<Plugin nginx>
  #     IncludeDir "/my/include/path"
  #     BaseName "Collectd::Plugin"
  #     EnableDebugger ""
 -#     LoadPlugin foo
 +#     LoadPlugin Monitorus
 +#     LoadPlugin OpenVZ
  #
  #     <Plugin foo>
  #             Foo "Bar"
  
  #<Plugin ping>
  #     Host "host.foo.bar"
 +#     Interval 1.0
 +#     Timeout 0.9
  #     TTL 255
 +#     SourceAddress "1.2.3.4"
 +#     Device "eth0"
 +#     MaxMissed -1
  #</Plugin>
  
  #<Plugin postgresql>
  #     IgnoreSelected false
  #</Plugin>
  
 +#<Plugin python>
 +#     ModulePath "/path/to/your/python/modules"
 +#     LogTraces true
 +#     Interactive true
 +#     Import "spam"
 +#
 +#     <Module spam>
 +#             spam "wonderful" "lovely"
 +#     </Module>
 +#</Plugin>
 +
 +#<Plugin routeros>
 +#     <Router>
 +#             Host "router.example.com"
 +#             Port "8728"
 +#             User "admin"
 +#             Password "dozaiTh4"
 +#             CollectInterface true
 +#             CollectRegistrationTable true
 +#     </Router>
 +#</Plugin>
 +
  #<Plugin rrdcached>
  #     DaemonAddress "unix:/tmp/rrdcached.sock"
  #     DataDir "@prefix@/var/lib/@PACKAGE_NAME@/rrd"
  
  # Load required matches:
  #@BUILD_PLUGIN_MATCH_EMPTY_COUNTER_TRUE@LoadPlugin match_empty_counter
 +#@BUILD_PLUGIN_MATCH_HASHED_TRUE@LoadPlugin match_hashed
  #@BUILD_PLUGIN_MATCH_REGEX_TRUE@LoadPlugin match_regex
  #@BUILD_PLUGIN_MATCH_VALUE_TRUE@LoadPlugin match_value
  #@BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE@LoadPlugin match_timediff
  # Load required targets:
  #@BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE@LoadPlugin target_notification
  #@BUILD_PLUGIN_TARGET_REPLACE_TRUE@LoadPlugin target_replace
 +#@BUILD_PLUGIN_TARGET_SCALE_TRUE@LoadPlugin target_scale
  #@BUILD_PLUGIN_TARGET_SET_TRUE@LoadPlugin target_set
  
  #----------------------------------------------------------------------------#
diff --combined src/collectd.conf.pod
@@@ -112,7 -112,7 +112,7 @@@ a value higher than the number of plugi
  =item B<Hostname> I<Name>
  
  Sets the hostname that identifies a host. If you omit this setting, the
- hostname will be determinded using the L<gethostname(2)> system call.
+ hostname will be determined using the L<gethostname(2)> system call.
  
  =item B<FQDNLookup> B<true|false>
  
@@@ -443,7 -443,7 +443,7 @@@ The curl plugin uses the B<libcurl> (L<
  and the match infrastructure (the same code used by the tail plugin) to use
  regular expressions with the received data.
  
- The following example will read the current value of AMD stock from google's
+ The following example will read the current value of AMD stock from Google's
  finance page and dispatch the value to collectd.
  
    <Plugin curl>
@@@ -501,18 -501,12 +501,18 @@@ File that holds one or more SSL certifi
  possibly need this option. What CA certificates come bundled with C<libcurl>
  and are checked by default depends on the distribution you use.
  
 +=item B<MeasureResponseTime> B<true>|B<false>
 +
 +Measure response time for the request. If this setting is enabled, B<Match>
 +blocks (see below) are optional. Disabled by default.
 +
  =item B<E<lt>MatchE<gt>>
  
  One or more B<Match> blocks that define how to match information in the data
  returned by C<libcurl>. The C<curl> plugin uses the same infrastructure that's
  used by the C<tail> plugin, so please see the documentation of the C<tail>
 -plugin below on how matches are defined.
 +plugin below on how matches are defined. If the B<MeasureResponseTime> option
 +is set to B<true>, B<Match> blocks are optional.
  
  =back
  
@@@ -872,44 -866,19 +872,44 @@@ Select partitions based on the mountpoi
  
  Select partitions based on the filesystem type.
  
 -=item B<IgnoreSelected> I<true>|I<false>
 +=item B<IgnoreSelected> B<true>|B<false>
  
  Invert the selection: If set to true, all partitions B<except> the ones that
  match any one of the criteria are collected. By default only selected
  partitions are collected if a selection is made. If no selection is configured
  at all, B<all> partitions are selected.
  
 -=item B<ReportByDevice> I<true>|I<false>
 +=item B<ReportByDevice> B<true>|B<false>
  
  Report using the device name rather than the mountpoint. i.e. with this I<false>,
  (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
 +inode collection being disabled.
 +
 +Enable this option if inodes are a scarce resource for you, usually because
 +many small files are stored on the disk. This is a usual scenario for mail
 +transfer agents and web caches.
 +
  =back
  
  =head2 Plugin C<disk>
@@@ -952,7 -921,7 +952,7 @@@ is set to B<true>, all disks are collec
  
  =item B<Interface> I<Interface>
  
- The dns plugin uses B<libpcap> to capture dns traffic and analyses it. This
+ The dns plugin uses B<libpcap> to capture dns traffic and analyzes it. This
  option sets the interface that should be used. If this option is not set, or
  set to "any", the plugin will try to get packets from B<all> interfaces. This
  may not work on certain platforms, such as MacE<nbsp>OSE<nbsp>X.
@@@ -1671,463 -1640,6 +1671,463 @@@ or SQL threads are not running
  
  =back
  
 +=head2 Plugin C<netapp>
 +
 +The netapp plugin can collect various performance and capacity information
 +from a NetApp filer using the NetApp API.
 +
 +Please note that NetApp has a wide line of products and a lot of different
 +software versions for each of these products. This plugin was developed for a
 +NetApp FAS3040 running OnTap 7.2.3P8 and tested on FAS2050 7.3.1.1L1,
 +FAS3140 7.2.5.1 and FAS3020 7.2.4P9. It I<should> work for most combinations of
 +model and software version but it is very hard to test this.
 +If you have used this plugin with other models and/or software version, feel
 +free to send us a mail to tell us about the results, even if it's just a short
 +"It works".
 +
 +To collect these data collectd will log in to the NetApp via HTTP(S) and HTTP
 +basic authentication.
 +
 +B<Do not use a regular user for this!> Create a special collectd user with just
 +the minimum of capabilities needed. The user only needs the "login-http-admin"
 +capability as well as a few more depending on which data will be collected.
 +Required capabilities are documented below.
 +
 +=head3 Synopsis
 +
 + <Plugin "netapp">
 +   <Host "netapp1.example.com">
 +    Protocol      "https"
 +    Address       "10.0.0.1"
 +    Port          443
 +    User          "username"
 +    Password      "aef4Aebe"
 +    Interval      30
 +    
 +    <WAFL>
 +      Interval 30
 +      GetNameCache   true
 +      GetDirCache    true
 +      GetBufferCache true
 +      GetInodeCache  true
 +    </WAFL>
 +    
 +    <Disks>
 +      Interval 30
 +      GetBusy true
 +    </Disks>
 +    
 +    <VolumePerf>
 +      Interval 30
 +      GetIO      "volume0"
 +      IgnoreSelectedIO      false
 +      GetOps     "volume0"
 +      IgnoreSelectedOps     false
 +      GetLatency "volume0"
 +      IgnoreSelectedLatency false
 +    </VolumePerf>
 +    
 +    <VolumeUsage>
 +      Interval 30
 +      GetCapacity "vol0"
 +      GetCapacity "vol1"
 +      IgnoreSelectedCapacity false
 +      GetSnapshot "vol1"
 +      GetSnapshot "vol3"
 +      IgnoreSelectedSnapshot false
 +    </VolumeUsage>
 +    
 +    <System>
 +      Interval 30
 +      GetCPULoad     true
 +      GetInterfaces  true
 +      GetDiskOps     true
 +      GetDiskIO      true
 +    </System>
 +   </Host>
 + </Plugin>
 +
 +The netapp plugin accepts the following configuration options:
 +
 +=over 4
 +
 +=item B<Host> I<Name>
 +
 +A host block defines one NetApp filer. It will appear in collectd with the name
 +you specify here which does not have to be its real name nor its hostname.
 +
 +=item B<Protocol> B<httpd>|B<http>
 +
 +The protocol collectd will use to query this host.
 +
 +Optional
 +
 +Type: string
 +
 +Default: https
 +
 +Valid options: http, https
 +
 +=item B<Address> I<Address>
 +
 +The hostname or IP address of the host.
 +
 +Optional
 +
 +Type: string
 +
 +Default: The "host" block's name.
 +
 +=item B<Port> I<Port>
 +
 +The TCP port to connect to on the host.
 +
 +Optional
 +
 +Type: integer
 +
 +Default: 80 for protocol "http", 443 for protocol "https"
 +
 +=item B<User> I<User>
 +
 +=item B<Password> I<Password>
 +
 +The username and password to use to login to the NetApp.
 +
 +Mandatory
 +
 +Type: string
 +
 +=item B<Interval> I<Interval>
 +
 +B<TODO>
 +
 +=back
 +
 +The following options decide what kind of data will be collected. You can
 +either use them as a block and fine tune various parameters inside this block,
 +use them as a single statement to just accept all default values, or omit it to
 +not collect any data.
 +
 +The following options are valid inside all blocks:
 +
 +=over 4
 +
 +=item B<Interval> I<Seconds>
 +
 +Collect the respective statistics every I<Seconds> seconds. Defaults to the
 +host specific setting.
 +
 +=back
 +
 +=head3 The System block
 +
 +This will collect various performance data about the whole system.
 +
 +B<Note:> To get this data the collectd user needs the
 +"api-perf-object-get-instances" capability.
 +
 +=over 4
 +
 +=item B<Interval> I<Seconds>
 +
 +Collect disk statistics every I<Seconds> seconds.
 +
 +=item B<GetCPULoad> B<true>|B<false>
 +
 +If you set this option to true the current CPU usage will be read. This will be
 +the average usage between all CPUs in your NetApp without any information about
 +individual CPUs.
 +
 +B<Note:> These are the same values that the NetApp CLI command "sysstat"
 +returns in the "CPU" field.
 +
 +Optional
 +
 +Type: boolean
 +
 +Default: true
 +
 +Result: Two value lists of type "cpu", and type instances "idle" and "system".
 +
 +=item B<GetInterfaces> B<true>|B<false>
 +
 +If you set this option to true the current traffic of the network interfaces
 +will be read. This will be the total traffic over all interfaces of your NetApp
 +without any information about individual interfaces.
 +
 +B<Note:> This is the same values that the NetApp CLI command "sysstat" returns
 +in the "Net kB/s" field.
 +
 +B<Or is it?>
 +
 +Optional
 +
 +Type: boolean
 +
 +Default: true
 +
 +Result: One value list of type "if_octects".
 +
 +=item B<GetDiskIO> B<true>|B<false>
 +
 +If you set this option to true the current IO throughput will be read. This
 +will be the total IO of your NetApp without any information about individual
 +disks, volumes or aggregates.
 +
 +B<Note:> This is the same values that the NetApp CLI command "sysstat" returns
 +in the "DiskE<nbsp>kB/s" field.
 +
 +Optional
 +
 +Type: boolean
 +
 +Default: true
 +
 +Result: One value list of type "disk_octets".
 +
 +=item B<GetDiskOps> B<true>|B<false>
 +
 +If you set this option to true the current number of HTTP, NFS, CIFS, FCP,
 +iSCSI, etc. operations will be read. This will be the total number of
 +operations on your NetApp without any information about individual volumes or
 +aggregates.
 +
 +B<Note:> These are the same values that the NetApp CLI command "sysstat"
 +returns in the "NFS", "CIFS", "HTTP", "FCP" and "iSCSI" fields.
 +
 +Optional
 +
 +Type: boolean
 +
 +Default: true
 +
 +Result: A variable number of value lists of type "disk_ops_complex". Each type
 +of operation will result in one value list with the name of the operation as
 +type instance.
 +
 +=back
 +
 +=head3 The WAFL block
 +
 +This will collect various performance data about the WAFL file system. At the
 +moment this just means cache performance.
 +
 +B<Note:> To get this data the collectd user needs the
 +"api-perf-object-get-instances" capability.
 +
 +B<Note:> The interface to get these values is classified as "Diagnostics" by
 +NetApp. This means that it is not guaranteed to be stable even between minor
 +releases.
 +
 +=over 4
 +
 +=item B<Interval> I<Seconds>
 +
 +Collect disk statistics every I<Seconds> seconds.
 +
 +=item B<GetNameCache> B<true>|B<false>
 +
 +Optional
 +
 +Type: boolean
 +
 +Default: true
 +
 +Result: One value list of type "cache_ratio" and type instance
 +"name_cache_hit".
 +
 +=item B<GetDirCache> B<true>|B<false>
 +
 +Optional
 +
 +Type: boolean
 +
 +Default: true
 +
 +Result: One value list of type "cache_ratio" and type instance "find_dir_hit".
 +
 +=item B<GetInodeCache> B<true>|B<false>
 +
 +Optional
 +
 +Type: boolean
 +
 +Default: true
 +
 +Result: One value list of type "cache_ratio" and type instance
 +"inode_cache_hit".
 +
 +=item B<GetBufferCache> B<true>|B<false>
 +
 +B<Note:> This is the same value that the NetApp CLI command "sysstat" returns
 +in the "Cache hit" field.
 +
 +Optional
 +
 +Type: boolean
 +
 +Default: true
 +
 +Result: One value list of type "cache_ratio" and type instance "buf_hash_hit".
 +
 +=back
 +
 +=head3 The Disks block
 +
 +This will collect performance data about the individual disks in the NetApp.
 +
 +B<Note:> To get this data the collectd user needs the
 +"api-perf-object-get-instances" capability.
 +
 +=over 4
 +
 +=item B<Interval> I<Seconds>
 +
 +Collect disk statistics every I<Seconds> seconds.
 +
 +=item B<GetBusy> B<true>|B<false>
 +
 +If you set this option to true the busy time of all disks will be calculated
 +and the value of the busiest disk in the system will be written.
 +
 +B<Note:> This is the same values that the NetApp CLI command "sysstat" returns
 +in the "Disk util" field. Probably.
 +
 +Optional
 +
 +Type: boolean
 +
 +Default: true
 +
 +Result: One value list of type "percent" and type instance "disk_busy".
 +
 +=back
 +
 +=head3 The VolumePerf block
 +
 +This will collect various performance data about the individual volumes.
 +
 +You can select which data to collect about which volume using the following
 +options. They follow the standard ignorelist semantic.
 +
 +B<Note:> To get this data the collectd user needs the
 +I<api-perf-object-get-instances> capability.
 +
 +=over 4
 +
 +=item B<Interval> I<Seconds>
 +
 +Collect volume performance data every I<Seconds> seconds.
 +
 +=item B<GetIO> I<Volume>
 +
 +=item B<GetOps> I<Volume>
 +
 +=item B<GetLatency> I<Volume>
 +
 +Select the given volume for IO, operations or latency statistics collection.
 +The argument is the name of the volume without the C</vol/> prefix.
 +
 +Since the standard ignorelist functionality is used here, you can use a string
 +starting and ending with a slash to specify regular expression matching: To
 +match the volumes "vol0", "vol2" and "vol7", you can use this regular
 +expression:
 +
 +  GetIO "/^vol[027]$/"
 +
 +If no regular expression is specified, an exact match is required. Both,
 +regular and exact matching are case sensitive.
 +
 +If no volume was specified at all for either of the three options, that data
 +will be collected for all available volumes.
 +
 +=item B<IgnoreSelectedIO> B<true>|B<false>
 +
 +=item B<IgnoreSelectedOps> B<true>|B<false>
 +
 +=item B<IgnoreSelectedLatency> B<true>|B<false>
 +
 +When set to B<true>, the volumes selected for IO, operations or latency
 +statistics collection will be ignored and the data will be collected for all
 +other volumes.
 +
 +When set to B<false>, data will only be collected for the specified volumes and
 +all other volumes will be ignored.
 +
 +If no volumes have been specified with the above B<Get*> options, all volumes
 +will be collected regardless of the B<IgnoreSelected*> option.
 +
 +Defaults to B<false>
 +
 +=back
 +
 +=head3 The VolumeUsage block
 +
 +This will collect capacity data about the individual volumes.
 +
 +B<Note:> To get this data the collectd user needs the I<api-volume-list-info>
 +capability.
 +
 +=over 4
 +
 +=item B<Interval> I<Seconds>
 +
 +Collect volume usage statistics every I<Seconds> seconds.
 +
 +=item B<GetCapacity> I<VolumeName>
 +
 +The current capacity of the volume will be collected. This will result in two
 +to four value lists, depending on the configuration of the volume. All data
 +sources are of type "df_complex" with the name of the volume as
 +plugin_instance.
 +
 +There will be type_instances "used" and "free" for the number of used and
 +available bytes on the volume.  If the volume has some space reserved for
 +snapshots, a type_instance "snap_reserved" will be available.  If the volume
 +has SIS enabled, a type_instance "sis_saved" will be available. This is the
 +number of bytes saved by the SIS feature.
 +
 +B<Note:> The current NetApp API has a bug that results in this value being
 +reported as a 32E<nbsp>bit number. This plugin tries to guess the correct
 +number which works most of the time.  If you see strange values here, bug
 +NetApp support to fix this.
 +
 +Repeat this option to specify multiple volumes.
 +
 +=item B<IgnoreSelectedCapacity> B<true>|B<false>
 +
 +Specify whether to collect only the volumes selected by the B<GetCapacity>
 +option or to ignore those volumes. B<IgnoreSelectedCapacity> defaults to
 +B<false>. However, if no B<GetCapacity> option is specified at all, all
 +capacities will be selected anyway.
 +
 +=item B<GetSnapshot> I<VolumeName>
 +
 +Select volumes from which to collect snapshot information.
 +
 +Usually, the space used for snapshots is included in the space reported as
 +"used". If snapshot information is collected as well, the space used for
 +snapshots is subtracted from the used space.
 +
 +To make things even more interesting, it is possible to reserve space to be
 +used for snapshots. If the space required for snapshots is less than that
 +reserved space, there is "reserved free" and "reserved used" space in addition
 +to "free" and "used". If the space required for snapshots exceeds the reserved
 +space, that part allocated in the normal space is subtracted from the "used"
 +space again.
 +
 +Repeat this option to specify multiple volumes.
 +
 +=item B<IgnoreSelectedSnapshot>
 +
 +Specify whether to collect only the volumes selected by the B<GetSnapshot>
 +option or to ignore those volumes. B<IgnoreSelectedSnapshot> defaults to
 +B<false>. However, if no B<GetSnapshot> option is specified at all, all
 +capacities will be selected anyway.
 +
 +=back
 +
  =head2 Plugin C<netlink>
  
  The C<netlink> plugin uses a netlink socket to query the Linux kernel about
@@@ -2197,7 -1709,7 +2197,7 @@@ Here are some examples to help you unde
  
  =item B<IgnoreSelected>
  
- The behaviour is the same as with all other similar plugins: If nothing is
+ The behavior is the same as with all other similar plugins: If nothing is
  selected at all, everything is collected. If some things are selected using the
  options described above, only these statistics are collected. If you set
  B<IgnoreSelected> to B<true>, this behavior is inverted, i.E<nbsp>e. the
@@@ -2209,7 -1721,7 +2209,7 @@@ specified statistics will not be collec
  
  The Network plugin sends data to a remote instance of collectd, receives data
  from a remote instance, or both at the same time. Data which has been received
- from the network is usually not transmitted again, but this can be actived, see
+ from the network is usually not transmitted again, but this can be activated, see
  the B<Forward> option below.
  
  The default IPv6 multicast group is C<ff18::efc0:4a42>. The default IPv4
@@@ -2352,14 -1864,6 +2352,14 @@@ normally doesn't do much, this value sh
  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
 +statistics about itself. Collected data included the number of received and
 +sent octets and packets, the length of the receive queue and the number of
 +values handled. When set to B<true>, the I<Network plugin> will make these
 +statistics available. Defaults to B<false>.
 +
  =back
  
  =head2 Plugin C<nginx>
@@@ -2503,7 -2007,7 +2503,7 @@@ UDP-Port to connect to. Defaults to B<1
  
  =item B<ReverseLookups> B<true>|B<false>
  
- Sets wether or not to perform reverse lookups on peers. Since the name or
+ Sets whether or not to perform reverse lookups on peers. Since the name or
  IP-address may be used in a filename it is recommended to disable reverse
  lookups. The default is to do reverse lookups to preserve backwards
  compatibility, though.
@@@ -2661,12 -2165,6 +2661,12 @@@ Available options
  
  Specifies the location of the status file.
  
 +=item B<Compression> B<true>|B<false>
 +
 +Sets whether or not statistics about the compression used by OpenVPN should be
 +collected. This information is only available in I<single> mode. Enabled by
 +default.
 +
  =back
  
  =head2 Plugin C<oracle>
@@@ -2776,24 -2274,6 +2776,24 @@@ Default: B<0.9
  
  Sets the Time-To-Live of generated ICMP packets.
  
 +=item B<SourceAddress> I<host>
 +
 +Sets the source address to use. I<host> may either be a numerical network
 +address or a network hostname.
 +
 +=item B<Device> I<name>
 +
 +Sets the outgoing network device to be used. I<name> has to specify an
 +interface name (e.E<nbsp>g. C<eth0>). This might not be supported by all
 +operating systems.
 +
 +=item B<MaxMissed> I<Packets>
 +
 +Trigger a DNS resolv after the host has not replied to I<Packets> packets. This
 +enables the use of dynamic DNS services (like dyndns.org) with the ping plugin.
 +
 +Default: B<-1> (disabled)
 +
  =back
  
  =head2 Plugin C<postgresql>
@@@ -3270,7 -2750,7 +3270,7 @@@ C<I<prefix>/var/run/collectd-powerdns>
  Select more detailed statistics of processes matching this name. The statistics
  collected for these selected processes are size of the resident segment size
  (RSS), user- and system-time used, number of processes and number of threads,
 -and minor and major pagefaults.
 +io data (where available) and minor and major pagefaults.
  
  =item B<ProcessMatch> I<name> I<regex>
  
@@@ -3316,71 -2796,6 +3316,71 @@@ matching values will be ignored
  
  =back
  
 +=head2 Plugin C<python>
 +
 +This plugin embeds a Python-interpreter into collectd and provides an interface
 +to collectd's plugin system. See L<collectd-python(5)> for its documentation.
 +
 +=head2 Plugin C<routeros>
 +
 +The C<routeros> plugin connects to a device running I<RouterOS>, the
 +Linux-based operating system for routers by I<MikroTik>. The plugin uses
 +I<librouteros> to connect and reads information about the interfaces and
 +wireless connections of the device. The configuration supports querying
 +multiple routers:
 +
 +  <Plugin "routeros">
 +    <Router>
 +      Host "router0.example.com"
 +      User "collectd"
 +      Password "secr3t"
 +      CollectInterface true
 +    </Router>
 +    <Router>
 +      Host "router1.example.com"
 +      User "collectd"
 +      Password "5ecret"
 +      CollectInterface true
 +      CollectRegistrationTable true
 +    </Router>
 +  </Plugin>
 +
 +As you can see above, the configuration of the I<routeros> plugin consists of
 +one or more B<E<lt>RouterE<gt>> blocks. Within each block, the following
 +options are understood:
 +
 +=over 4
 +
 +=item B<Host> I<Host>
 +
 +Hostname or IP-address of the router to connect to.
 +
 +=item B<Port> I<Port>
 +
 +Port name or port number used when connecting. If left unspecified, the default
 +will be chosen by I<librouteros>, currently "8728". This option expects a
 +string argument, even when a numeric port number is given.
 +
 +=item B<User> I<User>
 +
 +Use the user name I<User> to authenticate. Defaults to "admin".
 +
 +=item B<Password> I<Password>
 +
 +Set the password used to authenticate.
 +
 +=item B<CollectInterface> B<true>|B<false>
 +
 +When set to B<true>, interface statistics will be collected for all interfaces
 +present on the device. Defaults to B<false>.
 +
 +=item B<CollectRegistrationTable> B<true>|B<false>
 +
 +When set to B<true>, information about wireless LAN connections will be
 +collected. Defaults to B<false>.
 +
 +=back
 +
  =head2 Plugin C<rrdcached>
  
  The C<rrdcached> plugin uses the RRDtool accelerator daemon, L<rrdcached(1)>,
@@@ -4740,77 -4155,6 +4740,77 @@@ time. If the counter is reset for some 
  usually), the graph will be empty (NAN) for a long time. People may not
  understand why.
  
 +=item B<hashed>
 +
 +Calculates a hash value of the host name and matches values according to that
 +hash value. This makes it possible to divide all hosts into groups and match
 +only values that are in a specific group. The intended use is in load
 +balancing, where you want to handle only part of all data and leave the rest
 +for other servers.
 +
 +The hashing function used tries to distribute the hosts evenly. First, it
 +calculates a 32E<nbsp>bit hash value using the characters of the hostname:
 +
 +  hash_value = 0;
 +  for (i = 0; host[i] != 0; i++)
 +    hash_value = (hash_value * 251) + host[i];
 +
 +The constant 251 is a prime number which is supposed to make this hash value
 +more random. The code then checks the group for this host according to the
 +I<Total> and I<Match> arguments:
 +
 +  if ((hash_value % Total) == Match)
 +    matches;
 +  else
 +    does not match;
 +
 +Please note that when you set I<Total> to two (i.E<nbsp>e. you have only two
 +groups), then the least significant bit of the hash value will be the XOR of
 +all least significant bits in the host name. One consequence is that when you
 +have two hosts, "server0.example.com" and "server1.example.com", where the host
 +name differs in one digit only and the digits differ by one, those hosts will
 +never end up in the same group.
 +
 +Available options:
 +
 +=over 4
 +
 +=item B<Match> I<Match> I<Total>
 +
 +Divide the data into I<Total> groups and match all hosts in group I<Match> as
 +described above. The groups are numbered from zero, i.E<nbsp>e. I<Match> must
 +be smaller than I<Total>. I<Total> must be at least one, although only values
 +greater than one really do make any sense.
 +
 +You can repeat this option to match multiple groups, for example:
 +
 +  Match 3 7
 +  Match 5 7
 +
 +The above config will divide the data into seven groups and match groups three
 +and five. One use would be to keep every value on two hosts so that if one
 +fails the missing data can later be reconstructed from the second host.
 +
 +=back
 +
 +Example:
 +
 + # Operate on the pre-cache chain, so that ignored values are not even in the
 + # global cache.
 + <Chain "PreCache">
 +   <Rule>
 +     <Match "hashed">
 +       # Divide all received hosts in seven groups and accept all hosts in
 +       # group three.
 +       Match 3 7
 +     </Match>
 +     # If matched: Return and continue.
 +     Target "return"
 +   </Rule>
 +   # If not matched: Return and stop.
 +   Target "stop"
 + </Chain>
 +
  =back
  
  =head2 Available targets
diff --combined src/exec.c
@@@ -265,17 -265,6 +265,17 @@@ static int exec_config (oconfig_item_t 
    return (0);
  } /* int exec_config }}} */
  
 +static void set_environment (void) /* {{{ */
 +{
 +  char buffer[1024];
 +
 +  ssnprintf (buffer, sizeof (buffer), "%i", interval_g);
 +  setenv ("COLLECTD_INTERVAL", buffer, /* overwrite = */ 1);
 +
 +  ssnprintf (buffer, sizeof (buffer), "%s", hostname_g);
 +  setenv ("COLLECTD_HOSTNAME", buffer, /* overwrite = */ 1);
 +} /* }}} void set_environment */
 +
  static void exec_child (program_list_t *pl) /* {{{ */
  {
    int status;
    status = getpwnam_r (pl->user, &sp, nambuf, sizeof (nambuf), &sp_ptr);
    if (status != 0)
    {
-     ERROR ("exec plugin: getpwnam_r failed: %s",
-       sstrerror (errno, errbuf, sizeof (errbuf)));
+     ERROR ("exec plugin: Failed to get user information for user ``%s'': %s",
+       pl->user, sstrerror (errno, errbuf, sizeof (errbuf)));
      exit (-1);
    }
    if (sp_ptr == NULL)
        status = getgrnam_r (pl->group, &gr, nambuf, sizeof (nambuf), &gr_ptr);
        if (0 != status)
        {
-       ERROR ("exec plugin: getgrnam_r failed: %s",
+       ERROR ("exec plugin: Failed to get group information "
+           "for group ``%s'': %s", pl->group,
            sstrerror (errno, errbuf, sizeof (errbuf)));
        exit (-1);
        }
  
    status = execvp (pl->exec, pl->argv);
  
-   ERROR ("exec plugin: exec failed: %s",
-       sstrerror (errno, errbuf, sizeof (errbuf)));
+   ERROR ("exec plugin: Failed to execute ``%s'': %s",
+       pl->exec, sstrerror (errno, errbuf, sizeof (errbuf)));
    exit (-1);
  } /* void exec_child }}} */
  
@@@ -488,8 -478,6 +489,8 @@@ static int fork_child (program_list_t *
        close (fd_pipe_err[1]);
      }
  
 +    set_environment ();
 +
      /* Unblock all signals */
      reset_signal_mask ();
  
diff --combined src/ping.c
  # define NI_MAXHOST 1025
  #endif
  
 +#if defined(OPING_VERSION) && (OPING_VERSION >= 1003000)
 +# define HAVE_OPING_1_3
 +#endif
 +
  /*
   * Private data types
   */
@@@ -49,7 -45,6 +49,7 @@@ struct hostlist_
  
    uint32_t pkg_sent;
    uint32_t pkg_recv;
 +  uint32_t pkg_missed;
  
    double latency_total;
    double latency_squared;
@@@ -63,14 -58,9 +63,14 @@@ typedef struct hostlist_s hostlist_t
   */
  static hostlist_t *hostlist_head = NULL;
  
 +static char  *ping_source = NULL;
 +#ifdef HAVE_OPING_1_3
 +static char  *ping_device = NULL;
 +#endif
  static int    ping_ttl = PING_DEF_TTL;
  static double ping_interval = 1.0;
  static double ping_timeout = 0.9;
 +static int    ping_max_missed = -1;
  
  static int             ping_thread_loop = 0;
  static int             ping_thread_error = 0;
@@@ -81,14 -71,9 +81,14 @@@ static pthread_cond_t  ping_cond = PTHR
  static const char *config_keys[] =
  {
    "Host",
 +  "SourceAddress",
 +#ifdef HAVE_OPING_1_3
 +  "Device",
 +#endif
    "TTL",
    "Interval",
 -  "Timeout"
 +  "Timeout",
 +  "MaxMissed"
  };
  static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
  
@@@ -152,7 -137,7 +152,7 @@@ static void *ping_thread (void *arg) /
    struct timespec ts_int;
  
    hostlist_t *hl;
 -  int status;
 +  int count;
  
    pthread_mutex_lock (&ping_lock);
  
      return ((void *) -1);
    }
  
 +  if (ping_source != NULL)
 +    if (ping_setopt (pingobj, PING_OPT_SOURCE, (void *) ping_source) != 0)
 +      ERROR ("ping plugin: Failed to set source address: %s",
 +          ping_get_error (pingobj));
 +
 +#ifdef HAVE_OPING_1_3
 +  if (ping_device != NULL)
 +    if (ping_setopt (pingobj, PING_OPT_DEVICE, (void *) ping_device) != 0)
 +      ERROR ("ping plugin: Failed to set device: %s",
 +          ping_get_error (pingobj));
 +#endif
 +
    ping_setopt (pingobj, PING_OPT_TIMEOUT, (void *) &ping_timeout);
    ping_setopt (pingobj, PING_OPT_TTL, (void *) &ping_ttl);
  
    /* Add all the hosts to the ping object. */
 -  status = 0;
 +  count = 0;
    for (hl = hostlist_head; hl != NULL; hl = hl->next)
    {
-     int status;
-     status = ping_host_add (pingobj, hl->host);
-     if (status != 0)
-       WARNING ("ping plugin: ping_host_add (%s) failed.", hl->host);
+     int tmp_status;
+     tmp_status = ping_host_add (pingobj, hl->host);
+     if (tmp_status != 0)
+       WARNING ("ping plugin: ping_host_add (%s) failed: %s",
+           hl->host, ping_get_error (pingobj));
      else
 -      status++;
 +      count++;
    }
  
 -  if (status == 0)
 +  if (count == 0)
    {
      ERROR ("ping plugin: No host could be added to ping object. Giving up.");
      ping_thread_error = 1;
  
      if (gettimeofday (&tv_begin, NULL) < 0)
      {
-       ERROR ("ping plugin: gettimeofday failed");
+       char errbuf[1024];
+       ERROR ("ping plugin: gettimeofday failed: %s",
+           sstrerror (errno, errbuf, sizeof (errbuf)));
        ping_thread_error = 1;
        break;
      }
          hl->pkg_recv++;
          hl->latency_total += latency;
          hl->latency_squared += (latency * latency);
 -      }
 +
 +        /* reset missed packages counter */
 +        hl->pkg_missed = 0;
 +      } else
 +        hl->pkg_missed++;
 +
 +      /* if the host did not answer our last N packages, trigger a resolv. */
 +      if (ping_max_missed >= 0 && hl->pkg_missed >= ping_max_missed)
 +      { /* {{{ */
 +        /* we reset the missed package counter here, since we only want to
 +         * trigger a resolv every N packages and not every package _AFTER_ N
 +         * missed packages */
 +        hl->pkg_missed = 0;
 +
 +        WARNING ("ping plugin: host %s has not answered %d PING requests,"
 +          " triggering resolve", hl->host, ping_max_missed);
 +
 +        /* we trigger the resolv simply be removeing and adding the host to our
 +         * ping object */
 +        status = ping_host_remove (pingobj, hl->host);
 +        if (status != 0)
 +        {
 +          WARNING ("ping plugin: ping_host_remove (%s) failed.", hl->host);
 +        }
 +        else
 +        {
 +          status = ping_host_add (pingobj, hl->host);
 +          if (status != 0)
 +            WARNING ("ping plugin: ping_host_add (%s) failed.", hl->host);
 +        }
 +      } /* }}} ping_max_missed */
      } /* }}} for (iter) */
  
      if (gettimeofday (&tv_end, NULL) < 0)
      {
-       ERROR ("ping plugin: gettimeofday failed");
+       char errbuf[1024];
+       ERROR ("ping plugin: gettimeofday failed: %s",
+           sstrerror (errno, errbuf, sizeof (errbuf)));
        ping_thread_error = 1;
        break;
      }
@@@ -420,26 -368,6 +425,26 @@@ static int ping_init (void) /* {{{ *
    return (0);
  } /* }}} int ping_init */
  
 +static int config_set_string (const char *name, /* {{{ */
 +    char **var, const char *value)
 +{
 +  char *tmp;
 +
 +  tmp = strdup (value);
 +  if (tmp == NULL)
 +  {
 +    char errbuf[1024];
 +    ERROR ("ping plugin: Setting `%s' to `%s' failed: strdup failed: %s",
 +        name, value, sstrerror (errno, errbuf, sizeof (errbuf)));
 +    return (1);
 +  }
 +
 +  if (*var != NULL)
 +    free (*var);
 +  *var = tmp;
 +  return (0);
 +} /* }}} int config_set_string */
 +
  static int ping_config (const char *key, const char *value) /* {{{ */
  {
    if (strcasecmp (key, "Host") == 0)
      hl->host = host;
      hl->pkg_sent = 0;
      hl->pkg_recv = 0;
 +    hl->pkg_missed = 0;
      hl->latency_total = 0.0;
      hl->latency_squared = 0.0;
      hl->next = hostlist_head;
      hostlist_head = hl;
    }
 +  else if (strcasecmp (key, "SourceAddress") == 0)
 +  {
 +    int status = config_set_string (key, &ping_source, value);
 +    if (status != 0)
 +      return (status);
 +  }
 +#ifdef HAVE_OPING_1_3
 +  else if (strcasecmp (key, "Device") == 0)
 +  {
 +    int status = config_set_string (key, &ping_device, value);
 +    if (status != 0)
 +      return (status);
 +  }
 +#endif
    else if (strcasecmp (key, "TTL") == 0)
    {
      int ttl = atoi (value);
        WARNING ("ping plugin: Ignoring invalid timeout %g (%s)",
            tmp, value);
    }
 +  else if (strcasecmp (key, "MaxMissed") == 0)
 +  {
 +    ping_max_missed = atoi (value);
 +    if (ping_max_missed < 0)
 +      INFO ("ping plugin: MaxMissed < 0, disabled re-resolving of hosts");
 +  }
    else
    {
      return (-1);
diff --combined src/plugin.c
@@@ -151,7 -151,7 +151,7 @@@ static void destroy_read_heap (void) /
        {
                callback_func_t *cf;
  
 -              cf = c_head_get_root (read_heap);
 +              cf = c_heap_get_root (read_heap);
                if (cf == NULL)
                        break;
  
@@@ -173,7 -173,7 +173,7 @@@ static int register_callback (llist_t *
                *list = llist_create ();
                if (*list == NULL)
                {
 -                      ERROR ("plugin: create_register_callback: "
 +                      ERROR ("plugin: register_callback: "
                                        "llist_create failed.");
                        destroy_callback (cf);
                        return (-1);
        key = strdup (name);
        if (key == NULL)
        {
 -              ERROR ("plugin: create_register_callback: strdup failed.");
 +              ERROR ("plugin: register_callback: strdup failed.");
                destroy_callback (cf);
                return (-1);
        }
                le = llentry_create (key, cf);
                if (le == NULL)
                {
 -                      ERROR ("plugin: create_register_callback: "
 +                      ERROR ("plugin: register_callback: "
                                        "llentry_create failed.");
                        free (key);
                        destroy_callback (cf);
                old_cf = le->value;
                le->value = cf;
  
 +              WARNING ("plugin: register_callback: "
 +                              "a callback named `%s' already exists - "
 +                              "overwriting the old entry!", name);
 +
                destroy_callback (old_cf);
                sfree (key);
        }
@@@ -274,7 -270,7 +274,7 @@@ static int plugin_unregister (llist_t *
   * object, but it will bitch about a shared object not having a
   * ``module_register'' symbol..
   */
 -static int plugin_load_file (char *file)
 +static int plugin_load_file (char *file, uint32_t flags)
  {
        lt_dlhandle dlh;
        void (*reg_handle) (void);
        lt_dlinit ();
        lt_dlerror (); /* clear errors */
  
 -      if ((dlh = lt_dlopen (file)) == NULL)
 +#if LIBTOOL_VERSION == 2
 +      if (flags & PLUGIN_FLAGS_GLOBAL) {
 +              lt_dladvise advise;
 +              lt_dladvise_init(&advise);
 +              lt_dladvise_global(&advise);
 +              dlh = lt_dlopenadvise(file, advise);
 +              lt_dladvise_destroy(&advise);
 +      } else {
 +              dlh = lt_dlopen (file);
 +      }
 +#else /* if LIBTOOL_VERSION == 1 */
 +      if (flags & PLUGIN_FLAGS_GLOBAL)
 +              ERROR ("plugin_load_file: The global flag is not supported, "
 +                              "libtool 2 is required for this.");
 +      dlh = lt_dlopen (file);
 +#endif
 +
 +      if (dlh == NULL)
        {
                const char *error = lt_dlerror ();
  
        return (0);
  }
  
+ static _Bool timeout_reached(struct timespec timeout)
+ {
+       struct timeval now;
+       gettimeofday(&now, NULL);
+       return (now.tv_sec >= timeout.tv_sec && now.tv_usec >= (timeout.tv_nsec / 1000));
+ }
  static void *plugin_read_thread (void __attribute__((unused)) *args)
  {
        while (read_loop != 0)
                struct timeval now;
                int status;
                int rf_type;
+               int rc;
  
                /* Get the read function that needs to be read next. */
 -              rf = c_head_get_root (read_heap);
 +              rf = c_heap_get_root (read_heap);
                if (rf == NULL)
                {
                        struct timespec abstime;
                /* sleep until this entry is due,
                 * using pthread_cond_timedwait */
                pthread_mutex_lock (&read_lock);
-               pthread_cond_timedwait (&read_cond, &read_lock,
+               /* In pthread_cond_timedwait, spurious wakeups are possible
+                * (and really happen, at least on NetBSD with > 1 CPU), thus
+                * we need to re-evaluate the condition every time
+                * pthread_cond_timedwait returns. */
+               rc = 0;
+               while (!timeout_reached(rf->rf_next_read) && rc == 0) {
+                       rc = pthread_cond_timedwait (&read_cond, &read_lock,
                                &rf->rf_next_read);
+               }
                /* Must hold `real_lock' when accessing `rf->rf_type'. */
                rf_type = rf->rf_type;
                pthread_mutex_unlock (&read_lock);
@@@ -556,7 -551,7 +572,7 @@@ void plugin_set_dir (const char *dir
  }
  
  #define BUFSIZE 512
 -int plugin_load (const char *type)
 +int plugin_load (const char *type, uint32_t flags)
  {
        DIR  *dh;
        const char *dir;
                        continue;
                }
  
 -              if (plugin_load_file (filename) == 0)
 +              if (plugin_load_file (filename, flags) == 0)
                {
                        /* success */
                        ret = 0;
@@@ -1057,7 -1052,7 +1073,7 @@@ int plugin_read_all_once (void
        {
                read_func_t *rf;
  
 -              rf = c_head_get_root (read_heap);
 +              rf = c_heap_get_root (read_heap);
                if (rf == NULL)
                        break;