--- /dev/null
+Anthony <anthony>
+Florian Forster <octo>
+Florian Forster <octo@dev4.office.noris.de>
+Luboš Staněk <kolektor@atlas.cz>
+Luboš Staněk <lubek@users.sourceforge.net>
+Niki W. Waibel <niki>
+Sebastian Harl <tokkee>
+
- cpufreq
CPU frequency (For laptops with speed step or a similar technology)
+ - dbi
+ Executes SQL statements on various databases and interprets the returned
+ data.
+
- df
Mountpoint usage (Basically the values `df(1)' delivers)
Iptables' counters: Number of bytes that were matched by a certain
iptables rule.
+ - ipmi
+ IPMI (Intelligent Platform Management Interface) sensors information.
+
- ipvs
IPVS connection statistics (number of connections, octets and packets
for each service and destination).
PostgreSQL database statistics: active server connections, transaction
numbers, block IO, table row manipulations.
+ - powerdns
+ PowerDNS name server statistics.
+
- processes
Process counts: Number of running, sleeping, zombie, ... processes.
+ - rrdcached
+ RRDtool caching daemon (RRDcacheD) statistics.
+
- sensors
System sensors, accessed using lm_sensors: Voltages, temperatures and
fan rotation speeds.
- tcpconns
Number of TCP connections to specific local and remote ports.
+ - teamspeak2
+ TeamSpeak2 server statistics.
+
+ - thermal
+ Linux ACPI thermal zone information.
+
- users
Users currently logged in.
you can easily do weird stuff with the plugins we didn't dare think of
;) See collectd-perl(5).
+ - rrdcached
+ Output to round-robin-database (RRD) files using the RRDtool caching
+ daemon (RRDcacheD) - see rrdcached(1). That daemon provides a general
+ implementation of the caching done by the `rrdtool' plugin.
+
- rrdtool
Output to round-robin-database (RRD) files using librrd. See rrdtool(1).
This is likely the most popular destination for such values. Since
since collectd is programmed multithreaded it benefits from hyperthreading
and multicore processors and makes sure that the daemon isn't idle if only
one plugins waits for an IO-operation to complete.
-
+
* Once set up, hardly any maintenance is necessary. Setup is kept as easy
as possible and the default values should be okay for most users.
* CoreFoundation.framework and IOKit.framework (optional)
For compiling on Darwin in general and the `apple_sensors' plugin in
particular.
+ <http://developer.apple.com/corefoundation/>
* libcurl (optional)
If you want to use the `apache', `ascent', or `nginx' plugin.
+ <http://curl.haxx.se/>
+
+ * libdbi (optional)
+ Used by the `dbi' plugin to connect to various databases.
+ <http://libdbi.sourceforge.net/>
* libesmtp (optional)
For the `notify_email' plugin.
+ <http://www.stafford.uklinux.net/libesmtp/>
* libhal (optional)
If present, the uuid plugin will check for UUID from HAL.
+ <http://hal.freedesktop.org/>
- * libiptc (optional)
+ * libiptc (optional, if not found a version shipped with this distribution
+ can be used if the Linux kernel headers are available)
For querying iptables counters.
+ <http://netfilter.org/>
* libmysqlclient (optional)
Unsurprisingly used by the `mysql' plugin.
+ <http://dev.mysql.com/>
* libnetlink (optional)
Used, obviously, for the `netlink' plugin.
+ <http://www.linuxfoundation.org/en/Net:Iproute2>
* libnetsnmp (optional)
For the `snmp' plugin.
+ <http://www.net-snmp.org/>
* libnotify (optional)
For the `notify_desktop' plugin.
+ <http://www.galago-project.org/>
* liboping (optional, if not found a version shipped with this distribution
can be used)
Used by the `ping' plugin to send and receive ICMP packets.
+ <http://verplant.org/liboping/>
* libowcapi (optional)
Used by the `onewire' plugin to read values from onewire sensors (or the
owserver(1) daemon).
+ <http://www.owfs.org/>
* libpcap (optional)
Used to capture packets by the `dns' plugin.
+ <http://www.tcpdump.org/>
* libperl (optional)
Obviously used by the `perl' plugin. The library has to be compiled with
ithread support (introduced in Perl 5.6.0).
+ <http://www.perl.org/>
* libpq (optional)
The PostgreSQL C client library used by the `postgresql' plugin.
+ <http://www.postgresql.org/>
- * librrd (optional; headers and library; rrdtool 1.0 and 1.2 both work fine)
- If built without `librrd' the resulting binary will be `client only', i.e.
- will send its values via multicast and not create any RRD files itself.
- Alternatively you can chose to write CSV-files (Comma Separated Values)
- instead.
+ * librrd (optional)
+ Used by the `rrdtool' and `rrdcached' plugins. The latter requires RRDtool
+ client support which was added after version 1.3 of RRDtool. Versions 1.0,
+ 1.2 and 1.3 are known to work with the `rrdtool' plugin.
+ <http://oss.oetiker.ch/rrdtool/>
* librt, libsocket, libkstat, libdevinfo (optional)
Various standard Solaris libraries which provide system functions.
+ <http://developers.sun.com/solaris/>
* libsensors (optional)
To read from `lm_sensors', see the `sensors' plugin.
+ <http://www.lm-sensors.org/>
- * libstatgrab (optional) may be used to collect statistics on systems other
- than Linux and/or Solaris. Note that CPU- and disk-statistics, while being
- provided by this library, are not supported in collectd right now..
- <http://www.i-scream.org/libstatgrab/>
+ * libstatgrab (optional)
+ Used by various plugins to collect statistics on systems other than Linux
+ and/or Solaris.
+ <http://www.i-scream.org/libstatgrab/>
* libupsclient/nut (optional)
For the `nut' plugin which queries nut's `upsd'.
+ <http://networkupstools.org/>
* libvirt (optional)
Collect statistics from virtual machines.
+ <http://libvirt.org/>
* libxml2 (optional)
Parse XML data. This is needed for the `ascent' and `libvirt' plugins.
+ <http://xmlsoft.org/>
* libxmms (optional)
+ <http://www.xmms.org/>
Configuring / Compiling / Installing
`./configure && make && make install'. For detailed, generic instructions
see INSTALL. For a complete list of configure options and their description,
run `./configure --help'.
-
+
By default, the configure script will check for all build dependencies and
disable all plugins whose requirements cannot be fulfilled (any other plugin
will be enabled). To enable a plugin, install missing dependencies (see
m4_divert_once([HELP_WITH], [
collectd additional packages:])
-# AC_ARG_WITH (package, help-string, [action-if-given], [action-if-not-given])
-librrd_cflags=""
-librrd_ldflags=""
-librrd_threadsafe="yes"
-AC_ARG_WITH(rrdtool, [AS_HELP_STRING([--with-rrdtool@<:@=PREFIX@:>@], [Path to rrdtool.])],
-[ if test "x$withval" != "xno" && test "x$withval" != "xyes"
- then
- librrd_cflags="-I$withval/include"
- librrd_ldflags="-L$withval/lib"
- with_rrdtool="yes"
- else
- with_rrdtool="$withval"
- fi
-], [with_rrdtool="yes"])
-if test "x$with_rrdtool" = "xyes"
-then
- SAVE_CPPFLAGS="$CPPFLAGS"
- SAVE_LDFLAGS="$LDFLAGS"
-
- CPPFLAGS="$CPPFLAGS $librrd_cflags"
- LDFLAGS="$LDFLAGS $librrd_ldflags"
-
- AC_CHECK_HEADERS(rrd.h,, [with_rrdtool="no (rrd.h not found)"])
-
- CPPFLAGS="$SAVE_CPPFLAGS"
- LDFLAGS="$SAVE_LDFLAGS"
-fi
-if test "x$with_rrdtool" = "xyes"
-then
- SAVE_CPPFLAGS="$CPPFLAGS"
- SAVE_LDFLAGS="$LDFLAGS"
-
- CPPFLAGS="$CPPFLAGS $librrd_cflags"
- LDFLAGS="$LDFLAGS $librrd_ldflags"
-
- AC_CHECK_LIB(rrd_th, rrd_update_r,
- [with_rrdtool="yes"
- librrd_ldflags="$librrd_ldflags -lrrd_th -lm"
- ],
- [librrd_threadsafe="no"
- AC_CHECK_LIB(rrd, rrd_update,
- [with_rrdtool="yes"
- librrd_ldflags="$librrd_ldflags -lrrd -lm"
- ],
- [with_rrdtool="no (symbol 'rrd_update' not found)"],
- [-lm])
- ],
- [-lm])
-
- CPPFLAGS="$SAVE_CPPFLAGS"
- LDFLAGS="$SAVE_LDFLAGS"
-fi
-if test "x$with_rrdtool" = "xyes"
-then
- BUILD_WITH_LIBRRD_CFLAGS="$librrd_cflags"
- BUILD_WITH_LIBRRD_LDFLAGS="$librrd_ldflags"
- AC_SUBST(BUILD_WITH_LIBRRD_CFLAGS)
- AC_SUBST(BUILD_WITH_LIBRRD_LDFLAGS)
-fi
-if test "x$librrd_threadsafe" = "xyes"
-then
- AC_DEFINE(HAVE_THREADSAFE_LIBRRD, 1, [Define to 1 if you have the threadsafe rrd library (-lrrd_th).])
-fi
-
-AC_ARG_WITH(libpthread, [AS_HELP_STRING([--with-libpthread=@<:@=PREFIX@:>@], [Path to libpthread.])],
-[ if test "x$withval" != "xno" \
- && test "x$withval" != "xyes"
- then
- LDFLAGS="$LDFLAGS -L$withval/lib"
- CPPFLAGS="$CPPFLAGS -I$withval/include"
- with_libpthread="yes"
- else
- if test "x$withval" = "xno"
- then
- with_libpthread="no (disabled)"
- fi
- fi
-], [with_libpthread="yes"])
-if test "x$with_libpthread" = "xyes"
-then
- AC_CHECK_LIB(pthread, pthread_create, [with_libpthread="yes"], [with_libpthread="no (libpthread not found)"], [])
-fi
-if test "x$with_libpthread" = "xyes"
-then
- AC_CHECK_HEADERS(pthread.h,, [with_libpthread="no (pthread.h not found)"])
-fi
-if test "x$with_libpthread" = "xyes"
-then
- collect_pthread=1
-else
- collect_pthread=0
-fi
-AC_DEFINE_UNQUOTED(HAVE_LIBPTHREAD, [$collect_pthread],
- [Wether or not to use pthread (POSIX threads) library])
-AM_CONDITIONAL(BUILD_WITH_LIBPTHREAD, test "x$with_libpthread" = "xyes")
-
if test "x$ac_system" = "xSolaris"
then
with_kstat="yes"
AM_CONDITIONAL(BUILD_WITH_LIBKSTAT, test "x$with_kstat" = "xyes")
AM_CONDITIONAL(BUILD_WITH_LIBDEVINFO, test "x$with_devinfo" = "xyes")
-### BEGIN of check for libcurl ###
+with_libiokit="no"
+AC_CHECK_LIB(IOKit, IOServiceGetMatchingServices,
+[
+ with_libiokit="yes"
+],
+[
+ with_libiokit="no"
+])
+AM_CONDITIONAL(BUILD_WITH_LIBIOKIT, test "x$with_libiokit" = "xyes")
+
+with_libkvm="no"
+AC_CHECK_LIB(kvm, kvm_getprocs, [with_kvm_getprocs="yes"], [with_kvm_getprocs="no"])
+if test "x$with_kvm_getprocs" = "xyes"
+then
+ AC_DEFINE(HAVE_LIBKVM_GETPROCS, 1,
+ [Define to 1 if you have the 'kvm' library with the 'kvm_getprocs' symbol (-lkvm)])
+ with_libkvm="yes"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBKVM_GETPROCS, test "x$with_kvm_getprocs" = "xyes")
+
+AC_CHECK_LIB(kvm, kvm_getswapinfo, [with_kvm_getswapinfo="yes"], [with_kvm_getswapinfo="no"])
+if test "x$with_kvm_getswapinfo" = "xyes"
+then
+ AC_DEFINE(HAVE_LIBKVM_GETSWAPINFO, 1,
+ [Define to 1 if you have the 'kvm' library with the 'kvm_getswapinfo' symbol (-lkvm)])
+ with_libkvm="yes"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBKVM_GETSWAPINFO, test "x$with_kvm_getswapinfo" = "xyes")
+
+AC_CHECK_LIB(kvm, kvm_nlist, [with_kvm_nlist="yes"], [with_kvm_nlist="no"])
+if test "x$with_kvm_nlist" = "xyes"
+then
+ AC_DEFINE(HAVE_LIBKVM_NLIST, 1,
+ [Define to 1 if you have the 'kvm' library with the 'kvm_nlist' symbol (-lkvm)])
+ with_libkvm="yes"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBKVM_NLIST, test "x$with_kvm_nlist" = "xyes")
+
+# --with-libcurl {{{
with_curl_config="curl-config"
with_curl_cflags=""
with_curl_libs=""
AC_SUBST(BUILD_WITH_LIBCURL_LIBS)
fi
AM_CONDITIONAL(BUILD_WITH_LIBCURL, test "x$with_libcurl" = "xyes")
-### END of check for libcurl ###
-
-with_libiokit="no"
-AC_CHECK_LIB(IOKit, IOServiceGetMatchingServices,
-[
- with_libiokit="yes"
-],
-[
- with_libiokit="no"
-])
-AM_CONDITIONAL(BUILD_WITH_LIBIOKIT, test "x$with_libiokit" = "xyes")
+# }}}
-with_libstatgrab_cflags=""
-with_libstatgrab_ldflags=""
-AC_ARG_WITH(libstatgrab, [AS_HELP_STRING([--with-libstatgrab@<:@=PREFIX@:>@], [Path to libstatgrab.])],
+# --with-libdbi {{{
+with_libdbi_cppflags=""
+with_libdbi_ldflags=""
+AC_ARG_WITH(libdbi, [AS_HELP_STRING([--with-libdbi@<:@=PREFIX@:>@], [Path to libdbi.])],
[
- if test "x$withval" != "xno" \
- && test "x$withval" != "xyes"
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
then
- with_libstatgrab_cflags="-I$withval/include"
- with_libstatgrab_ldflags="-L$withval/lib"
- with_libstatgrab="yes"
+ with_libdbi_cppflags="-I$withval/include"
+ with_libdbi_ldflags="-L$withval/lib"
+ with_libdbi="yes"
else
- with_libstatgrab="$withval"
+ with_libdbi="$withval"
fi
],
[
- if test "x$ac_system" = "xunknown"
- then
- with_libstatgrab="yes"
- else
- with_libstatgrab="no"
- fi
+ with_libdbi="yes"
])
-with_libstatgrab_pkg_config="yes"
-if test "x$with_libstatgrab" = "xyes" \
- && test "x$PKG_CONFIG" != "x"
+if test "x$with_libdbi" = "xyes"
then
- AC_MSG_CHECKING([pkg-config for libstatgrab])
- temp_result="found"
- $PKG_CONFIG --exists libstatgrab 2>/dev/null
- if test "$?" != "0"
- then
- with_libstatgrab_pkg_config="no"
- temp_result="not found"
- fi
- AC_MSG_RESULT([$temp_result])
-else
- AC_MSG_NOTICE([pkg-config not available, trying to guess flags for the statgrab library.])
- with_libstatgrab_pkg_config="no"
- with_libstatgrab_ldflags="$with_libstatgrab_ldflags -lstatgrab"
-fi
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libdbi_cppflags"
-if test "x$with_libstatgrab" = "xyes" \
- && test "x$with_libstatgrab_pkg_config" = "xyes" \
- && test "x$with_libstatgrab_cflags" = "x"
-then
- AC_MSG_CHECKING([for libstatgrab CFLAGS])
- temp_result="`$PKG_CONFIG --cflags libstatgrab`"
- if test "$?" = "0"
- then
- with_libstatgrab_cflags="$temp_result"
- else
- with_libstatgrab="no ($PKG_CONFIG --cflags libstatgrab failed)"
- temp_result="$PKG_CONFIG --cflags libstatgrab failed"
- fi
- AC_MSG_RESULT([$temp_result])
-fi
+ AC_CHECK_HEADERS(dbi/dbi.h, [with_libdbi="yes"], [with_libdbi="no (dbi/dbi.h not found)"])
-if test "x$with_libstatgrab" = "xyes" \
- && test "x$with_libstatgrab_pkg_config" = "xyes" \
- && test "x$with_libstatgrab_ldflags" = "x"
-then
- AC_MSG_CHECKING([for libstatgrab LDFLAGS])
- temp_result="`$PKG_CONFIG --libs libstatgrab`"
- if test "$?" = "0"
- then
- with_libstatgrab_ldflags="$temp_result"
- else
- with_libstatgrab="no ($PKG_CONFIG --libs libstatgrab failed)"
- temp_result="$PKG_CONFIG --libs libstatgrab failed"
- fi
- AC_MSG_RESULT([$temp_result])
+ CPPFLAGS="$SAVE_CPPFLAGS"
fi
-
-if test "x$with_libstatgrab" = "xyes"
+if test "x$with_libdbi" = "xyes"
then
- SAVE_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $with_libstatgrab_cflags"
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libdbi_cppflags"
+ LDFLAGS="$LDFLAGS $with_libdbi_ldflags"
- AC_CHECK_HEADERS(statgrab.h,
- [with_libstatgrab="yes"],
- [with_libstatgrab="no (statgrab.h not found)"])
+ AC_CHECK_LIB(dbi, dbi_initialize, [with_libdbi="yes"], [with_libdbi="no (Symbol 'dbi_initialize' not found)"])
- CPPFLAGS="$SAVE_CPPFLAGS"
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
fi
-
-if test "x$with_libstatgrab" = "xyes"
+if test "x$with_libdbi" = "xyes"
then
- SAVE_CFLAGS="$CFLAGS"
- SAVE_LDFLAGS="$LDFLAGS"
-
- CFLAGS="$CFLAGS $with_libstatgrab_cflags"
- LDFLAGS="$LDFLAGS $with_libstatgrab_ldflags"
-
- AC_CHECK_LIB(statgrab, sg_init,
- [with_libstatgrab="yes"],
- [with_libstatgrab="no (symbol sg_init not found)"])
-
- CFLAGS="$SAVE_CFLAGS"
- LDFLAGS="$SAVE_LDFLAGS"
+ BUILD_WITH_LIBDBI_CPPFLAGS="$with_libdbi_cppflags"
+ BUILD_WITH_LIBDBI_LDFLAGS="$with_libdbi_ldflags"
+ BUILD_WITH_LIBDBI_LIBS="-ldbi"
+ AC_SUBST(BUILD_WITH_LIBDBI_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBDBI_LDFLAGS)
+ AC_SUBST(BUILD_WITH_LIBDBI_LIBS)
fi
+AM_CONDITIONAL(BUILD_WITH_LIBDBI, test "x$with_libdbi" = "xyes")
+# }}}
-AM_CONDITIONAL(BUILD_WITH_LIBSTATGRAB, test "x$with_libstatgrab" = "xyes")
-if test "x$with_libstatgrab" = "xyes"
+# --with-libesmtp {{{
+AC_ARG_WITH(libesmtp, [AS_HELP_STRING([--with-libesmtp@<:@=PREFIX@:>@], [Path to libesmtp.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ CPPFLAGS="$CPPFLAGS -I$withval/include -D_THREAD_SAFE"
+ with_libesmtp="yes"
+ else
+ with_libesmtp="$withval"
+ fi
+],
+[
+ with_libesmtp="yes"
+])
+if test "x$with_libesmtp" = "xyes"
then
- AC_DEFINE(HAVE_LIBSTATGRAB, 1, [Define to 1 if you have the 'statgrab' library (-lstatgrab)])
- BUILD_WITH_LIBSTATGRAB_CFLAGS="$with_libstatgrab_cflags"
- BUILD_WITH_LIBSTATGRAB_LDFLAGS="$with_libstatgrab_ldflags"
- AC_SUBST(BUILD_WITH_LIBSTATGRAB_CFLAGS)
- AC_SUBST(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+ AC_CHECK_LIB(esmtp, smtp_create_session,
+ [
+ AC_DEFINE(HAVE_LIBESMTP, 1, [Define to 1 if you have the esmtp library (-lesmtp).])
+ ], [with_libesmtp="no (libesmtp not found)"])
fi
-
-with_libkvm="no"
-AC_CHECK_LIB(kvm, kvm_getprocs, [with_kvm_getprocs="yes"], [with_kvm_getprocs="no"])
-if test "x$with_kvm_getprocs" = "xyes"
+if test "x$with_libesmtp" = "xyes"
then
- AC_DEFINE(HAVE_LIBKVM_GETPROCS, 1,
- [Define to 1 if you have the 'kvm' library with the 'kvm_getprocs' symbol (-lkvm)])
- with_libkvm="yes"
-fi
-AM_CONDITIONAL(BUILD_WITH_LIBKVM_GETPROCS, test "x$with_kvm_getprocs" = "xyes")
-
-AC_CHECK_LIB(kvm, kvm_getswapinfo, [with_kvm_getswapinfo="yes"], [with_kvm_getswapinfo="no"])
-if test "x$with_kvm_getswapinfo" = "xyes"
-then
- AC_DEFINE(HAVE_LIBKVM_GETSWAPINFO, 1,
- [Define to 1 if you have the 'kvm' library with the 'kvm_getswapinfo' symbol (-lkvm)])
- with_libkvm="yes"
+ AC_CHECK_HEADERS(libesmtp.h,
+ [
+ AC_DEFINE(HAVE_LIBESMTP_H, 1, [Define to 1 if you have the <libesmtp.h> header file.])
+ ], [with_libesmtp="no (libesmtp.h not found)"])
fi
-AM_CONDITIONAL(BUILD_WITH_LIBKVM_GETSWAPINFO, test "x$with_kvm_getswapinfo" = "xyes")
-
-AC_CHECK_LIB(kvm, kvm_nlist, [with_kvm_nlist="yes"], [with_kvm_nlist="no"])
-if test "x$with_kvm_nlist" = "xyes"
+if test "x$with_libesmtp" = "xyes"
then
- AC_DEFINE(HAVE_LIBKVM_NLIST, 1,
- [Define to 1 if you have the 'kvm' library with the 'kvm_nlist' symbol (-lkvm)])
- with_libkvm="yes"
+ collect_libesmtp=1
+else
+ collect_libesmtp=0
fi
-AM_CONDITIONAL(BUILD_WITH_LIBKVM_NLIST, test "x$with_kvm_nlist" = "xyes")
+AC_DEFINE_UNQUOTED(COLLECT_LIBESMTP, [$collect_libesmtp],
+ [Wether or not to use the esmtp library])
+AM_CONDITIONAL(BUILD_WITH_LIBESMTP, test "x$with_libesmtp" = "xyes")
+# }}}
-with_sensors_cflags=""
-with_sensors_ldflags=""
-AC_ARG_WITH(lm-sensors, [AS_HELP_STRING([--with-lm-sensors@<:@=PREFIX@:>@], [Path to lm_sensors.])],
+# --with-libiptc {{{
+with_own_libiptc="no"
+AC_ARG_WITH(libiptc, [AS_HELP_STRING([--with-libiptc@<:@=PREFIX@:>@], [Path to libiptc.])],
[
- if test "x$withval" = "xno"
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
then
- with_lm_sensors="no"
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ with_libiptc="yes"
else
- with_lm_sensors="yes"
- if test "x$withval" != "xyes"
- then
- with_sensors_cflags="-I$withval/include"
- with_sensors_ldflags="-L$withval/lib"
- with_lm_sensors="yes"
- fi
+ with_libiptc="$withval"
fi
],
[
if test "x$ac_system" = "xLinux"
then
- with_lm_sensors="yes"
+ with_libiptc="yes"
else
- with_lm_sensors="no (Linux only library)"
+ with_libiptc="no (Linux only)"
fi
])
-if test "x$with_lm_sensors" = "xyes"
+if test "x$with_libiptc" = "xyes"
then
- SAVE_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $with_sensors_cflags"
-
-# AC_CHECK_HEADERS(sensors/sensors.h,
-# [
-# AC_DEFINE(HAVE_SENSORS_SENSORS_H, 1, [Define to 1 if you have the <sensors/sensors.h> header file.])
-# ],
-# [with_lm_sensors="no (sensors/sensors.h not found)"])
- AC_CHECK_HEADERS(sensors/sensors.h, [], [with_lm_sensors="no (sensors/sensors.h not found)"])
-
- CPPFLAGS="$SAVE_CPPFLAGS"
+ AC_CHECK_LIB(iptc, iptc_init,
+ [
+ AC_DEFINE(HAVE_LIBIPTC, 1, [Define to 1 if you have the iptc library (-liptc).])
+ ],
+ [
+ with_libiptc="yes"
+ with_own_libiptc="yes"
+ ])
fi
-if test "x$with_lm_sensors" = "xyes"
+if test "x$with_libiptc" = "xyes" -a "x$with_own_libiptc" != "xyes"
then
- SAVE_CPPFLAGS="$CPPFLAGS"
- SAVE_LDFLAGS="$LDFLAGS"
- CPPFLAGS="$CPPFLAGS $with_sensors_cflags"
- LDFLAGS="$LDFLAGS $with_sensors_ldflags"
+ AC_CHECK_HEADERS(libiptc/libiptc.h,
+ [
+ AC_DEFINE(HAVE_LIBIPTC_LIBIPTC_H, 1, [Define to 1 if you have the <libiptc/libiptc.h> header file.])
+ ],
+ [
+ with_libiptc="yes"
+ with_own_libiptc="yes"
+ ])
+fi
+if test "x$with_libiptc" = "xyes"
+then
+ SAVE_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS $KERNEL_CFLAGS"
- AC_CHECK_LIB(sensors, sensors_init,
+ AC_CHECK_HEADERS(linux/netfilter_ipv4/ip_tables.h linux/netfilter_ipv6/ip6_tables.h, [],
[
- AC_DEFINE(HAVE_LIBSENSORS, 1, [Define to 1 if you have the sensors library (-lsensors).])
+ with_libiptc="no (Linux iptables headers not found - check KERNEL_DIR)"
+ with_own_libiptc="no"
],
- [with_lm_sensors="no (libsensors not found)"])
+ [
+#include "$srcdir/src/libiptc/ipt_kernel_headers.h"
+ ])
- CPPFLAGS="$SAVE_CPPFLAGS"
- LDFLAGS="$SAVE_LDFLAGS"
+ CFLAGS=$SAVE_CFLAGS
fi
-if test "x$with_lm_sensors" = "xyes"
+AM_CONDITIONAL(BUILD_WITH_LIBIPTC, test "x$with_libiptc" = "xyes")
+AM_CONDITIONAL(BUILD_WITH_OWN_LIBIPTC, test "x$with_own_libiptc" = "xyes")
+if test "x$with_own_libiptc" = "xyes"
then
- BUILD_WITH_LIBSENSORS_CFLAGS="$with_sensors_cflags"
- BUILD_WITH_LIBSENSORS_LDFLAGS="$with_sensors_ldflags"
- AC_SUBST(BUILD_WITH_LIBSENSORS_CFLAGS)
- AC_SUBST(BUILD_WITH_LIBSENSORS_LDFLAGS)
+ AC_DEFINE(OWN_LIBIPTC, 1, [Define to 1 if we use the shipped iptc library.])
fi
-AM_CONDITIONAL(BUILD_WITH_LM_SENSORS, test "x$with_lm_sensors" = "xyes")
+# }}}
+# --with-libmysql {{{
with_mysql_config="mysql_config"
with_mysql_cflags=""
with_mysql_libs=""
AC_SUBST(BUILD_WITH_LIBMYSQL_LIBS)
fi
AM_CONDITIONAL(BUILD_WITH_LIBMYSQL, test "x$with_libmysql" = "xyes")
+# }}}
-with_own_liboconfig="no"
-liboconfig_LDFLAGS="$LDFLAGS"
-liboconfig_CPPFLAGS="$CPPFLAGS"
-AC_ARG_WITH(liboconfig, [AS_HELP_STRING([--with-liboconfig@<:@=PREFIX@:>@], [Path to liboconfig.])],
+# --with-libnetlink {{{
+with_libnetlink_cflags=""
+with_libnetlink_libs="-lnetlink"
+AC_ARG_WITH(libnetlink, [AS_HELP_STRING([--with-libnetlink@<:@=PREFIX@:>@], [Path to libnetlink.])],
[
- if test "x$withval" != "xno" && test "x$withval" != "xyes"
- then
- if test -d "$withval/lib"
- then
- liboconfig_LDFLAGS="$LDFLAGS -L$withval/lib"
- fi
- if test -d "$withval/include"
- then
- liboconfig_CPPFLAGS="$CPPFLAGS -I$withval/include"
- fi
- fi
- if test "x$withval" = "xno"
- then
- AC_MSG_ERROR("liboconfig is required")
- fi
+ echo "libnetlink: withval = $withval"
+ if test "x$withval" = "xyes"
+ then
+ with_libnetlink="yes"
+ else if test "x$withval" = "xno"
+ then
+ with_libnetlink="no"
+ else
+ if test -d "$withval/include"
+ then
+ with_libnetlink_cflags="-I$withval/include"
+ with_libnetlink_libs="-L$withval/lib -lnetlink"
+ with_libnetlink="yes"
+ else
+ AC_MSG_ERROR("no such directory: $withval/include")
+ fi
+ fi; fi
],
[
- with_liboconfig="yes"
+ if test "x$ac_system" = "xLinux"
+ then
+ with_libnetlink="yes"
+ else
+ with_libnetlink="no (Linux only library)"
+ fi
])
+if test "x$with_libnetlink" = "xyes"
+then
+ SAVE_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS $with_libnetlink_cflags"
-save_LDFLAGS="$LDFLAGS"
-save_CPPFLAGS="$CPPFLAGS"
-LDFLAGS="$liboconfig_LDFLAGS"
-CPPFLAGS="$liboconfig_CPPFLAGS"
-AC_CHECK_LIB(oconfig, oconfig_parse_fh,
-[
- with_liboconfig="yes"
- with_own_liboconfig="no"
-],
-[
- with_liboconfig="yes"
- with_own_liboconfig="yes"
- LDFLAGS="$save_LDFLAGS"
- CPPFLAGS="$save_CPPFLAGS"
-])
+ with_libnetlink="no (libnetlink.h not found)"
-AM_CONDITIONAL(BUILD_WITH_OWN_LIBOCONFIG, test "x$with_own_liboconfig" = "xyes")
-if test "x$with_own_liboconfig" = "xyes"
+ AC_CHECK_HEADERS(libnetlink.h iproute/libnetlink.h linux/libnetlink.h,
+ [
+ with_libnetlink="yes"
+ break
+ ], [],
+[#include <stdio.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>])
+ AC_CHECK_HEADERS(linux/gen_stats.h linux/pkt_sched.h, [], [],
+[#include <stdio.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/socket.h>])
+
+ AC_COMPILE_IFELSE(
+[#include <stdio.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+int main (void)
+{
+ int retval = TCA_STATS2;
+ return (retval);
+}],
+ [AC_DEFINE([HAVE_TCA_STATS2], 1, [True if the enum-member TCA_STATS2 exists])]
+ []);
+
+ AC_COMPILE_IFELSE(
+[#include <stdio.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+int main (void)
+{
+ int retval = TCA_STATS;
+ return (retval);
+}],
+ [AC_DEFINE([HAVE_TCA_STATS], 1, [True if the enum-member TCA_STATS exists])]
+ []);
+
+ CFLAGS="$SAVE_CFLAGS"
+fi
+if test "x$with_libnetlink" = "xyes"
then
- with_liboconfig="yes (shipped version)"
+ AC_CHECK_LIB(netlink, rtnl_open,
+ [with_libnetlink="yes"],
+ [with_libnetlink="no (symbol 'rtnl_open' not found)"],
+ [$with_libnetlink_libs])
+fi
+if test "x$with_libnetlink" = "xyes"
+then
+ BUILD_WITH_LIBNETLINK_CFLAGS="$with_libnetlink_cflags"
+ BUILD_WITH_LIBNETLINK_LIBS="$with_libnetlink_libs"
+ AC_SUBST(BUILD_WITH_LIBNETLINK_CFLAGS)
+ AC_SUBST(BUILD_WITH_LIBNETLINK_LIBS)
fi
+AM_CONDITIONAL(BUILD_WITH_LIBNETLINK, test "x$with_libnetlink" = "xyes")
+# }}}
-#with_liboping="yes"
-with_own_liboping="no"
-liboping_LDFLAGS="$LDFLAGS"
-liboping_CPPFLAGS="$CPPFLAGS"
-AC_ARG_WITH(liboping, [AS_HELP_STRING([--with-liboping@<:@=PREFIX@:>@], [Path to liboping.])],
+# --with-libnetsnmp {{{
+with_snmp_config="net-snmp-config"
+with_snmp_cflags=""
+with_snmp_libs=""
+AC_ARG_WITH(libnetsnmp, [AS_HELP_STRING([--with-libnetsnmp@<:@=PREFIX@:>@], [Path to the Net-SNMPD library.])],
[
- if test "x$withval" != "xno" && test "x$withval" != "xyes"
- then
- if test -d "$withval/lib"
- then
- liboping_LDFLAGS="$LDFLAGS -L$withval/lib"
- fi
- if test -d "$withval/include"
- then
- liboping_CPPFLAGS="$CPPFLAGS -I$withval/include"
- fi
- fi
if test "x$withval" = "xno"
then
- with_liboping="no"
- with_own_liboping="no"
+ with_libnetsnmp="no"
+ else if test "x$withval" = "xyes"
+ then
+ with_libnetsnmp="yes"
+ else
+ if test -x "$withval"
+ then
+ with_snmp_config="$withval"
+ with_libnetsnmp="yes"
+ else
+ with_snmp_config="$withval/bin/net-snmp-config"
+ with_libnetsnmp="yes"
+ fi
+ fi; fi
+],
+[with_libnetsnmp="yes"])
+if test "x$with_libnetsnmp" = "xyes"
+then
+ with_snmp_cflags=`$with_snmp_config --cflags 2>/dev/null`
+ snmp_config_status=$?
+
+ if test $snmp_config_status -ne 0
+ then
+ with_libnetsnmp="no ($with_snmp_config failed)"
+ else
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_snmp_cflags"
+
+ AC_CHECK_HEADERS(net-snmp/net-snmp-config.h, [], [with_libnetsnmp="no (net-snmp/net-snmp-config.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ fi
+fi
+if test "x$with_libnetsnmp" = "xyes"
+then
+ with_snmp_libs=`$with_snmp_config --libs 2>/dev/null`
+ snmp_config_status=$?
+
+ if test $snmp_config_status -ne 0
+ then
+ with_libnetsnmp="no ($with_snmp_config failed)"
+ else
+ AC_CHECK_LIB(netsnmp, init_snmp,
+ [with_libnetsnmp="yes"],
+ [with_libnetsnmp="no (libnetsnmp not found)"],
+ [$with_snmp_libs])
+ fi
+fi
+if test "x$with_libnetsnmp" = "xyes"
+then
+ BUILD_WITH_LIBSNMP_CFLAGS="$with_snmp_cflags"
+ BUILD_WITH_LIBSNMP_LIBS="$with_snmp_libs"
+ AC_SUBST(BUILD_WITH_LIBSNMP_CFLAGS)
+ AC_SUBST(BUILD_WITH_LIBSNMP_LIBS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBNETSNMP, test "x$with_libnetsnmp" = "xyes")
+# }}}
+
+# --with-liboconfig {{{
+with_own_liboconfig="no"
+liboconfig_LDFLAGS="$LDFLAGS"
+liboconfig_CPPFLAGS="$CPPFLAGS"
+AC_ARG_WITH(liboconfig, [AS_HELP_STRING([--with-liboconfig@<:@=PREFIX@:>@], [Path to liboconfig.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ if test -d "$withval/lib"
+ then
+ liboconfig_LDFLAGS="$LDFLAGS -L$withval/lib"
+ fi
+ if test -d "$withval/include"
+ then
+ liboconfig_CPPFLAGS="$CPPFLAGS -I$withval/include"
+ fi
+ fi
+ if test "x$withval" = "xno"
+ then
+ AC_MSG_ERROR("liboconfig is required")
+ fi
+],
+[
+ with_liboconfig="yes"
+])
+
+save_LDFLAGS="$LDFLAGS"
+save_CPPFLAGS="$CPPFLAGS"
+LDFLAGS="$liboconfig_LDFLAGS"
+CPPFLAGS="$liboconfig_CPPFLAGS"
+AC_CHECK_LIB(oconfig, oconfig_parse_fh,
+[
+ with_liboconfig="yes"
+ with_own_liboconfig="no"
+],
+[
+ with_liboconfig="yes"
+ with_own_liboconfig="yes"
+ LDFLAGS="$save_LDFLAGS"
+ CPPFLAGS="$save_CPPFLAGS"
+])
+
+AM_CONDITIONAL(BUILD_WITH_OWN_LIBOCONFIG, test "x$with_own_liboconfig" = "xyes")
+if test "x$with_own_liboconfig" = "xyes"
+then
+ with_liboconfig="yes (shipped version)"
+fi
+# }}}
+
+# --with-liboping {{{
+with_own_liboping="no"
+liboping_LDFLAGS="$LDFLAGS"
+liboping_CPPFLAGS="$CPPFLAGS"
+AC_ARG_WITH(liboping, [AS_HELP_STRING([--with-liboping@<:@=PREFIX@:>@], [Path to liboping.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ if test -d "$withval/lib"
+ then
+ liboping_LDFLAGS="$LDFLAGS -L$withval/lib"
+ fi
+ if test -d "$withval/include"
+ then
+ liboping_CPPFLAGS="$CPPFLAGS -I$withval/include"
+ fi
+ fi
+ if test "x$withval" = "xno"
+ then
+ with_liboping="no"
+ with_own_liboping="no"
else if test "x$withval" = "xyes"
then
with_liboping="yes"
fi
AM_CONDITIONAL(BUILD_WITH_LIBOPING, test "x$with_liboping" = "xyes")
AM_CONDITIONAL(BUILD_WITH_OWN_LIBOPING, test "x$with_own_liboping" = "xyes")
+# }}}
+# --with-libowcapi {{{
with_libowcapi_cppflags=""
with_libowcapi_libs="-lowcapi"
AC_ARG_WITH(libowcapi, [AS_HELP_STRING([--with-libowcapi@<:@=PREFIX@:>@], [Path to libowcapi.])],
AC_SUBST(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
AC_SUBST(BUILD_WITH_LIBOWCAPI_LIBS)
fi
+# }}}
-
+# --with-libpcap {{{
AC_ARG_WITH(libpcap, [AS_HELP_STRING([--with-libpcap@<:@=PREFIX@:>@], [Path to libpcap.])],
[
if test "x$withval" != "xno" && test "x$withval" != "xyes"
AC_DEFINE_UNQUOTED(COLLECT_LIBPCAP, [$collect_libpcap],
[Wether or not to use the pcap library])
AM_CONDITIONAL(BUILD_WITH_LIBPCAP, test "x$with_libpcap" = "xyes")
+# }}}
-AC_ARG_WITH(libesmtp, [AS_HELP_STRING([--with-libesmtp@<:@=PREFIX@:>@], [Path to libesmtp.])],
-[
- if test "x$withval" != "xno" && test "x$withval" != "xyes"
- then
- LDFLAGS="$LDFLAGS -L$withval/lib"
- CPPFLAGS="$CPPFLAGS -I$withval/include -D_THREAD_SAFE"
- with_libesmtp="yes"
- else
- with_libesmtp="$withval"
- fi
-],
-[
- with_libesmtp="yes"
-])
-if test "x$with_libesmtp" = "xyes"
-then
- AC_CHECK_LIB(esmtp, smtp_create_session,
- [
- AC_DEFINE(HAVE_LIBESMTP, 1, [Define to 1 if you have the esmtp library (-lesmtp).])
- ], [with_libesmtp="no (libesmtp not found)"])
-fi
-if test "x$with_libesmtp" = "xyes"
-then
- AC_CHECK_HEADERS(libesmtp.h,
- [
- AC_DEFINE(HAVE_LIBESMTP_H, 1, [Define to 1 if you have the <libesmtp.h> header file.])
- ], [with_libesmtp="no (libesmtp.h not found)"])
-fi
-if test "x$with_libesmtp" = "xyes"
-then
- collect_libesmtp=1
-else
- collect_libesmtp=0
-fi
-AC_DEFINE_UNQUOTED(COLLECT_LIBESMTP, [$collect_libesmtp],
- [Wether or not to use the esmtp library])
-AM_CONDITIONAL(BUILD_WITH_LIBESMTP, test "x$with_libesmtp" = "xyes")
-
+# --with-libperl {{{
perl_interpreter="perl"
AC_ARG_WITH(libperl, [AS_HELP_STRING([--with-libperl@<:@=PREFIX@:>@], [Path to libperl.])],
[
CFLAGS=$SAVE_CFLAGS
LDFLAGS=$SAVE_LDFLAGS
fi
+# }}}
-with_own_libiptc="no"
-AC_ARG_WITH(libiptc, [AS_HELP_STRING([--with-libiptc@<:@=PREFIX@:>@], [Path to libiptc.])],
+# --with-libpq {{{
+with_pg_config="pg_config"
+with_libpq_includedir=""
+with_libpq_libdir=""
+with_libpq_cppflags=""
+with_libpq_ldflags=""
+AC_ARG_WITH(libpq, [AS_HELP_STRING([--with-libpq@<:@=PREFIX@:>@],
+ [Path to libpq.])],
[
- if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ if test "x$withval" = "xno"
then
- LDFLAGS="$LDFLAGS -L$withval/lib"
- CPPFLAGS="$CPPFLAGS -I$withval/include"
- with_libiptc="yes"
+ with_libpq="no"
+ else if test "x$withval" = "xyes"
+ then
+ with_libpq="yes"
else
- with_libiptc="$withval"
- fi
+ if test -f "$withval" && test -x "$withval";
+ then
+ with_pg_config="$withval"
+ else if test -x "$withval/bin/pg_config"
+ then
+ with_pg_config="$withval/bin/pg_config"
+ fi; fi
+ with_libpq="yes"
+ fi; fi
],
[
- if test "x$ac_system" = "xLinux"
+ with_libpq="yes"
+])
+if test "x$with_libpq" = "xyes"
+then
+ with_libpq_includedir=`$with_pg_config --includedir 2> /dev/null`
+ pg_config_status=$?
+
+ if test $pg_config_status -eq 0
then
- with_libiptc="yes"
+ if test -n "$with_libpq_includedir"; then
+ for dir in $with_libpq_includedir; do
+ with_libpq_cppflags="$with_libpq_cppflags -I$dir"
+ done
+ fi
else
- with_libiptc="no (Linux only)"
+ AC_MSG_WARN([$with_pg_config returned with status $pg_config_status])
fi
-])
-if test "x$with_libiptc" = "xyes"
-then
- AC_CHECK_LIB(iptc, iptc_init,
- [
- AC_DEFINE(HAVE_LIBIPTC, 1, [Define to 1 if you have the iptc library (-liptc).])
- ],
- [
- with_libiptc="yes"
- with_own_libiptc="yes"
- ])
-fi
-if test "x$with_libiptc" = "xyes" -a "x$with_own_libiptc" != "xyes"
-then
- AC_CHECK_HEADERS(libiptc/libiptc.h,
- [
- AC_DEFINE(HAVE_LIBIPTC_LIBIPTC_H, 1, [Define to 1 if you have the <libiptc/libiptc.h> header file.])
- ],
- [
- with_libiptc="yes"
- with_own_libiptc="yes"
- ])
-fi
-if test "x$with_libiptc" = "xyes"
-then
- SAVE_CFLAGS=$CFLAGS
- CFLAGS="$CFLAGS $KERNEL_CFLAGS"
- AC_CHECK_HEADERS(linux/netfilter_ipv4/ip_tables.h linux/netfilter_ipv6/ip6_tables.h, [],
- [
- with_libiptc="no (Linux iptables headers not found - check KERNEL_DIR)"
- with_own_libiptc="no"
- ],
- [
-#include "$srcdir/src/libiptc/ipt_kernel_headers.h"
- ])
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libpq_cppflags"
- CFLAGS=$SAVE_CFLAGS
+ AC_CHECK_HEADERS(libpq-fe.h, [],
+ [with_libpq="no (libpq-fe.h not found)"], [])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
fi
-AM_CONDITIONAL(BUILD_WITH_LIBIPTC, test "x$with_libiptc" = "xyes")
-AM_CONDITIONAL(BUILD_WITH_OWN_LIBIPTC, test "x$with_own_libiptc" = "xyes")
-if test "x$with_own_libiptc" = "xyes"
+if test "x$with_libpq" = "xyes"
then
- AC_DEFINE(OWN_LIBIPTC, 1, [Define to 1 if we use the shipped iptc library.])
-fi
+ with_libpq_libdir=`$with_pg_config --libdir 2> /dev/null`
+ pg_config_status=$?
-with_snmp_config="net-snmp-config"
-with_snmp_cflags=""
-with_snmp_libs=""
-AC_ARG_WITH(libnetsnmp, [AS_HELP_STRING([--with-libnetsnmp@<:@=PREFIX@:>@], [Path to the Net-SNMPD library.])],
-[
- if test "x$withval" = "xno"
- then
- with_libnetsnmp="no"
- else if test "x$withval" = "xyes"
+ if test $pg_config_status -eq 0
then
- with_libnetsnmp="yes"
- else
- if test -x "$withval"
- then
- with_snmp_config="$withval"
- with_libnetsnmp="yes"
- else
- with_snmp_config="$withval/bin/net-snmp-config"
- with_libnetsnmp="yes"
+ if test -n "$with_libpq_libdir"; then
+ for dir in $with_libpq_libdir; do
+ with_libpq_ldflags="$with_libpq_ldflags -L$dir"
+ done
fi
- fi; fi
-],
-[with_libnetsnmp="yes"])
-if test "x$with_libnetsnmp" = "xyes"
-then
- with_snmp_cflags=`$with_snmp_config --cflags 2>/dev/null`
- snmp_config_status=$?
-
- if test $snmp_config_status -ne 0
- then
- with_libnetsnmp="no ($with_snmp_config failed)"
else
- SAVE_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $with_snmp_cflags"
-
- AC_CHECK_HEADERS(net-snmp/net-snmp-config.h, [], [with_libnetsnmp="no (net-snmp/net-snmp-config.h not found)"])
-
- CPPFLAGS="$SAVE_CPPFLAGS"
+ AC_MSG_WARN([$with_pg_config returned with status $pg_config_status])
fi
+
+ SAVE_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $with_libpq_ldflags"
+
+ AC_CHECK_LIB(pq, PQconnectdb,
+ [with_libpq="yes"],
+ [with_libpq="no (symbol 'PQconnectdb' not found)"])
+
+ LDFLAGS="$SAVE_LDFLAGS"
fi
-if test "x$with_libnetsnmp" = "xyes"
+if test "x$with_libpq" = "xyes"
then
- with_snmp_libs=`$with_snmp_config --libs 2>/dev/null`
- snmp_config_status=$?
+ BUILD_WITH_LIBPQ_CPPFLAGS="$with_libpq_cppflags"
+ BUILD_WITH_LIBPQ_LDFLAGS="$with_libpq_ldflags"
+ AC_SUBST(BUILD_WITH_LIBPQ_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBPQ_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBPQ, test "x$with_libpq" = "xyes")
+# }}}
- if test $snmp_config_status -ne 0
+# --with-libpthread {{{
+AC_ARG_WITH(libpthread, [AS_HELP_STRING([--with-libpthread=@<:@=PREFIX@:>@], [Path to libpthread.])],
+[ if test "x$withval" != "xno" \
+ && test "x$withval" != "xyes"
then
- with_libnetsnmp="no ($with_snmp_config failed)"
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ with_libpthread="yes"
else
- AC_CHECK_LIB(netsnmp, init_snmp,
- [with_libnetsnmp="yes"],
- [with_libnetsnmp="no (libnetsnmp not found)"],
- [$with_snmp_libs])
+ if test "x$withval" = "xno"
+ then
+ with_libpthread="no (disabled)"
+ fi
fi
-fi
-if test "x$with_libnetsnmp" = "xyes"
+], [with_libpthread="yes"])
+if test "x$with_libpthread" = "xyes"
then
- BUILD_WITH_LIBSNMP_CFLAGS="$with_snmp_cflags"
- BUILD_WITH_LIBSNMP_LIBS="$with_snmp_libs"
- AC_SUBST(BUILD_WITH_LIBSNMP_CFLAGS)
- AC_SUBST(BUILD_WITH_LIBSNMP_LIBS)
+ AC_CHECK_LIB(pthread, pthread_create, [with_libpthread="yes"], [with_libpthread="no (libpthread not found)"], [])
fi
-AM_CONDITIONAL(BUILD_WITH_LIBNETSNMP, test "x$with_libnetsnmp" = "xyes")
-
-PKG_CHECK_MODULES([LIBNOTIFY], [libnotify],
- [with_libnotify="yes"],
- [with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"])
-
-with_libupsclient="no (pkg-config isn't available)"
-with_libupsclient_cflags=""
-with_libupsclient_libs=""
-if test "x$PKG_CONFIG" != "x"
+if test "x$with_libpthread" = "xyes"
then
- pkg-config --exists 'libupsclient' 2>/dev/null
- if test "$?" = "0"
- then
- with_libupsclient="yes"
- else
- with_libupsclient="no (pkg-config doesn't know library)"
- fi
+ AC_CHECK_HEADERS(pthread.h,, [with_libpthread="no (pthread.h not found)"])
fi
-if test "x$with_libupsclient" = "xyes"
+if test "x$with_libpthread" = "xyes"
then
- with_libupsclient_cflags="`pkg-config --cflags 'libupsclient'`"
- if test $? -ne 0
- then
- with_libupsclient="no"
- fi
- with_libupsclient_libs="`pkg-config --libs 'libupsclient'`"
- if test $? -ne 0
+ collect_pthread=1
+else
+ collect_pthread=0
+fi
+AC_DEFINE_UNQUOTED(HAVE_LIBPTHREAD, [$collect_pthread],
+ [Wether or not to use pthread (POSIX threads) library])
+AM_CONDITIONAL(BUILD_WITH_LIBPTHREAD, test "x$with_libpthread" = "xyes")
+# }}}
+
+# --with-librrd {{{
+# AC_ARG_WITH (package, help-string, [action-if-given], [action-if-not-given])
+librrd_cflags=""
+librrd_ldflags=""
+librrd_threadsafe="yes"
+librrd_rrdc_update="no"
+AC_ARG_WITH(librrd, [AS_HELP_STRING([--with-librrd@<:@=PREFIX@:>@], [Path to rrdtool.])],
+[ if test "x$withval" != "xno" && test "x$withval" != "xyes"
then
- with_libupsclient="no"
+ librrd_cflags="-I$withval/include"
+ librrd_ldflags="-L$withval/lib"
+ with_librrd="yes"
+ else
+ with_librrd="$withval"
fi
-fi
-if test "x$with_libupsclient" = "xyes"
+], [with_librrd="yes"])
+if test "x$with_librrd" = "xyes"
then
SAVE_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags"
+ SAVE_LDFLAGS="$LDFLAGS"
- AC_CHECK_HEADERS(upsclient.h, [], [with_libupsclient="no (upsclient.h not found)"])
+ CPPFLAGS="$CPPFLAGS $librrd_cflags"
+ LDFLAGS="$LDFLAGS $librrd_ldflags"
+
+ AC_CHECK_HEADERS(rrd.h,, [with_librrd="no (rrd.h not found)"])
CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
fi
-if test "x$with_libupsclient" = "xyes"
+if test "x$with_librrd" = "xyes"
then
SAVE_CPPFLAGS="$CPPFLAGS"
SAVE_LDFLAGS="$LDFLAGS"
- CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags"
- LDFLAGS="$LDFLAGS $with_libupsclient_libs"
+ CPPFLAGS="$CPPFLAGS $librrd_cflags"
+ LDFLAGS="$LDFLAGS $librrd_ldflags"
- AC_CHECK_LIB(upsclient, upscli_connect,
- [with_libupsclient="yes"],
- [with_libupsclient="no (symbol upscli_connect not found)"])
+ AC_CHECK_LIB(rrd_th, rrd_update_r,
+ [with_librrd="yes"
+ librrd_ldflags="$librrd_ldflags -lrrd_th -lm"
+ ],
+ [librrd_threadsafe="no"
+ AC_CHECK_LIB(rrd, rrd_update,
+ [with_librrd="yes"
+ librrd_ldflags="$librrd_ldflags -lrrd -lm"
+ ],
+ [with_librrd="no (symbol 'rrd_update' not found)"],
+ [-lm])
+ ],
+ [-lm])
+
+ if test "x$librrd_threadsafe" = "xyes"
+ then
+ AC_CHECK_LIB(rrd_th, rrdc_update, [librrd_rrdc_update="yes"], [librrd_rrdc_update="no"])
+ else
+ AC_CHECK_LIB(rrd, rrdc_update, [librrd_rrdc_update="yes"], [librrd_rrdc_update="no"])
+ fi
CPPFLAGS="$SAVE_CPPFLAGS"
LDFLAGS="$SAVE_LDFLAGS"
fi
-if test "x$with_libupsclient" = "xyes"
+if test "x$with_librrd" = "xyes"
then
- SAVE_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags"
-
- AC_CHECK_TYPES([UPSCONN_t, UPSCONN], [], [],
-[#include <stdlib.h>
-#include <stdio.h>
-#include <upsclient.h>])
-
- CPPFLAGS="$SAVE_CPPFLAGS"
+ BUILD_WITH_LIBRRD_CFLAGS="$librrd_cflags"
+ BUILD_WITH_LIBRRD_LDFLAGS="$librrd_ldflags"
+ AC_SUBST(BUILD_WITH_LIBRRD_CFLAGS)
+ AC_SUBST(BUILD_WITH_LIBRRD_LDFLAGS)
fi
-if test "x$with_libupsclient" = "xyes"
+if test "x$librrd_threadsafe" = "xyes"
then
- BUILD_WITH_LIBUPSCLIENT_CFLAGS="$with_libupsclient_cflags"
- BUILD_WITH_LIBUPSCLIENT_LIBS="$with_libupsclient_libs"
- AC_SUBST(BUILD_WITH_LIBUPSCLIENT_CFLAGS)
- AC_SUBST(BUILD_WITH_LIBUPSCLIENT_LIBS)
+ AC_DEFINE(HAVE_THREADSAFE_LIBRRD, 1, [Define to 1 if you have the threadsafe rrd library (-lrrd_th).])
fi
+# }}}
-### BEGIN of check for libxmms ###
-with_xmms_config="xmms-config"
-with_xmms_cflags=""
-with_xmms_libs=""
-AC_ARG_WITH(libxmms, [AS_HELP_STRING([--with-libxmms@<:@=PREFIX@:>@], [Path to libxmms.])],
+# --with-libsensors {{{
+with_sensors_cflags=""
+with_sensors_ldflags=""
+AC_ARG_WITH(libsensors, [AS_HELP_STRING([--with-libsensors@<:@=PREFIX@:>@], [Path to lm_sensors.])],
[
- if test "x$withval" != "xno" \
- && test "x$withval" != "xyes"
- then
- if test -f "$withval" && test -x "$withval";
- then
- with_xmms_config="$withval"
- else if test -x "$withval/bin/xmms-config"
- then
- with_xmms_config="$withval/bin/xmms-config"
- fi; fi
- with_libxmms="yes"
- else if test "x$withval" = "xno"
+ if test "x$withval" = "xno"
then
- with_libxmms="no"
+ with_libsensors="no"
else
- with_libxmms="yes"
- fi; fi
+ with_libsensors="yes"
+ if test "x$withval" != "xyes"
+ then
+ with_sensors_cflags="-I$withval/include"
+ with_sensors_ldflags="-L$withval/lib"
+ with_libsensors="yes"
+ fi
+ fi
],
[
- with_libxmms="yes"
-])
-if test "x$with_libxmms" = "xyes"
-then
- with_xmms_cflags=`$with_xmms_config --cflags 2>/dev/null`
- xmms_config_status=$?
-
- if test $xmms_config_status -ne 0
+ if test "x$ac_system" = "xLinux"
then
- with_libxmms="no"
+ with_libsensors="yes"
+ else
+ with_libsensors="no (Linux only library)"
fi
-fi
-if test "x$with_libxmms" = "xyes"
+])
+if test "x$with_libsensors" = "xyes"
then
- with_xmms_libs=`$with_xmms_config --libs 2>/dev/null`
- xmms_config_status=$?
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_sensors_cflags"
- if test $xmms_config_status -ne 0
- then
- with_libxmms="no"
- fi
+# AC_CHECK_HEADERS(sensors/sensors.h,
+# [
+# AC_DEFINE(HAVE_SENSORS_SENSORS_H, 1, [Define to 1 if you have the <sensors/sensors.h> header file.])
+# ],
+# [with_libsensors="no (sensors/sensors.h not found)"])
+ AC_CHECK_HEADERS(sensors/sensors.h, [], [with_libsensors="no (sensors/sensors.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
fi
-if test "x$with_libxmms" = "xyes"
+if test "x$with_libsensors" = "xyes"
then
- AC_CHECK_LIB(xmms, xmms_remote_get_info,
- [
- BUILD_WITH_LIBXMMS_CFLAGS="$with_xmms_cflags"
- BUILD_WITH_LIBXMMS_LIBS="$with_xmms_libs"
- AC_SUBST(BUILD_WITH_LIBXMMS_CFLAGS)
- AC_SUBST(BUILD_WITH_LIBXMMS_LIBS)
- ],
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_sensors_cflags"
+ LDFLAGS="$LDFLAGS $with_sensors_ldflags"
+
+ AC_CHECK_LIB(sensors, sensors_init,
[
- with_libxmms="no"
+ AC_DEFINE(HAVE_LIBSENSORS, 1, [Define to 1 if you have the sensors library (-lsensors).])
],
- [$with_xmms_libs])
+ [with_libsensors="no (libsensors not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
fi
-with_libxmms_numeric=0
-if test "x$with_libxmms" = "xyes"
+if test "x$with_libsensors" = "xyes"
then
- with_libxmms_numeric=1
+ BUILD_WITH_LIBSENSORS_CFLAGS="$with_sensors_cflags"
+ BUILD_WITH_LIBSENSORS_LDFLAGS="$with_sensors_ldflags"
+ AC_SUBST(BUILD_WITH_LIBSENSORS_CFLAGS)
+ AC_SUBST(BUILD_WITH_LIBSENSORS_LDFLAGS)
fi
-AC_DEFINE_UNQUOTED(HAVE_LIBXMMS, [$with_libxmms_numeric], [Define to 1 if you have the 'xmms' library (-lxmms).])
-AM_CONDITIONAL(BUILD_WITH_LIBXMMS, test "x$with_libxmms" = "xyes")
-### END of check for libxmms ###
+AM_CONDITIONAL(BUILD_WITH_LM_SENSORS, test "x$with_libsensors" = "xyes")
+# }}}
-with_libnetlink_cflags=""
-with_libnetlink_libs="-lnetlink"
-AC_ARG_WITH(libnetlink, [AS_HELP_STRING([--with-libnetlink@<:@=PREFIX@:>@], [Path to libnetlink.])],
+# --with-libstatgrab {{{
+with_libstatgrab_cflags=""
+with_libstatgrab_ldflags=""
+AC_ARG_WITH(libstatgrab, [AS_HELP_STRING([--with-libstatgrab@<:@=PREFIX@:>@], [Path to libstatgrab.])],
[
- echo "libnetlink: withval = $withval"
- if test "x$withval" = "xyes"
- then
- with_libnetlink="yes"
- else if test "x$withval" = "xno"
- then
- with_libnetlink="no"
- else
- if test -d "$withval/include"
- then
- with_libnetlink_cflags="-I$withval/include"
- with_libnetlink_libs="-L$withval/lib -lnetlink"
- with_libnetlink="yes"
- else
- AC_MSG_ERROR("no such directory: $withval/include")
- fi
- fi; fi
+ if test "x$withval" != "xno" \
+ && test "x$withval" != "xyes"
+ then
+ with_libstatgrab_cflags="-I$withval/include"
+ with_libstatgrab_ldflags="-L$withval/lib"
+ with_libstatgrab="yes"
+ else
+ with_libstatgrab="$withval"
+ fi
],
[
- if test "x$ac_system" = "xLinux"
- then
- with_libnetlink="yes"
- else
- with_libnetlink="no (Linux only library)"
- fi
+ if test "x$ac_system" = "xunknown"
+ then
+ with_libstatgrab="yes"
+ else
+ with_libstatgrab="no"
+ fi
])
-if test "x$with_libnetlink" = "xyes"
-then
- SAVE_CFLAGS=$CFLAGS
- CFLAGS="$CFLAGS $with_libnetlink_cflags"
-
- with_libnetlink="no (libnetlink.h not found)"
-
- AC_CHECK_HEADERS(libnetlink.h iproute/libnetlink.h linux/libnetlink.h,
- [
- with_libnetlink="yes"
- break
- ], [],
-[#include <stdio.h>
-#include <sys/types.h>
-#include <asm/types.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>])
- AC_CHECK_HEADERS(linux/gen_stats.h linux/pkt_sched.h, [], [],
-[#include <stdio.h>
-#include <sys/types.h>
-#include <asm/types.h>
-#include <sys/socket.h>])
-
- AC_COMPILE_IFELSE(
-[#include <stdio.h>
-#include <sys/types.h>
-#include <asm/types.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-
-int main (void)
-{
- int retval = TCA_STATS2;
- return (retval);
-}],
- [AC_DEFINE([HAVE_TCA_STATS2], 1, [True if the enum-member TCA_STATS2 exists])]
- []);
-
- AC_COMPILE_IFELSE(
-[#include <stdio.h>
-#include <sys/types.h>
-#include <asm/types.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-
-int main (void)
-{
- int retval = TCA_STATS;
- return (retval);
-}],
- [AC_DEFINE([HAVE_TCA_STATS], 1, [True if the enum-member TCA_STATS exists])]
- []);
-
- CFLAGS="$SAVE_CFLAGS"
-fi
-if test "x$with_libnetlink" = "xyes"
-then
- AC_CHECK_LIB(netlink, rtnl_open,
- [with_libnetlink="yes"],
- [with_libnetlink="no (symbol 'rtnl_open' not found)"],
- [$with_libnetlink_libs])
-fi
-if test "x$with_libnetlink" = "xyes"
-then
- BUILD_WITH_LIBNETLINK_CFLAGS="$with_libnetlink_cflags"
- BUILD_WITH_LIBNETLINK_LIBS="$with_libnetlink_libs"
- AC_SUBST(BUILD_WITH_LIBNETLINK_CFLAGS)
- AC_SUBST(BUILD_WITH_LIBNETLINK_LIBS)
-fi
-AM_CONDITIONAL(BUILD_WITH_LIBNETLINK, test "x$with_libnetlink" = "xyes")
-
-with_libopenipmipthread="yes"
-with_libopenipmipthread_cflags=""
-with_libopenipmipthread_libs=""
-
-AC_MSG_CHECKING([for pkg-config])
-temp_result="no"
-if test "x$PKG_CONFIG" = "x"
+with_libstatgrab_pkg_config="yes"
+if test "x$with_libstatgrab" = "xyes" \
+ && test "x$PKG_CONFIG" != "x"
then
- with_libopenipmipthread="no"
- temp_result="no"
+ AC_MSG_CHECKING([pkg-config for libstatgrab])
+ temp_result="found"
+ $PKG_CONFIG --exists libstatgrab 2>/dev/null
+ if test "$?" != "0"
+ then
+ with_libstatgrab_pkg_config="no"
+ temp_result="not found"
+ fi
+ AC_MSG_RESULT([$temp_result])
else
- temp_result="$PKG_CONFIG"
+ AC_MSG_NOTICE([pkg-config not available, trying to guess flags for the statgrab library.])
+ with_libstatgrab_pkg_config="no"
+ with_libstatgrab_ldflags="$with_libstatgrab_ldflags -lstatgrab"
fi
-AC_MSG_RESULT([$temp_result])
-if test "x$with_libopenipmipthread" = "xyes"
+if test "x$with_libstatgrab" = "xyes" \
+ && test "x$with_libstatgrab_pkg_config" = "xyes" \
+ && test "x$with_libstatgrab_cflags" = "x"
then
- AC_MSG_CHECKING([for libOpenIPMIpthread])
- $PKG_CONFIG --exists OpenIPMIpthread 2>/dev/null
- if test "$?" != "0"
- then
- with_libopenipmipthread="no ($PKG_CONFIG doesn't know OpenIPMIpthread)"
- fi
- AC_MSG_RESULT([$with_libopenipmipthread])
+ AC_MSG_CHECKING([for libstatgrab CFLAGS])
+ temp_result="`$PKG_CONFIG --cflags libstatgrab`"
+ if test "$?" = "0"
+ then
+ with_libstatgrab_cflags="$temp_result"
+ else
+ with_libstatgrab="no ($PKG_CONFIG --cflags libstatgrab failed)"
+ temp_result="$PKG_CONFIG --cflags libstatgrab failed"
+ fi
+ AC_MSG_RESULT([$temp_result])
fi
-if test "x$with_libopenipmipthread" = "xyes"
+if test "x$with_libstatgrab" = "xyes" \
+ && test "x$with_libstatgrab_pkg_config" = "xyes" \
+ && test "x$with_libstatgrab_ldflags" = "x"
then
- AC_MSG_CHECKING([for libOpenIPMIpthread CFLAGS])
- temp_result="`$PKG_CONFIG --cflags OpenIPMIpthread`"
- if test "$?" = "0"
- then
- with_libopenipmipthread_cflags="$temp_result"
- else
- with_libopenipmipthread="no ($PKG_CONFIG --cflags OpenIPMIpthread failed)"
- temp_result="$PKG_CONFIG --cflags OpenIPMIpthread failed"
- fi
- AC_MSG_RESULT([$temp_result])
+ AC_MSG_CHECKING([for libstatgrab LDFLAGS])
+ temp_result="`$PKG_CONFIG --libs libstatgrab`"
+ if test "$?" = "0"
+ then
+ with_libstatgrab_ldflags="$temp_result"
+ else
+ with_libstatgrab="no ($PKG_CONFIG --libs libstatgrab failed)"
+ temp_result="$PKG_CONFIG --libs libstatgrab failed"
+ fi
+ AC_MSG_RESULT([$temp_result])
fi
-if test "x$with_libopenipmipthread" = "xyes"
+if test "x$with_libstatgrab" = "xyes"
then
- AC_MSG_CHECKING([for libOpenIPMIpthread LDFLAGS])
- temp_result="`$PKG_CONFIG --libs OpenIPMIpthread`"
- if test "$?" = "0"
- then
- with_libopenipmipthread_ldflags="$temp_result"
- else
- with_libopenipmipthread="no ($PKG_CONFIG --libs OpenIPMIpthread failed)"
- temp_result="$PKG_CONFIG --libs OpenIPMIpthread failed"
- fi
- AC_MSG_RESULT([$temp_result])
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libstatgrab_cflags"
+
+ AC_CHECK_HEADERS(statgrab.h,
+ [with_libstatgrab="yes"],
+ [with_libstatgrab="no (statgrab.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
fi
-if test "x$with_libopenipmipthread" = "xyes"
+if test "x$with_libstatgrab" = "xyes"
then
- SAVE_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $with_libopenipmipthread_cflags"
+ SAVE_CFLAGS="$CFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
- AC_CHECK_HEADERS(OpenIPMI/ipmi_smi.h,
- [with_libopenipmipthread="yes"],
- [with_libopenipmipthread="no (OpenIPMI/ipmi_smi.h not found)"],
-[#include <OpenIPMI/ipmiif.h>
-#include <OpenIPMI/ipmi_err.h>
-#include <OpenIPMI/ipmi_posix.h>
-#include <OpenIPMI/ipmi_conn.h>
-])
+ CFLAGS="$CFLAGS $with_libstatgrab_cflags"
+ LDFLAGS="$LDFLAGS $with_libstatgrab_ldflags"
- CPPFLAGS="$SAVE_CPPFLAGS"
+ AC_CHECK_LIB(statgrab, sg_init,
+ [with_libstatgrab="yes"],
+ [with_libstatgrab="no (symbol sg_init not found)"])
+
+ CFLAGS="$SAVE_CFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
fi
-if test "x$with_libopenipmipthread" = "xyes"
+AM_CONDITIONAL(BUILD_WITH_LIBSTATGRAB, test "x$with_libstatgrab" = "xyes")
+if test "x$with_libstatgrab" = "xyes"
then
- BUILD_WITH_OPENIPMI_CFLAGS="$with_libopenipmipthread_cflags"
- BUILD_WITH_OPENIPMI_LIBS="$with_libopenipmipthread_ldflags"
- AC_SUBST(BUILD_WITH_OPENIPMI_CFLAGS)
- AC_SUBST(BUILD_WITH_OPENIPMI_LIBS)
+ AC_DEFINE(HAVE_LIBSTATGRAB, 1, [Define to 1 if you have the 'statgrab' library (-lstatgrab)])
+ BUILD_WITH_LIBSTATGRAB_CFLAGS="$with_libstatgrab_cflags"
+ BUILD_WITH_LIBSTATGRAB_LDFLAGS="$with_libstatgrab_ldflags"
+ AC_SUBST(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+ AC_SUBST(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
fi
+# }}}
-dnl Check for libpq.
-with_pg_config="pg_config"
-with_libpq_includedir=""
-with_libpq_libdir=""
-with_libpq_cppflags=""
-with_libpq_ldflags=""
-AC_ARG_WITH(libpq, [AS_HELP_STRING([--with-libpq@<:@=PREFIX@:>@],
- [Path to libpq.])],
+# --with-libxmms {{{
+with_xmms_config="xmms-config"
+with_xmms_cflags=""
+with_xmms_libs=""
+AC_ARG_WITH(libxmms, [AS_HELP_STRING([--with-libxmms@<:@=PREFIX@:>@], [Path to libxmms.])],
[
- if test "x$withval" = "xno"
- then
- with_libpq="no"
- else if test "x$withval" = "xyes"
+ if test "x$withval" != "xno" \
+ && test "x$withval" != "xyes"
then
- with_libpq="yes"
- else
if test -f "$withval" && test -x "$withval";
then
- with_pg_config="$withval"
- else if test -x "$withval/bin/pg_config"
+ with_xmms_config="$withval"
+ else if test -x "$withval/bin/xmms-config"
then
- with_pg_config="$withval/bin/pg_config"
+ with_xmms_config="$withval/bin/xmms-config"
fi; fi
- with_libpq="yes"
+ with_libxmms="yes"
+ else if test "x$withval" = "xno"
+ then
+ with_libxmms="no"
+ else
+ with_libxmms="yes"
fi; fi
],
[
- with_libpq="yes"
+ with_libxmms="yes"
])
-if test "x$with_libpq" = "xyes"
+if test "x$with_libxmms" = "xyes"
then
- with_libpq_includedir=`$with_pg_config --includedir 2> /dev/null`
- pg_config_status=$?
+ with_xmms_cflags=`$with_xmms_config --cflags 2>/dev/null`
+ xmms_config_status=$?
- if test $pg_config_status -eq 0
+ if test $xmms_config_status -ne 0
then
- if test -n "$with_libpq_includedir"; then
- for dir in $with_libpq_includedir; do
- with_libpq_cppflags="$with_libpq_cppflags -I$dir"
- done
- fi
- else
- AC_MSG_WARN([$with_pg_config returned with status $pg_config_status])
+ with_libxmms="no"
fi
+fi
+if test "x$with_libxmms" = "xyes"
+then
+ with_xmms_libs=`$with_xmms_config --libs 2>/dev/null`
+ xmms_config_status=$?
- SAVE_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $with_libpq_cppflags"
-
- AC_CHECK_HEADERS(libpq-fe.h, [],
- [with_libpq="no (libpq-fe.h not found)"], [])
-
- CPPFLAGS="$SAVE_CPPFLAGS"
+ if test $xmms_config_status -ne 0
+ then
+ with_libxmms="no"
+ fi
fi
-if test "x$with_libpq" = "xyes"
+if test "x$with_libxmms" = "xyes"
then
- with_libpq_libdir=`$with_pg_config --libdir 2> /dev/null`
- pg_config_status=$?
+ AC_CHECK_LIB(xmms, xmms_remote_get_info,
+ [
+ BUILD_WITH_LIBXMMS_CFLAGS="$with_xmms_cflags"
+ BUILD_WITH_LIBXMMS_LIBS="$with_xmms_libs"
+ AC_SUBST(BUILD_WITH_LIBXMMS_CFLAGS)
+ AC_SUBST(BUILD_WITH_LIBXMMS_LIBS)
+ ],
+ [
+ with_libxmms="no"
+ ],
+ [$with_xmms_libs])
+fi
+with_libxmms_numeric=0
+if test "x$with_libxmms" = "xyes"
+then
+ with_libxmms_numeric=1
+fi
+AC_DEFINE_UNQUOTED(HAVE_LIBXMMS, [$with_libxmms_numeric], [Define to 1 if you have the 'xmms' library (-lxmms).])
+AM_CONDITIONAL(BUILD_WITH_LIBXMMS, test "x$with_libxmms" = "xyes")
+# }}}
- if test $pg_config_status -eq 0
+# pkg-config --exists 'libupsclient' {{{
+with_libupsclient="no (pkg-config isn't available)"
+with_libupsclient_cflags=""
+with_libupsclient_libs=""
+if test "x$PKG_CONFIG" != "x"
+then
+ pkg-config --exists 'libupsclient' 2>/dev/null
+ if test "$?" = "0"
then
- if test -n "$with_libpq_libdir"; then
- for dir in $with_libpq_libdir; do
- with_libpq_ldflags="$with_libpq_ldflags -L$dir"
- done
- fi
+ with_libupsclient="yes"
else
- AC_MSG_WARN([$with_pg_config returned with status $pg_config_status])
+ with_libupsclient="no (pkg-config doesn't know library)"
+ fi
+fi
+if test "x$with_libupsclient" = "xyes"
+then
+ with_libupsclient_cflags="`pkg-config --cflags 'libupsclient'`"
+ if test $? -ne 0
+ then
+ with_libupsclient="no"
+ fi
+ with_libupsclient_libs="`pkg-config --libs 'libupsclient'`"
+ if test $? -ne 0
+ then
+ with_libupsclient="no"
fi
+fi
+if test "x$with_libupsclient" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags"
+ AC_CHECK_HEADERS(upsclient.h, [], [with_libupsclient="no (upsclient.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libupsclient" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
SAVE_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $with_libpq_ldflags"
- AC_CHECK_LIB(pq, PQconnectdb,
- [with_libpq="yes"],
- [with_libpq="no (symbol 'PQconnectdb' not found)"])
+ CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags"
+ LDFLAGS="$LDFLAGS $with_libupsclient_libs"
+
+ AC_CHECK_LIB(upsclient, upscli_connect,
+ [with_libupsclient="yes"],
+ [with_libupsclient="no (symbol upscli_connect not found)"])
+ CPPFLAGS="$SAVE_CPPFLAGS"
LDFLAGS="$SAVE_LDFLAGS"
fi
-if test "x$with_libpq" = "xyes"
+if test "x$with_libupsclient" = "xyes"
then
- BUILD_WITH_LIBPQ_CPPFLAGS="$with_libpq_cppflags"
- BUILD_WITH_LIBPQ_LDFLAGS="$with_libpq_ldflags"
- AC_SUBST(BUILD_WITH_LIBPQ_CPPFLAGS)
- AC_SUBST(BUILD_WITH_LIBPQ_LDFLAGS)
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags"
+
+ AC_CHECK_TYPES([UPSCONN_t, UPSCONN], [], [],
+[#include <stdlib.h>
+#include <stdio.h>
+#include <upsclient.h>])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
fi
-AM_CONDITIONAL(BUILD_WITH_LIBPQ, test "x$with_libpq" = "xyes")
+if test "x$with_libupsclient" = "xyes"
+then
+ BUILD_WITH_LIBUPSCLIENT_CFLAGS="$with_libupsclient_cflags"
+ BUILD_WITH_LIBUPSCLIENT_LIBS="$with_libupsclient_libs"
+ AC_SUBST(BUILD_WITH_LIBUPSCLIENT_CFLAGS)
+ AC_SUBST(BUILD_WITH_LIBUPSCLIENT_LIBS)
+fi
+# }}}
-dnl Check for libvirt and libxml2 libraries.
+# pkg-config --exists 'libxml-2.0'; pkg-config --exists libvirt {{{
with_libxml2="no (pkg-config isn't available)"
with_libxml2_cflags=""
with_libxml2_ldflags=""
AC_SUBST(BUILD_WITH_LIBVIRT_CFLAGS)
AC_SUBST(BUILD_WITH_LIBVIRT_LIBS)
fi
+# }}}
+
+# $PKG_CONFIG --exists OpenIPMIpthread {{{
+with_libopenipmipthread="yes"
+with_libopenipmipthread_cflags=""
+with_libopenipmipthread_libs=""
+
+AC_MSG_CHECKING([for pkg-config])
+temp_result="no"
+if test "x$PKG_CONFIG" = "x"
+then
+ with_libopenipmipthread="no"
+ temp_result="no"
+else
+ temp_result="$PKG_CONFIG"
+fi
+AC_MSG_RESULT([$temp_result])
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+ AC_MSG_CHECKING([for libOpenIPMIpthread])
+ $PKG_CONFIG --exists OpenIPMIpthread 2>/dev/null
+ if test "$?" != "0"
+ then
+ with_libopenipmipthread="no ($PKG_CONFIG doesn't know OpenIPMIpthread)"
+ fi
+ AC_MSG_RESULT([$with_libopenipmipthread])
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+ AC_MSG_CHECKING([for libOpenIPMIpthread CFLAGS])
+ temp_result="`$PKG_CONFIG --cflags OpenIPMIpthread`"
+ if test "$?" = "0"
+ then
+ with_libopenipmipthread_cflags="$temp_result"
+ else
+ with_libopenipmipthread="no ($PKG_CONFIG --cflags OpenIPMIpthread failed)"
+ temp_result="$PKG_CONFIG --cflags OpenIPMIpthread failed"
+ fi
+ AC_MSG_RESULT([$temp_result])
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+ AC_MSG_CHECKING([for libOpenIPMIpthread LDFLAGS])
+ temp_result="`$PKG_CONFIG --libs OpenIPMIpthread`"
+ if test "$?" = "0"
+ then
+ with_libopenipmipthread_ldflags="$temp_result"
+ else
+ with_libopenipmipthread="no ($PKG_CONFIG --libs OpenIPMIpthread failed)"
+ temp_result="$PKG_CONFIG --libs OpenIPMIpthread failed"
+ fi
+ AC_MSG_RESULT([$temp_result])
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libopenipmipthread_cflags"
+
+ AC_CHECK_HEADERS(OpenIPMI/ipmi_smi.h,
+ [with_libopenipmipthread="yes"],
+ [with_libopenipmipthread="no (OpenIPMI/ipmi_smi.h not found)"],
+[#include <OpenIPMI/ipmiif.h>
+#include <OpenIPMI/ipmi_err.h>
+#include <OpenIPMI/ipmi_posix.h>
+#include <OpenIPMI/ipmi_conn.h>
+])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+ BUILD_WITH_OPENIPMI_CFLAGS="$with_libopenipmipthread_cflags"
+ BUILD_WITH_OPENIPMI_LIBS="$with_libopenipmipthread_ldflags"
+ AC_SUBST(BUILD_WITH_OPENIPMI_CFLAGS)
+ AC_SUBST(BUILD_WITH_OPENIPMI_LIBS)
+fi
+# }}}
-dnl End of check for libvirt and libxml2 libraries.
+PKG_CHECK_MODULES([LIBNOTIFY], [libnotify],
+ [with_libnotify="yes"],
+ [with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"])
# Check for enabled/disabled features
#
AC_PLUGIN([cpufreq], [$plugin_cpufreq], [CPU frequency statistics])
AC_PLUGIN([csv], [yes], [CSV output plugin])
AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications])
+AC_PLUGIN([dbi], [$with_libdbi], [General database statistics])
AC_PLUGIN([df], [$plugin_df], [Filesystem usage statistics])
AC_PLUGIN([disk], [$plugin_disk], [Disk usage statistics])
AC_PLUGIN([dns], [$with_libpcap], [DNS traffic analysis])
AC_PLUGIN([postgresql], [$with_libpq], [PostgreSQL database statistics])
AC_PLUGIN([powerdns], [yes], [PowerDNS statistics])
AC_PLUGIN([processes], [$plugin_processes], [Process statistics])
-AC_PLUGIN([rrdtool], [$with_rrdtool], [RRDTool output plugin])
-AC_PLUGIN([sensors], [$with_lm_sensors], [lm_sensors statistics])
+AC_PLUGIN([rrdtool], [$with_librrd], [RRDTool output plugin])
+AC_PLUGIN([rrdcached], [$librrd_rrdc_update], [RRDTool output plugin])
+AC_PLUGIN([sensors], [$with_libsensors], [lm_sensors statistics])
AC_PLUGIN([serial], [$plugin_serial], [serial port traffic])
AC_PLUGIN([snmp], [$with_libnetsnmp], [SNMP querying plugin])
AC_PLUGIN([swap], [$plugin_swap], [Swap usage statistics])
AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/libiptc/Makefile src/liboconfig/Makefile src/liboping/Makefile bindings/Makefile)
-if test "x$with_rrdtool" = "xyes" \
+if test "x$with_librrd" = "xyes" \
&& test "x$librrd_threadsafe" != "xyes"
then
- with_rrdtool="yes (warning: librrd is not thread-safe)"
+ with_librrd="yes (warning: librrd is not thread-safe)"
fi
if test "x$with_liboping" = "xyes" \
Configuration:
Libraries:
libcurl . . . . . . . $with_libcurl
+ libdbi . . . . . . . $with_libdbi
libesmtp . . . . . . $with_libesmtp
libiokit . . . . . . $with_libiokit
libiptc . . . . . . . $with_libiptc
libperl . . . . . . . $with_libperl
libpthread . . . . . $with_libpthread
libpq . . . . . . . . $with_libpq
- librrd . . . . . . . $with_rrdtool
- libsensors . . . . . $with_lm_sensors
+ librrd . . . . . . . $with_librrd
+ libsensors . . . . . $with_libsensors
libstatgrab . . . . . $with_libstatgrab
libupsclient . . . . $with_libupsclient
libvirt . . . . . . . $with_libvirt
cpu . . . . . . . . . $enable_cpu
cpufreq . . . . . . . $enable_cpufreq
csv . . . . . . . . . $enable_csv
+ dbi . . . . . . . . . $enable_dbi
df . . . . . . . . . $enable_df
disk . . . . . . . . $enable_disk
dns . . . . . . . . . $enable_dns
powerdns . . . . . . $enable_powerdns
processes . . . . . . $enable_processes
rrdtool . . . . . . . $enable_rrdtool
+ rrdcached . . . . . . $enable_rrdcached
sensors . . . . . . . $enable_sensors
serial . . . . . . . $enable_serial
snmp . . . . . . . . $enable_snmp
if test "x$dependency_error" = "xyes"; then
AC_MSG_ERROR("Some plugins are missing dependencies - see above summary for details")
fi
+
+# vim: set fdm=marker :
collectd_DEPENDENCIES += csv.la
endif
+if BUILD_PLUGIN_DBI
+pkglib_LTLIBRARIES += dbi.la
+dbi_la_SOURCES = dbi.c
+dbi_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBDBI_CPPFLAGS)
+dbi_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBDBI_LDFLAGS)
+dbi_la_LIBADD = $(BUILD_WITH_LIBDBI_LIBS)
+collectd_LDADD += "-dlopen" dbi.la
+collectd_DEPENDENCIES += dbi.la
+endif
+
if BUILD_PLUGIN_DF
pkglib_LTLIBRARIES += df.la
df_la_SOURCES = df.c
endif
endif
+if BUILD_PLUGIN_RRDCACHED
+pkglib_LTLIBRARIES += rrdcached.la
+rrdcached_la_SOURCES = rrdcached.c utils_rrdcreate.c utils_rrdcreate.h
+rrdcached_la_LDFLAGS = -module -avoid-version
+rrdcached_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS)
+rrdcached_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS)
+collectd_LDADD += "-dlopen" rrdcached.la
+collectd_DEPENDENCIES += rrdcached.la
+endif
+
if BUILD_PLUGIN_RRDTOOL
pkglib_LTLIBRARIES += rrdtool.la
-rrdtool_la_SOURCES = rrdtool.c
+rrdtool_la_SOURCES = rrdtool.c utils_rrdcreate.c utils_rrdcreate.h
rrdtool_la_LDFLAGS = -module -avoid-version
rrdtool_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS)
rrdtool_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS)
@BUILD_PLUGIN_CPU_TRUE@LoadPlugin cpu
@BUILD_PLUGIN_CPUFREQ_TRUE@LoadPlugin cpufreq
@BUILD_PLUGIN_CSV_TRUE@LoadPlugin csv
+@BUILD_PLUGIN_DBI_TRUE@LoadPlugin dbi
@BUILD_PLUGIN_DF_TRUE@LoadPlugin df
@BUILD_PLUGIN_DISK_TRUE@LoadPlugin disk
@BUILD_PLUGIN_DNS_TRUE@LoadPlugin dns
@BUILD_PLUGIN_POSTGRESQL_TRUE@LoadPlugin postgresql
@BUILD_PLUGIN_POWERDNS_TRUE@LoadPlugin powerdns
@BUILD_PLUGIN_PROCESSES_TRUE@LoadPlugin processes
+@BUILD_PLUGIN_RRDCACHED_TRUE@LoadPlugin rrdcached
@BUILD_PLUGIN_RRDTOOL_TRUE@LoadPlugin rrdtool
@BUILD_PLUGIN_SENSORS_TRUE@LoadPlugin sensors
@BUILD_PLUGIN_SERIAL_TRUE@LoadPlugin serial
# StoreRates false
#</Plugin>
+#<Plugin dbi>
+# <Query "num_of_customers">
+# Statement "SELECT 'customers' AS c_key, COUNT(*) AS c_value FROM customers_tbl"
+# Type "gauge"
+# InstancesFrom "c_key"
+# ValuesFrom "c_value"
+# </Query>
+# <Database "customers_db">
+# Driver "mysql"
+# DriverOption "host" "localhost"
+# DriverOption "username" "collectd"
+# DriverOption "password" "AeXohy0O"
+# DriverOption "dbname" "custdb0"
+# #SelectDB "custdb0"
+# Query "num_of_customers"
+# #Query "..."
+# </Database>
+#</Plugin>
+
#<Plugin df>
# Device "/dev/hda1"
# Device "192.168.0.2:/mnt/nfs"
# Process "name"
#</Plugin>
+#<Plugin rrdcached>
+# DaemonAddress "unix:/tmp/rrdcached.sock"
+# DataDir "@prefix@/var/lib/@PACKAGE_NAME@/rrd"
+# CreateFiles true
+# CollectStatistics true
+#</Plugin>
+
#<Plugin rrdtool>
# DataDir "@prefix@/var/lib/@PACKAGE_NAME@/rrd"
# CacheTimeout 120
=back
+=head2 Plugin C<dbi>
+
+This plugin uses the "B<dbi>" library (L<http://libdbi.sourceforge.net/>) to
+connect to various databases, execute SQL statements and read back the results.
+You can configure how each column is to be interpreted and the plugin will
+generate one data set from each row returned according to these rules.
+
+Because the plugin is very generic, the configuration is a little more complex
+than those of other plugins. It usually looks something like this:
+
+ <Plugin dbi>
+ <Query "out_of_stock">
+ Statement "SELECT category, COUNT(*) AS value FROM products WHERE in_stock = 0 GROUP BY category"
+ Type "gauge"
+ InstancesFrom "category"
+ ValuesFrom "value"
+ </Query>
+ <Database "product_information">
+ Driver "mysql"
+ DriverOption "host" "localhost"
+ DriverOption "username" "collectd"
+ DriverOption "password" "aZo6daiw"
+ DriverOption "dbname" "prod_info"
+ SelectDB "prod_info"
+ Query "out_of_stock"
+ </Database>
+ </Plugin>
+
+The configuration above defines one query and one database. The query is then
+linked to the database with the B<Query> option I<within> the
+B<E<lt>DatabaseE<gt>> block. You can have any number of queries and databases
+and you can also use the B<Include> statement to split up the configuration
+file in multiple, smaller files. However, the B<E<lt>QueryE<gt>> block I<must>
+precede the B<E<lt>DatabaseE<gt>> blocks, because the file is interpreted from
+top to bottom!
+
+The following is a complete list of options:
+
+=head3 B<Query> blocks
+
+Query blocks define SQL statements and how the returned data should be
+interpreted. They are identified by the name that is given in the opening line
+of the block. Thus the name needs to be unique. Other than that, the name is
+not used in collectd.
+
+=over 4
+
+=item B<Statement> I<SQL>
+
+Sets the statement that should be executed on the server. This is B<not>
+interpreted by collectd, but simply passed to the database server. Therefore,
+the SQL dialect that's used depends on the server collectd is connected to.
+
+The query has to return at least two columns, one for the instance and one
+value. You cannot omit the instance, even if the statement is guaranteed to
+always return exactly one line. In that case, you can usually specify something
+like this:
+
+ Statement "SELECT \"instance\", COUNT(*) AS value FROM table"
+
+(That works with MySQL but may not be valid SQL according to the spec. If you
+use a more strict database server, you may have to select from a dummy table or
+something.)
+
+=item B<Type> I<Type>
+
+The B<type> that's used for each line returned. See L<types.db(5)> for more
+details on how types are defined. In short: A type is a predefined layout of
+data and the number of values and type of values has to match the type
+definition.
+
+If you specify "temperature" here, you need exactly one gauge column. If you
+specify "if_octets", you will need two counter columns. See the B<ValuesFrom>
+setting below.
+
+=item B<InstancesFrom> I<column0> [I<column1> ...]
+
+Specifies the columns whose values will be used to create the "TypeInstance"
+for each row. You need to specify at least one column for each query. If you
+specify more than one column, the value of all columns will be join together
+with the hyphen as separation character.
+
+The plugin itself does not check whether or not all built instances are
+different. It's your responsibility to assure that each is unique.
+
+=item B<ValuesFrom> I<column0> [I<column1> ...]
+
+Names the columns whose content is used as the actual data for the data sets
+that are dispatched to the daemon. How many such columns you need is determined
+by the B<Type> setting above. If you specify too many or not enough columns,
+the plugin will complain about that and no data will be submitted to the
+daemon.
+
+The actual data type in the columns is not that important. The plugin will
+automatically cast the values to the right type if it know how to do that. So
+it should be able to handle integer an floating point types, as well as strings
+(if they include a number at the beginning).
+
+=back
+
+=head3 B<Database> blocks
+
+Database blocks define a connection to a database and which queries should be
+sent to that database. Since the used "dbi" library can handle a wide variety
+of databases, the configuration is very generic. If in doubt, refer to libdbi's
+documentationE<nbsp>- we stick as close to the terminology used there.
+
+Each database needs a "name" as string argument in the starting tag of the
+block. This name will be used as "PluginInstance" in the values submitted to
+the daemon. Other than that, that name is not used.
+
+=over 4
+
+=item B<Driver> I<Driver>
+
+Specifies the driver to use to connect to the database. In many cases those
+drivers are named after the database they can connect to, but this is not a
+technical necessity. These drivers are sometimes referred to as "DBD",
+B<D>ataB<B>ase B<D>river, and some distributions ship them in separate
+packages. Drivers for the "dbi" library are developed by the B<libdbi-drivers>
+project at L<http://libdbi-drivers.sourceforge.net/>.
+
+You need to give the driver name as expected by the "dbi" library here. You
+should be able to find that in the documentation for each driver. If you
+mistype the driver name, the plugin will dump a list of all known driver names
+to the log.
+
+=item B<DriverOption> I<Key> I<Value>
+
+Sets driver-specific options. What option a driver supports can be found in the
+documentation for each driver, somewhere at
+L<http://libdbi-drivers.sourceforge.net/>. However, the options "host",
+"username", "password", and "dbname" seem to be deE<nbsp>facto standards.
+
+Unfortunately, drivers are not too keen to report errors when an unknown option
+is passed to them, so invalid settings here may go unnoticed. This is not the
+plugin's fault, it will report errors if it gets them from the libraryE<nbsp>/
+the driver. If a driver complains about an option, the plugin will dump a
+complete list of all options understood by that driver to the log.
+
+=item B<SelectDB> I<Database>
+
+In some cases, the database name you connect with is not the database name you
+want to use for querying data. If this option is set, the plugin will "select"
+(switch to) that database after the connection is established.
+
+=item B<Query> I<QueryName>
+
+Associates the query named I<QueryName> with this database connection. The
+query needs to be defined I<before> this statement, i.E<nbsp>e. all query
+blocks you want to refer to must be placed above the database block you want to
+refer to them from.
+
+=back
+
=head2 Plugin C<df>
=over 4
=back
+=head2 Plugin C<rrdcached>
+
+The C<rrdcached> plugin uses the RRDTool accelerator daemon, L<rrdcached(1)>,
+to store values to RRD files in an efficient manner. The combination of the
+C<rrdcached> B<plugin> and the C<rrdcached> B<daemon> is very similar to the
+way the C<rrdtool> plugin works (see below). The added abstraction layer
+provides a number of benefits, though: Because the cache is not within
+C<collectd> anymore, it does not need to be flushed when C<collectd> is to be
+restarted. This results in much shorter (if any) gaps in graphs, especially
+under heavy load. Also, the C<rrdtool> command line utility is aware of the
+daemon so that it can flush values to disk automatically when needed. This
+allows to integrate automated flushing of values into graphing solutions much
+more easily.
+
+There are disadvantages, though: The daemon may reside on a different host, so
+it may not be possible for C<collectd> to create the appropriate RRD files
+anymore. And even if C<rrdcached> runs on the same host, it may run in a
+different base directory, so relative paths may do weird stuff if you're not
+careful.
+
+So the B<recommended configuration> is to let C<collectd> and C<rrdcached> run
+on the same host, communicating via a UNIX domain socket. The B<DataDir>
+setting should be set to an absolute path, so that a changed base directory
+does not result in RRD files being createdE<nbsp>/ expected in the wrong place.
+
+=over 4
+
+=item B<DaemonAddress> I<Address>
+
+Address of the daemon as understood by the C<rrdc_connect> function of the RRD
+library. See L<rrdcached(1)> for details. Example:
+
+ <Plugin "rrdcached">
+ DaemonAddress "unix:/var/run/rrdcached.sock"
+ </Plugin>
+
+=item B<DataDir> I<Directory>
+
+Set the base directory in which the RRD files reside. If this is a relative
+path, it is relative to the working base directory of the C<rrdcached> daemon!
+Use of an absolute path is recommended.
+
+=item B<CreateFiles> B<true>|B<false>
+
+Enables or disables the creation of RRD files. If the daemon is not running
+locally, or B<DataDir> is set to a relative path, this will not work as
+expected. Default is B<true>.
+
+=back
+
=head2 Plugin C<rrdtool>
You can use the settings B<StepSize>, B<HeartBeat>, B<RRARows>, and B<XFF> to
--- /dev/null
+/**
+ * collectd - src/dbi.c
+ * Copyright (C) 2008 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
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <dbi/dbi.h>
+
+/*
+ * Data types
+ */
+struct cdbi_driver_option_s
+{
+ char *key;
+ char *value;
+};
+typedef struct cdbi_driver_option_s cdbi_driver_option_t;
+
+struct cdbi_query_s
+{
+ char *name;
+ char *statement;
+ char *type;
+ char **instances;
+ size_t instances_num;
+ char **values;
+ size_t values_num;
+};
+typedef struct cdbi_query_s cdbi_query_t;
+
+struct cdbi_database_s
+{
+ char *name;
+ char *select_db;
+
+ char *driver;
+ cdbi_driver_option_t *driver_options;
+ size_t driver_options_num;
+
+ cdbi_query_t **queries;
+ size_t queries_num;
+
+ dbi_conn connection;
+};
+typedef struct cdbi_database_s cdbi_database_t;
+
+/*
+ * Global variables
+ */
+static cdbi_query_t **queries = NULL;
+static size_t queries_num = 0;
+static cdbi_database_t **databases = NULL;
+static size_t databases_num = 0;
+
+/*
+ * Functions
+ */
+static const char *cdbi_strerror (dbi_conn conn, /* {{{ */
+ char *buffer, size_t buffer_size)
+{
+ const char *msg;
+ int status;
+
+ if (conn == NULL)
+ {
+ sstrncpy (buffer, "connection is NULL", buffer_size);
+ return (buffer);
+ }
+
+ msg = NULL;
+ status = dbi_conn_error (conn, &msg);
+ if ((status >= 0) && (msg != NULL))
+ ssnprintf (buffer, buffer_size, "%s (status %i)", msg, status);
+ else
+ ssnprintf (buffer, buffer_size, "dbi_conn_error failed with status %i",
+ status);
+
+ return (buffer);
+} /* }}} const char *cdbi_conn_error */
+
+static int cdbi_result_get_field (dbi_result res, /* {{{ */
+ const char *name, int dst_type, value_t *ret_value)
+{
+ value_t value;
+ unsigned int index;
+ unsigned short src_type;
+ dbi_conn connection;
+
+ index = dbi_result_get_field_idx (res, name);
+ if (index < 1)
+ {
+ ERROR ("dbi plugin: cdbi_result_get: No such column: %s.", name);
+ return (-1);
+ }
+
+ src_type = dbi_result_get_field_type_idx (res, index);
+ if (src_type == DBI_TYPE_ERROR)
+ {
+ ERROR ("dbi plugin: cdbi_result_get: "
+ "dbi_result_get_field_type_idx failed.");
+ return (-1);
+ }
+
+ if ((dst_type != DS_TYPE_COUNTER) && (dst_type != DS_TYPE_GAUGE))
+ {
+ ERROR ("dbi plugin: cdbi_result_get: Don't know how to handle "
+ "destination type %i.", dst_type);
+ return (-1);
+ }
+
+ if (src_type == DBI_TYPE_INTEGER)
+ {
+ if (dst_type == DS_TYPE_COUNTER)
+ value.counter = dbi_result_get_ulonglong_idx (res, index);
+ else
+ value.gauge = (gauge_t) dbi_result_get_longlong_idx (res, index);
+ }
+ else if (src_type == DBI_TYPE_DECIMAL)
+ {
+ value.gauge = dbi_result_get_double_idx (res, index);
+ if (dst_type == DS_TYPE_COUNTER)
+ value.counter = (counter_t) round (value.gauge);
+ }
+ else if (src_type == DBI_TYPE_STRING)
+ {
+ const char *string = dbi_result_get_string_idx (res, index);
+ char *endptr = NULL;
+
+ if (string == NULL)
+ value.gauge = NAN;
+ else if (dst_type == DS_TYPE_COUNTER)
+ value.counter = (counter_t) strtoll (string, &endptr, 0);
+ else
+ value.gauge = (gauge_t) strtod (string, &endptr);
+
+ if (string == endptr)
+ {
+ ERROR ("dbi plugin: cdbi_result_get: Can't parse string as number: %s.",
+ string);
+ return (-1);
+ }
+ }
+ else
+ {
+ ERROR ("dbi plugin: cdbi_result_get: Don't know how to handle "
+ "source type %hu.", src_type);
+ return (-1);
+ }
+
+ connection = dbi_result_get_conn (res);
+ if (dbi_conn_error_flag (connection) != 0)
+ {
+ char errbuf[1024];
+ ERROR ("dbi plugin: cdbi_result_get: dbi_result_get_*_idx failed: %s.",
+ cdbi_strerror (connection, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+
+ *ret_value = value;
+ return (0);
+} /* }}} int cdbi_result_get_field */
+
+static void cdbi_query_free (cdbi_query_t *q) /* {{{ */
+{
+ size_t i;
+
+ if (q == NULL)
+ return;
+
+ sfree (q->name);
+ sfree (q->statement);
+ sfree (q->type);
+
+ for (i = 0; i < q->instances_num; i++)
+ sfree (q->instances[i]);
+ sfree (q->instances);
+
+ for (i = 0; i < q->values_num; i++)
+ sfree (q->values[i]);
+ sfree (q->values);
+
+ sfree (q);
+} /* }}} void cdbi_query_free */
+
+static void cdbi_database_free (cdbi_database_t *db) /* {{{ */
+{
+ size_t i;
+
+ if (db == NULL)
+ return;
+
+ sfree (db->name);
+ sfree (db->driver);
+
+ for (i = 0; i < db->driver_options_num; i++)
+ {
+ sfree (db->driver_options[i].key);
+ sfree (db->driver_options[i].value);
+ }
+ sfree (db->driver_options);
+
+ sfree (db);
+} /* }}} void cdbi_database_free */
+
+static void cdbi_submit (cdbi_database_t *db, cdbi_query_t *q, /* {{{ */
+ char **instances, value_t *values)
+{
+ value_list_t vl = VALUE_LIST_INIT;
+
+ vl.values = values;
+ vl.values_len = (int) q->values_num;
+ vl.time = time (NULL);
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "dbi", sizeof (vl.plugin));
+ sstrncpy (vl.plugin_instance, db->name, sizeof (vl.type_instance));
+ sstrncpy (vl.type, q->type, sizeof (vl.type));
+ strjoin (vl.type_instance, sizeof (vl.type_instance),
+ instances, q->instances_num, "-");
+ vl.type_instance[sizeof (vl.type_instance) - 1] = 0;
+
+ plugin_dispatch_values (&vl);
+} /* }}} void cdbi_submit */
+
+/* Configuration handling functions {{{
+ *
+ * <Plugin dbi>
+ * <Query "plugin_instance0">
+ * Statement "SELECT name, value FROM table"
+ * Type "gauge"
+ * InstancesFrom "name"
+ * ValuesFrom "value"
+ * </Query>
+ *
+ * <Database "plugin_instance1">
+ * Driver "mysql"
+ * DriverOption "hostname" "localhost"
+ * ...
+ * Query "plugin_instance0"
+ * </Database>
+ * </Plugin>
+ */
+
+static int cdbi_config_set_string (char **ret_string, /* {{{ */
+ oconfig_item_t *ci)
+{
+ char *string;
+
+ if ((ci->values_num != 1)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("dbi plugin: The `%s' config option "
+ "needs exactly one string argument.", ci->key);
+ return (-1);
+ }
+
+ string = strdup (ci->values[0].value.string);
+ if (string == NULL)
+ {
+ ERROR ("dbi plugin: strdup failed.");
+ return (-1);
+ }
+
+ if (*ret_string != NULL)
+ free (*ret_string);
+ *ret_string = string;
+
+ return (0);
+} /* }}} int cdbi_config_set_string */
+
+static int cdbi_config_add_string (char ***ret_array, /* {{{ */
+ size_t *ret_array_len, oconfig_item_t *ci)
+{
+ char **array;
+ size_t array_len;
+ int i;
+
+ if (ci->values_num < 1)
+ {
+ WARNING ("dbi plugin: The `%s' config option "
+ "needs at least one argument.", ci->key);
+ return (-1);
+ }
+
+ for (i = 0; i < ci->values_num; i++)
+ {
+ if (ci->values[i].type != OCONFIG_TYPE_STRING)
+ {
+ WARNING ("dbi plugin: Argument %i to the `%s' option "
+ "is not a string.", i + 1, ci->key);
+ return (-1);
+ }
+ }
+
+ array_len = *ret_array_len;
+ array = (char **) realloc (*ret_array,
+ sizeof (char *) * (array_len + ci->values_num));
+ if (array == NULL)
+ {
+ ERROR ("dbi plugin: realloc failed.");
+ return (-1);
+ }
+ *ret_array = array;
+
+ for (i = 0; i < ci->values_num; i++)
+ {
+ array[array_len] = strdup (ci->values[i].value.string);
+ if (array[array_len] == NULL)
+ {
+ ERROR ("dbi plugin: strdup failed.");
+ *ret_array_len = array_len;
+ return (-1);
+ }
+ array_len++;
+ }
+
+ *ret_array_len = array_len;
+ return (0);
+} /* }}} int cdbi_config_add_string */
+
+static int cdbi_config_add_query (oconfig_item_t *ci) /* {{{ */
+{
+ cdbi_query_t *q;
+ int status;
+ int i;
+
+ if ((ci->values_num != 1)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("dbi plugin: The `Query' block "
+ "needs exactly one string argument.");
+ return (-1);
+ }
+
+ q = (cdbi_query_t *) malloc (sizeof (*q));
+ if (q == NULL)
+ {
+ ERROR ("dbi plugin: malloc failed.");
+ return (-1);
+ }
+ memset (q, 0, sizeof (*q));
+
+ status = cdbi_config_set_string (&q->name, ci);
+ if (status != 0)
+ {
+ sfree (q);
+ return (status);
+ }
+
+ /* Fill the `cdbi_query_t' structure.. */
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp ("Statement", child->key) == 0)
+ status = cdbi_config_set_string (&q->statement, child);
+ else if (strcasecmp ("Type", child->key) == 0)
+ status = cdbi_config_set_string (&q->type, child);
+ else if (strcasecmp ("InstancesFrom", child->key) == 0)
+ status = cdbi_config_add_string (&q->instances, &q->instances_num, child);
+ else if (strcasecmp ("ValuesFrom", child->key) == 0)
+ status = cdbi_config_add_string (&q->values, &q->values_num, child);
+ else
+ {
+ WARNING ("dbi plugin: Option `%s' not allowed here.", child->key);
+ status = -1;
+ }
+
+ if (status != 0)
+ break;
+ }
+
+ /* Check that all necessary options have been given. */
+ while (status == 0)
+ {
+ if (q->statement == NULL)
+ {
+ WARNING ("dbi plugin: `Statement' not given for query `%s'", q->name);
+ status = -1;
+ }
+ if (q->type == NULL)
+ {
+ WARNING ("dbi plugin: `Type' not given for query `%s'", q->name);
+ status = -1;
+ }
+ if (q->instances == NULL)
+ {
+ WARNING ("dbi plugin: `InstancesFrom' not given for query `%s'", q->name);
+ status = -1;
+ }
+ if (q->values == NULL)
+ {
+ WARNING ("dbi plugin: `ValuesFrom' not given for query `%s'", q->name);
+ status = -1;
+ }
+
+ break;
+ } /* while (status == 0) */
+
+ /* If all went well, add this query to the list of queries within the
+ * database structure. */
+ if (status == 0)
+ {
+ cdbi_query_t **temp;
+
+ temp = (cdbi_query_t **) realloc (queries,
+ sizeof (*queries) * (queries_num + 1));
+ if (temp == NULL)
+ {
+ ERROR ("dbi plugin: realloc failed");
+ status = -1;
+ }
+ else
+ {
+ queries = temp;
+ queries[queries_num] = q;
+ queries_num++;
+ }
+ }
+
+ if (status != 0)
+ {
+ cdbi_query_free (q);
+ return (-1);
+ }
+
+ return (0);
+} /* }}} int cdbi_config_add_query */
+
+static int cdbi_config_add_database_driver_option (cdbi_database_t *db, /* {{{ */
+ oconfig_item_t *ci)
+{
+ cdbi_driver_option_t *option;
+
+ if ((ci->values_num != 2)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING)
+ || (ci->values[1].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("dbi plugin: The `DriverOption' config option "
+ "needs exactly two string arguments.");
+ return (-1);
+ }
+
+ option = (cdbi_driver_option_t *) realloc (db->driver_options,
+ sizeof (*option) * (db->driver_options_num + 1));
+ if (option == NULL)
+ {
+ ERROR ("dbi plugin: realloc failed");
+ return (-1);
+ }
+
+ db->driver_options = option;
+ option = db->driver_options + db->driver_options_num;
+
+ option->key = strdup (ci->values[0].value.string);
+ if (option->key == NULL)
+ {
+ ERROR ("dbi plugin: strdup failed.");
+ return (-1);
+ }
+
+ option->value = strdup (ci->values[1].value.string);
+ if (option->value == NULL)
+ {
+ ERROR ("dbi plugin: strdup failed.");
+ sfree (option->key);
+ return (-1);
+ }
+
+ db->driver_options_num++;
+ return (0);
+} /* }}} int cdbi_config_add_database_driver_option */
+
+static int cdbi_config_add_database_query (cdbi_database_t *db, /* {{{ */
+ oconfig_item_t *ci)
+{
+ cdbi_query_t *q;
+ cdbi_query_t **temp;
+ size_t i;
+
+ if ((ci->values_num != 1)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("dbi plugin: The `Query' config option "
+ "needs exactly one string argument.");
+ return (-1);
+ }
+
+ q = NULL;
+ for (i = 0; i < queries_num; i++)
+ {
+ if (strcasecmp (queries[i]->name, ci->values[0].value.string) == 0)
+ {
+ q = queries[i];
+ break;
+ }
+ }
+
+ if (q == NULL)
+ {
+ WARNING ("dbi plugin: Database `%s': Unknown query `%s'. "
+ "Please make sure that the <Query \"%s\"> block comes before "
+ "the <Database \"%s\"> block.",
+ db->name, ci->values[0].value.string,
+ ci->values[0].value.string, db->name);
+ return (-1);
+ }
+
+ temp = (cdbi_query_t **) realloc (db->queries,
+ sizeof (*db->queries) * (db->queries_num + 1));
+ if (temp == NULL)
+ {
+ ERROR ("dbi plugin: realloc failed");
+ return (-1);
+ }
+ else
+ {
+ db->queries = temp;
+ db->queries[db->queries_num] = q;
+ db->queries_num++;
+ }
+
+ return (0);
+} /* }}} int cdbi_config_add_database_query */
+
+static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
+{
+ cdbi_database_t *db;
+ int status;
+ int i;
+
+ if ((ci->values_num != 1)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("dbi plugin: The `Database' block "
+ "needs exactly one string argument.");
+ return (-1);
+ }
+
+ db = (cdbi_database_t *) malloc (sizeof (*db));
+ if (db == NULL)
+ {
+ ERROR ("dbi plugin: malloc failed.");
+ return (-1);
+ }
+ memset (db, 0, sizeof (*db));
+
+ status = cdbi_config_set_string (&db->name, ci);
+ if (status != 0)
+ {
+ sfree (db);
+ return (status);
+ }
+
+ /* Fill the `cdbi_database_t' structure.. */
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp ("Driver", child->key) == 0)
+ status = cdbi_config_set_string (&db->driver, child);
+ else if (strcasecmp ("DriverOption", child->key) == 0)
+ status = cdbi_config_add_database_driver_option (db, child);
+ else if (strcasecmp ("SelectDB", child->key) == 0)
+ status = cdbi_config_set_string (&db->select_db, child);
+ else if (strcasecmp ("Query", child->key) == 0)
+ status = cdbi_config_add_database_query (db, child);
+ else
+ {
+ WARNING ("dbi plugin: Option `%s' not allowed here.", child->key);
+ status = -1;
+ }
+
+ if (status != 0)
+ break;
+ }
+
+ /* Check that all necessary options have been given. */
+ while (status == 0)
+ {
+ if (db->driver == NULL)
+ {
+ WARNING ("dbi plugin: `Driver' not given for database `%s'", db->name);
+ status = -1;
+ }
+ if (db->driver_options_num == 0)
+ {
+ WARNING ("dbi plugin: No `DriverOption' given for database `%s'. "
+ "This will likely not work.", db->name);
+ }
+
+ break;
+ } /* while (status == 0) */
+
+ /* If all went well, add this database to the global list of databases. */
+ if (status == 0)
+ {
+ cdbi_database_t **temp;
+
+ temp = (cdbi_database_t **) realloc (databases,
+ sizeof (*databases) * (databases_num + 1));
+ if (temp == NULL)
+ {
+ ERROR ("dbi plugin: realloc failed");
+ status = -1;
+ }
+ else
+ {
+ databases = temp;
+ databases[databases_num] = db;
+ databases_num++;
+ }
+ }
+
+ if (status != 0)
+ {
+ cdbi_database_free (db);
+ return (-1);
+ }
+
+ return (0);
+} /* }}} int cdbi_config_add_database */
+
+static int cdbi_config (oconfig_item_t *ci) /* {{{ */
+{
+ int i;
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+ if (strcasecmp ("Query", child->key) == 0)
+ cdbi_config_add_query (child);
+ else if (strcasecmp ("Database", child->key) == 0)
+ cdbi_config_add_database (child);
+ else
+ {
+ WARNING ("snmp plugin: Ignoring unknown config option `%s'.", child->key);
+ }
+ } /* for (ci->children) */
+
+ return (0);
+} /* }}} int cdbi_config */
+
+/* }}} End of configuration handling functions */
+
+static int cdbi_init (void) /* {{{ */
+{
+ static int did_init = 0;
+ int status;
+
+ if (did_init != 0)
+ return (0);
+
+ if (queries_num == 0)
+ {
+ ERROR ("dbi plugin: No <Query> blocks have been found. Without them, "
+ "this plugin can't do anything useful, so we will returns an error.");
+ return (-1);
+ }
+
+ if (databases_num == 0)
+ {
+ ERROR ("dbi plugin: No <Database> blocks have been found. Without them, "
+ "this plugin can't do anything useful, so we will returns an error.");
+ return (-1);
+ }
+
+ status = dbi_initialize (NULL);
+ if (status < 0)
+ {
+ ERROR ("dbi plugin: cdbi_init: dbi_initialize failed with status %i.",
+ status);
+ return (-1);
+ }
+ else if (status == 0)
+ {
+ ERROR ("dbi plugin: `dbi_initialize' could not load any drivers. Please "
+ "install at least one `DBD' or check your installation.");
+ return (-1);
+ }
+ DEBUG ("dbi plugin: cdbi_init: dbi_initialize reports %i driver%s.",
+ status, (status == 1) ? "" : "s");
+
+ return (0);
+} /* }}} int cdbi_init */
+
+static int cdbi_read_database_query (cdbi_database_t *db, /* {{{ */
+ cdbi_query_t *q)
+{
+ dbi_result res;
+ char **instances;
+ value_t *values;
+ const data_set_t *ds;
+ size_t i;
+ int status;
+
+ res = NULL;
+ instances = NULL;
+ values = NULL;
+
+ /* Macro that cleans up dynamically allocated memory and returns the
+ * specified status. */
+#define BAIL_OUT(status) \
+ if (res != NULL) { dbi_result_free (res); res = NULL; } \
+ if (instances != NULL) { sfree (instances[0]); sfree (instances); } \
+ sfree (values); \
+ return (status)
+
+ ds = plugin_get_ds (q->type);
+ if (ds == NULL)
+ {
+ ERROR ("dbi plugin: cdbi_read_database_query: Query `%s': Type `%s' is not "
+ "known by the daemon. See types.db(5) for details.",
+ q->name, q->type);
+ BAIL_OUT (-1);
+ }
+
+ if (((size_t) ds->ds_num) != q->values_num)
+ {
+ ERROR ("dbi plugin: cdbi_read_database_query: Query `%s': The type `%s' "
+ "requires exactly %i value%s, but the configuration specifies %zu.",
+ q->name, q->type,
+ ds->ds_num, (ds->ds_num == 1) ? "" : "s",
+ q->values_num);
+ BAIL_OUT (-1);
+ }
+
+ /* Allocate `instances' and `values' {{{ */
+ instances = (char **) malloc (sizeof (*instances) * q->instances_num);
+ if (instances == NULL)
+ {
+ ERROR ("dbi plugin: malloc failed.");
+ BAIL_OUT (-1);
+ }
+
+ instances[0] = (char *) malloc (q->instances_num * DATA_MAX_NAME_LEN);
+ if (instances[0] == NULL)
+ {
+ ERROR ("dbi plugin: malloc failed.");
+ BAIL_OUT (-1);
+ }
+ for (i = 1; i < q->instances_num; i++)
+ instances[i] = instances[i - 1] + DATA_MAX_NAME_LEN;
+
+ values = (value_t *) malloc (sizeof (*values) * q->values_num);
+ if (values == NULL)
+ {
+ ERROR ("dbi plugin: malloc failed.");
+ BAIL_OUT (-1);
+ }
+ /* }}} */
+
+ res = dbi_conn_query (db->connection, q->statement);
+ if (res == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
+ "dbi_conn_query failed: %s",
+ db->name, q->name,
+ cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
+ BAIL_OUT (-1);
+ }
+
+ status = dbi_result_first_row (res);
+ if (status != 1)
+ {
+ char errbuf[1024];
+ ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
+ "dbi_result_first_row failed: %s. Maybe the statement didn't "
+ "return any rows?",
+ db->name, q->name,
+ cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
+ BAIL_OUT (-1);
+ }
+
+ while (42)
+ {
+ /* Get instance names and values from the result: */
+ for (i = 0; i < q->instances_num; i++) /* {{{ */
+ {
+ const char *inst;
+
+ inst = dbi_result_get_string (res, q->instances[i]);
+ if (dbi_conn_error_flag (db->connection) != 0)
+ {
+ char errbuf[1024];
+ ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
+ "dbi_result_get_string (%s) failed: %s",
+ db->name, q->name, q->instances[i],
+ cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
+ BAIL_OUT (-1);
+ }
+
+ sstrncpy (instances[i], (inst == NULL) ? "" : inst, DATA_MAX_NAME_LEN);
+ DEBUG ("dbi plugin: cdbi_read_database_query (%s, %s): "
+ "instances[%zu] = %s;",
+ db->name, q->name, i, instances[i]);
+ } /* }}} for (i = 0; i < q->instances_num; i++) */
+
+ for (i = 0; i < q->values_num; i++) /* {{{ */
+ {
+ status = cdbi_result_get_field (res, q->values[i], ds->ds[i].type,
+ values + i);
+ if (status != 0)
+ {
+ BAIL_OUT (-1);
+ }
+
+ if (ds->ds[i].type == DS_TYPE_COUNTER)
+ {
+ DEBUG ("dbi plugin: cdbi_read_database_query (%s, %s): values[%zu] = %llu;",
+ db->name, q->name, i, values[i].counter);
+ }
+ else
+ {
+ DEBUG ("dbi plugin: cdbi_read_database_query (%s, %s): values[%zu] = %g;",
+ db->name, q->name, i, values[i].gauge);
+ }
+ } /* }}} for (i = 0; i < q->values_num; i++) */
+
+ /* Dispatch this row to the daemon. */
+ cdbi_submit (db, q, instances, values);
+
+ /* Get the next row from the database. */
+ status = dbi_result_next_row (res);
+ if (status != 1)
+ {
+ if (dbi_conn_error_flag (db->connection) != 0)
+ {
+ char errbuf[1024];
+ WARNING ("dbi plugin: cdbi_read_database_query (%s, %s): "
+ "dbi_result_next_row failed: %s.",
+ db->name, q->name,
+ cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
+ }
+ break;
+ }
+ } /* while (42) */
+
+ BAIL_OUT (0);
+#undef BAIL_OUT
+} /* }}} int cdbi_read_database_query */
+
+static int cdbi_connect_database (cdbi_database_t *db) /* {{{ */
+{
+ dbi_driver driver;
+ dbi_conn connection;
+ size_t i;
+ int status;
+
+ if (db->connection != NULL)
+ {
+ status = dbi_conn_ping (db->connection);
+ if (status != 0) /* connection is alive */
+ return (0);
+
+ dbi_conn_close (db->connection);
+ db->connection = NULL;
+ }
+
+ driver = dbi_driver_open (db->driver);
+ if (driver == NULL)
+ {
+ ERROR ("dbi plugin: cdbi_connect_database: dbi_driver_open (%s) failed.",
+ db->driver);
+ INFO ("dbi plugin: Maybe the driver isn't installed? "
+ "Known drivers are:");
+ for (driver = dbi_driver_list (NULL);
+ driver != NULL;
+ driver = dbi_driver_list (driver))
+ {
+ INFO ("dbi plugin: * %s", dbi_driver_get_name (driver));
+ }
+ return (-1);
+ }
+
+ connection = dbi_conn_open (driver);
+ if (connection == NULL)
+ {
+ ERROR ("dbi plugin: cdbi_connect_database: dbi_conn_open (%s) failed.",
+ db->driver);
+ return (-1);
+ }
+
+ /* Set all the driver options. Because this is a very very very generic
+ * interface, the error handling is kind of long. If an invalid option is
+ * encountered, it will get a list of options understood by the driver and
+ * report that as `INFO'. This way, users hopefully don't have too much
+ * trouble finding out how to configure the plugin correctly.. */
+ for (i = 0; i < db->driver_options_num; i++)
+ {
+ DEBUG ("dbi plugin: cdbi_connect_database (%s): "
+ "key = %s; value = %s;",
+ db->name,
+ db->driver_options[i].key,
+ db->driver_options[i].value);
+
+ status = dbi_conn_set_option (connection,
+ db->driver_options[i].key, db->driver_options[i].value);
+ if (status != 0)
+ {
+ char errbuf[1024];
+ const char *opt;
+
+ ERROR ("dbi plugin: cdbi_connect_database (%s): "
+ "dbi_conn_set_option (%s, %s) failed: %s.",
+ db->name,
+ db->driver_options[i].key, db->driver_options[i].value,
+ cdbi_strerror (connection, errbuf, sizeof (errbuf)));
+
+ INFO ("dbi plugin: This is a list of all options understood "
+ "by the `%s' driver:", db->driver);
+ for (opt = dbi_conn_get_option_list (connection, NULL);
+ opt != NULL;
+ opt = dbi_conn_get_option_list (connection, opt))
+ {
+ INFO ("dbi plugin: * %s", opt);
+ }
+
+ dbi_conn_close (connection);
+ return (-1);
+ }
+ } /* for (i = 0; i < db->driver_options_num; i++) */
+
+ status = dbi_conn_connect (connection);
+ if (status != 0)
+ {
+ char errbuf[1024];
+ ERROR ("dbi plugin: cdbi_connect_database (%s): "
+ "dbi_conn_connect failed: %s",
+ db->name, cdbi_strerror (connection, errbuf, sizeof (errbuf)));
+ dbi_conn_close (connection);
+ return (-1);
+ }
+
+ if (db->select_db != NULL)
+ {
+ status = dbi_conn_select_db (connection, db->select_db);
+ if (status != 0)
+ {
+ char errbuf[1024];
+ WARNING ("dbi plugin: cdbi_connect_database (%s): "
+ "dbi_conn_select_db (%s) failed: %s. Check the `SelectDB' option.",
+ db->name, db->select_db,
+ cdbi_strerror (connection, errbuf, sizeof (errbuf)));
+ dbi_conn_close (connection);
+ return (-1);
+ }
+ }
+
+ db->connection = connection;
+ return (0);
+} /* }}} int cdbi_connect_database */
+
+static int cdbi_read_database (cdbi_database_t *db) /* {{{ */
+{
+ size_t i;
+ int success;
+ int status;
+
+ status = cdbi_connect_database (db);
+ if (status != 0)
+ return (status);
+ assert (db->connection != NULL);
+
+ success = 0;
+ for (i = 0; i < db->queries_num; i++)
+ {
+ status = cdbi_read_database_query (db, db->queries[i]);
+ if (status == 0)
+ success++;
+ }
+
+ if (success == 0)
+ {
+ ERROR ("dbi plugin: All queries failed for database `%s'.", db->name);
+ return (-1);
+ }
+
+ return (0);
+} /* }}} int cdbi_read_database */
+
+static int cdbi_read (void) /* {{{ */
+{
+ size_t i;
+ int success = 0;
+ int status;
+
+ for (i = 0; i < databases_num; i++)
+ {
+ status = cdbi_read_database (databases[i]);
+ if (status == 0)
+ success++;
+ }
+
+ if (success == 0)
+ {
+ ERROR ("dbi plugin: No database could be read. Will return an error so "
+ "the plugin will be delayed.");
+ return (-1);
+ }
+
+ return (0);
+} /* }}} int cdbi_read */
+
+static int cdbi_shutdown (void) /* {{{ */
+{
+ size_t i;
+
+ for (i = 0; i < databases_num; i++)
+ {
+ if (databases[i]->connection != NULL)
+ {
+ dbi_conn_close (databases[i]->connection);
+ databases[i]->connection = NULL;
+ }
+ cdbi_database_free (databases[i]);
+ }
+ sfree (databases);
+ databases_num = 0;
+
+ for (i = 0; i < queries_num; i++)
+ cdbi_query_free (queries[i]);
+ sfree (queries);
+ queries_num = 0;
+
+ return (0);
+} /* }}} int cdbi_shutdown */
+
+void module_register (void) /* {{{ */
+{
+ plugin_register_complex_config ("dbi", cdbi_config);
+ plugin_register_init ("dbi", cdbi_init);
+ plugin_register_read ("dbi", cdbi_read);
+ plugin_register_shutdown ("dbi", cdbi_shutdown);
+} /* }}} void module_register */
+
+/*
+ * vim: shiftwidth=2 softtabstop=2 et fdm=marker
+ */
#include "common.h"
#include "plugin.h"
#include "configfile.h"
+#include "utils_ignorelist.h"
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
};
static int config_keys_num = 2;
-static char **if_list = NULL;
-static int if_list_num = 0;
-/*
- * if_list_action:
- * 0 => default is to collect selected interface
- * 1 => ignore selcted interfaces
- */
-static int if_list_action = 0;
+static ignorelist_t *ignorelist = NULL;
#ifdef HAVE_LIBKSTAT
#define MAX_NUMIF 256
static int interface_config (const char *key, const char *value)
{
- char **temp;
+ if (ignorelist == NULL)
+ ignorelist = ignorelist_create (/* invert = */ 1);
if (strcasecmp (key, "Interface") == 0)
{
- temp = (char **) realloc (if_list, (if_list_num + 1) * sizeof (char *));
- if (temp == NULL)
- {
- ERROR ("Cannot allocate more memory.");
- return (1);
- }
- if_list = temp;
-
- if ((if_list[if_list_num] = strdup (value)) == NULL)
- {
- ERROR ("Cannot allocate memory.");
- return (1);
- }
- if_list_num++;
+ ignorelist_add (ignorelist, value);
}
else if (strcasecmp (key, "IgnoreSelected") == 0)
{
+ int invert = 1;
if ((strcasecmp (value, "True") == 0)
|| (strcasecmp (value, "Yes") == 0)
|| (strcasecmp (value, "On") == 0))
- if_list_action = 1;
- else
- if_list_action = 0;
+ invert = 0;
+ ignorelist_set_invert (ignorelist, invert);
}
else
{
} /* int interface_init */
#endif /* HAVE_LIBKSTAT */
-/*
- * Check if this interface/instance should be ignored. This is called from
- * both, `submit' and `write' to give client and server the ability to
- * ignore certain stuff..
- */
-static int check_ignore_if (const char *interface)
-{
- int i;
-
- /* If no interfaces are given collect all interfaces. Mostly to be
- * backwards compatible, but also because this is much easier. */
- if (if_list_num < 1)
- return (0);
-
- for (i = 0; i < if_list_num; i++)
- if (strcasecmp (interface, if_list[i]) == 0)
- return (if_list_action);
- return (1 - if_list_action);
-} /* int check_ignore_if */
-
static void if_submit (const char *dev, const char *type,
unsigned long long rx,
unsigned long long tx)
value_t values[2];
value_list_t vl = VALUE_LIST_INIT;
- if (check_ignore_if (dev))
+ if (ignorelist_match (ignorelist, dev) != 0)
return;
values[0].counter = rx;
AUTOMAKE_OPTIONS = foreign no-dependencies
-EXTRA_DIST = libiptc.c
+EXTRA_DIST = libiptc.c README.collectd
if COMPILER_IS_GCC
AM_CFLAGS = -Wall -Werror
noinst_LTLIBRARIES = libiptc.la
-libiptc_la_CFLAGS = -DIPTABLES_VERSION=\"1.4.0\" -I$(KERNEL_DIR)/include
+libiptc_la_CFLAGS = -I$(KERNEL_DIR)/include
libiptc_la_SOURCES = libip4tc.c libip6tc.c \
ipt_kernel_headers.h libip6tc.h libiptc.h linux_list.h
--- /dev/null
+ libiptc (IPTables Chains) in collectd
+=======================================
+http://netfilter.org/
+http://collectd.org/
+
+About
+-----
+
+ This is libiptc taken from the iptables source distribution. As it is not
+ meant to be a public interface by upstream it is not shipped in some binary
+ distributions. Thus, collectd ships its own copy as a fall-back.
+
+ The presently available version was imported from iptables 1.4.1.1.
+
+Changes to the iptables upstream sources:
+-----------------------------------------
+
+ * Added copyright headers mentioning the "Netfilter Core Team" as copyright
+ holder.
+
+ * Changed "libiptc/*" includes to "*".
+
+ * Use the shipped copy of "xtables.h" instead of the one possibly available
+ on the system.
+
#include "libiptc.c"
#define BIT6(a, l) \
- ((ntohl(a->in6_u.u6_addr32[(l) / 32]) >> (31 - ((l) & 31))) & 1)
+ ((ntohl(a->s6_addr32[(l) / 32]) >> (31 - ((l) & 31))) & 1)
int
ipv6_prefix_length(const struct in6_addr *a)
int ip6tc_commit(ip6tc_handle_t *handle);
/* Get raw socket. */
-int ip6tc_get_raw_socket();
+int ip6tc_get_raw_socket(void);
/* Translates errno numbers into more human-readable form than strerror. */
const char *ip6tc_strerror(int err);
/* Return prefix length, or -1 if not contiguous */
int ipv6_prefix_length(const struct in6_addr *a);
+extern void dump_entries6(const ip6tc_handle_t);
+
#endif /* _LIBIP6TC_H */
*/
#include <sys/types.h>
#include <sys/socket.h>
+#include "xtables.h"
#include "linux_list.h"
#define DEBUGP_C(x, args...)
#endif
-#ifndef IPT_LIB_DIR
-#define IPT_LIB_DIR "/usr/local/lib/iptables"
+#ifdef DEBUG
+#define debug(x, args...) fprintf(stderr, x, ## args)
+#else
+#define debug(x, args...)
#endif
static int sockfd = -1;
struct chain_head *chain_iterator_cur;
struct rule_head *rule_iterator_cur;
+ unsigned int num_chains; /* number of user defined chains */
+
+ struct chain_head **chain_index; /* array for fast chain list access*/
+ unsigned int chain_index_sz;/* size of chain index array */
+
STRUCT_GETINFO info;
STRUCT_GET_ENTRIES *entries;
};
}
/* notify us that the ruleset has been modified by the user */
-static void
+static inline void
set_changed(TC_HANDLE_T h)
{
h->changed = 1;
/**********************************************************************
+ * Chain index (cache utility) functions
+ **********************************************************************
+ * The chain index is an array with pointers into the chain list, with
+ * CHAIN_INDEX_BUCKET_LEN spacing. This facilitates the ability to
+ * speedup chain list searching, by find a more optimal starting
+ * points when searching the linked list.
+ *
+ * The starting point can be found fast by using a binary search of
+ * the chain index. Thus, reducing the previous search complexity of
+ * O(n) to O(log(n/k) + k) where k is CHAIN_INDEX_BUCKET_LEN.
+ *
+ * A nice property of the chain index, is that the "bucket" list
+ * length is max CHAIN_INDEX_BUCKET_LEN (when just build, inserts will
+ * change this). Oppose to hashing, where the "bucket" list length can
+ * vary a lot.
+ */
+#ifndef CHAIN_INDEX_BUCKET_LEN
+#define CHAIN_INDEX_BUCKET_LEN 40
+#endif
+
+/* Another nice property of the chain index is that inserting/creating
+ * chains in chain list don't change the correctness of the chain
+ * index, it only causes longer lists in the buckets.
+ *
+ * To mitigate the performance penalty of longer bucket lists and the
+ * penalty of rebuilding, the chain index is rebuild only when
+ * CHAIN_INDEX_INSERT_MAX chains has been added.
+ */
+#ifndef CHAIN_INDEX_INSERT_MAX
+#define CHAIN_INDEX_INSERT_MAX 355
+#endif
+
+static inline unsigned int iptcc_is_builtin(struct chain_head *c);
+
+
+/* Use binary search in the chain index array, to find a chain_head
+ * pointer closest to the place of the searched name element.
+ *
+ * Notes that, binary search (obviously) requires that the chain list
+ * is sorted by name.
+ */
+static struct list_head *
+iptcc_bsearch_chain_index(const char *name, unsigned int *idx, TC_HANDLE_T handle)
+{
+ unsigned int pos, end;
+ int res;
+
+ struct list_head *list_pos;
+ list_pos=&handle->chains;
+
+ /* Check for empty array, e.g. no user defined chains */
+ if (handle->chain_index_sz == 0) {
+ debug("WARNING: handle->chain_index_sz == 0\n");
+ return list_pos;
+ }
+
+ /* Init */
+ end = handle->chain_index_sz;
+ pos = end / 2;
+
+ debug("bsearch Find chain:%s (pos:%d end:%d)\n", name, pos, end);
+
+ /* Loop */
+ loop:
+ if (!handle->chain_index[pos]) {
+ fprintf(stderr, "ERROR: NULL pointer chain_index[%d]\n", pos);
+ return &handle->chains; /* Be safe, return orig start pos */
+ }
+
+ res = strcmp(name, handle->chain_index[pos]->name);
+ list_pos = &handle->chain_index[pos]->list;
+ *idx = pos;
+
+ debug("bsearch Index[%d] name:%s res:%d ",
+ pos, handle->chain_index[pos]->name, res);
+
+ if (res == 0) { /* Found element, by direct hit */
+ debug("[found] Direct hit pos:%d end:%d\n", pos, end);
+ return list_pos;
+ } else if (res < 0) { /* Too far, jump back */
+ end = pos;
+ pos = pos / 2;
+
+ /* Exit case: First element of array */
+ if (end == 0) {
+ debug("[found] Reached first array elem (end%d)\n",end);
+ return list_pos;
+ }
+ debug("jump back to pos:%d (end:%d)\n", pos, end);
+ goto loop;
+ } else if (res > 0 ){ /* Not far enough, jump forward */
+
+ /* Exit case: Last element of array */
+ if (pos == handle->chain_index_sz-1) {
+ debug("[found] Last array elem (end:%d)\n", end);
+ return list_pos;
+ }
+
+ /* Exit case: Next index less, thus elem in this list section */
+ res = strcmp(name, handle->chain_index[pos+1]->name);
+ if (res < 0) {
+ debug("[found] closest list (end:%d)\n", end);
+ return list_pos;
+ }
+
+ pos = (pos+end)/2;
+ debug("jump forward to pos:%d (end:%d)\n", pos, end);
+ goto loop;
+ }
+
+ return list_pos;
+}
+
+#ifdef DEBUG
+/* Trivial linear search of chain index. Function used for verifying
+ the output of bsearch function */
+static struct list_head *
+iptcc_linearly_search_chain_index(const char *name, TC_HANDLE_T handle)
+{
+ unsigned int i=0;
+ int res=0;
+
+ struct list_head *list_pos;
+ list_pos = &handle->chains;
+
+ if (handle->chain_index_sz)
+ list_pos = &handle->chain_index[0]->list;
+
+ /* Linearly walk of chain index array */
+
+ for (i=0; i < handle->chain_index_sz; i++) {
+ if (handle->chain_index[i]) {
+ res = strcmp(handle->chain_index[i]->name, name);
+ if (res > 0)
+ break; // One step too far
+ list_pos = &handle->chain_index[i]->list;
+ if (res == 0)
+ break; // Direct hit
+ }
+ }
+
+ return list_pos;
+}
+#endif
+
+static int iptcc_chain_index_alloc(TC_HANDLE_T h)
+{
+ unsigned int list_length = CHAIN_INDEX_BUCKET_LEN;
+ unsigned int array_elems;
+ unsigned int array_mem;
+
+ /* Allocate memory for the chain index array */
+ array_elems = (h->num_chains / list_length) +
+ (h->num_chains % list_length ? 1 : 0);
+ array_mem = sizeof(h->chain_index) * array_elems;
+
+ debug("Alloc Chain index, elems:%d mem:%d bytes\n",
+ array_elems, array_mem);
+
+ h->chain_index = malloc(array_mem);
+ if (!h->chain_index) {
+ h->chain_index_sz = 0;
+ return -ENOMEM;
+ }
+ memset(h->chain_index, 0, array_mem);
+ h->chain_index_sz = array_elems;
+
+ return 1;
+}
+
+static void iptcc_chain_index_free(TC_HANDLE_T h)
+{
+ h->chain_index_sz = 0;
+ free(h->chain_index);
+}
+
+
+#ifdef DEBUG
+static void iptcc_chain_index_dump(TC_HANDLE_T h)
+{
+ unsigned int i = 0;
+
+ /* Dump: contents of chain index array */
+ for (i=0; i < h->chain_index_sz; i++) {
+ if (h->chain_index[i]) {
+ fprintf(stderr, "Chain index[%d].name: %s\n",
+ i, h->chain_index[i]->name);
+ }
+ }
+}
+#endif
+
+/* Build the chain index */
+static int iptcc_chain_index_build(TC_HANDLE_T h)
+{
+ unsigned int list_length = CHAIN_INDEX_BUCKET_LEN;
+ unsigned int chains = 0;
+ unsigned int cindex = 0;
+ struct chain_head *c;
+
+ /* Build up the chain index array here */
+ debug("Building chain index\n");
+
+ debug("Number of user defined chains:%d bucket_sz:%d array_sz:%d\n",
+ h->num_chains, list_length, h->chain_index_sz);
+
+ if (h->chain_index_sz == 0)
+ return 0;
+
+ list_for_each_entry(c, &h->chains, list) {
+
+ /* Issue: The index array needs to start after the
+ * builtin chains, as they are not sorted */
+ if (!iptcc_is_builtin(c)) {
+ cindex=chains / list_length;
+
+ /* Safe guard, break out on array limit, this
+ * is useful if chains are added and array is
+ * rebuild, without realloc of memory. */
+ if (cindex >= h->chain_index_sz)
+ break;
+
+ if ((chains % list_length)== 0) {
+ debug("\nIndex[%d] Chains:", cindex);
+ h->chain_index[cindex] = c;
+ }
+ chains++;
+ }
+ debug("%s, ", c->name);
+ }
+ debug("\n");
+
+ return 1;
+}
+
+static int iptcc_chain_index_rebuild(TC_HANDLE_T h)
+{
+ debug("REBUILD chain index array\n");
+ iptcc_chain_index_free(h);
+ if ((iptcc_chain_index_alloc(h)) < 0)
+ return -ENOMEM;
+ iptcc_chain_index_build(h);
+ return 1;
+}
+
+/* Delete chain (pointer) from index array. Removing an element from
+ * the chain list only affects the chain index array, if the chain
+ * index points-to/uses that list pointer.
+ *
+ * There are different strategies, the simple and safe is to rebuild
+ * the chain index every time. The more advanced is to update the
+ * array index to point to the next element, but that requires some
+ * house keeping and boundry checks. The advanced is implemented, as
+ * the simple approach behaves badly when all chains are deleted
+ * because list_for_each processing will always hit the first chain
+ * index, thus causing a rebuild for every chain.
+ */
+static int iptcc_chain_index_delete_chain(struct chain_head *c, TC_HANDLE_T h)
+{
+ struct list_head *index_ptr, *index_ptr2, *next;
+ struct chain_head *c2;
+ unsigned int idx, idx2;
+
+ index_ptr = iptcc_bsearch_chain_index(c->name, &idx, h);
+
+ debug("Del chain[%s] c->list:%p index_ptr:%p\n",
+ c->name, &c->list, index_ptr);
+
+ /* Save the next pointer */
+ next = c->list.next;
+ list_del(&c->list);
+
+ if (index_ptr == &c->list) { /* Chain used as index ptr */
+
+ /* See if its possible to avoid a rebuild, by shifting
+ * to next pointer. Its possible if the next pointer
+ * is located in the same index bucket.
+ */
+ c2 = list_entry(next, struct chain_head, list);
+ index_ptr2 = iptcc_bsearch_chain_index(c2->name, &idx2, h);
+ if (idx != idx2) {
+ /* Rebuild needed */
+ return iptcc_chain_index_rebuild(h);
+ } else {
+ /* Avoiding rebuild */
+ debug("Update cindex[%d] with next ptr name:[%s]\n",
+ idx, c2->name);
+ h->chain_index[idx]=c2;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+
+/**********************************************************************
* iptc cache utility functions (iptcc_*)
**********************************************************************/
/* Is the given chain builtin (1) or user-defined (0) */
-static unsigned int iptcc_is_builtin(struct chain_head *c)
+static inline unsigned int iptcc_is_builtin(struct chain_head *c)
{
return (c->hooknum ? 1 : 0);
}
return NULL;
}
+
/* Returns chain head if found, otherwise NULL. */
static struct chain_head *
iptcc_find_label(const char *name, TC_HANDLE_T handle)
{
struct list_head *pos;
+ struct list_head *list_start_pos;
+ unsigned int i=0;
+ int res;
if (list_empty(&handle->chains))
return NULL;
+ /* First look at builtin chains */
list_for_each(pos, &handle->chains) {
struct chain_head *c = list_entry(pos, struct chain_head, list);
+ if (!iptcc_is_builtin(c))
+ break;
if (!strcmp(c->name, name))
return c;
}
+ /* Find a smart place to start the search via chain index */
+ //list_start_pos = iptcc_linearly_search_chain_index(name, handle);
+ list_start_pos = iptcc_bsearch_chain_index(name, &i, handle);
+
+ /* Handel if bsearch bails out early */
+ if (list_start_pos == &handle->chains) {
+ list_start_pos = pos;
+ }
+#ifdef DEBUG
+ else {
+ /* Verify result of bsearch against linearly index search */
+ struct list_head *test_pos;
+ struct chain_head *test_c, *tmp_c;
+ test_pos = iptcc_linearly_search_chain_index(name, handle);
+ if (list_start_pos != test_pos) {
+ debug("BUG in chain_index search\n");
+ test_c=list_entry(test_pos, struct chain_head,list);
+ tmp_c =list_entry(list_start_pos,struct chain_head,list);
+ debug("Verify search found:\n");
+ debug(" Chain:%s\n", test_c->name);
+ debug("BSearch found:\n");
+ debug(" Chain:%s\n", tmp_c->name);
+ exit(42);
+ }
+ }
+#endif
+
+ /* Initial/special case, no user defined chains */
+ if (handle->num_chains == 0)
+ return NULL;
+
+ /* Start searching through the chain list */
+ list_for_each(pos, list_start_pos->prev) {
+ struct chain_head *c = list_entry(pos, struct chain_head, list);
+ res = strcmp(c->name, name);
+ debug("List search name:%s == %s res:%d\n", name, c->name, res);
+ if (res==0)
+ return c;
+
+ /* We can stop earlier as we know list is sorted */
+ if (res>0 && !iptcc_is_builtin(c)) { /* Walked too far*/
+ debug(" Not in list, walked too far, sorted list\n");
+ return NULL;
+ }
+
+ /* Stop on wrap around, if list head is reached */
+ if (pos == &handle->chains) {
+ debug("Stop, list head reached\n");
+ return NULL;
+ }
+ }
+
+ debug("List search NOT found name:%s\n", name);
return NULL;
}
static inline void iptc_insert_chain(TC_HANDLE_T h, struct chain_head *c)
{
struct chain_head *tmp;
+ struct list_head *list_start_pos;
+ unsigned int i=1;
+
+ /* Find a smart place to start the insert search */
+ list_start_pos = iptcc_bsearch_chain_index(c->name, &i, h);
+
+ /* Handle the case, where chain.name is smaller than index[0] */
+ if (i==0 && strcmp(c->name, h->chain_index[0]->name) <= 0) {
+ h->chain_index[0] = c; /* Update chain index head */
+ list_start_pos = h->chains.next;
+ debug("Update chain_index[0] with %s\n", c->name);
+ }
+
+ /* Handel if bsearch bails out early */
+ if (list_start_pos == &h->chains) {
+ list_start_pos = h->chains.next;
+ }
/* sort only user defined chains */
if (!c->hooknum) {
- list_for_each_entry(tmp, &h->chains, list) {
+ list_for_each_entry(tmp, list_start_pos->prev, list) {
if (!tmp->hooknum && strcmp(c->name, tmp->name) <= 0) {
list_add(&c->list, tmp->list.prev);
return;
}
+
+ /* Stop if list head is reached */
+ if (&tmp->list == &h->chains) {
+ debug("Insert, list head reached add to tail\n");
+ break;
+ }
}
}
errno = -ENOMEM;
return -1;
}
+ h->num_chains++; /* New user defined chain */
__iptcc_p_add_chain(h, c, offset, num);
ENTRY_ITERATE(h->entries->entrytable, h->entries->size,
cache_add_entry, h, &prev, &num);
+ /* Build the chain index, used for chain list search speedup */
+ if ((iptcc_chain_index_alloc(h)) < 0)
+ return -ENOMEM;
+ iptcc_chain_index_build(h);
+
/* Second pass: fixup parsed data from first pass */
list_for_each_entry(c, &h->chains, list) {
struct rule_head *r;
list_for_each_entry(r, &c->rules, list) {
- struct chain_head *c;
+ struct chain_head *lc;
STRUCT_STANDARD_TARGET *t;
if (r->type != IPTCC_R_JUMP)
continue;
t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry);
- c = iptcc_find_chain_by_offset(h, t->verdict);
- if (!c)
+ lc = iptcc_find_chain_by_offset(h, t->verdict);
+ if (!lc)
return -1;
- r->jump = c;
- c->references++;
+ r->jump = lc;
+ lc->references++;
}
}
return NULL;
}
sockfd_use++;
-
+retry:
s = sizeof(info);
strcpy(info.name, tablename);
return h;
error:
TC_FREE(&h);
+ /* A different process changed the ruleset size, retry */
+ if (errno == EAGAIN)
+ goto retry;
return NULL;
}
free(c);
}
+ iptcc_chain_index_free(*h);
+
free((*h)->entries);
free(*h);
CHECK(handle);
printf("libiptc v%s. %u bytes.\n",
- IPTABLES_VERSION, handle->entries->size);
+ XTABLES_VERSION, handle->entries->size);
printf("Table `%s'\n", handle->info.name);
printf("Hooks: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n",
handle->info.hook_entry[HOOK_PRE_ROUTING],
}
/* How many rules in this chain? */
-unsigned int
+static unsigned int
TC_NUM_RULES(const char *chain, TC_HANDLE_T *handle)
{
struct chain_head *c;
return c->num_rules;
}
-const STRUCT_ENTRY *TC_GET_RULE(const char *chain,
- unsigned int n,
- TC_HANDLE_T *handle)
+static const STRUCT_ENTRY *
+TC_GET_RULE(const char *chain, unsigned int n, TC_HANDLE_T *handle)
{
struct chain_head *c;
struct rule_head *r;
TC_CREATE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
{
static struct chain_head *c;
+ int capacity;
+ int exceeded;
iptc_fn = TC_CREATE_CHAIN;
return 0;
}
+ (*handle)->num_chains++; /* New user defined chain */
DEBUGP("Creating chain `%s'\n", chain);
iptc_insert_chain(*handle, c); /* Insert sorted */
+ /* Inserting chains don't change the correctness of the chain
+ * index (except if its smaller than index[0], but that
+ * handled by iptc_insert_chain). It only causes longer lists
+ * in the buckets. Thus, only rebuild chain index when the
+ * capacity is exceed with CHAIN_INDEX_INSERT_MAX chains.
+ */
+ capacity = (*handle)->chain_index_sz * CHAIN_INDEX_BUCKET_LEN;
+ exceeded = ((((*handle)->num_chains)-capacity));
+ if (exceeded > CHAIN_INDEX_INSERT_MAX) {
+ debug("Capacity(%d) exceeded(%d) rebuild (chains:%d)\n",
+ capacity, exceeded, (*handle)->num_chains);
+ iptcc_chain_index_rebuild(*handle);
+ }
+
set_changed(*handle);
return 1;
}
/* If we are about to delete the chain that is the current
- * iterator, move chain iterator firward. */
+ * iterator, move chain iterator forward. */
if (c == (*handle)->chain_iterator_cur)
iptcc_chain_iterator_advance(*handle);
- list_del(&c->list);
+ (*handle)->num_chains--; /* One user defined chain deleted */
+
+ //list_del(&c->list); /* Done in iptcc_chain_index_delete_chain() */
+ iptcc_chain_index_delete_chain(c, *handle);
free(c);
DEBUGP("chain `%s' deleted\n", chain);
}
-static void counters_nomap(STRUCT_COUNTERS_INFO *newcounters,
- unsigned int index)
+static void counters_nomap(STRUCT_COUNTERS_INFO *newcounters, unsigned int idx)
{
- newcounters->counters[index] = ((STRUCT_COUNTERS) { 0, 0});
+ newcounters->counters[idx] = ((STRUCT_COUNTERS) { 0, 0});
DEBUGP_C("NOMAP => zero\n");
}
static void counters_normal_map(STRUCT_COUNTERS_INFO *newcounters,
- STRUCT_REPLACE *repl,
- unsigned int index,
+ STRUCT_REPLACE *repl, unsigned int idx,
unsigned int mappos)
{
/* Original read: X.
* => Add in X + Y
* => Add in replacement read.
*/
- newcounters->counters[index] = repl->counters[mappos];
+ newcounters->counters[idx] = repl->counters[mappos];
DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos);
}
static void counters_map_zeroed(STRUCT_COUNTERS_INFO *newcounters,
- STRUCT_REPLACE *repl,
- unsigned int index,
- unsigned int mappos,
- STRUCT_COUNTERS *counters)
+ STRUCT_REPLACE *repl, unsigned int idx,
+ unsigned int mappos, STRUCT_COUNTERS *counters)
{
/* Original read: X.
* Atomic read on replacement: X + Y.
* => Add in Y.
* => Add in (replacement read - original read).
*/
- subtract_counters(&newcounters->counters[index],
+ subtract_counters(&newcounters->counters[idx],
&repl->counters[mappos],
counters);
DEBUGP_C("ZEROED => mappos %u\n", mappos);
}
static void counters_map_set(STRUCT_COUNTERS_INFO *newcounters,
- unsigned int index,
- STRUCT_COUNTERS *counters)
+ unsigned int idx, STRUCT_COUNTERS *counters)
{
/* Want to set counter (iptables-restore) */
- memcpy(&newcounters->counters[index], counters,
+ memcpy(&newcounters->counters[idx], counters,
sizeof(STRUCT_COUNTERS));
DEBUGP_C("SET\n");
int iptc_commit(iptc_handle_t *handle);
/* Get raw socket. */
-int iptc_get_raw_socket();
+int iptc_get_raw_socket(void);
/* Translates errno numbers into more human-readable form than strerror. */
const char *iptc_strerror(int err);
+extern void dump_entries(const iptc_handle_t);
+
#ifdef __cplusplus
}
#endif
--- /dev/null
+/**
+ * This file was imported from the iptables sources.
+ * Copyright (C) 1999-2008 Netfilter Core Team
+ *
+ * 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
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _LIBXTC_H
+#define _LIBXTC_H
+/* Library which manipulates filtering rules. */
+
+#include "ipt_kernel_headers.h"
+#include <linux/netfilter/x_tables.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef XT_MIN_ALIGN
+/* xt_entry has pointers and u_int64_t's in it, so if you align to
+ it, you'll also align to any crazy matches and targets someone
+ might write */
+#define XT_MIN_ALIGN (__alignof__(struct xt_entry))
+#endif
+
+#ifndef XT_ALIGN
+#define XT_ALIGN(s) (((s) + ((XT_MIN_ALIGN)-1)) & ~((XT_MIN_ALIGN)-1))
+#endif
+
+typedef char xt_chainlabel[32];
+
+#define XTC_LABEL_ACCEPT "ACCEPT"
+#define XTC_LABEL_DROP "DROP"
+#define XTC_LABEL_QUEUE "QUEUE"
+#define XTC_LABEL_RETURN "RETURN"
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBXTC_H */
--- /dev/null
+/**
+ * This file was imported from the iptables sources.
+ * Copyright (C) 1999-2008 Netfilter Core Team
+ *
+ * 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
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _XTABLES_H
+#define _XTABLES_H
+
+#include <sys/types.h>
+#include <linux/types.h>
+#include <linux/netfilter/x_tables.h>
+#include "libxtc.h"
+#include <stdbool.h>
+
+#ifndef IPPROTO_SCTP
+#define IPPROTO_SCTP 132
+#endif
+#ifndef IPPROTO_DCCP
+#define IPPROTO_DCCP 33
+#endif
+#ifndef IPPROTO_UDPLITE
+#define IPPROTO_UDPLITE 136
+#endif
+
+#define XTABLES_VERSION "1.4.1.1"
+#define XTABLES_VERSION_CODE (0x10000 * 1 + 0x100 * 4 + 1)
+
+#define XTABLES_API_VERSION(x,y,z) (0x10000*(x) + 0x100*(y) + z)
+
+/* Include file for additions: new matches and targets. */
+struct xtables_match
+{
+ struct xtables_match *next;
+
+ xt_chainlabel name;
+
+ /* Revision of match (0 by default). */
+ u_int8_t revision;
+
+ u_int16_t family;
+
+ const char *version;
+
+ /* Size of match data. */
+ size_t size;
+
+ /* Size of match data relevent for userspace comparison purposes */
+ size_t userspacesize;
+
+ /* Function which prints out usage message. */
+ void (*help)(void);
+
+ /* Initialize the match. */
+ void (*init)(struct xt_entry_match *m);
+
+ /* Function which parses command options; returns true if it
+ ate an option */
+ /* entry is struct ipt_entry for example */
+ int (*parse)(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry,
+ struct xt_entry_match **match);
+
+ /* Final check; exit if not ok. */
+ void (*final_check)(unsigned int flags);
+
+ /* Prints out the match iff non-NULL: put space at end */
+ /* ip is struct ipt_ip * for example */
+ void (*print)(const void *ip,
+ const struct xt_entry_match *match, int numeric);
+
+ /* Saves the match info in parsable form to stdout. */
+ /* ip is struct ipt_ip * for example */
+ void (*save)(const void *ip, const struct xt_entry_match *match);
+
+ /* Pointer to list of extra command-line options */
+ const struct option *extra_opts;
+
+ /* Ignore these men behind the curtain: */
+ unsigned int option_offset;
+ struct xt_entry_match *m;
+ unsigned int mflags;
+#ifdef NO_SHARED_LIBS
+ unsigned int loaded; /* simulate loading so options are merged properly */
+#endif
+};
+
+struct xtables_target
+{
+ struct xtables_target *next;
+
+ xt_chainlabel name;
+
+ /* Revision of target (0 by default). */
+ u_int8_t revision;
+
+ u_int16_t family;
+
+ const char *version;
+
+ /* Size of target data. */
+ size_t size;
+
+ /* Size of target data relevent for userspace comparison purposes */
+ size_t userspacesize;
+
+ /* Function which prints out usage message. */
+ void (*help)(void);
+
+ /* Initialize the target. */
+ void (*init)(struct xt_entry_target *t);
+
+ /* Function which parses command options; returns true if it
+ ate an option */
+ /* entry is struct ipt_entry for example */
+ int (*parse)(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry,
+ struct xt_entry_target **targetinfo);
+
+ /* Final check; exit if not ok. */
+ void (*final_check)(unsigned int flags);
+
+ /* Prints out the target iff non-NULL: put space at end */
+ void (*print)(const void *ip,
+ const struct xt_entry_target *target, int numeric);
+
+ /* Saves the targinfo in parsable form to stdout. */
+ void (*save)(const void *ip,
+ const struct xt_entry_target *target);
+
+ /* Pointer to list of extra command-line options */
+ const struct option *extra_opts;
+
+ /* Ignore these men behind the curtain: */
+ unsigned int option_offset;
+ struct xt_entry_target *t;
+ unsigned int tflags;
+ unsigned int used;
+#ifdef NO_SHARED_LIBS
+ unsigned int loaded; /* simulate loading so options are merged properly */
+#endif
+};
+
+/* Your shared library should call one of these. */
+extern void xtables_register_match(struct xtables_match *me);
+extern void xtables_register_target(struct xtables_target *me);
+
+extern int string_to_number_ll(const char *s,
+ unsigned long long min,
+ unsigned long long max,
+ unsigned long long *ret);
+extern int string_to_number_l(const char *s,
+ unsigned long min,
+ unsigned long max,
+ unsigned long *ret);
+extern int string_to_number(const char *s,
+ unsigned int min,
+ unsigned int max,
+ unsigned int *ret);
+extern bool strtonuml(const char *, char **, unsigned long *,
+ unsigned long, unsigned long);
+extern bool strtonum(const char *, char **, unsigned int *,
+ unsigned int, unsigned int);
+extern int service_to_port(const char *name, const char *proto);
+extern u_int16_t parse_port(const char *port, const char *proto);
+extern void
+parse_interface(const char *arg, char *vianame, unsigned char *mask);
+
+enum exittype {
+ OTHER_PROBLEM = 1,
+ PARAMETER_PROBLEM,
+ VERSION_PROBLEM,
+ RESOURCE_PROBLEM,
+ P_ONLY_ONCE,
+ P_NO_INVERT,
+ P_BAD_VALUE,
+ P_ONE_ACTION,
+};
+
+/* this is a special 64bit data type that is 8-byte aligned */
+#define aligned_u64 u_int64_t __attribute__((aligned(8)))
+
+int check_inverse(const char option[], int *invert, int *my_optind, int argc);
+void exit_error(enum exittype, const char *, ...)__attribute__((noreturn,
+ format(printf,2,3)));
+extern void param_act(unsigned int, const char *, ...);
+extern const char *program_name, *program_version;
+
+extern const char *ipaddr_to_numeric(const struct in_addr *);
+extern const char *ipaddr_to_anyname(const struct in_addr *);
+extern const char *ipmask_to_numeric(const struct in_addr *);
+extern struct in_addr *numeric_to_ipaddr(const char *);
+extern struct in_addr *numeric_to_ipmask(const char *);
+extern void ipparse_hostnetworkmask(const char *, struct in_addr **,
+ struct in_addr *, unsigned int *);
+
+extern struct in6_addr *numeric_to_ip6addr(const char *);
+extern const char *ip6addr_to_numeric(const struct in6_addr *);
+extern const char *ip6addr_to_anyname(const struct in6_addr *);
+extern const char *ip6mask_to_numeric(const struct in6_addr *);
+extern void ip6parse_hostnetworkmask(const char *, struct in6_addr **,
+ struct in6_addr *, unsigned int *);
+
+/**
+ * Print the specified value to standard output, quoting dangerous
+ * characters if required.
+ */
+extern void save_string(const char *value);
+
+#ifdef NO_SHARED_LIBS
+# ifdef _INIT
+# undef _init
+# define _init _INIT
+# endif
+ extern void init_extensions(void);
+#else
+# define _init __attribute__((constructor)) _INIT
+#endif
+
+/* Present in both iptables.c and ip6tables.c */
+extern u_int16_t parse_protocol(const char *s);
+
+#ifdef XTABLES_INTERNAL
+# include <xtables/internal.h>
+#endif
+
+#endif /* _XTABLES_H */
else if (0 == strcasecmp (c->key, "Plugin"))
current_status = perl_config_plugin (aTHX_ c);
else
+ {
log_warn ("Ignoring unknown config key \"%s\".", c->key);
+ current_status = 0;
+ }
/* fatal error - it's up to perl_config_* to clean up */
if (0 > current_status) {
int plugin_dispatch_values (value_list_t *vl)
{
- static c_complain_t no_write_complaint = C_COMPLAIN_INIT;
+ static c_complain_t no_write_complaint = C_COMPLAIN_INIT_STATIC;
int (*callback) (const data_set_t *, const value_list_t *);
data_set_t *ds;
db->conn = NULL;
- db->conn_complaint.last = 0;
- db->conn_complaint.interval = 0;
+ C_COMPLAIN_INIT (&db->conn_complaint);
db->proto_version = 0;
--- /dev/null
+/**
+ * collectd - src/rrdcached.c
+ * Copyright (C) 2008 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
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "utils_rrdcreate.h"
+
+#include <rrd_client.h>
+
+/*
+ * Private variables
+ */
+static const char *config_keys[] =
+{
+ "DaemonAddress",
+ "DataDir",
+ "CreateFiles",
+ "CollectStatistics"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static char *datadir = NULL;
+static char *daemon_address = NULL;
+static int config_create_files = 1;
+static int config_collect_stats = 1;
+static rrdcreate_config_t rrdcreate_config =
+{
+ /* stepsize = */ 0,
+ /* heartbeat = */ 0,
+ /* rrarows = */ 1200,
+ /* xff = */ 0.1,
+
+ /* timespans = */ NULL,
+ /* timespans_num = */ 0,
+
+ /* consolidation_functions = */ NULL,
+ /* consolidation_functions_num = */ 0
+};
+
+static int value_list_to_string (char *buffer, int buffer_len,
+ const data_set_t *ds, const value_list_t *vl)
+{
+ int offset;
+ int status;
+ int i;
+
+ assert (0 == strcmp (ds->type, vl->type));
+
+ memset (buffer, '\0', buffer_len);
+
+ status = ssnprintf (buffer, buffer_len, "%u", (unsigned int) vl->time);
+ if ((status < 1) || (status >= buffer_len))
+ return (-1);
+ offset = status;
+
+ for (i = 0; i < ds->ds_num; i++)
+ {
+ if ((ds->ds[i].type != DS_TYPE_COUNTER)
+ && (ds->ds[i].type != DS_TYPE_GAUGE))
+ return (-1);
+
+ if (ds->ds[i].type == DS_TYPE_COUNTER)
+ {
+ status = ssnprintf (buffer + offset, buffer_len - offset,
+ ":%llu", vl->values[i].counter);
+ }
+ else /* if (ds->ds[i].type == DS_TYPE_GAUGE) */
+ {
+ status = ssnprintf (buffer + offset, buffer_len - offset,
+ ":%lf", vl->values[i].gauge);
+ }
+
+ if ((status < 1) || (status >= (buffer_len - offset)))
+ return (-1);
+
+ offset += status;
+ } /* for ds->ds_num */
+
+ return (0);
+} /* int value_list_to_string */
+
+static int value_list_to_filename (char *buffer, int buffer_len,
+ const data_set_t *ds, const value_list_t *vl)
+{
+ int offset = 0;
+ int status;
+
+ assert (0 == strcmp (ds->type, vl->type));
+
+ if (datadir != NULL)
+ {
+ status = ssnprintf (buffer + offset, buffer_len - offset,
+ "%s/", datadir);
+ if ((status < 1) || (status >= buffer_len - offset))
+ return (-1);
+ offset += status;
+ }
+
+ status = ssnprintf (buffer + offset, buffer_len - offset,
+ "%s/", vl->host);
+ if ((status < 1) || (status >= buffer_len - offset))
+ return (-1);
+ offset += status;
+
+ if (strlen (vl->plugin_instance) > 0)
+ status = ssnprintf (buffer + offset, buffer_len - offset,
+ "%s-%s/", vl->plugin, vl->plugin_instance);
+ else
+ status = ssnprintf (buffer + offset, buffer_len - offset,
+ "%s/", vl->plugin);
+ if ((status < 1) || (status >= buffer_len - offset))
+ return (-1);
+ offset += status;
+
+ if (strlen (vl->type_instance) > 0)
+ status = ssnprintf (buffer + offset, buffer_len - offset,
+ "%s-%s", vl->type, vl->type_instance);
+ else
+ status = ssnprintf (buffer + offset, buffer_len - offset,
+ "%s", vl->type);
+ if ((status < 1) || (status >= buffer_len - offset))
+ return (-1);
+ offset += status;
+
+ strncpy (buffer + offset, ".rrd", buffer_len - offset);
+ buffer[buffer_len - 1] = 0;
+
+ return (0);
+} /* int value_list_to_filename */
+
+static int rc_config (const char *key, const char *value)
+{
+ if (strcasecmp ("DataDir", key) == 0)
+ {
+ if (datadir != NULL)
+ free (datadir);
+ datadir = strdup (value);
+ if (datadir != NULL)
+ {
+ int len = strlen (datadir);
+ while ((len > 0) && (datadir[len - 1] == '/'))
+ {
+ len--;
+ datadir[len] = '\0';
+ }
+ if (len <= 0)
+ {
+ free (datadir);
+ datadir = NULL;
+ }
+ }
+ }
+ else if (strcasecmp ("DaemonAddress", key) == 0)
+ {
+ sfree (daemon_address);
+ daemon_address = strdup (value);
+ if (daemon_address == NULL)
+ {
+ ERROR ("rrdcached plugin: strdup failed.");
+ return (1);
+ }
+ }
+ else if (strcasecmp ("CreateFiles", key) == 0)
+ {
+ if ((strcasecmp ("false", value) == 0)
+ || (strcasecmp ("no", value) == 0)
+ || (strcasecmp ("off", value) == 0))
+ config_create_files = 0;
+ else
+ config_create_files = 1;
+ }
+ else if (strcasecmp ("CollectStatistics", key) == 0)
+ {
+ if ((strcasecmp ("false", value) == 0)
+ || (strcasecmp ("no", value) == 0)
+ || (strcasecmp ("off", value) == 0))
+ config_collect_stats = 0;
+ else
+ config_collect_stats = 1;
+ }
+ else
+ {
+ return (-1);
+ }
+ return (0);
+} /* int rc_config */
+
+static int rc_read (void)
+{
+ int status;
+ rrdc_stats_t *head;
+ rrdc_stats_t *ptr;
+
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ if (daemon_address == NULL)
+ return (-1);
+
+ if (config_collect_stats == 0)
+ return (-1);
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+
+ if ((strncmp ("unix:", daemon_address, strlen ("unix:")) == 0)
+ || (daemon_address[0] == '/'))
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ else
+ sstrncpy (vl.host, daemon_address, sizeof (vl.host));
+ sstrncpy (vl.plugin, "rrdcached", sizeof (vl.plugin));
+
+ head = NULL;
+ status = rrdc_stats_get (&head);
+ if (status != 0)
+ {
+ ERROR ("rrdcached plugin: rrdc_stats_get failed with status %i.", status);
+ return (-1);
+ }
+
+ for (ptr = head; ptr != NULL; ptr = ptr->next)
+ {
+ if (ptr->type == RRDC_STATS_TYPE_GAUGE)
+ values[0].gauge = (gauge_t) ptr->value.gauge;
+ else if (ptr->type == RRDC_STATS_TYPE_COUNTER)
+ values[0].counter = (counter_t) ptr->value.counter;
+ else
+ continue;
+
+ if (strcasecmp ("QueueLength", ptr->name) == 0)
+ {
+ sstrncpy (vl.type, "queue_length", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
+ }
+ else if (strcasecmp ("UpdatesWritten", ptr->name) == 0)
+ {
+ sstrncpy (vl.type, "operations", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "write-updates", sizeof (vl.type_instance));
+ }
+ else if (strcasecmp ("DataSetsWritten", ptr->name) == 0)
+ {
+ sstrncpy (vl.type, "operations", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "write-data_sets",
+ sizeof (vl.type_instance));
+ }
+ else if (strcasecmp ("TreeNodesNumber", ptr->name) == 0)
+ {
+ sstrncpy (vl.type, "gauge", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "tree_nodes", sizeof (vl.type_instance));
+ }
+ else if (strcasecmp ("TreeDepth", ptr->name) == 0)
+ {
+ sstrncpy (vl.type, "gauge", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "tree_depth", sizeof (vl.type_instance));
+ }
+ else if (strcasecmp ("FlushesReceived", ptr->name) == 0)
+ {
+ sstrncpy (vl.type, "operations", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "receive-flush", sizeof (vl.type_instance));
+ }
+ else if (strcasecmp ("JournalBytes", ptr->name) == 0)
+ {
+ sstrncpy (vl.type, "counter", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "journal-bytes", sizeof (vl.type_instance));
+ }
+ else if (strcasecmp ("JournalRotate", ptr->name) == 0)
+ {
+ sstrncpy (vl.type, "counter", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "journal-rotates", sizeof (vl.type_instance));
+ }
+ else if (strcasecmp ("UpdatesReceived", ptr->name) == 0)
+ {
+ sstrncpy (vl.type, "operations", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "receive-update", sizeof (vl.type_instance));
+ }
+ else
+ {
+ DEBUG ("rrdcached plugin: rc_read: Unknown statistic `%s'.", ptr->name);
+ continue;
+ }
+
+ plugin_dispatch_values (&vl);
+ } /* for (ptr = head; ptr != NULL; ptr = ptr->next) */
+
+ rrdc_stats_free (head);
+
+ return (0);
+} /* int rc_read */
+
+static int rc_init (void)
+{
+ if (config_collect_stats != 0)
+ plugin_register_read ("rrdcached", rc_read);
+
+ return (0);
+} /* int rc_init */
+
+static int rc_write (const data_set_t *ds, const value_list_t *vl)
+{
+ char filename[512];
+ char values[512];
+ char *values_array[2];
+ int status;
+
+ if (daemon_address == NULL)
+ {
+ ERROR ("rrdcached plugin: daemon_address == NULL.");
+ plugin_unregister_write ("rrdcached");
+ return (-1);
+ }
+
+ if (strcmp (ds->type, vl->type) != 0)
+ {
+ ERROR ("rrdcached plugin: DS type does not match value list type");
+ return (-1);
+ }
+
+ if (value_list_to_filename (filename, sizeof (filename), ds, vl) != 0)
+ {
+ ERROR ("rrdcached plugin: value_list_to_filename failed.");
+ return (-1);
+ }
+
+ if (value_list_to_string (values, sizeof (values), ds, vl) != 0)
+ {
+ ERROR ("rrdcached plugin: value_list_to_string failed.");
+ return (-1);
+ }
+
+ values_array[0] = values;
+ values_array[1] = NULL;
+
+ if (config_create_files != 0)
+ {
+ struct stat statbuf;
+
+ status = stat (filename, &statbuf);
+ if (status != 0)
+ {
+ if (errno != ENOENT)
+ {
+ char errbuf[1024];
+ ERROR ("rrdcached plugin: stat (%s) failed: %s",
+ filename, sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+
+ status = cu_rrd_create_file (filename, ds, vl, &rrdcreate_config);
+ if (status != 0)
+ {
+ ERROR ("rrdcached plugin: cu_rrd_create_file (%s) failed.",
+ filename);
+ return (-1);
+ }
+ }
+ }
+
+ status = rrdc_connect (daemon_address);
+ if (status != 0)
+ {
+ ERROR ("rrdcached plugin: rrdc_connect (%s) failed with status %i.",
+ daemon_address, status);
+ return (-1);
+ }
+
+ status = rrdc_update (filename, /* values_num = */ 1, (void *) values_array);
+ if (status != 0)
+ {
+ ERROR ("rrdcached plugin: rrdc_update (%s, [%s], 1) failed with "
+ "status %i.",
+ filename, values_array[0], status);
+ return (-1);
+ }
+
+ return (0);
+} /* int rc_write */
+
+static int rc_shutdown (void)
+{
+ rrdc_disconnect ();
+ return (0);
+} /* int rc_shutdown */
+
+void module_register (void)
+{
+ plugin_register_config ("rrdcached", rc_config,
+ config_keys, config_keys_num);
+ plugin_register_init ("rrdcached", rc_init);
+ plugin_register_write ("rrdcached", rc_write);
+ plugin_register_shutdown ("rrdcached", rc_shutdown);
+} /* void module_register */
+
+/*
+ * vim: set sw=2 sts=2 et :
+ */
#include "plugin.h"
#include "common.h"
#include "utils_avltree.h"
+#include "utils_rrdcreate.h"
#include <rrd.h>
/*
* Private variables
*/
-static int rra_timespans[] =
-{
- 3600,
- 86400,
- 604800,
- 2678400,
- 31622400
-};
-static int rra_timespans_num = STATIC_ARRAY_SIZE (rra_timespans);
-
-static int *rra_timespans_custom = NULL;
-static int rra_timespans_custom_num = 0;
-
-static char *rra_types[] =
-{
- "AVERAGE",
- "MIN",
- "MAX"
-};
-static int rra_types_num = STATIC_ARRAY_SIZE (rra_types);
-
static const char *config_keys[] =
{
"CacheTimeout",
/* If datadir is zero, the daemon's basedir is used. If stepsize or heartbeat
* is zero a default, depending on the `interval' member of the value list is
* being used. */
-static char *datadir = NULL;
-static int stepsize = 0;
-static int heartbeat = 0;
-static int rrarows = 1200;
-static double xff = 0.1;
-static double write_rate = 0.0;
+static char *datadir = NULL;
+static double write_rate = 0.0;
+static rrdcreate_config_t rrdcreate_config =
+{
+ /* stepsize = */ 0,
+ /* heartbeat = */ 0,
+ /* rrarows = */ 1200,
+ /* xff = */ 0.1,
+
+ /* timespans = */ NULL,
+ /* timespans_num = */ 0,
+
+ /* consolidation_functions = */ NULL,
+ /* consolidation_functions_num = */ 0
+};
/* XXX: If you need to lock both, cache_lock and queue_lock, at the same time,
* ALWAYS lock `cache_lock' first! */
static int do_shutdown = 0;
-/* * * * * * * * * *
- * WARNING: Magic *
- * * * * * * * * * */
-
-static void rra_free (int rra_num, char **rra_def)
-{
- int i;
-
- for (i = 0; i < rra_num; i++)
- {
- sfree (rra_def[i]);
- }
- sfree (rra_def);
-} /* void rra_free */
-
-static int rra_get (char ***ret, const value_list_t *vl)
-{
- char **rra_def;
- int rra_num;
-
- int *rts;
- int rts_num;
-
- int rra_max;
-
- int span;
-
- int cdp_num;
- int cdp_len;
- int i, j;
-
- char buffer[64];
-
- /* The stepsize we use here: If it is user-set, use it. If not, use the
- * interval of the value-list. */
- int ss;
-
- if (rrarows <= 0)
- {
- *ret = NULL;
- return (-1);
- }
-
- ss = (stepsize > 0) ? stepsize : vl->interval;
- if (ss <= 0)
- {
- *ret = NULL;
- return (-1);
- }
-
- /* Use the configured timespans or fall back to the built-in defaults */
- if (rra_timespans_custom_num != 0)
- {
- rts = rra_timespans_custom;
- rts_num = rra_timespans_custom_num;
- }
- else
- {
- rts = rra_timespans;
- rts_num = rra_timespans_num;
- }
-
- rra_max = rts_num * rra_types_num;
-
- if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
- return (-1);
- memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
- rra_num = 0;
-
- cdp_len = 0;
- for (i = 0; i < rts_num; i++)
- {
- span = rts[i];
-
- if ((span / ss) < rrarows)
- span = ss * rrarows;
-
- if (cdp_len == 0)
- cdp_len = 1;
- else
- cdp_len = (int) floor (((double) span)
- / ((double) (rrarows * ss)));
-
- cdp_num = (int) ceil (((double) span)
- / ((double) (cdp_len * ss)));
-
- for (j = 0; j < rra_types_num; j++)
- {
- if (rra_num >= rra_max)
- break;
-
- if (ssnprintf (buffer, sizeof (buffer), "RRA:%s:%3.1f:%u:%u",
- rra_types[j], xff,
- cdp_len, cdp_num) >= sizeof (buffer))
- {
- ERROR ("rra_get: Buffer would have been truncated.");
- continue;
- }
-
- rra_def[rra_num++] = sstrdup (buffer);
- }
- }
-
-#if COLLECT_DEBUG
- DEBUG ("rra_num = %i", rra_num);
- for (i = 0; i < rra_num; i++)
- DEBUG (" %s", rra_def[i]);
-#endif
-
- *ret = rra_def;
- return (rra_num);
-} /* int rra_get */
-
-static void ds_free (int ds_num, char **ds_def)
-{
- int i;
-
- for (i = 0; i < ds_num; i++)
- if (ds_def[i] != NULL)
- free (ds_def[i]);
- free (ds_def);
-}
-
-static int ds_get (char ***ret, const data_set_t *ds, const value_list_t *vl)
-{
- char **ds_def;
- int ds_num;
-
- char min[32];
- char max[32];
- char buffer[128];
-
- DEBUG ("ds->ds_num = %i", ds->ds_num);
-
- ds_def = (char **) malloc (ds->ds_num * sizeof (char *));
- if (ds_def == NULL)
- {
- char errbuf[1024];
- ERROR ("rrdtool plugin: malloc failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
- }
- memset (ds_def, '\0', ds->ds_num * sizeof (char *));
-
- for (ds_num = 0; ds_num < ds->ds_num; ds_num++)
- {
- data_source_t *d = ds->ds + ds_num;
- char *type;
- int status;
-
- ds_def[ds_num] = NULL;
-
- if (d->type == DS_TYPE_COUNTER)
- type = "COUNTER";
- else if (d->type == DS_TYPE_GAUGE)
- type = "GAUGE";
- else
- {
- ERROR ("rrdtool plugin: Unknown DS type: %i",
- d->type);
- break;
- }
-
- if (isnan (d->min))
- {
- sstrncpy (min, "U", sizeof (min));
- }
- else
- ssnprintf (min, sizeof (min), "%lf", d->min);
-
- if (isnan (d->max))
- {
- sstrncpy (max, "U", sizeof (max));
- }
- else
- ssnprintf (max, sizeof (max), "%lf", d->max);
-
- status = ssnprintf (buffer, sizeof (buffer),
- "DS:%s:%s:%i:%s:%s",
- d->name, type,
- (heartbeat > 0) ? heartbeat : (2 * vl->interval),
- min, max);
- if ((status < 1) || (status >= sizeof (buffer)))
- break;
-
- ds_def[ds_num] = sstrdup (buffer);
- } /* for ds_num = 0 .. ds->ds_num */
-
-#if COLLECT_DEBUG
-{
- int i;
- DEBUG ("ds_num = %i", ds_num);
- for (i = 0; i < ds_num; i++)
- DEBUG (" %s", ds_def[i]);
-}
-#endif
-
- if (ds_num != ds->ds_num)
- {
- ds_free (ds_num, ds_def);
- return (-1);
- }
-
- *ret = ds_def;
- return (ds_num);
-}
-
#if HAVE_THREADSAFE_LIBRRD
-static int srrd_create (char *filename, unsigned long pdp_step, time_t last_up,
- int argc, const char **argv)
-{
- int status;
-
- optind = 0; /* bug in librrd? */
- rrd_clear_error ();
-
- status = rrd_create_r (filename, pdp_step, last_up, argc, (void *) argv);
-
- if (status != 0)
- {
- WARNING ("rrdtool plugin: rrd_create_r (%s) failed: %s",
- filename, rrd_get_error ());
- }
-
- return (status);
-} /* int srrd_create */
-
static int srrd_update (char *filename, char *template,
int argc, const char **argv)
{
/* #endif HAVE_THREADSAFE_LIBRRD */
#else /* !HAVE_THREADSAFE_LIBRRD */
-static int srrd_create (char *filename, unsigned long pdp_step, time_t last_up,
- int argc, const char **argv)
-{
- int status;
-
- int new_argc;
- char **new_argv;
-
- char pdp_step_str[16];
- char last_up_str[16];
-
- new_argc = 6 + argc;
- new_argv = (char **) malloc ((new_argc + 1) * sizeof (char *));
- if (new_argv == NULL)
- {
- ERROR ("rrdtool plugin: malloc failed.");
- return (-1);
- }
-
- if (last_up == 0)
- last_up = time (NULL) - 10;
-
- ssnprintf (pdp_step_str, sizeof (pdp_step_str), "%lu", pdp_step);
- ssnprintf (last_up_str, sizeof (last_up_str), "%u", (unsigned int) last_up);
-
- new_argv[0] = "create";
- new_argv[1] = filename;
- new_argv[2] = "-s";
- new_argv[3] = pdp_step_str;
- new_argv[4] = "-b";
- new_argv[5] = last_up_str;
-
- memcpy (new_argv + 6, argv, argc * sizeof (char *));
- new_argv[new_argc] = NULL;
-
- pthread_mutex_lock (&librrd_lock);
- optind = 0; /* bug in librrd? */
- rrd_clear_error ();
-
- status = rrd_create (new_argc, new_argv);
- pthread_mutex_unlock (&librrd_lock);
-
- if (status != 0)
- {
- WARNING ("rrdtool plugin: rrd_create (%s) failed: %s",
- filename, rrd_get_error ());
- }
-
- sfree (new_argv);
-
- return (status);
-} /* int srrd_create */
-
static int srrd_update (char *filename, char *template,
int argc, const char **argv)
{
} /* int srrd_update */
#endif /* !HAVE_THREADSAFE_LIBRRD */
-static int rrd_create_file (char *filename, const data_set_t *ds, const value_list_t *vl)
-{
- char **argv;
- int argc;
- char **rra_def;
- int rra_num;
- char **ds_def;
- int ds_num;
- int status = 0;
-
- if (check_create_dir (filename))
- return (-1);
-
- if ((rra_num = rra_get (&rra_def, vl)) < 1)
- {
- ERROR ("rrd_create_file failed: Could not calculate RRAs");
- return (-1);
- }
-
- if ((ds_num = ds_get (&ds_def, ds, vl)) < 1)
- {
- ERROR ("rrd_create_file failed: Could not calculate DSes");
- return (-1);
- }
-
- argc = ds_num + rra_num;
-
- if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
- {
- char errbuf[1024];
- ERROR ("rrd_create failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
- }
-
- memcpy (argv, ds_def, ds_num * sizeof (char *));
- memcpy (argv + ds_num, rra_def, rra_num * sizeof (char *));
- argv[ds_num + rra_num] = NULL;
-
- assert (vl->time > 10);
- status = srrd_create (filename,
- (stepsize > 0) ? stepsize : vl->interval,
- vl->time - 10,
- argc, (const char **)argv);
-
- free (argv);
- ds_free (ds_num, ds_def);
- rra_free (rra_num, rra_def);
-
- return (status);
-}
-
static int value_list_to_string (char *buffer, int buffer_len,
const data_set_t *ds, const value_list_t *vl)
{
{
if (errno == ENOENT)
{
- if (rrd_create_file (filename, ds, vl))
+ status = cu_rrd_create_file (filename,
+ ds, vl, &rrdcreate_config);
+ if (status != 0)
return (-1);
}
else
}
else if (strcasecmp ("StepSize", key) == 0)
{
- stepsize = atoi (value);
- if (stepsize < 0)
- stepsize = 0;
+ int temp = atoi (value);
+ if (temp > 0)
+ rrdcreate_config.stepsize = temp;
}
else if (strcasecmp ("HeartBeat", key) == 0)
{
- heartbeat = atoi (value);
- if (heartbeat < 0)
- heartbeat = 0;
+ int temp = atoi (value);
+ if (temp > 0)
+ rrdcreate_config.heartbeat = temp;
}
else if (strcasecmp ("RRARows", key) == 0)
{
"be greater than 0.\n");
return (1);
}
- rrarows = tmp;
+ rrdcreate_config.rrarows = tmp;
}
else if (strcasecmp ("RRATimespan", key) == 0)
{
{
dummy = NULL;
- tmp_alloc = realloc (rra_timespans_custom,
- sizeof (int) * (rra_timespans_custom_num + 1));
+ tmp_alloc = realloc (rrdcreate_config.timespans,
+ sizeof (int) * (rrdcreate_config.timespans_num + 1));
if (tmp_alloc == NULL)
{
fprintf (stderr, "rrdtool: realloc failed.\n");
free (value_copy);
return (1);
}
- rra_timespans_custom = tmp_alloc;
- rra_timespans_custom[rra_timespans_custom_num] = atoi (ptr);
- if (rra_timespans_custom[rra_timespans_custom_num] != 0)
- rra_timespans_custom_num++;
+ rrdcreate_config.timespans = tmp_alloc;
+ rrdcreate_config.timespans[rrdcreate_config.timespans_num] = atoi (ptr);
+ if (rrdcreate_config.timespans[rrdcreate_config.timespans_num] != 0)
+ rrdcreate_config.timespans_num++;
} /* while (strtok_r) */
- qsort (/* base = */ rra_timespans_custom,
- /* nmemb = */ rra_timespans_custom_num,
- /* size = */ sizeof (rra_timespans_custom[0]),
+ qsort (/* base = */ rrdcreate_config.timespans,
+ /* nmemb = */ rrdcreate_config.timespans_num,
+ /* size = */ sizeof (rrdcreate_config.timespans[0]),
/* compar = */ rrd_compare_numeric);
free (value_copy);
"be in the range 0 to 1 (exclusive).");
return (1);
}
- xff = tmp;
+ rrdcreate_config.xff = tmp;
}
else if (strcasecmp ("WritesPerSecond", key) == 0)
{
{
int status;
- if (stepsize < 0)
- stepsize = 0;
- if (heartbeat <= 0)
- heartbeat = 2 * stepsize;
+ if (rrdcreate_config.stepsize < 0)
+ rrdcreate_config.stepsize = 0;
+ if (rrdcreate_config.heartbeat <= 0)
+ rrdcreate_config.heartbeat = 2 * rrdcreate_config.stepsize;
- if ((heartbeat > 0) && (heartbeat < interval_g))
+ if ((rrdcreate_config.heartbeat > 0)
+ && (rrdcreate_config.heartbeat < interval_g))
WARNING ("rrdtool plugin: Your `heartbeat' is "
"smaller than your `interval'. This will "
"likely cause problems.");
- else if ((stepsize > 0) && (stepsize < interval_g))
+ else if ((rrdcreate_config.stepsize > 0)
+ && (rrdcreate_config.stepsize < interval_g))
WARNING ("rrdtool plugin: Your `stepsize' is "
"smaller than your `interval'. This will "
"create needlessly big RRD-files.");
DEBUG ("rrdtool plugin: rrd_init: datadir = %s; stepsize = %i;"
" heartbeat = %i; rrarows = %i; xff = %lf;",
(datadir == NULL) ? "(null)" : datadir,
- stepsize, heartbeat, rrarows, xff);
+ rrdcreate_config.stepsize,
+ rrdcreate_config.heartbeat,
+ rrdcreate_config.rrarows,
+ rrdcreate_config.xff);
return (0);
} /* int rrd_init */
#include "collectd.h"
#include "common.h"
#include "plugin.h"
+#include "utils_complain.h"
#include <pthread.h>
char *community;
int version;
void *sess_handle;
+ c_complain_t complaint;
uint32_t interval;
time_t next_update;
data_definition_t **data_list;
/*
* Private functions
*/
+/* Many functions to handle the configuration. {{{ */
/* First there are many functions which do configuration stuff. It's a big
* bloated and messy, I'm afraid. */
return (-1);
memset (hd, '\0', sizeof (host_definition_t));
hd->version = 2;
+ C_COMPLAIN_INIT (&hd->complaint);
hd->name = strdup (ci->values[0].value.string);
if (hd->name == NULL)
return (0);
} /* int csnmp_config */
-/* End of the config stuff. Now the interesting part begins */
+/* }}} End of the config stuff. Now the interesting part begins */
static void csnmp_host_close_session (host_definition_t *host)
{
char *errstr = NULL;
snmp_sess_error (host->sess_handle, NULL, NULL, &errstr);
- ERROR ("snmp plugin: host %s: snmp_sess_synch_response failed: %s",
+
+ c_complain (LOG_ERR, &host->complaint,
+ "snmp plugin: host %s: snmp_sess_synch_response failed: %s",
host->name, (errstr == NULL) ? "Unknown problem" : errstr);
if (res != NULL)
}
status = 0;
assert (res != NULL);
+ c_release (LOG_INFO, &host->complaint,
+ "snmp plugin: host %s: snmp_sess_synch_response successful.",
+ host->name);
vb = res->variables;
if (vb == NULL)
} /* void module_register */
/*
- * vim: shiftwidth=2 softtabstop=2 tabstop=8
+ * vim: shiftwidth=2 softtabstop=2 tabstop=8 fdm=marker
*/
nfs_procedure value:COUNTER:0:4294967295
nginx_connections value:GAUGE:0:U
nginx_requests value:COUNTER:0:134217728
+operations value:COUNTER:0:4294967295
percent percent:GAUGE:0:100.1
pg_blks value:COUNTER:0:U
pg_db_size value:GAUGE:0:U
ps_pagefaults minflt:COUNTER:0:9223372036854775807, majflt:COUNTER:0:9223372036854775807
ps_rss value:GAUGE:0:9223372036854775807
ps_state value:GAUGE:0:65535
+queue_length value:GAUGE:0:U
serial_octets rx:COUNTER:0:4294967295, tx:COUNTER:0:4294967295
signal_noise value:GAUGE:U:0
signal_power value:GAUGE:U:0
int interval;
} c_complain_t;
-#define C_COMPLAIN_INIT { 0, 0 }
+#define C_COMPLAIN_INIT_STATIC { 0, 0 }
+#define C_COMPLAIN_INIT(c) do { (c)->last = 0; (c)->interval = 0; } while (0)
/*
* NAME
--- /dev/null
+/**
+ * collectd - src/utils_rrdcreate.c
+ * Copyright (C) 2006-2008 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
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "utils_rrdcreate.h"
+
+#include <rrd.h>
+
+/*
+ * Private variables
+ */
+static int rra_timespans[] =
+{
+ 3600,
+ 86400,
+ 604800,
+ 2678400,
+ 31622400
+};
+static int rra_timespans_num = STATIC_ARRAY_SIZE (rra_timespans);
+
+static char *rra_types[] =
+{
+ "AVERAGE",
+ "MIN",
+ "MAX"
+};
+static int rra_types_num = STATIC_ARRAY_SIZE (rra_types);
+
+/*
+ * Private functions
+ */
+static void rra_free (int rra_num, char **rra_def) /* {{{ */
+{
+ int i;
+
+ for (i = 0; i < rra_num; i++)
+ {
+ sfree (rra_def[i]);
+ }
+ sfree (rra_def);
+} /* }}} void rra_free */
+
+/* * * * * * * * * *
+ * WARNING: Magic *
+ * * * * * * * * * */
+static int rra_get (char ***ret, const value_list_t *vl, /* {{{ */
+ const rrdcreate_config_t *cfg)
+{
+ char **rra_def;
+ int rra_num;
+
+ int *rts;
+ int rts_num;
+
+ int rra_max;
+
+ int span;
+
+ int cdp_num;
+ int cdp_len;
+ int i, j;
+
+ char buffer[128];
+
+ /* The stepsize we use here: If it is user-set, use it. If not, use the
+ * interval of the value-list. */
+ int ss;
+
+ if (cfg->rrarows <= 0)
+ {
+ *ret = NULL;
+ return (-1);
+ }
+
+ if ((cfg->xff < 0) || (cfg->xff >= 1.0))
+ {
+ *ret = NULL;
+ return (-1);
+ }
+
+ ss = (cfg->stepsize > 0) ? cfg->stepsize : vl->interval;
+ if (ss <= 0)
+ {
+ *ret = NULL;
+ return (-1);
+ }
+
+ /* Use the configured timespans or fall back to the built-in defaults */
+ if (cfg->timespans_num != 0)
+ {
+ rts = cfg->timespans;
+ rts_num = cfg->timespans_num;
+ }
+ else
+ {
+ rts = rra_timespans;
+ rts_num = rra_timespans_num;
+ }
+
+ rra_max = rts_num * rra_types_num;
+
+ if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
+ return (-1);
+ memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
+ rra_num = 0;
+
+ cdp_len = 0;
+ for (i = 0; i < rts_num; i++)
+ {
+ span = rts[i];
+
+ if ((span / ss) < cfg->rrarows)
+ span = ss * cfg->rrarows;
+
+ if (cdp_len == 0)
+ cdp_len = 1;
+ else
+ cdp_len = (int) floor (((double) span)
+ / ((double) (cfg->rrarows * ss)));
+
+ cdp_num = (int) ceil (((double) span)
+ / ((double) (cdp_len * ss)));
+
+ for (j = 0; j < rra_types_num; j++)
+ {
+ if (rra_num >= rra_max)
+ break;
+
+ if (ssnprintf (buffer, sizeof (buffer), "RRA:%s:%3.1f:%u:%u",
+ rra_types[j], cfg->xff,
+ cdp_len, cdp_num) >= sizeof (buffer))
+ {
+ ERROR ("rra_get: Buffer would have been truncated.");
+ continue;
+ }
+
+ rra_def[rra_num++] = sstrdup (buffer);
+ }
+ }
+
+ *ret = rra_def;
+ return (rra_num);
+} /* }}} int rra_get */
+
+static void ds_free (int ds_num, char **ds_def) /* {{{ */
+{
+ int i;
+
+ for (i = 0; i < ds_num; i++)
+ if (ds_def[i] != NULL)
+ free (ds_def[i]);
+ free (ds_def);
+} /* }}} void ds_free */
+
+static int ds_get (char ***ret, /* {{{ */
+ const data_set_t *ds, const value_list_t *vl,
+ const rrdcreate_config_t *cfg)
+{
+ char **ds_def;
+ int ds_num;
+
+ char min[32];
+ char max[32];
+ char buffer[128];
+
+ ds_def = (char **) malloc (ds->ds_num * sizeof (char *));
+ if (ds_def == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("rrdtool plugin: malloc failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+ memset (ds_def, '\0', ds->ds_num * sizeof (char *));
+
+ for (ds_num = 0; ds_num < ds->ds_num; ds_num++)
+ {
+ data_source_t *d = ds->ds + ds_num;
+ char *type;
+ int status;
+
+ ds_def[ds_num] = NULL;
+
+ if (d->type == DS_TYPE_COUNTER)
+ type = "COUNTER";
+ else if (d->type == DS_TYPE_GAUGE)
+ type = "GAUGE";
+ else
+ {
+ ERROR ("rrdtool plugin: Unknown DS type: %i",
+ d->type);
+ break;
+ }
+
+ if (isnan (d->min))
+ {
+ sstrncpy (min, "U", sizeof (min));
+ }
+ else
+ ssnprintf (min, sizeof (min), "%lf", d->min);
+
+ if (isnan (d->max))
+ {
+ sstrncpy (max, "U", sizeof (max));
+ }
+ else
+ ssnprintf (max, sizeof (max), "%lf", d->max);
+
+ status = ssnprintf (buffer, sizeof (buffer),
+ "DS:%s:%s:%i:%s:%s",
+ d->name, type,
+ (cfg->heartbeat > 0) ? cfg->heartbeat : (2 * vl->interval),
+ min, max);
+ if ((status < 1) || (status >= sizeof (buffer)))
+ break;
+
+ ds_def[ds_num] = sstrdup (buffer);
+ } /* for ds_num = 0 .. ds->ds_num */
+
+ if (ds_num != ds->ds_num)
+ {
+ ds_free (ds_num, ds_def);
+ return (-1);
+ }
+
+ *ret = ds_def;
+ return (ds_num);
+} /* }}} int ds_get */
+
+#if HAVE_THREADSAFE_LIBRRD
+static int srrd_create (const char *filename, /* {{{ */
+ unsigned long pdp_step, time_t last_up,
+ int argc, const char **argv)
+{
+ int status;
+
+ optind = 0; /* bug in librrd? */
+ rrd_clear_error ();
+
+ status = rrd_create_r (filename, pdp_step, last_up, argc, (void *) argv);
+
+ if (status != 0)
+ {
+ WARNING ("rrdtool plugin: rrd_create_r (%s) failed: %s",
+ filename, rrd_get_error ());
+ }
+
+ return (status);
+} /* }}} int srrd_create */
+/* #endif HAVE_THREADSAFE_LIBRRD */
+
+#else /* !HAVE_THREADSAFE_LIBRRD */
+static int srrd_create (const char *filename, /* {{{ */
+ unsigned long pdp_step, time_t last_up,
+ int argc, const char **argv)
+{
+ int status;
+
+ int new_argc;
+ char **new_argv;
+
+ char pdp_step_str[16];
+ char last_up_str[16];
+
+ new_argc = 6 + argc;
+ new_argv = (char **) malloc ((new_argc + 1) * sizeof (char *));
+ if (new_argv == NULL)
+ {
+ ERROR ("rrdtool plugin: malloc failed.");
+ return (-1);
+ }
+
+ if (last_up == 0)
+ last_up = time (NULL) - 10;
+
+ ssnprintf (pdp_step_str, sizeof (pdp_step_str), "%lu", pdp_step);
+ ssnprintf (last_up_str, sizeof (last_up_str), "%u", (unsigned int) last_up);
+
+ new_argv[0] = "create";
+ new_argv[1] = filename;
+ new_argv[2] = "-s";
+ new_argv[3] = pdp_step_str;
+ new_argv[4] = "-b";
+ new_argv[5] = last_up_str;
+
+ memcpy (new_argv + 6, argv, argc * sizeof (char *));
+ new_argv[new_argc] = NULL;
+
+ pthread_mutex_lock (&librrd_lock);
+ optind = 0; /* bug in librrd? */
+ rrd_clear_error ();
+
+ status = rrd_create (new_argc, new_argv);
+ pthread_mutex_unlock (&librrd_lock);
+
+ if (status != 0)
+ {
+ WARNING ("rrdtool plugin: rrd_create (%s) failed: %s",
+ filename, rrd_get_error ());
+ }
+
+ sfree (new_argv);
+
+ return (status);
+} /* }}} int srrd_create */
+#endif /* !HAVE_THREADSAFE_LIBRRD */
+
+/*
+ * Public functions
+ */
+int cu_rrd_create_file (const char *filename, /* {{{ */
+ const data_set_t *ds, const value_list_t *vl,
+ const rrdcreate_config_t *cfg)
+{
+ char **argv;
+ int argc;
+ char **rra_def;
+ int rra_num;
+ char **ds_def;
+ int ds_num;
+ int status = 0;
+
+ if (check_create_dir (filename))
+ return (-1);
+
+ if ((rra_num = rra_get (&rra_def, vl, cfg)) < 1)
+ {
+ ERROR ("cu_rrd_create_file failed: Could not calculate RRAs");
+ return (-1);
+ }
+
+ if ((ds_num = ds_get (&ds_def, ds, vl, cfg)) < 1)
+ {
+ ERROR ("cu_rrd_create_file failed: Could not calculate DSes");
+ return (-1);
+ }
+
+ argc = ds_num + rra_num;
+
+ if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("cu_rrd_create_file failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+
+ memcpy (argv, ds_def, ds_num * sizeof (char *));
+ memcpy (argv + ds_num, rra_def, rra_num * sizeof (char *));
+ argv[ds_num + rra_num] = NULL;
+
+ assert (vl->time > 10);
+ status = srrd_create (filename,
+ (cfg->stepsize > 0) ? cfg->stepsize : vl->interval,
+ vl->time - 10,
+ argc, (const char **) argv);
+
+ free (argv);
+ ds_free (ds_num, ds_def);
+ rra_free (rra_num, rra_def);
+
+ if (status != 0)
+ {
+ WARNING ("cu_rrd_create_file: srrd_create (%s) returned status %i.",
+ filename, status);
+ }
+ else
+ {
+ DEBUG ("cu_rrd_create_file: Successfully created RRD file \"%s\".",
+ filename);
+ }
+
+ return (status);
+} /* }}} int cu_rrd_create_file */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
--- /dev/null
+/**
+ * collectd - src/utils_rrdcreate.h
+ * Copyright (C) 2008 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
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#ifndef UTILS_RRDCREATE_H
+#define UTILS_RRDCREATE_H 1
+
+struct rrdcreate_config_s
+{
+ int stepsize;
+ int heartbeat;
+ int rrarows;
+ double xff;
+
+ int *timespans;
+ size_t timespans_num;
+
+ char **consolidation_functions;
+ size_t consolidation_functions_num;
+};
+typedef struct rrdcreate_config_s rrdcreate_config_t;
+
+int cu_rrd_create_file (const char *filename,
+ const data_set_t *ds, const value_list_t *vl,
+ const rrdcreate_config_t *cfg);
+
+#endif /* UTILS_RRDCREATE_H */
+
+/* vim: set sw=2 sts=2 et : */