From: Florian Forster Date: Sun, 1 Apr 2012 10:01:58 +0000 (+0200) Subject: Merge branch 'collectd-4.10' into collectd-5.0 X-Git-Tag: collectd-5.0.4~2 X-Git-Url: https://git.octo.it/?a=commitdiff_plain;h=483e801902bca3c779793224eddf3bb2749d7288;hp=-c;p=collectd.git Merge branch 'collectd-4.10' into collectd-5.0 Conflicts: ChangeLog src/collectd.conf.pod src/common.c src/network.c src/processes.c version-gen.sh --- 483e801902bca3c779793224eddf3bb2749d7288 diff --combined ChangeLog index 4a99a15a,32e9ba33..1beef6eb --- a/ChangeLog +++ b/ChangeLog @@@ -1,145 -1,32 +1,174 @@@ +2012-02-19, Version 5.0.3 + * Build system: Fix problems when building the ipvs and iptables + plugins. Thanks to Sebastian Harl for his patch. A bashism in the + version-gen.sh script has been fixed. Thanks to Jo-Philipp Wich for + his patch. + * csv and rrdtool plugins: Print a more helpful error message when the + DataDir is a symlink pointing to a non-existing location. Thanks to + Jonathan Nieder for his patch. + * exec plugin: Fix a problem when using select(2) to read from file + handles. Thanks to Gerrie Roos for his patch. + * network plugin: An incorrect error message in the handling of the + "Interface" configuration option has been fixed. Thanks to Gerrie + Roos for his patch. + * oracle plugin: A potential endless loop in the error handling has + been fixed. + * python plugin: A crash bug in the configuration handling has been + fixed. Thanks to Sven Trenkel for his patch. + * interfaces plugin: The change which was supposed to ignore "bogus" + interfaces has been reverted, since it ignored legit interfaces, such + as bonding pseudo-devices as well. + +2012-01-21, Version 5.0.2 + * curl_xml plugin: Fix handling of file:// and other URLs (which don't + follow HTTP status codes). Thanks to Fabien Wernli for his patch! + * df plugin: Fix handling of negative "available" counts. This can + occur with some file systems, for example UFS. Thanks to Toni Ylenius + for his patch. + * interface plugin: "mac" interfaces are now ignored on Solaris. These + pseudo-interfaces occur multiple times, causing warnings. Also switch + to 64-bit counters on Solaris, improving overflow behavior for + high-speed interfaces. Thanks to Eddy Geez and Fabien Wernli for + their patches. + * memory plugin: Account kernel and unused memory under Solaris. Thanks + to Fabien Wernli for his patch. + * network plugin: A bug in the interaction between the Network plugin + and filter chains has been fixed: When a filter modified a field such + as the hostname, subsequent values in the same network packets could + have ended up using the modified name rather than the original name. + Thanks to Sebastian Harl for identifying the problem. + * oracle plugin: A memory leak has been fixed in the parameter handling. + * python plugin: A memory leak has been fixed. Thanks to Sven Trenkel + for fixing this bug! + +2011-10-07, Version 5.0.1 + * collectd: A mutex leak has been fixed in the meta data code. Thanks + to Rafal Lesniak for his patch. + * collectd: Compatibility fixes for GCC 4.6 have been applied. Thanks + to Peter Green for his patch. + * csv plugin: The line buffer size has been increased. Thanks to Colin + McCabe for the patch. + * curl_json plugin: Don't use the "parent" node to build the type + instance, if it is empty. Compatibility with libyajl 2 has been + added. Thanks to "spupykin" of the Arch Linux project for the initial + code. Formatting of time has been fixed in the JSON module. + * exec plugin: Fix the timestamp value passed to notification scripts. + Thanks to Alexander Kovalenko for fixing this. + * iptables plugin: Fix linking with some versions of libiptc. + * irq plugin: Fix support for interrupts under Linux. The old code + assumed that interrupts have a numeric value -- this is no longer + true for Linux. Thanks to Bostjan Skufca for implementing this. + * notify_desktop plugin: Compatibility with libnotify 0.7 has been + added. Thanks to Samuli Suominen for his patch. + * processes plugin: Fix handling of regular expressions containing + spaces. Thanks for Sebastian Harl for fixing this. + * rrdtool, rrdcached plugins: Improve precision of the XFF parameter. + Previously, values like 0.999 would have been rounded to 1.0. Thanks + to Francois-Xavier Bourlet for fixing this. + * varnish plugin: Fix data type handling of some metrics. Some values + were submitted as gauge even though they were derives. + * Various plugin: Set a multi-threading flag in libcurl. Thanks to Mike + Flisher for the fix. + +2011-03-28, Version 5.0.0 + * collectd: The "FQDNLookup" option is now enabled by default. + * collectd: The internal representation of time has been changed to + allow a higher accuracy than one second. + * collectdcmd: This new command line utility can send various commands + to collectd using the UnixSock plugin. Thanks to Håkon Dugstad + Johnsen and Sebastian Harl for their code. + * collectd-nagios: The "-m" option has been implemented (treat NaNs as + critical). + * collectd-tg: Traffic generator creating bogus network traffic + compatible to the Network plugin. This utility can be used to + stress-test new write plugins and collectd in general. + * libcollectdclient: Creating and sending network packets has been + added to the collectd client library. + * All data sets: The data source name of all data sets with exactly + one data source has been changed to "value". + * All plugins: All "counter" data sources have been converted to + "derive" data sources. All plugins now use "derive" by default, but + plugins such as the network plugin can still handle "counter", of + course. The minimum value of all derive data sources is zero, the + maximum value is unspecified. + * amqp plugin: The new AMQP plugin can send data to and receive data + from an AMQP broker. Thanks to Sebastien Pahl for his code. + * apache plugin: Backwards compatibility code has been removed. + Support for the IBM HTTP Server has been added. Thanks to Manuel + Luis Sanmartín Rozada for his patch. + * contextswitch plugin: Support for sysctlbyname(3) has been added. + Thanks to Kimo Rosenbaum for his patch. + * df plugin: The default behavior has been changed to be equivalent to + the "ReportReserved" behavior of v4. + * dns plugin: Improved RFC 1035 name parsing has been imported from + "dnstop". + * exec plugin: Backwards compatibility code has been removed. + * GenericJMX plugin: The "InstancePrefix" option has been added to + "Connection" blocks. + * hddtemp plugin: The "TranslateDevicename" config option has been + removed. + * interface plugin: Use the "plugin instance" to store the interface + value. + * libvirt plugin: The "InterfaceFormat" option has been added. Thanks + to Ruben Kerkhof for his patch. + * lpar plugin: New plugins for "logical partitions", a virtualization + technique of POWER CPUs. Thanks to Aurélien Reynaud for his code and + patience. + * modbus plugin: Support for libmodbus 2.9.2 has been added and the + license has been changes to LGPLv2.1. + * mysql plugin: Backwards compatibility code has been removed. The + data sets used have been improved. + * network plugin: The default buffer size has been increased to + 1452 bytes. + * perl plugin: Backwards compatibility code has been removed. + * postgresql plugin: Backwards compatibility code has been removed. + * redis plugin: Plugin for collecting statistics from Redis, a key- + value store, has been added. Thanks to Andres J. Diaz for his code. + * swap plugin: Implement collection of physical and virtual memory + statistics under Solaris. The new default is collecting physical + memory. Thanks to Aurélien Reynaud for his patches. + * threshold plugin: The threshold configuration has been moved into + this separate plugin. + * unixsock plugin: The "DeleteSocket" option has been added. + * varnish plugin: The new Varnish plugin reads statistics from + Varnish, a web accelerator. Thanks to Jérôme Renard and Marc + Fournier for their contributions. + * write_redis: New plugin for writing data to Redis, a key-value + store. + * zfs_arc plugin: The data sets have been replaced by more elegant + alternatives. + * v5upgrade target: Target for converting v4 data sets to the v5 + schema. + + 2012-03-23, Version 4.10.7 + * Build system: Fix the use of a libltdl macro. Thanks to Clemens Lang + for fixing this. Adresses some issues with building the iptables + plugin under Gentoo. + * libcollectdclient: A memory leak in the lcc_getval() function has + been fixed. Thanks to Jason Schmidlapp for finding and fixing this + issue. + * bind plugin: The use of 'QType" types has been fixed. + * df plugin: Fixed compiler issue under Mac OS X 10.7. + * conntrack plugin: Support zero as legitimate value. Thanks to Louis + Opter for his patch. + * memcached plugin: Increased the size of a static buffer, which was + truncating status messages form memcached. Thanks to Timon for the + patch. + * network plugin: Forwarding of notifications has been disabled. This + was a contition not checked for before, which may retult in an + endless loop. + * processes plugin: Support for process names with spaces has been + added to the Linux implementation. Thanks to Darrell Bishop for his + patch. + * perl plugin: A race condition in several callbacks, including log and + write callbacks, has been fixed. Thanks to "Rrpv" for reporting this + bug. + * snmp plugin: A bug when casting unsigned integers to gauge values has + been fixed: Unsigned integers would be cast to a signed integer and + then to a gauge, possibly resulting in a negative value. + * tcpconns plugin: Compilation with newer versions of the FreeBSD + runtime has been fixed. + 2012-02-19, Version 4.10.6 * Build system: Fix problems when building the ipvs and iptables plugins. Thanks to Sebastian Harl for his patch. A bashism in the diff --combined configure.in index e30d0f88,1dc23bf2..bb26716d --- a/configure.in +++ b/configure.in @@@ -109,13 -109,9 +109,13 @@@ AC_ARG_ENABLE(standards if test "x$enable_standards" = "xyes" then AC_DEFINE(_ISOC99_SOURCE, 1, [Define to enforce ISO C99 compliance.]) - AC_DEFINE(_POSIX_C_SOURCE, 200112L, [Define to enforce POSIX.1-2001 compliance.]) - AC_DEFINE(_XOPEN_SOURCE, 600, [Define to enforce X/Open 6 (XSI) compliance.]) + AC_DEFINE(_POSIX_C_SOURCE, 200809L, [Define to enforce POSIX.1-2008 compliance.]) + AC_DEFINE(_XOPEN_SOURCE, 700, [Define to enforce X/Open 7 (XSI) compliance.]) AC_DEFINE(_REENTRANT, 1, [Define to enable reentrancy interfaces.]) + if test "x$GCC" = "xyes" + then + CFLAGS="$CFLAGS -std=c99" + fi fi AM_CONDITIONAL(BUILD_FEATURE_STANDARDS, test "x$enable_standards" = "xyes") @@@ -591,27 -587,6 +591,27 @@@ socket_needs_socket="no AC_CHECK_FUNCS(socket, [], AC_CHECK_LIB(socket, socket, [socket_needs_socket="yes"], AC_MSG_ERROR(cannot find socket))) AM_CONDITIONAL(BUILD_WITH_LIBSOCKET, test "x$socket_needs_socket" = "xyes") +clock_gettime_needs_rt="no" +clock_gettime_needs_posix4="no" +have_clock_gettime="no" +AC_CHECK_FUNCS(clock_gettime, [have_clock_gettime="yes"]) +if test "x$have_clock_gettime" = "xno" +then + AC_CHECK_LIB(rt, clock_gettime, [clock_gettime_needs_rt="yes" + have_clock_gettime="yes"]) +fi +if test "x$have_clock_gettime" = "xno" +then + AC_CHECK_LIB(posix4, clock_gettime, [clock_gettime_needs_posix4="yes" + have_clock_gettime="yes"]) +fi +if test "x$have_clock_gettime" = "xyes" +then + AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if the clock_gettime(2) function is available.]) +else + AC_MSG_WARN(cannot find clock_gettime) +fi + nanosleep_needs_rt="no" nanosleep_needs_posix4="no" AC_CHECK_FUNCS(nanosleep, @@@ -621,9 -596,8 +621,9 @@@ AC_CHECK_LIB(posix4, nanosleep, [nanosleep_needs_posix4="yes"], AC_MSG_ERROR(cannot find nanosleep)))) -AM_CONDITIONAL(BUILD_WITH_LIBRT, test "x$nanosleep_needs_rt" = "xyes") -AM_CONDITIONAL(BUILD_WITH_LIBPOSIX4, test "x$nanosleep_needs_posix4" = "xyes") + +AM_CONDITIONAL(BUILD_WITH_LIBRT, test "x$clock_gettime_needs_rt" = "xyes" || test "x$nanosleep_needs_rt" = "xyes") +AM_CONDITIONAL(BUILD_WITH_LIBPOSIX4, test "x$clock_gettime_needs_posix4" = "xyes" || test "x$nanosleep_needs_posix4" = "xyes") AC_CHECK_FUNCS(sysctl, [have_sysctl="yes"], [have_sysctl="no"]) AC_CHECK_FUNCS(sysctlbyname, [have_sysctlbyname="yes"], [have_sysctlbyname="no"]) @@@ -633,127 -607,13 +633,127 @@@ AC_CHECK_FUNCS(thread_info, [have_threa AC_CHECK_FUNCS(statfs, [have_statfs="yes"], [have_statfs="no"]) AC_CHECK_FUNCS(statvfs, [have_statvfs="yes"], [have_statvfs="no"]) AC_CHECK_FUNCS(getifaddrs, [have_getifaddrs="yes"], [have_getifaddrs="no"]) +AC_CHECK_FUNCS(getloadavg, [have_getloadavg="yes"], [have_getloadavg="no"]) AC_CHECK_FUNCS(syslog, [have_syslog="yes"], [have_syslog="no"]) AC_CHECK_FUNCS(getutent, [have_getutent="yes"], [have_getutent="no"]) AC_CHECK_FUNCS(getutxent, [have_getutxent="yes"], [have_getutxent="no"]) -AC_CHECK_FUNCS(swapctl, [have_swapctl="yes"], [have_swapctl="no"]) -# For load module -AC_CHECK_FUNCS(getloadavg, [have_getloadavg="yes"], [have_getloadavg="no"]) +# Check for strptime {{{ +if test "x$GCC" = "xyes" +then + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Wall -Wextra -Werror" +fi + +AC_CHECK_FUNCS(strptime, [have_strptime="yes"], [have_strptime="no"]) +if test "x$have_strptime" = "xyes" +then + AC_CACHE_CHECK([whether strptime is exported by default], + [c_cv_have_strptime_default], + AC_COMPILE_IFELSE( +AC_LANG_PROGRAM( +[[ +AC_INCLUDES_DEFAULT +#include +]], +[[ + struct tm stm; + (void) strptime ("2010-12-30%13:42:42", "%Y-%m-%dT%T", &stm); +]]), + [c_cv_have_strptime_default="yes"], + [c_cv_have_strptime_default="no"])) +fi +if test "x$have_strptime" = "xyes" && test "x$c_cv_have_strptime_default" = "xno" +then + AC_CACHE_CHECK([whether strptime needs standards mode], + [c_cv_have_strptime_standards], + AC_COMPILE_IFELSE( +AC_LANG_PROGRAM( +[[ +#ifndef _ISOC99_SOURCE +# define _ISOC99_SOURCE 1 +#endif +#ifndef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200112L +#endif +#ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE 500 +#endif +AC_INCLUDES_DEFAULT +#include +]], +[[ + struct tm stm; + (void) strptime ("2010-12-30%13:42:42", "%Y-%m-%dT%T", &stm); +]]), + [c_cv_have_strptime_standards="yes"], + [c_cv_have_strptime_standards="no"])) + + if test "x$c_cv_have_strptime_standards" = "xyes" + then + AC_DEFINE([STRPTIME_NEEDS_STANDARDS], 1, [Set to true if strptime is only exported in X/Open mode (GNU libc).]) + else + have_strptime="no" + fi +fi + +if test "x$GCC" = "xyes" +then + CFLAGS="$SAVE_CFLAGS" +fi + +# }}} Check for strptime + +AC_CHECK_FUNCS(swapctl, [have_swapctl="yes"], [have_swapctl="no"]) +if test "x$have_swapctl" = "xyes"; then + AC_CACHE_CHECK([whether swapctl takes two arguments], + [c_cv_have_swapctl_two_args], + AC_COMPILE_IFELSE( + AC_LANG_PROGRAM([[AC_INCLUDES_DEFAULT +#if HAVE_SYS_SWAP_H && !defined(_LP64) && _FILE_OFFSET_BITS == 64 +# undef _FILE_OFFSET_BITS +# undef _LARGEFILE64_SOURCE +#endif +#include +#include ]], + [[ + int num = swapctl(0, NULL); + ]] + ), + [c_cv_have_swapctl_two_args="yes"], + [c_cv_have_swapctl_two_args="no"] + ) + ) + AC_CACHE_CHECK([whether swapctl takes three arguments], + [c_cv_have_swapctl_three_args], + AC_COMPILE_IFELSE( + AC_LANG_PROGRAM([[AC_INCLUDES_DEFAULT +#if HAVE_SYS_SWAP_H && !defined(_LP64) && _FILE_OFFSET_BITS == 64 +# undef _FILE_OFFSET_BITS +# undef _LARGEFILE64_SOURCE +#endif +#include +#include ]], + [[ + int num = swapctl(0, NULL,0); + ]] + ), + [c_cv_have_swapctl_three_args="yes"], + [c_cv_have_swapctl_three_args="no"] + ) + ) +fi +# Check for different versions of `swapctl' here.. +if test "x$have_swapctl" = "xyes"; then + if test "x$c_cv_have_swapctl_two_args" = "xyes"; then + AC_DEFINE(HAVE_SWAPCTL_TWO_ARGS, 1, + [Define if the function swapctl exists and takes two arguments.]) + fi + if test "x$c_cv_have_swapctl_three_args" = "xyes"; then + AC_DEFINE(HAVE_SWAPCTL_THREE_ARGS, 1, + [Define if the function swapctl exists and takes three arguments.]) + fi +fi # Check for NAN AC_ARG_WITH(nan-emulation, [AS_HELP_STRING([--with-nan-emulation], [use emulated NAN. For crosscompiling only.])], @@@ -775,7 -635,7 +775,7 @@@ if test "x$nan_type" = "xnone"; the [[ #include #include -static float foo = NAN; +static double foo = NAN; ]], [[ if (isnan (foo)) @@@ -801,7 -661,7 +801,7 @@@ if test "x$nan_type" = "xnone"; the #include #define __USE_ISOC99 1 #include -static float foo = NAN; +static double foo = NAN; ]], [[ if (isnan (foo)) @@@ -835,7 -695,7 +835,7 @@@ if test "x$nan_type" = "xnone"; the #ifndef isnan # define isnan(f) ((f) != (f)) #endif -static float foo = NAN; +static double foo = NAN; ]], [[ if (isnan (foo)) @@@ -1303,12 -1163,6 +1303,12 @@@ f if test "x$with_perfstat" = "xyes" then AC_DEFINE(HAVE_PERFSTAT, 1, [Define to 1 if you have the 'perfstat' library (-lperfstat)]) + # struct members pertaining to donation have been added to libperfstat somewhere between AIX5.3ML5 and AIX5.3ML9 + AC_CHECK_MEMBER([perfstat_partition_type_t.b.donate_enabled], [], [], [[#include @], [Path to libcredis.])], +[ + if test "x$withval" = "xyes" + then + with_libcredis="yes" + else if test "x$withval" = "xno" + then + with_libcredis="no" + else + with_libcredis="yes" + LIBCREDIS_CPPFLAGS="$LIBCREDIS_CPPFLAGS -I$withval/include" + LIBCREDIS_LDFLAGS="$LIBCREDIS_LDFLAGS -L$withval/lib" + fi; fi +], +[with_libcredis="yes"]) + +SAVE_CPPFLAGS="$CPPFLAGS" +SAVE_LDFLAGS="$LDFLAGS" + +CPPFLAGS="$CPPFLAGS $LIBCREDIS_CPPFLAGS" +LDFLAGS="$LDFLAGS $LIBCREDIS_LDFLAGS" + +if test "x$with_libcredis" = "xyes" +then + if test "x$LIBCREDIS_CPPFLAGS" != "x" + then + AC_MSG_NOTICE([libcredis CPPFLAGS: $LIBCREDIS_CPPFLAGS]) + fi + AC_CHECK_HEADERS(credis.h, + [with_libcredis="yes"], + [with_libcredis="no (credis.h not found)"]) +fi +if test "x$with_libcredis" = "xyes" +then + if test "x$LIBCREDIS_LDFLAGS" != "x" + then + AC_MSG_NOTICE([libcredis LDFLAGS: $LIBCREDIS_LDFLAGS]) + fi + AC_CHECK_LIB(credis, credis_info, + [with_libcredis="yes"], + [with_libcredis="no (symbol 'credis_info' not found)"]) + +fi + +CPPFLAGS="$SAVE_CPPFLAGS" +LDFLAGS="$SAVE_LDFLAGS" + +if test "x$with_libcredis" = "xyes" +then + BUILD_WITH_LIBCREDIS_CPPFLAGS="$LIBCREDIS_CPPFLAGS" + BUILD_WITH_LIBCREDIS_LDFLAGS="$LIBCREDIS_LDFLAGS" + AC_SUBST(BUILD_WITH_LIBCREDIS_CPPFLAGS) + AC_SUBST(BUILD_WITH_LIBCREDIS_LDFLAGS) +fi +AM_CONDITIONAL(BUILD_WITH_LIBCREDIS, test "x$with_libcredis" = "xyes") +# }}} + # --with-libcurl {{{ with_curl_config="curl-config" with_curl_cflags="" @@@ -1853,9 -1650,10 +1854,10 @@@ the AC_CHECK_TYPES([iptc_handle_t, ip6tc_handle_t], [], []) fi # Check for the iptc_init symbol in the library. + # This could be in iptc or ip4tc if test "x$with_libiptc" = "xpkgconfig" then - AC_CHECK_LIB(iptc, iptc_init, + AC_SEARCH_LIBS(iptc_init, [iptc ip4tc], [with_libiptc="pkgconfig"], [with_libiptc="no"], [$with_libiptc_libs]) @@@ -2155,7 -1953,7 +2157,7 @@@ the $PKG_CONFIG --exists 'modbus' 2>/dev/null if test $? -ne 0 then - with_libmodbus="no (pkg-config doesn't know library)" + with_libmodbus="no (pkg-config doesn't know modbus)" fi fi if test "x$with_libmodbus" = "xuse_pkgconfig" @@@ -2195,9 -1993,9 +2197,9 @@@ the CPPFLAGS="$CPPFLAGS $with_libmodbus_cflags" LDFLAGS="$LDFLAGS $with_libmodbus_libs" - AC_CHECK_LIB(modbus, modbus_init_tcp, + AC_CHECK_LIB(modbus, modbus_connect, [with_libmodbus="yes"], - [with_libmodbus="no (symbol modbus_init_tcp not found)"]) + [with_libmodbus="no (symbol modbus_connect not found)"]) CPPFLAGS="$SAVE_CPPFLAGS" LDFLAGS="$SAVE_LDFLAGS" @@@ -2620,7 -2418,7 +2622,7 @@@ the fi AC_CHECK_HEADERS(oping.h, [with_liboping="yes"], - [with_liboping="no ('oping.h' not found)"]) + [with_liboping="no (oping.h not found)"]) fi if test "x$with_liboping" = "xyes" then @@@ -2791,8 -2589,7 +2793,8 @@@ the fi if test "x$with_libpcap" = "xyes" then - AC_CHECK_HEADERS(pcap-bpf.h) + AC_CHECK_HEADERS(pcap-bpf.h,, + [with_libpcap="no (pcap-bpf.h not found)"]) fi AM_CONDITIONAL(BUILD_WITH_LIBPCAP, test "x$with_libpcap" = "xyes") # }}} @@@ -3227,72 -3024,6 +3229,72 @@@ the fi # }}} --with-python +# --with-librabbitmq {{{ +with_librabbitmq_cppflags="" +with_librabbitmq_ldflags="" +AC_ARG_WITH(librabbitmq, [AS_HELP_STRING([--with-librabbitmq@<:@=PREFIX@:>@], [Path to librabbitmq.])], +[ + if test "x$withval" != "xno" && test "x$withval" != "xyes" + then + with_librabbitmq_cppflags="-I$withval/include" + with_librabbitmq_ldflags="-L$withval/lib" + with_librabbitmq="yes" + else + with_librabbitmq="$withval" + fi +], +[ + with_librabbitmq="yes" +]) +SAVE_CPPFLAGS="$CPPFLAGS" +SAVE_LDFLAGS="$LDFLAGS" +CPPFLAGS="$CPPFLAGS $with_librabbitmq_cppflags" +LDFLAGS="$LDFLAGS $with_librabbitmq_ldflags" +if test "x$with_librabbitmq" = "xyes" +then + AC_CHECK_HEADERS(amqp.h, [with_librabbitmq="yes"], [with_librabbitmq="no (amqp.h not found)"]) +fi +if test "x$with_librabbitmq" = "xyes" +then + # librabbitmq up to version 0.9.1 provides "library_errno", later + # versions use "library_error". The library does not provide a version + # macro :( Use "AC_CHECK_MEMBERS" (plural) for automatic defines. + AC_CHECK_MEMBERS([amqp_rpc_reply_t.library_errno],,, + [ +#if HAVE_STDLIB_H +# include +#endif +#if HAVE_STDIO_H +# include +#endif +#if HAVE_STDINT_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#endif +#include + ]) +fi +if test "x$with_librabbitmq" = "xyes" +then + AC_CHECK_LIB(rabbitmq, amqp_basic_publish, [with_librabbitmq="yes"], [with_librabbitmq="no (Symbol 'amqp_basic_publish' not found)"]) +fi +if test "x$with_librabbitmq" = "xyes" +then + BUILD_WITH_LIBRABBITMQ_CPPFLAGS="$with_librabbitmq_cppflags" + BUILD_WITH_LIBRABBITMQ_LDFLAGS="$with_librabbitmq_ldflags" + BUILD_WITH_LIBRABBITMQ_LIBS="-lrabbitmq" + AC_SUBST(BUILD_WITH_LIBRABBITMQ_CPPFLAGS) + AC_SUBST(BUILD_WITH_LIBRABBITMQ_LDFLAGS) + AC_SUBST(BUILD_WITH_LIBRABBITMQ_LIBS) + AC_DEFINE(HAVE_LIBRABBITMQ, 1, [Define if librabbitmq is present and usable.]) +fi +CPPFLAGS="$SAVE_CPPFLAGS" +LDFLAGS="$SAVE_LDFLAGS" +AM_CONDITIONAL(BUILD_WITH_LIBRABBITMQ, test "x$with_librabbitmq" = "xyes") +# }}} + # --with-librouteros {{{ AC_ARG_WITH(librouteros, [AS_HELP_STRING([--with-librouteros@<:@=PREFIX@:>@], [Path to librouteros.])], [ @@@ -3324,7 -3055,7 +3326,7 @@@ the fi AC_CHECK_HEADERS(routeros_api.h, [with_librouteros="yes"], - [with_librouteros="no ('routeros_api.h' not found)"]) + [with_librouteros="no (routeros_api.h not found)"]) fi if test "x$with_librouteros" = "xyes" then @@@ -3523,7 -3254,7 +3525,7 @@@ the if test "$?" != "0" then with_libstatgrab_pkg_config="no" - with_libstatgrab="no ($PKG_CONFIG doesn't know libstatgrab)" + with_libstatgrab="no (pkg-config doesn't know libstatgrab)" temp_result="not found" fi AC_MSG_RESULT([$temp_result]) @@@ -3743,7 -3474,7 +3745,7 @@@ the $PKG_CONFIG --exists 'libupsclient' 2>/dev/null if test $? -ne 0 then - with_libupsclient="no (pkg-config doesn't know library)" + with_libupsclient="no (pkg-config doesn't know libupsclient)" fi fi if test "x$with_libupsclient" = "xuse_pkgconfig" @@@ -3933,98 -3664,6 +3935,98 @@@ f AM_CONDITIONAL(BUILD_WITH_LIBYAJL, test "x$with_libyajl" = "xyes") # }}} +# --with-libvarnish {{{ +with_libvarnish_cppflags="" +with_libvarnish_cflags="" +with_libvarnish_libs="" +AC_ARG_WITH(libvarnish, [AS_HELP_STRING([--with-libvarnish@<:@=PREFIX@:>@], [Path to libvarnish.])], +[ + if test "x$withval" = "xno" + then + with_libvarnish="no" + else if test "x$withval" = "xyes" + then + with_libvarnish="use_pkgconfig" + else if test -d "$with_libvarnish/lib" + then + AC_MSG_NOTICE([Not checking for libvarnish: Manually configured]) + with_libvarnish_cflags="-I$withval/include" + with_libvarnish_libs="-L$withval/lib -lvarnish -lvarnishcompat -lvarnishapi" + with_libvarnish="yes" + fi; fi; fi +], +[with_libvarnish="use_pkgconfig"]) + +# configure using pkg-config +if test "x$with_libvarnish" = "xuse_pkgconfig" +then + if test "x$PKG_CONFIG" = "x" + then + with_libvarnish="no (Don't have pkg-config)" + fi +fi +if test "x$with_libvarnish" = "xuse_pkgconfig" +then + AC_MSG_NOTICE([Checking for varnishapi using $PKG_CONFIG]) + $PKG_CONFIG --exists 'varnishapi' 2>/dev/null + if test $? -ne 0 + then + with_libvarnish="no (pkg-config doesn't know varnishapi)" + fi +fi +if test "x$with_libvarnish" = "xuse_pkgconfig" +then + with_libvarnish_cflags="`$PKG_CONFIG --cflags 'varnishapi'`" + if test $? -ne 0 + then + with_libvarnish="no ($PKG_CONFIG failed)" + fi + with_libvarnish_libs="`$PKG_CONFIG --libs 'varnishapi'`" + if test $? -ne 0 + then + with_libvarnish="no ($PKG_CONFIG failed)" + fi +fi +if test "x$with_libvarnish" = "xuse_pkgconfig" +then + with_libvarnish="yes" +fi + +# with_libvarnish_cflags and with_libvarnish_libs are set up now, let's do +# the actual checks. +if test "x$with_libvarnish" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_libvarnish_cflags" + AC_CHECK_HEADERS(varnish/varnishapi.h, [], [with_libvarnish="no (varnish/varnishapi.h not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" +fi +if test "x$with_libvarnish" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + #SAVE_LDFLAGS="$LDFLAGS" + + CPPFLAGS="$CPPFLAGS $with_libvarnish_cflags" + #LDFLAGS="$LDFLAGS $with_libvarnish_libs" + + AC_CHECK_LIB(varnishapi, VSL_OpenStats, + [with_libvarnish="yes"], + [with_libvarnish="no (symbol VSL_OpenStats not found)"], + [$with_libvarnish_libs]) + + CPPFLAGS="$SAVE_CPPFLAGS" + #LDFLAGS="$SAVE_LDFLAGS" +fi +if test "x$with_libvarnish" = "xyes" +then + BUILD_WITH_LIBVARNISH_CFLAGS="$with_libvarnish_cflags" + BUILD_WITH_LIBVARNISH_LIBS="$with_libvarnish_libs" + AC_SUBST(BUILD_WITH_LIBVARNISH_CFLAGS) + AC_SUBST(BUILD_WITH_LIBVARNISH_LIBS) +fi +# }}} + # pkg-config --exists 'libxml-2.0'; pkg-config --exists libvirt {{{ with_libxml2="no (pkg-config isn't available)" with_libxml2_cflags="" @@@ -4039,7 -3678,7 +4041,7 @@@ the then with_libxml2="yes" else - with_libxml2="no (pkg-config doesn't know library)" + with_libxml2="no (pkg-config doesn't know libxml-2.0)" fi pkg-config --exists libvirt 2>/dev/null @@@ -4047,7 -3686,7 +4049,7 @@@ then with_libvirt="yes" else - with_libvirt="no (pkg-config doesn't know library)" + with_libvirt="no (pkg-config doesn't know libvirt)" fi fi if test "x$with_libxml2" = "xyes" @@@ -4164,7 -3803,7 +4166,7 @@@ the $PKG_CONFIG --exists OpenIPMIpthread 2>/dev/null if test "$?" != "0" then - with_libopenipmipthread="no ($PKG_CONFIG doesn't know OpenIPMIpthread)" + with_libopenipmipthread="no (pkg-config doesn't know OpenIPMIpthread)" fi AC_MSG_RESULT([$with_libopenipmipthread]) fi @@@ -4225,11 -3864,7 +4227,11 @@@ f PKG_CHECK_MODULES([LIBNOTIFY], [libnotify], [with_libnotify="yes"], - [with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"]) + [if test "x$LIBNOTIFY_PKG_ERRORS" = "x"; then + with_libnotify="no" + else + with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)" + fi]) # Check for enabled/disabled features # @@@ -4472,6 -4107,11 +4474,6 @@@ the plugin_tape="yes" fi -if test "x$have_sys_swap_h$with_kstat$ac_system" = "xyesyesSolaris" -then - plugin_swap="yes" -fi - # libstatgrab if test "x$with_libstatgrab" = "xyes" then @@@ -4487,10 -4127,7 +4489,10 @@@ f if test "x$with_libcurl" = "xyes" && test "x$with_libxml2" = "xyes" then plugin_ascent="yes" - plugin_bind="yes" + if test "x$have_strptime" = "xyes" + then + plugin_bind="yes" + fi fi if test "x$with_libopenipmipthread" = "xyes" @@@ -4516,15 -4153,11 +4518,15 @@@ if test "x$have_sysctl" = "xyes then plugin_cpu="yes" plugin_memory="yes" - plugin_swap="yes" plugin_uptime="yes" + if test "x$ac_system" = "xDarwin" + then + plugin_swap="yes" + fi fi if test "x$have_sysctlbyname" = "xyes" then + plugin_contextswitch="yes" plugin_cpu="yes" plugin_memory="yes" plugin_tcpconns="yes" @@@ -4612,7 -4245,7 +4614,7 @@@ the plugin_swap="yes" fi -if test "x$have_swapctl" = "xyes" +if test "x$have_swapctl" = "xyes" && test "x$c_cv_have_swapctl_two_args" = "xyes" then plugin_swap="yes" fi @@@ -4652,7 -4285,6 +4654,7 @@@ AC_ARG_ENABLE([all-plugins] m4_divert_once([HELP_ENABLE], []) +AC_PLUGIN([amqp], [$with_librabbitmq], [AMQP output plugin]) AC_PLUGIN([apache], [$with_libcurl], [Apache httpd statistics]) AC_PLUGIN([apcups], [yes], [Statistics of UPSes by APC]) AC_PLUGIN([apple_sensors], [$with_libiokit], [Apple's hardware sensors]) @@@ -4687,7 -4319,6 +4689,7 @@@ AC_PLUGIN([java], [$with_java] AC_PLUGIN([libvirt], [$plugin_libvirt], [Virtual machine statistics]) AC_PLUGIN([load], [$plugin_load], [System load]) AC_PLUGIN([logfile], [yes], [File logging plugin]) +AC_PLUGIN([lpar], [$with_perfstat], [AIX logical partitions statistics]) 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]) @@@ -4723,7 -4354,6 +4725,7 @@@ AC_PLUGIN([powerdns], [yes] 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([redis], [$with_libcredis], [Redis plugin]) AC_PLUGIN([routeros], [$with_librouteros], [RouterOS plugin]) AC_PLUGIN([rrdcached], [$librrd_rrdc_update], [RRDTool output plugin]) AC_PLUGIN([rrdtool], [$with_librrd], [RRDTool output plugin]) @@@ -4739,23 -4369,19 +4741,23 @@@ AC_PLUGIN([target_notification], [yes] 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([target_v5upgrade], [yes], [The v5upgrade target]) AC_PLUGIN([tcpconns], [$plugin_tcpconns], [TCP connection statistics]) AC_PLUGIN([teamspeak2], [yes], [TeamSpeak2 server statistics]) AC_PLUGIN([ted], [$plugin_ted], [Read The Energy Detective values]) AC_PLUGIN([thermal], [$plugin_thermal], [Linux ACPI thermal zone statistics]) +AC_PLUGIN([threshold], [yes], [Threshold checking plugin]) AC_PLUGIN([tokyotyrant], [$with_libtokyotyrant], [TokyoTyrant database statistics]) AC_PLUGIN([unixsock], [yes], [Unixsock communication plugin]) AC_PLUGIN([uptime], [$plugin_uptime], [Uptime statistics]) AC_PLUGIN([users], [$plugin_users], [User statistics]) AC_PLUGIN([uuid], [yes], [UUID as hostname plugin]) +AC_PLUGIN([varnish], [$with_libvarnish], [Varnish cache statistics]) AC_PLUGIN([vmem], [$plugin_vmem], [Virtual memory statistics]) AC_PLUGIN([vserver], [$plugin_vserver], [Linux VServer statistics]) AC_PLUGIN([wireless], [$plugin_wireless], [Wireless statistics]) AC_PLUGIN([write_http], [$with_libcurl], [HTTP output plugin]) +AC_PLUGIN([write_redis], [$with_libcredis], [Redis output plugin]) AC_PLUGIN([xmms], [$with_libxmms], [XMMS statistics]) AC_PLUGIN([zfs_arc], [$plugin_zfs_arc], [ZFS ARC statistics]) @@@ -4930,7 -4556,6 +4932,7 @@@ Configuration Libraries: libcurl . . . . . . . $with_libcurl libdbi . . . . . . . $with_libdbi + libcredis . . . . . . $with_libcredis libesmtp . . . . . . $with_libesmtp libganglia . . . . . $with_libganglia libgcrypt . . . . . . $with_libgcrypt @@@ -4954,14 -4579,12 +4956,14 @@@ libperl . . . . . . . $with_libperl libpq . . . . . . . . $with_libpq libpthread . . . . . $with_libpthread + librabbitmq . . . . . $with_librabbitmq librouteros . . . . . $with_librouteros librrd . . . . . . . $with_librrd libsensors . . . . . $with_libsensors libstatgrab . . . . . $with_libstatgrab libtokyotyrant . . . $with_libtokyotyrant libupsclient . . . . $with_libupsclient + libvarnish . . . . . $with_libvarnish libvirt . . . . . . . $with_libvirt libxml2 . . . . . . . $with_libxml2 libxmms . . . . . . . $with_libxmms @@@ -4979,7 -4602,6 +4981,7 @@@ perl . . . . . . . . $with_perl_bindings Modules: + amqp . . . . . . . $enable_amqp apache . . . . . . . $enable_apache apcups . . . . . . . $enable_apcups apple_sensors . . . . $enable_apple_sensors @@@ -5014,7 -4636,6 +5016,7 @@@ libvirt . . . . . . . $enable_libvirt load . . . . . . . . $enable_load logfile . . . . . . . $enable_logfile + lpar... . . . . . . . $enable_lpar madwifi . . . . . . . $enable_madwifi match_empty_counter . $enable_match_empty_counter match_hashed . . . . $enable_match_hashed @@@ -5049,7 -4670,6 +5051,7 @@@ processes . . . . . . $enable_processes protocols . . . . . . $enable_protocols python . . . . . . . $enable_python + redis . . . . . . . . $enable_redis routeros . . . . . . $enable_routeros rrdcached . . . . . . $enable_rrdcached rrdtool . . . . . . . $enable_rrdtool @@@ -5065,23 -4685,19 +5067,23 @@@ target_replace . . . $enable_target_replace target_scale . . . . $enable_target_scale target_set . . . . . $enable_target_set + target_v5upgrade . . $enable_target_v5upgrade tcpconns . . . . . . $enable_tcpconns teamspeak2 . . . . . $enable_teamspeak2 ted . . . . . . . . . $enable_ted thermal . . . . . . . $enable_thermal + threshold . . . . . . $enable_threshold tokyotyrant . . . . . $enable_tokyotyrant unixsock . . . . . . $enable_unixsock uptime . . . . . . . $enable_uptime users . . . . . . . . $enable_users uuid . . . . . . . . $enable_uuid + varnish . . . . . . . $enable_varnish vmem . . . . . . . . $enable_vmem vserver . . . . . . . $enable_vserver wireless . . . . . . $enable_wireless write_http . . . . . $enable_write_http + write_redis . . . . . $enable_write_redis xmms . . . . . . . . $enable_xmms zfs_arc . . . . . . . $enable_zfs_arc diff --combined src/Makefile.am index 259a3816,fd85107f..ba59bf54 --- a/src/Makefile.am +++ b/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 \ @@@ -40,7 -40,7 +40,7 @@@ 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) @@@ -85,7 -85,7 +85,7 @@@ endi if BUILD_WITH_OWN_LIBOCONFIG collectd_LDADD += $(LIBLTDL) liboconfig/liboconfig.la - collectd_DEPENDENCIES += $(LIBLTDL) liboconfig/liboconfig.la + collectd_DEPENDENCIES += liboconfig/liboconfig.la else collectd_LDADD += -loconfig endif @@@ -105,36 -105,11 +105,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 -501,6 +526,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 -887,6 +921,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 -1044,6 +1088,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 -1080,6 +1132,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 -1098,7 +1158,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 -1145,6 +1204,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 -1184,6 +1253,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 -1208,12 +1287,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 -1224,6 +1305,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 \ @@@ -1313,7 -1231,6 +1313,7 @@@ collectd-python.pod \ collectd.pod \ collectd-snmp.pod \ + collectd-threshold.pod \ collectd-unixsock.pod \ postgresql_default.conf \ types.db.pod diff --combined src/collectd.conf.pod index 1b0c2fd9,274e3887..1c0f4f07 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@@ -72,19 -72,15 +72,19 @@@ options are allowed inside a Bg., when loading a plugin -that embeds some scripting language into the daemon (e.Eg. the C -or C 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 and +I). 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.Eg., -L or L) for details. +interpreter, which is loaded as a dependency of the respective collectd plugin. +See the documentation of those plugins (e.g., L or +L) for details. + +By default, this is disabled. As a special exception, if the plugin name is +either C or C, 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 -141,7 +145,7 @@@ missing when no update has been receive this setting uses iterations, the maximum allowed time without update depends on the I information contained in each value list. This is used in the I configuration to dispatch notifications about missing values, -see L<"THRESHOLD CONFIGURATION"> below. +see L for details. =item B I @@@ -163,8 -159,13 +163,8 @@@ hostname will be determined using the L If B 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. - -Using this feature (i.Ee. setting this option to B) is recommended. -However, to preserve backwards compatibility the default is set to B. -The sample config file that is installed with Cinstall> 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. This option +is enabled by default. =item B I @@@ -189,143 -190,6 +189,143 @@@ A list of all plugins and a short summa F file shipped with the sourcecode and hopefully binary packets as well. +=head2 Plugin C + +The I can be used to communicate with other instances of +I 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. + + + # Send values to an AMQP broker + + Host "localhost" + Port "5672" + VHost "/" + User "guest" + Password "guest" + Exchange "amq.fanout" + # ExchangeType "fanout" + # RoutingKey "collectd" + # Persistent false + # Format "command" + # StoreRates false + + + # Receive values from an AMQP broker + + Host "localhost" + Port "5672" + VHost "/" + User "guest" + Password "guest" + Exchange "amq.fanout" + # ExchangeType "fanout" + # Queue "queue_name" + # RoutingKey "collectd.#" + + + +The plugin's configuration consists of a number of I and I +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 of certain +I blocks in the future. + +=over 4 + +=item B I + +Hostname or IP-address of the AMQP broker. Defaults to the default behavior of +the underlying communications library, I, which is "localhost". + +=item B I + +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 I + +Name of the I on the AMQP broker to use. Defaults to "/". + +=item B I + +=item B I + +Credentials used to authenticate to the AMQP broker. By default "guest"/"guest" +is used. + +=item B I + +In I blocks, this option specifies the I to send values to. +By default, "amq.fanout" will be used. + +In I blocks this option is optional. If given, a I between +the given exchange and the I is created, using the I if +configured. See the B and B options below. + +=item B I + +If given, the plugin will try to create the configured I with this +I after connecting. When in a I block, the I will then +be bound to this exchange. + +=item B I (Subscribe only) + +Configures the I name to subscribe to. If no queue name was configures +explicitly, a unique queue name will be created by the broker. + +=item B I + +In I blocks, this configures the routing key to set on all outgoing +messages. If not given, the routing key will be computed from the I +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 blocks, configures the I used when creating a +I between an I and the I. 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 B|B (Publish only) + +Selects the I to use. If set to B, the I +mode will be used, i.e. delivery is guaranteed. If set to B (the +default), the I delivery mode will be used, i.e. messages may be +lost due to high load, overflowing queues or similar issues. + +=item B B|B (Publish only) + +Selects the format in which messages are sent to the broker. If set to +B (the default), values are sent as C commands which are +identical to the syntax used by the I and I. In this +case, the C header field will be set to C. + +If set to B, the values are encoded in the I, +an easy and straight forward exchange format. The C header field +will be set to C. + +A subscribing client I use the C header field to +determine how to decode the values. Currently, the I itself can +only decode the B format. + +=item B B|B (Publish only) + +Determines whether or not C, C and C data sources +are converted to a I (i.e. a C value). If set to B (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 option has +been set to B. + +=back + =head2 Plugin C To configure the C-plugin you first need to configure the Apache @@@ -344,25 -208,7 +344,25 @@@ Since its C module is very also supported. It introduces a new field, called C, to count the number of currently connected clients. This field is also supported. -The following options are accepted by the C-plugin: +The configuration of the I plugin consists of one or more +CInstanceE/E> blocks. Each block requires one string argument +as the instance name. For example: + + + + URL "http://www1.example.com/mod_status?auto" + + + URL "http://www2.example.com/mod_status?auto" + + + +The instance name will be used as the I. To emulate the old +(versionE4) 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 block: =over 4 @@@ -370,7 -216,7 +370,7 @@@ Sets the URL of the C output. This needs to be the output generated by C and it needs to be the machine readable output -generated by appending the C argument. +generated by appending the C argument. This option is I. =item B I @@@ -739,6 -585,22 +739,6 @@@ runtime statistics module of CouchD -Another CouchDB example: -The following example will collect the status values from each database: - - - Instance "dbs" - - Type "gauge" - - - Type "counter" - - - Type "bytes" - - - In the B block, there may be one or more B blocks, each defining a URL to be fetched via HTTP (using libcurl) and one or more B blocks. The B string argument must be in a path format, which is used to collect a @@@ -1168,6 -1030,22 +1168,6 @@@ Report using the device name rather tha (the default), it will report a disk as "root", but with it I, it will be "sda1" (or whichever). -=item B B|B - -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) 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 B|B Enables or disables reporting of free, reserved and used inodes. Defaults to @@@ -1487,6 -1365,13 +1487,6 @@@ Hostname to connect to. Defaults to B<1 TCP-Port to connect to. Defaults to B<7634>. -=item B I|I - -If enabled, translate the disk names to major/minor device numbers -(e.Eg. "8-0" for /dev/sda). For backwards compatibility this defaults to -I but it's recommended to disable it as it will probably be removed in -the next major version. - =back =head2 Plugin C @@@ -1714,16 -1599,6 +1714,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 B|B
+ +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. + +B
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 @@@ -1742,8 -1617,8 +1742,8 @@@ debugging support Sets the file to write log messages to. The special strings B and B 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 +is running in foreground- or non-daemon-mode. =item B B|B @@@ -1760,33 -1635,6 +1760,33 @@@ B: There is no need to notify th log file (e.Eg. when rotating the logs). The plugin reopens the file for each line it writes. +=head2 Plugin C + +The I reads CPU statistics of I, 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 B|B + +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 B|B + +If enabled, the serial of the physical machine the partition is currently +running on is reported as I and the logical hostname of the machine +is reported in the I. Otherwise, the logical hostname will be +used (just like other plugins) and the I will be empty. +Defaults to false. + +=back + =head2 Plugin C The C uses mbmon to retrieve temperature, voltage, etc. @@@ -2012,7 -1860,7 +2012,7 @@@ B option is mandatory The C requires B 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 / C command and collects information about MySQL network traffic, executed statements, @@@ -2654,10 -2502,18 +2654,18 @@@ The default IPv6 multicast group is C. The default I port is B<25826>. Both, B and B can be used as single option or as block. When - used as block, given options are valid for this socket only. For example: + used as block, given options are valid for this socket only. The following + example will export the metrics twice: Once to an "internal" server (without + encryption and signing) and one to an external server (with cryptographic + signature): + # Export to an internal server + # (demonstrates usage without additional options) Server "collectd.internal.tld" + + # Export to an external server + # (demonstrates usage with signature options) SecurityLevel "sign" Username "myhostname" @@@ -2786,18 -2642,7 +2794,18 @@@ operating systems =item B 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 1452Ebytes, which is the maximum +payload size that can be transmitted in one Ethernet frame using IPv6E/ +UDP. + +On the server side, this limit should be set to the largest value used on +I client. Likewise, the value on the client must not be larger than the +value on the server, or data will be lost. + +B Versions prior to I4.8> used a fixed sized +buffer of 1024Ebytes. Versions I<4.8>, I<4.9> and I<4.10> used a default +value of 1024Ebytes to avoid problems when sending data to an older +server. =item B I @@@ -2808,6 -2653,16 +2816,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 I - -For each host/plugin/type combination the C caches the time of -the last value being sent or received. Every I seconds the plugin -searches and removes all entries that are older than I 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 B|B The network plugin cannot only receive and send statistics, it can also create @@@ -3442,6 -3297,11 +3450,6 @@@ allowed as long as a single non-empty c The returned lines will be handled separately one after another. -=item B I - -This is a deprecated synonym for B. It will be removed in version 5 -of collectd. - =item B I|I|I|I Specify the parameters which should be passed to the SQL query. The parameters @@@ -3517,6 -3377,21 +3525,6 @@@ This option is required inside a B options are specified, the columns are read in the given order. -=item B I [I] - -This is a deprecated alternative to a B block. It will be removed in -version 5 of collectd. It is equivalent to the following B block: - - - Type I - InstancePrefix I - ValuesFrom I - - -The order of the B 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 I =item B I @@@ -3531,6 -3406,13 +3539,6 @@@ The I 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 I - -=item B I - -These are deprecated synonyms for B and B -respectively. They will be removed in version 5 of collectd. - =back The following predefined queries are available (the definitions can be found @@@ -3941,52 -3823,6 +3949,52 @@@ Defaults to B =back +=head2 Plugin C + +The I connects to one or more Redis servers and gathers +information about each server's state. For each server there is a I block +which configures the connection parameters for this node. + + + + Host "localhost" + Port "6379" + Timeout 2000 + + + +The information shown in the synopsis above is the I +which is used by the plugin if no configuration is present. + +=over 4 + +=item B I + +The B 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. It is limited to +64Echaracters in length. + +=item B I + +The B option is the hostname or IP-address where the Redis instance is +running on. + +=item B I + +The B 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 I + +The B 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 values for all B should be lower +than B defined globally. + +=back + =head2 Plugin C The C plugin uses the RRDtool accelerator daemon, L, @@@ -4150,7 -3986,7 +4158,7 @@@ because all values were added to the in =head2 Plugin C -The C uses B to retrieve sensor-values. This means +The I uses B 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. Read L for details. @@@ -4185,25 -4021,6 +4193,25 @@@ Since the configuration of the C. Please see there for details. +=head2 Plugin C + +The I collects information about used and available swap space. On +I, the following options are available: + +=over 4 + +=item B B|B + +Configures how to report physical swap devices. If set to B 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 is configured, the used +and available space of each device will be reported separately. + +This option is only available if the I can use the L +mechanism under I. + +=back + =head2 Plugin C =over 4 @@@ -4553,7 -4370,7 +4561,7 @@@ port in numeric form =item B I|I -By default, the C plugin tries to read the statistics from the Linux +By default, the I tries to read the statistics from the Linux C interface. If that is not available, the plugin falls back to the C interface. By setting this option to I, you can force the plugin to use the latter. This option defaults to I. @@@ -4573,18 -4390,9 +4581,18 @@@ selection is configured at all, B =back +=head2 Plugin C + +The I checks values collected or received by I +against a configurable I and issues I if values are +out of bounds. + +Documentation for this plugin is available in the L +manual page. + =head2 Plugin C -The C connects to a TokyoTyrant server and collects a +The I connects to a TokyoTyrant server and collects a couple metrics: number of records, and database size on disk. =over 4 @@@ -4621,13 -4429,6 +4629,13 @@@ Change the file permissions of the UNIX permissions must be given as a numeric, octal value as you would pass to L. Defaults to B<0770>. +=item B B|B + +If set to B, delete the socket file before calling L, if a file +with the given name already exists. If I 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. + =back =head2 Plugin C @@@ -4671,68 -4472,6 +4679,68 @@@ Take the UUID from the given file (defa =back +=head2 Plugin C + +The Varnish plugin collects information about Varnish, an HTTP accelerator. + +=over 4 + +=item B B|B + +Cache hits and misses. True by default. + +=item B B|B + +Number of client connections received, accepted and dropped. True by default. + +=item B B|B + +Back-end connection statistics, such as successful, reused, +and closed connections. True by default. + +=item B B|B + +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 B|B + +Edge Side Includes (ESI) parse statistics. False by default. + +=item B B|B + +Statistics about fetches (HTTP requests sent to the backend). False by default. + +=item B B|B + +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 B|B + +malloc or umem (umem_alloc(3MALLOC) based) storage statistics. +The umem storage component is Solaris specific. False by default. + +=item B B|B + +synth (synthetic content) storage statistics. This storage +component is used internally only. False by default. + +=item B B|B + +file (memory mapped file) storage statistics. False by default. + +=item B B|B + +Collects overview counters, such as the number of sessions created, +the number of requests and bytes transferred. False by default. + +=item B B|B + +Collect statistics about worker threads. False by default. + +=back + =head2 Plugin C The C plugin collects information about the usage of virtual memory. @@@ -4831,6 -4570,170 +4839,170 @@@ number =back + =head1 THRESHOLD CONFIGURATION + + Starting with version C<4.3.0> collectd has support for B. By that + we mean that the values are not only stored or sent somewhere, but that they + are judged and, if a problem is recognized, acted upon. The only action + collectd takes itself is to generate and dispatch a "notification". Plugins can + register to receive notifications and perform appropriate further actions. + + Since systems and what you expect them to do differ a lot, you can configure + B for your values freely. This gives you a lot of flexibility but + also a lot of responsibility. + + Every time a value is out of range a notification is dispatched. This means + that the idle percentage of your CPU needs to be less then the configured + threshold only once for a notification to be generated. There's no such thing + as a moving average or similar - at least not now. + + Also, all values that match a threshold are considered to be relevant or + "interesting". As a consequence collectd will issue a notification if they are + not received for B iterations. The B configuration option is + explained in section L<"GLOBAL OPTIONS">. If, for example, B is set to + "2" (the default) and some hosts sends it's CPU statistics to the server every + 60 seconds, a notification will be dispatched after about 120 seconds. It may + take a little longer because the timeout is checked only once each B + on the server. + + When a value comes within range again or is received after it was missing, an + "OKAY-notification" is dispatched. + + Here is a configuration example to get you started. Read below for more + information. + + + + WarningMin 0.00 + WarningMax 1000.00 + FailureMin 0.00 + FailureMax 1200.00 + Invert false + Instance "bar" + + + + Instance "eth0" + + FailureMax 10000000 + DataSource "rx" + + + + + + Instance "idle" + FailureMin 10 + + + + + Instance "cached" + WarningMin 100000000 + + + + + + There are basically two types of configuration statements: The C, + C, and C blocks select the value for which a threshold should be + configured. The C and C blocks may be specified further using the + C option. You can combine the block by nesting the blocks, though + they must be nested in the above order, i.Ee. C may contain either + C and C blocks, C may only contain C blocks and + C may not contain other blocks. If multiple blocks apply to the same + value the most specific block is used. + + The other statements specify the threshold to configure. They B be + included in a C block. Currently the following statements are recognized: + + =over 4 + + =item B I + + =item B I + + Sets the upper bound of acceptable values. If unset defaults to positive + infinity. If a value is greater than B a B notification + will be created. If the value is greater than B but less than (or + equal to) B a B notification will be created. + + =item B I + + =item B I + + Sets the lower bound of acceptable values. If unset defaults to negative + infinity. If a value is less than B a B notification will + be created. If the value is less than B but greater than (or equal + to) B a B notification will be created. + + =item B I + + Some data sets have more than one "data source". Interesting examples are the + C data set, which has received (C) and sent (C) bytes and + the C data set, which holds C and C operations. The + system load data set, C, even has three data sources: C, + C, and C. + + Normally, all data sources are checked against a configured threshold. If this + is undesirable, or if you want to specify different limits for each data + source, you can use the B option to have a threshold apply only to + one data source. + + =item B B|B + + If set to B the range of acceptable values is inverted, i.Ee. + values between B and B (B and + B) are not okay. Defaults to B. + + =item B B|B + + Sets how often notifications are generated. If set to B one notification + will be generated for each value that is out of the acceptable range. If set to + B (the default) then a notification is only generated if a value is out + of range but the previous value was okay. + + This applies to missing values, too: If set to B a notification about a + missing value is generated once every B seconds. If set to B + only one such notification is generated until the value appears again. + + =item B B|B + + If set to B, the minimum and maximum values given are interpreted as + percentage value, relative to the other data sources. This is helpful for + example for the "df" type, where you may want to issue a warning when less than + 5E% of the total space is available. Defaults to B. + + =item B I + + Delay creating the notification until the threshold has been passed I + times. When a notification has been generated, or when a subsequent value is + inside the threshold, the counter is reset. If, for example, a value is + collected once every 10Eseconds and B is set to 3, a notification + will be dispatched at most once every 30Eseconds. + + This is useful when short bursts are not a problem. If, for example, 100% CPU + usage for up to a minute is normal (and data is collected every + 10Eseconds), you could set B to B<6> to account for this. + + =item B I + + When set to non-zero, a hysteresis value is applied when checking minimum and + maximum bounds. This is useful for values that increase slowly and fluctuate a + bit while doing so. When these values come close to the threshold, they may + "flap", i.e. switch between failure / warning case and okay case repeatedly. + + If, for example, the threshold is configures as + + WarningMax 100.0 + Hysteresis 1.0 + + then a I notification is created when the value exceeds I<101> and the + corresponding I notification is only created once the value falls below + I<99>, thus avoiding the "flapping". + + =back + =head1 FILTER CONFIGURATION Starting with collectd 4.6 there is a powerful filtering infrastructure diff --combined src/common.c index 0069a8b6,c5bd6470..459c7024 --- a/src/common.c +++ b/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 + * Florian octo Forster * Niki W. Waibel * Sebastian Harl * Michał Mirosław @@@ -29,7 -29,6 +29,7 @@@ #include "collectd.h" #include "common.h" #include "plugin.h" +#include "utils_cache.h" #if HAVE_PTHREAD_H # include @@@ -39,6 -38,11 +39,6 @@@ # include #endif -/* for ntohl and htonl */ -#if HAVE_ARPA_INET_H -# include -#endif - /* for getaddrinfo */ #include #include @@@ -48,11 -52,6 +48,11 @@@ # include #endif +/* for ntohl and htonl */ +#if HAVE_ARPA_INET_H +# include +#endif + #ifdef HAVE_LIBKSTAT extern kstat_ctl_t *kc; #endif @@@ -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) @@@ -919,43 -849,25 +919,59 @@@ 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, value_t *ret_value, int ds_type) + int parse_value (const char *value_orig, value_t *ret_value, int ds_type) { + char *value; char *endptr = NULL; + size_t value_len; + + if (value_orig == NULL) + return (EINVAL); + + value = strdup (value_orig); + if (value == NULL) + return (ENOMEM); + value_len = strlen (value); + + while ((value_len > 0) && isspace ((int) value[value_len - 1])) + { + value[value_len - 1] = 0; + value_len--; + } switch (ds_type) { @@@ -976,11 -888,13 +992,13 @@@ break; default: + sfree (value); ERROR ("parse_value: Invalid data source type: %i.", ds_type); return -1; } if (value == endptr) { + sfree (value); ERROR ("parse_value: Failed to parse string as %s: %s.", DS_TYPE_TO_STRING (ds_type), value); return -1; @@@ -988,8 -902,9 +1006,9 @@@ else if ((NULL != endptr) && ('\0' != *endptr)) INFO ("parse_value: Ignoring trailing garbage \"%s\" after %s value. " "Input string was \"%s\".", - endptr, DS_TYPE_TO_STRING (ds_type), value); + endptr, DS_TYPE_TO_STRING (ds_type), value_orig); + sfree (value); return 0; } /* int parse_value */ @@@ -1017,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/common.h index e6b899de,c292abfd..6b11b538 --- a/src/common.h +++ b/src/common.h @@@ -1,6 -1,6 +1,6 @@@ /** * collectd - src/common.h - * 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 + * Florian octo Forster * Niki W. Waibel **/ @@@ -258,14 -258,10 +258,14 @@@ int format_name (char *ret, int ret_len #define FORMAT_VL(ret, ret_len, vl) \ format_name (ret, ret_len, (vl)->host, (vl)->plugin, (vl)->plugin_instance, \ (vl)->type, (vl)->type_instance) +int format_values (char *ret, size_t ret_len, + const data_set_t *ds, const value_list_t *vl, + _Bool store_rates); int parse_identifier (char *str, char **ret_host, char **ret_plugin, char **ret_plugin_instance, char **ret_type, char **ret_type_instance); +int parse_identifier_vl (const char *str, value_list_t *vl); int parse_value (const char *value, value_t *ret_value, int ds_type); int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds); @@@ -278,15 -274,16 +278,16 @@@ int notification_init (notification_t * const char *host, const char *plugin, const char *plugin_instance, const char *type, const char *type_instance); -#define NOTIFICATION_INIT_VL(n, vl, ds) \ +#define NOTIFICATION_INIT_VL(n, vl) \ notification_init (n, NOTIF_FAILURE, NULL, \ (vl)->host, (vl)->plugin, (vl)->plugin_instance, \ - (ds)->type, (vl)->type_instance) + (vl)->type, (vl)->type_instance) typedef int (*dirwalk_callback_f)(const char *dirname, const char *filename, void *user_data); int walk_directory (const char *dir, dirwalk_callback_f callback, void *user_data, int hidden); + /* Returns the number of bytes read or negative on error. */ int read_file_contents (const char *filename, char *buf, int bufsize); counter_t counter_diff (counter_t old_value, counter_t new_value); diff --combined src/libcollectdclient/client.c index 3eb0d055,2f427a83..f5fe2049 --- a/src/libcollectdclient/client.c +++ b/src/libcollectdclient/client.c @@@ -164,14 -164,27 +164,14 @@@ static int lcc_set_errno (lcc_connectio return (0); } /* }}} int lcc_set_errno */ -/* lcc_strdup: Since `strdup' is an XSI extension, we provide our own version - * here. */ -__attribute__((malloc, nonnull (1))) -static char *lcc_strdup (const char *str) /* {{{ */ -{ - size_t strsize; - char *ret; - - strsize = strlen (str) + 1; - ret = (char *) malloc (strsize); - if (ret != NULL) - memcpy (ret, str, strsize); - return (ret); -} /* }}} char *lcc_strdup */ - -__attribute__((nonnull (1, 2))) static char *lcc_strescape (char *dest, const char *src, size_t dest_size) /* {{{ */ { size_t dest_pos; size_t src_pos; + if ((dest == NULL) || (src == NULL)) + return (NULL); + dest_pos = 0; src_pos = 0; @@@ -325,7 -338,7 +325,7 @@@ static int lcc_receive (lcc_connection_ lcc_chomp (buffer); LCC_DEBUG ("receive: <-- %s\n", buffer); - res.lines[i] = lcc_strdup (buffer); + res.lines[i] = strdup (buffer); if (res.lines[i] == NULL) { lcc_set_errno (c, ENOMEM); @@@ -720,7 -733,7 +720,7 @@@ int lcc_getval (lcc_connection_t *c, lc if (values_names != NULL) { - values_names[i] = lcc_strdup (key); + values_names[i] = strdup (key); if (values_names[i] == NULL) BAIL_OUT (ENOMEM); } @@@ -733,6 -746,8 +733,8 @@@ if (ret_values_names != NULL) *ret_values_names = values_names; + lcc_response_free (&res); + return (0); } /* }}} int lcc_getval */ @@@ -775,7 -790,7 +777,7 @@@ int lcc_putval (lcc_connection_t *c, co else if (vl->values_types[i] == LCC_TYPE_GAUGE) { if (isnan (vl->values[i].gauge)) - SSTRCPY (command, ":U"); + SSTRCATF (command, ":U"); else SSTRCATF (command, ":%g", vl->values[i].gauge); } @@@ -1000,7 -1015,7 +1002,7 @@@ int lcc_string_to_identifier (lcc_conne char *type; char *type_instance; - string_copy = lcc_strdup (string); + string_copy = strdup (string); if (string_copy == NULL) { lcc_set_errno (c, ENOMEM); diff --combined src/memcached.c index ee3dbe12,4c9e6adc..48fa713b --- a/src/memcached.c +++ b/src/memcached.c @@@ -1,7 -1,7 +1,7 @@@ /** * collectd - src/memcached.c, based on src/hddtemp.c * Copyright (C) 2007 Antony Dovgal - * Copyright (C) 2007-2009 Florian Forster + * Copyright (C) 2007-2010 Florian Forster * Copyright (C) 2009 Doug MacEachern * Copyright (C) 2009 Franck Lombardi * @@@ -21,7 -21,7 +21,7 @@@ * * Authors: * Antony Dovgal - * Florian octo Forster + * Florian octo Forster * Doug MacEachern * Franck Lombardi **/ @@@ -176,14 -176,12 +176,14 @@@ static int memcached_query_daemon (cha p.events = POLLIN | POLLERR | POLLHUP; p.revents = 0; - status = poll (&p, /* nfds = */ 1, /* timeout = */ 1000 * interval_g); + status = poll (&p, /* nfds = */ 1, + /* timeout = */ CDTIME_T_TO_MS (interval_g)); if (status <= 0) { if (status == 0) { - ERROR ("memcached: poll(2) timed out after %i seconds.", interval_g); + ERROR ("memcached: poll(2) timed out after %.3f seconds.", + CDTIME_T_TO_DOUBLE (interval_g)); } else { @@@ -273,13 -271,13 +273,13 @@@ static int memcached_config (const cha } /* }}} */ -static void submit_counter (const char *type, const char *type_inst, - counter_t value) /* {{{ */ +static void submit_derive (const char *type, const char *type_inst, + derive_t value) /* {{{ */ { value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].counter = value; + values[0].derive = value; vl.values = values; vl.values_len = 1; @@@ -293,17 -291,18 +293,17 @@@ } /* void memcached_submit_cmd */ /* }}} */ -static void submit_counter2 (const char *type, const char *type_inst, - counter_t value0, counter_t value1) /* {{{ */ +static void submit_derive2 (const char *type, const char *type_inst, + derive_t value0, derive_t value1) /* {{{ */ { value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - values[0].counter = value0; - values[1].counter = value1; + values[0].derive = value0; + values[1].derive = value1; vl.values = values; vl.values_len = 2; - vl.time = time (NULL); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin)); sstrncpy (vl.type, type, sizeof (vl.type)); @@@ -324,6 -323,7 +324,6 @@@ static void submit_gauge (const char *t vl.values = values; vl.values_len = 1; - vl.time = time (NULL); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin)); sstrncpy (vl.type, type, sizeof (vl.type)); @@@ -345,6 -345,7 +345,6 @@@ static void submit_gauge2 (const char * vl.values = values; vl.values_len = 2; - vl.time = time (NULL); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin)); sstrncpy (vl.type, type, sizeof (vl.type)); @@@ -357,7 -358,7 +357,7 @@@ static int memcached_read (void) /* {{{ */ { - char buf[1024]; + char buf[4096]; char *fields[3]; char *ptr; char *line; @@@ -368,10 -369,10 +368,10 @@@ gauge_t bytes_total = NAN; gauge_t hits = NAN; gauge_t gets = NAN; - counter_t rusage_user = 0; - counter_t rusage_syst = 0; - counter_t octets_rx = 0; - counter_t octets_tx = 0; + derive_t rusage_user = 0; + derive_t rusage_syst = 0; + derive_t octets_rx = 0; + derive_t octets_tx = 0; /* get data from daemon */ if (memcached_query_daemon (buf, sizeof (buf)) < 0) { @@@ -456,7 -457,7 +456,7 @@@ else if ((name_len > 4) && (strncmp (fields[1], "cmd_", 4) == 0)) { const char *name = fields[1] + 4; - submit_counter ("memcached_command", name, atoll (fields[2])); + submit_derive ("memcached_command", name, atoll (fields[2])); if (strcmp (name, "get") == 0) gets = atof (fields[2]); } @@@ -466,16 -467,16 +466,16 @@@ */ else if (FIELD_IS ("get_hits")) { - submit_counter ("memcached_ops", "hits", atoll (fields[2])); + submit_derive ("memcached_ops", "hits", atoll (fields[2])); hits = atof (fields[2]); } else if (FIELD_IS ("get_misses")) { - submit_counter ("memcached_ops", "misses", atoll (fields[2])); + submit_derive ("memcached_ops", "misses", atoll (fields[2])); } else if (FIELD_IS ("evictions")) { - submit_counter ("memcached_ops", "evictions", atoll (fields[2])); + submit_derive ("memcached_ops", "evictions", atoll (fields[2])); } /* @@@ -495,10 -496,10 +495,10 @@@ submit_gauge2 ("df", "cache", bytes_used, bytes_total - bytes_used); if ((rusage_user != 0) || (rusage_syst != 0)) - submit_counter2 ("ps_cputime", NULL, rusage_user, rusage_syst); + submit_derive2 ("ps_cputime", NULL, rusage_user, rusage_syst); if ((octets_rx != 0) || (octets_tx != 0)) - submit_counter2 ("memcached_octets", NULL, octets_rx, octets_tx); + submit_derive2 ("memcached_octets", NULL, octets_rx, octets_tx); if (!isnan (gets) && !isnan (hits)) { diff --combined src/network.c index e0c329c6,34cd1c01..5fed1b19 --- a/src/network.c +++ b/src/network.c @@@ -1,6 -1,6 +1,6 @@@ /** * collectd - src/network.c - * Copyright (C) 2005-2009 Florian octo Forster + * Copyright (C) 2005-2010 Florian octo Forster * Copyright (C) 2009 Aman Gupta * * This program is free software; you can redistribute it and/or modify it @@@ -259,8 -259,7 +259,8 @@@ typedef struct receive_list_entry_s rec * Private variables */ static int network_config_ttl = 0; -static size_t network_config_packet_size = 1024; +/* Ethernet - (IPv6 + UDP) = 1500 - (40 + 8) = 1452 */ +static size_t network_config_packet_size = 1452; static int network_config_forward = 0; static int network_config_stats = 0; @@@ -297,14 -296,14 +297,14 @@@ static pthread_mutex_t send_buffer_loc * example). Only if neither is true, the stats_lock is acquired. The counters * are always read without holding a lock in the hope that writing 8 bytes to * memory is an atomic operation. */ -static uint64_t stats_octets_rx = 0; -static uint64_t stats_octets_tx = 0; -static uint64_t stats_packets_rx = 0; -static uint64_t stats_packets_tx = 0; -static uint64_t stats_values_dispatched = 0; -static uint64_t stats_values_not_dispatched = 0; -static uint64_t stats_values_sent = 0; -static uint64_t stats_values_not_sent = 0; +static derive_t stats_octets_rx = 0; +static derive_t stats_octets_tx = 0; +static derive_t stats_packets_rx = 0; +static derive_t stats_packets_tx = 0; +static derive_t stats_values_dispatched = 0; +static derive_t stats_values_not_dispatched = 0; +static derive_t stats_values_sent = 0; +static derive_t stats_values_not_sent = 0; static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER; /* @@@ -321,30 -320,30 +321,30 @@@ static _Bool check_receive_okay (const /* This is a value we already sent. Don't allow it to be received again in * order to avoid looping. */ if ((status == 0) && (time_sent >= ((uint64_t) vl->time))) - return (false); + return (0); - return (true); + return (1); } /* }}} _Bool check_receive_okay */ static _Bool check_send_okay (const value_list_t *vl) /* {{{ */ { - _Bool received = false; + _Bool received = 0; int status; if (network_config_forward != 0) - return (true); + return (1); if (vl->meta == NULL) - return (true); + return (1); status = meta_data_get_boolean (vl->meta, "network:received", &received); if (status == -ENOENT) - return (true); + return (1); else if (status != 0) { ERROR ("network plugin: check_send_okay: meta_data_get_boolean failed " "with status %i.", status); - return (true); + return (1); } /* By default, only *send* value lists that were not *received* by the @@@ -352,6 -351,43 +352,43 @@@ return (!received); } /* }}} _Bool check_send_okay */ + static _Bool check_notify_received (const notification_t *n) /* {{{ */ + { + notification_meta_t *ptr; + + for (ptr = n->meta; ptr != NULL; ptr = ptr->next) + if ((strcmp ("network:received", ptr->name) == 0) + && (ptr->type == NM_TYPE_BOOLEAN)) + return ((_Bool) ptr->nm_value.nm_boolean); + + return (0); + } /* }}} _Bool check_notify_received */ + + static _Bool check_send_notify_okay (const notification_t *n) /* {{{ */ + { + static c_complain_t complain_forwarding = C_COMPLAIN_INIT_STATIC; + _Bool received = 0; + + if (n->meta == NULL) + return (1); + + received = check_notify_received (n); + + if (network_config_forward && received) + { + c_complain_once (LOG_ERR, &complain_forwarding, + "network plugin: A notification has been received via the network " + "forwarding if enabled. Forwarding of notifications is currently " + "not supported, because there is not loop-deteciton available. " + "Please contact the collectd mailing list if you need this " + "feature."); + } + + /* By default, only *send* value lists that were not *received* by the + * network plugin. */ + return (!received); + } /* }}} _Bool check_send_notify_okay */ + static int network_dispatch_values (value_list_t *vl, /* {{{ */ const char *username) { @@@ -385,7 -421,7 +422,7 @@@ return (-ENOMEM); } - status = meta_data_add_boolean (vl->meta, "network:received", true); + status = meta_data_add_boolean (vl->meta, "network:received", 1); if (status != 0) { ERROR ("network plugin: meta_data_add_boolean failed."); @@@ -415,6 -451,29 +452,29 @@@ return (0); } /* }}} int network_dispatch_values */ + static int network_dispatch_notification (notification_t *n) /* {{{ */ + { + int status; + + assert (n->meta == NULL); + + status = plugin_notification_meta_add_boolean (n, "network:received", 1); + if (status != 0) + { + ERROR ("network plugin: plugin_notification_meta_add_boolean failed."); + plugin_notification_meta_free (n->meta); + n->meta = NULL; + return (status); + } + + status = plugin_dispatch_notification (n); + + plugin_notification_meta_free (n->meta); + n->meta = NULL; + + return (status); + } /* }}} int network_dispatch_notification */ + #if HAVE_LIBGCRYPT static gcry_cipher_hd_t network_get_aes256_cypher (sockent_t *se, /* {{{ */ const void *iv, size_t iv_size, const char *username) @@@ -705,7 -764,7 +765,7 @@@ static int parse_part_values (void **re exp_size = 3 * sizeof (uint16_t) + pkg_numval * (sizeof (uint8_t) + sizeof (value_t)); - if ((buffer_len < 0) || (buffer_len < exp_size)) + if (buffer_len < exp_size) { WARNING ("network plugin: parse_part_values: " "Packet too short: " @@@ -790,7 -849,7 +850,7 @@@ static int parse_part_number (void **re uint16_t pkg_length; - if ((buffer_len < 0) || ((size_t) buffer_len < exp_size)) + if (buffer_len < exp_size) { WARNING ("network plugin: parse_part_number: " "Packet too short: " @@@ -829,7 -888,7 +889,7 @@@ static int parse_part_string (void **re uint16_t pkg_length; - if ((buffer_len < 0) || (buffer_len < header_size)) + if (buffer_len < header_size) { WARNING ("network plugin: parse_part_string: " "Packet too short: " @@@ -1380,19 -1439,8 +1440,19 @@@ static int parse_packet (sockent_t *se &tmp); if (status == 0) { - vl.time = (time_t) tmp; - n.time = (time_t) tmp; + vl.time = TIME_T_TO_CDTIME_T (tmp); + n.time = TIME_T_TO_CDTIME_T (tmp); + } + } + else if (pkg_type == TYPE_TIME_HR) + { + uint64_t tmp = 0; + status = parse_part_number (&buffer, &buffer_size, + &tmp); + if (status == 0) + { + vl.time = (cdtime_t) tmp; + n.time = (cdtime_t) tmp; } } else if (pkg_type == TYPE_INTERVAL) @@@ -1401,15 -1449,7 +1461,15 @@@ status = parse_part_number (&buffer, &buffer_size, &tmp); if (status == 0) - vl.interval = (int) tmp; + vl.interval = TIME_T_TO_CDTIME_T (tmp); + } + else if (pkg_type == TYPE_INTERVAL_HR) + { + uint64_t tmp = 0; + status = parse_part_number (&buffer, &buffer_size, + &tmp); + if (status == 0) + vl.interval = (cdtime_t) tmp; } else if (pkg_type == TYPE_HOST) { @@@ -1484,7 -1524,7 +1544,7 @@@ } else { - plugin_dispatch_notification (&n); + network_dispatch_notification (&n); } } else if (pkg_type == TYPE_SEVERITY) @@@ -2606,7 -2646,7 +2666,7 @@@ static int add_to_buffer (char *buffer if (vl_def->time != vl->time) { - if (write_part_number (&buffer, &buffer_size, TYPE_TIME, + if (write_part_number (&buffer, &buffer_size, TYPE_TIME_HR, (uint64_t) vl->time)) return (-1); vl_def->time = vl->time; @@@ -2614,7 -2654,7 +2674,7 @@@ if (vl_def->interval != vl->interval) { - if (write_part_number (&buffer, &buffer_size, TYPE_INTERVAL, + if (write_part_number (&buffer, &buffer_size, TYPE_INTERVAL_HR, (uint64_t) vl->interval)) return (-1); vl_def->interval = vl->interval; @@@ -3076,6 -3116,8 +3136,6 @@@ static int network_config (oconfig_item network_config_set_boolean (child, &network_config_forward); else if (strcasecmp ("ReportStats", child->key) == 0) network_config_set_boolean (child, &network_config_stats); - else if (strcasecmp ("CacheFlush", child->key) == 0) - /* no op for backwards compatibility only */; else { WARNING ("network plugin: Option `%s' is not allowed here.", @@@ -3087,16 -3129,19 +3147,19 @@@ } /* }}} int network_config */ static int network_notification (const notification_t *n, - user_data_t __attribute__((unused)) *user_data) + user_data_t __attribute__((unused)) *user_data) { char buffer[network_config_packet_size]; char *buffer_ptr = buffer; int buffer_free = sizeof (buffer); int status; - memset (buffer, '\0', sizeof (buffer)); + if (!check_send_notify_okay (n)) + return (0); + + memset (buffer, 0, sizeof (buffer)); - status = write_part_number (&buffer_ptr, &buffer_free, TYPE_TIME, + status = write_part_number (&buffer_ptr, &buffer_free, TYPE_TIME_HR, (uint64_t) n->time); if (status != 0) return (-1); @@@ -3109,7 -3154,7 +3172,7 @@@ if (strlen (n->host) > 0) { status = write_part_string (&buffer_ptr, &buffer_free, TYPE_HOST, - n->host, strlen (n->host)); + n->host, strlen (n->host)); if (status != 0) return (-1); } @@@ -3117,7 -3162,7 +3180,7 @@@ if (strlen (n->plugin) > 0) { status = write_part_string (&buffer_ptr, &buffer_free, TYPE_PLUGIN, - n->plugin, strlen (n->plugin)); + n->plugin, strlen (n->plugin)); if (status != 0) return (-1); } @@@ -3125,8 -3170,8 +3188,8 @@@ if (strlen (n->plugin_instance) > 0) { status = write_part_string (&buffer_ptr, &buffer_free, - TYPE_PLUGIN_INSTANCE, - n->plugin_instance, strlen (n->plugin_instance)); + TYPE_PLUGIN_INSTANCE, + n->plugin_instance, strlen (n->plugin_instance)); if (status != 0) return (-1); } @@@ -3134,7 -3179,7 +3197,7 @@@ if (strlen (n->type) > 0) { status = write_part_string (&buffer_ptr, &buffer_free, TYPE_TYPE, - n->type, strlen (n->type)); + n->type, strlen (n->type)); if (status != 0) return (-1); } @@@ -3142,7 -3187,7 +3205,7 @@@ if (strlen (n->type_instance) > 0) { status = write_part_string (&buffer_ptr, &buffer_free, TYPE_TYPE_INSTANCE, - n->type_instance, strlen (n->type_instance)); + n->type_instance, strlen (n->type_instance)); if (status != 0) return (-1); } @@@ -3201,15 -3246,15 +3264,15 @@@ static int network_shutdown (void static int network_stats_read (void) /* {{{ */ { - uint64_t copy_octets_rx; - uint64_t copy_octets_tx; - uint64_t copy_packets_rx; - uint64_t copy_packets_tx; - uint64_t copy_values_dispatched; - uint64_t copy_values_not_dispatched; - uint64_t copy_values_sent; - uint64_t copy_values_not_sent; - uint64_t copy_receive_list_length; + derive_t copy_octets_rx; + derive_t copy_octets_tx; + derive_t copy_packets_rx; + derive_t copy_packets_tx; + derive_t copy_values_dispatched; + derive_t copy_values_not_dispatched; + derive_t copy_values_sent; + derive_t copy_values_not_sent; + derive_t copy_receive_list_length; value_list_t vl = VALUE_LIST_INIT; value_t values[2]; @@@ -3232,14 -3277,14 +3295,14 @@@ sstrncpy (vl.plugin, "network", sizeof (vl.plugin)); /* Octets received / sent */ - vl.values[0].counter = (counter_t) copy_octets_rx; - vl.values[1].counter = (counter_t) copy_octets_tx; + vl.values[0].derive = (derive_t) copy_octets_rx; + vl.values[1].derive = (derive_t) copy_octets_tx; sstrncpy (vl.type, "if_octets", sizeof (vl.type)); plugin_dispatch_values_secure (&vl); /* Packets received / send */ - vl.values[0].counter = (counter_t) copy_packets_rx; - vl.values[1].counter = (counter_t) copy_packets_tx; + vl.values[0].derive = (derive_t) copy_packets_rx; + vl.values[1].derive = (derive_t) copy_packets_tx; sstrncpy (vl.type, "if_packets", sizeof (vl.type)); plugin_dispatch_values_secure (&vl); @@@ -3278,13 -3323,13 +3341,13 @@@ static int network_init (void) { - static _Bool have_init = false; + static _Bool have_init = 0; /* Check if we were already initialized. If so, just return - there's * nothing more to do (for now, that is). */ if (have_init) return (0); - have_init = true; + have_init = 1; #if HAVE_LIBGCRYPT gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); @@@ -3370,9 -3415,9 +3433,9 @@@ * just send the buffer if `flush' is called - if the requested value was in * there, good. If not, well, then there is nothing to flush.. -octo */ -static int network_flush (int timeout, - const char __attribute__((unused)) *identifier, - user_data_t __attribute__((unused)) *user_data) +static int network_flush (__attribute__((unused)) cdtime_t timeout, + __attribute__((unused)) const char *identifier, + __attribute__((unused)) user_data_t *user_data) { pthread_mutex_lock (&send_buffer_lock); diff --combined src/perl.c index f8a48227,41e763dc..a2568da2 --- a/src/perl.c +++ b/src/perl.c @@@ -33,10 -33,6 +33,10 @@@ #include "configfile.h" +#if HAVE_STDBOOL_H +# include +#endif + #include #include @@@ -235,6 -231,15 +235,6 @@@ struct { "", NULL } }; -struct { - char name[64]; - int *var; -} g_integers[] = -{ - { "Collectd::interval_g", &interval_g }, - { "", NULL } -}; - /* * Helper functions for data type conversion. */ @@@ -388,16 -393,10 +388,16 @@@ static int hv2value_list (pTHX_ HV *has } if (NULL != (tmp = hv_fetch (hash, "time", 4, 0))) - vl->time = (time_t)SvIV (*tmp); + { + double t = SvNV (*tmp); + vl->time = DOUBLE_TO_CDTIME_T (t); + } if (NULL != (tmp = hv_fetch (hash, "interval", 8, 0))) - vl->interval = SvIV (*tmp); + { + double t = SvNV (*tmp); + vl->interval = DOUBLE_TO_CDTIME_T (t); + } if (NULL != (tmp = hv_fetch (hash, "host", 4, 0))) sstrncpy (vl->host, SvPV_nolen (*tmp), sizeof (vl->host)); @@@ -549,12 -548,9 +549,12 @@@ static int hv2notification (pTHX_ HV *h n->severity = NOTIF_FAILURE; if (NULL != (tmp = hv_fetch (hash, "time", 4, 0))) - n->time = (time_t)SvIV (*tmp); + { + double t = SvNV (*tmp); + n->time = DOUBLE_TO_CDTIME_T (t); + } else - n->time = time (NULL); + n->time = cdtime (); if (NULL != (tmp = hv_fetch (hash, "message", 7, 0))) sstrncpy (n->message, SvPV_nolen (*tmp), sizeof (n->message)); @@@ -672,17 -668,11 +672,17 @@@ static int value_list2hv (pTHX_ value_l return -1; if (0 != vl->time) - if (NULL == hv_store (hash, "time", 4, newSViv (vl->time), 0)) + { + double t = CDTIME_T_TO_DOUBLE (vl->time); + if (NULL == hv_store (hash, "time", 4, newSVnv (t), 0)) return -1; + } - if (NULL == hv_store (hash, "interval", 8, newSViv (vl->interval), 0)) - return -1; + { + double t = CDTIME_T_TO_DOUBLE (vl->interval); + if (NULL == hv_store (hash, "interval", 8, newSVnv (t), 0)) + return -1; + } if ('\0' != vl->host[0]) if (NULL == hv_store (hash, "host", 4, newSVpv (vl->host, 0), 0)) @@@ -760,11 -750,8 +760,11 @@@ static int notification2hv (pTHX_ notif return -1; if (0 != n->time) - if (NULL == hv_store (hash, "time", 4, newSViv (n->time), 0)) + { + double t = CDTIME_T_TO_DOUBLE (n->time); + if (NULL == hv_store (hash, "time", 4, newSVnv (t), 0)) return -1; + } if ('\0' != *n->message) if (NULL == hv_store (hash, "message", 7, newSVpv (n->message, 0), 0)) @@@ -1115,15 -1102,11 +1115,15 @@@ static int pplugin_call_all (pTHX_ int XPUSHs (sv_2mortal (newRV_noinc ((SV *)notif))); } else if (PLUGIN_FLUSH == type) { + cdtime_t timeout; + /* * $_[0] = $timeout; * $_[1] = $identifier; */ - XPUSHs (sv_2mortal (newSViv (va_arg (ap, int)))); + timeout = va_arg (ap, cdtime_t); + + XPUSHs (sv_2mortal (newSVnv (CDTIME_T_TO_DOUBLE (timeout)))); XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0))); } @@@ -1627,29 -1610,40 +1627,29 @@@ static XS (Collectd_plugin_unregister_d static XS (Collectd_plugin_dispatch_values) { SV *values = NULL; - int values_idx = 0; int ret = 0; dXSARGS; - if (2 == items) { - log_warn ("Collectd::plugin_dispatch_values with two arguments " - "is deprecated - pass the type through values->{type}."); - values_idx = 1; - } - else if (1 != items) { + if (1 != items) { log_err ("Usage: Collectd::plugin_dispatch_values(values)"); XSRETURN_EMPTY; } log_debug ("Collectd::plugin_dispatch_values: values=\"%s\"", - SvPV_nolen (ST (values_idx))); + SvPV_nolen (ST (/* stack index = */ 0))); - values = ST (values_idx); + values = ST (/* stack index = */ 0); + /* Make sure the argument is a hash reference. */ if (! (SvROK (values) && (SVt_PVHV == SvTYPE (SvRV (values))))) { log_err ("Collectd::plugin_dispatch_values: Invalid values."); XSRETURN_EMPTY; } - if (((2 == items) && (NULL == ST (0))) || (NULL == values)) - XSRETURN_EMPTY; - - if ((2 == items) && (NULL == hv_store ((HV *)SvRV (values), "type", 4, - newSVsv (ST (0)), 0))) { - log_err ("Collectd::plugin_dispatch_values: Could not store type."); + if (NULL == values) XSRETURN_EMPTY; - } ret = pplugin_dispatch_values (aTHX_ (HV *)SvRV (values)); @@@ -1929,6 -1923,11 +1929,11 @@@ static int perl_read (void aTHX = t->interp; } + /* Assert that we're not running as the base thread. Otherwise, we might + * run into concurrency issues with c_ithread_create(). See + * https://github.com/collectd/collectd/issues/9 for details. */ + assert (aTHX != perl_threads->head->interp); + log_debug ("perl_read: c_ithread: interp = %p (active threads: %i)", aTHX, perl_threads->number_of_threads); return pplugin_call_all (aTHX_ PLUGIN_READ); @@@ -1937,6 -1936,7 +1942,7 @@@ static int perl_write (const data_set_t *ds, const value_list_t *vl, user_data_t __attribute__((unused)) *user_data) { + int status; dTHX; if (NULL == perl_threads) @@@ -1952,9 -1952,20 +1958,20 @@@ aTHX = t->interp; } + /* Lock the base thread if this is not called from one of the read threads + * to avoid race conditions with c_ithread_create(). See + * https://github.com/collectd/collectd/issues/9 for details. */ + if (aTHX == perl_threads->head->interp) + pthread_mutex_lock (&perl_threads->mutex); + log_debug ("perl_write: c_ithread: interp = %p (active threads: %i)", aTHX, perl_threads->number_of_threads); - return pplugin_call_all (aTHX_ PLUGIN_WRITE, ds, vl); + status = pplugin_call_all (aTHX_ PLUGIN_WRITE, ds, vl); + + if (aTHX == perl_threads->head->interp) + pthread_mutex_unlock (&perl_threads->mutex); + + return status; } /* static int perl_write (const data_set_t *, const value_list_t *) */ static void perl_log (int level, const char *msg, @@@ -1975,7 -1986,17 +1992,17 @@@ aTHX = t->interp; } + /* Lock the base thread if this is not called from one of the read threads + * to avoid race conditions with c_ithread_create(). See + * https://github.com/collectd/collectd/issues/9 for details. */ + if (aTHX == perl_threads->head->interp) + pthread_mutex_lock (&perl_threads->mutex); + pplugin_call_all (aTHX_ PLUGIN_LOG, level, msg); + + if (aTHX == perl_threads->head->interp) + pthread_mutex_unlock (&perl_threads->mutex); + return; } /* static void perl_log (int, const char *) */ @@@ -1999,7 -2020,7 +2026,7 @@@ static int perl_notify (const notificat return pplugin_call_all (aTHX_ PLUGIN_NOTIF, notif); } /* static int perl_notify (const notification_t *) */ -static int perl_flush (int timeout, const char *identifier, +static int perl_flush (cdtime_t timeout, const char *identifier, user_data_t __attribute__((unused)) *user_data) { dTHX; @@@ -2101,27 -2122,19 +2128,27 @@@ static int g_pv_set (pTHX_ SV *var, MAG return 0; } /* static int g_pv_set (pTHX_ SV *, MAGIC *) */ -static int g_iv_get (pTHX_ SV *var, MAGIC *mg) +static int g_interval_get (pTHX_ SV *var, MAGIC *mg) { - int *iv = (int *)mg->mg_ptr; - sv_setiv (var, *iv); + cdtime_t *interval = (cdtime_t *)mg->mg_ptr; + double nv; + + nv = CDTIME_T_TO_DOUBLE (*interval); + + sv_setnv (var, nv); return 0; -} /* static int g_iv_get (pTHX_ SV *, MAGIC *) */ +} /* static int g_interval_get (pTHX_ SV *, MAGIC *) */ -static int g_iv_set (pTHX_ SV *var, MAGIC *mg) +static int g_interval_set (pTHX_ SV *var, MAGIC *mg) { - int *iv = (int *)mg->mg_ptr; - *iv = (int)SvIV (var); + cdtime_t *interval = (cdtime_t *)mg->mg_ptr; + double nv; + + nv = (double)SvNV (var); + + *interval = DOUBLE_TO_CDTIME_T (nv); return 0; -} /* static int g_iv_set (pTHX_ SV *, MAGIC *) */ +} /* static int g_interval_set (pTHX_ SV *, MAGIC *) */ static MGVTBL g_pv_vtbl = { g_pv_get, g_pv_set, NULL, NULL, NULL, NULL, NULL @@@ -2129,8 -2142,8 +2156,8 @@@ , NULL #endif }; -static MGVTBL g_iv_vtbl = { - g_iv_get, g_iv_set, NULL, NULL, NULL, NULL, NULL +static MGVTBL g_interval_vtbl = { + g_interval_get, g_interval_set, NULL, NULL, NULL, NULL, NULL #if HAVE_PERL_STRUCT_MGVTBL_SVT_LOCAL , NULL #endif @@@ -2172,11 -2185,12 +2199,11 @@@ static void xs_init (pTHX g_strings[i].var, 0); } - /* global integers */ - for (i = 0; '\0' != g_integers[i].name[0]; ++i) { - tmp = get_sv (g_integers[i].name, 1); - sv_magicext (tmp, NULL, PERL_MAGIC_ext, &g_iv_vtbl, - (char *)g_integers[i].var, 0); - } + tmp = get_sv ("Collectd::interval_g", /* create = */ 1); + sv_magicext (tmp, NULL, /* how = */ PERL_MAGIC_ext, + /* vtbl = */ &g_interval_vtbl, + /* name = */ (char *) &interval_g, /* namelen = */ 0); + return; } /* static void xs_init (pTHX) */ diff --combined src/processes.c index 8f4eb88f,5e448cf9..8a1436e1 --- a/src/processes.c +++ b/src/processes.c @@@ -1,7 -1,7 +1,7 @@@ /** * collectd - src/processes.c * Copyright (C) 2005 Lyonel Vincent - * Copyright (C) 2006-2008 Florian octo Forster + * Copyright (C) 2006-2010 Florian octo Forster * Copyright (C) 2008 Oleg King * Copyright (C) 2009 Sebastian Harl * Copyright (C) 2009 Andrés J. Díaz @@@ -136,13 -136,13 +136,13 @@@ typedef struct procstat_entry_ unsigned long vmem_minflt; unsigned long vmem_majflt; - unsigned long vmem_minflt_counter; - unsigned long vmem_majflt_counter; + derive_t vmem_minflt_counter; + derive_t vmem_majflt_counter; unsigned long cpu_user; unsigned long cpu_system; - unsigned long cpu_user_counter; - unsigned long cpu_system_counter; + derive_t cpu_user_counter; + derive_t cpu_system_counter; /* io data */ derive_t io_rchar; @@@ -169,11 -169,11 +169,11 @@@ typedef struct procsta unsigned long vmem_code; unsigned long stack_size; - unsigned long vmem_minflt_counter; - unsigned long vmem_majflt_counter; + derive_t vmem_minflt_counter; + derive_t vmem_majflt_counter; - unsigned long cpu_user_counter; - unsigned long cpu_system_counter; + derive_t cpu_user_counter; + derive_t cpu_system_counter; /* io data */ derive_t io_rchar; @@@ -676,8 -676,8 +676,8 @@@ static void ps_submit_proc_list (procst plugin_dispatch_values (&vl); sstrncpy (vl.type, "ps_cputime", sizeof (vl.type)); - vl.values[0].counter = ps->cpu_user_counter; - vl.values[1].counter = ps->cpu_system_counter; + vl.values[0].derive = ps->cpu_user_counter; + vl.values[1].derive = ps->cpu_system_counter; vl.values_len = 2; plugin_dispatch_values (&vl); @@@ -688,8 -688,8 +688,8 @@@ plugin_dispatch_values (&vl); sstrncpy (vl.type, "ps_pagefaults", sizeof (vl.type)); - vl.values[0].counter = ps->vmem_minflt_counter; - vl.values[1].counter = ps->vmem_majflt_counter; + vl.values[0].derive = ps->vmem_minflt_counter; + vl.values[1].derive = ps->vmem_majflt_counter; vl.values_len = 2; plugin_dispatch_values (&vl); @@@ -714,8 -714,8 +714,8 @@@ DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; " "vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; " "vmem_code = %lu; " - "vmem_minflt_counter = %lu; vmem_majflt_counter = %lu; " - "cpu_user_counter = %lu; cpu_system_counter = %lu; " + "vmem_minflt_counter = %"PRIi64"; vmem_majflt_counter = %"PRIi64"; " + "cpu_user_counter = %"PRIi64"; cpu_system_counter = %"PRIi64"; " "io_rchar = %"PRIi64"; io_wchar = %"PRIi64"; " "io_syscr = %"PRIi64"; io_syscw = %"PRIi64";", ps->name, ps->num_proc, ps->num_lwp, @@@ -881,12 -881,15 +881,15 @@@ int ps_read_process (int pid, procstat_ char *fields[64]; char fields_len; - int i; + int buffer_len; - int name_len; + char *buffer_ptr; + size_t name_start_pos; + size_t name_end_pos; + size_t name_len; - long long unsigned cpu_user_counter; - long long unsigned cpu_system_counter; + derive_t cpu_user_counter; + derive_t cpu_system_counter; long long unsigned vmem_size; long long unsigned vmem_rss; long long unsigned stack_size; @@@ -895,33 -898,56 +898,56 @@@ ssnprintf (filename, sizeof (filename), "/proc/%i/stat", pid); - i = read_file_contents (filename, buffer, sizeof(buffer) - 1); - if (i <= 0) + buffer_len = read_file_contents (filename, + buffer, sizeof(buffer) - 1); + if (buffer_len <= 0) return (-1); - buffer[i] = 0; - - fields_len = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields)); - if (fields_len < 24) + buffer[buffer_len] = 0; + + /* The name of the process is enclosed in parens. Since the name can + * contain parens itself, spaces, numbers and pretty much everything + * else, use these to determine the process name. We don't use + * strchr(3) and strrchr(3) to avoid pointer arithmetic which would + * otherwise be required to determine name_len. */ + name_start_pos = 0; + while ((buffer[name_start_pos] != '(') + && (name_start_pos < buffer_len)) + name_start_pos++; + + name_end_pos = buffer_len; + while ((buffer[name_end_pos] != ')') + && (name_end_pos > 0)) + name_end_pos--; + + /* Either '(' or ')' is not found or they are in the wrong order. + * Anyway, something weird that shouldn't happen ever. */ + if (name_start_pos >= name_end_pos) { - DEBUG ("processes plugin: ps_read_process (pid = %i):" - " `%s' has only %i fields..", - (int) pid, filename, fields_len); + ERROR ("processes plugin: name_start_pos = %zu >= name_end_pos = %zu", + name_start_pos, name_end_pos); return (-1); } - /* copy the name, strip brackets in the process */ - name_len = strlen (fields[1]) - 2; - if ((fields[1][0] != '(') || (fields[1][name_len + 1] != ')')) + name_len = (name_end_pos - name_start_pos) - 1; + if (name_len >= sizeof (ps->name)) + name_len = sizeof (ps->name) - 1; + + sstrncpy (ps->name, &buffer[name_start_pos + 1], name_len + 1); + + if ((buffer_len - name_end_pos) < 2) + return (-1); + buffer_ptr = &buffer[name_end_pos + 2]; + + fields_len = strsplit (buffer_ptr, fields, STATIC_ARRAY_SIZE (fields)); + if (fields_len < 22) { - DEBUG ("No brackets found in process name: `%s'", fields[1]); + DEBUG ("processes plugin: ps_read_process (pid = %i):" + " `%s' has only %i fields..", + (int) pid, filename, fields_len); return (-1); } - fields[1] = fields[1] + 1; - fields[1][name_len] = '\0'; - strncpy (ps->name, fields[1], PROCSTAT_NAME_LEN); - - *state = fields[2][0]; + *state = fields[0][0]; if (*state == 'Z') { @@@ -946,16 -972,16 +972,16 @@@ return (0); } - cpu_user_counter = atoll (fields[13]); - cpu_system_counter = atoll (fields[14]); - vmem_size = atoll (fields[22]); - vmem_rss = atoll (fields[23]); - ps->vmem_minflt_counter = atoll (fields[9]); - ps->vmem_majflt_counter = atoll (fields[11]); + cpu_user_counter = atoll (fields[11]); + cpu_system_counter = atoll (fields[12]); + vmem_size = atoll (fields[20]); + vmem_rss = atoll (fields[21]); + ps->vmem_minflt_counter = atol (fields[7]); + ps->vmem_majflt_counter = atol (fields[9]); { - unsigned long long stack_start = atoll (fields[27]); - unsigned long long stack_ptr = atoll (fields[28]); + unsigned long long stack_start = atoll (fields[25]); + unsigned long long stack_ptr = atoll (fields[26]); stack_size = (stack_start > stack_ptr) ? stack_start - stack_ptr @@@ -975,8 -1001,8 +1001,8 @@@ DEBUG("ps_read_process: did not get vmem data for pid %i",pid); } - ps->cpu_user_counter = (unsigned long) cpu_user_counter; - ps->cpu_system_counter = (unsigned long) cpu_system_counter; + ps->cpu_user_counter = cpu_user_counter; + ps->cpu_system_counter = cpu_system_counter; ps->vmem_size = (unsigned long) vmem_size; ps->vmem_rss = (unsigned long) vmem_rss; ps->stack_size = (unsigned long) stack_size; diff --combined src/snmp.c index 54bcf672,5c6cce26..d24ca2cd --- a/src/snmp.c +++ b/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) { @@@ -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; @@@ -590,7 -607,7 +590,7 @@@ 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); @@@ -634,7 -651,9 +634,7 @@@ 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, @@@ -708,7 -727,9 +708,9 @@@ static value_t csnmp_value_list_to_valu value_t ret; uint64_t tmp_unsigned = 0; int64_t tmp_signed = 0; - int defined = 1; + _Bool defined = 1; + /* Set to true when the original SNMP type appears to have been signed. */ + _Bool prefer_signed = 0; if ((vl->type == ASN_INTEGER) || (vl->type == ASN_UINTEGER) @@@ -720,7 -741,12 +722,12 @@@ { tmp_unsigned = (uint32_t) *vl->val.integer; tmp_signed = (int32_t) *vl->val.integer; - DEBUG ("snmp plugin: Parsed int32 value is %"PRIi64".", tmp_signed); + + if ((vl->type == ASN_INTEGER) + || (vl->type == ASN_GAUGE)) + prefer_signed = 1; + + DEBUG ("snmp plugin: Parsed int32 value is %"PRIu64".", tmp_unsigned); } else if (vl->type == ASN_COUNTER64) { @@@ -809,14 -835,24 +816,24 @@@ } else if (type == DS_TYPE_GAUGE) { - ret.gauge = NAN; - if (defined != 0) + if (!defined) + ret.gauge = NAN; + else if (prefer_signed) ret.gauge = (scale * tmp_signed) + shift; + else + ret.gauge = (scale * tmp_unsigned) + shift; } else if (type == DS_TYPE_DERIVE) - ret.derive = (derive_t) tmp_signed; + { + if (prefer_signed) + ret.derive = (derive_t) tmp_signed; + else + ret.derive = (derive_t) tmp_unsigned; + } else if (type == DS_TYPE_ABSOLUTE) + { ret.absolute = (absolute_t) tmp_unsigned; + } else { ERROR ("snmp plugin: csnmp_value_list_to_value: Unknown data source " @@@ -1510,8 -1546,8 +1527,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; @@@ -1521,7 -1557,9 +1538,7 @@@ 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); @@@ -1543,14 -1581,14 +1560,14 @@@ 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)