author | Marc Fournier <marc.fournier@camptocamp.com> | |
Fri, 6 Nov 2015 08:42:11 +0000 (09:42 +0100) | ||
committer | Marc Fournier <marc.fournier@camptocamp.com> | |
Fri, 6 Nov 2015 08:42:11 +0000 (09:42 +0100) |
132 files changed:
diff --git a/.gitignore b/.gitignore
index 54eaa9748ef6240a0e8cd12650275d6536892f53..cf4ad158cdf3287937d7ce6f0a5becf6f4d8d3d5 100644 (file)
--- a/.gitignore
+++ b/.gitignore
src/tests/mock/.deps/
src/tests/.dirstamp
src/tests/mock/.dirstamp
+src/test_utils_latency
+src/test_utils_mount
+src/test_utils_vl_lookup
test*.log
+*.trs
# new daemon repo
src/daemon/.deps/
src/daemon/.dirstamp
src/daemon/collectd
+src/daemon/test_common
+src/daemon/test_meta_data
+src/daemon/test_utils_avltree
+src/daemon/test_utils_heap
+src/daemon/test_utils_subst
diff --git a/.travis.yml b/.travis.yml
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,25 @@
+sudo: false
+compiler:
+ - gcc
+ - clang
+addons:
+ apt:
+ packages:
+ - iptables-dev
+ - libcap-dev
+ - libdbi-dev
+ - libhiredis-dev
+ - libnfnetlink-dev
+ - libnotify-dev
+ - libpcap-dev
+ - libperl-dev
+ - libprotobuf-c0-dev
+ - librrd-dev
+ - libsnmp-dev
+ - libudev-dev
+ - libvarnishapi-dev
+ - libyajl-dev
+ - linux-libc-dev
+ - protobuf-c-compiler
+language: c
+script: sh build.sh && ./configure && make distcheck
index 3f63c3dcd5591c72131b4bfa3dc579d9bc5e36cc..02b125688ee778587d14992e449d28bb2142515f 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
Cyril Feraudet <cyril at feraudet.com>
- ethstat plugin.
+Dagobert Michelsen <dam at opencsw.org>
+ - zone plugin.
+
Dan Berrange <berrange at redhat.com>
- uuid plugin.
- ip6tables support in the iptables plugin.
- openvpn plugin (support for more status file formats)
+Mathijs Möhlmann <collectd at mmrc.nl>
+ - zone plugin.
+
Michael Hanselmann <public at hansmi.ch>
- md plugin.
index 3e2c0233adc3ea9ccfbcbbf072c107a0f6dcbd5b..ad5b66783473bc531d9c20451c306db47b22a3e7 100644 (file)
--- a/README
+++ b/README
Reads values from Modbus/TCP enabled devices. Supports reading values
from multiple "slaves" so gateway devices can be used.
+ - mqtt
+ Publishes and subscribes to MQTT topics.
+
- multimeter
Information provided by serial multimeters, such as the `Metex
M-4650CR'.
- zfs_arc
Statistics for ZFS' “Adaptive Replacement Cache” (ARC).
+ - zone
+ Measures the percentage of cpu load per container (zone) under Solaris 10
+ and higher
+
- zookeeper
Read data from Zookeeper's MNTR command.
index 5e79d2682ecbb723ff094f1d12add49b15b72a76..d927d13e4bc486b48110c5d786ad537d763f8de8 100644 (file)
sub _escape_argument
{
- local $_ = shift;
+ my $arg = shift;
- return $_ if /^\w+$/;
+ return $arg if $arg =~ /^\w+$/;
- s#\\#\\\\#g;
- s#"#\\"#g;
- return "\"$_\"";
+ $arg =~ s#\\#\\\\#g;
+ $arg =~ s#"#\\"#g;
+ return "\"$arg\"";
}
# Send a command on a socket, including any required argument escaping.
index 2f7818b15799cb650e6d2288072286f4426ac583..4e94f8e8d235f53fa742bd716a1b738b6aade28f 100644 (file)
my ($nresults, $resultdata) = @$results;
my $r = $s->getval(%{Collectd::Unixsock::_parse_identifier($attr)});
is(ref $r, 'HASH', "Got a result for $attr");
- is(scalar keys $r, $nresults, "$nresults result result for $attr");
+ is(scalar keys %$r, $nresults, "$nresults result result for $attr");
is_deeply($r, $resultdata, "Data or $attr matches");
}
diff --git a/configure.ac b/configure.ac
index 7b2296d0f56bf8ba5111f23f9145afe4c4db243c..3f5f2d8b19e1d65b84268cdb93ae321f40e5998f 100644 (file)
--- a/configure.ac
+++ b/configure.ac
AM_CONDITIONAL(BUILD_WITH_LIBMONGOC, test "x$with_libmongoc" = "xyes")
# }}}
+# --with-libmosquitto {{{
+with_libmosquitto_cppflags=""
+with_libmosquitto_libs="-lmosquitto"
+AC_ARG_WITH(libmosquitto, [AS_HELP_STRING([--with-libmosquitto@<:@=PREFIX@:>@], [Path to libmosquitto.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ with_libmosquitto_cppflags="-I$withval/include"
+ with_libmosquitto_libs="-L$withval/lib -lmosquitto"
+ with_libmosquitto="yes"
+ else
+ with_libmosquitto="$withval"
+ fi
+],
+[
+ with_libmosquitto="yes"
+])
+if test "x$with_libmosquitto" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$with_libmosquitto_cppflags"
+
+ AC_CHECK_HEADERS(mosquitto.h, [with_libmosquitto="yes"], [with_libmosquitto="no (mosquitto.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libmosquitto" = "xyes"
+then
+ SAVE_LDFLAGS="$LDFLAGS"
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ LDFLAGS="$with_libmosquitto_libs"
+ CPPFLAGS="$with_libmosquitto_cppflags"
+
+ AC_CHECK_LIB(mosquitto, mosquitto_connect, [with_libmosquitto="yes"], [with_libmosquitto="no (libmosquitto not found)"])
+
+ LDFLAGS="$SAVE_LDFLAGS"
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libmosquitto" = "xyes"
+then
+ BUILD_WITH_LIBMOSQUITTO_CPPFLAGS="$with_libmosquitto_cppflags"
+ BUILD_WITH_LIBMOSQUITTO_LIBS="$with_libmosquitto_libs"
+ AC_SUBST(BUILD_WITH_LIBMOSQUITTO_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBMOSQUITTO_LIBS)
+fi
+# }}}
+
# --with-libmysql {{{
with_mysql_config="mysql_config"
with_mysql_cflags=""
AC_COLLECTD([debug], [enable], [feature], [debugging])
AC_COLLECTD([daemon], [disable], [feature], [daemon mode])
AC_COLLECTD([getifaddrs],[enable], [feature], [getifaddrs under Linux])
+AC_COLLECTD([werror], [disable], [feature], [building with -Werror])
dependency_warning="no"
dependency_error="no"
plugin_vserver="no"
plugin_wireless="no"
plugin_zfs_arc="no"
+plugin_zone="no"
plugin_zookeeper="no"
# Linux
if test "x$ac_system" = "xFreeBSD"
then
+ plugin_disk="yes"
plugin_zfs_arc="yes"
fi
plugin_processes="yes"
plugin_uptime="yes"
plugin_zfs_arc="yes"
+ plugin_zone="yes"
fi
if test "x$with_devinfo$with_kstat" = "xyesyes"
AC_PLUGIN([memory], [$plugin_memory], [Memory usage])
AC_PLUGIN([mic], [$with_mic], [Intel Many Integrated Core stats])
AC_PLUGIN([modbus], [$with_libmodbus], [Modbus plugin])
+AC_PLUGIN([mqtt], [$with_libmosquitto], [MQTT output plugin])
AC_PLUGIN([multimeter], [$plugin_multimeter], [Read multimeter values])
AC_PLUGIN([mysql], [$with_libmysql], [MySQL statistics])
AC_PLUGIN([netapp], [$with_libnetapp], [NetApp plugin])
AC_PLUGIN([write_tsdb], [yes], [TSDB output plugin])
AC_PLUGIN([xmms], [$with_libxmms], [XMMS statistics])
AC_PLUGIN([zfs_arc], [$plugin_zfs_arc], [ZFS ARC statistics])
+AC_PLUGIN([zone], [$plugin_zone], [Solaris container statistics])
AC_PLUGIN([zookeeper], [yes], [Zookeeper statistics])
dnl Default configuration file
AC_CONFIG_FILES(src/libcollectdclient/collectd/lcc_features.h)
+AM_CFLAGS="-Wall"
+if test "x$enable_werror" != "xno"
+then
+ AM_CFLAGS="$AM_CFLAGS -Werror"
+fi
+AC_SUBST([AM_CFLAGS])
+
AC_CONFIG_FILES([Makefile src/Makefile src/daemon/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile])
AC_OUTPUT
cat <<EOF;
Configuration:
+ Build:
+ Platform . . . . . . $ac_system
+ CC . . . . . . . . . $CC
+ CFLAGS . . . . . . . $AM_CFLAGS $CFLAGS
+ CPP . . . . . . . . . $CPP
+ CPPFLAGS . . . . . . $CPPFLAGS
+ LD . . . . . . . . . $LD
+ LDFLAGS . . . . . . . $LDFLAGS
+ YACC . . . . . . . . $YACC
+ YFLAGS . . . . . . . $YFLAGS
+
Libraries:
intel mic . . . . . . $with_mic
libaquaero5 . . . . . $with_libaquaero5
libmnl . . . . . . . $with_libmnl
libmodbus . . . . . . $with_libmodbus
libmongoc . . . . . . $with_libmongoc
+ libmosquitto . . . . $with_libmosquitto
libmysql . . . . . . $with_libmysql
libnetapp . . . . . . $with_libnetapp
libnetsnmp . . . . . $with_libnetsnmp
memory . . . . . . . $enable_memory
mic . . . . . . . . . $enable_mic
modbus . . . . . . . $enable_modbus
+ mqtt . . . . . . . . $enable_mqtt
multimeter . . . . . $enable_multimeter
mysql . . . . . . . . $enable_mysql
netapp . . . . . . . $enable_netapp
write_tsdb . . . . . $enable_write_tsdb
xmms . . . . . . . . $enable_xmms
zfs_arc . . . . . . . $enable_zfs_arc
+ zone . . . . . . . . $enable_zone
zookeeper . . . . . . $enable_zookeeper
EOF
diff --git a/contrib/README b/contrib/README
index 1ebf1f146e6332ce88f90b894ec233bbbc196946..897d61978c32532c535d635cf96c1bdac781007e 100644 (file)
--- a/contrib/README
+++ b/contrib/README
RRD-file that should have been in multiple RRD-files instead. Is is used by
`migrate-3-4.px' to split up the cpu-, nfs-, swap-files and possibly others.
-fedora/
--------
- Init-script and Spec-file that can be used when creating RPM-packages for
-Fedora.
-
GenericJMX.conf
---------------
Example configuration file for the ‘GenericJMX’ Java plugin. Please read the
diff --git a/contrib/collectd.service b/contrib/collectd.service
--- a/contrib/collectd.service
+++ /dev/null
@@ -1,15 +0,0 @@
-[Unit]
-Description=statistics collection daemon
-Documentation=man:collectd(1)
-After=local-fs.target network.target
-Requires=local-fs.target network.target
-
-[Service]
-ExecStart=/usr/sbin/collectd -C /etc/collectd/collectd.conf -f
-Restart=always
-RestartSec=10
-StandardOutput=syslog
-StandardError=syslog
-
-[Install]
-WantedBy=multi-user.target
diff --git a/contrib/fedora/collectd.spec b/contrib/fedora/collectd.spec
+++ /dev/null
@@ -1,376 +0,0 @@
-Summary: Statistics collection daemon for filling RRD files.
-Name: collectd
-Version: 4.2.0
-Release: 1.fc6
-Source: http://collectd.org/files/%{name}-%{version}.tar.gz
-License: GPL
-Group: System Environment/Daemons
-BuildRoot: %{_tmppath}/%{name}-%{version}-root
-BuildPrereq: lm_sensors-devel
-BuildPrereq: mysql-devel
-BuildPrereq: rrdtool-devel
-BuildPrereq: net-snmp-devel
-Requires: rrdtool
-Requires: perl-Regexp-Common
-Packager: Florian octo Forster <octo@verplant.org>
-Vendor: Florian octo Forster <octo@verplant.org>
-
-%description
-collectd is a small daemon written in C for performance. It reads various
-system statistics and updates RRD files, creating them if neccessary.
-Since the daemon doesn't need to startup every time it wants to update the
-files it's very fast and easy on the system. Also, the statistics are very
-fine grained since the files are updated every 10 seconds.
-
-%package apache
-Summary: apache-plugin for collectd.
-Group: System Environment/Daemons
-Requires: collectd = %{version}, curl
-%description apache
-This plugin collectd data provided by Apache's `mod_status'.
-
-%package email
-Summary: email-plugin for collectd.
-Group: System Environment/Daemons
-Requires: collectd = %{version}, spamassassin
-%description email
-This plugin collectd data provided by spamassassin.
-
-%package mysql
-Summary: mysql-module for collectd.
-Group: System Environment/Daemons
-Requires: collectd = %{version}, mysql
-%description mysql
-MySQL querying plugin. This plugins provides data of issued commands,
-called handlers and database traffic.
-
-%package sensors
-Summary: libsensors-module for collectd.
-Group: System Environment/Daemons
-Requires: collectd = %{version}, lm_sensors
-%description sensors
-This plugin for collectd provides querying of sensors supported by
-lm_sensors.
-
-%prep
-rm -rf $RPM_BUILD_ROOT
-%setup
-
-%build
-./configure --prefix=%{_prefix} --sbindir=%{_sbindir} --mandir=%{_mandir} --libdir=%{_libdir} --sysconfdir=%{_sysconfdir}
-make
-
-%install
-make install DESTDIR=$RPM_BUILD_ROOT
-mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
-mkdir -p $RPM_BUILD_ROOT/var/www/cgi-bin
-cp src/collectd.conf $RPM_BUILD_ROOT/etc/collectd.conf
-cp contrib/fedora/init.d-collectd $RPM_BUILD_ROOT/etc/rc.d/init.d/collectd
-cp contrib/collection.cgi $RPM_BUILD_ROOT/var/www/cgi-bin
-cp contrib/collection.conf $RPM_BUILD_ROOT/etc/collection.conf
-mkdir -p $RPM_BUILD_ROOT/var/lib/collectd
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%post
-/sbin/chkconfig --add collectd
-/sbin/chkconfig collectd on
-
-%preun
-if [ "$1" = 0 ]; then
- /sbin/chkconfig collectd off
- /etc/init.d/collectd stop
- /sbin/chkconfig --del collectd
-fi
-exit 0
-
-%postun
-if [ "$1" -ge 1 ]; then
- /etc/init.d/collectd restart
-fi
-exit 0
-
-%files
-%defattr(-,root,root)
-%doc AUTHORS COPYING ChangeLog INSTALL NEWS README
-%attr(0644,root,root) %config(noreplace) /etc/collectd.conf
-%attr(0644,root,root) %config(noreplace) /etc/collection.conf
-%attr(0755,root,root) /etc/rc.d/init.d/collectd
-%attr(0755,root,root) /var/www/cgi-bin/collection.cgi
-%attr(0755,root,root) %{_sbindir}/collectd
-%attr(0755,root,root) %{_bindir}/collectd-nagios
-%attr(0644,root,root) %{_mandir}/man1/*
-%attr(0644,root,root) %{_mandir}/man5/*
-
-%attr(0644,root,root) /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod
-%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/Collectd.pm
-%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/Collectd/Unixsock.pm
-%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/Collectd/.packlist
-%attr(0644,root,root) %{_mandir}/man3/Collectd::Unixsock.3pm.gz
-
-%attr(0644,root,root) %{_libdir}/%{name}/apcups.so*
-%attr(0644,root,root) %{_libdir}/%{name}/apcups.la
-
-# FIXME!!!
-#%attr(0644,root,root) %{_libdir}/%{name}/apple_sensors.so*
-#%attr(0644,root,root) %{_libdir}/%{name}/apple_sensors.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/battery.so*
-%attr(0644,root,root) %{_libdir}/%{name}/battery.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/conntrack.so*
-%attr(0644,root,root) %{_libdir}/%{name}/conntrack.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/cpufreq.so*
-%attr(0644,root,root) %{_libdir}/%{name}/cpufreq.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/cpu.so*
-%attr(0644,root,root) %{_libdir}/%{name}/cpu.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/csv.so*
-%attr(0644,root,root) %{_libdir}/%{name}/csv.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/df.so*
-%attr(0644,root,root) %{_libdir}/%{name}/df.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/disk.so*
-%attr(0644,root,root) %{_libdir}/%{name}/disk.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/dns.so*
-%attr(0644,root,root) %{_libdir}/%{name}/dns.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/entropy.so*
-%attr(0644,root,root) %{_libdir}/%{name}/entropy.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/exec.so*
-%attr(0644,root,root) %{_libdir}/%{name}/exec.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/hddtemp.so*
-%attr(0644,root,root) %{_libdir}/%{name}/hddtemp.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/interface.so*
-%attr(0644,root,root) %{_libdir}/%{name}/interface.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/iptables.so*
-%attr(0644,root,root) %{_libdir}/%{name}/iptables.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/irq.so*
-%attr(0644,root,root) %{_libdir}/%{name}/irq.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/load.so*
-%attr(0644,root,root) %{_libdir}/%{name}/load.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/logfile.so*
-%attr(0644,root,root) %{_libdir}/%{name}/logfile.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/mbmon.so*
-%attr(0644,root,root) %{_libdir}/%{name}/mbmon.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/memcached.so*
-%attr(0644,root,root) %{_libdir}/%{name}/memcached.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/memory.so*
-%attr(0644,root,root) %{_libdir}/%{name}/memory.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/multimeter.so*
-%attr(0644,root,root) %{_libdir}/%{name}/multimeter.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/network.so*
-%attr(0644,root,root) %{_libdir}/%{name}/network.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/nfs.so*
-%attr(0644,root,root) %{_libdir}/%{name}/nfs.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/nginx.so*
-%attr(0644,root,root) %{_libdir}/%{name}/nginx.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/ntpd.so*
-%attr(0644,root,root) %{_libdir}/%{name}/ntpd.la
-
-# FIXME!!!
-#%attr(0644,root,root) %{_libdir}/%{name}/nut.so*
-#%attr(0644,root,root) %{_libdir}/%{name}/nut.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/perl.so*
-%attr(0644,root,root) %{_libdir}/%{name}/perl.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/ping.so*
-%attr(0644,root,root) %{_libdir}/%{name}/ping.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/processes.so*
-%attr(0644,root,root) %{_libdir}/%{name}/processes.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/rrdtool.so*
-%attr(0644,root,root) %{_libdir}/%{name}/rrdtool.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/serial.so*
-%attr(0644,root,root) %{_libdir}/%{name}/serial.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/swap.so*
-%attr(0644,root,root) %{_libdir}/%{name}/swap.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/snmp.so*
-%attr(0644,root,root) %{_libdir}/%{name}/snmp.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/syslog.so*
-%attr(0644,root,root) %{_libdir}/%{name}/syslog.la
-
-# FIXME!!!
-#%attr(0644,root,root) %{_libdir}/%{name}/tape.so*
-#%attr(0644,root,root) %{_libdir}/%{name}/tape.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/tcpconns.so*
-%attr(0644,root,root) %{_libdir}/%{name}/tcpconns.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/unixsock.so*
-%attr(0644,root,root) %{_libdir}/%{name}/unixsock.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/users.so*
-%attr(0644,root,root) %{_libdir}/%{name}/users.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/vserver.so*
-%attr(0644,root,root) %{_libdir}/%{name}/vserver.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/wireless.so*
-%attr(0644,root,root) %{_libdir}/%{name}/wireless.la
-
-%attr(0644,root,root) %{_datadir}/%{name}/types.db
-
-%dir /var/lib/collectd
-
-%files apache
-%attr(0644,root,root) %{_libdir}/%{name}/apache.so*
-%attr(0644,root,root) %{_libdir}/%{name}/apache.la
-
-%files email
-%attr(0644,root,root) %{_libdir}/%{name}/email.so*
-%attr(0644,root,root) %{_libdir}/%{name}/email.la
-
-%files mysql
-%attr(0644,root,root) %{_libdir}/%{name}/mysql.so*
-%attr(0644,root,root) %{_libdir}/%{name}/mysql.la
-
-%files sensors
-%attr(0644,root,root) %{_libdir}/%{name}/sensors.so*
-%attr(0644,root,root) %{_libdir}/%{name}/sensors.la
-
-%changelog
-* Wed Oct 31 2007 Iain Lea <iain@bricbrac.de> 4.2.0
-- New major release
-- Changes to support 4.2.0 (ie. contrib/collection.conf)
-
-* Mon Aug 06 2007 Kjell Randa <Kjell.Randa@broadpark.no> 4.0.6
-- New upstream version
-
-* Wed Jul 25 2007 Kjell Randa <Kjell.Randa@broadpark.no> 4.0.5
-- New major release
-- Changes to support 4.0.5
-
-* Wed Jan 11 2007 Iain Lea <iain@bricbrac.de> 3.11.0-0
-- fixed spec file to build correctly on fedora core
-- added improved init.d script to work with chkconfig
-- added %post and %postun to call chkconfig automatically
-
-* Sun Jul 09 2006 Florian octo Forster <octo@verplant.org> 3.10.0-1
-- New upstream version
-
-* Tue Jun 25 2006 Florian octo Forster <octo@verplant.org> 3.9.4-1
-- New upstream version
-
-* Tue Jun 01 2006 Florian octo Forster <octo@verplant.org> 3.9.3-1
-- New upstream version
-
-* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.9.2-1
-- New upstream version
-
-* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.8.5-1
-- New upstream version
-
-* Fri Apr 21 2006 Florian octo Forster <octo@verplant.org> 3.9.1-1
-- New upstream version
-
-* Fri Apr 14 2006 Florian octo Forster <octo@verplant.org> 3.9.0-1
-- New upstream version
-- Added the `apache' package.
-
-* Thu Mar 14 2006 Florian octo Forster <octo@verplant.org> 3.8.2-1
-- New upstream version
-
-* Thu Mar 13 2006 Florian octo Forster <octo@verplant.org> 3.8.1-1
-- New upstream version
-
-* Thu Mar 09 2006 Florian octo Forster <octo@verplant.org> 3.8.0-1
-- New upstream version
-
-* Sat Feb 18 2006 Florian octo Forster <octo@verplant.org> 3.7.2-1
-- Include `tape.so' so the build doesn't terminate because of missing files..
-- New upstream version
-
-* Sat Feb 04 2006 Florian octo Forster <octo@verplant.org> 3.7.1-1
-- New upstream version
-
-* Mon Jan 30 2006 Florian octo Forster <octo@verplant.org> 3.7.0-1
-- New upstream version
-- Removed the extra `hddtemp' package
-
-* Tue Jan 24 2006 Florian octo Forster <octo@verplant.org> 3.6.2-1
-- New upstream version
-
-* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.1-1
-- New upstream version
-
-* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.0-1
-- New upstream version
-- Added config file, `collectd.conf(5)', `df.so'
-- Added package `collectd-mysql', dependency on `mysqlclient10 | mysql'
-
-* Wed Dec 07 2005 Florian octo Forster <octo@verplant.org> 3.5.0-1
-- New upstream version
-
-* Sat Nov 26 2005 Florian octo Forster <octo@verplant.org> 3.4.0-1
-- New upstream version
-
-* Sat Nov 05 2005 Florian octo Forster <octo@verplant.org> 3.3.0-1
-- New upstream version
-
-* Tue Oct 26 2005 Florian octo Forster <octo@verplant.org> 3.2.0-1
-- New upstream version
-- Added statement to remove the `*.la' files. This fixes a problem when
- `Unpackaged files terminate build' is in effect.
-- Added `processes.so*' to the main package
-
-* Fri Oct 14 2005 Florian octo Forster <octo@verplant.org> 3.1.0-1
-- New upstream version
-- Added package `collectd-hddtemp'
-
-* Fri Sep 30 2005 Florian octo Forster <octo@verplant.org> 3.0.0-1
-- New upstream version
-- Split the package into `collectd' and `collectd-sensors'
-
-* Fri Sep 16 2005 Florian octo Forster <octo@verplant.org> 2.1.0-1
-- New upstream version
-
-* Mon Sep 10 2005 Florian octo Forster <octo@verplant.org> 2.0.0-1
-- New upstream version
-
-* Mon Aug 29 2005 Florian octo Forster <octo@verplant.org> 1.8.0-1
-- New upstream version
-
-* Sun Aug 25 2005 Florian octo Forster <octo@verplant.org> 1.7.0-1
-- New upstream version
-
-* Sun Aug 21 2005 Florian octo Forster <octo@verplant.org> 1.6.0-1
-- New upstream version
-
-* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5.1-1
-- New upstream version
-
-* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5-1
-- New upstream version
-
-* Mon Jul 11 2005 Florian octo Forster <octo@verplant.org> 1.4.2-1
-- New upstream version
-
-* Sat Jul 09 2005 Florian octo Forster <octo@verplant.org> 1.4-1
-- Built on RedHat 7.3
diff --git a/contrib/fedora/init.d-collectd b/contrib/fedora/init.d-collectd
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/bash
-#
-# collectd Startup script for the Collectd statistics gathering daemon
-# chkconfig: - 86 15
-# description: Collectd is a statistics gathering daemon used to collect \
-# system information ie. cpu, memory, disk, network
-# processname: collectd
-# config: /etc/collectd.conf
-# config: /etc/sysconfig/collectd
-# pidfile: /var/run/collectd.pid
-
-# Source function library.
-. /etc/init.d/functions
-
-RETVAL=0
-ARGS=""
-prog="collectd"
-CONFIG=/etc/collectd.conf
-
-if [ -r /etc/default/$prog ]; then
- . /etc/default/$prog
-fi
-
-start () {
- echo -n $"Starting $prog: "
- if [ -r "$CONFIG" ]
- then
- daemon /usr/sbin/collectd -C "$CONFIG"
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
- fi
-}
-stop () {
- echo -n $"Stopping $prog: "
- killproc $prog
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
-}
-# See how we were called.
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status $prog
- ;;
- restart|reload)
- stop
- start
- ;;
- condrestart)
- [ -f /var/lock/subsys/$prog ] && stop && start || :
- ;;
- *)
- echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
- exit 1
-esac
-
-exit $?
-
-# vim:syntax=sh
index 9d491ff818e88986ca67046607636839019d22d1..2252181335cff9c2e116cc962b0836c6b61d1e22 100644 (file)
%{?el7:%global _has_atasmart 1}
%{?el7:%global _has_hiredis 1}
%{?el7:%global _has_asm_msr_index 1}
+%{?el7:%global _has_libmosquitto 1}
# plugins enabled by default
%define with_aggregation 0%{!?_without_aggregation:1}
%define with_memory 0%{!?_without_memory:1}
%define with_multimeter 0%{!?_without_multimeter:1}
%define with_modbus 0%{!?_without_modbus:0%{?_has_libmodbus}}
+%define with_mqtt 0%{!?_without_mqtt:0%{?_has_libmosquitto}}
%define with_mysql 0%{!?_without_mysql:1}
%define with_netlink 0%{!?_without_netlink:0%{?_has_iproute}}
%define with_network 0%{!?_without_network:1}
%define with_write_mongodb 0%{!?_without_write_mongodb:0}
# plugin xmms disabled, requires xmms
%define with_xmms 0%{!?_without_xmms:0}
+# plugin zone disabled, requires Solaris
+%define with_zone 0%{!?_without_zone:0}
Summary: statistics collection and monitoring daemon
Name: collectd
handlers and database traffic.
%endif
+%if %{with_mqtt}
+%package mqtt
+Summary: mqtt plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: mosquitto-devel
+%description mqtt
+The MQTT plugin publishes and subscribes to MQTT topics.
+%endif
+
%if %{with_netlink}
%package netlink
Summary: netlink plugin for collectd
%define _with_multimeter --disable-multimeter
%endif
+%if %{with_mqtt}
+%define _with_mqtt --enable-mqtt
+%else
+%define _with_mqtt --disable-mqtt
+%endif
+
%if %{with_mysql}
%define _with_mysql --enable-mysql
%else
%define _with_zfs_arc --disable-zfs_arc
%endif
+%if %{with_zone}
+%define _with_zone --enable-zone
+%else
+%define _with_zone --disable-zone
+%endif
+
%if %{with_zookeeper}
%define _with_zookeeper --enable-zookeeper
%else
%{?_with_mic} \
%{?_with_modbus} \
%{?_with_multimeter} \
+ %{?_with_mqtt} \
%{?_with_mysql} \
%{?_with_netapp} \
%{?_with_netlink} \
%{?_with_write_redis} \
%{?_with_xmms} \
%{?_with_zfs_arc} \
+ %{?_with_zone} \
%{?_with_zookeeper} \
%{?_with_irq} \
%{?_with_load} \
%{_libdir}/%{name}/modbus.so
%endif
+%if %{with_mqtt}
+%files mqtt
+%{_libdir}/%{name}/mqtt.so
+%endif
+
%if %{with_mysql}
%files mysql
%{_libdir}/%{name}/mysql.so
%doc contrib/
%changelog
+#* TODO: next feature release changelog
+#- New upstream version
+#- New plugins enabled by default: mqtt
+#- New plugins disabled by default: zone
+#
* Wed May 27 2015 Marc Fournier <marc.fournier@camptocamp.com> 5.5.0-1
- New upstream version
- New plugins enabled by default: ceph, drbd, log_logstash, write_tsdb, smart,
diff --git a/src/Makefile.am b/src/Makefile.am
index 07ffdda9ce58ec20107893a4513bef2d144c2ce1..d0bf5463d125b58b83d461b347961ff25e0a3208 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
PLUGIN_LDFLAGS = -module -avoid-version -export-symbols-regex '\<module_register\>'
-if COMPILER_IS_GCC
-AM_CFLAGS = -Wall -Werror
-endif
-
AM_CPPFLAGS = -I$(srcdir)/daemon
AM_CPPFLAGS += -DPREFIX='"${prefix}"'
AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
AUTOMAKE_OPTIONS = subdir-objects
-noinst_LTLIBRARIES = libmount.la liblookup.la
+noinst_LTLIBRARIES =
+check_PROGRAMS =
+TESTS =
-libmount_la_SOURCES = utils_mount.c utils_mount.h
-libmount_la_LIBADD = daemon/libcommon.la
+noinst_LTLIBRARIES += liblatency.la
+liblatency_la_SOURCES = utils_latency.c utils_latency.h
+check_PROGRAMS += test_utils_latency
+TESTS += test_utils_latency
+test_utils_latency_SOURCES = utils_latency_test.c testing.h
+test_utils_latency_LDADD = liblatency.la daemon/libcommon.la daemon/libplugin_mock.la -lm
+noinst_LTLIBRARIES += liblookup.la
liblookup_la_SOURCES = utils_vl_lookup.c utils_vl_lookup.h
-liblookup_la_LIBADD = daemon/libavltree.la daemon/libcommon.la
+liblookup_la_LIBADD = daemon/libavltree.la
+check_PROGRAMS += test_utils_vl_lookup
+TESTS += test_utils_vl_lookup
+test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h
+test_utils_vl_lookup_LDADD = liblookup.la daemon/libcommon.la daemon/libplugin_mock.la
+if BUILD_WITH_LIBKSTAT
+test_utils_vl_lookup_LDADD += -lkstat
+endif
+
+noinst_LTLIBRARIES += libmount.la
+libmount_la_SOURCES = utils_mount.c utils_mount.h
+check_PROGRAMS += test_utils_mount
+TESTS += test_utils_mount
+test_utils_mount_SOURCES = utils_mount_test.c testing.h
+test_utils_mount_LDADD = libmount.la daemon/libcommon.la daemon/libplugin_mock.la
+if BUILD_WITH_LIBKSTAT
+test_utils_mount_LDADD += -lkstat
+endif
sbin_PROGRAMS = collectdmon
bin_PROGRAMS = collectd-nagios collectdctl collectd-tg
collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la
collectd_tg_SOURCES = collectd-tg.c
-collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
collectd_tg_LDADD = daemon/libheap.la
if BUILD_WITH_LIBSOCKET
collectd_tg_LDADD += -lsocket
if BUILD_WITH_LIBUDEV
disk_la_LIBADD += -ludev
endif
+if BUILD_FREEBSD
+disk_la_LIBADD += -ldevstat -lgeom
+endif
if BUILD_WITH_PERFSTAT
disk_la_LIBADD += -lperfstat
endif
ipvs_la_SOURCES = ipvs.c
if IP_VS_H_NEEDS_KERNEL_CFLAGS
ipvs_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
+else
+ipvs_la_CFLAGS = $(AM_CFLAGS)
endif
ipvs_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
modbus_la_LIBADD = $(BUILD_WITH_LIBMODBUS_LIBS)
endif
+if BUILD_PLUGIN_MQTT
+pkglib_LTLIBRARIES += mqtt.la
+mqtt_la_SOURCES = mqtt.c
+mqtt_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+mqtt_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMOSQUITTO_CPPFLAGS)
+mqtt_la_LIBADD = $(BUILD_WITH_LIBMOSQUITTO_LIBS)
+endif
+
if BUILD_PLUGIN_MULTIMETER
pkglib_LTLIBRARIES += multimeter.la
multimeter_la_SOURCES = multimeter.c
if BUILD_PLUGIN_STATSD
pkglib_LTLIBRARIES += statsd.la
-statsd_la_SOURCES = statsd.c \
- utils_latency.h utils_latency.c
+statsd_la_SOURCES = statsd.c
statsd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-statsd_la_LIBADD = -lpthread -lm
+statsd_la_LIBADD = liblatency.la -lpthread -lm
endif
if BUILD_PLUGIN_SWAP
BUILT_SOURCES += $(dist_man_MANS)
+if BUILD_PLUGIN_ZONE
+pkglib_LTLIBRARIES += zone.la
+zone_la_SOURCES = zone.c
+zone_la_CFLAGS = $(AM_CFLAGS)
+zone_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
dist_man_MANS = collectd.1 \
collectd.conf.5 \
collectd-email.5 \
rm -f $(DESTDIR)$(sysconfdir)/collectd.conf
rm -f $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
-check_PROGRAMS = test_utils_mount test_utils_vl_lookup
-
-test_utils_mount_SOURCES = utils_mount_test.c testing.h
-test_utils_mount_LDADD = libmount.la daemon/libplugin_mock.la
-
-test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h
-test_utils_vl_lookup_LDADD = liblookup.la daemon/libplugin_mock.la
-TESTS = test_utils_mount test_utils_vl_lookup
diff --git a/src/apache.c b/src/apache.c
index 8910675ad06a67e8f80a322ef75d991123a48b0c..41b807af7541fb748634d2b5c3660198659dc43a 100644 (file)
--- a/src/apache.c
+++ b/src/apache.c
status = plugin_register_complex_read (/* group = */ NULL,
/* name = */ callback_name,
/* callback = */ apache_read_host,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user_data = */ &ud);
}
if (st->timeout >= 0)
curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS, (long) st->timeout);
else
- curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
diff --git a/src/apcups.c b/src/apcups.c
index 281bf9803bdd6e6a84086b152f14b623961337b7..29d58c3ad6e0a2d1b2038bf6433d078113fe0497 100644 (file)
--- a/src/apcups.c
+++ b/src/apcups.c
/*
* collectd - src/apcups.c
- * Copyright (C) 2006-2012 Florian octo Forster
+ * Copyright (C) 2006-2015 Florian octo Forster
* Copyright (C) 2006 Anthony Gialluca <tonyabg at charter.net>
* Copyright (C) 2000-2004 Kern Sibbald
* Copyright (C) 1996-1999 Andre M. Hedrick <andre at suse.com>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NETDB_H
# include <netdb.h>
#endif
# include <netinet/in.h>
#endif
-#define NISPORT 3551
-#define MAXSTRING 256
-#define MODULE_NAME "apcups"
+#ifndef APCUPS_DEFAULT_NODE
+# define APCUPS_DEFAULT_NODE "localhost"
+#endif
-#define APCUPS_DEFAULT_HOST "localhost"
+#ifndef APCUPS_DEFAULT_SERVICE
+# define APCUPS_DEFAULT_SERVICE "3551"
+#endif
/*
* Private data types
* Private variables
*/
/* Default values for contacting daemon */
-static char *conf_host = NULL;
-static int conf_port = NISPORT;
+static char *conf_node = NULL;
+static char *conf_service = NULL;
/* Defaults to false for backwards compatibility. */
static _Bool conf_report_seconds = 0;
+static _Bool conf_persistent_conn = 1;
static int global_sockfd = -1;
static int count_retries = 0;
static int count_iterations = 0;
-static _Bool close_socket = 0;
-
-static const char *config_keys[] =
-{
- "Host",
- "Port",
- "ReportSeconds"
-};
-static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
static int net_shutdown (int *fd)
{
* Returns -1 on error
* Returns socket file descriptor otherwise
*/
-static int net_open (char *host, int port)
+static int net_open (char const *node, char const *service)
{
int sd;
int status;
- char port_str[8];
struct addrinfo ai_hints;
struct addrinfo *ai_return;
struct addrinfo *ai_list;
- assert ((port > 0x00000000) && (port <= 0x0000FFFF));
-
- /* Convert the port to a string */
- ssnprintf (port_str, sizeof (port_str), "%i", port);
-
/* Resolve name */
- memset ((void *) &ai_hints, '\0', sizeof (ai_hints));
- ai_hints.ai_family = AF_INET; /* XXX: Change this to `AF_UNSPEC' if apcupsd can handle IPv6 */
+ memset (&ai_hints, 0, sizeof (ai_hints));
+ /* TODO: Change this to `AF_UNSPEC' if apcupsd can handle IPv6 */
+ ai_hints.ai_family = AF_INET;
ai_hints.ai_socktype = SOCK_STREAM;
- status = getaddrinfo (host, port_str, &ai_hints, &ai_return);
+ status = getaddrinfo (node, service, &ai_hints, &ai_return);
if (status != 0)
{
char errbuf[1024];
DEBUG ("apcups plugin: Done opening a socket %i", sd);
return (sd);
-} /* int net_open (char *host, char *service, int port) */
+} /* int net_open */
/*
* Receive a message from the other end. Each message consists of
}
/* Get and print status from apcupsd NIS server */
-static int apc_query_server (char *host, int port,
+static int apc_query_server (char const *node, char const *service,
struct apc_detail_s *apcups_detail)
{
int n;
{
if (global_sockfd < 0)
{
- global_sockfd = net_open (host, port);
+ global_sockfd = net_open (node, service);
if (global_sockfd < 0)
{
ERROR ("apcups plugin: Connecting to the "
"first %i iterations. Will close the socket "
"in future iterations.",
count_retries, count_iterations);
- close_socket = 1;
+ conf_persistent_conn = 0;
}
while ((n = net_recv (&global_sockfd, recvline, sizeof (recvline) - 1)) > 0)
{
- assert ((unsigned int)n < sizeof (recvline));
- recvline[n] = '\0';
+ assert ((size_t)n < sizeof (recvline));
+ recvline[n] = 0;
#if APCMAIN
printf ("net_recv = `%s';\n", recvline);
#endif /* if APCMAIN */
+ if (strncmp ("END APC", recvline, strlen ("END APC")) == 0)
+ break;
+
toksaveptr = NULL;
tokptr = strtok_r (recvline, " :\t", &toksaveptr);
while (tokptr != NULL)
}
status = errno; /* save errno, net_shutdown() may re-set it. */
- if (close_socket)
+ if (!conf_persistent_conn)
net_shutdown (&global_sockfd);
if (n < 0)
return (0);
}
-static int apcups_config (const char *key, const char *value)
+static int apcups_config (oconfig_item_t *ci)
{
- if (strcasecmp (key, "host") == 0)
- {
- if (conf_host != NULL)
- {
- free (conf_host);
- conf_host = NULL;
- }
- if ((conf_host = strdup (value)) == NULL)
- return (1);
- }
- else if (strcasecmp (key, "Port") == 0)
- {
- int port_tmp = atoi (value);
- if (port_tmp < 1 || port_tmp > 65535)
- {
- WARNING ("apcups plugin: Invalid port: %i", port_tmp);
- return (1);
- }
- conf_port = port_tmp;
- }
- else if (strcasecmp (key, "ReportSeconds") == 0)
+ int i;
+
+ for (i = 0; i < ci->children_num; i++)
{
- if (IS_TRUE (value))
- conf_report_seconds = 1;
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp (child->key, "Host") == 0)
+ cf_util_get_string (child, &conf_node);
+ else if (strcasecmp (child->key, "Port") == 0)
+ cf_util_get_service (child, &conf_service);
+ else if (strcasecmp (child->key, "ReportSeconds") == 0)
+ cf_util_get_boolean (child, &conf_report_seconds);
+ else if (strcasecmp (child->key, "PersistentConnection") == 0)
+ cf_util_get_boolean (child, &conf_persistent_conn);
else
- conf_report_seconds = 0;
- }
- else
- {
- return (-1);
+ ERROR ("apcups plugin: Unknown config option \"%s\".", child->key);
}
+
return (0);
-}
+} /* int apcups_config */
static void apc_submit_generic (char *type, char *type_inst, double value)
{
apcups_detail.itemp = -300.0;
apcups_detail.linefreq = -1.0;
- status = apc_query_server (conf_host == NULL
- ? APCUPS_DEFAULT_HOST
- : conf_host,
- conf_port, &apcups_detail);
+ status = apc_query_server ((conf_node == NULL) ? APCUPS_DEFAULT_NODE : conf_node,
+ (conf_service == NULL) ? APCUPS_DEFAULT_SERVICE : conf_service,
+ &apcups_detail);
/*
* if we did not connect then do not bother submitting
*/
if (status != 0)
{
- DEBUG ("apcups plugin: apc_query_server (%s, %i) = %i",
- conf_host == NULL
- ? APCUPS_DEFAULT_HOST
- : conf_host,
- conf_port, status);
+ DEBUG ("apcups plugin: apc_query_server (%s, %s) = %i",
+ (conf_node == NULL) ? APCUPS_DEFAULT_NODE : conf_node,
+ (conf_service == NULL) ? APCUPS_DEFAULT_SERVICE : conf_service,
+ status);
return (-1);
}
void module_register (void)
{
- plugin_register_config ("apcups", apcups_config, config_keys,
- config_keys_num);
+ plugin_register_complex_config ("apcups", apcups_config);
plugin_register_read ("apcups", apcups_read);
plugin_register_shutdown ("apcups", apcups_shutdown);
} /* void module_register */
diff --git a/src/ascent.c b/src/ascent.c
index 11175af5e6104afa7b39291fd77fd45441a0cb64..2ba3c772d5f9f8116f4100b6f3484756cfbb8ef7 100644 (file)
--- a/src/ascent.c
+++ b/src/ascent.c
if (timeout != NULL)
curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, atol(timeout));
else
- curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
diff --git a/src/barometer.c b/src/barometer.c
index a6d98354d7ae2857c9be395e0bb81254c3c2d7cb..c5e7f77b09380acdb31631d3c237cb71fc71013c 100644 (file)
--- a/src/barometer.c
+++ b/src/barometer.c
gauge_t * values = NULL; /**< rate values */
size_t values_num = 0; /**< number of rate values */
- int i;
+ size_t i;
gauge_t values_history[REF_TEMP_AVG_NUM];
for(i=0; i<values_num; ++i)
{
- DEBUG ("barometer: get_reference_temperature - rate %d: %lf **",
- i,
- values[i]);
+ DEBUG ("barometer: get_reference_temperature - rate %zu: %lf **",
+ i, values[i]);
if(!isnan(values[i]))
{
avg_sum += values[i];
for(i=0; i<REF_TEMP_AVG_NUM*list->num_values; ++i)
{
- DEBUG ("barometer: get_reference_temperature - history %d: %lf",
- i,
- values_history[i]);
+ DEBUG ("barometer: get_reference_temperature - history %zu: %lf",
+ i, values_history[i]);
if(!isnan(values_history[i]))
{
avg_sum += values_history[i];
for(i=0; i<values_num; ++i)
{
- DEBUG ("barometer: get_reference_temperature - rate last %d: %lf **",
- i,
- values[i]);
+ DEBUG ("barometer: get_reference_temperature - rate last %zu: %lf **",
+ i, values[i]);
if(!isnan(values[i]))
{
avg_sum += values[i];
diff --git a/src/bind.c b/src/bind.c
index 32b0f16e21f50311d530f934f72964076dfee0ee..06b4ace00393e2321fc7bef9762f4b320c582aa5 100644 (file)
--- a/src/bind.c
+++ b/src/bind.c
curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 50L);
#ifdef HAVE_CURLOPT_TIMEOUT_MS
curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (timeout >= 0) ?
- (long) timeout : CDTIME_T_TO_MS(plugin_get_interval()));
+ (long) timeout : (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
diff --git a/src/ceph.c b/src/ceph.c
index d928a7ba4b5db1d71e87449f635783e44000f621..419ca6e56170758c5c05dea2e1e20994b53b2ff3 100644 (file)
--- a/src/ceph.c
+++ b/src/ceph.c
#include <stdlib.h>
#include <string.h>
#include <strings.h>
-#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/un.h>
diff --git a/src/collectd-nagios.c b/src/collectd-nagios.c
index 8b0f867949e1f09c1b8f015598c8dd08e8d8925c..b17e47e2e1618949772dd3ccfd3db592ddf643ca 100644 (file)
--- a/src/collectd-nagios.c
+++ b/src/collectd-nagios.c
static _Bool nan_is_error_g = 0;
static char **match_ds_g = NULL;
-static int match_ds_num_g = 0;
+static size_t match_ds_num_g = 0;
/* `strdup' is an XSI extension. I don't want to pull in all of XSI just for
* that, so here's an own implementation.. It's easy enough. The GCC attributes
return (RET_UNKNOWN);
}
- for (i = 0; i < (size_t) match_ds_num_g; i++)
+ for (i = 0; i < match_ds_num_g; i++)
{
size_t j;
diff --git a/src/collectd-tg.c b/src/collectd-tg.c
index 45e788c22206c5c733d696bc6ab778ab732643ec..9bd65bca8936c7175b7981dd0d2d8f72b008208b 100644 (file)
--- a/src/collectd-tg.c
+++ b/src/collectd-tg.c
# include "config.h"
#endif
-#ifndef _ISOC99_SOURCE
-# define _ISOC99_SOURCE
-#endif
-
-#ifndef _POSIX_C_SOURCE
-# define _POSIX_C_SOURCE 200809L
-#endif
-
-#ifndef _XOPEN_SOURCE
-# define _XOPEN_SOURCE 700
-#endif
-
#if !__GNUC__
# define __attribute__(x) /**/
#endif
#include <time.h>
#include <signal.h>
#include <errno.h>
+#include <math.h>
+#include <sys/time.h>
#include "utils_heap.h"
loop = 0;
} /* }}} void signal_handler */
+#if HAVE_CLOCK_GETTIME
+static double dtime (void) /* {{{ */
+{
+ struct timespec ts = { 0 };
+
+ if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0)
+ perror ("clock_gettime");
+
+ return ((double) ts.tv_sec) + (((double) ts.tv_nsec) / 1e9);
+} /* }}} double dtime */
+#else
+/* Work around for Mac OS X which doesn't have clock_gettime(2). *sigh* */
+static double dtime (void) /* {{{ */
+{
+ struct timeval tv = { 0 };
+
+ if (gettimeofday (&tv, /* timezone = */ NULL) != 0)
+ perror ("gettimeofday");
+
+ return ((double) tv.tv_sec) + (((double) tv.tv_usec) / 1e6);
+} /* }}} double dtime */
+#endif
+
static int compare_time (const void *v0, const void *v1) /* {{{ */
{
const lcc_value_list_t *vl0 = v0;
host_num = get_boundet_random (0, conf_num_hosts);
vl->interval = conf_interval;
- vl->time = 1.0 + time (NULL)
+ vl->time = 1.0 + dtime ()
+ (host_num % (1 + (int) vl->interval));
if (get_boundet_random (0, 2) == 0)
if (vl->values_types[0] == LCC_TYPE_GAUGE)
vl->values[0].gauge = 100.0 * ((gauge_t) random ()) / (((gauge_t) RAND_MAX) + 1.0);
else
- vl->values[0].derive += get_boundet_random (0, 100);
+ vl->values[0].derive += (derive_t) get_boundet_random (0, 100);
status = lcc_network_values_send (net, vl);
if (status != 0)
int main (int argc, char **argv) /* {{{ */
{
int i;
- time_t last_time;
+ double last_time;
int values_sent = 0;
read_options (argc, argv);
printf ("%i values have been sent.\n", values_sent);
/* Check if we need to sleep */
- time_t now = time (NULL);
+ double now = dtime ();
while (now < vl->time)
{
/* 1 / 100 second */
struct timespec ts = { 0, 10000000 };
+
+ ts.tv_sec = (time_t) now;
+ ts.tv_nsec = (long) ((now - ((double) ts.tv_sec)) * 1e9);
+
nanosleep (&ts, /* remaining = */ NULL);
- now = time (NULL);
+ now = dtime ();
if (!loop)
break;
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
index 729aa032d0caa2bd4df5711acd2b4af0b50a4839..61c01f944bfc4477893d58936c14f868ccab1edc 100644 (file)
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
@BUILD_PLUGIN_MEMORY_TRUE@@BUILD_PLUGIN_MEMORY_TRUE@LoadPlugin memory
#@BUILD_PLUGIN_MIC_TRUE@LoadPlugin mic
#@BUILD_PLUGIN_MODBUS_TRUE@LoadPlugin modbus
+#@BUILD_PLUGIN_MQTT_TRUE@LoadPlugin mqtt
#@BUILD_PLUGIN_MULTIMETER_TRUE@LoadPlugin multimeter
#@BUILD_PLUGIN_MYSQL_TRUE@LoadPlugin mysql
#@BUILD_PLUGIN_NETAPP_TRUE@LoadPlugin netapp
#@BUILD_PLUGIN_WRITE_TSDB_TRUE@LoadPlugin write_tsdb
#@BUILD_PLUGIN_XMMS_TRUE@LoadPlugin xmms
#@BUILD_PLUGIN_ZFS_ARC_TRUE@LoadPlugin zfs_arc
+#@BUILD_PLUGIN_ZONE_TRUE@LoadPlugin zone
#@BUILD_PLUGIN_ZOOKEEPER_TRUE@LoadPlugin zookeeper
##############################################################################
# Host "localhost"
# Port "3551"
# ReportSeconds true
+# PersistentConnection true
#</Plugin>
#<Plugin aquaero>
# </Host>
#</Plugin>
+#<Plugin mqtt>
+# <Publish "name">
+# Host "localhost"
+# Port 1883
+# ClientId "localhost"
+# User "user"
+# Password "secret"
+# QoS 0
+# Prefix "collectd"
+# StoreRates true
+# Retain false
+# </Publish>
+# <Subscribe "name">
+# Host "localhost"
+# Port 1883
+# ClientId "localhost"
+# User "user"
+# Password "secret"
+# QoS 2
+# Topic "collectd/#"
+# CleanSession true
+# </Subscribe>
+#</Plugin>
+
#<Plugin mysql>
# <Database db_name>
# Host "database.serv.er"
# Host "localhost"
# Port "6379"
# Timeout 1000
+# Prefix "collectd/"
# </Node>
#</Plugin>
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 8189e9734bc098225626157a3ebbab0e90ef16d3..8a508089d2589ba35994f159fef1098d7c128563 100644 (file)
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
global B<Interval> setting. If a plugin provides own support for specifying an
interval, that setting will take precedence.
+=item B<FlushInterval> I<Seconds>
+
+Specifies the the interval, in seconds, to call the flush callback if it's
+defined in this plugin. By default, this is disabled
+
+=item B<FlushTimeout> I<Seconds>
+
+Specifies the value of the timeout argument of the flush callback.
+
=back
=item B<AutoLoadPlugin> B<false>|B<true>
The I<AMQP plugin> can be used to communicate with other instances of
I<collectd> or third party applications using an AMQP message broker. Values
are sent to or received from the broker, which handles routing, queueing and
-possibly filtering or messages.
+possibly filtering out messages.
+
+B<Synopsis:>
<Plugin "amqp">
# Send values to an AMQP broker
TCP-Port to connect to. Defaults to B<3551>.
-=item B<ReportSeconds> B<true|false>
+=item B<ReportSeconds> B<true>|B<false>
If set to B<true>, the time reported in the C<timeleft> metric will be
converted to seconds. This is the recommended setting. If set to B<false>, the
default for backwards compatibility, the time will be reported in minutes.
+=item B<PersistentConnection> B<true>|B<false>
+
+By default, the plugin will try to keep the connection to UPS open between
+reads. Since this appears to be somewhat brittle (I<apcupsd> appears to close
+the connection due to inactivity quite quickly), the plugin will try to detect
+this problem and switch to an open-read-close mode in such cases.
+
+You can instruct the plugin to close the connection after each read by setting
+this option to B<false>.
+
=back
=head2 Plugin C<aquaero>
</Query>
<Database "product_information">
Driver "mysql"
+ Interval 120
DriverOption "host" "localhost"
DriverOption "username" "collectd"
DriverOption "password" "aZo6daiw"
=over 4
+=item B<Interval> I<Interval>
+
+Sets the interval (in seconds) in which the values will be collected from this
+database. By default the global B<Interval> setting will be used.
+
=item B<Driver> I<Driver>
Specifies the driver to use to connect to the database. In many cases those
=back
+=head2 Plugin C<mqtt>
+
+The I<MQTT plugin> can send metrics to MQTT (B<Publish> blocks) and receive
+values from MQTT (B<Subscribe> blocks).
+
+B<Synopsis:>
+
+ <Plugin mqtt>
+ <Publish "name">
+ Host "mqtt.example.com"
+ Prefix "collectd"
+ </Publish>
+ <Subscribe "name">
+ Host "mqtt.example.com"
+ Topic "collectd/#"
+ </Subscribe>
+ </Plugin>
+
+The plugin's configuration is in B<Publish> and/or B<Subscribe> blocks,
+configuring the sending and receiving direction respectively. The plugin will
+register a write callback named C<mqtt/I<name>> where I<name> is the string
+argument given to the B<Publish> block. Both types of blocks share many but not
+all of the following options. If an option is valid in only one of the blocks,
+it will be mentioned explicitly.
+
+B<Options:>
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname of the MQTT broker to connect to.
+
+=item B<Port> I<Service>
+
+Port number or service name of the MQTT broker to connect to.
+
+=item B<User> I<UserName>
+
+Username used when authenticating to the MQTT broker.
+
+=item B<Password> I<Password>
+
+Password used when authenticating to the MQTT broker.
+
+=item B<ClientId> I<ClientId>
+
+MQTT client ID to use. Defaults to the hostname used by I<collectd>.
+
+=item B<QoS> [B<0>-B<2>]
+
+Sets the I<Quality of Service>, with the values C<0>, C<1> and C<2> meaning:
+
+=over 4
+
+=item B<0>
+
+At most once
+
+=item B<1>
+
+At least once
+
+=item B<2>
+
+Exactly once
+
+=back
+
+In B<Publish> blocks, this option determines the QoS flag set on outgoing
+messages and defaults to B<0>. In B<Subscribe> blocks, determines the maximum
+QoS setting the client is going to accept and defaults to B<2>. If the QoS flag
+on a message is larger than the maximum accepted QoS of a subscriber, the
+message's QoS will be downgraded.
+
+=item B<Prefix> I<Prefix> (Publish only)
+
+This plugin will use one topic per I<value list> which will looks like a path.
+I<Prefix> is used as the first path element and defaults to B<collectd>.
+
+An example topic name would be:
+
+ collectd/cpu-0/cpu-user
+
+=item B<Retain> B<false>|B<true> (Publish only)
+
+Controls whether the MQTT broker will retain (keep a copy of) the last message
+sent to each topic and deliver it to new subscribers. Defaults to B<false>.
+
+=item B<StoreRates> B<true>|B<false> (Publish only)
+
+Controls whether C<DERIVE> and C<COUNTER> metrics are converted to a I<rate>
+before sending. Defaults to B<true>.
+
+=item B<CleanSession> B<true>|B<false> (Subscribe only)
+
+Controls whether the MQTT "cleans" the session up after the subscriber
+disconnects or if it maintains the subscriber's subscriptions and all messages
+that arrive while the subscriber is disconnected. Defaults to B<true>.
+
+=item B<Topic> I<TopicName> (Subscribe only)
+
+Configures the topic(s) to subscribe to. You can use the single level C<+> and
+multi level C<#> wildcards. Defaults to B<collectd/#>, i.e. all topics beneath
+the B<collectd> branch.
+
+=back
+
=head2 Plugin C<mysql>
The C<mysql plugin> requires B<mysqlclient> to be installed. It connects to
Sets the URL to use to connect to the I<OpenLDAP> server. This option is
I<mandatory>.
+=item B<BindDN> I<BindDN>
+
+Name in the form of an LDAP distinguished name intended to be used for
+authentication. Defaults to empty string to establish an anonymous authorization.
+
+=item B<Password> I<Password>
+
+Password for simple bind authentication. If this option is not set,
+unauthenticated bind operation is used.
+
=item B<StartTLS> B<true|false>
Defines whether TLS must be used when connecting to the I<OpenLDAP> server.
allows to "group" several processes together. I<name> must not contain
slashes.
+=item B<CollectContextSwitch> I<Boolean>
+
+Collect context switch of the process.
+
=back
=head2 Plugin C<protocols>
B<address> means use the interface's mac address. This is useful since the
interface path might change between reboots of a guest or across migrations.
-=item B<PluginInstanceFormat> B<name|uuid>
+=item B<PluginInstanceFormat> B<name|uuid|none>
When the virt plugin logs data, it sets the plugin_instance of the collected
-data according to this setting. The default is to use the guest name as provided
-by the hypervisor, which is equal to setting B<name>.
+data according to this setting. The default is to not set the plugin_instance.
+B<name> means use the guest's name as provided by the hypervisor.
B<uuid> means use the guest's UUID.
-You can also specify combinations of these fields. For example B<name uuid>
-means to concatenate the guest name and UUID (with a literal colon character
-between, thus I<"foo:1234-1234-1234-1234">).
+You can also specify combinations of the B<name> and B<uuid> fields.
+For example B<name uuid> means to concatenate the guest name and UUID
+(with a literal colon character between, thus I<"foo:1234-1234-1234-1234">).
=back
@@ -7343,6 +7492,10 @@ complete. When this limit is reached, the POST operation will be aborted, and
all the data in the current send buffer will probably be lost. Defaults to 0,
which means the connection never times out.
+=item B<LogHttpError> B<false>|B<true>
+
+Enables printing of HTTP error code to log. Turned off by default.
+
The C<write_http> plugin regularly submits the collected values to the HTTP
server. How frequently this happens depends on how much data you are collecting
and the size of B<BufferSize>. The optimal value to set B<Timeout> to is
Host "localhost"
Port "6379"
Timeout 1000
+ Prefix "collectd/"
+ Database 1
+ MaxSetSize -1
+ StoreRates true
</Node>
</Plugin>
Values are submitted to I<Sorted Sets>, using the metric name as the key, and
the timestamp as the score. Retrieving a date range can then be done using the
C<ZRANGEBYSCORE> I<Redis> command. Additionally, all the identifiers of these
-I<Sorted Sets> are kept in a I<Set> called C<collectd/values> and can be
-retrieved using the C<SMEMBERS> I<Redis> command. See
+I<Sorted Sets> are kept in a I<Set> called C<collectd/values> (or
+C<${prefix}/values> if the B<Prefix> option was specified) and can be retrieved
+using the C<SMEMBERS> I<Redis> command. You can specify the database to use
+with the B<Database> parameter (default is C<0>). See
L<http://redis.io/commands#sorted_set> and L<http://redis.io/commands#set> for
details.
The B<Timeout> option sets the socket connection timeout, in milliseconds.
+=item B<Prefix> I<Prefix>
+
+Prefix used when constructing the name of the I<Sorted Sets> and the I<Set>
+containing all metrics. Defaults to C<collectd/>, so metrics will have names
+like C<collectd/cpu-0/cpu-user>. When setting this to something different, it
+is recommended but not required to include a trailing slash in I<Prefix>.
+
+=item B<Database> I<Index>
+
+This index selects the redis database to use for writing operations. Defaults
+to C<0>.
+
+=item B<MaxSetSize> I<Items>
+
+The B<MaxSetSize> option limits the number of items that the I<Sorted Sets> can
+hold. Negative values for I<Items> sets no limit, which is the default behavior.
+
+=item B<StoreRates> B<true>|B<false>
+
+If set to B<true> (the default), convert counter values to rates. If set to
+B<false> counter values are stored as is, i.e. as an increasing integer number.
+
=back
=head2 Plugin C<write_riemann>
diff --git a/src/collectdctl.c b/src/collectdctl.c
index 8357ce841838cad2f85238b5bbe3ba1758e1db43..febc99833aaa917f084e4d606e34a84c70b90fb4 100644 (file)
--- a/src/collectdctl.c
+++ b/src/collectdctl.c
return count;
} /* count_chars */
-static int array_grow (void **array, int *array_len, size_t elem_size)
+static int array_grow (void **array, size_t *array_len, size_t elem_size)
{
void *tmp;
int timeout = -1;
lcc_identifier_t *identifiers = NULL;
- int identifiers_num = 0;
+ size_t identifiers_num = 0;
char **plugins = NULL;
- int plugins_num = 0;
+ size_t plugins_num = 0;
int status;
int i;
values_types[values_len] = LCC_TYPE_GAUGE;
}
else { /* integer */
- values[values_len].counter = strtol (value, &endptr, 0);
+ values[values_len].counter = (counter_t) strtoull (value, &endptr, 0);
values_types[values_len] = LCC_TYPE_COUNTER;
}
++values_len;
int status;
while (42) {
- int c;
+ int opt;
- c = getopt (argc, argv, "s:h");
+ opt = getopt (argc, argv, "s:h");
- if (c == -1)
+ if (opt == -1)
break;
- switch (c) {
+ switch (opt) {
case 's':
snprintf (address, sizeof (address), "unix:%s", optarg);
address[sizeof (address) - 1] = '\0';
diff --git a/src/cpu.c b/src/cpu.c
index 2a2a4a9715d20e9b76055d559edcb1b2f9e55aa1..bcaea38c546305968487a8c509e117b09dfa1e0a 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
/* Adds a derive value to the internal state. This should be used by each read
* function for each state. At the end of the iteration, the read function
* should call cpu_commit(). */
-static int cpu_stage (size_t cpu_num, size_t state, derive_t value, cdtime_t now) /* {{{ */
+static int cpu_stage (size_t cpu_num, size_t state, derive_t d, cdtime_t now) /* {{{ */
{
int status;
cpu_state_t *s;
- value_t v;
+ gauge_t rate = NAN;
+ value_t val = {.derive = d};
if (state >= COLLECTD_CPU_STATE_ACTIVE)
return (EINVAL);
@@ -544,12 +545,11 @@ static int cpu_stage (size_t cpu_num, size_t state, derive_t value, cdtime_t now
s = get_cpu_state (cpu_num, state);
- v.gauge = NAN;
- status = value_to_rate (&v, value, &s->conv, DS_TYPE_DERIVE, now);
+ status = value_to_rate (&rate, val, DS_TYPE_DERIVE, now, &s->conv);
if (status != 0)
return (status);
- s->rate = v.gauge;
+ s->rate = rate;
s->has_value = 1;
return (0);
} /* }}} int cpu_stage */
diff --git a/src/csv.c b/src/csv.c
index b6e535ee6b4c9b44eae4cde70052e877c1c5e2ee..15494f450dd60a852be2b948c8356c781194c2e1 100644 (file)
--- a/src/csv.c
+++ b/src/csv.c
{
int offset;
int status;
- int i;
+ size_t i;
gauge_t *rates = NULL;
assert (0 == strcmp (ds->type, vl->type));
static int csv_create_file (const char *filename, const data_set_t *ds)
{
FILE *csv;
- int i;
+ size_t i;
if (check_create_dir (filename))
return (-1);
diff --git a/src/curl.c b/src/curl.c
index ac4cc512c63fd51dcdd9190814aca5e0eaf1cc7d..16ae3ababc1d48c421c85c814b2eb0499edd699e 100644 (file)
--- a/src/curl.c
+++ b/src/curl.c
if (wp->timeout >= 0)
curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS, (long) wp->timeout);
else
- curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
diff --git a/src/curl_json.c b/src/curl_json.c
index 3ba55603d329342e6a30fa86b6908531e3e36e73..510d9b621d0b9a32b235337856f455c82eef2b3e 100644 (file)
--- a/src/curl_json.c
+++ b/src/curl_json.c
#include "utils_avltree.h"
#include "utils_complain.h"
-#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
if (*ptr == '/')
{
c_avl_tree_t *value;
- int len;
+ size_t len;
len = ptr-name;
if (len == 0)
if (db->timeout >= 0)
curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) db->timeout);
else if (db->interval > 0)
- curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(db->timeout));
+ curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(db->timeout));
else
- curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
{
user_data_t ud;
char *cb_name;
- struct timespec interval = { 0, 0 };
-
- CDTIME_T_TO_TIMESPEC (db->interval, &interval);
if (db->instance == NULL)
db->instance = strdup("default");
db->instance, db->url ? db->url : db->sock);
plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read,
- /* interval = */ (db->interval > 0) ? &interval : NULL,
+ /* interval = */ db->interval,
&ud);
sfree (cb_name);
}
diff --git a/src/curl_xml.c b/src/curl_xml.c
index 37a36866c91982345f56b0371fac92ed42a78449..5a1f2baba232e7c56d5ed2ade5b8912e0f13ddd9 100644 (file)
--- a/src/curl_xml.c
+++ b/src/curl_xml.c
char *path;
char *type;
cx_values_t *values;
- int values_len;
+ size_t values_len;
char *instance_prefix;
char *instance;
int is_table;
if (ds->ds_num != xpath->values_len)
{
- WARNING ("curl_xml plugin: DataSet `%s' requires %i values, but config talks about %i",
+ WARNING ("curl_xml plugin: DataSet `%s' requires %zu values, but config talks about %zu",
xpath->type, ds->ds_num, xpath->values_len);
return (-1);
}
{
value_t values[xpath->values_len];
int status;
- int i;
+ size_t i;
assert (xpath->values_len > 0);
assert (xpath->values_len == vl->values_len);
xpath->values = (cx_values_t *) malloc (sizeof (cx_values_t) * ci->values_num);
if (xpath->values == NULL)
return (-1);
- xpath->values_len = ci->values_num;
+ xpath->values_len = (size_t) ci->values_num;
/* populate cx_values_t structure */
for (i = 0; i < ci->values_num; i++)
if (db->timeout >= 0)
curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) db->timeout);
else
- curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
cb_name = ssnprintf_alloc ("curl_xml-%s-%s", db->instance, db->url);
plugin_register_complex_read (/* group = */ "curl_xml", cb_name, cx_read,
- /* interval = */ NULL, &ud);
+ /* interval = */ 0, &ud);
sfree (cb_name);
}
else
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index 99dc1584f62b2afbd4e14fbe201369012189711a..4e383413589b6f9ef43e5a50fa91ed8f6a3bdf0c 100644 (file)
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
-if COMPILER_IS_GCC
-AM_CFLAGS = -Wall -Werror
-endif
-
AM_CPPFLAGS = -I$(top_srcdir)/src
AM_CPPFLAGS += -DPREFIX='"${prefix}"'
AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
sbin_PROGRAMS = collectd
-noinst_LTLIBRARIES = libavltree.la libcommon.la libheap.la libplugin_mock.la
+noinst_LTLIBRARIES = libavltree.la libcommon.la libheap.la libmetadata.la libplugin_mock.la
libavltree_la_SOURCES = utils_avltree.c utils_avltree.h
libcommon_la_SOURCES = common.c common.h
+libcommon_la_LIBADD = $(COMMON_LIBS)
libheap_la_SOURCES = utils_heap.c utils_heap.h
+libmetadata_la_SOURCES = meta_data.c meta_data.h
+
libplugin_mock_la_SOURCES = plugin_mock.c utils_cache_mock.c utils_time_mock.c
+libplugin_mock_la_LIBADD = $(COMMON_LIBS)
collectd_SOURCES = collectd.c collectd.h \
configfile.c configfile.h \
collectd_CFLAGS = $(AM_CFLAGS)
collectd_LDFLAGS = -export-dynamic
collectd_LDADD = libavltree.la libcommon.la libheap.la -lm $(COMMON_LIBS)
-collectd_DEPENDENCIES = libavltree.la libcommon.la libheap.la
+collectd_DEPENDENCIES = libavltree.la libcommon.la libheap.la libmetadata.la
# The daemon needs to call sg_init, so we need to link it against libstatgrab,
# too. -octo
collectd_LDADD += -loconfig
endif
-check_PROGRAMS = test_common test_utils_avltree test_utils_heap
-TESTS = test_common test_utils_avltree test_utils_heap
+check_PROGRAMS = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_time test_utils_subst
+TESTS = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_time test_utils_subst
test_common_SOURCES = common_test.c ../testing.h
-test_common_LDADD = libcommon.la libplugin_mock.la $(COMMON_LIBS)
+test_common_LDADD = libcommon.la libplugin_mock.la
+
+test_meta_data_SOURCES = meta_data_test.c ../testing.h
+test_meta_data_LDADD = libmetadata.la libplugin_mock.la
test_utils_avltree_SOURCES = utils_avltree_test.c ../testing.h
test_utils_avltree_LDADD = libavltree.la $(COMMON_LIBS)
test_utils_heap_SOURCES = utils_heap_test.c ../testing.h
test_utils_heap_LDADD = libheap.la $(COMMON_LIBS)
+
+test_utils_time_SOURCES = utils_time_test.c ../testing.h
+
+test_utils_subst_SOURCES = utils_subst_test.c ../testing.h \
+ utils_subst.c utils_subst.h
+test_utils_subst_LDADD = libcommon.la libplugin_mock.la
diff --git a/src/daemon/collectd.c b/src/daemon/collectd.c
index 88c38acea0990e1aa8684959c55ca9e8d94877e1..fc52933111e79fec0c291d115618d4b57f6032e5 100644 (file)
--- a/src/daemon/collectd.c
+++ b/src/daemon/collectd.c
#include "configfile.h"
#include <sys/types.h>
-#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#ifdef KERNEL_LINUX
int notify_upstart (void)
{
- const char *upstart_job = getenv("UPSTART_JOB");
+ char const *upstart_job = getenv("UPSTART_JOB");
if (upstart_job == NULL)
return 0;
if (strcmp(upstart_job, "collectd") != 0)
+ {
+ WARNING ("Environment specifies unexpected UPSTART_JOB=\"%s\", expected \"collectd\". Ignoring the variable.", upstart_job);
return 0;
+ }
- WARNING ("supervised by upstart, will stop to signal readyness");
+ NOTICE("Upstart detected, stopping now to signal readyness.");
raise(SIGSTOP);
unsetenv("UPSTART_JOB");
int notify_systemd (void)
{
- int fd = -1;
- const char *notifysocket = getenv("NOTIFY_SOCKET");
+ int fd;
+ const char *notifysocket;
struct sockaddr_un su;
- struct iovec iov;
- struct msghdr hdr;
+ size_t su_size;
+ char buffer[] = "READY=1\n";
+ notifysocket = getenv ("NOTIFY_SOCKET");
if (notifysocket == NULL)
return 0;
- if ((strchr("@/", notifysocket[0])) == NULL ||
- strlen(notifysocket) < 2)
+ if ((strlen (notifysocket) < 2)
+ || ((notifysocket[0] != '@') && (notifysocket[0] != '/')))
+ {
+ ERROR ("invalid notification socket NOTIFY_SOCKET=\"%s\": path must be absolute", notifysocket);
return 0;
+ }
+ NOTICE ("Systemd detected, trying to signal readyness.");
+
+ unsetenv ("NOTIFY_SOCKET");
- WARNING ("supervised by systemd, will signal readyness");
- if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
- WARNING ("cannot contact systemd socket %s", notifysocket);
+#if defined(SOCK_CLOEXEC)
+ fd = socket (AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, /* protocol = */ 0);
+#else
+ fd = socket (AF_UNIX, SOCK_DGRAM, /* protocol = */ 0);
+#endif
+ if (fd < 0) {
+ char errbuf[1024];
+ ERROR ("creating UNIX socket failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
return 0;
}
- bzero(&su, sizeof(su));
+ memset (&su, 0, sizeof (su));
su.sun_family = AF_UNIX;
- sstrncpy (su.sun_path, notifysocket, sizeof(su.sun_path));
-
- if (notifysocket[0] == '@')
+ if (notifysocket[0] != '@')
+ {
+ /* regular UNIX socket */
+ sstrncpy (su.sun_path, notifysocket, sizeof (su.sun_path));
+ su_size = sizeof (su);
+ }
+ else
+ {
+ /* Linux abstract namespace socket: specify address as "\0foo", i.e.
+ * start with a null byte. Since null bytes have no special meaning in
+ * that case, we have to set su_size correctly to cover only the bytes
+ * that are part of the address. */
+ sstrncpy (su.sun_path, notifysocket, sizeof (su.sun_path));
su.sun_path[0] = 0;
+ su_size = sizeof (sa_family_t) + strlen (notifysocket);
+ if (su_size > sizeof (su))
+ su_size = sizeof (su);
+ }
- bzero(&iov, sizeof(iov));
- iov.iov_base = "READY=1";
- iov.iov_len = strlen("READY=1");
-
- bzero(&hdr, sizeof(hdr));
- hdr.msg_name = &su;
- hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) +
- strlen(notifysocket);
- hdr.msg_iov = &iov;
- hdr.msg_iovlen = 1;
-
- unsetenv("NOTIFY_SOCKET");
- if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) {
- WARNING ("cannot send notification to systemd");
+ if (sendto (fd, buffer, strlen (buffer), MSG_NOSIGNAL, (void *) &su, (socklen_t) su_size) < 0)
+ {
+ char errbuf[1024];
+ ERROR ("sendto(\"%s\") failed: %s", notifysocket,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
close(fd);
return 0;
}
+
+ unsetenv ("NOTIFY_SOCKET");
close(fd);
return 1;
}
diff --git a/src/daemon/collectd.h b/src/daemon/collectd.h
index 80b753c8a83442b3e278858a8cb54528bf9868d1..66b485681b223c97c7fda9cc595a16d9616e0494 100644 (file)
--- a/src/daemon/collectd.h
+++ b/src/daemon/collectd.h
# include <time.h>
# endif
#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
#if HAVE_ASSERT_H
# include <assert.h>
diff --git a/src/daemon/common.c b/src/daemon/common.c
index b2448086c53aadc0641b63bf7eef9b51e8c1decf..8f22011ed57c46c94244f8273461fce3fa7af155 100644 (file)
--- a/src/daemon/common.c
+++ b/src/daemon/common.c
/* for getaddrinfo */
#include <sys/types.h>
-#include <sys/socket.h>
#include <netdb.h>
#if HAVE_NETINET_IN_H
assert ((0 > status) || (nleft >= (size_t)status));
- nleft = nleft - status;
- ptr = ptr + status;
+ nleft = nleft - ((size_t) status);
+ ptr = ptr + ((size_t) status);
}
return (0);
if (status < 0)
return (status);
- nleft = nleft - status;
- ptr = ptr + status;
+ nleft = nleft - ((size_t) status);
+ ptr = ptr + ((size_t) status);
}
return (0);
}
assert (buffer[buffer_size - 1] == 0);
- return (strlen (buffer));
+ return ((int) strlen (buffer));
}
int strsubstitute (char *str, char c_from, char c_to)
int escape_slashes (char *buffer, size_t buffer_size)
{
- int i;
size_t buffer_len;
+ size_t i;
buffer_len = strlen (buffer);
* Join the components together again
*/
dir[0] = '/';
- if (strjoin (dir + path_is_absolute, dir_len - path_is_absolute,
- fields, i + 1, "/") < 0)
+ if (strjoin (dir + path_is_absolute, (size_t) (dir_len - path_is_absolute),
+ fields, (size_t) (i + 1), "/") < 0)
{
ERROR ("strjoin failed: `%s', component #%i", file_orig, i);
return (-1);
{
size_t offset = 0;
int status;
- int i;
+ size_t i;
gauge_t *rates = NULL;
assert (0 == strcmp (ds->type, vl->type));
int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
{
- int i;
+ size_t i;
char *dummy;
char *ptr;
char *saveptr;
- i = -1;
+ i = 0;
dummy = buffer;
saveptr = NULL;
+ vl->time = 0;
while ((ptr = strtok_r (dummy, ":", &saveptr)) != NULL)
{
dummy = NULL;
if (i >= vl->values_len)
{
/* Make sure i is invalid. */
- i = vl->values_len + 1;
+ i = 0;
break;
}
- if (i == -1)
+ if (vl->time == 0)
{
if (strcmp ("N", ptr) == 0)
vl->time = cdtime ();
vl->time = DOUBLE_TO_CDTIME_T (tmp);
}
- }
- else
- {
- if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
- vl->values[i].gauge = NAN;
- else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
- return -1;
+
+ continue;
}
+ if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
+ vl->values[i].gauge = NAN;
+ else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
+ return -1;
+
i++;
} /* while (strtok_r) */
- if ((ptr != NULL) || (i != vl->values_len))
+ if ((ptr != NULL) || (i == 0))
return (-1);
return (0);
} /* int parse_values */
if (old_value > new_value)
{
if (old_value <= 4294967295U)
- diff = (4294967295U - old_value) + new_value;
+ diff = (4294967295U - old_value) + new_value + 1;
else
- diff = (18446744073709551615ULL - old_value)
- + new_value;
+ diff = (18446744073709551615ULL - old_value) + new_value + 1;
}
else
{
return (0);
} /* }}} value_t rate_to_value */
-int value_to_rate (value_t *ret_rate, derive_t value, /* {{{ */
- value_to_rate_state_t *state,
- int ds_type, cdtime_t t)
+int value_to_rate (gauge_t *ret_rate, /* {{{ */
+ value_t value, int ds_type, cdtime_t t, value_to_rate_state_t *state)
{
- double interval;
+ gauge_t interval;
/* Another invalid state: The time is not increasing. */
if (t <= state->last_time)
interval = CDTIME_T_TO_DOUBLE(t - state->last_time);
/* Previous value is invalid. */
- if (state->last_time == 0) /* {{{ */
+ if (state->last_time == 0)
{
- if (ds_type == DS_TYPE_DERIVE)
- {
- state->last_value.derive = value;
- }
- else if (ds_type == DS_TYPE_COUNTER)
- {
- state->last_value.counter = (counter_t) value;
- }
- else if (ds_type == DS_TYPE_ABSOLUTE)
- {
- state->last_value.absolute = (absolute_t) value;
- }
- else
- {
- assert (23 == 42);
- }
-
+ state->last_value = value;
state->last_time = t;
return (EAGAIN);
- } /* }}} */
+ }
- if (ds_type == DS_TYPE_DERIVE)
- {
- ret_rate->gauge = (value - state->last_value.derive) / interval;
- state->last_value.derive = value;
+ switch (ds_type) {
+ case DS_TYPE_DERIVE: {
+ derive_t diff = value.derive - state->last_value.derive;
+ *ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
+ break;
}
- else if (ds_type == DS_TYPE_COUNTER)
- {
- ret_rate->gauge = (((counter_t)value) - state->last_value.counter) / interval;
- state->last_value.counter = (counter_t) value;
+ case DS_TYPE_GAUGE: {
+ *ret_rate = value.gauge;
+ break;
}
- else if (ds_type == DS_TYPE_ABSOLUTE)
- {
- ret_rate->gauge = (((absolute_t)value) - state->last_value.absolute) / interval;
- state->last_value.absolute = (absolute_t) value;
+ case DS_TYPE_COUNTER: {
+ counter_t diff = counter_diff (state->last_value.counter, value.counter);
+ *ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
+ break;
}
- else
- {
- assert (23 == 42);
+ case DS_TYPE_ABSOLUTE: {
+ absolute_t diff = value.absolute;
+ *ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
+ break;
+ }
+ default:
+ return EINVAL;
}
- state->last_time = t;
+ state->last_value = value;
+ state->last_time = t;
return (0);
} /* }}} value_t rate_to_value */
diff --git a/src/daemon/common.h b/src/daemon/common.h
index da21cad9a6f3a81f1120b466740a669ec009c231..c3f7f5485cb5888ed7a95634e538ff9c35b82d46 100644 (file)
--- a/src/daemon/common.h
+++ b/src/daemon/common.h
int rate_to_value (value_t *ret_value, gauge_t rate,
rate_to_value_state_t *state, int ds_type, cdtime_t t);
-int value_to_rate (value_t *ret_rate, derive_t value,
- value_to_rate_state_t *state, int ds_type, cdtime_t t);
+int value_to_rate (gauge_t *ret_rate, value_t value, int ds_type, cdtime_t t,
+ value_to_rate_state_t *state);
/* Converts a service name (a string) to a port number
* (in the range [1-65535]). Returns less than zero on error. */
index 1fa8f324461293c201b30440a8bb3e857062a993..399f8b533b2bcfdce28afa6b9c3a9f7573a89a75 100644 (file)
--- a/src/daemon/common_test.c
+++ b/src/daemon/common_test.c
#include "testing.h"
#include "common.h"
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc;
+#endif /* HAVE_LIBKSTAT */
+
DEF_TEST(sstrncpy)
{
char buffer[16] = "";
ret = sstrncpy (ptr, "foobar", 8);
OK(ret == ptr);
- STREQ ("foobar", ptr);
+ EXPECT_EQ_STR ("foobar", ptr);
OK(buffer[3] == buffer[12]);
ret = sstrncpy (ptr, "abc", 8);
OK(ret == ptr);
- STREQ ("abc", ptr);
+ EXPECT_EQ_STR ("abc", ptr);
OK(buffer[3] == buffer[12]);
ret = sstrncpy (ptr, "collectd", 8);
OK(ret == ptr);
OK(ptr[7] == 0);
- STREQ ("collect", ptr);
+ EXPECT_EQ_STR ("collect", ptr);
OK(buffer[3] == buffer[12]);
return (0);
status = ssnprintf (ptr, 8, "%i", 1337);
OK(status == 4);
- STREQ ("1337", ptr);
+ EXPECT_EQ_STR ("1337", ptr);
status = ssnprintf (ptr, 8, "%s", "collectd");
OK(status == 8);
OK(ptr[7] == 0);
- STREQ ("collect", ptr);
+ EXPECT_EQ_STR ("collect", ptr);
OK(buffer[3] == buffer[12]);
return (0);
ptr = sstrdup ("collectd");
OK(ptr != NULL);
- STREQ ("collectd", ptr);
+ EXPECT_EQ_STR ("collectd", ptr);
sfree(ptr);
OK(ptr == NULL);
strncpy (buffer, "foo bar", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 2);
- STREQ ("foo", fields[0]);
- STREQ ("bar", fields[1]);
+ EXPECT_EQ_STR ("foo", fields[0]);
+ EXPECT_EQ_STR ("bar", fields[1]);
strncpy (buffer, "foo \t bar", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 2);
- STREQ ("foo", fields[0]);
- STREQ ("bar", fields[1]);
+ EXPECT_EQ_STR ("foo", fields[0]);
+ EXPECT_EQ_STR ("bar", fields[1]);
strncpy (buffer, "one two\tthree\rfour\nfive", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 5);
- STREQ ("one", fields[0]);
- STREQ ("two", fields[1]);
- STREQ ("three", fields[2]);
- STREQ ("four", fields[3]);
- STREQ ("five", fields[4]);
+ EXPECT_EQ_STR ("one", fields[0]);
+ EXPECT_EQ_STR ("two", fields[1]);
+ EXPECT_EQ_STR ("three", fields[2]);
+ EXPECT_EQ_STR ("four", fields[3]);
+ EXPECT_EQ_STR ("five", fields[4]);
strncpy (buffer, "\twith trailing\n", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 2);
- STREQ ("with", fields[0]);
- STREQ ("trailing", fields[1]);
+ EXPECT_EQ_STR ("with", fields[0]);
+ EXPECT_EQ_STR ("trailing", fields[1]);
strncpy (buffer, "1 2 3 4 5 6 7 8 9 10 11 12 13", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 8);
- STREQ ("7", fields[6]);
- STREQ ("8", fields[7]);
+ EXPECT_EQ_STR ("7", fields[6]);
+ EXPECT_EQ_STR ("8", fields[7]);
strncpy (buffer, "single", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 1);
- STREQ ("single", fields[0]);
+ EXPECT_EQ_STR ("single", fields[0]);
strncpy (buffer, "", sizeof (buffer));
status = strsplit (buffer, fields, 8);
status = strjoin (buffer, sizeof (buffer), fields, 2, "!");
OK(status == 7);
- STREQ ("foo!bar", buffer);
+ EXPECT_EQ_STR ("foo!bar", buffer);
status = strjoin (buffer, sizeof (buffer), fields, 1, "!");
OK(status == 3);
- STREQ ("foo", buffer);
+ EXPECT_EQ_STR ("foo", buffer);
status = strjoin (buffer, sizeof (buffer), fields, 0, "!");
OK(status < 0);
status = strjoin (buffer, sizeof (buffer), fields, 2, "rcht");
OK(status == 10);
- STREQ ("foorchtbar", buffer);
+ EXPECT_EQ_STR ("foorchtbar", buffer);
status = strjoin (buffer, sizeof (buffer), fields, 4, "");
OK(status == 12);
- STREQ ("foobarbazqux", buffer);
+ EXPECT_EQ_STR ("foobarbazqux", buffer);
status = strjoin (buffer, sizeof (buffer), fields, 4, "!");
OK(status == 15);
- STREQ ("foo!bar!baz!qux", buffer);
+ EXPECT_EQ_STR ("foo!bar!baz!qux", buffer);
fields[0] = "0123";
fields[1] = "4567";
return (0);
}
+DEF_TEST(escape_slashes)
+{
+ struct {
+ char *str;
+ char *want;
+ } cases[] = {
+ {"foo/bar/baz", "foo_bar_baz"},
+ {"/like/a/path", "like_a_path"},
+ {"trailing/slash/", "trailing_slash_"},
+ {"foo//bar", "foo__bar"},
+ };
+ size_t i;
+
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ char buffer[32];
+
+ strncpy (buffer, cases[i].str, sizeof (buffer));
+ OK(escape_slashes (buffer, sizeof (buffer)) == 0);
+ EXPECT_EQ_STR(cases[i].want, buffer);
+ }
+
+ return 0;
+}
+
+DEF_TEST(escape_string)
+{
+ struct {
+ char *str;
+ char *want;
+ } cases[] = {
+ {"foobar", "foobar"},
+ {"f00bar", "f00bar"},
+ {"foo bar", "\"foo bar\""},
+ {"foo \"bar\"", "\"foo \\\"bar\\\"\""},
+ {"012345678901234", "012345678901234"},
+ {"012345 78901234", "\"012345 789012\""},
+ {"012345 78901\"34", "\"012345 78901\""},
+ };
+ size_t i;
+
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ char buffer[16];
+
+ strncpy (buffer, cases[i].str, sizeof (buffer));
+ OK(escape_string (buffer, sizeof (buffer)) == 0);
+ EXPECT_EQ_STR(cases[i].want, buffer);
+ }
+
+ return 0;
+}
+
DEF_TEST(strunescape)
{
char buffer[16];
strncpy (buffer, "foo\\tbar", sizeof (buffer));
status = strunescape (buffer, sizeof (buffer));
OK(status == 0);
- STREQ ("foo\tbar", buffer);
+ EXPECT_EQ_STR ("foo\tbar", buffer);
strncpy (buffer, "\\tfoo\\r\\n", sizeof (buffer));
status = strunescape (buffer, sizeof (buffer));
OK(status == 0);
- STREQ ("\tfoo\r\n", buffer);
+ EXPECT_EQ_STR ("\tfoo\r\n", buffer);
strncpy (buffer, "With \\\"quotes\\\"", sizeof (buffer));
status = strunescape (buffer, sizeof (buffer));
OK(status == 0);
- STREQ ("With \"quotes\"", buffer);
+ EXPECT_EQ_STR ("With \"quotes\"", buffer);
/* Backslash before null byte */
strncpy (buffer, "\\tbackslash end\\", sizeof (buffer));
status = strunescape (buffer, sizeof (buffer));
OK(status != 0);
- STREQ ("\tbackslash end", buffer);
+ EXPECT_EQ_STR ("\tbackslash end", buffer);
return (0);
/* Backslash at buffer end */
return (0);
}
+DEF_TEST(parse_values)
+{
+ struct {
+ char buffer[64];
+ int status;
+ gauge_t value;
+ } cases[] = {
+ {"1435044576:42", 0, 42.0},
+ {"1435044576:42:23", -1, NAN},
+ {"1435044576:U", 0, NAN},
+ {"N:12.3", 0, 12.3},
+ {"N:42.0:23", -1, NAN},
+ {"N:U", 0, NAN},
+ {"T:42.0", -1, NAN},
+ };
+
+ size_t i;
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+ {
+ data_source_t dsrc = {
+ .name = "value",
+ .type = DS_TYPE_GAUGE,
+ .min = 0.0,
+ .max = NAN,
+ };
+ data_set_t ds = {
+ .type = "example",
+ .ds_num = 1,
+ .ds = &dsrc,
+ };
+
+ value_t v = {
+ .gauge = NAN,
+ };
+ value_list_t vl = {
+ .values = &v,
+ .values_len = 1,
+ .time = 0,
+ .interval = 0,
+ .host = "example.com",
+ .plugin = "common_test",
+ .type = "example",
+ .meta = NULL,
+ };
+
+ int status = parse_values (cases[i].buffer, &vl, &ds);
+ EXPECT_EQ_INT (cases[i].status, status);
+ if (status != 0)
+ continue;
+
+ EXPECT_EQ_DOUBLE (cases[i].value, vl.values[0].gauge);
+ }
+
+ return (0);
+}
+
+DEF_TEST(value_to_rate)
+{
+ struct {
+ time_t t0;
+ time_t t1;
+ int ds_type;
+ value_t v0;
+ value_t v1;
+ gauge_t want;
+ } cases[] = {
+ { 0, 10, DS_TYPE_DERIVE, {.derive = 0}, {.derive = 1000}, NAN},
+ {10, 20, DS_TYPE_DERIVE, {.derive = 1000}, {.derive = 2000}, 100.0},
+ {20, 30, DS_TYPE_DERIVE, {.derive = 2000}, {.derive = 1800}, -20.0},
+ { 0, 10, DS_TYPE_COUNTER, {.counter = 0}, {.counter = 1000}, NAN},
+ {10, 20, DS_TYPE_COUNTER, {.counter = 1000}, {.counter = 5000}, 400.0},
+ /* 32bit wrap-around. */
+ {20, 30, DS_TYPE_COUNTER, {.counter = 4294967238ULL}, {.counter = 42}, 10.0},
+ /* 64bit wrap-around. */
+ {30, 40, DS_TYPE_COUNTER, {.counter = 18446744073709551558ULL}, {.counter = 42}, 10.0},
+ };
+ size_t i;
+
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ value_to_rate_state_t state = { cases[i].v0, TIME_T_TO_CDTIME_T (cases[i].t0) };
+ gauge_t got;
+
+ if (cases[i].t0 == 0) {
+ OK(value_to_rate (&got, cases[i].v1, cases[i].ds_type, TIME_T_TO_CDTIME_T(cases[i].t1), &state) == EAGAIN);
+ continue;
+ }
+
+ OK(value_to_rate (&got, cases[i].v1, cases[i].ds_type, TIME_T_TO_CDTIME_T(cases[i].t1), &state) == 0);
+ EXPECT_EQ_DOUBLE(cases[i].want, got);
+ }
+
+ return 0;
+}
+
int main (void)
{
RUN_TEST(sstrncpy);
RUN_TEST(sstrdup);
RUN_TEST(strsplit);
RUN_TEST(strjoin);
+ RUN_TEST(escape_slashes);
+ RUN_TEST(escape_string);
RUN_TEST(strunescape);
+ RUN_TEST(parse_values);
+ RUN_TEST(value_to_rate);
END_TEST;
}
index ae3e79899d2eddf1304bcc00ba178289b3602d02..ae9ab3a6cfe6bd6679fbc3dadc5ffa5a124fc25f 100644 (file)
--- a/src/daemon/configfile.c
+++ b/src/daemon/configfile.c
/* default to the global interval set before loading this plugin */
memset (&ctx, 0, sizeof (ctx));
ctx.interval = cf_get_default_interval ();
+ ctx.flush_interval = 0;
+ ctx.flush_timeout = 0;
- for (i = 0; i < ci->children_num; ++i) {
- if (strcasecmp("Globals", ci->children[i].key) == 0)
- cf_util_get_flag (ci->children + i, &flags, PLUGIN_FLAGS_GLOBAL);
- else if (strcasecmp ("Interval", ci->children[i].key) == 0) {
- if (cf_util_get_cdtime (ci->children + i, &ctx.interval) != 0) {
- /* cf_util_get_cdtime will log an error */
- continue;
- }
- }
+ for (i = 0; i < ci->children_num; ++i)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp("Globals", child->key) == 0)
+ cf_util_get_flag (child, &flags, PLUGIN_FLAGS_GLOBAL);
+ else if (strcasecmp ("Interval", child->key) == 0)
+ cf_util_get_cdtime (child, &ctx.interval);
+ else if (strcasecmp ("FlushInterval", child->key) == 0)
+ cf_util_get_cdtime (child, &ctx.flush_interval);
+ else if (strcasecmp ("FlushTimeout", child->key) == 0)
+ cf_util_get_cdtime (child, &ctx.flush_timeout);
else {
WARNING("Ignoring unknown LoadPlugin option \"%s\" "
"for plugin \"%s\"",
- ci->children[i].key, ci->values[0].value.string);
+ child->key, ci->values[0].value.string);
}
}
diff --git a/src/daemon/meta_data_test.c b/src/daemon/meta_data_test.c
--- /dev/null
@@ -0,0 +1,119 @@
+/**
+ * collectd - src/daemon/meta_data_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#include "testing.h"
+#include "collectd.h"
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "meta_data.h"
+
+DEF_TEST(base)
+{
+ meta_data_t *m;
+
+ char *s;
+ int64_t si;
+ uint64_t ui;
+ double d;
+ _Bool b;
+
+ CHECK_NOT_NULL (m = meta_data_create ());
+
+ /* all of these are absent */
+ OK(meta_data_get_string (m, "string", &s) != 0);
+ OK(meta_data_get_signed_int (m, "signed_int", &si) != 0);
+ OK(meta_data_get_unsigned_int (m, "unsigned_int", &ui) != 0);
+ OK(meta_data_get_double (m, "double", &d) != 0);
+ OK(meta_data_get_boolean (m, "boolean", &b) != 0);
+
+ /* populate structure */
+ CHECK_ZERO (meta_data_add_string (m, "string", "foobar"));
+ OK(meta_data_exists (m, "string"));
+ OK(meta_data_type (m, "string") == MD_TYPE_STRING);
+
+ CHECK_ZERO (meta_data_add_signed_int (m, "signed_int", -1));
+ OK(meta_data_exists (m, "signed_int"));
+ OK(meta_data_type (m, "signed_int") == MD_TYPE_SIGNED_INT);
+
+ CHECK_ZERO (meta_data_add_unsigned_int (m, "unsigned_int", 1));
+ OK(meta_data_exists (m, "unsigned_int"));
+ OK(meta_data_type (m, "unsigned_int") == MD_TYPE_UNSIGNED_INT);
+
+ CHECK_ZERO (meta_data_add_double (m, "double", 47.11));
+ OK(meta_data_exists (m, "double"));
+ OK(meta_data_type (m, "double") == MD_TYPE_DOUBLE);
+
+ CHECK_ZERO (meta_data_add_boolean (m, "boolean", 1));
+ OK(meta_data_exists (m, "boolean"));
+ OK(meta_data_type (m, "boolean") == MD_TYPE_BOOLEAN);
+
+ /* retrieve and check all values */
+ CHECK_ZERO (meta_data_get_string (m, "string", &s));
+ EXPECT_EQ_STR ("foobar", s);
+ sfree (s);
+
+ CHECK_ZERO (meta_data_get_signed_int (m, "signed_int", &si));
+ EXPECT_EQ_INT (-1, (int) si);
+
+ CHECK_ZERO (meta_data_get_unsigned_int (m, "unsigned_int", &ui));
+ EXPECT_EQ_INT (1, (int) ui);
+
+ CHECK_ZERO (meta_data_get_double (m, "double", &d));
+ EXPECT_EQ_DOUBLE (47.11, d);
+
+ CHECK_ZERO (meta_data_get_boolean (m, "boolean", &b));
+ OK1 (b, "b evaluates to true");
+
+ /* retrieving the wrong type always fails */
+ EXPECT_EQ_INT (-2, meta_data_get_boolean (m, "string", &b));
+ EXPECT_EQ_INT (-2, meta_data_get_string (m, "signed_int", &s));
+ EXPECT_EQ_INT (-2, meta_data_get_string (m, "unsigned_int", &s));
+ EXPECT_EQ_INT (-2, meta_data_get_string (m, "double", &s));
+ EXPECT_EQ_INT (-2, meta_data_get_string (m, "boolean", &s));
+
+ /* replace existing keys */
+ CHECK_ZERO (meta_data_add_signed_int (m, "string", 666));
+ OK(meta_data_type (m, "string") == MD_TYPE_SIGNED_INT);
+
+ CHECK_ZERO (meta_data_add_signed_int (m, "signed_int", 666));
+ CHECK_ZERO (meta_data_get_signed_int (m, "signed_int", &si));
+ EXPECT_EQ_INT (666, (int) si);
+
+ /* deleting keys */
+ CHECK_ZERO (meta_data_delete (m, "signed_int"));
+ EXPECT_EQ_INT (-2, meta_data_delete (m, "doesnt exist"));
+
+ meta_data_destroy (m);
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(base);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/plugin.c b/src/daemon/plugin.c
index 3da8eccbb3b2b147f8042c866ded54ee788fe127..b57dd4a21281a486b3356fe863aeec3fbebc305a 100644 (file)
--- a/src/daemon/plugin.c
+++ b/src/daemon/plugin.c
write_queue_t *next;
};
+struct flush_callback_s {
+ char *name;
+ cdtime_t timeout;
+};
+typedef struct flush_callback_s flush_callback_t;
+
/*
* Private variables
*/
static void stop_write_threads (void) /* {{{ */
{
write_queue_t *q;
- int i;
+ size_t i;
if (write_threads == NULL)
return;
if (i > 0)
{
- WARNING ("plugin: %i value list%s left after shutting down "
+ WARNING ("plugin: %zu value list%s left after shutting down "
"the write threads.",
i, (i == 1) ? " was" : "s were");
}
/* success */
plugin_mark_loaded (plugin_name);
ret = 0;
+ INFO ("plugin_load: plugin \"%s\" successfully loaded.", plugin_name);
break;
}
else
int plugin_register_complex_read (const char *group, const char *name,
plugin_read_cb callback,
- const struct timespec *interval,
+ cdtime_t interval,
user_data_t *user_data)
{
read_func_t *rf;
rf->rf_group[0] = '\0';
rf->rf_name = strdup (name);
rf->rf_type = RF_COMPLEX;
- if (interval != NULL)
- rf->rf_interval = TIMESPEC_TO_CDTIME_T (interval);
- else
- rf->rf_interval = plugin_get_interval ();
+ rf->rf_interval = (interval != 0) ? interval : plugin_get_interval ();
/* Set user data */
if (user_data == NULL)
(void *) callback, ud));
} /* int plugin_register_write */
+static int plugin_flush_timeout_callback (user_data_t *ud)
+{
+ flush_callback_t *cb = ud->data;
+
+ return plugin_flush (cb->name, cb->timeout, /* identifier = */ NULL);
+} /* static int plugin_flush_callback */
+
+static void plugin_flush_timeout_callback_free (void *data)
+{
+ flush_callback_t *cb = data;
+
+ if (cb == NULL) return;
+
+ sfree(cb->name);
+ sfree(cb);
+} /* static void plugin_flush_callback_free */
+
+static char *plugin_flush_callback_name (const char *name)
+{
+ char *flush_prefix = "flush/";
+ size_t prefix_size;
+ char *flush_name;
+ size_t name_size;
+
+ prefix_size = strlen(flush_prefix);
+ name_size = strlen(name);
+
+ flush_name = malloc (sizeof(char) * (name_size + prefix_size + 1));
+ if (flush_name == NULL)
+ {
+ ERROR ("plugin_flush_callback_name: malloc failed.");
+ return (NULL);
+ }
+
+ sstrncpy (flush_name, flush_prefix, prefix_size + 1);
+ sstrncpy (flush_name + prefix_size, name, name_size + 1);
+
+ return flush_name;
+} /* static char *plugin_flush_callback_name */
+
int plugin_register_flush (const char *name,
plugin_flush_cb callback, user_data_t *ud)
{
- return (create_register_callback (&list_flush, name,
- (void *) callback, ud));
+ int status;
+ plugin_ctx_t ctx = plugin_get_ctx ();
+
+ status = create_register_callback (&list_flush, name,
+ (void *) callback, ud);
+ if (status != 0)
+ return status;
+
+ if (ctx.flush_interval != 0)
+ {
+ char *flush_name;
+ user_data_t ud;
+ flush_callback_t *cb;
+
+ flush_name = plugin_flush_callback_name (name);
+ if (flush_name == NULL)
+ return (-1);
+
+ cb = malloc(sizeof(flush_callback_t));
+ if (cb == NULL)
+ {
+ ERROR ("plugin_register_flush: malloc failed.");
+ sfree(flush_name);
+ return (-1);
+ }
+
+ cb->name = strdup (name);
+ if (cb->name == NULL)
+ {
+ ERROR ("plugin_register_flush: strdup failed.");
+ sfree(cb);
+ sfree(flush_name);
+ return (-1);
+ }
+ cb->timeout = ctx.flush_timeout;
+
+ ud.data = cb;
+ ud.free_func = plugin_flush_timeout_callback_free;
+
+ status = plugin_register_complex_read (
+ /* group = */ "flush",
+ /* name = */ flush_name,
+ /* callback = */ plugin_flush_timeout_callback,
+ /* interval = */ ctx.flush_interval,
+ /* user data = */ &ud);
+
+ sfree(flush_name);
+ if (status != 0)
+ {
+ sfree(cb->name);
+ sfree(cb);
+ return status;
+ }
+ }
+
+ return 0;
} /* int plugin_register_flush */
int plugin_register_missing (const char *name,
int plugin_register_data_set (const data_set_t *ds)
{
data_set_t *ds_copy;
- int i;
+ size_t i;
if ((data_sets != NULL)
&& (c_avl_get (data_sets, ds->type, NULL) == 0))
int plugin_unregister_flush (const char *name)
{
- return (plugin_unregister (list_flush, name));
+ plugin_ctx_t ctx = plugin_get_ctx ();
+
+ if (ctx.flush_interval != 0)
+ {
+ char *flush_name;
+
+ flush_name = plugin_flush_callback_name (name);
+ if (flush_name != NULL)
+ {
+ plugin_unregister_read(flush_name);
+ sfree(flush_name);
+ }
+ }
+
+ return plugin_unregister (list_flush, name);
}
int plugin_unregister_missing (const char *name)
if (ds->ds_num != vl->values_len)
{
ERROR ("plugin_dispatch_values: ds->type = %s: "
- "(ds->ds_num = %i) != "
- "(vl->values_len = %i)",
+ "(ds->ds_num = %zu) != "
+ "(vl->values_len = %zu)",
ds->type, ds->ds_num, vl->values_len);
return (-1);
}
diff --git a/src/daemon/plugin.h b/src/daemon/plugin.h
index 70a22326e09f7b3f492877711e6b5152e5e369c8..b1adb527bb46536334af708275e1cbd0232a4f1d 100644 (file)
--- a/src/daemon/plugin.h
+++ b/src/daemon/plugin.h
struct value_list_s
{
value_t *values;
- int values_len;
+ size_t values_len;
cdtime_t time;
cdtime_t interval;
char host[DATA_MAX_NAME_LEN];
struct data_set_s
{
char type[DATA_MAX_NAME_LEN];
- int ds_num;
+ size_t ds_num;
data_source_t *ds;
};
typedef struct data_set_s data_set_t;
struct plugin_ctx_s
{
cdtime_t interval;
+ cdtime_t flush_interval;
+ cdtime_t flush_timeout;
};
typedef struct plugin_ctx_s plugin_ctx_t;
* "plugin_register_complex_read" returns an error (non-zero). */
int plugin_register_complex_read (const char *group, const char *name,
plugin_read_cb callback,
- const struct timespec *interval,
+ cdtime_t interval,
user_data_t *user_data);
int plugin_register_write (const char *name,
plugin_write_cb callback, user_data_t *user_data);
index 865288099500979c5ebaeab904899693a8e2cff1..f7bf1c016ad894f926003ad179112a6196edd161 100644 (file)
--- a/src/daemon/plugin_mock.c
+++ b/src/daemon/plugin_mock.c
#include "plugin.h"
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc = NULL;
+#endif /* HAVE_LIBKSTAT */
+
void plugin_log (int level, char const *format, ...)
{
char buffer[1024];
index c0e61c54b0e9e52168c85b31c9cd7bd9b422efde..75a980aa2a9801c2d754362beb1ca2e12642c820 100644 (file)
--- a/src/daemon/types_list.c
+++ b/src/daemon/types_list.c
char *fields[64];
size_t fields_num;
data_set_t *ds;
- int i;
+ size_t i;
fields_num = strsplit (buf, fields, 64);
if (fields_num < 2)
if (parse_ds (ds->ds + i, fields[i + 1], strlen (fields[i + 1])) != 0)
{
sfree (ds->ds);
- ERROR ("types_list: parse_line: Cannot parse data source #%i "
+ ERROR ("types_list: parse_line: Cannot parse data source #%zu "
"of data set %s", i, ds->type);
return;
}
index 76213955ca168dc17c9b01833b15fdd5afe3c517..3f7a596b1d6acae1b4ce6a4e82db7346a3ac78d3 100644 (file)
--- a/src/daemon/utils_cache.c
+++ b/src/daemon/utils_cache.c
typedef struct cache_entry_s
{
char name[6 * DATA_MAX_NAME_LEN];
- int values_num;
+ size_t values_num;
gauge_t *values_gauge;
value_t *values_raw;
/* Time contained in the package
return (strcmp (a->name, b->name));
} /* int cache_compare */
-static cache_entry_t *cache_alloc (int values_num)
+static cache_entry_t *cache_alloc (size_t values_num)
{
cache_entry_t *ce;
static void uc_check_range (const data_set_t *ds, cache_entry_t *ce)
{
- int i;
+ size_t i;
for (i = 0; i < ds->ds_num; i++)
{
static int uc_insert (const data_set_t *ds, const value_list_t *vl,
const char *key)
{
- int i;
char *key_copy;
cache_entry_t *ce;
+ size_t i;
/* `cache_lock' has been locked by `uc_update' */
if (ce == NULL)
{
sfree (key_copy);
- ERROR ("uc_insert: cache_alloc (%i) failed.", ds->ds_num);
+ ERROR ("uc_insert: cache_alloc (%zu) failed.", ds->ds_num);
return (-1);
}
char name[6 * DATA_MAX_NAME_LEN];
cache_entry_t *ce = NULL;
int status;
- int i;
+ size_t i;
if (FORMAT_VL (name, sizeof (name), vl) != 0)
{
{
case DS_TYPE_COUNTER:
{
- counter_t diff;
-
- /* check if the counter has wrapped around */
- if (vl->values[i].counter < ce->values_raw[i].counter)
- {
- if (ce->values_raw[i].counter <= 4294967295U)
- diff = (4294967295U - ce->values_raw[i].counter)
- + vl->values[i].counter;
- else
- diff = (18446744073709551615ULL - ce->values_raw[i].counter)
- + vl->values[i].counter;
- }
- else /* counter has NOT wrapped around */
- {
- diff = vl->values[i].counter - ce->values_raw[i].counter;
- }
-
+ counter_t diff = counter_diff (ce->values_raw[i].counter, vl->values[i].counter);
ce->values_gauge[i] = ((double) diff)
/ (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
ce->values_raw[i].counter = vl->values[i].counter;
case DS_TYPE_DERIVE:
{
- derive_t diff;
-
- diff = vl->values[i].derive - ce->values_raw[i].derive;
+ derive_t diff = vl->values[i].derive - ce->values_raw[i].derive;
ce->values_gauge[i] = ((double) diff)
/ (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
return (-1);
} /* switch (ds->ds[i].type) */
- DEBUG ("uc_update: %s: ds[%i] = %lf", name, i, ce->values_gauge[i]);
+ DEBUG ("uc_update: %s: ds[%zu] = %lf", name, i, ce->values_gauge[i]);
} /* for (i) */
/* Update the history if it exists. */
* values are returned. */
if (ret_num != (size_t) ds->ds_num)
{
- ERROR ("utils_cache: uc_get_rate: ds[%s] has %i values, "
+ ERROR ("utils_cache: uc_get_rate: ds[%s] has %zu values, "
"but uc_get_rate_by_name returned %zu.",
ds->type, ds->ds_num, ret_num);
sfree (ret);
index 6c78d64dc86c01bc731ff5a09ed6688fd94a5587..37f21edb0f9023d1e3132999b75953e6e6cbec17 100644 (file)
#include "utils_cache.h"
-gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl)
+gauge_t *uc_get_rate (__attribute((unused)) data_set_t const *ds,
+ __attribute((unused)) value_list_t const *vl)
{
return (NULL);
}
index 2f28eb9b141fabbdaf452b227727dfa3f1b40bd5..43634df2d6a0a7ef4a8d586b6ea97f6522fb0205 100644 (file)
--- a/src/daemon/utils_subst.c
+++ b/src/daemon/utils_subst.c
#include "collectd.h"
#include "common.h"
-char *subst (char *buf, size_t buflen, const char *string, int off1, int off2,
+char *subst (char *buf, size_t buflen, const char *string, size_t off1, size_t off2,
const char *replacement)
{
- char *buf_ptr = buf;
- size_t len = buflen;
+ char *out = buf;
- if ((NULL == buf) || (0 >= buflen) || (NULL == string)
- || (0 > off1) || (0 > off2) || (off1 > off2)
- || (NULL == replacement))
+ char const *front;
+ char const *back;
+ size_t front_len;
+ size_t replacement_len;
+ size_t back_len;
+
+ if ((NULL == buf) || (0 == buflen) || (NULL == string) || (NULL == replacement))
return NULL;
- sstrncpy (buf_ptr, string,
- ((size_t)off1 + 1 > buflen) ? buflen : (size_t)off1 + 1);
- buf_ptr += off1;
- len -= off1;
+ size_t string_len = strlen (string);
+ if ((off1 > string_len) || (off2 > string_len) || (off1 > off2))
+ return NULL;
- if (0 >= len)
- return buf;
+ front = string;
+ back = string + off2;
+ front_len = off1;
+ replacement_len = strlen (replacement);
+ back_len = strlen (back);
+
+ if (front_len >= buflen) {
+ front_len = buflen - 1;
+ replacement_len = 0;
+ back_len = 0;
+ } else if ((front_len + replacement_len) >= buflen) {
+ replacement_len = buflen - (front_len + 1);
+ back_len = 0;
+ } else if ((front_len + replacement_len + back_len) >= buflen) {
+ back_len = buflen - (front_len + replacement_len + 1);
+ } else {
+ buflen = front_len + replacement_len + back_len + 1;
+ }
+ assert ((front_len + replacement_len + back_len) == (buflen - 1));
- sstrncpy (buf_ptr, replacement, len);
- buf_ptr += strlen (replacement);
- len -= strlen (replacement);
+ if (front_len != 0) {
+ sstrncpy (out, front, front_len + 1);
+ out += front_len;
+ }
- if (0 >= len)
- return buf;
+ if (replacement_len != 0) {
+ sstrncpy (out, replacement, replacement_len + 1);
+ out += replacement_len;
+ }
- sstrncpy (buf_ptr, string + off2, len);
+ if (back_len != 0) {
+ sstrncpy (out, back, back_len + 1);
+ out += back_len;
+ }
+
+ out[0] = 0;
return buf;
} /* subst */
char *subst_string (char *buf, size_t buflen, const char *string,
const char *needle, const char *replacement)
{
- char *temp;
size_t needle_len;
size_t i;
|| (needle == NULL) || (replacement == NULL))
return (NULL);
- temp = (char *) malloc (buflen);
- if (temp == NULL)
- {
- ERROR ("subst_string: malloc failed.");
- return (NULL);
- }
-
needle_len = strlen (needle);
- strncpy (buf, string, buflen);
+ sstrncpy (buf, string, buflen);
/* Limit the loop to prevent endless loops. */
for (i = 0; i < buflen; i++)
{
+ char temp[buflen];
char *begin_ptr;
size_t begin;
i, string, needle, replacement);
}
- sfree (temp);
return (buf);
} /* char *subst_string */
diff --git a/src/daemon/utils_subst_test.c b/src/daemon/utils_subst_test.c
--- /dev/null
@@ -0,0 +1,133 @@
+/**
+ * collectd - src/daemon/utils_subst_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#include "testing.h"
+#include "collectd.h"
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "utils_subst.h"
+
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc;
+#endif /* HAVE_LIBKSTAT */
+
+DEF_TEST(subst)
+{
+ struct {
+ char *str;
+ int off1;
+ int off2;
+ char *rplmt;
+ char *want;
+ } cases[] = {
+ {"foo_____bar", 3, 8, " - ", "foo - bar"}, /* documentation example */
+ {"foo bar", 0, 2, "m", "mo bar"}, /* beginning, shorten */
+ {"foo bar", 0, 1, "m", "moo bar"}, /* beginning, same length */
+ {"foo bar", 0, 3, "milk", "milk bar"}, /* beginning, extend */
+ {"foo bar", 3, 6, "de", "fooder"}, /* center, shorten */
+ {"foo bar", 2, 6, "rste", "forster"}, /* center, same length */
+ {"foo bar", 1, 3, "ish", "fish bar"}, /* center, extend */
+ {"foo bar", 2, 7, "ul", "foul"}, /* end, shorten */
+ {"foo bar", 3, 7, "lish", "foolish"}, /* end, same length */
+ {"foo bar", 3, 7, "dwear", "foodwear"}, /* end, extend */
+ /* truncation (buffer is 16 chars) */
+ {"01234567890123", 8, 8, "", "01234567890123"},
+ {"01234567890123", 8, 8, "*", "01234567*890123"},
+ {"01234567890123", 8, 8, "**", "01234567**89012"},
+ /* input > buffer */
+ {"012345678901234----", 0, 0, "", "012345678901234"},
+ {"012345678901234----", 17, 18, "", "012345678901234"},
+ {"012345678901234----", 0, 3, "", "345678901234---"},
+ {"012345678901234----", 0, 4, "", "45678901234----"},
+ {"012345678901234----", 0, 5, "", "5678901234----"},
+ {"012345678901234----", 8, 8, "#", "01234567#890123"},
+ {"012345678901234----", 12, 12, "##", "012345678901##2"},
+ {"012345678901234----", 13, 13, "##", "0123456789012##"},
+ {"012345678901234----", 14, 14, "##", "01234567890123#"},
+ {"012345678901234----", 15, 15, "##", "012345678901234"},
+ {"012345678901234----", 16, 16, "##", "012345678901234"},
+ /* error cases */
+ {NULL, 3, 4, "_", NULL}, /* no input */
+ {"foo bar", 3, 10, "_", NULL}, /* offset exceeds input */
+ {"foo bar", 10, 13, "_", NULL}, /* offset exceeds input */
+ {"foo bar", 4, 3, "_", NULL}, /* off1 > off2 */
+ {"foo bar", 3, 4, NULL, NULL}, /* no replacement */
+ };
+ size_t i;
+
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ char buffer[16] = "!!!!!!!!!!!!!!!";
+
+ if (cases[i].want == NULL) {
+ OK(subst (buffer, sizeof (buffer), cases[i].str, cases[i].off1, cases[i].off2, cases[i].rplmt) == NULL);
+ continue;
+ }
+
+ OK(subst (buffer, sizeof (buffer), cases[i].str, cases[i].off1, cases[i].off2, cases[i].rplmt) == &buffer[0]);
+ EXPECT_EQ_STR(cases[i].want, buffer);
+ }
+
+ return 0;
+}
+
+DEF_TEST(subst_string)
+{
+ struct {
+ char *str; char *srch; char *rplmt; char *want;
+ } cases[] = {
+ {"Hello %{name}", "%{name}", "world", "Hello world"},
+ {"abcccccc", "abc", "cab", "ccccccab"},
+ {"(((()(())))())", "()", "", ""},
+ {"food booth", "oo", "ee", "feed beeth"},
+ {"foo bar", "baz", "qux", "foo bar"},
+ {"foo bar", "oo", "oo", "foo bar"},
+ {"sixteen chars", "chars", "characters", "sixteen charact"},
+ };
+ size_t i;
+
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ char buffer[16];
+
+ if (cases[i].want == NULL) {
+ OK(subst_string (buffer, sizeof (buffer), cases[i].str, cases[i].srch, cases[i].rplmt) == NULL);
+ continue;
+ }
+
+ OK(subst_string (buffer, sizeof (buffer), cases[i].str, cases[i].srch, cases[i].rplmt) == buffer);
+ EXPECT_EQ_STR(cases[i].want, buffer);
+ }
+
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(subst);
+ RUN_TEST(subst_string);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
index 6603c15e89f161afc832a5e2cd8ef08b335564ea..5d905d9b7c2dbe9fad9fcf6e45ad027a0e56947b 100644 (file)
--- a/src/daemon/utils_time.c
+++ b/src/daemon/utils_time.c
if (max - len > 2) {
int n = snprintf (s + len, max - len, ".%09i", (int)t_spec.tv_nsec);
- len += (n < max - len) ? n : max - len;
+ len += (n < 0) ? 0
+ : (((size_t) n) < (max - len)) ? ((size_t) n)
+ : (max - len);
}
if (max - len > 3) {
- int n = strftime (s + len, max - len, "%z", &t_tm);
+ size_t n = strftime (s + len, max - len, "%z", &t_tm);
len += (n < max - len) ? n : max - len;
}
index 9b08e8e4de68f011d24b4dc947c9d23922506544..6566a739bdf8be34b695a3d715dd90b7644e2f23 100644 (file)
--- a/src/daemon/utils_time.h
+++ b/src/daemon/utils_time.h
/**
- * collectd - src/utils_time.h
- * Copyright (C) 2010 Florian octo Forster
+ * collectd - src/daemon/utils_time.h
+ * Copyright (C) 2010-2015 Florian octo Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* DEALINGS IN THE SOFTWARE.
*
* Authors:
- * Florian octo Forster <ff at octo.it>
+ * Florian octo Forster <octo at collectd.org>
**/
#ifndef UTILS_TIME_H
/* typedef uint64_t cdtime_t; */
/* 2^30 = 1073741824 */
-#define TIME_T_TO_CDTIME_T(t) (((cdtime_t) (t)) * 1073741824)
-#define CDTIME_T_TO_TIME_T(t) ((time_t) ((t) / 1073741824))
+#define TIME_T_TO_CDTIME_T(t) (((cdtime_t) (t)) << 30)
+
+#define MS_TO_CDTIME_T(ms) (((((cdtime_t) (ms)) / 1000) << 30) | \
+ ((((((cdtime_t) (ms)) % 1000) << 30) + 500) / 1000))
+#define US_TO_CDTIME_T(us) (((((cdtime_t) (us)) / 1000000) << 30) | \
+ ((((((cdtime_t) (us)) % 1000000) << 30) + 500000) / 1000000))
+#define NS_TO_CDTIME_T(ns) (((((cdtime_t) (ns)) / 1000000000) << 30) | \
+ ((((((cdtime_t) (ns)) % 1000000000) << 30) + 500000000) / 1000000000))
+
+#define CDTIME_T_TO_TIME_T(t) ((time_t) (((t) + (1 << 29)) >> 30))
+#define CDTIME_T_TO_MS(t) ((uint64_t) ((((t) >> 30) * 1000) + \
+ ((((t) & 0x3fffffff) * 1000 + (1 << 29)) >> 30)))
+#define CDTIME_T_TO_US(t) ((uint64_t) ((((t) >> 30) * 1000000) + \
+ ((((t) & 0x3fffffff) * 1000000 + (1 << 29)) >> 30)))
+#define CDTIME_T_TO_NS(t) ((uint64_t) ((((t) >> 30) * 1000000000) + \
+ ((((t) & 0x3fffffff) * 1000000000 + (1 << 29)) >> 30)))
#define CDTIME_T_TO_DOUBLE(t) (((double) (t)) / 1073741824.0)
#define DOUBLE_TO_CDTIME_T(d) ((cdtime_t) ((d) * 1073741824.0))
-#define MS_TO_CDTIME_T(ms) ((cdtime_t) (((double) (ms)) * 1073741.824))
-#define CDTIME_T_TO_MS(t) ((long) (((double) (t)) / 1073741.824))
-#define US_TO_CDTIME_T(us) ((cdtime_t) (((double) (us)) * 1073.741824))
-#define CDTIME_T_TO_US(t) ((suseconds_t) (((double) (t)) / 1073.741824))
-#define NS_TO_CDTIME_T(ns) ((cdtime_t) (((double) (ns)) * 1.073741824))
-#define CDTIME_T_TO_NS(t) ((long) (((double) (t)) / 1.073741824))
-
#define CDTIME_T_TO_TIMEVAL(cdt,tvp) do { \
(tvp)->tv_sec = CDTIME_T_TO_TIME_T (cdt); \
- (tvp)->tv_usec = CDTIME_T_TO_US ((cdt) % 1073741824); \
+ (tvp)->tv_usec = (suseconds_t) CDTIME_T_TO_US ((cdt) & 0x3fffffff); \
} while (0)
-#define TIMEVAL_TO_CDTIME_T(tv) (TIME_T_TO_CDTIME_T ((tv)->tv_sec) \
- + US_TO_CDTIME_T ((tv)->tv_usec))
+#define TIMEVAL_TO_CDTIME_T(tv) US_TO_CDTIME_T(1000000 * (tv)->tv_sec + (tv)->tv_usec)
#define CDTIME_T_TO_TIMESPEC(cdt,tsp) do { \
(tsp)->tv_sec = CDTIME_T_TO_TIME_T (cdt); \
- (tsp)->tv_nsec = CDTIME_T_TO_NS ((cdt) % 1073741824); \
+ (tsp)->tv_nsec = (long) CDTIME_T_TO_NS ((cdt) & 0x3fffffff); \
} while (0)
-#define TIMESPEC_TO_CDTIME_T(ts) (TIME_T_TO_CDTIME_T ((ts)->tv_sec) \
- + NS_TO_CDTIME_T ((ts)->tv_nsec))
+#define TIMESPEC_TO_CDTIME_T(ts) NS_TO_CDTIME_T(1000000000ULL * (ts)->tv_sec + (ts)->tv_nsec)
cdtime_t cdtime (void);
index 5edfe6f922a751c2df1a29a245cd83ad9e5c938f..217515ebd752e99c1b5a7cedac4c347ca7614394 100644 (file)
cdtime_t cdtime (void)
{
- return (0);
+ return ((cdtime_t) 1542455354518929408ULL);
}
diff --git a/src/daemon/utils_time_test.c b/src/daemon/utils_time_test.c
--- /dev/null
@@ -0,0 +1,125 @@
+/**
+ * collectd - src/daemon/utils_time_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#define DBL_PRECISION 1e-3
+
+#include "testing.h"
+#include "collectd.h"
+#include "utils_time.h"
+
+DEF_TEST(conversion)
+{
+ struct {
+ cdtime_t t;
+ double d;
+ time_t tt;
+ uint64_t ms;
+ struct timeval tv;
+ struct timespec ts;
+ } cases[] = {
+ /* cdtime double time_t milliseconds timeval timespec */
+ { 0, 0.0 , 0, 0, { 0, 0}, { 0, 0}},
+ { 10737418240ULL, 10.0 , 10, 10000, { 10, 0}, { 10, 0}},
+ {1542908534771941376ULL, 1436945549.0 , 1436945549, 1436945549000ULL, {1436945549, 0}, {1436945549, 0}},
+ {1542908535540740522ULL, 1436945549.716, 1436945550, 1436945549716ULL, {1436945549, 716000}, {1436945549, 716000000}},
+ // 1426076671.123 * 2^30 = 1531238166015458148.352
+ {1531238166015458148ULL, 1426076671.123, 1426076671, 1426076671123ULL, {1426076671, 123000}, {1426076671, 123000000}},
+ // 1426076681.234 * 2^30 = 1531238176872061730.816
+ {1531238176872061731ULL, 1426076681.234, 1426076681, 1426076681234ULL, {1426076681, 234000}, {1426076681, 234000000}},
+ // 1426083986.314 * 2^30 = 1531246020641985396.736
+ {1531246020641985397ULL, 1426083986.314, 1426083986, 1426083986314ULL, {1426083986, 314000}, {1426083986, 314000000}},
+ // 1426083986.494142531 * 2^30 = 1531246020835411966.5
+ {1531246020835411967ULL, 1426083986.494, 1426083986, 1426083986494ULL, {1426083986, 494143}, {1426083986, 494142531}},
+ // 1426083986.987410814 * 2^30 = 1531246021365054752.4
+ {1531246021365054752ULL, 1426083986.987, 1426083987, 1426083986987ULL, {1426083986, 987411}, {1426083986, 987410814}},
+
+ /* These cases test the cdtime_t -> ns conversion rounds correctly. */
+ // 1546167635576736987 / 2^30 = 1439980823.1524536265...
+ {1546167635576736987ULL, 1439980823.152, 1439980823, 1439980823152ULL, {1439980823, 152454}, {1439980823, 152453627}},
+ // 1546167831554815222 / 2^30 = 1439981005.6712620165...
+ {1546167831554815222ULL, 1439981005.671, 1439981006, 1439981005671ULL, {1439981005, 671262}, {1439981005, 671262017}},
+ // 1546167986577716567 / 2^30 = 1439981150.0475896215...
+ {1546167986577716567ULL, 1439981150.048, 1439981150, 1439981150048ULL, {1439981150, 47590}, {1439981005, 47589622}},
+ };
+ size_t i;
+
+ for (i = 0; i < (sizeof (cases) / sizeof (cases[0])); i++) {
+ struct timeval tv;
+ struct timespec ts;
+
+ // cdtime -> s
+ EXPECT_EQ_UINT64 (cases[i].tt, CDTIME_T_TO_TIME_T (cases[i].t));
+
+ // cdtime -> ms
+ EXPECT_EQ_UINT64(cases[i].ms, CDTIME_T_TO_MS (cases[i].t));
+
+ // cdtime -> us
+ CDTIME_T_TO_TIMEVAL (cases[i].t, &tv);
+ EXPECT_EQ_UINT64 (cases[i].tv.tv_usec, tv.tv_usec);
+
+ // cdtime -> ns
+ CDTIME_T_TO_TIMESPEC (cases[i].t, &ts);
+ EXPECT_EQ_UINT64 (cases[i].ts.tv_nsec, ts.tv_nsec);
+
+ // cdtime -> double
+ EXPECT_EQ_DOUBLE (cases[i].d, CDTIME_T_TO_DOUBLE (cases[i].t));
+ }
+
+ return 0;
+}
+
+/* These cases test the ns -> cdtime_t conversion rounds correctly. */
+DEF_TEST(ns_to_cdtime)
+{
+ struct {
+ uint64_t ns;
+ cdtime_t want;
+ } cases[] = {
+ // 1439981652801860766 * 2^30 / 10^9 = 1546168526406004689.4
+ {1439981652801860766ULL, 1546168526406004689ULL},
+ // 1439981836985281914 * 2^30 / 10^9 = 1546168724171447263.4
+ {1439981836985281914ULL, 1546168724171447263ULL},
+ // 1439981880053705608 * 2^30 / 10^9 = 1546168770415815077.4
+ {1439981880053705608ULL, 1546168770415815077ULL},
+ };
+ size_t i;
+
+ for (i = 0; i < (sizeof (cases) / sizeof (cases[0])); i++) {
+ EXPECT_EQ_UINT64 (cases[i].want, NS_TO_CDTIME_T (cases[i].ns));
+ }
+
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(conversion);
+ RUN_TEST(ns_to_cdtime);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/dbi.c b/src/dbi.c
index a7963ea223371f5d70a4ef63f2d0a3a6263db22a..94d0762d261fada2a4ebda04278f43947dc0b006 100644 (file)
--- a/src/dbi.c
+++ b/src/dbi.c
char *name;
char *select_db;
+ cdtime_t interval;
+
char *driver;
char *host;
cdbi_driver_option_t *driver_options;
*
* <Database "plugin_instance1">
* Driver "mysql"
+ * Interval 120
* DriverOption "hostname" "localhost"
* ...
* Query "plugin_instance0"
&db->queries, &db->queries_num);
else if (strcasecmp ("Host", child->key) == 0)
status = cf_util_get_string (child, &db->host);
+ else if (strcasecmp ("Interval", child->key) == 0)
+ status = cf_util_get_cdtime(child, &db->interval);
else
{
WARNING ("dbi plugin: Option `%s' not allowed here.", child->key);
while ((status == 0) && (db->queries_num > 0))
{
+ size_t j;
db->q_prep_areas = (udb_query_preparation_area_t **) calloc (
db->queries_num, sizeof (*db->q_prep_areas));
break;
}
- for (i = 0; i < db->queries_num; ++i)
+ for (j = 0; j < db->queries_num; ++j)
{
- db->q_prep_areas[i]
- = udb_query_allocate_preparation_area (db->queries[i]);
+ db->q_prep_areas[j]
+ = udb_query_allocate_preparation_area (db->queries[j]);
- if (db->q_prep_areas[i] == NULL)
+ if (db->q_prep_areas[j] == NULL)
{
WARNING ("dbi plugin: udb_query_allocate_preparation_area failed");
status = -1;
plugin_register_complex_read (/* group = */ NULL,
/* name = */ name ? name : db->name,
/* callback = */ cdbi_read_database,
- /* interval = */ NULL,
+ /* interval = */ (db->interval > 0) ? db->interval : 0,
/* user_data = */ &ud);
free (name);
}
udb_query_prepare_result (q, prep_area, (db->host ? db->host : hostname_g),
/* plugin = */ "dbi", db->name,
- column_names, column_num, /* interval = */ 0);
+ column_names, column_num, /* interval = */ (db->interval > 0) ? db->interval : 0);
/* 0 = error; 1 = success; */
status = dbi_result_first_row (res); /* {{{ */
diff --git a/src/disk.c b/src/disk.c
index 1c3dd98d7d2a93318e8ce0318fbd8acbbd15e016..8f8f370240ba2f99c48dcfdf2d0efe4b77d05521 100644 (file)
--- a/src/disk.c
+++ b/src/disk.c
#if HAVE_IOKIT_IOBSD_H
# include <IOKit/IOBSD.h>
#endif
+#if KERNEL_FREEBSD
+#include <devstat.h>
+#include <libgeom.h>
+#endif
#if HAVE_LIMITS_H
# include <limits.h>
static diskstats_t *disklist;
/* #endif KERNEL_LINUX */
+#elif KERNEL_FREEBSD
+static struct gmesh geom_tree;
+/* #endif KERNEL_FREEBSD */
#elif HAVE_LIBKSTAT
#define MAX_NUMDISK 1024
/* do nothing */
/* #endif KERNEL_LINUX */
+#elif KERNEL_FREEBSD
+ int rv;
+
+ rv = geom_gettree(&geom_tree);
+ if (rv != 0) {
+ ERROR ("geom_gettree() failed, returned %d", rv);
+ return (-1);
+ }
+ rv = geom_stats_open();
+ if (rv != 0) {
+ ERROR ("geom_stats_open() failed, returned %d", rv);
+ return (-1);
+ }
+/* #endif KERNEL_FREEBSD */
+
#elif HAVE_LIBKSTAT
kstat_t *ksp_chain;
IOObjectRelease (disk_list);
/* #endif HAVE_IOKIT_IOKITLIB_H */
+#elif KERNEL_FREEBSD
+ int retry, dirty;
+
+ void *snap = NULL;
+ struct devstat *snap_iter;
+
+ struct gident *geom_id;
+
+ const char *disk_name;
+ long double read_time, write_time;
+
+ for (retry = 0, dirty = 1; retry < 5 && dirty == 1; retry++) {
+ if (snap != NULL)
+ geom_stats_snapshot_free(snap);
+
+ /* Get a fresh copy of stats snapshot */
+ snap = geom_stats_snapshot_get();
+ if (snap == NULL) {
+ ERROR("disk plugin: geom_stats_snapshot_get() failed.");
+ return (-1);
+ }
+
+ /* Check if we have dirty read from this snapshot */
+ dirty = 0;
+ geom_stats_snapshot_reset(snap);
+ while ((snap_iter = geom_stats_snapshot_next(snap)) != NULL) {
+ if (snap_iter->id == NULL)
+ continue;
+ geom_id = geom_lookupid(&geom_tree, snap_iter->id);
+
+ /* New device? refresh GEOM tree */
+ if (geom_id == NULL) {
+ geom_deletetree(&geom_tree);
+ if (geom_gettree(&geom_tree) != 0) {
+ ERROR("disk plugin: geom_gettree() failed");
+ geom_stats_snapshot_free(snap);
+ return (-1);
+ }
+ geom_id = geom_lookupid(&geom_tree, snap_iter->id);
+ }
+ /*
+ * This should be rare: the device come right before we take the
+ * snapshot and went away right after it. We will handle this
+ * case later, so don't mark dirty but silently ignore it.
+ */
+ if (geom_id == NULL)
+ continue;
+
+ /* Only collect PROVIDER data */
+ if (geom_id->lg_what != ISPROVIDER)
+ continue;
+
+ /* Only collect data when rank is 1 (physical devices) */
+ if (((struct gprovider *)(geom_id->lg_ptr))->lg_geom->lg_rank != 1)
+ continue;
+
+ /* Check if this is a dirty read quit for another try */
+ if (snap_iter->sequence0 != snap_iter->sequence1) {
+ dirty = 1;
+ break;
+ }
+ }
+ }
+
+ /* Reset iterator */
+ geom_stats_snapshot_reset(snap);
+ for (;;) {
+ snap_iter = geom_stats_snapshot_next(snap);
+ if (snap_iter == NULL)
+ break;
+
+ if (snap_iter->id == NULL)
+ continue;
+ geom_id = geom_lookupid(&geom_tree, snap_iter->id);
+ if (geom_id == NULL)
+ continue;
+ if (geom_id->lg_what != ISPROVIDER)
+ continue;
+ if (((struct gprovider *)(geom_id->lg_ptr))->lg_geom->lg_rank != 1)
+ continue;
+ /* Skip dirty reads, if present */
+ if (dirty && (snap_iter->sequence0 != snap_iter->sequence1))
+ continue;
+
+ disk_name = ((struct gprovider *)geom_id->lg_ptr)->lg_name;
+
+ if ((snap_iter->bytes[DEVSTAT_READ] != 0) || (snap_iter->bytes[DEVSTAT_WRITE] != 0)) {
+ disk_submit(disk_name, "disk_octets",
+ (derive_t)snap_iter->bytes[DEVSTAT_READ],
+ (derive_t)snap_iter->bytes[DEVSTAT_WRITE]);
+ }
+
+ if ((snap_iter->operations[DEVSTAT_READ] != 0) || (snap_iter->operations[DEVSTAT_WRITE] != 0)) {
+ disk_submit(disk_name, "disk_ops",
+ (derive_t)snap_iter->operations[DEVSTAT_READ],
+ (derive_t)snap_iter->operations[DEVSTAT_WRITE]);
+ }
+
+ read_time = devstat_compute_etime(&snap_iter->duration[DEVSTAT_READ], NULL);
+ write_time = devstat_compute_etime(&snap_iter->duration[DEVSTAT_WRITE], NULL);
+ if ((read_time != 0) || (write_time != 0)) {
+ disk_submit (disk_name, "disk_time",
+ (derive_t)(read_time*1000), (derive_t)(write_time*1000));
+ }
+ }
+ geom_stats_snapshot_free(snap);
+
#elif KERNEL_LINUX
FILE *fh;
char buffer[1024];
diff --git a/src/email.c b/src/email.c
index 365af274d4274cb70d42215e04c11e2fb08c3851..1bf9addaea09631f005ec96af2e97c9fdd602a56 100644 (file)
--- a/src/email.c
+++ b/src/email.c
# include <pthread.h>
#endif
-#include <sys/socket.h>
#include <sys/un.h>
#include <sys/select.h>
diff --git a/src/gmond.c b/src/gmond.c
index 336fbb9468b8eeb6c1002fc79dea02136829390d..c778d48dceb9a1ff4848c72571107d8f87c63471 100644 (file)
--- a/src/gmond.c
+++ b/src/gmond.c
#if HAVE_PTHREAD_H
# include <pthread.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NETDB_H
# include <netdb.h>
#endif
struct metric_map_s
{
- char *ganglia_name;
- char *type;
- char *type_instance;
- char *ds_name;
- int ds_type;
- int ds_index;
+ char *ganglia_name;
+ char *type;
+ char *type_instance;
+ char *ds_name;
+ int ds_type;
+ size_t ds_index;
};
typedef struct metric_map_s metric_map_t;
return (NULL);
/* Look up the DS type and ds_index. */
- if ((map[i].ds_type < 0) || (map[i].ds_index < 0)) /* {{{ */
+ if (map[i].ds_type < 0) /* {{{ */
{
const data_set_t *ds;
}
else
{
- int j;
+ size_t j;
for (j = 0; j < ds->ds_num; j++)
if (strcasecmp (ds->ds[j].name, map[i].ds_name) == 0)
static int staging_entry_update (const char *host, const char *name, /* {{{ */
const char *type, const char *type_instance,
- int ds_index, int ds_type, value_t value)
+ size_t ds_index, int ds_type, value_t value)
{
const data_set_t *ds;
staging_entry_t *se;
if (ds->ds_num <= ds_index)
{
- ERROR ("gmond plugin: Invalid index %i: %s has only %i data source(s).",
+ ERROR ("gmond plugin: Invalid index %zu: %s has only %zu data source(s).",
ds_index, ds->type, ds->ds_num);
return (-1);
}
diff --git a/src/hddtemp.c b/src/hddtemp.c
index 82c158cab17180dc18a4d5e878d1704b60e081ce..3de18fd91354d166a58beff919d4b38e65e0fe33 100644 (file)
--- a/src/hddtemp.c
+++ b/src/hddtemp.c
#include "configfile.h"
# include <netdb.h>
-# include <sys/socket.h>
# include <netinet/in.h>
# include <netinet/tcp.h>
# include <libgen.h> /* for basename */
diff --git a/src/interface.c b/src/interface.c
index df8ffb46c34522ee5696b22a3409a687c37161e4..e17711e3105ae31ccd106576ede46b72dc5b48a4 100644 (file)
--- a/src/interface.c
+++ b/src/interface.c
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
/* One cannot include both. This sucks. */
#if HAVE_LINUX_IF_H
diff --git a/src/iptables.c b/src/iptables.c
index 606b24d9afdacfeda05ecd30a44f4976d674377a..806b7a457f76308c3226aa3255444e97eeda20d5 100644 (file)
--- a/src/iptables.c
+++ b/src/iptables.c
#include "plugin.h"
#include "configfile.h"
-#include <sys/socket.h>
-
#include <libiptc/libiptc.h>
#include <libiptc/libip6tc.h>
diff --git a/src/ipvs.c b/src/ipvs.c
index cbb554286bd08f292219ff91b8a81a601925638d..4345a46532237081bcd8ff075102e6d34635f4a7 100644 (file)
--- a/src/ipvs.c
+++ b/src/ipvs.c
#if HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif /* HAVE_ARPA_INET_H */
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif /* HAVE_SYS_SOCKET_H */
#if HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
(se->protocol == IPPROTO_TCP) ? "TCP" : "UDP",
ntohs (se->port));
- if ((0 > len) || (size <= len)) {
+ if ((0 > len) || (size <= ((size_t) len))) {
log_err ("plugin instance truncated: %s", pi);
return -1;
}
len = ssnprintf (ti, size, "%s_%u", inet_ntoa (addr),
ntohs (de->port));
- if ((0 > len) || (size <= len)) {
+ if ((0 > len) || (size <= ((size_t) len))) {
log_err ("type instance truncated: %s", ti);
return -1;
}
char pi[DATA_MAX_NAME_LEN];
- int i = 0;
+ size_t i;
if (0 != get_pi (se, pi, sizeof (pi)))
{
static int cipvs_read (void)
{
struct ip_vs_get_services *services = NULL;
- int i = 0;
+ size_t i;
if (sockfd < 0)
return (-1);
diff --git a/src/java.c b/src/java.c
index c74fe6c79de8fee4a3e80cd3a6fd7f15ea7dcb62..6b92f54e966f313e907514d17569aed104312f1c 100644 (file)
--- a/src/java.c
+++ b/src/java.c
jmethodID m_add;
jobject o_type;
jobject o_dataset;
- int i;
+ size_t i;
/* Look up the org/collectd/api/DataSet class */
c_dataset = (*jvm_env)->FindClass (jvm_env, "org/collectd/api/DataSet");
jmethodID m_valuelist_constructor;
jobject o_valuelist;
int status;
- int i;
+ size_t i;
/* First, create a new ValueList instance..
* Look up the class.. */
ud.free_func = cjni_callback_info_destroy;
plugin_register_complex_read (/* group = */ NULL, cbi->name, cjni_read,
- /* interval = */ NULL, &ud);
+ /* interval = */ 0, &ud);
(*jvm_env)->DeleteLocalRef (jvm_env, o_read);
index 5abee2f1a44f1fd0abdce185c1cb390ffd00aeab..e81a59438394960ab8cb6b4b0c0e40a30ca6befa 100644 (file)
AUTOMAKE_OPTIONS = foreign no-dependencies
-if COMPILER_IS_GCC
-AM_CFLAGS = -Wall -Werror
-endif
-
pkginclude_HEADERS = collectd/client.h collectd/network.h collectd/network_buffer.h collectd/lcc_features.h
lib_LTLIBRARIES = libcollectdclient.la
nodist_pkgconfig_DATA = libcollectdclient.pc
index a97dc509e4d7ff7e94b491f28244ad9e9e1d10cc..eaee9c0f7cb0f411d199a1cfc8051212fe15fa84 100644 (file)
* beginning of the message. */
ptr = NULL;
errno = 0;
- res.status = strtol (buffer, &ptr, 0);
+ res.status = (int) strtol (buffer, &ptr, 0);
if ((errno != 0) || (ptr == &buffer[0]))
{
lcc_set_errno (c, errno);
index c390a1ce7cada8de9b029cb5d088de05ad0c8c3e..0539cd0c05266a9965ac522e4599b5fd5bf07bb4 100644 (file)
int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ */
{
- int if_index;
+ unsigned int if_index;
int status;
if ((srv == NULL) || (interface == NULL))
@@ -421,7 +421,7 @@ int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ *
memset (&mreq, 0, sizeof (mreq));
mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
mreq.imr_address.s_addr = ntohl (INADDR_ANY);
- mreq.imr_ifindex = if_index;
+ mreq.imr_ifindex = (int) if_index;
#else
struct ip_mreq mreq;
@@ -457,8 +457,8 @@ int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ *
/* else: Not a multicast interface. */
#if defined(SO_BINDTODEVICE)
- status = setsockopt (srv->fd, SOL_SOCKET, SO_BINDTODEVICE,
- interface, strlen (interface) + 1);
+ status = setsockopt (srv->fd, SOL_SOCKET, SO_BINDTODEVICE, interface,
+ (socklen_t) (strlen (interface) + 1));
if (status != 0)
return (-1);
#endif
index f422f5adcb905e1d2bb5abed011ba10424c779a6..d01c79dd3f164f5da66bf17b208c0af4d534164a 100644 (file)
--- a/src/liboconfig/oconfig.c
+++ b/src/liboconfig/oconfig.c
yyset_in (fh);
if (NULL == c_file) {
- int status;
-
status = snprintf (file, sizeof (file), "<fd#%d>", fileno (fh));
- if ((status < 0) || (status >= sizeof (file))) {
+ if ((status < 0) || (((size_t) status) >= sizeof (file))) {
c_file = "<unknown>";
}
else {
{
int i;
- ci_copy->values = (oconfig_value_t *) calloc (ci_orig->values_num,
- sizeof (*ci_copy->values));
+ ci_copy->values = (oconfig_value_t *) calloc ((size_t) ci_orig->values_num,
+ sizeof (*ci_copy->values));
if (ci_copy->values == NULL)
{
fprintf (stderr, "calloc failed.\n");
ci_copy->values[i].type = ci_orig->values[i].type;
if (ci_copy->values[i].type == OCONFIG_TYPE_STRING)
{
- ci_copy->values[i].value.string
- = strdup (ci_orig->values[i].value.string);
- if (ci_copy->values[i].value.string == NULL)
- {
- fprintf (stderr, "strdup failed.\n");
- oconfig_free (ci_copy);
- return (NULL);
- }
+ ci_copy->values[i].value.string = strdup (ci_orig->values[i].value.string);
+ if (ci_copy->values[i].value.string == NULL)
+ {
+ fprintf (stderr, "strdup failed.\n");
+ oconfig_free (ci_copy);
+ return (NULL);
+ }
}
else /* ci_copy->values[i].type != OCONFIG_TYPE_STRING) */
{
- ci_copy->values[i].value = ci_orig->values[i].value;
+ ci_copy->values[i].value = ci_orig->values[i].value;
}
}
} /* }}} if (ci_orig->values_num > 0) */
{
int i;
- ci_copy->children = (oconfig_item_t *) calloc (ci_orig->children_num,
- sizeof (*ci_copy->children));
+ ci_copy->children = (oconfig_item_t *) calloc ((size_t) ci_orig->children_num,
+ sizeof (*ci_copy->children));
if (ci_copy->children == NULL)
{
fprintf (stderr, "calloc failed.\n");
diff --git a/src/madwifi.c b/src/madwifi.c
index 13301fffe15aea8afbce76c3ce06105ededfa195..bb33b15d2c7818fe6cd3b623fd3fece4d1f47814 100644 (file)
--- a/src/madwifi.c
+++ b/src/madwifi.c
#include <dirent.h>
#include <sys/ioctl.h>
-#include <sys/socket.h>
#if !KERNEL_LINUX
# error "No applicable input method."
static inline int item_watched(int i)
{
assert (i >= 0);
- assert (i < ((STATIC_ARRAY_SIZE (watch_items) + 1) * 32));
+ assert (((size_t) i) < ((STATIC_ARRAY_SIZE (watch_items) + 1) * 32));
return watch_items[i / 32] & FLAG (i);
}
static inline int item_summed(int i)
{
assert (i >= 0);
- assert (i < ((STATIC_ARRAY_SIZE (misc_items) + 1) * 32));
+ assert (((size_t) i) < ((STATIC_ARRAY_SIZE (misc_items) + 1) * 32));
return misc_items[i / 32] & FLAG (i);
}
static int madwifi_real_init (void)
{
- int max = STATIC_ARRAY_SIZE (specs);
- int i;
+ size_t max = STATIC_ARRAY_SIZE (specs);
+ size_t i;
for (i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
bounds[i] = 0;
@@ -618,7 +617,7 @@ process_stat_struct (int which, const void *ptr, const char *dev, const char *ma
int i;
assert (which >= 1);
- assert (which < STATIC_ARRAY_SIZE (bounds));
+ assert (((size_t) which) < STATIC_ARRAY_SIZE (bounds));
for (i = bounds[which - 1]; i < bounds[which]; i++)
{
uint8_t buf[24*1024];
struct iwreq iwr;
uint8_t *cp;
- int len, nodes;
+ int nodes;
+ size_t len;
int status;
memset (&iwr, 0, sizeof (iwr));
index abde2b3495f818bf25b3188b4dadfd090210d6c9..e30ff91bc7f17e6a9983a9215e53497ea8c78794 100644 (file)
{
int num_counters;
int num_empty;
- int i;
+ size_t i;
if ((user_data == NULL) || (*user_data == NULL))
return (-1);
diff --git a/src/match_value.c b/src/match_value.c
index 4d49984f618173b48323634a3ed34a1b85cde048..9ffcecaae473b9bc24b49d721e5b2914ae4bcfbe 100644 (file)
--- a/src/match_value.c
+++ b/src/match_value.c
*/
static void mv_free_match (mv_match_t *m) /* {{{ */
{
- int i;
+ size_t i;
if (m == NULL)
return;
mv_match_t *m;
gauge_t *values;
int status;
- int i;
+ size_t i;
if ((user_data == NULL) || (*user_data == NULL))
return (-1);
diff --git a/src/mbmon.c b/src/mbmon.c
index d23062db2d54734551789c76cac837c9915c43f2..5e87f00b7087935786d695a6b37387df00901ce5 100644 (file)
--- a/src/mbmon.c
+++ b/src/mbmon.c
#include "configfile.h"
#include <netdb.h>
-#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
diff --git a/src/memcached.c b/src/memcached.c
index f6af4fc77c2019e3152f26af5aa77ac4b43cc26d..f684abffe9314515771d75cef1d1cd81143838ee 100644 (file)
--- a/src/memcached.c
+++ b/src/memcached.c
#include "configfile.h"
#include <netdb.h>
-#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
status = plugin_register_complex_read (/* group = */ "memcached",
/* name = */ callback_name,
/* callback = */ memcached_read,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user_data = */ &ud);
return (status);
} /* int memcached_add_read_callback */
diff --git a/src/memory.c b/src/memory.c
index fb2f3d38a4045fd8790160a1155ed04cda33ab23..ea16ce315f102126d7ca0f497ea8d153fb6c2339 100644 (file)
--- a/src/memory.c
+++ b/src/memory.c
#elif HAVE_LIBKSTAT
static int pagesize;
static kstat_t *ksp;
+static kstat_t *ksz;
/* #endif HAVE_LIBKSTAT */
#elif HAVE_SYSCTL
ksp = NULL;
return (-1);
}
+ if (get_kstat (&ksz, "zfs", 0, "arcstats") != 0)
+ {
+ ksz = NULL;
+ return (-1);
+ }
+
/* #endif HAVE_LIBKSTAT */
#elif HAVE_SYSCTL
long long mem_lock;
long long mem_kern;
long long mem_unus;
+ long long arcsize;
+
long long pp_kernel;
long long physmem;
if (ksp == NULL)
return (-1);
+ if (ksz == NULL)
+ return (-1);
mem_used = get_kstat_value (ksp, "pagestotal");
mem_free = get_kstat_value (ksp, "pagesfree");
mem_lock = get_kstat_value (ksp, "pageslocked");
- mem_kern = 0;
- mem_unus = 0;
-
+ arcsize = get_kstat_value (ksz, "size");
pp_kernel = get_kstat_value (ksp, "pp_kernel");
physmem = get_kstat_value (ksp, "physmem");
availrmem = get_kstat_value (ksp, "availrmem");
+ mem_kern = 0;
+ mem_unus = 0;
+
if ((mem_used < 0LL) || (mem_free < 0LL) || (mem_lock < 0LL))
{
WARNING ("memory plugin: one of used, free or locked is negative.");
mem_lock *= pagesize; /* some? ;) */
mem_kern *= pagesize; /* it's 2011 RAM is cheap */
mem_unus *= pagesize;
+ mem_kern -= arcsize;
+
MEMORY_SUBMIT ("used", (gauge_t) mem_used,
"free", (gauge_t) mem_free,
"locked", (gauge_t) mem_lock,
"kernel", (gauge_t) mem_kern,
+ "arc", (gauge_t) arcsize,
"unusable", (gauge_t) mem_unus);
/* #endif HAVE_LIBKSTAT */
diff --git a/src/modbus.c b/src/modbus.c
index 08871a25732f60ab7bc5ef9c67fe248a303ecd48..cfc6331e293218b4fdfaca1d99eadabae02754fa 100644 (file)
--- a/src/modbus.c
+++ b/src/modbus.c
if (ds->ds_num != 1)
{
- ERROR ("Modbus plugin: The type \"%s\" has %i data sources. "
+ ERROR ("Modbus plugin: The type \"%s\" has %zu data sources. "
"I can only handle data sets with only one data source.",
data->type, ds->ds_num);
return (-1);
{
user_data_t ud;
char name[1024];
- struct timespec interval = { 0, 0 };
ud.data = host;
ud.free_func = host_free;
ssnprintf (name, sizeof (name), "modbus-%s", host->host);
- CDTIME_T_TO_TIMESPEC (host->interval, &interval);
-
plugin_register_complex_read (/* group = */ NULL, name,
/* callback = */ mb_read,
- /* interval = */ (host->interval > 0) ? &interval : NULL,
+ /* interval = */ host->interval,
&ud);
}
else
diff --git a/src/mqtt.c b/src/mqtt.c
--- /dev/null
+++ b/src/mqtt.c
@@ -0,0 +1,748 @@
+/**
+ * collectd - src/mqtt.c
+ * Copyright (C) 2014 Marc Falzon
+ * Copyright (C) 2014,2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Marc Falzon <marc at baha dot mu>
+ * Florian octo Forster <octo at collectd.org>
+ **/
+
+// Reference: http://mosquitto.org/api/files/mosquitto-h.html
+
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_cache.h"
+#include "utils_complain.h"
+
+#include <pthread.h>
+
+#include <mosquitto.h>
+
+#define MQTT_MAX_TOPIC_SIZE 1024
+#define MQTT_MAX_MESSAGE_SIZE MQTT_MAX_TOPIC_SIZE + 1024
+#define MQTT_DEFAULT_HOST "localhost"
+#define MQTT_DEFAULT_PORT 1883
+#define MQTT_DEFAULT_TOPIC_PREFIX "collectd"
+#define MQTT_DEFAULT_TOPIC "collectd/#"
+#ifndef MQTT_KEEPALIVE
+# define MQTT_KEEPALIVE 60
+#endif
+
+
+/*
+ * Data types
+ */
+struct mqtt_client_conf
+{
+ _Bool publish;
+ char *name;
+
+ struct mosquitto *mosq;
+ _Bool connected;
+
+ char *host;
+ int port;
+ char *client_id;
+ char *username;
+ char *password;
+ int qos;
+
+ /* For publishing */
+ char *topic_prefix;
+ _Bool store_rates;
+ _Bool retain;
+
+ /* For subscribing */
+ pthread_t thread;
+ _Bool loop;
+ char *topic;
+ _Bool clean_session;
+
+ c_complain_t complaint_cantpublish;
+ pthread_mutex_t lock;
+};
+typedef struct mqtt_client_conf mqtt_client_conf_t;
+
+static mqtt_client_conf_t **subscribers = NULL;
+static size_t subscribers_num = 0;
+
+/*
+ * Functions
+ */
+#if LIBMOSQUITTO_MAJOR == 0
+static char const *mosquitto_strerror (int code)
+{
+ switch (code)
+ {
+ case MOSQ_ERR_SUCCESS: return "MOSQ_ERR_SUCCESS";
+ case MOSQ_ERR_NOMEM: return "MOSQ_ERR_NOMEM";
+ case MOSQ_ERR_PROTOCOL: return "MOSQ_ERR_PROTOCOL";
+ case MOSQ_ERR_INVAL: return "MOSQ_ERR_INVAL";
+ case MOSQ_ERR_NO_CONN: return "MOSQ_ERR_NO_CONN";
+ case MOSQ_ERR_CONN_REFUSED: return "MOSQ_ERR_CONN_REFUSED";
+ case MOSQ_ERR_NOT_FOUND: return "MOSQ_ERR_NOT_FOUND";
+ case MOSQ_ERR_CONN_LOST: return "MOSQ_ERR_CONN_LOST";
+ case MOSQ_ERR_SSL: return "MOSQ_ERR_SSL";
+ case MOSQ_ERR_PAYLOAD_SIZE: return "MOSQ_ERR_PAYLOAD_SIZE";
+ case MOSQ_ERR_NOT_SUPPORTED: return "MOSQ_ERR_NOT_SUPPORTED";
+ case MOSQ_ERR_AUTH: return "MOSQ_ERR_AUTH";
+ case MOSQ_ERR_ACL_DENIED: return "MOSQ_ERR_ACL_DENIED";
+ case MOSQ_ERR_UNKNOWN: return "MOSQ_ERR_UNKNOWN";
+ case MOSQ_ERR_ERRNO: return "MOSQ_ERR_ERRNO";
+ }
+
+ return "UNKNOWN ERROR CODE";
+}
+#else
+/* provided by libmosquitto */
+#endif
+
+static void mqtt_free (mqtt_client_conf_t *conf)
+{
+ if (conf == NULL)
+ return;
+
+ if (conf->connected)
+ (void) mosquitto_disconnect (conf->mosq);
+ conf->connected = 0;
+ (void) mosquitto_destroy (conf->mosq);
+
+ sfree (conf->host);
+ sfree (conf->username);
+ sfree (conf->password);
+ sfree (conf->client_id);
+ sfree (conf->topic_prefix);
+ sfree (conf);
+}
+
+static char *strip_prefix (char *topic)
+{
+ size_t num;
+ size_t i;
+
+ num = 0;
+ for (i = 0; topic[i] != 0; i++)
+ if (topic[i] == '/')
+ num++;
+
+ if (num < 2)
+ return (NULL);
+
+ while (num > 2)
+ {
+ char *tmp = strchr (topic, '/');
+ if (tmp == NULL)
+ return (NULL);
+ topic = tmp + 1;
+ num--;
+ }
+
+ return (topic);
+}
+
+static void on_message (
+#if LIBMOSQUITTO_MAJOR == 0
+#else
+ __attribute__((unused)) struct mosquitto *m,
+#endif
+ __attribute__((unused)) void *arg,
+ const struct mosquitto_message *msg)
+{
+ value_list_t vl = VALUE_LIST_INIT;
+ data_set_t const *ds;
+ char *topic;
+ char *name;
+ char *payload;
+ int status;
+
+ if ((msg->payloadlen <= 0)
+ || (((uint8_t *) msg->payload)[msg->payloadlen - 1] != 0))
+ return;
+
+ topic = strdup (msg->topic);
+ name = strip_prefix (topic);
+
+ status = parse_identifier_vl (name, &vl);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: Unable to parse topic \"%s\".", topic);
+ sfree (topic);
+ return;
+ }
+ sfree (topic);
+
+ ds = plugin_get_ds (vl.type);
+ if (ds == NULL)
+ {
+ ERROR ("mqtt plugin: Unknown type: \"%s\".", vl.type);
+ return;
+ }
+
+ vl.values = calloc (ds->ds_num, sizeof (*vl.values));
+ if (vl.values == NULL)
+ {
+ ERROR ("mqtt plugin: calloc failed.");
+ return;
+ }
+ vl.values_len = ds->ds_num;
+
+ payload = strdup ((void *) msg->payload);
+ DEBUG ("mqtt plugin: payload = \"%s\"", payload);
+ status = parse_values (payload, &vl, ds);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: Unable to parse payload \"%s\".", payload);
+ sfree (payload);
+ sfree (vl.values);
+ return;
+ }
+ sfree (payload);
+
+ plugin_dispatch_values (&vl);
+ sfree (vl.values);
+} /* void on_message */
+
+/* must hold conf->lock when calling. */
+static int mqtt_reconnect (mqtt_client_conf_t *conf)
+{
+ int status;
+
+ if (conf->connected)
+ return (0);
+
+ status = mosquitto_reconnect (conf->mosq);
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ char errbuf[1024];
+ ERROR ("mqtt_connect_broker: mosquitto_connect failed: %s",
+ (status == MOSQ_ERR_ERRNO)
+ ? sstrerror(errno, errbuf, sizeof (errbuf))
+ : mosquitto_strerror (status));
+ return (-1);
+ }
+
+ conf->connected = 1;
+
+ c_release (LOG_INFO,
+ &conf->complaint_cantpublish,
+ "mqtt plugin: successfully reconnected to broker \"%s:%d\"",
+ conf->host, conf->port);
+
+ return (0);
+} /* mqtt_reconnect */
+
+/* must hold conf->lock when calling. */
+static int mqtt_connect (mqtt_client_conf_t *conf)
+{
+ char const *client_id;
+ int status;
+
+ if (conf->mosq != NULL)
+ return mqtt_reconnect (conf);
+
+ if (conf->client_id)
+ client_id = conf->client_id;
+ else
+ client_id = hostname_g;
+
+#if LIBMOSQUITTO_MAJOR == 0
+ conf->mosq = mosquitto_new (client_id, /* user data = */ conf);
+#else
+ conf->mosq = mosquitto_new (client_id, conf->clean_session, /* user data = */ conf);
+#endif
+ if (conf->mosq == NULL)
+ {
+ ERROR ("mqtt plugin: mosquitto_new failed");
+ return (-1);
+ }
+
+ if (conf->username && conf->password)
+ {
+ status = mosquitto_username_pw_set (conf->mosq, conf->username, conf->password);
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ char errbuf[1024];
+ ERROR ("mqtt plugin: mosquitto_username_pw_set failed: %s",
+ (status == MOSQ_ERR_ERRNO)
+ ? sstrerror (errno, errbuf, sizeof (errbuf))
+ : mosquitto_strerror (status));
+
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+ }
+
+#if LIBMOSQUITTO_MAJOR == 0
+ status = mosquitto_connect (conf->mosq, conf->host, conf->port,
+ /* keepalive = */ MQTT_KEEPALIVE, /* clean session = */ conf->clean_session);
+#else
+ status = mosquitto_connect (conf->mosq, conf->host, conf->port, MQTT_KEEPALIVE);
+#endif
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ char errbuf[1024];
+ ERROR ("mqtt plugin: mosquitto_connect failed: %s",
+ (status == MOSQ_ERR_ERRNO)
+ ? sstrerror (errno, errbuf, sizeof (errbuf))
+ : mosquitto_strerror (status));
+
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+
+ if (!conf->publish)
+ {
+ mosquitto_message_callback_set (conf->mosq, on_message);
+
+ status = mosquitto_subscribe (conf->mosq,
+ /* message_id = */ NULL,
+ conf->topic, conf->qos);
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ ERROR ("mqtt plugin: Subscribing to \"%s\" failed: %s",
+ conf->topic, mosquitto_strerror (status));
+
+ mosquitto_disconnect (conf->mosq);
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+ }
+
+ conf->connected = 1;
+ return (0);
+} /* mqtt_connect */
+
+static void *subscribers_thread (void *arg)
+{
+ mqtt_client_conf_t *conf = arg;
+ int status;
+
+ conf->loop = 1;
+
+ while (conf->loop)
+ {
+ status = mqtt_connect (conf);
+ if (status != 0)
+ {
+ sleep (1);
+ continue;
+ }
+
+ /* The documentation says "0" would map to the default (1000ms), but
+ * that does not work on some versions. */
+#if LIBMOSQUITTO_MAJOR == 0
+ status = mosquitto_loop (conf->mosq, /* timeout = */ 1000 /* ms */);
+#else
+ status = mosquitto_loop (conf->mosq,
+ /* timeout[ms] = */ 1000,
+ /* max_packets = */ 100);
+#endif
+ if (status == MOSQ_ERR_CONN_LOST)
+ {
+ conf->connected = 0;
+ continue;
+ }
+ else if (status != MOSQ_ERR_SUCCESS)
+ {
+ ERROR ("mqtt plugin: mosquitto_loop failed: %s",
+ mosquitto_strerror (status));
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ conf->connected = 0;
+ continue;
+ }
+
+ DEBUG ("mqtt plugin: mosquitto_loop succeeded.");
+ } /* while (conf->loop) */
+
+ pthread_exit (0);
+} /* void *subscribers_thread */
+
+static int publish (mqtt_client_conf_t *conf, char const *topic,
+ void const *payload, size_t payload_len)
+{
+ int status;
+
+ pthread_mutex_lock (&conf->lock);
+
+ status = mqtt_connect (conf);
+ if (status != 0) {
+ pthread_mutex_unlock (&conf->lock);
+ ERROR ("mqtt plugin: unable to reconnect to broker");
+ return (status);
+ }
+
+ status = mosquitto_publish(conf->mosq, /* message_id */ NULL, topic,
+#if LIBMOSQUITTO_MAJOR == 0
+ (uint32_t) payload_len, payload,
+#else
+ (int) payload_len, payload,
+#endif
+ conf->qos, conf->retain);
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ char errbuf[1024];
+ c_complain (LOG_ERR,
+ &conf->complaint_cantpublish,
+ "mqtt plugin: mosquitto_publish failed: %s",
+ (status == MOSQ_ERR_ERRNO)
+ ? sstrerror(errno, errbuf, sizeof (errbuf))
+ : mosquitto_strerror(status));
+ /* Mark our connection "down" regardless of the error as a safety
+ * measure; we will try to reconnect the next time we have to publish a
+ * message */
+ conf->connected = 0;
+
+ pthread_mutex_unlock (&conf->lock);
+ return (-1);
+ }
+
+ pthread_mutex_unlock (&conf->lock);
+ return (0);
+} /* int publish */
+
+static int format_topic (char *buf, size_t buf_len,
+ data_set_t const *ds, value_list_t const *vl,
+ mqtt_client_conf_t *conf)
+{
+ char name[MQTT_MAX_TOPIC_SIZE];
+ int status;
+
+ if ((conf->topic_prefix == NULL) || (conf->topic_prefix[0] == 0))
+ return (FORMAT_VL (buf, buf_len, vl));
+
+ status = FORMAT_VL (name, sizeof (name), vl);
+ if (status != 0)
+ return (status);
+
+ status = ssnprintf (buf, buf_len, "%s/%s", conf->topic_prefix, name);
+ if ((status < 0) || (((size_t) status) >= buf_len))
+ return (ENOMEM);
+
+ return (0);
+} /* int format_topic */
+
+static int mqtt_write (const data_set_t *ds, const value_list_t *vl,
+ user_data_t *user_data)
+{
+ mqtt_client_conf_t *conf;
+ char topic[MQTT_MAX_TOPIC_SIZE];
+ char payload[MQTT_MAX_MESSAGE_SIZE];
+ int status = 0;
+
+ if ((user_data == NULL) || (user_data->data == NULL))
+ return (EINVAL);
+ conf = user_data->data;
+
+ status = format_topic (topic, sizeof (topic), ds, vl, conf);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: format_topic failed with status %d.", status);
+ return (status);
+ }
+
+ status = format_values (payload, sizeof (payload),
+ ds, vl, conf->store_rates);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: format_values failed with status %d.", status);
+ return (status);
+ }
+
+ status = publish (conf, topic, payload, strlen (payload) + 1);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: publish failed: %s", mosquitto_strerror (status));
+ return (status);
+ }
+
+ return (status);
+} /* mqtt_write */
+
+/*
+ * <Publish "name">
+ * Host "example.com"
+ * Port 1883
+ * ClientId "collectd"
+ * User "guest"
+ * Password "secret"
+ * Prefix "collectd"
+ * StoreRates true
+ * Retain false
+ * QoS 0
+ * </Publish>
+ */
+static int mqtt_config_publisher (oconfig_item_t *ci)
+{
+ mqtt_client_conf_t *conf;
+ char cb_name[1024];
+ user_data_t user_data;
+ int status;
+ int i;
+
+ conf = calloc (1, sizeof (*conf));
+ if (conf == NULL)
+ {
+ ERROR ("mqtt plugin: malloc failed.");
+ return (-1);
+ }
+ conf->publish = 1;
+
+ conf->name = NULL;
+ status = cf_util_get_string (ci, &conf->name);
+ if (status != 0)
+ {
+ mqtt_free (conf);
+ return (status);
+ }
+
+ conf->host = strdup (MQTT_DEFAULT_HOST);
+ conf->port = MQTT_DEFAULT_PORT;
+ conf->client_id = NULL;
+ conf->qos = 0;
+ conf->topic_prefix = strdup (MQTT_DEFAULT_TOPIC_PREFIX);
+ conf->store_rates = 1;
+
+ status = pthread_mutex_init (&conf->lock, NULL);
+ if (status != 0)
+ {
+ mqtt_free (conf);
+ return (status);
+ }
+
+ C_COMPLAIN_INIT (&conf->complaint_cantpublish);
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+ if (strcasecmp ("Host", child->key) == 0)
+ cf_util_get_string (child, &conf->host);
+ else if (strcasecmp ("Port", child->key) == 0)
+ {
+ int tmp = cf_util_get_port_number (child);
+ if (tmp < 0)
+ ERROR ("mqtt plugin: Invalid port number.");
+ else
+ conf->port = tmp;
+ }
+ else if (strcasecmp ("ClientId", child->key) == 0)
+ cf_util_get_string (child, &conf->client_id);
+ else if (strcasecmp ("User", child->key) == 0)
+ cf_util_get_string (child, &conf->username);
+ else if (strcasecmp ("Password", child->key) == 0)
+ cf_util_get_string (child, &conf->password);
+ else if (strcasecmp ("QoS", child->key) == 0)
+ {
+ int tmp = -1;
+ status = cf_util_get_int (child, &tmp);
+ if ((status != 0) || (tmp < 0) || (tmp > 2))
+ ERROR ("mqtt plugin: Not a valid QoS setting.");
+ else
+ conf->qos = tmp;
+ }
+ else if (strcasecmp ("Prefix", child->key) == 0)
+ cf_util_get_string (child, &conf->topic_prefix);
+ else if (strcasecmp ("StoreRates", child->key) == 0)
+ cf_util_get_boolean (child, &conf->store_rates);
+ else if (strcasecmp ("Retain", child->key) == 0)
+ cf_util_get_boolean (child, &conf->retain);
+ else
+ ERROR ("mqtt plugin: Unknown config option: %s", child->key);
+ }
+
+ ssnprintf (cb_name, sizeof (cb_name), "mqtt/%s", conf->name);
+ memset (&user_data, 0, sizeof (user_data));
+ user_data.data = conf;
+
+ plugin_register_write (cb_name, mqtt_write, &user_data);
+ return (0);
+} /* mqtt_config_publisher */
+
+/*
+ * <Subscribe "name">
+ * Host "example.com"
+ * Port 1883
+ * ClientId "collectd"
+ * User "guest"
+ * Password "secret"
+ * Topic "collectd/#"
+ * </Publish>
+ */
+static int mqtt_config_subscriber (oconfig_item_t *ci)
+{
+ mqtt_client_conf_t **tmp;
+ mqtt_client_conf_t *conf;
+ int status;
+ int i;
+
+ conf = calloc (1, sizeof (*conf));
+ if (conf == NULL)
+ {
+ ERROR ("mqtt plugin: malloc failed.");
+ return (-1);
+ }
+ conf->publish = 0;
+
+ conf->name = NULL;
+ status = cf_util_get_string (ci, &conf->name);
+ if (status != 0)
+ {
+ mqtt_free (conf);
+ return (status);
+ }
+
+ conf->host = strdup (MQTT_DEFAULT_HOST);
+ conf->port = MQTT_DEFAULT_PORT;
+ conf->client_id = NULL;
+ conf->qos = 2;
+ conf->topic = strdup (MQTT_DEFAULT_TOPIC);
+ conf->clean_session = 1;
+
+ status = pthread_mutex_init (&conf->lock, NULL);
+ if (status != 0)
+ {
+ mqtt_free (conf);
+ return (status);
+ }
+
+ C_COMPLAIN_INIT (&conf->complaint_cantpublish);
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+ if (strcasecmp ("Host", child->key) == 0)
+ cf_util_get_string (child, &conf->host);
+ else if (strcasecmp ("Port", child->key) == 0)
+ {
+ int tmp = cf_util_get_port_number (child);
+ if (tmp < 0)
+ ERROR ("mqtt plugin: Invalid port number.");
+ else
+ conf->port = tmp;
+ }
+ else if (strcasecmp ("ClientId", child->key) == 0)
+ cf_util_get_string (child, &conf->client_id);
+ else if (strcasecmp ("User", child->key) == 0)
+ cf_util_get_string (child, &conf->username);
+ else if (strcasecmp ("Password", child->key) == 0)
+ cf_util_get_string (child, &conf->password);
+ else if (strcasecmp ("QoS", child->key) == 0)
+ {
+ int tmp = -1;
+ status = cf_util_get_int (child, &tmp);
+ if ((status != 0) || (tmp < 0) || (tmp > 2))
+ ERROR ("mqtt plugin: Not a valid QoS setting.");
+ else
+ conf->qos = tmp;
+ }
+ else if (strcasecmp ("Topic", child->key) == 0)
+ cf_util_get_string (child, &conf->topic);
+ else if (strcasecmp ("CleanSession", child->key) == 0)
+ cf_util_get_boolean (child, &conf->clean_session);
+ else
+ ERROR ("mqtt plugin: Unknown config option: %s", child->key);
+ }
+
+ tmp = realloc (subscribers, sizeof (*subscribers) * subscribers_num);
+ if (tmp == NULL)
+ {
+ ERROR ("mqtt plugin: realloc failed.");
+ mqtt_free (conf);
+ return (-1);
+ }
+ subscribers = tmp;
+ subscribers[subscribers_num] = conf;
+ subscribers_num++;
+
+ return (0);
+} /* mqtt_config_subscriber */
+
+/*
+ * <Plugin mqtt>
+ * <Publish "name">
+ * # ...
+ * </Publish>
+ * <Subscribe "name">
+ * # ...
+ * </Subscribe>
+ * </Plugin>
+ */
+static int mqtt_config (oconfig_item_t *ci)
+{
+ int i;
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp ("Publish", child->key) == 0)
+ mqtt_config_publisher (child);
+ else if (strcasecmp ("Subscribe", child->key) == 0)
+ mqtt_config_subscriber (child);
+ else
+ ERROR ("mqtt plugin: Unknown config option: %s", child->key);
+ }
+
+ return (0);
+} /* int mqtt_config */
+
+static int mqtt_init (void)
+{
+ size_t i;
+
+ mosquitto_lib_init ();
+
+ for (i = 0; i < subscribers_num; i++)
+ {
+ int status;
+
+ if (subscribers[i]->loop)
+ continue;
+
+ status = plugin_thread_create (&subscribers[i]->thread,
+ /* attrs = */ NULL,
+ /* func = */ subscribers_thread,
+ /* args = */ subscribers[i]);
+ if (status != 0)
+ {
+ char errbuf[1024];
+ ERROR ("mqtt plugin: pthread_create failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ continue;
+ }
+ }
+
+ return (0);
+} /* mqtt_init */
+
+void module_register (void)
+{
+ plugin_register_complex_config ("mqtt", mqtt_config);
+ plugin_register_init ("mqtt", mqtt_init);
+} /* void module_register */
+
+/* vim: set sw=4 sts=4 et fdm=marker : */
diff --git a/src/mysql.c b/src/mysql.c
index eaa03719c5216b23ba316273af40aa654bc891e3..a8a8e86d906f79572754dab09a7af08931078a03 100644 (file)
--- a/src/mysql.c
+++ b/src/mysql.c
plugin_register_complex_read (/* group = */ NULL, cb_name,
mysql_read,
- /* interval = */ NULL, &ud);
+ /* interval = */ 0, &ud);
}
else
{
diff --git a/src/netapp.c b/src/netapp.c
index f446d597de1f27610b0be1c7e2cfde8957509a79..020bfba192baffad8eb59661c464aaaf77bc585c 100644 (file)
--- a/src/netapp.c
+++ b/src/netapp.c
static int cna_register_host (host_config_t *host) /* {{{ */
{
char cb_name[256];
- struct timespec interval;
user_data_t ud;
if (host->vfiler)
else
ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name);
- CDTIME_T_TO_TIMESPEC (host->interval, &interval);
-
memset (&ud, 0, sizeof (ud));
ud.data = host;
ud.free_func = (void (*) (void *)) free_host_config;
plugin_register_complex_read (/* group = */ NULL, cb_name,
/* callback = */ cna_read,
- /* interval = */ (host->interval > 0) ? &interval : NULL,
+ /* interval = */ host->interval,
/* user data = */ &ud);
return (0);
diff --git a/src/netlink.c b/src/netlink.c
index aa9760f9328b78eb87e14f70501bc1622a57f12d..e1f378d9408a741a6e75c85efe62ee5a80426028 100644 (file)
--- a/src/netlink.c
+++ b/src/netlink.c
#include "common.h"
#include <asm/types.h>
-#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
diff --git a/src/network.c b/src/network.c
index af24911ee365b1ae512000cce93103ffdaf86a94..916900065aff9241a99454ab86cd2bf675655d8f 100644 (file)
--- a/src/network.c
+++ b/src/network.c
#if HAVE_PTHREAD_H
# include <pthread.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NETDB_H
# include <netdb.h>
#endif
static int network_config_ttl = 0;
/* Ethernet - (IPv6 + UDP) = 1500 - (40 + 8) = 1452 */
static size_t network_config_packet_size = 1452;
-static int network_config_forward = 0;
-static int network_config_stats = 0;
+static _Bool network_config_forward = 0;
+static _Bool network_config_stats = 0;
static sockent_t *sending_sockets = NULL;
static char *send_buffer;
static char *send_buffer_ptr;
static int send_buffer_fill;
+static cdtime_t send_buffer_last_update;
static value_list_t send_buffer_vl = VALUE_LIST_STATIC;
static pthread_mutex_t send_buffer_lock = PTHREAD_MUTEX_INITIALIZER;
_Bool received = 0;
int status;
- if (network_config_forward != 0)
+ if (network_config_forward)
return (1);
if (vl->meta == NULL)
} /* int write_part_string */
static int parse_part_values (void **ret_buffer, size_t *ret_buffer_len,
- value_t **ret_values, int *ret_num_values)
+ value_t **ret_values, size_t *ret_num_values)
{
char *buffer = *ret_buffer;
size_t buffer_len = *ret_buffer_len;
*ret_buffer = buffer;
*ret_buffer_len = buffer_len - pkg_length;
- *ret_num_values = pkg_numval;
+ *ret_num_values = (size_t) pkg_numval;
*ret_values = pkg_values;
sfree (pkg_types);
char buffer[network_config_packet_size];
int buffer_len;
- int i;
+ size_t i;
int status = 0;
receive_list_entry_t *private_list_head;
memset (send_buffer, 0, network_config_packet_size);
send_buffer_ptr = send_buffer;
send_buffer_fill = 0;
+ send_buffer_last_update = 0;
memset (&send_buffer_vl, 0, sizeof (send_buffer_vl));
} /* int network_init_buffer */
/* status == bytes added to the buffer */
send_buffer_fill += status;
send_buffer_ptr += status;
+ send_buffer_last_update = cdtime();
stats_values_sent++;
}
return ((status < 0) ? -1 : 0);
} /* int network_write */
-static int network_config_set_boolean (const oconfig_item_t *ci, /* {{{ */
- int *retval)
-{
- if ((ci->values_num != 1)
- || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN)
- && (ci->values[0].type != OCONFIG_TYPE_STRING)))
- {
- ERROR ("network plugin: The `%s' config option needs "
- "exactly one boolean argument.", ci->key);
- return (-1);
- }
-
- if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
- {
- if (ci->values[0].value.boolean)
- *retval = 1;
- else
- *retval = 0;
- }
- else
- {
- char *str = ci->values[0].value.string;
-
- if (IS_TRUE (str))
- *retval = 1;
- else if (IS_FALSE (str))
- *retval = 0;
- else
- {
- ERROR ("network plugin: Cannot parse string value `%s' of the `%s' "
- "option as boolean value.",
- str, ci->key);
- return (-1);
- }
- }
-
- return (0);
-} /* }}} int network_config_set_boolean */
-
static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */
{
- int tmp;
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
- {
- WARNING ("network plugin: The `TimeToLive' config option needs exactly "
- "one numeric argument.");
- return (-1);
- }
+ int tmp = 0;
- tmp = (int) ci->values[0].value.number;
- if ((tmp > 0) && (tmp <= 255))
+ if (cf_util_get_int (ci, &tmp) != 0)
+ return (-1);
+ else if ((tmp > 0) && (tmp <= 255))
network_config_ttl = tmp;
else {
WARNING ("network plugin: The `TimeToLive' must be between 1 and 255.");
static int network_config_set_interface (const oconfig_item_t *ci, /* {{{ */
int *interface)
{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("network plugin: The `Interface' config option needs exactly "
- "one string argument.");
- return (-1);
- }
+ char if_name[256];
- if (interface == NULL)
+ if (cf_util_get_string_buffer (ci, if_name, sizeof (if_name)) != 0)
return (-1);
- *interface = if_nametoindex (ci->values[0].value.string);
-
+ *interface = if_nametoindex (if_name);
return (0);
} /* }}} int network_config_set_interface */
static int network_config_set_buffer_size (const oconfig_item_t *ci) /* {{{ */
{
- int tmp;
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
- {
- WARNING ("network plugin: The `MaxPacketSize' config option needs exactly "
- "one numeric argument.");
- return (-1);
- }
+ int tmp = 0;
- tmp = (int) ci->values[0].value.number;
- if ((tmp >= 1024) && (tmp <= 65535))
+ if (cf_util_get_int (ci, &tmp) != 0)
+ return (-1);
+ else if ((tmp >= 1024) && (tmp <= 65535))
network_config_packet_size = tmp;
-
- return (0);
-} /* }}} int network_config_set_buffer_size */
-
-#if HAVE_LIBGCRYPT
-static int network_config_set_string (const oconfig_item_t *ci, /* {{{ */
- char **ret_string)
-{
- char *tmp;
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("network plugin: The `%s' config option needs exactly "
- "one string argument.", ci->key);
+ else {
+ WARNING ("network plugin: The `MaxPacketSize' must be between 1024 and 65535.");
return (-1);
}
- tmp = strdup (ci->values[0].value.string);
- if (tmp == NULL)
- return (-1);
-
- sfree (*ret_string);
- *ret_string = tmp;
-
return (0);
-} /* }}} int network_config_set_string */
-#endif /* HAVE_LIBGCRYPT */
+} /* }}} int network_config_set_buffer_size */
#if HAVE_LIBGCRYPT
static int network_config_set_security_level (oconfig_item_t *ci, /* {{{ */
#if HAVE_LIBGCRYPT
if (strcasecmp ("AuthFile", child->key) == 0)
- network_config_set_string (child, &se->data.server.auth_file);
+ cf_util_get_string (child, &se->data.server.auth_file);
else if (strcasecmp ("SecurityLevel", child->key) == 0)
network_config_set_security_level (child,
&se->data.server.security_level);
else
#endif /* HAVE_LIBGCRYPT */
if (strcasecmp ("Interface", child->key) == 0)
- network_config_set_interface (child,
- &se->interface);
+ network_config_set_interface (child, &se->interface);
else
{
WARNING ("network plugin: Option `%s' is not allowed here.",
status = sockent_server_listen (se);
if (status != 0)
{
- ERROR ("network plugin: network_config_add_server: sockent_server_listen failed.");
+ ERROR ("network plugin: network_config_add_listen: sockent_server_listen failed.");
sockent_destroy (se);
return (-1);
}
#if HAVE_LIBGCRYPT
if (strcasecmp ("Username", child->key) == 0)
- network_config_set_string (child, &se->data.client.username);
+ cf_util_get_string (child, &se->data.client.username);
else if (strcasecmp ("Password", child->key) == 0)
- network_config_set_string (child, &se->data.client.password);
+ cf_util_get_string (child, &se->data.client.password);
else if (strcasecmp ("SecurityLevel", child->key) == 0)
network_config_set_security_level (child,
&se->data.client.security_level);
else
#endif /* HAVE_LIBGCRYPT */
if (strcasecmp ("Interface", child->key) == 0)
- network_config_set_interface (child,
- &se->interface);
- else if (strcasecmp ("ResolveInterval", child->key) == 0)
- cf_util_get_cdtime(child, &se->data.client.resolve_interval);
+ network_config_set_interface (child, &se->interface);
+ else if (strcasecmp ("ResolveInterval", child->key) == 0)
+ cf_util_get_cdtime(child, &se->data.client.resolve_interval);
else
{
WARNING ("network plugin: Option `%s' is not allowed here.",
else if (strcasecmp ("MaxPacketSize", child->key) == 0)
network_config_set_buffer_size (child);
else if (strcasecmp ("Forward", child->key) == 0)
- network_config_set_boolean (child, &network_config_forward);
+ cf_util_get_boolean (child, &network_config_forward);
else if (strcasecmp ("ReportStats", child->key) == 0)
- network_config_set_boolean (child, &network_config_stats);
+ cf_util_get_boolean (child, &network_config_stats);
else
{
WARNING ("network plugin: Option `%s' is not allowed here.",
network_init_gcrypt ();
#endif
- if (network_config_stats != 0)
+ if (network_config_stats)
plugin_register_read ("network", network_stats_read);
plugin_register_shutdown ("network", network_shutdown);
* just send the buffer if `flush' is called - if the requested value was in
* there, good. If not, well, then there is nothing to flush.. -octo
*/
-static int network_flush (__attribute__((unused)) cdtime_t timeout,
+static int network_flush (cdtime_t timeout,
__attribute__((unused)) const char *identifier,
__attribute__((unused)) user_data_t *user_data)
{
pthread_mutex_lock (&send_buffer_lock);
if (send_buffer_fill > 0)
- flush_buffer ();
-
+ {
+ if (timeout > 0)
+ {
+ cdtime_t now = cdtime ();
+ if ((send_buffer_last_update + timeout) > now)
+ {
+ pthread_mutex_unlock (&send_buffer_lock);
+ return (0);
+ }
+ }
+ flush_buffer ();
+ }
pthread_mutex_unlock (&send_buffer_lock);
return (0);
diff --git a/src/nginx.c b/src/nginx.c
index 4e4ce3bbc6115572873668a76507f80ccd82b316..69ec06dc996edc9452ea565776c9d9d70c241e68 100644 (file)
--- a/src/nginx.c
+++ b/src/nginx.c
}
else
{
- curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
}
#endif
diff --git a/src/ntpd.c b/src/ntpd.c
index 5fdfef3f0db415c0bae5634ac69b5af64e31518f..dbde6609f64527ff8d58c91a4e9fda5f53e226e6 100644 (file)
--- a/src/ntpd.c
+++ b/src/ntpd.c
#if HAVE_NETDB_H
# include <netdb.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
"JJY", "TT_IRIG", "GPS_ZYFER", "GPS_RIPENCC", /* 40-43 */
"NEOCLK4X" /* 44 */
};
-static int refclock_names_num = STATIC_ARRAY_SIZE (refclock_names);
+static size_t refclock_names_num = STATIC_ARRAY_SIZE (refclock_names);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* End of the copied stuff.. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32_t refclock_id = ntpd_get_refclock_id (peer_info);
uint32_t unit_id = ntohl (peer_info->srcadr) & 0x00FF;
- if (refclock_id >= refclock_names_num)
+ if (((size_t) refclock_id) >= refclock_names_num)
return (ntpd_get_name_from_address (buffer, buffer_size,
peer_info,
/* do_reverse_lookup = */ 0));
diff --git a/src/olsrd.c b/src/olsrd.c
index 6d0576cf7bc7d26e39567646f40fa1ebd49262cc..bbf387f4123dfe12a375ca85b234fd315843e385 100644 (file)
--- a/src/olsrd.c
+++ b/src/olsrd.c
#include <sys/types.h>
#include <netdb.h>
-#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
diff --git a/src/onewire.c b/src/onewire.c
index 51e6407137b0f2c8bc64598f822cac804c5a9fab..58c35e1eb83be009b342fbfbb7af8f2a7642cb2b 100644 (file)
--- a/src/onewire.c
+++ b/src/onewire.c
static int cow_init (void)
{
int status;
- struct timespec cb_interval;
if (device_g == NULL)
{
return (1);
}
- CDTIME_T_TO_TIMESPEC (ow_interval, &cb_interval);
-
plugin_register_complex_read (/* group = */ NULL, "onewire", cow_read,
- (ow_interval != 0) ? &cb_interval : NULL,
- /* user data = */ NULL);
+ ow_interval, /* user data = */ NULL);
plugin_register_shutdown ("onewire", cow_shutdown);
return (0);
diff --git a/src/openldap.c b/src/openldap.c
index 8667058ed049b164d7e496f37917253e55adcf14..ffcdb94e8049000961cd19bc65a167387532f9c0 100644 (file)
--- a/src/openldap.c
+++ b/src/openldap.c
{
char *name;
+ char *binddn;
+ char *password;
char *cacert;
char *host;
int state;
if (st == NULL)
return;
+ sfree (st->binddn);
+ sfree (st->password);
sfree (st->cacert);
sfree (st->host);
sfree (st->name);
}
struct berval cred;
- cred.bv_val = "";
- cred.bv_len = 0;
+ if (st->password != NULL)
+ {
+ cred.bv_val = st->password;
+ cred.bv_len = strlen (st->password);
+ }
+ else
+ {
+ cred.bv_val = "";
+ cred.bv_len = 0;
+ }
- rc = ldap_sasl_bind_s (st->ld, NULL, NULL, &cred, NULL, NULL, NULL);
+ rc = ldap_sasl_bind_s (st->ld, st->binddn, LDAP_SASL_SIMPLE, &cred,
+ NULL, NULL, NULL);
if (rc != LDAP_SUCCESS)
{
ERROR ("openldap plugin: Failed to bind to %s: %s",
{
oconfig_item_t *child = ci->children + i;
- if (strcasecmp ("CACert", child->key) == 0)
+ if (strcasecmp ("BindDN", child->key) == 0)
+ status = cf_util_get_string (child, &st->binddn);
+ else if (strcasecmp ("Password", child->key) == 0)
+ status = cf_util_get_string (child, &st->password);
+ else if (strcasecmp ("CACert", child->key) == 0)
status = cf_util_get_string (child, &st->cacert);
else if (strcasecmp ("StartTLS", child->key) == 0)
status = cf_util_get_boolean (child, &st->starttls);
status = plugin_register_complex_read (/* group = */ NULL,
/* name = */ callback_name,
/* callback = */ cldap_read_host,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user_data = */ &ud);
}
diff --git a/src/perl.c b/src/perl.c
index a964cce4eb58b548e2842063ef38afb6664e5e44..0a98684e9e809f30be3eb042abe3a254bb028510 100644 (file)
--- a/src/perl.c
+++ b/src/perl.c
return 0;
} /* static int hv2data_source (HV *, data_source_t *) */
-static int av2value (pTHX_ char *name, AV *array, value_t *value, int len)
+/* av2value converts at most "len" elements from "array" to "value". Returns the
+ * number of elements converted or zero on error. */
+static size_t av2value (pTHX_ char *name, AV *array, value_t *value, size_t array_len)
{
const data_set_t *ds;
+ size_t i;
- int i = 0;
-
- if ((NULL == name) || (NULL == array) || (NULL == value))
- return -1;
-
- if (av_len (array) < len - 1)
- len = av_len (array) + 1;
-
- if (0 >= len)
- return -1;
+ if ((NULL == name) || (NULL == array) || (NULL == value) || (array_len == 0))
+ return 0;
ds = plugin_get_ds (name);
if (NULL == ds) {
log_err ("av2value: Unknown dataset \"%s\"", name);
- return -1;
+ return 0;
}
- if (ds->ds_num < len) {
- log_warn ("av2value: Value length exceeds data set length.");
- len = ds->ds_num;
+ if (array_len < ds->ds_num) {
+ log_warn ("av2value: array does not contain enough elements for type \"%s\": got %zu, want %zu",
+ name, array_len, ds->ds_num);
+ return 0;
+ } else if (array_len > ds->ds_num) {
+ log_warn ("av2value: array contains excess elements for type \"%s\": got %zu, want %zu",
+ name, array_len, ds->ds_num);
}
- for (i = 0; i < len; ++i) {
+ for (i = 0; i < ds->ds_num; ++i) {
SV **tmp = av_fetch (array, i, 0);
if (NULL != tmp) {
value[i].absolute = SvIV (*tmp);
}
else {
- return -1;
+ return 0;
}
}
- return len;
-} /* static int av2value (char *, AV *, value_t *, int) */
+
+ return ds->ds_num;
+} /* static size_t av2value (char *, AV *, value_t *, size_t) */
/*
* value list:
{
AV *array = (AV *)SvRV (*tmp);
- int len = av_len (array) + 1;
-
- if (len <= 0)
+ /* av_len returns the highest index, not the actual length. */
+ size_t array_len = (size_t) (av_len (array) + 1);
+ if (array_len == 0)
return -1;
- vl->values = (value_t *)smalloc (len * sizeof (value_t));
- vl->values_len = av2value (aTHX_ vl->type, (AV *)SvRV (*tmp),
- vl->values, len);
-
- if (-1 == vl->values_len) {
+ vl->values = calloc (array_len, sizeof (*vl->values));
+ vl->values_len = av2value (aTHX_ vl->type, (AV *)SvRV (*tmp), vl->values, array_len);
+ if (vl->values_len == 0) {
sfree (vl->values);
return -1;
}
static int data_set2av (pTHX_ data_set_t *ds, AV *array)
{
- int i = 0;
+ size_t i;
if ((NULL == ds) || (NULL == array))
return -1;
static int value_list2hv (pTHX_ value_list_t *vl, data_set_t *ds, HV *hash)
{
AV *values = NULL;
-
- int i = 0;
- int len = 0;
+ size_t i;
if ((NULL == vl) || (NULL == ds) || (NULL == hash))
return -1;
- len = vl->values_len;
-
- if (ds->ds_num < len) {
- log_warn ("value2av: Value length exceeds data set length.");
- len = ds->ds_num;
- }
-
values = newAV ();
- av_extend (values, len - 1);
+ /* av_extend takes the last *index* to which the array should be extended. */
+ av_extend (values, vl->values_len - 1);
- for (i = 0; i < len; ++i) {
+ assert (ds->ds_num == vl->values_len);
+ for (i = 0; i < vl->values_len; ++i) {
SV *val = NULL;
if (DS_TYPE_COUNTER == ds->ds[i].type)
diff --git a/src/pf.c b/src/pf.c
index 112e28f3554dee66efb5dd5dcd3fb15843ad4e85..a2bd5499916d735a3ec8143e93c8d79caa3485cf 100644 (file)
--- a/src/pf.c
+++ b/src/pf.c
#if HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NET_IF_H
# include <net/if.h>
#endif
diff --git a/src/pinba.c b/src/pinba.c
index 9f0a80023324d55c00871c2299a22aa484978f74..b6e7b152554a13b00af34ab0fe6bbf3d9be67381 100644 (file)
--- a/src/pinba.c
+++ b/src/pinba.c
#include "configfile.h"
#include <pthread.h>
-#include <sys/socket.h>
#include <netdb.h>
#include <poll.h>
diff --git a/src/ping.c b/src/ping.c
index d669aa937d4b15f187e7d3c69edd4f2d341b25f9..df2f6da6e6bc69158ebad65e8c47615cd10bfcad 100644 (file)
--- a/src/ping.c
+++ b/src/ping.c
hl->pkg_missed++;
/* if the host did not answer our last N packages, trigger a resolv. */
- if (ping_max_missed >= 0 && hl->pkg_missed >= ping_max_missed)
+ if ((ping_max_missed >= 0)
+ && (hl->pkg_missed >= ((uint32_t) ping_max_missed)))
{ /* {{{ */
/* we reset the missed package counter here, since we only want to
* trigger a resolv every N packages and not every package _AFTER_ N
diff --git a/src/postgresql.c b/src/postgresql.c
index 54c856d66464f68f9683a16c5c73cb630c180cbf..bef3490ff0f16852d345c85bf8c167f851116597 100644 (file)
--- a/src/postgresql.c
+++ b/src/postgresql.c
c_psql_database_t *db;
int success = 0;
- int i;
+ size_t i;
if ((ud == NULL) || (ud->data == NULL)) {
log_err ("c_psql_read: Invalid user data.");
{
char *str_ptr;
size_t str_len;
-
- int i;
+ size_t i;
str_ptr = string;
str_len = string_len;
{
char *str_ptr;
size_t str_len;
-
- int i;
+ size_t i;
str_ptr = string;
str_len = string_len;
size_t str_len;
gauge_t *rates = NULL;
-
- int i;
+ size_t i;
str_ptr = string;
str_len = string_len;
const char *params[9];
int success = 0;
- int i;
+ size_t i;
if ((ud == NULL) || (ud->data == NULL)) {
log_err ("c_psql_write: Invalid user data.");
c_psql_database_t *db;
char cb_name[DATA_MAX_NAME_LEN];
- struct timespec cb_interval = { 0, 0 };
user_data_t ud;
static _Bool have_flush = 0;
ssnprintf (cb_name, sizeof (cb_name), "postgresql-%s", db->instance);
if (db->queries_num > 0) {
- CDTIME_T_TO_TIMESPEC (db->interval, &cb_interval);
-
++db->ref_cnt;
plugin_register_complex_read ("postgresql", cb_name, c_psql_read,
- /* interval = */ (db->interval > 0) ? &cb_interval : NULL,
- &ud);
+ /* interval = */ db->interval, &ud);
}
if (db->writers_num > 0) {
++db->ref_cnt;
diff --git a/src/powerdns.c b/src/powerdns.c
index f9f291aed08b924cf6c9940e1020bc1b80ec647a..1050e7fa40447546c6e9a629b2703d1e4fc84800 100644 (file)
--- a/src/powerdns.c
+++ b/src/powerdns.c
#include <string.h>
#include <errno.h>
#include <sys/types.h>
-#include <sys/socket.h>
#include <sys/un.h>
#ifndef UNIX_PATH_MAX
typedef struct statname_lookup_s statname_lookup_t;
/* Description of statistics returned by the recursor: {{{
-all-outqueries counts the number of outgoing UDP queries since starting
-answers0-1 counts the number of queries answered within 1 millisecond
-answers100-1000 counts the number of queries answered within 1 second
-answers10-100 counts the number of queries answered within 100 milliseconds
-answers1-10 counts the number of queries answered within 10 milliseconds
-answers-slow counts the number of queries answered after 1 second
-cache-entries shows the number of entries in the cache
-cache-hits counts the number of cache hits since starting
-cache-misses counts the number of cache misses since starting
-chain-resends number of queries chained to existing outstanding query
-client-parse-errors counts number of client packets that could not be parsed
-concurrent-queries shows the number of MThreads currently running
-dlg-only-drops number of records dropped because of delegation only setting
-negcache-entries shows the number of entries in the Negative answer cache
-noerror-answers counts the number of times it answered NOERROR since starting
-nsspeeds-entries shows the number of entries in the NS speeds map
-nsset-invalidations number of times an nsset was dropped because it no longer worked
-nxdomain-answers counts the number of times it answered NXDOMAIN since starting
-outgoing-timeouts counts the number of timeouts on outgoing UDP queries since starting
-qa-latency shows the current latency average
-questions counts all End-user initiated queries with the RD bit set
-resource-limits counts number of queries that could not be performed because of resource limits
-server-parse-errors counts number of server replied packets that could not be parsed
-servfail-answers counts the number of times it answered SERVFAIL since starting
-spoof-prevents number of times PowerDNS considered itself spoofed, and dropped the data
-sys-msec number of CPU milliseconds spent in 'system' mode
-tcp-client-overflow number of times an IP address was denied TCP access because it already had too many connections
-tcp-outqueries counts the number of outgoing TCP queries since starting
-tcp-questions counts all incoming TCP queries (since starting)
-throttled-out counts the number of throttled outgoing UDP queries since starting
-throttle-entries shows the number of entries in the throttle map
-unauthorized-tcp number of TCP questions denied because of allow-from restrictions
-unauthorized-udp number of UDP questions denied because of allow-from restrictions
-unexpected-packets number of answers from remote servers that were unexpected (might point to spoofing)
-uptime number of seconds process has been running (since 3.1.5)
-user-msec number of CPU milliseconds spent in 'user' mode
+all-outqueries counts the number of outgoing UDP queries since starting
+answers-slow counts the number of queries answered after 1 second
+answers0-1 counts the number of queries answered within 1 millisecond
+answers1-10 counts the number of queries answered within 10 milliseconds
+answers10-100 counts the number of queries answered within 100 milliseconds
+answers100-1000 counts the number of queries answered within 1 second
+cache-bytes size of the cache in bytes (since 3.3.1)
+cache-entries shows the number of entries in the cache
+cache-hits counts the number of cache hits since starting, this does not include hits that got answered from the packet-cache
+cache-misses counts the number of cache misses since starting
+case-mismatches counts the number of mismatches in character case since starting
+chain-resends number of queries chained to existing outstanding query
+client-parse-errors counts number of client packets that could not be parsed
+concurrent-queries shows the number of MThreads currently running
+dlg-only-drops number of records dropped because of delegation only setting
+dont-outqueries number of outgoing queries dropped because of 'dont-query' setting (since 3.3)
+edns-ping-matches number of servers that sent a valid EDNS PING respons
+edns-ping-mismatches number of servers that sent an invalid EDNS PING response
+failed-host-entries number of servers that failed to resolve
+ipv6-outqueries number of outgoing queries over IPv6
+ipv6-questions counts all End-user initiated queries with the RD bit set, received over IPv6 UDP
+malloc-bytes returns the number of bytes allocated by the process (broken, always returns 0)
+max-mthread-stack maximum amount of thread stack ever used
+negcache-entries shows the number of entries in the Negative answer cache
+no-packet-error number of errorneous received packets
+noedns-outqueries number of queries sent out without EDNS
+noerror-answers counts the number of times it answered NOERROR since starting
+noping-outqueries number of queries sent out without ENDS PING
+nsset-invalidations number of times an nsset was dropped because it no longer worked
+nsspeeds-entries shows the number of entries in the NS speeds map
+nxdomain-answers counts the number of times it answered NXDOMAIN since starting
+outgoing-timeouts counts the number of timeouts on outgoing UDP queries since starting
+over-capacity-drops questions dropped because over maximum concurrent query limit (since 3.2)
+packetcache-bytes size of the packet cache in bytes (since 3.3.1)
+packetcache-entries size of packet cache (since 3.2)
+packetcache-hits packet cache hits (since 3.2)
+packetcache-misses packet cache misses (since 3.2)
+policy-drops packets dropped because of (Lua) policy decision
+qa-latency shows the current latency average
+questions counts all end-user initiated queries with the RD bit set
+resource-limits counts number of queries that could not be performed because of resource limits
+security-status security status based on security polling
+server-parse-errors counts number of server replied packets that could not be parsed
+servfail-answers counts the number of times it answered SERVFAIL since starting
+spoof-prevents number of times PowerDNS considered itself spoofed, and dropped the data
+sys-msec number of CPU milliseconds spent in 'system' mode
+tcp-client-overflow number of times an IP address was denied TCP access because it already had too many connections
+tcp-clients counts the number of currently active TCP/IP clients
+tcp-outqueries counts the number of outgoing TCP queries since starting
+tcp-questions counts all incoming TCP queries (since starting)
+throttle-entries shows the number of entries in the throttle map
+throttled-out counts the number of throttled outgoing UDP queries since starting
+throttled-outqueries idem to throttled-out
+unauthorized-tcp number of TCP questions denied because of allow-from restrictions
+unauthorized-udp number of UDP questions denied because of allow-from restrictions
+unexpected-packets number of answers from remote servers that were unexpected (might point to spoofing)
+unreachables number of times nameservers were unreachable since starting
+uptime number of seconds process has been running (since 3.1.5)
+user-msec number of CPU milliseconds spent in 'user' mode
}}} */
const char* const default_server_fields[] = /* {{{ */
{"udp-answers-bytes", "total_bytes", "udp-answers-bytes"},
/* Cache stuff */
+ {"cache-bytes", "cache_size", "cache-bytes"},
+ {"packetcache-bytes", "cache_size", "packet-bytes"},
+ {"packetcache-entries", "cache_size", "packet-entries"},
{"packetcache-hit", "cache_result", "packet-hit"},
+ {"packetcache-hits", "cache_result", "packet-hit"},
{"packetcache-miss", "cache_result", "packet-miss"},
+ {"packetcache-misses", "cache_result", "packet-miss"},
{"packetcache-size", "cache_size", "packet"},
{"key-cache-size", "cache_size", "key"},
{"meta-cache-size", "cache_size", "meta"},
{"corrupt-packets", "ipt_packets", "corrupt"},
{"deferred-cache-inserts", "counter", "cache-deferred_insert"},
{"deferred-cache-lookup", "counter", "cache-deferred_lookup"},
+ {"dont-outqueries", "dns_question", "dont-outqueries"},
{"qsize-a", "cache_size", "answers"},
{"qsize-q", "cache_size", "questions"},
{"servfail-packets", "ipt_packets", "servfail"},
* Recursor statistics *
***********************/
/* Answers by return code */
- {"noerror-answers", "dns_rcode", "NOERROR"},
- {"nxdomain-answers", "dns_rcode", "NXDOMAIN"},
- {"servfail-answers", "dns_rcode", "SERVFAIL"},
+ {"noerror-answers", "dns_rcode", "NOERROR"},
+ {"nxdomain-answers", "dns_rcode", "NXDOMAIN"},
+ {"servfail-answers", "dns_rcode", "SERVFAIL"},
/* CPU utilization */
- {"sys-msec", "cpu", "system"},
- {"user-msec", "cpu", "user"},
+ {"sys-msec", "cpu", "system"},
+ {"user-msec", "cpu", "user"},
/* Question-to-answer latency */
- {"qa-latency", "latency", NULL},
+ {"qa-latency", "latency", NULL},
/* Cache */
- {"cache-entries", "cache_size", NULL},
- {"cache-hits", "cache_result", "hit"},
- {"cache-misses", "cache_result", "miss"},
+ {"cache-entries", "cache_size", NULL},
+ {"cache-hits", "cache_result", "hit"},
+ {"cache-misses", "cache_result", "miss"},
/* Total number of questions.. */
- {"questions", "dns_qtype", "total"},
+ {"questions", "dns_qtype", "total"},
/* All the other stuff.. */
- {"all-outqueries", "dns_question", "outgoing"},
- {"answers0-1", "dns_answer", "0_1"},
- {"answers1-10", "dns_answer", "1_10"},
- {"answers10-100", "dns_answer", "10_100"},
- {"answers100-1000", "dns_answer", "100_1000"},
- {"answers-slow", "dns_answer", "slow"},
- {"chain-resends", "dns_question", "chained"},
- {"client-parse-errors", "counter", "drops-client_parse_error"},
- {"concurrent-queries", "dns_question", "concurrent"},
- {"dlg-only-drops", "counter", "drops-delegation_only"},
- {"negcache-entries", "cache_size", "negative"},
- {"nsspeeds-entries", "gauge", "entries-ns_speeds"},
- {"nsset-invalidations", "counter", "ns_set_invalidation"},
- {"outgoing-timeouts", "counter", "drops-timeout_outgoing"},
- {"resource-limits", "counter", "drops-resource_limit"},
- {"server-parse-errors", "counter", "drops-server_parse_error"},
- {"spoof-prevents", "counter", "drops-spoofed"},
- {"tcp-client-overflow", "counter", "denied-client_overflow_tcp"},
- {"tcp-outqueries", "dns_question", "outgoing-tcp"},
- {"tcp-questions", "dns_question", "incoming-tcp"},
- {"throttled-out", "dns_question", "outgoing-throttled"},
- {"throttle-entries", "gauge", "entries-throttle"},
- {"unauthorized-tcp", "counter", "denied-unauthorized_tcp"},
- {"unauthorized-udp", "counter", "denied-unauthorized_udp"},
- {"unexpected-packets", "dns_answer", "unexpected"},
- {"uptime", "uptime", NULL}
+ {"all-outqueries", "dns_question", "outgoing"},
+ {"answers0-1", "dns_answer", "0_1"},
+ {"answers1-10", "dns_answer", "1_10"},
+ {"answers10-100", "dns_answer", "10_100"},
+ {"answers100-1000", "dns_answer", "100_1000"},
+ {"answers-slow", "dns_answer", "slow"},
+ {"case-mismatches", "counter", "case_mismatches"},
+ {"chain-resends", "dns_question", "chained"},
+ {"client-parse-errors", "counter", "drops-client_parse_error"},
+ {"concurrent-queries", "dns_question", "concurrent"},
+ {"dlg-only-drops", "counter", "drops-delegation_only"},
+ {"edns-ping-matches", "counter", "edns-ping_matches"},
+ {"edns-ping-mismatches", "counter", "edns-ping_mismatches"},
+ {"failed-host-entries", "counter", "entries-failed_host"},
+ {"ipv6-outqueries", "dns_question", "outgoing-ipv6"},
+ {"ipv6-questions", "dns_question", "incoming-ipv6"},
+ {"malloc-bytes", "gauge", "malloc_bytes"},
+ {"max-mthread-stack", "gauge", "max_mthread_stack"},
+ {"no-packet-error", "gauge", "no_packet_error"},
+ {"noedns-outqueries", "dns_question", "outgoing-noedns"},
+ {"noping-outqueries", "dns_question", "outgoing-noping"},
+ {"over-capacity-drops", "dns_question", "incoming-over_capacity"},
+ {"negcache-entries", "cache_size", "negative"},
+ {"nsspeeds-entries", "gauge", "entries-ns_speeds"},
+ {"nsset-invalidations", "counter", "ns_set_invalidation"},
+ {"outgoing-timeouts", "counter", "drops-timeout_outgoing"},
+ {"policy-drops", "counter", "drops-policy"},
+ {"resource-limits", "counter", "drops-resource_limit"},
+ {"server-parse-errors", "counter", "drops-server_parse_error"},
+ {"spoof-prevents", "counter", "drops-spoofed"},
+ {"tcp-client-overflow", "counter", "denied-client_overflow_tcp"},
+ {"tcp-clients", "gauge", "clients-tcp"},
+ {"tcp-outqueries", "dns_question", "outgoing-tcp"},
+ {"tcp-questions", "dns_question", "incoming-tcp"},
+ {"throttled-out", "dns_question", "outgoing-throttled"},
+ {"throttle-entries", "gauge", "entries-throttle"},
+ {"throttled-outqueries", "dns_question", "outgoing-throttle"},
+ {"unauthorized-tcp", "counter", "denied-unauthorized_tcp"},
+ {"unauthorized-udp", "counter", "denied-unauthorized_udp"},
+ {"unexpected-packets", "dns_answer", "unexpected"},
+ {"uptime", "uptime", NULL}
}; /* }}} */
int lookup_table_length = STATIC_ARRAY_SIZE (lookup_table);
static char *local_sockpath = NULL;
/* TODO: Do this before 4.4:
- * - Recursor:
- * - Complete list of known pdns -> collectd mappings.
* - Update the collectd.conf(5) manpage.
*
* -octo
*/
-/* <http://doc.powerdns.com/recursor-stats.html> */
+/* <https://doc.powerdns.com/md/recursor/stats/> */
static void submit (const char *plugin_instance, /* {{{ */
const char *pdns_type, const char *value)
{
if (ds->ds_num != 1)
{
- ERROR ("powerdns plugin: type `%s' has %i data sources, "
+ ERROR ("powerdns plugin: type `%s' has %zu data sources, "
"but I can only handle one.",
type, ds->ds_num);
return;
return (-1);
}
buffer[sizeof (buffer) - 1] = 0;
- int i = strlen (buffer);
- if (i < sizeof (buffer) - 2)
+ size_t len = strlen (buffer);
+ if (len < sizeof (buffer) - 2)
{
- buffer[i++] = ' ';
- buffer[i++] = '\n';
- buffer[i++] = '\0';
+ buffer[len++] = ' ';
+ buffer[len++] = '\n';
+ buffer[len++] = '\0';
}
}
diff --git a/src/processes.c b/src/processes.c
index bac61c09e3867bb2ff59fc142b2208f314549e21..d094e73ec005830f6937a6b94eb4d65ce81c7c38 100644 (file)
--- a/src/processes.c
+++ b/src/processes.c
derive_t io_syscr;
derive_t io_syscw;
+ derive_t cswitch_vol;
+ derive_t cswitch_invol;
+
struct procstat_entry_s *next;
} procstat_entry_t;
derive_t io_syscr;
derive_t io_syscw;
+ derive_t cswitch_vol;
+ derive_t cswitch_invol;
+
struct procstat *next;
struct procstat_entry_s *instances;
} procstat_t;
static procstat_t *list_head_g = NULL;
+static _Bool report_ctx_switch = 0;
+
#if HAVE_THREAD_INFO
static mach_port_t port_host_self;
static mach_port_t port_task_self;
@@ -398,6 +406,8 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t
pse->io_wchar = entry->io_wchar;
pse->io_syscr = entry->io_syscr;
pse->io_syscw = entry->io_syscw;
+ pse->cswitch_vol = entry->cswitch_vol;
+ pse->cswitch_invol = entry->cswitch_invol;
ps->num_proc += pse->num_proc;
ps->num_lwp += pse->num_lwp;
@@ -412,6 +422,9 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t
ps->io_syscr += ((pse->io_syscr == -1)?0:pse->io_syscr);
ps->io_syscw += ((pse->io_syscw == -1)?0:pse->io_syscw);
+ ps->cswitch_vol += ((pse->cswitch_vol == -1)?0:pse->cswitch_vol);
+ ps->cswitch_invol += ((pse->cswitch_invol == -1)?0:pse->cswitch_invol);
+
if ((entry->vmem_minflt_counter == 0)
&& (entry->vmem_majflt_counter == 0))
{
ps->io_wchar = -1;
ps->io_syscr = -1;
ps->io_syscw = -1;
+ ps->cswitch_vol = -1;
+ ps->cswitch_invol = -1;
pse_prev = NULL;
pse = ps->instances;
ps_list_register (c->values[0].value.string,
c->values[1].value.string);
}
+ else if (strcasecmp (c->key, "CollectContextSwitch") == 0)
+ {
+ cf_util_get_boolean (c, &report_ctx_switch);
+ }
else
{
ERROR ("processes plugin: The `%s' configuration option is not "
plugin_dispatch_values (&vl);
}
+ if ( report_ctx_switch )
+ {
+ sstrncpy (vl.type, "contextswitch", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "voluntary", sizeof (vl.type_instance));
+ vl.values[0].derive = ps->cswitch_vol;
+ vl.values_len = 1;
+ plugin_dispatch_values (&vl);
+
+ sstrncpy (vl.type, "contextswitch", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "involuntary", sizeof (vl.type_instance));
+ vl.values[0].derive = ps->cswitch_invol;
+ vl.values_len = 1;
+ plugin_dispatch_values (&vl);
+ }
+
DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; "
"vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
"vmem_code = %lu; "
"vmem_minflt_counter = %"PRIi64"; vmem_majflt_counter = %"PRIi64"; "
"cpu_user_counter = %"PRIi64"; cpu_system_counter = %"PRIi64"; "
"io_rchar = %"PRIi64"; io_wchar = %"PRIi64"; "
- "io_syscr = %"PRIi64"; io_syscw = %"PRIi64";",
+ "io_syscr = %"PRIi64"; io_syscw = %"PRIi64"; "
+ "cswitch_vol = %"PRIi64"; cswitch_invol = %"PRIi64";",
ps->name, ps->num_proc, ps->num_lwp,
ps->vmem_size, ps->vmem_rss,
ps->vmem_data, ps->vmem_code,
ps->vmem_minflt_counter, ps->vmem_majflt_counter,
ps->cpu_user_counter, ps->cpu_system_counter,
- ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw);
+ ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw,
+ ps->cswitch_vol, ps->cswitch_invol);
} /* void ps_submit_proc_list */
#if KERNEL_LINUX || KERNEL_SOLARIS
/* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
#if KERNEL_LINUX
-static int ps_read_tasks (int pid)
+static procstat_t *ps_read_tasks_status (int pid, procstat_t *ps)
{
char dirname[64];
DIR *dh;
+ char filename[64];
+ FILE *fh;
struct dirent *ent;
- int count = 0;
+ derive_t cswitch_vol = 0;
+ derive_t cswitch_invol = 0;
+ char buffer[1024];
+ char *fields[8];
+ int numfields;
ssnprintf (dirname, sizeof (dirname), "/proc/%i/task", pid);
if ((dh = opendir (dirname)) == NULL)
{
DEBUG ("Failed to open directory `%s'", dirname);
- return (-1);
+ return (NULL);
}
while ((ent = readdir (dh)) != NULL)
{
+ char *tpid;
+
if (!isdigit ((int) ent->d_name[0]))
continue;
- else
- count++;
+
+ tpid = ent->d_name;
+
+ ssnprintf (filename, sizeof (filename), "/proc/%i/task/%s/status", pid, tpid);
+ if ((fh = fopen (filename, "r")) == NULL)
+ {
+ DEBUG ("Failed to open file `%s'", filename);
+ continue;
+ }
+
+ while (fgets (buffer, sizeof(buffer), fh) != NULL)
+ {
+ derive_t tmp;
+ char *endptr;
+
+ if (strncmp (buffer, "voluntary_ctxt_switches", 23) != 0
+ && strncmp (buffer, "nonvoluntary_ctxt_switches", 26) != 0)
+ continue;
+
+ numfields = strsplit (buffer, fields,
+ STATIC_ARRAY_SIZE (fields));
+
+ if (numfields < 2)
+ continue;
+
+ errno = 0;
+ endptr = NULL;
+ tmp = (derive_t) strtoll (fields[1], &endptr, /* base = */ 10);
+ if ((errno == 0) && (endptr != fields[1]))
+ {
+ if (strncmp (buffer, "voluntary_ctxt_switches", 23) == 0)
+ {
+ cswitch_vol += tmp;
+ }
+ else if (strncmp (buffer, "nonvoluntary_ctxt_switches", 26) == 0)
+ {
+ cswitch_invol += tmp;
+ }
+ }
+ } /* while (fgets) */
+
+ if (fclose (fh))
+ {
+ char errbuf[1024];
+ WARNING ("processes: fclose: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ }
}
closedir (dh);
- return ((count >= 1) ? count : 1);
-} /* int *ps_read_tasks */
+ ps->cswitch_vol = cswitch_vol;
+ ps->cswitch_invol = cswitch_invol;
-/* Read advanced virtual memory data from /proc/pid/status */
-static procstat_t *ps_read_vmem (int pid, procstat_t *ps)
+ return (ps);
+} /* int *ps_read_tasks_status */
+
+/* Read data from /proc/pid/status */
+static procstat_t *ps_read_status (int pid, procstat_t *ps)
{
FILE *fh;
char buffer[1024];
char filename[64];
- unsigned long long lib = 0;
- unsigned long long exe = 0;
- unsigned long long data = 0;
+ unsigned long lib = 0;
+ unsigned long exe = 0;
+ unsigned long data = 0;
+ unsigned long threads = 0;
char *fields[8];
int numfields;
while (fgets (buffer, sizeof(buffer), fh) != NULL)
{
- long long tmp;
+ unsigned long tmp;
char *endptr;
- if (strncmp (buffer, "Vm", 2) != 0)
+ if (strncmp (buffer, "Vm", 2) != 0
+ && strncmp (buffer, "Threads", 7) != 0)
continue;
numfields = strsplit (buffer, fields,
errno = 0;
endptr = NULL;
- tmp = strtoll (fields[1], &endptr, /* base = */ 10);
+ tmp = strtoul (fields[1], &endptr, /* base = */ 10);
if ((errno == 0) && (endptr != fields[1]))
{
if (strncmp (buffer, "VmData", 6) == 0)
{
exe = tmp;
}
+ else if (strncmp(buffer, "Threads", 7) == 0)
+ {
+ threads = tmp;
+ }
}
} /* while (fgets) */
ps->vmem_data = data * 1024;
ps->vmem_code = (exe + lib) * 1024;
+ if (threads != 0)
+ ps->num_lwp = threads;
return (ps);
} /* procstat_t *ps_read_vmem */
char *fields[64];
char fields_len;
- int buffer_len;
+ size_t buffer_len;
- char *buffer_ptr;
+ char *buffer_ptr;
size_t name_start_pos;
size_t name_end_pos;
size_t name_len;
long long unsigned vmem_rss;
long long unsigned stack_size;
+ ssize_t status;
+
memset (ps, 0, sizeof (procstat_t));
ssnprintf (filename, sizeof (filename), "/proc/%i/stat", pid);
- buffer_len = read_file_contents (filename,
- buffer, sizeof(buffer) - 1);
- if (buffer_len <= 0)
+ status = read_file_contents (filename, buffer, sizeof(buffer) - 1);
+ if (status <= 0)
return (-1);
+ buffer_len = (size_t) status;
buffer[buffer_len] = 0;
/* The name of the process is enclosed in parens. Since the name can
}
else
{
- if ( (ps->num_lwp = ps_read_tasks (pid)) == -1 )
+ ps->num_lwp = strtoul (fields[17], /* endptr = */ NULL, /* base = */ 10);
+ if ((ps_read_status(pid, ps)) == NULL)
{
- /* returns -1 => kernel 2.4 */
- ps->num_lwp = 1;
+ /* No VMem data */
+ ps->vmem_data = -1;
+ ps->vmem_code = -1;
+ DEBUG("ps_read_process: did not get vmem data for pid %i",pid);
}
+ if (ps->num_lwp <= 0)
+ ps->num_lwp = 1;
ps->num_proc = 1;
}
cpu_system_counter = cpu_system_counter * 1000000 / CONFIG_HZ;
vmem_rss = vmem_rss * pagesize_g;
- if ( (ps_read_vmem(pid, ps)) == NULL)
- {
- /* No VMem data */
- ps->vmem_data = -1;
- ps->vmem_code = -1;
- DEBUG("ps_read_process: did not get vmem data for pid %i",pid);
- }
-
ps->cpu_user_counter = cpu_user_counter;
ps->cpu_system_counter = cpu_system_counter;
ps->vmem_size = (unsigned long) vmem_size;
DEBUG("ps_read_process: not get io data for pid %i",pid);
}
+ if ( report_ctx_switch )
+ {
+ if ( (ps_read_tasks_status(pid, ps)) == NULL)
+ {
+ ps->cswitch_vol = -1;
+ ps->cswitch_invol = -1;
+
+ DEBUG("ps_read_tasks_status: not get context "
+ "switch data for pid %i",pid);
+ }
+ }
+
/* success */
return (0);
} /* int ps_read_process (...) */
{
char path[PATH_MAX];
psinfo_t info;
- int status;
+ ssize_t status;
snprintf(path, sizeof (path), "/proc/%li/psinfo", pid);
status = read_file_contents (path, (void *) &info, sizeof (info));
- if (status != sizeof (info))
+ if ((status < 0) || (((size_t) status) != sizeof (info)))
{
ERROR ("processes plugin: Unexpected return value "
"while reading \"%s\": "
- "Returned %i but expected %zu.",
+ "Returned %zd but expected %zu.",
path, status, buffer_size);
return (NULL);
}
pse.io_syscr = ps.io_syscr;
pse.io_syscw = ps.io_syscw;
+ pse.cswitch_vol = ps.cswitch_vol;
+ pse.cswitch_invol = ps.cswitch_invol;
+
switch (state)
{
case 'R': running++; break;
diff --git a/src/python.c b/src/python.c
index e7795c751ef757fc2c97611d0838035df3b79acf..210d785c847d9d5b6e5577efdca0001163ffd9c7 100644 (file)
--- a/src/python.c
+++ b/src/python.c
}
static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_list, user_data_t *data) {
- int i;
+ size_t i;
cpy_callback_t *c = data->data;
PyObject *ret, *list, *temp, *dict = NULL;
Values *v;
@@ -355,22 +355,13 @@ static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_li
}
for (i = 0; i < value_list->values_len; ++i) {
if (ds->ds[i].type == DS_TYPE_COUNTER) {
- if ((long) value_list->values[i].counter == value_list->values[i].counter)
- PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].counter));
- else
- PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
+ PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
} else if (ds->ds[i].type == DS_TYPE_GAUGE) {
PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].gauge));
} else if (ds->ds[i].type == DS_TYPE_DERIVE) {
- if ((long) value_list->values[i].derive == value_list->values[i].derive)
- PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].derive));
- else
- PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
+ PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
} else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) {
- if ((long) value_list->values[i].absolute == value_list->values[i].absolute)
- PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].absolute));
- else
- PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
+ PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
} else {
Py_BEGIN_ALLOW_THREADS
ERROR("cpy_write_callback: Unknown value type %d.", ds->ds[i].type);
}
static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
- int i;
+ size_t i;
char *name;
const data_set_t *ds;
PyObject *list, *tuple;
@@ -653,7 +644,6 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwd
double interval = 0;
char *name = NULL;
PyObject *callback = NULL, *data = NULL;
- struct timespec ts;
static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback, &interval, &data, NULL, &name) == 0) return NULL;
@@ -675,10 +665,8 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwd
user_data = malloc(sizeof(*user_data));
user_data->free_func = cpy_destroy_user_data;
user_data->data = c;
- ts.tv_sec = interval;
- ts.tv_nsec = (interval - ts.tv_sec) * 1000000000;
plugin_register_complex_read(/* group = */ NULL, buf,
- cpy_read_callback, &ts, user_data);
+ cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), user_data);
return cpy_string_to_unicode_or_bytes(buf);
}
diff --git a/src/pyvalues.c b/src/pyvalues.c
index 78e6cf9d450413ed242fb73e6126a09f4dd86057..44176014fc27dc68de218f00acf6c2e8bf8560d7 100644 (file)
--- a/src/pyvalues.c
+++ b/src/pyvalues.c
}
static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
- int i, ret;
+ int ret;
const data_set_t *ds;
- int size;
+ size_t size, i;
value_t *value;
value_list_t value_list = VALUE_LIST_INIT;
PyObject *values = self->values, *meta = self->meta;
@@ -542,15 +542,15 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
PyErr_Format(PyExc_TypeError, "meta must be a dict");
return NULL;
}
- size = (int) PySequence_Length(values);
+ size = (size_t) PySequence_Length(values);
if (size != ds->ds_num) {
- PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", value_list.type, ds->ds_num, size);
+ PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu", value_list.type, ds->ds_num, size);
return NULL;
}
- value = malloc(size * sizeof(*value));
+ value = calloc(size, sizeof(*value));
for (i = 0; i < size; ++i) {
PyObject *item, *num;
- item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
+ item = PySequence_Fast_GET_ITEM(values, (int) i); /* Borrowed reference. */
if (ds->ds->type == DS_TYPE_COUNTER) {
num = PyNumber_Long(item); /* New reference. */
if (num != NULL) {
@@ -611,9 +611,9 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
}
static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
- int i, ret;
+ int ret;
const data_set_t *ds;
- int size;
+ size_t size, i;
value_t *value;
value_list_t value_list = VALUE_LIST_INIT;
PyObject *values = self->values, *meta = self->meta;
PyErr_Format(PyExc_TypeError, "values must be list or tuple");
return NULL;
}
- size = (int) PySequence_Length(values);
+ size = (size_t) PySequence_Length(values);
if (size != ds->ds_num) {
- PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", value_list.type, ds->ds_num, size);
+ PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu", value_list.type, ds->ds_num, size);
return NULL;
}
- value = malloc(size * sizeof(*value));
+ value = calloc(size, sizeof(*value));
for (i = 0; i < size; ++i) {
PyObject *item, *num;
item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
diff --git a/src/routeros.c b/src/routeros.c
index 4863d7c082b1e8297b48152c379dc6a4701b0a1d..667c2fa581722e00ef01161e385d6e13d0c4e36a 100644 (file)
--- a/src/routeros.c
+++ b/src/routeros.c
user_data.free_func = (void *) cr_free_data;
if (status == 0)
status = plugin_register_complex_read (/* group = */ NULL, read_name,
- cr_read, /* interval = */ NULL, &user_data);
+ cr_read, /* interval = */ 0, &user_data);
if (status != 0)
cr_free_data (router_data);
diff --git a/src/rrdcached.c b/src/rrdcached.c
index 645032cbe189686a707c7e6d34db7343432b8882..5d98de8e0dbd5dec3aaba79ea5bda1a03363c85f 100644 (file)
--- a/src/rrdcached.c
+++ b/src/rrdcached.c
{
int offset;
int status;
- int i;
+ size_t i;
time_t t;
assert (0 == strcmp (ds->type, vl->type));
diff --git a/src/rrdtool.c b/src/rrdtool.c
index 8497a24cd8b1f393a922acadd9907f02020ce77c..764d6d65db0d2b545c94f41b8a105cd0cda3e97e 100644 (file)
--- a/src/rrdtool.c
+++ b/src/rrdtool.c
int offset;
int status;
time_t tt;
- int i;
+ size_t i;
memset (buffer, '\0', buffer_len);
diff --git a/src/serial.c b/src/serial.c
index 430082220595c58f2b927089871a76e4e482a157..0878d3c93b1dac2b4d4bc331e4d13e56a358ede9 100644 (file)
--- a/src/serial.c
+++ b/src/serial.c
FILE *fh;
char buffer[1024];
- derive_t rx = 0;
- derive_t tx = 0;
-
- char *fields[16];
- int i, numfields;
- int len;
-
/* there are a variety of names for the serial device */
if ((fh = fopen ("/proc/tty/driver/serial", "r")) == NULL &&
(fh = fopen ("/proc/tty/driver/ttyS", "r")) == NULL)
while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
- int have_rx = 0, have_tx = 0;
+ derive_t rx = 0;
+ derive_t tx = 0;
+ _Bool have_rx = 0, have_tx = 0;
+ size_t len;
- numfields = strsplit (buffer, fields, 16);
+ char *fields[16];
+ int numfields;
+ int i;
+ numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
if (numfields < 6)
continue;
* 0: uart:16550A port:000003F8 irq:4 tx:0 rx:0
* 1: uart:16550A port:000002F8 irq:3 tx:0 rx:0
*/
- len = strlen (fields[0]) - 1;
- if (len < 1)
+ len = strlen (fields[0]);
+ if (len < 2)
continue;
- if (fields[0][len] != ':')
+ if (fields[0][len - 1] != ':')
continue;
- fields[0][len] = '\0';
+ fields[0][len - 1] = 0;
for (i = 1; i < numfields; i++)
{
if (strncmp (fields[i], "tx:", 3) == 0)
{
- tx = atoll (fields[i] + 3);
- have_tx++;
+ if (strtoderive (fields[i] + 3, &tx) == 0)
+ have_tx = 1;
}
else if (strncmp (fields[i], "rx:", 3) == 0)
{
- rx = atoll (fields[i] + 3);
- have_rx++;
+ if (strtoderive (fields[i] + 3, &rx) == 0)
+ have_rx = 1;
}
}
- if ((have_rx == 0) || (have_tx == 0))
- continue;
-
- serial_submit (fields[0], rx, tx);
+ if (have_rx && have_tx)
+ serial_submit (fields[0], rx, tx);
}
fclose (fh);
diff --git a/src/snmp.c b/src/snmp.c
index cb0b70fa15275360feab4ac8df55b8b479c03f74..18c52077fc0798079d9ba537fb1283f7fb460d70 100644 (file)
--- a/src/snmp.c
+++ b/src/snmp.c
instance_t instance;
char *instance_prefix;
oid_t *values;
- int values_len;
+ size_t values_len;
double scale;
double shift;
struct data_definition_s *next;
@@ -313,7 +313,7 @@ static int csnmp_config_add_data_values (data_definition_t *dd, oconfig_item_t *
dd->values = (oid_t *) malloc (sizeof (oid_t) * ci->values_num);
if (dd->values == NULL)
return (-1);
- dd->values_len = ci->values_num;
+ dd->values_len = (size_t) ci->values_num;
for (i = 0; i < ci->values_num; i++)
{
return (-1);
}
- DEBUG ("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = %i }",
+ DEBUG ("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = %zu }",
dd->name, dd->type, (dd->is_table != 0) ? "true" : "false", dd->values_len);
if (data_head == NULL)
/* Registration stuff. */
char cb_name[DATA_MAX_NAME_LEN];
user_data_t cb_data;
- struct timespec cb_interval;
hd = (host_definition_t *) malloc (sizeof (host_definition_t));
if (hd == NULL)
cb_data.data = hd;
cb_data.free_func = csnmp_host_definition_destroy;
- CDTIME_T_TO_TIMESPEC (hd->interval, &cb_interval);
-
status = plugin_register_complex_read (/* group = */ NULL, cb_name,
- csnmp_read_host, /* interval = */ &cb_interval,
- /* user_data = */ &cb_data);
+ csnmp_read_host, hd->interval, /* user_data = */ &cb_data);
if (status != 0)
{
ERROR ("snmp plugin: Registering complex read function failed.");
@@ -1053,6 +1049,10 @@ static value_t csnmp_value_list_to_value (struct variable_list *vl, int type,
return (ret);
} /* value_t csnmp_value_list_to_value */
+/* csnmp_strvbcopy_hexstring converts the bit string contained in "vb" to a hex
+ * representation and writes it to dst. Returns zero on success and ENOMEM if
+ * dst is not large enough to hold the string. dst is guaranteed to be
+ * nul-terminated. */
static int csnmp_strvbcopy_hexstring (char *dst, /* {{{ */
const struct variable_list *vb, size_t dst_size)
{
size_t buffer_free;
size_t i;
+ dst[0] = 0;
+
buffer_ptr = dst;
buffer_free = dst_size;
status = snprintf (buffer_ptr, buffer_free,
(i == 0) ? "%02x" : ":%02x", (unsigned int) vb->val.bitstring[i]);
+ assert (status >= 0);
- if (status >= buffer_free)
+ if (((size_t) status) >= buffer_free) /* truncated */
{
- buffer_ptr += (buffer_free - 1);
- *buffer_ptr = 0;
- return (dst_size + (buffer_free - status));
+ dst[dst_size - 1] = 0;
+ return ENOMEM;
}
else /* if (status < buffer_free) */
{
- buffer_ptr += status;
- buffer_free -= status;
+ buffer_ptr += (size_t) status;
+ buffer_free -= (size_t) status;
}
}
- return ((int) (dst_size - buffer_free));
+ return 0;
} /* }}} int csnmp_strvbcopy_hexstring */
+/* csnmp_strvbcopy copies the octet string or bit string contained in vb to
+ * dst. If non-printable characters are detected, it will switch to a hex
+ * representation of the string. Returns zero on success, EINVAL if vb does not
+ * contain a string and ENOMEM if dst is not large enough to contain the
+ * string. */
static int csnmp_strvbcopy (char *dst, /* {{{ */
const struct variable_list *vb, size_t dst_size)
{
dst[i] = src[i];
}
dst[num_chars] = 0;
+ dst[dst_size - 1] = 0;
- return ((int) vb->val_len);
+ if (dst_size <= vb->val_len)
+ return ENOMEM;
+
+ return 0;
} /* }}} int csnmp_strvbcopy */
static int csnmp_instance_list_add (csnmp_list_instances_t **head,
@@ -1224,7 +1235,7 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
csnmp_list_instances_t *instance_list_ptr;
csnmp_table_values_t **value_table_ptr;
- int i;
+ size_t i;
_Bool have_more;
oid_t current_suffix;
@@ -1239,7 +1250,7 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
instance_list_ptr = instance_list;
- value_table_ptr = calloc ((size_t) data->values_len, sizeof (*value_table_ptr));
+ value_table_ptr = calloc (data->values_len, sizeof (*value_table_ptr));
if (value_table_ptr == NULL)
return (-1);
for (i = 0; i < data->values_len; i++)
@@ -1382,7 +1393,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
const data_set_t *ds;
- uint32_t oid_list_len = (uint32_t) (data->values_len + 1);
+ size_t oid_list_len = data->values_len + 1;
/* Holds the last OID returned by the device. We use this in the GETNEXT
* request to proceed. */
oid_t oid_list[oid_list_len];
@@ -1391,8 +1402,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
_Bool oid_list_todo[oid_list_len];
int status;
- int i;
- uint32_t j;
+ size_t i;
/* `value_list_head' and `value_list_tail' implement a linked list for each
* value. `instance_list_head' and `instance_list_tail' implement a linked list of
@@ -1420,7 +1430,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
if (ds->ds_num != data->values_len)
{
- ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i",
+ ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu",
data->type, ds->ds_num, data->values_len);
return (-1);
}
@@ -1433,8 +1443,8 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
else /* no InstanceFrom option specified. */
oid_list_len--;
- for (j = 0; j < oid_list_len; j++)
- oid_list_todo[j] = 1;
+ for (i = 0; i < oid_list_len; i++)
+ oid_list_todo[i] = 1;
/* We're going to construct n linked lists, one for each "value".
* value_list_head will contain pointers to the heads of these linked lists,
@@ -1466,13 +1476,13 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
}
oid_list_todo_num = 0;
- for (j = 0; j < oid_list_len; j++)
+ for (i = 0; i < oid_list_len; i++)
{
/* Do not rerequest already finished OIDs */
- if (!oid_list_todo[j])
+ if (!oid_list_todo[i])
continue;
oid_list_todo_num++;
- snmp_add_null_var (req, oid_list[j].oid, oid_list[j].oid_len);
+ snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len);
}
if (oid_list_todo_num == 0)
@@ -1568,7 +1578,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
if (ret != 0)
{
- DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
+ DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; "
"Value probably left its subtree.",
host->name, data->name, i);
oid_list_todo[i] = 0;
@@ -1580,7 +1590,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
if ((value_list_tail[i] != NULL)
&& (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0))
{
- DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
+ DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; "
"Suffix is not increasing.",
host->name, data->name, i);
oid_list_todo[i] = 0;
@@ -1664,7 +1674,7 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
value_list_t vl = VALUE_LIST_INIT;
int status;
- int i;
+ size_t i;
DEBUG ("snmp plugin: csnmp_read_value (host = %s, data = %s)",
host->name, data->name);
@@ -1684,7 +1694,7 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
if (ds->ds_num != data->values_len)
{
- ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i",
+ ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu",
data->type, ds->ds_num, data->values_len);
return (-1);
}
diff --git a/src/statsd.c b/src/statsd.c
index 5b0bdd693de71088f8ec47f3560b29c4c87f79f5..3ec1d9e938f4067f9a0ad9f37dc1104833cc4e43 100644 (file)
--- a/src/statsd.c
+++ b/src/statsd.c
#include <pthread.h>
#include <sys/types.h>
-#include <sys/socket.h>
#include <netdb.h>
#include <poll.h>
else
values[0].gauge = (gauge_t) c_avl_size (metric->set);
}
- else
- values[0].derive = (derive_t) metric->value;
+ else { /* STATSD_COUNTER */
+ /*
+ * Expand a single value to two metrics:
+ *
+ * - The absolute counter, as a gauge
+ * - A derived rate for this counter
+ */
+ values[0].derive = (derive_t) metric->value;
+ plugin_dispatch_values(&vl);
+
+ sstrncpy(vl.type, "gauge", sizeof (vl.type));
+ values[0].gauge = (gauge_t) metric->value;
+ }
return (plugin_dispatch_values (&vl));
} /* }}} int statsd_metric_submit_unsafe */
diff --git a/src/table.c b/src/table.c
index beded1ae9eeafef7e7bbfe0232ee80e954622fbe..b0bc95f80bb90c5f999c525d17aa9d94bbc1d8b7 100644 (file)
--- a/src/table.c
+++ b/src/table.c
*/
typedef struct {
- char *type;
- char *instance_prefix;
- int *instances;
- size_t instances_num;
- int *values;
- size_t values_num;
+ char *type;
+ char *instance_prefix;
+ size_t *instances;
+ size_t instances_num;
+ size_t *values;
+ size_t values_num;
const data_set_t *ds;
} tbl_result_t;
return 0;
} /* tbl_config_set_separator */
-static int tbl_config_append_array_i (char *name, int **var, size_t *len,
+static int tbl_config_append_array_i (char *name, size_t **var, size_t *len,
oconfig_item_t *ci)
{
- int *tmp;
-
+ size_t *tmp;
+ size_t num;
size_t i;
if (1 > ci->values_num) {
return 1;
}
- for (i = 0; i < ci->values_num; ++i) {
+ num = (size_t) ci->values_num;
+ for (i = 0; i < num; ++i) {
if (OCONFIG_TYPE_NUMBER != ci->values[i].type) {
log_err ("\"%s\" expects numerical arguments only.", name);
return 1;
}
}
- *len += ci->values_num;
- tmp = (int *)realloc (*var, *len * sizeof (**var));
+ tmp = realloc (*var, ((*len) + num) * sizeof (**var));
if (NULL == tmp) {
char errbuf[1024];
log_err ("realloc failed: %s.",
sstrerror (errno, errbuf, sizeof (errbuf)));
return -1;
}
-
*var = tmp;
- for (i = *len - ci->values_num; i < *len; ++i)
- (*var)[i] = (int)ci->values[i].value.number;
+ for (i = 0; i < num; ++i) {
+ (*var)[*len] = (size_t) ci->values[i].value.number;
+ (*len)++;
+ }
+
return 0;
} /* tbl_config_append_array_s */
tbl_result_t *res;
int status = 0;
- size_t i;
+ int i;
if (0 != ci->values_num) {
log_err ("<Result> does not expect any arguments.");
tbl = tables + tables_num - 1;
tbl_setup (tbl, ci->values[0].value.string);
- for (i = 0; i < ci->children_num; ++i) {
+ for (i = 0; i < ((size_t) ci->children_num); ++i) {
oconfig_item_t *c = ci->children + i;
if (0 == strcasecmp (c->key, "Separator"))
static int tbl_config (oconfig_item_t *ci)
{
- size_t i;
+ int i;
for (i = 0; i < ci->children_num; ++i) {
oconfig_item_t *c = ci->children + i;
return -1;
}
- if (res->values_num != (size_t)res->ds->ds_num) {
+ if (res->values_num != res->ds->ds_num) {
log_err ("Invalid type \"%s\". Expected %zu data source%s, "
- "got %i.", res->type, res->values_num,
+ "got %zu.", res->type, res->values_num,
(1 == res->values_num) ? "" : "s",
res->ds->ds_num);
return -1;
diff --git a/src/tail.c b/src/tail.c
index 3904f1be201acb31c089057bfe189d78e7e8c5ed..751243bcb58c219adc86d465cebb9aad3ece8337 100644 (file)
--- a/src/tail.c
+++ b/src/tail.c
static int ctail_init (void)
{
- struct timespec cb_interval;
char str[255];
user_data_t ud;
size_t i;
{
ud.data = (void *)tail_match_list[i];
ssnprintf(str, sizeof(str), "tail-%zu", i);
- CDTIME_T_TO_TIMESPEC (tail_match_list_intervals[i], &cb_interval);
- plugin_register_complex_read (NULL, str, ctail_read, &cb_interval, &ud);
+ plugin_register_complex_read (NULL, str, ctail_read, tail_match_list_intervals[i], &ud);
}
return (0);
diff --git a/src/tail_csv.c b/src/tail_csv.c
index c3efcc9a3d3c79c844590f5a898b5c45ccb00de0..bb9b58aceaa1edc459bbf7220f581c5e796997db 100644 (file)
--- a/src/tail_csv.c
+++ b/src/tail_csv.c
#include <string.h>
struct metric_definition_s {
- char *name;
- char *type;
- char *instance;
- int data_source_type;
- int value_from;
+ char *name;
+ char *type;
+ char *instance;
+ int data_source_type;
+ ssize_t value_from;
struct metric_definition_s *next;
};
typedef struct metric_definition_s metric_definition_t;
struct instance_definition_s {
- char *instance;
- char *path;
- cu_tail_t *tail;
+ char *instance;
+ char *path;
+ cu_tail_t *tail;
metric_definition_t **metric_list;
- size_t metric_list_len;
- cdtime_t interval;
- int time_from;
+ size_t metric_list_len;
+ cdtime_t interval;
+ ssize_t time_from;
struct instance_definition_s *next;
};
typedef struct instance_definition_s instance_definition_t;
char **fields, size_t fields_num)
{
value_t v;
- cdtime_t t;
+ cdtime_t t = 0;
int status;
if (md->data_source_type == -1)
return (EINVAL);
- if (md->value_from >= fields_num)
+ assert (md->value_from >= 0);
+ if (((size_t) md->value_from) >= fields_num)
return (EINVAL);
- if (id->time_from >= 0 && (id->time_from >= fields_num))
- return (EINVAL);
-
- t = 0;
- if (id->time_from >= 0)
- t = parse_time (fields[id->time_from]);
-
status = parse_value (fields[md->value_from], &v, md->data_source_type);
if (status != 0)
return (status);
+ if (id->time_from >= 0) {
+ if (((size_t) id->time_from) >= fields_num)
+ return (EINVAL);
+ t = parse_time (fields[id->time_from]);
+ }
+
return (tcsv_submit (id, md, v, t));
}
-static _Bool tcsv_check_index (int index, size_t fields_num, char const *name)
+static _Bool tcsv_check_index (ssize_t index, size_t fields_num, char const *name)
{
if (index < 0)
return 1;
else if (((size_t) index) < fields_num)
return 1;
- ERROR ("tail_csv plugin: Metric \"%s\": Request for index %i when "
+ ERROR ("tail_csv plugin: Metric \"%s\": Request for index %zd when "
"only %zu fields are available.",
name, index, fields_num);
return (0);
tcsv_metric_definition_destroy (next);
}
-static int tcsv_config_get_index(oconfig_item_t *ci, int *ret_index) {
- int index;
-
+static int tcsv_config_get_index(oconfig_item_t *ci, ssize_t *ret_index) {
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)){
WARNING("tail_csv plugin: The \"%s\" config option needs exactly one "
"integer argument.", ci->key);
return (-1);
}
- index = (int) ci->values[0].value.number;
- if (index < 0) {
+ if (ci->values[0].value.number < 0) {
WARNING("tail_csv plugin: The \"%s\" config option must be positive "
"(or zero).", ci->key);
return (-1);
}
- *ret_index = index;
+ *ret_index = (ssize_t) ci->values[0].value.number;
return (0);
}
/* Parse metric */
static int tcsv_config_add_metric(oconfig_item_t *ci){
metric_definition_t *md;
- int status = 0;
+ int status;
int i;
md = (metric_definition_t *)malloc(sizeof(*md));
/* Registration variables */
char cb_name[DATA_MAX_NAME_LEN];
user_data_t cb_data;
- struct timespec cb_interval;
id = malloc(sizeof(*id));
if (id == NULL)
memset(&cb_data, 0, sizeof(cb_data));
cb_data.data = id;
cb_data.free_func = tcsv_instance_definition_destroy;
- CDTIME_T_TO_TIMESPEC(id->interval, &cb_interval);
- status = plugin_register_complex_read(NULL, cb_name, tcsv_read, &cb_interval, &cb_data);
+ status = plugin_register_complex_read(NULL, cb_name, tcsv_read, id->interval, &cb_data);
if (status != 0){
ERROR("tail_csv plugin: Registering complex read function failed.");
}
else if (ds->ds_num != 1)
{
- ERROR ("tail_csv plugin: The type \"%s\" has %i data sources. "
+ ERROR ("tail_csv plugin: The type \"%s\" has %zu data sources. "
"Only types with a single data soure are supported.",
ds->type, ds->ds_num);
continue;
index ceb454ecba7bb6e8579e27044468c876310437e0..14fb5418addc659a5c429c03160ff3ef8e84871a 100644 (file)
gauge_t *rates;
int rates_failed;
- int i;
+ size_t i;
if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
return (-EINVAL);
diff --git a/src/target_replace.c b/src/target_replace.c
index a85eced33532a75b7e81732ec7755ded9d2c1f66..bd8f9e5c51d443650545bc94325fe53df25233e3 100644 (file)
--- a/src/target_replace.c
+++ b/src/target_replace.c
}
subst_status = subst (temp, sizeof (temp), buffer,
- matches[0].rm_so, matches[0].rm_eo, act->replacement);
+ (size_t) matches[0].rm_so, (size_t) matches[0].rm_eo, act->replacement);
if (subst_status == NULL)
{
ERROR ("Target `replace': subst (buffer = %s, start = %zu, end = %zu, "
diff --git a/src/target_scale.c b/src/target_scale.c
index b29a02bfa64801d9e967294ba4d1af7e6ce0cb48..6169fa05d585ce4c7a97abc6c882b80dbbeb78db 100644 (file)
--- a/src/target_scale.c
+++ b/src/target_scale.c
if (failure == 0)
{
- uint64_t difference;
+ uint64_t diff;
double rate;
- /* Calcualte the rate */
- if (prev_counter > curr_counter) /* => counter overflow */
- {
- if (prev_counter <= 4294967295UL) /* 32 bit overflow */
- difference = (4294967295UL - prev_counter) + curr_counter;
- else /* 64 bit overflow */
- difference = (18446744073709551615ULL - prev_counter) + curr_counter;
- }
- else /* no overflow */
- {
- difference = curr_counter - prev_counter;
- }
- rate = ((double) difference) / CDTIME_T_TO_DOUBLE (vl->interval);
+ diff = (uint64_t) counter_diff (prev_counter, curr_counter);
+ rate = ((double) diff) / CDTIME_T_TO_DOUBLE (vl->interval);
/* Modify the rate. */
if (!isnan (data->factor))
/* Calculate the internal counter. */
int_fraction += (rate * CDTIME_T_TO_DOUBLE (vl->interval));
- difference = (uint64_t) int_fraction;
- int_fraction -= ((double) difference);
- int_counter += difference;
+ diff = (uint64_t) int_fraction;
+ int_fraction -= ((double) diff);
+ int_counter += diff;
assert (int_fraction >= 0.0);
assert (int_fraction < 1.0);
notification_meta_t __attribute__((unused)) **meta, void **user_data)
{
ts_data_t *data;
- int i;
+ size_t i;
if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
return (-EINVAL);
diff --git a/src/tcpconns.c b/src/tcpconns.c
index 5d4bb6966f98b024e57ffc7fd0956082777212ab..8f40be6f786b13d901c4ee5847580c0a01db270e 100644 (file)
--- a/src/tcpconns.c
+++ b/src/tcpconns.c
#if KERNEL_LINUX
# include <asm/types.h>
-/* sys/socket.h is necessary to compile when using netlink on older systems. */
-# include <sys/socket.h>
# include <linux/netlink.h>
#if HAVE_LINUX_INET_DIAG_H
# include <linux/inet_diag.h>
#endif
-# include <sys/socket.h>
# include <arpa/inet.h>
/* #endif KERNEL_LINUX */
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NET_IF_H
# include <net/if.h>
#endif
/* This is for OpenBSD and NetBSD. */
#elif HAVE_LIBKVM_NLIST
# include <sys/queue.h>
-# include <sys/socket.h>
# include <net/route.h>
# include <netinet/in.h>
# include <netinet/in_systm.h>
diff --git a/src/teamspeak2.c b/src/teamspeak2.c
index 201e1828a2b2037093fde4b02c45709a53d6d062..56e8d14e968642d4f632542ac8f9047a3562bf0d 100644 (file)
--- a/src/teamspeak2.c
+++ b/src/teamspeak2.c
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
-#include <sys/socket.h>
#include <netdb.h>
/*
diff --git a/src/ted.c b/src/ted.c
index 5dd75bc924b7bdea84f6664d89e8c85c77f33139..e76b3c9234f70878bf465ada946d6605642fdc86 100644 (file)
--- a/src/ted.c
+++ b/src/ted.c
WARNING ("ted plugin: Received EOF from file descriptor.");
return (-1);
}
- else if (receive_buffer_length > sizeof (receive_buffer))
+ else if (((size_t) receive_buffer_length) > sizeof (receive_buffer))
{
ERROR ("ted plugin: read(2) returned invalid value %zi.",
receive_buffer_length);
diff --git a/src/testing.h b/src/testing.h
index 5df1b83a3e0f076b3a35bff53df09b021b9a0ea5..0c415e48909f96db0d8844e3f422cdd7325d86a1 100644 (file)
--- a/src/testing.h
+++ b/src/testing.h
/**
* collectd - src/tests/macros.h
- * Copyright (C) 2013 Florian octo Forster
+ * Copyright (C) 2013-2015 Florian octo Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* Florian octo Forster <octo at collectd.org>
*/
+#include <inttypes.h>
+
static int fail_count__ = 0;
static int check_count__ = 0;
+#ifndef DBL_PRECISION
+# define DBL_PRECISION 1e-12
+#endif
+
#define DEF_TEST(func) static int test_##func ()
#define RUN_TEST(func) do { \
#define OK1(cond, text) do { \
_Bool result = (cond); \
printf ("%s %i - %s\n", result ? "ok" : "not ok", ++check_count__, text); \
+ if (!result) { return -1; } \
} while (0)
#define OK(cond) OK1(cond, #cond)
-#define STREQ(expect, actual) do { \
+#define EXPECT_EQ_STR(expect, actual) do { \
if (strcmp (expect, actual) != 0) { \
- printf ("not ok %i - %s incorrect: expected \"%s\", got \"%s\"\n", \
- ++check_count__, #actual, expect, actual); \
+ printf ("not ok %i - %s = \"%s\", want \"%s\"\n", \
+ ++check_count__, #actual, actual, expect); \
+ return (-1); \
+ } \
+ printf ("ok %i - %s = \"%s\"\n", ++check_count__, #actual, actual); \
+} while (0)
+
+#define EXPECT_EQ_INT(expect, actual) do { \
+ int want__ = (int) expect; \
+ int got__ = (int) actual; \
+ if (got__ != want__) { \
+ printf ("not ok %i - %s = %d, want %d\n", \
+ ++check_count__, #actual, got__, want__); \
+ return (-1); \
+ } \
+ printf ("ok %i - %s = %d\n", ++check_count__, #actual, got__); \
+} while (0)
+
+#define EXPECT_EQ_UINT64(expect, actual) do { \
+ uint64_t want__ = (uint64_t) expect; \
+ uint64_t got__ = (uint64_t) actual; \
+ if (got__ != want__) { \
+ printf ("not ok %i - %s = %"PRIu64", want %"PRIu64"\n", \
+ ++check_count__, #actual, got__, want__); \
+ return (-1); \
+ } \
+ printf ("ok %i - %s = %"PRIu64"\n", ++check_count__, #actual, got__); \
+} while (0)
+
+#define EXPECT_EQ_DOUBLE(expect, actual) do { \
+ double want__ = (double) expect; \
+ double got__ = (double) actual; \
+ if (isnan (want__) && !isnan (got__)) { \
+ printf ("not ok %i - %s = %.15g, want %.15g\n", \
+ ++check_count__, #actual, got__, want__); \
+ return (-1); \
+ } else if (!isnan (want__) && (((want__-got__) < -DBL_PRECISION) || ((want__-got__) > DBL_PRECISION))) { \
+ printf ("not ok %i - %s = %.15g, want %.15g\n", \
+ ++check_count__, #actual, got__, want__); \
return (-1); \
} \
- printf ("ok %i - %s evaluates to \"%s\"\n", ++check_count__, #actual, expect); \
+ printf ("ok %i - %s = %.15g\n", ++check_count__, #actual, got__); \
} while (0)
#define CHECK_NOT_NULL(expr) do { \
diff --git a/src/threshold.c b/src/threshold.c
index 8dcb711d5e6004bb82d266b8d9e950242681c50d..38c7efb016d73a1d62bd10bb3efb0e5670caf1e1 100644 (file)
--- a/src/threshold.c
+++ b/src/threshold.c
{
gauge_t value;
gauge_t sum;
- int i;
+ size_t i;
sum = 0.0;
for (i = 0; i < vl->values_len; i++)
{ /* {{{ */
int ret = -1;
int ds_index = -1;
- int i;
+ size_t i;
gauge_t values_copy[ds->ds_num];
memcpy (values_copy, values, sizeof (values_copy));
diff --git a/src/types.db b/src/types.db
index c605f56d603ce5d680a8f7b7180c27ab6e647f53..5847218aa0fe1cb17a057e98bd596849cc7af4ce 100644 (file)
--- a/src/types.db
+++ b/src/types.db
cache_operation value:DERIVE:0:U
cache_ratio value:GAUGE:0:100
cache_result value:DERIVE:0:U
-cache_size value:GAUGE:0:U
+cache_size value:GAUGE:0:1125899906842623
capacity value:GAUGE:0:U
ceph_bytes value:GAUGE:U:U
ceph_latency value:GAUGE:U:U
diff --git a/src/unixsock.c b/src/unixsock.c
index 664c0184a5d21a793e1fc529dcbe6fbdddfbcde8..e6c75a65644e7441425183fb1b041c9bb93274c0 100644 (file)
--- a/src/unixsock.c
+++ b/src/unixsock.c
/* Folks without pthread will need to disable this plugin. */
#include <pthread.h>
-#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
diff --git a/src/utils_cmd_flush.c b/src/utils_cmd_flush.c
index f19835ef3e4e066e9488ecfc52de95f7392fab5b..8b34a75821def8e9a24bef04475ed0758bcbf09f 100644 (file)
--- a/src/utils_cmd_flush.c
+++ b/src/utils_cmd_flush.c
for (i = 0; (i == 0) || (i < plugins_num); i++)
{
char *plugin = NULL;
- int j;
+ size_t j;
if (plugins_num != 0)
plugin = plugins[i];
diff --git a/src/utils_cmd_getval.c b/src/utils_cmd_getval.c
index 196b45e3267eca52bc7950ebac6b181aaa837d65..8cbb9b21ce6978502c0d7e06ac1cb1e445e3e0fd 100644 (file)
--- a/src/utils_cmd_getval.c
+++ b/src/utils_cmd_getval.c
return (-1);
}
- if ((size_t) ds->ds_num != values_num)
+ if (ds->ds_num != values_num)
{
- ERROR ("ds[%s]->ds_num = %i, "
- "but uc_get_rate_by_name returned %u values.",
- ds->type, ds->ds_num, (unsigned int) values_num);
+ ERROR ("ds[%s]->ds_num = %zu, "
+ "but uc_get_rate_by_name returned %zu values.",
+ ds->type, ds->ds_num, values_num);
print_to_socket (fh, "-1 Error reading value from cache.\n");
sfree (values);
sfree (identifier_copy);
return (-1);
}
- print_to_socket (fh, "%u Value%s found\n", (unsigned int) values_num,
+ print_to_socket (fh, "%zu Value%s found\n", values_num,
(values_num == 1) ? "" : "s");
for (i = 0; i < values_num; i++)
{
diff --git a/src/utils_db_query.c b/src/utils_db_query.c
index 9c84937f38845c34e2f7067fab6317f7d052c3fe..d2b811721d0d6ef2d40453854f87fde4b3c8bf4b 100644 (file)
--- a/src/utils_db_query.c
+++ b/src/utils_db_query.c
BAIL_OUT (-1);
}
- if (((size_t) prep_area->ds->ds_num) != r->values_num)
+ if (prep_area->ds->ds_num != r->values_num)
{
ERROR ("db query utils: udb_result_prepare_result: The type `%s' "
- "requires exactly %i value%s, but the configuration specifies %zu.",
+ "requires exactly %zu value%s, but the configuration specifies %zu.",
r->type,
prep_area->ds->ds_num, (prep_area->ds->ds_num == 1) ? "" : "s",
r->values_num);
diff --git a/src/utils_dns.c b/src/utils_dns.c
index 6abfde16fba0f5cd2da6e1da4f98832717f48519..4c763a1420a04a4008d0d16ce4000e1da9f3aceb 100644 (file)
--- a/src/utils_dns.c
+++ b/src/utils_dns.c
#include "plugin.h"
#include "common.h"
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-
#if HAVE_NET_IF_ARP_H
# include <net/if_arp.h>
#endif
@@ -305,7 +301,7 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
if (ns <= 0)
return 4; /* probably compression loop */
do {
- if ((*off) >= sz)
+ if ((*off) >= ((off_t) sz))
break;
c = *(buf + (*off));
if (c > 191) {
@@ -317,11 +313,11 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
s = ntohs(s);
(*off) += sizeof(s);
/* Sanity check */
- if ((*off) >= sz)
+ if ((*off) >= ((off_t) sz))
return 1; /* message too short */
ptr = s & 0x3FFF;
/* Make sure the pointer is inside this message */
- if (ptr >= sz)
+ if (ptr >= ((off_t) sz))
return 2; /* bad compression ptr */
if (ptr < DNS_MSG_HDR_SZ)
return 2; /* bad compression ptr */
@@ -355,7 +351,7 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
if (no > 0)
*(name + no - 1) = '\0';
/* make sure we didn't allow someone to overflow the name buffer */
- assert(no <= ns);
+ assert(no <= ((off_t) ns));
return 0;
}
index 023f7a46a5240f7a7f52e3c9d6f237c91f932223..eb5b4b327119210c4f2c6424ae99c47b3ec1dc5a 100644 (file)
unsigned int flags)
{
int status = 0;
- int i;
+ size_t i;
int buffer_pos = 0;
gauge_t *rates = NULL;
index 10a5343f2c11bb0a1eba7454eb663a41eacd4a7a..122c7f86a73f6ddf16d04c0403581b74d9a4c03f 100644 (file)
--- a/src/utils_format_json.c
+++ b/src/utils_format_json.c
const data_set_t *ds, const value_list_t *vl, int store_rates)
{
size_t offset = 0;
- int i;
+ size_t i;
gauge_t *rates = NULL;
memset (buffer, 0, buffer_size);
const data_set_t *ds)
{
size_t offset = 0;
- int i;
+ size_t i;
memset (buffer, 0, buffer_size);
const data_set_t *ds)
{
size_t offset = 0;
- int i;
+ size_t i;
memset (buffer, 0, buffer_size);
diff --git a/src/utils_ignorelist.c b/src/utils_ignorelist.c
index 7b1c7d2547e915db1931eecdbeb9e34590e9e117..a8ca7dbb7f3aecbb2c6ea90519c2583aae0c30f5 100644 (file)
--- a/src/utils_ignorelist.c
+++ b/src/utils_ignorelist.c
@@ -89,69 +89,45 @@ static inline void ignorelist_append (ignorelist_t *il, ignorelist_item_t *item)
}
#if HAVE_REGEX_H
-static int ignorelist_append_regex(ignorelist_t *il, const char *entry)
+static int ignorelist_append_regex(ignorelist_t *il, const char *re_str)
{
- int rcompile;
- regex_t *regtemp;
- int errsize;
- char *regerr = NULL;
- ignorelist_item_t *new;
+ regex_t *re;
+ ignorelist_item_t *entry;
+ int status;
- /* create buffer */
- if ((regtemp = malloc(sizeof(regex_t))) == NULL)
+ re = malloc (sizeof (*re));
+ if (re == NULL)
{
- ERROR ("cannot allocate new config entry");
- return (1);
+ ERROR ("utils_ignorelist: malloc failed");
+ return (ENOMEM);
}
- memset (regtemp, '\0', sizeof(regex_t));
+ memset (re, 0, sizeof (*re));
- /* compile regex */
- if ((rcompile = regcomp (regtemp, entry, REG_EXTENDED)) != 0)
+ status = regcomp (re, re_str, REG_EXTENDED);
+ if (status != 0)
{
- /* prepare message buffer */
- errsize = regerror(rcompile, regtemp, NULL, 0);
- if (errsize)
- regerr = smalloc(errsize);
- /* get error message */
- if (regerror (rcompile, regtemp, regerr, errsize))
- {
- fprintf (stderr, "Cannot compile regex %s: %i/%s",
- entry, rcompile, regerr);
- ERROR ("Cannot compile regex %s: %i/%s",
- entry, rcompile, regerr);
- }
- else
- {
- fprintf (stderr, "Cannot compile regex %s: %i",
- entry, rcompile);
- ERROR ("Cannot compile regex %s: %i",
- entry, rcompile);
- }
-
- if (errsize)
- sfree (regerr);
- regfree (regtemp);
- sfree (regtemp);
- return (1);
+ char errbuf[1024] = "";
+ regerror (status, re, errbuf, sizeof (errbuf));
+ ERROR ("utils_ignorelist: regcomp failed: %s", errbuf);
+ regfree (re);
+ sfree (re);
+ return (status);
}
- DEBUG("regex compiled: %s - %i", entry, rcompile);
- /* create new entry */
- if ((new = malloc(sizeof(ignorelist_item_t))) == NULL)
+ entry = malloc (sizeof (*entry));
+ if (entry == NULL)
{
- ERROR ("cannot allocate new config entry");
- regfree (regtemp);
- sfree (regtemp);
- return (1);
+ ERROR ("utils_ignorelist: malloc failed");
+ regfree (re);
+ sfree (re);
+ return (ENOMEM);
}
- memset (new, '\0', sizeof(ignorelist_item_t));
- new->rmatch = regtemp;
-
- /* append new entry */
- ignorelist_append (il, new);
+ memset (entry, 0, sizeof (*entry));
+ entry->rmatch = re;
+ ignorelist_append (il, entry);
return (0);
-} /* int ignorelist_append_regex(ignorelist_t *il, const char *entry) */
+} /* int ignorelist_append_regex */
#endif
static int ignorelist_append_string(ignorelist_t *il, const char *entry)
/*
* append entry into ignorelist_t
- * return 1 for success
+ * return 0 for success
*/
int ignorelist_add (ignorelist_t *il, const char *entry)
{
- int ret;
size_t entry_len;
if (il == NULL)
{
char *entry_copy;
size_t entry_copy_size;
+ int status;
/* We need to copy `entry' since it's const */
entry_copy_size = entry_len - 1;
entry_copy = smalloc (entry_copy_size);
sstrncpy (entry_copy, entry + 1, entry_copy_size);
- DEBUG("I'm about to add regex entry: %s", entry_copy);
- ret = ignorelist_append_regex(il, entry_copy);
+ status = ignorelist_append_regex(il, entry_copy);
sfree (entry_copy);
+ return status;
}
- else
#endif
- {
- DEBUG("to add entry: %s", entry);
- ret = ignorelist_append_string(il, entry);
- }
- return (ret);
+ return ignorelist_append_string(il, entry);
} /* int ignorelist_add (ignorelist_t *il, const char *entry) */
/*
diff --git a/src/utils_latency_test.c b/src/utils_latency_test.c
--- /dev/null
+++ b/src/utils_latency_test.c
@@ -0,0 +1,108 @@
+/**
+ * collectd - src/utils_latency_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#define DBL_PRECISION 1e-9
+
+#include "testing.h"
+#include "collectd.h"
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "utils_time.h"
+#include "utils_latency.h"
+
+DEF_TEST(simple)
+{
+ struct {
+ double val;
+ double min;
+ double max;
+ double sum;
+ double avg;
+ } cases[] = {
+ /* val min max sum avg */
+ {0.5, 0.5, 0.5, 0.5, 0.5},
+ {0.3, 0.3, 0.5, 0.8, 0.4},
+ {0.7, 0.3, 0.7, 1.5, 0.5},
+ {2.5, 0.3, 2.5, 4.0, 1.0},
+ { 99, 0.3, 99, 103, 20.6},
+ /* { -1, 0.3, 99, 103, 20.6}, see issue #1139 */
+ };
+ size_t i;
+ latency_counter_t *l;
+
+ CHECK_NOT_NULL (l = latency_counter_create ());
+
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ printf ("# case %zu: DOUBLE_TO_CDTIME_T(%g) = %"PRIu64"\n",
+ i, cases[i].val, DOUBLE_TO_CDTIME_T (cases[i].val));
+ latency_counter_add (l, DOUBLE_TO_CDTIME_T (cases[i].val));
+
+ EXPECT_EQ_DOUBLE (cases[i].min, CDTIME_T_TO_DOUBLE (latency_counter_get_min (l)));
+ EXPECT_EQ_DOUBLE (cases[i].max, CDTIME_T_TO_DOUBLE (latency_counter_get_max (l)));
+ EXPECT_EQ_DOUBLE (cases[i].sum, CDTIME_T_TO_DOUBLE (latency_counter_get_sum (l)));
+ EXPECT_EQ_DOUBLE (cases[i].avg, CDTIME_T_TO_DOUBLE (latency_counter_get_average (l)));
+ }
+
+ latency_counter_destroy (l);
+ return 0;
+}
+
+DEF_TEST(percentile)
+{
+ size_t i;
+ latency_counter_t *l;
+
+ CHECK_NOT_NULL (l = latency_counter_create ());
+
+ for (i = 0; i < 100; i++) {
+ latency_counter_add (l, TIME_T_TO_CDTIME_T (((time_t) i) + 1));
+ }
+
+ EXPECT_EQ_DOUBLE ( 1.0, CDTIME_T_TO_DOUBLE (latency_counter_get_min (l)));
+ EXPECT_EQ_DOUBLE (100.0, CDTIME_T_TO_DOUBLE (latency_counter_get_max (l)));
+ EXPECT_EQ_DOUBLE (100.0 * 101.0 / 2.0, CDTIME_T_TO_DOUBLE (latency_counter_get_sum (l)));
+ EXPECT_EQ_DOUBLE ( 50.5, CDTIME_T_TO_DOUBLE (latency_counter_get_average (l)));
+
+ EXPECT_EQ_DOUBLE (50.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 50.0)));
+ EXPECT_EQ_DOUBLE (80.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 80.0)));
+ EXPECT_EQ_DOUBLE (95.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 95.0)));
+ EXPECT_EQ_DOUBLE (99.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 99.0)));
+
+ CHECK_ZERO (latency_counter_get_percentile (l, -1.0));
+ CHECK_ZERO (latency_counter_get_percentile (l, 101.0));
+
+ latency_counter_destroy (l);
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(simple);
+ RUN_TEST(percentile);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/utils_mount_test.c b/src/utils_mount_test.c
index c5ffbfbcf9fb9d701db96f02aafa1cc9873b4790..b4cb43219a0e63b1ff8200ee79c3e2953704ca9c 100644 (file)
--- a/src/utils_mount_test.c
+++ b/src/utils_mount_test.c
#include "collectd.h"
#include "utils_mount.h"
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc;
+#endif /* HAVE_LIBKSTAT */
+
DEF_TEST(cu_mount_checkoption)
{
char line_opts[] = "foo=one,bar=two,qux=three";
char line_opts[] = "foo=one,bar=two,qux=three";
char line_bool[] = "one,two,three";
- STREQ ("one", cu_mount_getoptionvalue (line_opts, "foo="));
- STREQ ("two", cu_mount_getoptionvalue (line_opts, "bar="));
- STREQ ("three", cu_mount_getoptionvalue (line_opts, "qux="));
+ EXPECT_EQ_STR ("one", cu_mount_getoptionvalue (line_opts, "foo="));
+ EXPECT_EQ_STR ("two", cu_mount_getoptionvalue (line_opts, "bar="));
+ EXPECT_EQ_STR ("three", cu_mount_getoptionvalue (line_opts, "qux="));
OK (NULL == cu_mount_getoptionvalue (line_opts, "unknown="));
- STREQ ("", cu_mount_getoptionvalue (line_bool, "one"));
- STREQ ("", cu_mount_getoptionvalue (line_bool, "two"));
- STREQ ("", cu_mount_getoptionvalue (line_bool, "three"));
+ EXPECT_EQ_STR ("", cu_mount_getoptionvalue (line_bool, "one"));
+ EXPECT_EQ_STR ("", cu_mount_getoptionvalue (line_bool, "two"));
+ EXPECT_EQ_STR ("", cu_mount_getoptionvalue (line_bool, "three"));
OK (NULL == cu_mount_getoptionvalue (line_bool, "four"));
return (0);
diff --git a/src/utils_rrdcreate.c b/src/utils_rrdcreate.c
index 5add32373cd3d91f861265df88dc459d4bb57c99..39f42b205a2c5e22510445dfcea84c107ed29748 100644 (file)
--- a/src/utils_rrdcreate.c
+++ b/src/utils_rrdcreate.c
const rrdcreate_config_t *cfg)
{
char **ds_def;
- int ds_num;
+ size_t ds_num;
char min[32];
char max[32];
diff --git a/src/utils_vl_lookup.c b/src/utils_vl_lookup.c
index f0f0b4632ecafda01572e7d3252e25fc77c5136d..f85910e1737e7b5d1c328a6e9e15896be2d60d99 100644 (file)
--- a/src/utils_vl_lookup.c
+++ b/src/utils_vl_lookup.c
#include "utils_vl_lookup.h"
#include "utils_avltree.h"
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc;
+#endif /* HAVE_LIBKSTAT */
+
#if BUILD_TEST
# define sstrncpy strncpy
# define plugin_log(s, ...) do { \
index 6a2676a89e1d8ccee1cddc6735d2f5e7d9335ff7..41cc0a41af3a26c2ac7841178ca88289cd284f01 100644 (file)
identifier_t *class = user_class;
identifier_t *obj;
- OK(expect_new_obj);
+ assert (expect_new_obj);
memcpy (&last_class_ident, class, sizeof (last_class_ident));
return ((void *) obj);
}
-static void checked_lookup_add (lookup_t *obj, /* {{{ */
+static int checked_lookup_add (lookup_t *obj, /* {{{ */
char const *host,
char const *plugin, char const *plugin_instance,
char const *type, char const *type_instance,
memmove (user_class, &ident, sizeof (ident));
OK(lookup_add (obj, &ident, group_by, user_class) == 0);
-} /* }}} void test_add */
+ return 0;
+} /* }}} int checked_lookup_add */
static int checked_lookup_search (lookup_t *obj,
char const *host,
return (status);
}
-static lookup_t *checked_lookup_create (void)
-{
- lookup_t *obj = lookup_create (
- lookup_class_callback,
- lookup_obj_callback,
- (void *) free,
- (void *) free);
- OK(obj != NULL);
- return (obj);
-}
-
DEF_TEST(group_by_specific_host)
{
- lookup_t *obj = checked_lookup_create ();
+ lookup_t *obj;
+ CHECK_NOT_NULL (obj = lookup_create (
+ lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
checked_lookup_add (obj, "/.*/", "test", "", "test", "/.*/", LU_GROUP_BY_HOST);
checked_lookup_search (obj, "host0", "test", "", "test", "0",
DEF_TEST(group_by_any_host)
{
- lookup_t *obj = checked_lookup_create ();
+ lookup_t *obj;
+ CHECK_NOT_NULL (obj = lookup_create (
+ lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
checked_lookup_add (obj, "/.*/", "/.*/", "/.*/", "test", "/.*/", LU_GROUP_BY_HOST);
checked_lookup_search (obj, "host0", "plugin0", "", "test", "0",
DEF_TEST(multiple_lookups)
{
- lookup_t *obj = checked_lookup_create ();
+ lookup_t *obj;
int status;
+ CHECK_NOT_NULL (obj = lookup_create (
+ lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
+
checked_lookup_add (obj, "/.*/", "plugin0", "", "test", "/.*/", LU_GROUP_BY_HOST);
checked_lookup_add (obj, "/.*/", "/.*/", "", "test", "ti0", LU_GROUP_BY_HOST);
DEF_TEST(regex)
{
- lookup_t *obj = checked_lookup_create ();
+ lookup_t *obj;
+ CHECK_NOT_NULL (obj = lookup_create (
+ lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
checked_lookup_add (obj, "/^db[0-9]\\./", "cpu", "/.*/", "cpu", "/.*/",
LU_GROUP_BY_TYPE_INSTANCE);
diff --git a/src/varnish.c b/src/varnish.c
index 1089222327ac8a61f540f4a27d333ed1455c6a66..c6c4df05d413b97fe2ee1de80d81b3c42f29e2e1 100644 (file)
--- a/src/varnish.c
+++ b/src/varnish.c
plugin_register_complex_read (/* group = */ "varnish",
/* name = */ "varnish/localhost",
/* callback = */ varnish_read,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user data = */ &ud);
return (0);
plugin_register_complex_read (/* group = */ "varnish",
/* name = */ callback_name,
/* callback = */ varnish_read,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user data = */ &ud);
have_instance = 1;
diff --git a/src/virt.c b/src/virt.c
index 663555b9bd33a2375d717482987041824a3f5c76..6824b134aeed727de314b5006fee3f14477ae6f5 100644 (file)
--- a/src/virt.c
+++ b/src/virt.c
};
static enum plginst_field plugin_instance_format[PLGINST_MAX_FIELDS] =
- { plginst_name };
+ { plginst_none };
/* InterfaceFormat. */
enum if_field {
}
for (i = 0; i < n; ++i) {
- if (strcasecmp (fields[i], "name") == 0)
+ if (strcasecmp (fields[i], "none") == 0) {
+ plugin_instance_format[i] = plginst_none;
+ break;
+ } else if (strcasecmp (fields[i], "name") == 0)
plugin_instance_format[i] = plginst_name;
else if (strcasecmp (fields[i], "uuid") == 0)
plugin_instance_format[i] = plginst_uuid;
diff --git a/src/write_graphite.c b/src/write_graphite.c
index 41451a8cee8f8d0bab4dda5d81361b3efd30a229..7fc9eb9f90921d1c1887295fd912dfd659b01b32 100644 (file)
--- a/src/write_graphite.c
+++ b/src/write_graphite.c
/* Folks without pthread will need to disable this plugin. */
#include <pthread.h>
-#include <sys/socket.h>
#include <netdb.h>
-#ifndef WG_DEFAULT_NODE
-# define WG_DEFAULT_NODE "localhost"
-#endif
-
-#ifndef WG_DEFAULT_SERVICE
-# define WG_DEFAULT_SERVICE "2003"
-#endif
-
-#ifndef WG_DEFAULT_PROTOCOL
-# define WG_DEFAULT_PROTOCOL "tcp"
-#endif
-
-#ifndef WG_DEFAULT_LOG_SEND_ERRORS
-# define WG_DEFAULT_LOG_SEND_ERRORS 1
-#endif
-
-#ifndef WG_DEFAULT_ESCAPE
-# define WG_DEFAULT_ESCAPE '_'
-#endif
+#define WG_DEFAULT_NODE "localhost"
+#define WG_DEFAULT_SERVICE "2003"
+#define WG_DEFAULT_PROTOCOL "tcp"
+#define WG_DEFAULT_LOG_SEND_ERRORS 1
+#define WG_DEFAULT_ESCAPE '_'
/* Ethernet - (IPv6 + TCP) = 1500 - (40 + 32) = 1428 */
-#ifndef WG_SEND_BUF_SIZE
-# define WG_SEND_BUF_SIZE 1428
-#endif
+#define WG_SEND_BUF_SIZE 1428
-#ifndef WG_MIN_RECONNECT_INTERVAL
-# define WG_MIN_RECONNECT_INTERVAL TIME_T_TO_CDTIME_T (1)
-#endif
+#define WG_MIN_RECONNECT_INTERVAL TIME_T_TO_CDTIME_T (1)
/*
* Private variables
status = swrite (cb->sock_fd, cb->send_buf, strlen (cb->send_buf));
if (status < 0)
{
- const char *protocol = cb->protocol ? cb->protocol : WG_DEFAULT_PROTOCOL;
-
if (cb->log_send_errors)
{
char errbuf[1024];
ERROR ("write_graphite plugin: send to %s:%s (%s) failed with status %zi (%s)",
- cb->node, cb->service, protocol,
+ cb->node, cb->service, cb->protocol,
status, sstrerror (errno, errbuf, sizeof (errbuf)));
}
cdtime_t now;
int status;
- const char *node = cb->node ? cb->node : WG_DEFAULT_NODE;
- const char *service = cb->service ? cb->service : WG_DEFAULT_SERVICE;
- const char *protocol = cb->protocol ? cb->protocol : WG_DEFAULT_PROTOCOL;
-
char connerr[1024] = "";
if (cb->sock_fd > 0)
#endif
ai_hints.ai_family = AF_UNSPEC;
- if (0 == strcasecmp ("tcp", protocol))
+ if (0 == strcasecmp ("tcp", cb->protocol))
ai_hints.ai_socktype = SOCK_STREAM;
else
ai_hints.ai_socktype = SOCK_DGRAM;
ai_list = NULL;
- status = getaddrinfo (node, service, &ai_hints, &ai_list);
+ status = getaddrinfo (cb->node, cb->service, &ai_hints, &ai_list);
if (status != 0)
{
ERROR ("write_graphite plugin: getaddrinfo (%s, %s, %s) failed: %s",
- node, service, protocol, gai_strerror (status));
+ cb->node, cb->service, cb->protocol, gai_strerror (status));
return (-1);
}
sstrerror (errno, connerr, sizeof (connerr));
c_complain (LOG_ERR, &cb->init_complaint,
"write_graphite plugin: Connecting to %s:%s via %s failed. "
- "The last error was: %s", node, service, protocol, connerr);
+ "The last error was: %s", cb->node, cb->service, cb->protocol, connerr);
return (-1);
}
else
{
c_release (LOG_INFO, &cb->init_complaint,
"write_graphite plugin: Successfully connected to %s:%s via %s.",
- node, service, protocol);
+ cb->node, cb->service, cb->protocol);
}
wg_reset_buffer (cb);
cb->send_buf_free -= message_len;
DEBUG ("write_graphite plugin: [%s]:%s (%s) buf %zu/%zu (%.1f %%) \"%s\"",
- cb->node,
- cb->service,
- cb->protocol,
+ cb->node, cb->service, cb->protocol,
cb->send_buf_fill, sizeof (cb->send_buf),
100.0 * ((double) cb->send_buf_fill) / ((double) sizeof (cb->send_buf)),
message);
memset (cb, 0, sizeof (*cb));
cb->sock_fd = -1;
cb->name = NULL;
- cb->node = NULL;
- cb->service = NULL;
- cb->protocol = NULL;
+ cb->node = strdup (WG_DEFAULT_NODE);
+ cb->service = strdup (WG_DEFAULT_SERVICE);
+ cb->protocol = strdup (WG_DEFAULT_PROTOCOL);
cb->log_send_errors = WG_DEFAULT_LOG_SEND_ERRORS;
cb->prefix = NULL;
cb->postfix = NULL;
/* FIXME: Legacy configuration syntax. */
if (cb->name == NULL)
ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s/%s/%s",
- cb->node != NULL ? cb->node : WG_DEFAULT_NODE,
- cb->service != NULL ? cb->service : WG_DEFAULT_SERVICE,
- cb->protocol != NULL ? cb->protocol : WG_DEFAULT_PROTOCOL);
+ cb->node, cb->service, cb->protocol);
else
ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s",
cb->name);
diff --git a/src/write_http.c b/src/write_http.c
index ed596bbf56b9e9ee88becd425126951a4591fb91..868bca84395ac23fe0e672b179f882ec3f488c53 100644 (file)
--- a/src/write_http.c
+++ b/src/write_http.c
char *clientkeypass;
long sslversion;
_Bool store_rates;
+ _Bool log_http_error;
int low_speed_limit;
time_t low_speed_time;
int timeout;
};
typedef struct wh_callback_s wh_callback_t;
+static void wh_log_http_error (wh_callback_t *cb)
+{
+ if (!cb->log_http_error)
+ return;
+
+ long http_code = 0;
+
+ curl_easy_getinfo (cb->curl, CURLINFO_RESPONSE_CODE, &http_code);
+
+ if (http_code != 200)
+ INFO ("write_http plugin: HTTP Error code: %lu", http_code);
+}
+
static void wh_reset_buffer (wh_callback_t *cb) /* {{{ */
{
memset (cb->send_buffer, 0, cb->send_buffer_size);
curl_easy_setopt (cb->curl, CURLOPT_POSTFIELDS, cb->send_buffer);
status = curl_easy_perform (cb->curl);
+
+ wh_log_http_error (cb);
+
if (status != CURLE_OK)
{
ERROR ("write_http plugin: curl_easy_perform failed with "
cb->sslversion = CURL_SSLVERSION_DEFAULT;
cb->low_speed_limit = 0;
cb->timeout = 0;
+ cb->log_http_error = 0;
pthread_mutex_init (&cb->send_lock, /* attr = */ NULL);
cf_util_get_int (child, &cb->low_speed_limit);
else if (strcasecmp ("Timeout", child->key) == 0)
cf_util_get_int (child, &cb->timeout);
+ else if (strcasecmp ("LogHttpError", child->key) == 0)
+ cf_util_get_boolean (child, &cb->log_http_error);
else
{
ERROR ("write_http plugin: Invalid configuration "
diff --git a/src/write_log.c b/src/write_log.c
index e37aae9fd594fcce3ecd6d5abac7a6fb33adf32c..ebf0e12445cc9e9e3900a8416c3cedcf6db1a9eb 100644 (file)
--- a/src/write_log.c
+++ b/src/write_log.c
/* Folks without pthread will need to disable this plugin. */
#include <pthread.h>
-#include <sys/socket.h>
#include <netdb.h>
#define WL_BUF_SIZE 8192
diff --git a/src/write_redis.c b/src/write_redis.c
index da5b7bbe8ba1ffa84ddae9ab8e2fc5325c7a69ad..1eb082fb331cfcb9496658c8e98ef4fb8e5297b4 100644 (file)
--- a/src/write_redis.c
+++ b/src/write_redis.c
/**
* collectd - src/write_redis.c
- * Copyright (C) 2010 Florian Forster
+ * Copyright (C) 2010-2015 Florian Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
#include <sys/time.h>
#include <hiredis/hiredis.h>
+#ifndef REDIS_DEFAULT_PREFIX
+# define REDIS_DEFAULT_PREFIX "collectd/"
+#endif
+
struct wr_node_s
{
char name[DATA_MAX_NAME_LEN];
char *host;
int port;
struct timeval timeout;
+ char *prefix;
+ int database;
+ int max_set_size;
+ _Bool store_rates;
redisContext *conn;
pthread_mutex_t lock;
status = FORMAT_VL (ident, sizeof (ident), vl);
if (status != 0)
return (status);
- ssnprintf (key, sizeof (key), "collectd/%s", ident);
+ ssnprintf (key, sizeof (key), "%s%s",
+ (node->prefix != NULL) ? node->prefix : REDIS_DEFAULT_PREFIX,
+ ident);
ssnprintf (time, sizeof (time), "%.9f", CDTIME_T_TO_DOUBLE(vl->time));
memset (value, 0, sizeof (value));
value_size = sizeof (value);
value_ptr = &value[0];
- status = format_values (value_ptr, value_size, ds, vl, /* store rates = */ 0);
+ status = format_values (value_ptr, value_size, ds, vl, node->store_rates);
pthread_mutex_lock (&node->lock);
if (status != 0)
return (status);
pthread_mutex_unlock (&node->lock);
return (-1);
}
+
+ rr = redisCommand(node->conn, "SELECT %d", node->database);
+ if (rr == NULL)
+ WARNING("SELECT command error. database:%d message:%s", node->database, node->conn->errstr);
+ else
+ freeReplyObject (rr);
}
rr = redisCommand (node->conn, "ZADD %s %s %s", key, time, value);
else
freeReplyObject (rr);
+ if (node->max_set_size >= 0)
+ {
+ rr = redisCommand (node->conn, "ZREMRANGEBYRANK %s %d %d", key, 0, (-1 * node->max_set_size) - 1);
+ if (rr == NULL)
+ WARNING("ZREMRANGEBYRANK command error. key:%s message:%s", key, node->conn->errstr);
+ else
+ freeReplyObject (rr);
+ }
+
/* TODO(octo): This is more overhead than necessary. Use the cache and
* metadata to determine if it is a new metric and call SADD only once for
* each metric. */
- rr = redisCommand (node->conn, "SADD collectd/values %s", ident);
+ rr = redisCommand (node->conn, "SADD %svalues %s",
+ (node->prefix != NULL) ? node->prefix : REDIS_DEFAULT_PREFIX,
+ ident);
if (rr==NULL)
WARNING("SADD command error. ident:%s message:%s", ident, node->conn->errstr);
else
node->timeout.tv_sec = 0;
node->timeout.tv_usec = 1000;
node->conn = NULL;
+ node->prefix = NULL;
+ node->database = 0;
+ node->max_set_size = -1;
+ node->store_rates = 1;
pthread_mutex_init (&node->lock, /* attr = */ NULL);
status = cf_util_get_string_buffer (ci, node->name, sizeof (node->name));
status = cf_util_get_int (child, &timeout);
if (status == 0) node->timeout.tv_usec = timeout;
}
+ else if (strcasecmp ("Prefix", child->key) == 0) {
+ status = cf_util_get_string (child, &node->prefix);
+ }
+ else if (strcasecmp ("Database", child->key) == 0) {
+ status = cf_util_get_int (child, &node->database);
+ }
+ else if (strcasecmp ("MaxSetSize", child->key) == 0) {
+ status = cf_util_get_int (child, &node->max_set_size);
+ }
+ else if (strcasecmp ("StoreRates", child->key) == 0) {
+ status = cf_util_get_boolean (child, &node->store_rates);
+ }
else
WARNING ("write_redis plugin: Ignoring unknown config option \"%s\".",
child->key);
diff --git a/src/write_riemann.c b/src/write_riemann.c
index a09c72361f910ac8615a219fd9187da36e77a819..73d202c42fe8f228aaea46279dd12827a16d0371 100644 (file)
--- a/src/write_riemann.c
+++ b/src/write_riemann.c
#include "utils_cache.h"
#include "riemann.pb-c.h"
-#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
@@ -365,7 +364,7 @@ static Msg *riemann_notification_to_protobuf(struct riemann_host *host, /* {{{ *
char service_buffer[6 * DATA_MAX_NAME_LEN];
char const *severity;
notification_meta_t *meta;
- int i;
+ size_t i;
msg = malloc (sizeof (*msg));
if (msg == NULL)
char name_buffer[5 * DATA_MAX_NAME_LEN];
char service_buffer[6 * DATA_MAX_NAME_LEN];
double ttl;
- int i;
+ size_t i;
event = malloc (sizeof (*event));
if (event == NULL)
msg__init (msg);
/* Set up events. First, the list of pointers. */
- msg->n_events = (size_t) vl->values_len;
+ msg->n_events = vl->values_len;
msg->events = calloc (msg->n_events, sizeof (*msg->events));
if (msg->events == NULL)
{
len = msg__get_packed_size(host->batch_msg);
ret = 0;
- if (len >= host->batch_max) {
- ret = riemann_batch_flush_nolock(0, host);
+ if ((host->batch_max < 0) || (((size_t) host->batch_max) <= len)) {
+ ret = riemann_batch_flush_nolock(0, host);
}
pthread_mutex_unlock(&host->lock);
@@ -778,35 +777,35 @@ static int riemann_notification(const notification_t *n, user_data_t *ud) /* {{{
} /* }}} int riemann_notification */
static int riemann_write(const data_set_t *ds, /* {{{ */
- const value_list_t *vl,
- user_data_t *ud)
+ const value_list_t *vl,
+ user_data_t *ud)
{
int status = 0;
int statuses[vl->values_len];
struct riemann_host *host = ud->data;
- Msg *msg;
-
- if (host->check_thresholds)
- write_riemann_threshold_check(ds, vl, statuses);
-
- if (host->use_tcp == 1 && host->batch_mode) {
-
- riemann_batch_add_value_list (host, ds, vl, statuses);
+ if (host->check_thresholds) {
+ status = write_riemann_threshold_check(ds, vl, statuses);
+ if (status != 0)
+ return status;
+ } else {
+ memset (statuses, 0, sizeof (statuses));
+ }
- } else {
+ if (host->use_tcp == 1 && host->batch_mode) {
+ riemann_batch_add_value_list (host, ds, vl, statuses);
+ } else {
+ Msg *msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
+ if (msg == NULL)
+ return (-1);
- msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
- if (msg == NULL)
- return (-1);
+ status = riemann_send (host, msg);
+ if (status != 0)
+ ERROR ("write_riemann plugin: riemann_send failed with status %i", status);
- status = riemann_send (host, msg);
- if (status != 0)
- ERROR ("write_riemann plugin: riemann_send failed with status %i",
- status);
+ riemann_msg_protobuf_free (msg);
+ }
- riemann_msg_protobuf_free (msg);
- }
return status;
} /* }}} int riemann_write */
index 6d5af032565b909f8448811cc0aa8dc6167265d9..5c8559eb7b157414cd86df73a07ae25ab4e6927b 100644 (file)
int *statuses)
{ /* {{{ */
int ret = -1;
- int i;
+ size_t i;
int status;
gauge_t values_copy[ds->ds_num];
@@ -202,7 +202,9 @@ int write_riemann_threshold_check (const data_set_t *ds, const value_list_t *vl,
gauge_t *values;
int status;
+ assert (vl->values_len > 0);
memset(statuses, 0, vl->values_len * sizeof(*statuses));
+
if (threshold_tree == NULL)
return 0;
diff --git a/src/write_sensu.c b/src/write_sensu.c
index f7803e86a24cf1194dd7ee2d1651b1a4d8628694..67c04969227302c4f7f81dc0bafa2016587bd32a 100644 (file)
--- a/src/write_sensu.c
+++ b/src/write_sensu.c
#include "common.h"
#include "configfile.h"
#include "utils_cache.h"
-#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
{
char name_buffer[5 * DATA_MAX_NAME_LEN];
char service_buffer[6 * DATA_MAX_NAME_LEN];
- int i;
+ size_t i;
char *ret_str;
char *temp_str;
char *value_str;
char *ret_str;
char *temp_str;
int status;
- int i;
+ size_t i;
int res;
// add the severity/status
switch (n->severity) {
int statuses[vl->values_len];
struct sensu_host *host = ud->data;
gauge_t *rates = NULL;
- int i;
+ size_t i;
char *msg;
pthread_mutex_lock(&host->lock);
return -1;
}
}
- for (i = 0; i < (size_t) vl->values_len; i++) {
+ for (i = 0; i < vl->values_len; i++) {
msg = sensu_value_to_json(host, ds, vl, (int) i, rates, statuses[i]);
if (msg == NULL) {
sfree(rates);
diff --git a/src/write_tsdb.c b/src/write_tsdb.c
index 27ea4738051c9d6f6192b5cb76149816a5831c8a..4a626144f60498c2cd3a83fafba728c8b82b9b1b 100644 (file)
--- a/src/write_tsdb.c
+++ b/src/write_tsdb.c
#include "utils_cache.h"
#include <pthread.h>
-#include <sys/socket.h>
#include <netdb.h>
#ifndef WT_DEFAULT_NODE
const char* host, meta_data_t *md)
{
int status;
- int message_len;
+ size_t message_len;
char *temp = NULL;
char *tags = "";
char message[1024];
}
}
- message_len = ssnprintf (message,
+ status = ssnprintf (message,
sizeof(message),
"put %s %.0f %s fqdn=%s %s %s\r\n",
key,
host,
tags,
host_tags);
-
sfree(temp);
+ if (status < 0)
+ return -1;
+ message_len = (size_t) status;
if (message_len >= sizeof(message)) {
ERROR("write_tsdb plugin: message buffer too small: "
- "Need %d bytes.", message_len + 1);
+ "Need %zu bytes.", message_len + 1);
return -1;
}
char key[10*DATA_MAX_NAME_LEN];
char values[512];
- int status, i;
+ int status;
+ size_t i;
if (0 != strcmp(ds->type, vl->type))
{
diff --git a/src/zfs_arc.c b/src/zfs_arc.c
index f0d23239a82ab158c03c669f9a96cf2fc7f8dd24..dd633d5f2287352969f1619f553c105eccd7eade 100644 (file)
--- a/src/zfs_arc.c
+++ b/src/zfs_arc.c
/* Sizes */
za_read_gauge (ksp, "size", "cache_size", "arc");
+ za_read_gauge (ksp, "c", "cache_size", "c");
+ za_read_gauge (ksp, "c_min", "cache_size", "c_min");
+ za_read_gauge (ksp, "c_max", "cache_size", "c_max");
/* The "l2_size" value has disappeared from Solaris some time in
* early 2013, and has only reappeared recently in Solaris 11.2.
diff --git a/src/zone.c b/src/zone.c
--- /dev/null
+++ b/src/zone.c
@@ -0,0 +1,214 @@
+/**
+ * collectd - src/zone.c
+ * Copyright (C) 2011 Mathijs Mohlmann
+ *
+ * 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:
+ * Mathijs Mohlmann
+ * Dagobert Michelsen (forward-porting)
+ **/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+# undef HAVE_CONFIG_H
+#endif
+/* avoid procfs.h error "Cannot use procfs in the large file compilation environment" */
+#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
+# undef _FILE_OFFSET_BITS
+# undef _LARGEFILE64_SOURCE
+#endif
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <sys/types.h>
+#include <sys/vm_usage.h>
+#include <procfs.h>
+#include <zone.h>
+
+#include "utils_avltree.h"
+
+#define MAX_PROCFS_PATH 40
+#define FRC2PCT(pp)(((float)(pp))/0x8000*100)
+
+typedef struct zone_stats {
+ ushort_t pctcpu;
+ ushort_t pctmem;
+} zone_stats_t;
+
+static long pagesize;
+
+static int zone_init (void)
+{
+ pagesize = sysconf(_SC_PAGESIZE);
+ return (0);
+}
+
+static int
+zone_compare(const zoneid_t *a, const zoneid_t *b)
+{
+ if (*a == *b)
+ return(0);
+ if (*a < *b)
+ return(-1);
+ return(1);
+}
+
+static int
+zone_read_procfile(char const *pidstr, char const *name, void *buf, size_t bufsize)
+{
+ int fd;
+
+ char procfile[MAX_PROCFS_PATH];
+ (void)snprintf(procfile, sizeof(procfile), "/proc/%s/%s", pidstr, name);
+ if ((fd = open(procfile, O_RDONLY)) == -1) {
+ return (1);
+ }
+
+ if (sread(fd, buf, bufsize) != 0) {
+ char errbuf[1024];
+ ERROR ("zone plugin: Reading \"%s\" failed: %s", procfile,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ close(fd);
+ return (1);
+ }
+
+ close(fd);
+ return (0);
+}
+
+static int
+zone_submit_value(char *zone, gauge_t value)
+{
+ value_list_t vl = VALUE_LIST_INIT;
+ value_t values[1];
+
+ values[0].gauge = value;
+
+ vl.values = values;
+ vl.values_len = 1; /*STATIC_ARRAY_SIZE (values);*/
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "zone", sizeof (vl.plugin));
+ sstrncpy (vl.type, "percent", sizeof (vl.type));
+ sstrncpy (vl.type_instance, zone, sizeof (vl.type_instance));
+
+ return(plugin_dispatch_values (&vl));
+}
+
+static zone_stats_t *
+zone_find_stats(c_avl_tree_t *tree, zoneid_t zoneid)
+{
+ zone_stats_t *ret = NULL;
+ zoneid_t *key = NULL;
+
+ if (c_avl_get(tree, (void **)&zoneid, (void **)&ret)) {
+ if (!(ret = malloc(sizeof(zone_stats_t)))) {
+ WARNING("zone plugin: no memory");
+ return(NULL);
+ }
+ if (!(key = malloc(sizeof(zoneid_t)))) {
+ WARNING("zone plugin: no memory");
+ return(NULL);
+ }
+ *key = zoneid;
+ if (c_avl_insert(tree, key, ret)) {
+ WARNING("zone plugin: error inserting into tree");
+ return(NULL);
+ }
+ }
+ return(ret);
+}
+
+static void
+zone_submit_values(c_avl_tree_t *tree)
+{
+ char zonename[ZONENAME_MAX];
+ zoneid_t *zoneid = NULL;
+ zone_stats_t *stats = NULL;
+
+ while (c_avl_pick (tree, (void **)&zoneid, (void **)&stats) == 0)
+ {
+ if (getzonenamebyid(*zoneid, zonename, sizeof( zonename )) == -1) {
+ WARNING("zone plugin: error retreiving zonename");
+ } else {
+ zone_submit_value(zonename, (gauge_t)FRC2PCT(stats->pctcpu));
+ }
+ free(stats);
+ free(zoneid);
+ }
+ c_avl_destroy(tree);
+}
+
+static c_avl_tree_t *
+zone_scandir(DIR *procdir)
+{
+ pid_t pid;
+ dirent_t *direntp;
+ psinfo_t psinfo;
+ c_avl_tree_t *tree;
+ zone_stats_t *stats;
+
+ if (!(tree=c_avl_create((void *) zone_compare))) {
+ WARNING("zone plugin: Failed to create tree");
+ return(NULL);
+ }
+
+ rewinddir(procdir);
+ while ((direntp = readdir(procdir))) {
+ char const *pidstr = direntp->d_name;
+ if (pidstr[0] == '.') /* skip "." and ".." */
+ continue;
+
+ pid = atoi(pidstr);
+ if (pid == 0 || pid == 2 || pid == 3)
+ continue; /* skip sched, pageout and fsflush */
+
+ if (zone_read_procfile(pidstr, "psinfo", &psinfo, sizeof(psinfo_t)) != 0)
+ continue;
+
+ stats = zone_find_stats(tree, psinfo.pr_zoneid);
+ if( stats ) {
+ stats->pctcpu += psinfo.pr_pctcpu;
+ stats->pctmem += psinfo.pr_pctmem;
+ }
+ }
+ return(tree);
+}
+
+static int zone_read (void)
+{
+ DIR *procdir;
+ c_avl_tree_t *tree;
+
+ if ((procdir = opendir("/proc")) == NULL) {
+ ERROR("zone plugin: cannot open /proc directory\n");
+ return (-1);
+ }
+
+ tree=zone_scandir(procdir);
+ closedir(procdir);
+ if (tree == NULL) {
+ return (-1);
+ }
+ zone_submit_values(tree); /* this also frees tree */
+ return (0);
+}
+
+void module_register (void)
+{
+ plugin_register_init ("zone", zone_init);
+ plugin_register_read ("zone", zone_read);
+} /* void module_register */
diff --git a/src/zookeeper.c b/src/zookeeper.c
index 63ee6c90040596ec54198ee2a11909611dc04ad0..abdbf20f3361d257165d4697346e98213caeca11 100644 (file)
--- a/src/zookeeper.c
+++ b/src/zookeeper.c
#include "plugin.h"
#include <netdb.h>
-#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>