src/tests/mock/.deps/
src/tests/.dirstamp
src/tests/mock/.dirstamp
+test*.log
# new daemon repo
src/daemon/.deps/
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.
-2015-05-22, Version 5.5.0
+2015-05-27, Version 5.5.0
* Build system: Ability to make out-of-tree builds has been fixed.
Thanks to Vincent Bernat. #792
* Build system, Disk and Users plugins: Detection and use of libstatgrab
Ritschard, Tim Smith, Moshe Zada, Katelyn Perry and Marc Fournier.
* collectd: Rules/Targets can now be appended to existing Filter Chains.
Thanks to Marc Falzon. #444
+ * collectd: Failing Filter Chains destinations will now log the list of
+ available write targets. Thanks to Wilfried Goesgens. #650, #1043
* collectd: Support for process signaling and management by upstart and
systemd has been implemented for the Linux platform. Thanks to
Pierre-Yves Ritschard and Marc Fournier. #798, #811, #814
#890, #751, #771
* Redis and Write_Redis plugins: The support library has been switched
from credis to hiredis. Thanks to Andrés J. Díaz, Victor Seva, Marc
- Fournier, Johan Bergström and Michael Spiegle. #296, #464, #475, #799
+ Fournier, Johan Bergström, Michael Spiegle and brianpkelly. #296,
+ #464, #475, #799, #1030
* Redis plugin: Custom commands can now be used to fetch values stored
in Redis. Thanks to Pierre-Yves Ritschard. #816
* Redis plugin: Support for passwords up to 512 characters long has been
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.
database.
* Logging is, as everything in collectd, provided by plugins. The following
- plugins keep up informed about what's going on:
+ plugins keep us informed about what's going on:
- logfile
Writes log messages to a file or STDOUT/STDERR.
org/collectd/java/GenericJMX.java \
org/collectd/java/JMXMemory.java
-java-build-stamp: org/collectd/api/*.java org/collectd/java/*.java
+java-build-stamp: $(srcdir)/org/collectd/api/*.java $(srcdir)/org/collectd/java/*.java
$(JAVAC) -d "." "$(srcdir)/org/collectd/api"/*.java
$(JAVAC) -d "." "$(srcdir)/org/collectd/java"/*.java
mkdir -p .libs
$(INSTALL) -m 644 .libs/generic-jmx.jar \
"$(DESTDIR)$(pkgdatadir)/java"
+uninstall-local:
+ rm -f "$(DESTDIR)$(pkgdatadir)/java/collectd-api.jar"
+ rm -f "$(DESTDIR)$(pkgdatadir)/java/generic-jmx.jar"
+ rmdir "$(DESTDIR)$(pkgdatadir)/java" || true
+
clean-local:
rm -f "org/collectd/api"/*.class
rm -f "org/collectd/java"/*.class
then
AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Define to enforce POSIX thread semantics under Solaris.])
AC_DEFINE(_REENTRANT, 1, [Define to enable reentrancy interfaces.])
+
+ AC_MSG_CHECKING([whether compiler builds 64bit binaries])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
+ #ifndef _LP64
+ # error "Compiler not in 64bit mode."
+ #endif
+ ])],
+ [AC_MSG_RESULT([yes])],
+ [
+ AC_MSG_RESULT([no])
+ AC_MSG_NOTICE([Solaris detected. Please consider building a 64-bit binary.])
+ ])
fi
+
if test "x$ac_system" = "xAIX"
then
AC_DEFINE(_THREAD_SAFE_ERRNO, 1, [Define to use the thread-safe version of errno under AIX.])
#endif
])
+have_ip6_ext="no"
+AC_CHECK_TYPES([struct ip6_ext], [have_ip6_ext="yes"], [have_ip6_ext="no"],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP6_H
+# include <netinet/ip6.h>
+#endif
+])
+
+if test "x$have_ip6_ext" = "xno"; then
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -DSOLARIS2=8"
+
+ AC_CHECK_TYPES([struct ip6_ext],
+ [have_ip6_ext="yes, with -DSOLARIS2=8"],
+ [have_ip6_ext="no"],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP6_H
+# include <netinet/ip6.h>
+#endif
+])
+
+ if test "x$have_ip6_ext" = "xno"; then
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+fi
+
# For cpu modules
AC_CHECK_HEADERS(sys/dkstat.h)
if test "x$ac_system" = "xDarwin"
#endif
])
-if test "x$have_sys_swap_h$ac_system" = "xnoSolaris"
-then
- hint_64=""
- if test "x$GCC" = "xyes"
- then
- hint_64="CFLAGS='-m64'"
- else
- hint_64="CFLAGS='-xarch=v9'"
- fi
- AC_MSG_NOTICE([Solaris detected and sys/swap.h not usable. Try building a 64-bit binary ($hint_64 ./configure).])
-fi
-
# For load module
# For the processes plugin
# For users module
if test "x$have_asm_msrindex_h" = "xyes"
then
- AC_CACHE_CHECK([whether asm/msr-index.h has MSR_CORE_C3_RESIDENCY],
+ AC_CACHE_CHECK([whether asm/msr-index.h has MSR_PKG_C10_RESIDENCY],
[c_cv_have_usable_asm_msrindex_h],
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
[[[
#include<asm/msr-index.h>
]]],
[[[
-int y = MSR_CORE_C3_RESIDENCY;
+int y = MSR_PKG_C10_RESIDENCY;
return(y);
]]]
)],
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=""
plugin_vserver="no"
plugin_wireless="no"
plugin_zfs_arc="no"
+plugin_zone="no"
plugin_zookeeper="no"
# Linux
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
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
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
+++ /dev/null
-[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
END
# graph various ranges
- foreach my $span qw(1hour 1day 1week 1month){
+ foreach my $span (qw(1hour 1day 1week 1month)){
system("mkdir -p $IMG_DIR/" . dirname($bn));
my $img = "$IMG_DIR/${bn}-$span$IMG_SFX";
+++ /dev/null
-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
+++ /dev/null
-#!/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
%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
%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_write_redis} \
%{?_with_xmms} \
%{?_with_zfs_arc} \
+ %{?_with_zone} \
%{?_with_zookeeper} \
%{?_with_irq} \
%{?_with_load} \
%doc contrib/
%changelog
-* Wed May 20 2015 Marc Fournier <marc.fournier@camptocamp.com> 5.5.0-1
+#* TODO: next feature release changelog
+#- New upstream version
+#- 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,
openldap, redis, write_redis, zookeeper, write_log, write_sensu, ipc,
AUTOMAKE_OPTIONS = subdir-objects
+noinst_LTLIBRARIES =
+check_PROGRAMS =
+TESTS =
+
+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
+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
+
+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
+
+
sbin_PROGRAMS = collectdmon
bin_PROGRAMS = collectd-nagios collectdctl collectd-tg
collectdctl_LDADD += libcollectdclient/libcollectdclient.la
collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la
-collectd_tg_SOURCES = collectd-tg.c \
- daemon/utils_heap.c daemon/utils_heap.h
-collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
-collectd_tg_LDADD =
+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_LDADD = daemon/libheap.la
if BUILD_WITH_LIBSOCKET
collectd_tg_LDADD += -lsocket
endif
if BUILD_PLUGIN_CGROUPS
pkglib_LTLIBRARIES += cgroups.la
cgroups_la_SOURCES = cgroups.c \
- utils_ignorelist.c utils_ignorelist.h \
- utils_mount.c utils_mount.h
+ utils_ignorelist.c utils_ignorelist.h
cgroups_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+cgroups_la_LIBADD = libmount.la
endif
if BUILD_PLUGIN_CONNTRACK
if BUILD_PLUGIN_DF
pkglib_LTLIBRARIES += df.la
df_la_SOURCES = df.c \
- utils_ignorelist.c utils_ignorelist.h \
- utils_mount.c utils_mount.h
+ utils_ignorelist.c utils_ignorelist.h
df_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+df_la_LIBADD = libmount.la
endif
if BUILD_PLUGIN_DISK
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
+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_common test_utils_avltree test_utils_heap test_utils_mount test_utils_vl_lookup
-
-test_common_SOURCES = tests/test_common.c \
- daemon/common.h daemon/common.c \
- tests/macros.h \
- tests/mock/plugin.c \
- tests/mock/utils_cache.c \
- tests/mock/utils_time.c
-test_common_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
-test_common_LDFLAGS = -export-dynamic
-test_common_LDADD =
-
-test_utils_avltree_SOURCES = tests/test_utils_avltree.c \
- daemon/utils_avltree.c daemon/utils_avltree.h
-test_utils_avltree_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
-test_utils_avltree_LDFLAGS = -export-dynamic
-test_utils_avltree_LDADD =
-
-test_utils_heap_SOURCES = tests/test_utils_heap.c \
- daemon/utils_heap.c daemon/utils_heap.h
-test_utils_heap_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
-test_utils_heap_LDFLAGS = -export-dynamic
-test_utils_heap_LDADD =
-
-test_utils_mount_SOURCES = tests/test_utils_mount.c \
- utils_mount.c utils_mount.h \
- daemon/common.c daemon/common.h \
- tests/mock/plugin.c \
- tests/mock/utils_cache.c \
- tests/mock/utils_time.c
-test_utils_mount_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
-test_utils_mount_LDFLAGS = -export-dynamic
-test_utils_mount_LDADD =
-
-test_utils_vl_lookup_SOURCES = tests/test_utils_vl_lookup.c \
- utils_vl_lookup.h utils_vl_lookup.c \
- daemon/utils_avltree.c daemon/utils_avltree.h \
- daemon/common.c daemon/common.h \
- tests/mock/plugin.c \
- tests/mock/utils_cache.c \
- tests/mock/utils_time.c
-test_utils_vl_lookup_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
-test_utils_vl_lookup_LDFLAGS = -export-dynamic
-test_utils_vl_lookup_LDADD =
-
-TESTS = test_common test_utils_avltree test_utils_heap test_utils_mount test_utils_vl_lookup
+
continue;
}
- status = camqp_read_header (conf);
+ camqp_read_header (conf);
amqp_maybe_release_buffers (conf->connection);
} /* while (subscriber_threads_running) */
curl_easy_cleanup(st->curl);
st->curl = NULL;
}
+ sfree (st);
} /* apache_free */
static size_t apache_curl_callback (void *buf, size_t size, size_t nmemb,
status = plugin_register_complex_read (/* group = */ NULL,
/* name = */ callback_name,
/* callback = */ apache_read_host,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user_data = */ &ud);
}
/*
* 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>
# 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 ("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 ("apc_query_server (%s, %i) = %i",
- conf_host == NULL
- ? APCUPS_DEFAULT_HOST
- : conf_host,
- conf_port, status);
+ DEBUG ("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 */
*
* @return Zero when successful
*/
-static int averaging_create(averaging_t * avg, int size)
+static int averaging_create(averaging_t *avg, int size)
{
- int a;
-
- avg->ring_buffer = (long int *) malloc(size * sizeof(*avg));
+ avg->ring_buffer = calloc ((size_t) size, sizeof (*avg->ring_buffer));
if (avg->ring_buffer == NULL)
{
ERROR ("barometer: averaging_create - ring buffer allocation of size %d failed",
return -1;
}
- for (a=0; a<size; ++a)
- {
- avg->ring_buffer[a] = 0L;
- }
-
avg->ring_buffer_size = size;
avg->ring_buffer_sum = 0L;
avg->ring_buffer_head = 0;
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];
return 0;
}
-/**
+/**
* Read the MPL115 sensor conversion coefficients.
*
* These are (device specific) constants so we can read them just once.
*/
static int MPL115_read_coeffs(void)
{
- uint8_t mpl115_coeffs[MPL115_NUM_COEFFS];
+ uint8_t mpl115_coeffs[MPL115_NUM_COEFFS] = { 0 };
int32_t res;
int8_t sia0MSB, sia0LSB, sib1MSB, sib1LSB, sib2MSB, sib2LSB;
int8_t sic12MSB, sic12LSB, sic11MSB, sic11LSB, sic22MSB, sic22LSB;
int16_t sia0, sib1, sib2, sic12, sic11, sic22;
-
+
char errbuf[1024];
- res = i2c_smbus_read_i2c_block_data(i2c_bus_fd,
- MPL115_ADDR_COEFFS,
- MPL115_NUM_COEFFS,
+ res = i2c_smbus_read_i2c_block_data(i2c_bus_fd,
+ MPL115_ADDR_COEFFS,
+ STATIC_ARRAY_SIZE (mpl115_coeffs),
mpl115_coeffs);
if (res < 0)
{
sstrerror (errno, errbuf, sizeof (errbuf)));
return -1;
}
-
+
/* Using perhaps less elegant/efficient code, but more readable. */
/* a0: 16total 1sign 12int 4fract 0pad */
sia0MSB = mpl115_coeffs[0];
sia0 += (int16_t) sia0LSB & 0x00FF; /* Add LSB to 16bit number */
mpl115_coeffA0 = (double) (sia0);
mpl115_coeffA0 /= 8.0; /* 3 fract bits */
-
+
/* b1: 16total 1sign 2int 13fract 0pad */
sib1MSB= mpl115_coeffs[2];
sib1LSB= mpl115_coeffs[3];
sib1 += sib1LSB & 0x00FF; /* Add LSB to 16bit number */
mpl115_coeffB1 = (double) (sib1);
mpl115_coeffB1 /= 8192.0; /* 13 fract */
-
+
/* b2: 16total 1sign 1int 14fract 0pad */
sib2MSB= mpl115_coeffs[4];
sib2LSB= mpl115_coeffs[5];
mpl115_coeffC22 /= 33554432.0; /* 10+15=25 fract */
DEBUG("barometer: MPL115_read_coeffs: a0=%lf, b1=%lf, b2=%lf, c12=%lf, c11=%lf, c22=%lf",
- mpl115_coeffA0,
- mpl115_coeffB1,
- mpl115_coeffB2,
- mpl115_coeffC12,
- mpl115_coeffC11,
+ mpl115_coeffA0,
+ mpl115_coeffB1,
+ mpl115_coeffB2,
+ mpl115_coeffC12,
+ mpl115_coeffC11,
mpl115_coeffC22);
return 0;
}
}
-/**
+/**
* Read sensor averegaed measurements
*
* @param pressure averaged measured pressure
*/
static int MPL115_read_averaged(double * pressure, double * temperature)
{
- uint8_t mpl115_conv[MPL115_NUM_CONV];
+ uint8_t mpl115_conv[MPL115_NUM_CONV] = { 0 };
int8_t res;
int retries;
int conv_pressure;
*pressure = 0.0;
*temperature = 0.0;
-
+
/* start conversion of both temp and presure */
retries = MPL115_CONVERSION_RETRIES;
while (retries>0)
{
res = i2c_smbus_read_i2c_block_data(i2c_bus_fd,
MPL115_ADDR_CONV,
- MPL115_NUM_CONV,
- mpl115_conv);
+ STATIC_ARRAY_SIZE (mpl115_conv),
+ mpl115_conv);
if (res >= 0)
break;
return -1;
}
}
-
+
conv_pressure = ((mpl115_conv[0] << 8) | mpl115_conv[1]) >> 6;
conv_temperature = ((mpl115_conv[2] << 8) | mpl115_conv[3]) >> 6;
DEBUG ("barometer: MPL115_read_averaged, raw pressure ADC value = %d, " \
adc_temperature,
*pressure,
*temperature);
-
+
return 0;
}
ssnprintf (filename, sizeof (filename), "%s/%s/info", dir, power_supply);
fh = fopen (filename, "r");
- if ((fh = fopen (filename, "r")) == NULL)
+ if (fh == NULL)
return (errno);
/* last full capacity: 40090 mWh */
ssnprintf (filename, sizeof (filename), "%s/%s/state", dir, power_supply);
fh = fopen (filename, "r");
- if ((fh = fopen (filename, "r")) == NULL)
+ if (fh == NULL)
{
if ((errno == EAGAIN) || (errno == EINTR) || (errno == ENOENT))
return (0);
xmlFree (zone_name);
zone_name = NULL;
- if (j >= views->zones_num)
+ if (j >= view->zones_num)
return (0);
zone_name = view->zones[j];
static int cc_add_daemon_config(oconfig_item_t *ci)
{
int ret, i;
- struct ceph_daemon *array, *nd, cd;
+ struct ceph_daemon *nd, cd;
+ struct ceph_daemon **tmp;
memset(&cd, 0, sizeof(struct ceph_daemon));
if((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
return -EINVAL;
}
- array = realloc(g_daemons,
- sizeof(struct ceph_daemon *) * (g_num_daemons + 1));
- if(array == NULL)
+ tmp = realloc(g_daemons, (g_num_daemons+1) * sizeof(*g_daemons));
+ if(tmp == NULL)
{
/* The positive return value here indicates that this is a
* runtime error, not a configuration error. */
return ENOMEM;
}
- g_daemons = (struct ceph_daemon**) array;
- nd = malloc(sizeof(struct ceph_daemon));
+ g_daemons = tmp;
+
+ nd = malloc(sizeof(*nd));
if(!nd)
{
return ENOMEM;
}
- memcpy(nd, &cd, sizeof(struct ceph_daemon));
+ memcpy(nd, &cd, sizeof(*nd));
g_daemons[g_num_daemons++] = nd;
return 0;
}
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;
# 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 "utils_heap.h"
loop = 0;
} /* }}} void signal_handler */
+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 */
+
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;
#@BUILD_PLUGIN_BATTERY_TRUE@LoadPlugin battery
#@BUILD_PLUGIN_BIND_TRUE@LoadPlugin bind
#@BUILD_PLUGIN_CEPH_TRUE@LoadPlugin ceph
+#@BUILD_PLUGIN_CGROUPS_TRUE@LoadPlugin cgroups
#@BUILD_PLUGIN_CONNTRACK_TRUE@LoadPlugin conntrack
#@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@LoadPlugin contextswitch
-#@BUILD_PLUGIN_CGROUPS_TRUE@LoadPlugin cgroups
@BUILD_PLUGIN_CPU_TRUE@@BUILD_PLUGIN_CPU_TRUE@LoadPlugin cpu
#@BUILD_PLUGIN_CPUFREQ_TRUE@LoadPlugin cpufreq
@LOAD_PLUGIN_CSV@LoadPlugin csv
#@BUILD_PLUGIN_HDDTEMP_TRUE@LoadPlugin hddtemp
@BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_PLUGIN_INTERFACE_TRUE@LoadPlugin interface
#@BUILD_PLUGIN_IPC_TRUE@@BUILD_PLUGIN_IPC_TRUE@LoadPlugin ipc
-#@BUILD_PLUGIN_IPTABLES_TRUE@LoadPlugin iptables
#@BUILD_PLUGIN_IPMI_TRUE@LoadPlugin ipmi
+#@BUILD_PLUGIN_IPTABLES_TRUE@LoadPlugin iptables
#@BUILD_PLUGIN_IPVS_TRUE@LoadPlugin ipvs
#@BUILD_PLUGIN_IRQ_TRUE@LoadPlugin irq
#@BUILD_PLUGIN_JAVA_TRUE@LoadPlugin java
#@BUILD_PLUGIN_MEMCACHEC_TRUE@LoadPlugin memcachec
#@BUILD_PLUGIN_MEMCACHED_TRUE@LoadPlugin memcached
@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_USERS_TRUE@LoadPlugin users
#@BUILD_PLUGIN_UUID_TRUE@LoadPlugin uuid
#@BUILD_PLUGIN_VARNISH_TRUE@LoadPlugin varnish
-#@BUILD_PLUGIN_MIC_TRUE@LoadPlugin mic
#@BUILD_PLUGIN_VIRT_TRUE@LoadPlugin virt
#@BUILD_PLUGIN_VMEM_TRUE@LoadPlugin vmem
#@BUILD_PLUGIN_VSERVER_TRUE@LoadPlugin vserver
#@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>
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<AMQMP plugin> can be used to communicate with other instances of
I<collectd> or third party applications using an AMQP message broker. Values
are sent to or received from the broker, which handles routing, queueing and
-possibly filtering or messages.
+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>
=head2 Plugin C<curl_json>
The B<curl_json plugin> collects values from JSON data to be parsed by
-B<libyajl> (L<http://www.lloydforge.org/projects/yajl/>) retrieved via
+B<libyajl> (L<https://lloyd.github.io/yajl/>) retrieved via
either B<libcurl> (L<http://curl.haxx.se/>) or read directly from a
unix socket. The former can be used, for example, to collect values
from CouchDB documents (which are stored JSON notation), and the
=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>
Host "localhost"
Port "6379"
Timeout 1000
+ Prefix "collectd/"
+ Database 1
</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. Additionnally, 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>.
+
=back
=head2 Plugin C<write_riemann>
"Hostname defaults to the local hostname if omitted (e.g., uptime/uptime).\n"
"No error is returned if the specified identifier does not exist.\n"
- "\n"PACKAGE" "VERSION", http://collectd.org/\n"
+ "\n"PACKAGE_NAME" "PACKAGE_VERSION", http://collectd.org/\n"
"by Florian octo Forster <octo@collectd.org>\n"
"for contributions see `AUTHORS'\n"
, name);
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';
"\nFor <collectd options> see collectd.conf(5).\n"
- "\n"PACKAGE" "VERSION", http://collectd.org/\n"
+ "\n"PACKAGE_NAME" "PACKAGE_VERSION", http://collectd.org/\n"
"by Florian octo Forster <octo@collectd.org>\n"
"for contributions see `AUTHORS'\n", name);
exit (0);
openlog ("collectdmon", LOG_CONS | LOG_PID, LOG_DAEMON);
if (-1 == daemonize ())
+ {
+ free (collectd_argv);
return 1;
+ }
sa.sa_handler = sig_int_term_handler;
sa.sa_flags = 0;
if (0 != sigaction (SIGINT, &sa, NULL)) {
syslog (LOG_ERR, "Error: sigaction() failed: %s", strerror (errno));
+ free (collectd_argv);
return 1;
}
if (0 != sigaction (SIGTERM, &sa, NULL)) {
syslog (LOG_ERR, "Error: sigaction() failed: %s", strerror (errno));
+ free (collectd_argv);
return 1;
}
if (0 != sigaction (SIGHUP, &sa, NULL)) {
syslog (LOG_ERR, "Error: sigaction() failed: %s", strerror (errno));
+ free (collectd_argv);
return 1;
}
/* 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);
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 */
continue;
}
- if (cpu_info_len < COLLECTD_CPU_STATE_MAX)
+ if (cpu_info_len < CPU_STATE_MAX)
{
ERROR ("cpu plugin: processor_info returned only %i elements..", cpu_info_len);
continue;
}
- cpu_stage (cpu, COLLECTD_CPU_STATE_USER, (derive_t) cpu_info.cpu_ticks[COLLECTD_CPU_STATE_USER], now);
- cpu_stage (cpu, COLLECTD_CPU_STATE_NICE, (derive_t) cpu_info.cpu_ticks[COLLECTD_CPU_STATE_NICE], now);
- cpu_stage (cpu, COLLECTD_CPU_STATE_SYSTEM, (derive_t) cpu_info.cpu_ticks[COLLECTD_CPU_STATE_SYSTEM], now);
- cpu_stage (cpu, COLLECTD_CPU_STATE_IDLE, (derive_t) cpu_info.cpu_ticks[COLLECTD_CPU_STATE_IDLE], now);
+ cpu_stage (cpu, COLLECTD_CPU_STATE_USER, (derive_t) cpu_info.cpu_ticks[CPU_STATE_USER], now);
+ cpu_stage (cpu, COLLECTD_CPU_STATE_NICE, (derive_t) cpu_info.cpu_ticks[CPU_STATE_NICE], now);
+ cpu_stage (cpu, COLLECTD_CPU_STATE_SYSTEM, (derive_t) cpu_info.cpu_ticks[CPU_STATE_SYSTEM], now);
+ cpu_stage (cpu, COLLECTD_CPU_STATE_IDLE, (derive_t) cpu_info.cpu_ticks[CPU_STATE_IDLE], now);
}
/* }}} #endif PROCESSOR_CPU_LOAD_INFO */
{
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);
} /* while (status == 0) */
if (status != 0)
+ {
+ cc_web_match_free (match);
return (status);
+ }
match->match = match_create_simple (match->regex, match->exclude_regex,
match->dstype);
{
ERROR ("curl_json plugin: cj_config: "
"Invalid key: %s", ci->key);
+ cj_key_free (key);
return (-1);
}
db->tree = cj_avl_create();
tree = db->tree;
- name = key->path;
ptr = key->path;
if (*ptr == '/')
++ptr;
if (*ptr == '/')
{
c_avl_tree_t *value;
- int len;
+ size_t len;
len = ptr-name;
if (len == 0)
{
ERROR ("curl_json plugin: cj_config: "
"Invalid key: %s", ci->key);
+ cj_free (db);
return (-1);
}
if (status != 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);
}
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++)
{
ERROR ("curl_xml plugin: cx_config: "
"Invalid key: %s", ci->key);
+ cx_free (db);
return (-1);
}
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
AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"'
AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
+# Link to these libraries..
+COMMON_LIBS =
+if BUILD_WITH_LIBRT
+COMMON_LIBS += -lrt
+endif
+if BUILD_WITH_LIBPOSIX4
+COMMON_LIBS += -lposix4
+endif
+if BUILD_WITH_LIBSOCKET
+COMMON_LIBS += -lsocket
+endif
+if BUILD_WITH_LIBRESOLV
+COMMON_LIBS += -lresolv
+endif
+if BUILD_WITH_LIBPTHREAD
+COMMON_LIBS += -lpthread
+endif
+if BUILD_WITH_LIBKSTAT
+COMMON_LIBS += -lkstat
+endif
+if BUILD_WITH_LIBDEVINFO
+COMMON_LIBS += -ldevinfo
+endif
+
AUTOMAKE_OPTIONS = subdir-objects
sbin_PROGRAMS = collectd
+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 \
- common.c common.h \
configfile.c configfile.h \
filter_chain.c filter_chain.h \
meta_data.c meta_data.h \
plugin.c plugin.h \
- utils_avltree.c utils_avltree.h \
utils_cache.c utils_cache.h \
utils_complain.c utils_complain.h \
- utils_heap.c utils_heap.h \
utils_llist.c utils_llist.h \
utils_random.c utils_random.h \
utils_tail_match.c utils_tail_match.h \
collectd_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
collectd_CFLAGS = $(AM_CFLAGS)
collectd_LDFLAGS = -export-dynamic
-collectd_LDADD = -lm
-collectd_DEPENDENCIES =
-
-# Link to these libraries..
-if BUILD_WITH_LIBRT
-collectd_LDADD += -lrt
-endif
-if BUILD_WITH_LIBPOSIX4
-collectd_LDADD += -lposix4
-endif
-if BUILD_WITH_LIBSOCKET
-collectd_LDADD += -lsocket
-endif
-if BUILD_WITH_LIBRESOLV
-collectd_LDADD += -lresolv
-endif
-if BUILD_WITH_LIBPTHREAD
-collectd_LDADD += -lpthread
-endif
-if BUILD_WITH_LIBKSTAT
-collectd_LDADD += -lkstat
-endif
-if BUILD_WITH_LIBDEVINFO
-collectd_LDADD += -ldevinfo
-endif
-if BUILD_AIX
-collectd_LDFLAGS += -Wl,-bexpall,-brtllib
-endif
+collectd_LDADD = libavltree.la libcommon.la libheap.la -lm $(COMMON_LIBS)
+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
else
collectd_LDADD += -loconfig
endif
+
+check_PROGRAMS = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_subst
+TESTS = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_subst
+
+test_common_SOURCES = common_test.c ../testing.h
+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_subst_SOURCES = utils_subst_test.c ../testing.h \
+ utils_subst.c utils_subst.h
+test_utils_subst_LDADD = libcommon.la libplugin_mock.la
*/
static void exit_usage (int status)
{
- printf ("Usage: "PACKAGE" [OPTIONS]\n\n"
+ printf ("Usage: "PACKAGE_NAME" [OPTIONS]\n\n"
"Available options:\n"
" General:\n"
" PID file "PIDFILE"\n"
" Plugin directory "PLUGINDIR"\n"
" Data directory "PKGLOCALSTATEDIR"\n"
- "\n"PACKAGE" "VERSION", http://collectd.org/\n"
+ "\n"PACKAGE_NAME" "PACKAGE_VERSION", http://collectd.org/\n"
"by Florian octo Forster <octo@collectd.org>\n"
"for contributions see `AUTHORS'\n");
exit (status);
static int pidfile_remove (void)
{
const char *file = global_option_get ("PIDFile");
+ if (file == NULL)
+ return 0;
- DEBUG ("unlink (%s)", (file != NULL) ? file : "<null>");
return (unlink (file));
} /* static int pidfile_remove (const char *file) */
#endif /* COLLECT_DAEMON */
#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);
+ fd = socket (AF_UNIX, SOCK_DGRAM, /* protocol = */ 0);
+ 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
+ {
+#if KERNEL_LINUX
+ /* 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);
+#else
+ ERROR ("Systemd socket uses Linux abstract namespace notation (\"%s\"), "
+ "but I don't appear to be running on Linux.", notifysocket);
+ return 0;
+#endif
+ }
- 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;
}
+
close(fd);
return 1;
}
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);
return ((int) i);
}
-int strjoin (char *dst, size_t dst_len,
+int strjoin (char *buffer, size_t buffer_size,
char **fields, size_t fields_num,
const char *sep)
{
- size_t field_len;
+ size_t avail;
+ char *ptr;
size_t sep_len;
- int i;
-
- memset (dst, '\0', dst_len);
+ size_t i;
- if (fields_num <= 0)
+ if ((buffer_size < 1) || (fields_num <= 0))
return (-1);
+ memset (buffer, 0, buffer_size);
+ ptr = buffer;
+ avail = buffer_size - 1;
+
sep_len = 0;
if (sep != NULL)
sep_len = strlen (sep);
- for (i = 0; i < (int)fields_num; i++)
+ for (i = 0; i < fields_num; i++)
{
+ size_t field_len;
+
if ((i > 0) && (sep_len > 0))
{
- if (dst_len <= sep_len)
+ if (avail < sep_len)
return (-1);
- strncat (dst, sep, dst_len);
- dst_len -= sep_len;
+ memcpy (ptr, sep, sep_len);
+ ptr += sep_len;
+ avail -= sep_len;
}
field_len = strlen (fields[i]);
-
- if (dst_len <= field_len)
+ if (avail < field_len)
return (-1);
- strncat (dst, fields[i], dst_len);
- dst_len -= field_len;
+ memcpy (ptr, fields[i], field_len);
+ ptr += field_len;
+ avail -= field_len;
}
- return (strlen (dst));
+ assert (buffer[buffer_size - 1] == 0);
+ 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);
buffer_len--;
}
- for (i = 0; i < buffer_len - 1; i++)
+ for (i = 0; i < buffer_len; i++)
{
if (buffer[i] == '/')
buffer[i] = '_';
* 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 */
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. */
--- /dev/null
+/**
+ * collectd - src/tests/test_common.c
+ * Copyright (C) 2013 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 "common.h"
+
+DEF_TEST(sstrncpy)
+{
+ char buffer[16] = "";
+ char *ptr = &buffer[4];
+ char *ret;
+
+ buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0xff;
+ buffer[12] = buffer[13] = buffer[14] = buffer[15] = 0xff;
+
+ ret = sstrncpy (ptr, "foobar", 8);
+ OK(ret == ptr);
+ STREQ ("foobar", ptr);
+ OK(buffer[3] == buffer[12]);
+
+ ret = sstrncpy (ptr, "abc", 8);
+ OK(ret == ptr);
+ STREQ ("abc", ptr);
+ OK(buffer[3] == buffer[12]);
+
+ ret = sstrncpy (ptr, "collectd", 8);
+ OK(ret == ptr);
+ OK(ptr[7] == 0);
+ STREQ ("collect", ptr);
+ OK(buffer[3] == buffer[12]);
+
+ return (0);
+}
+
+DEF_TEST(ssnprintf)
+{
+ char buffer[16] = "";
+ char *ptr = &buffer[4];
+ int status;
+
+ buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0xff;
+ buffer[12] = buffer[13] = buffer[14] = buffer[15] = 0xff;
+
+ status = ssnprintf (ptr, 8, "%i", 1337);
+ OK(status == 4);
+ STREQ ("1337", ptr);
+
+ status = ssnprintf (ptr, 8, "%s", "collectd");
+ OK(status == 8);
+ OK(ptr[7] == 0);
+ STREQ ("collect", ptr);
+ OK(buffer[3] == buffer[12]);
+
+ return (0);
+}
+
+DEF_TEST(sstrdup)
+{
+ char *ptr;
+
+ ptr = sstrdup ("collectd");
+ OK(ptr != NULL);
+ STREQ ("collectd", ptr);
+
+ sfree(ptr);
+ OK(ptr == NULL);
+
+ ptr = sstrdup (NULL);
+ OK(ptr == NULL);
+
+ return (0);
+}
+
+DEF_TEST(strsplit)
+{
+ char buffer[32];
+ char *fields[8];
+ int status;
+
+ strncpy (buffer, "foo bar", sizeof (buffer));
+ status = strsplit (buffer, fields, 8);
+ OK(status == 2);
+ STREQ ("foo", fields[0]);
+ STREQ ("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]);
+
+ 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]);
+
+ strncpy (buffer, "\twith trailing\n", sizeof (buffer));
+ status = strsplit (buffer, fields, 8);
+ OK(status == 2);
+ STREQ ("with", fields[0]);
+ STREQ ("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]);
+
+ strncpy (buffer, "single", sizeof (buffer));
+ status = strsplit (buffer, fields, 8);
+ OK(status == 1);
+ STREQ ("single", fields[0]);
+
+ strncpy (buffer, "", sizeof (buffer));
+ status = strsplit (buffer, fields, 8);
+ OK(status == 0);
+
+ return (0);
+}
+
+DEF_TEST(strjoin)
+{
+ char buffer[16];
+ char *fields[4];
+ int status;
+
+ fields[0] = "foo";
+ fields[1] = "bar";
+ fields[2] = "baz";
+ fields[3] = "qux";
+
+ status = strjoin (buffer, sizeof (buffer), fields, 2, "!");
+ OK(status == 7);
+ STREQ ("foo!bar", buffer);
+
+ status = strjoin (buffer, sizeof (buffer), fields, 1, "!");
+ OK(status == 3);
+ STREQ ("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);
+
+ status = strjoin (buffer, sizeof (buffer), fields, 4, "");
+ OK(status == 12);
+ STREQ ("foobarbazqux", buffer);
+
+ status = strjoin (buffer, sizeof (buffer), fields, 4, "!");
+ OK(status == 15);
+ STREQ ("foo!bar!baz!qux", buffer);
+
+ fields[0] = "0123";
+ fields[1] = "4567";
+ fields[2] = "8901";
+ fields[3] = "2345";
+ status = strjoin (buffer, sizeof (buffer), fields, 4, "-");
+ OK(status < 0);
+
+ 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);
+ STREQ(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);
+ STREQ(cases[i].want, buffer);
+ }
+
+ return 0;
+}
+
+DEF_TEST(strunescape)
+{
+ char buffer[16];
+ int status;
+
+ strncpy (buffer, "foo\\tbar", sizeof (buffer));
+ status = strunescape (buffer, sizeof (buffer));
+ OK(status == 0);
+ STREQ ("foo\tbar", buffer);
+
+ strncpy (buffer, "\\tfoo\\r\\n", sizeof (buffer));
+ status = strunescape (buffer, sizeof (buffer));
+ OK(status == 0);
+ STREQ ("\tfoo\r\n", buffer);
+
+ strncpy (buffer, "With \\\"quotes\\\"", sizeof (buffer));
+ status = strunescape (buffer, sizeof (buffer));
+ OK(status == 0);
+ STREQ ("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);
+ return (0);
+
+ /* Backslash at buffer end */
+ strncpy (buffer, "\\t3\\56", sizeof (buffer));
+ status = strunescape (buffer, 4);
+ OK(status != 0);
+ OK(buffer[0] == '\t');
+ OK(buffer[1] == '3');
+ OK(buffer[2] == 0);
+ OK(buffer[3] == 0);
+ OK(buffer[4] == '5');
+ OK(buffer[5] == '6');
+ OK(buffer[6] == '7');
+
+ 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_INTEQ (cases[i].status, status);
+ if (status != 0)
+ continue;
+
+ DBLEQ (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);
+ DBLEQ(cases[i].want, got);
+ }
+
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(sstrncpy);
+ RUN_TEST(ssnprintf);
+ 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;
+}
+
+/* vim: set sw=2 sts=2 et : */
typedef struct cf_value_map_s
{
char *key;
- int (*func) (const oconfig_item_t *);
+ int (*func) (oconfig_item_t *);
} cf_value_map_t;
typedef struct cf_global_option_s
/*
* Prototypes of callback functions
*/
-static int dispatch_value_typesdb (const oconfig_item_t *ci);
-static int dispatch_value_plugindir (const oconfig_item_t *ci);
-static int dispatch_loadplugin (const oconfig_item_t *ci);
+static int dispatch_value_typesdb (oconfig_item_t *ci);
+static int dispatch_value_plugindir (oconfig_item_t *ci);
+static int dispatch_loadplugin (oconfig_item_t *ci);
+static int dispatch_block_plugin (oconfig_item_t *ci);
/*
* Private variables
{
{"TypesDB", dispatch_value_typesdb},
{"PluginDir", dispatch_value_plugindir},
- {"LoadPlugin", dispatch_loadplugin}
+ {"LoadPlugin", dispatch_loadplugin},
+ {"Plugin", dispatch_block_plugin}
};
static int cf_value_map_num = STATIC_ARRAY_SIZE (cf_value_map);
int ret;
int i;
+ if (orig_key == NULL)
+ return (EINVAL);
+
DEBUG ("type = %s, key = %s, value = %s",
ESCAPE_NULL(type),
- ESCAPE_NULL(orig_key),
+ orig_key,
ESCAPE_NULL(orig_value));
if ((cf_cb = cf_search (type)) == NULL)
free (key);
free (value);
- DEBUG ("cf_dispatch: return (%i)", ret);
-
return (ret);
} /* int cf_dispatch */
return (-1);
} /* int dispatch_global_option */
-static int dispatch_value_typesdb (const oconfig_item_t *ci)
+static int dispatch_value_typesdb (oconfig_item_t *ci)
{
int i = 0;
return (0);
} /* int dispatch_value_typesdb */
-static int dispatch_value_plugindir (const oconfig_item_t *ci)
+static int dispatch_value_plugindir (oconfig_item_t *ci)
{
assert (strcasecmp (ci->key, "PluginDir") == 0);
return (0);
}
-static int dispatch_loadplugin (const oconfig_item_t *ci)
+static int dispatch_loadplugin (oconfig_item_t *ci)
{
int i;
const char *name;
/* 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);
}
}
return (cf_dispatch (plugin, ci->key, buffer_ptr));
} /* int dispatch_value_plugin */
-static int dispatch_value (const oconfig_item_t *ci)
+static int dispatch_value (oconfig_item_t *ci)
{
int ret = -2;
int i;
if (IS_TRUE (global_option_get ("AutoLoadPlugin")))
{
+ plugin_ctx_t ctx;
+ plugin_ctx_t old_ctx;
int status;
+ /* default to the global interval set before loading this plugin */
+ memset (&ctx, 0, sizeof (ctx));
+ ctx.interval = cf_get_default_interval ();
+
+ old_ctx = plugin_set_ctx (ctx);
status = plugin_load (name, /* flags = */ 0);
+ /* reset to the "global" context */
+ plugin_set_ctx (old_ctx);
+
if (status != 0)
{
ERROR ("Automatically loading plugin \"%s\" failed "
filenames[filenames_num - 1] = sstrdup (name);
}
+ if (filenames == NULL)
+ return (root);
+
qsort ((void *) filenames, filenames_num, sizeof (*filenames),
cf_compare_string);
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
- status = 0;
if (strcasecmp ("Match", option->key) == 0)
status = fc_config_add_match (&rule->matches, option);
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
- status = 0;
if (strcasecmp ("Rule", option->key) == 0)
status = fc_config_add_rule (chain, option);
"all write plugins failed with status %i (ENOENT). "
"Most likely this means you didn't load any write plugins.",
status);
+
+ plugin_log_available_writers ();
}
else if (status != 0)
{
"Filter subsystem: Built-in target `write': Dispatching value to "
"the `%s' plugin failed with status %i.",
plugin_list[i].plugin, status);
+
+ plugin_log_available_writers ();
}
else
{
--- /dev/null
+/**
+ * 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));
+ STREQ ("foobar", s);
+ sfree (s);
+
+ CHECK_ZERO (meta_data_get_signed_int (m, "signed_int", &si));
+ EXPECT_INTEQ (-1, (int) si);
+
+ CHECK_ZERO (meta_data_get_unsigned_int (m, "unsigned_int", &ui));
+ EXPECT_INTEQ (1, (int) ui);
+
+ CHECK_ZERO (meta_data_get_double (m, "double", &d));
+ DBLEQ (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_INTEQ (-2, meta_data_get_boolean (m, "string", &b));
+ EXPECT_INTEQ (-2, meta_data_get_string (m, "signed_int", &s));
+ EXPECT_INTEQ (-2, meta_data_get_string (m, "unsigned_int", &s));
+ EXPECT_INTEQ (-2, meta_data_get_string (m, "double", &s));
+ EXPECT_INTEQ (-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_INTEQ (666, (int) si);
+
+ /* deleting keys */
+ CHECK_ZERO (meta_data_delete (m, "signed_int"));
+ EXPECT_INTEQ (-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 : */
write_queue_t *next;
};
+struct flush_callback_s {
+ char *name;
+ cdtime_t timeout;
+};
+typedef struct flush_callback_s flush_callback_t;
+
/*
* Private variables
*/
return (0);
} /* }}} int register_callback */
+static void log_list_callbacks (llist_t **list, /* {{{ */
+ const char *comment)
+{
+ char *str;
+ int len;
+ llentry_t *le;
+ int i;
+ int n;
+ char **keys;
+
+ n = llist_size(*list);
+ if (n == 0)
+ {
+ INFO("%s [none]", comment);
+ return;
+ }
+
+ keys = calloc(n, sizeof(char*));
+
+ if (keys == NULL)
+ {
+ ERROR("%s: failed to allocate memory for list of callbacks",
+ comment);
+
+ return;
+ }
+
+ for (le = llist_head (*list), i = 0, len = 0;
+ le != NULL;
+ le = le->next, i++)
+ {
+ keys[i] = le->key;
+ len += strlen(le->key) + 6;
+ }
+ str = malloc(len + 10);
+ if (str == NULL)
+ {
+ ERROR("%s: failed to allocate memory for list of callbacks",
+ comment);
+ }
+ else
+ {
+ *str = '\0';
+ strjoin(str, len, keys, n, "', '");
+ INFO("%s ['%s']", comment, str);
+ free(str);
+ }
+ free(keys);
+} /* }}} void log_list_callbacks */
+
static int create_register_callback (llist_t **list, /* {{{ */
const char *name, void *callback, user_data_t *ud)
{
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");
}
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))
return (0);
} /* }}} int plugin_unregister_read */
+void plugin_log_available_writers (void)
+{
+ log_list_callbacks (&list_write, "Available write targets:");
+}
+
static int compare_read_func_group (llentry_t *e, void *ud) /* {{{ */
{
read_func_t *rf = e->value;
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);
}
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);
int plugin_unregister_log (const char *name);
int plugin_unregister_notification (const char *name);
+/*
+ * NAME
+ * plugin_log_available_writers
+ *
+ * DESCRIPTION
+ * This function can be called to output a list of _all_ registered
+ * writers to the logfacility.
+ * Since some writers dynamically build their name it can be hard for
+ * the configuring person to know it. This function will fill this gap.
+ */
+void plugin_log_available_writers ();
/*
* NAME
--- /dev/null
+/**
+ * collectd - src/tests/mock/plugin.c
+ * Copyright (C) 2013 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 "plugin.h"
+
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc = NULL;
+#endif /* HAVE_LIBKSTAT */
+
+void plugin_log (int level, char const *format, ...)
+{
+ char buffer[1024];
+ va_list ap;
+
+ va_start (ap, format);
+ vsnprintf (buffer, sizeof (buffer), format, ap);
+ va_end (ap);
+
+ printf ("plugin_log (%i, \"%s\");\n", level, buffer);
+}
+
+/* vim: set sw=2 sts=2 et : */
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;
}
c_avl_node_t *y;
c_avl_node_t *b;
+ assert (x != NULL);
+ assert (x->left != NULL);
+
p = x->parent;
y = x->left;
b = y->right;
y->height = calc_height (y);
return (y);
-} /* void rotate_left */
+} /* void rotate_right */
/*
* (x) (y)
c_avl_node_t *y;
c_avl_node_t *b;
+ assert (x != NULL);
+ assert (x->right != NULL);
+
p = x->parent;
y = x->right;
b = y->left;
n = t->root;
while ((n->left != NULL) || (n->right != NULL))
{
- int height_left = (n->left == NULL) ? 0 : n->left->height;
- int height_right = (n->right == NULL) ? 0 : n->right->height;
+ if (n->left == NULL)
+ {
+ n = n->right;
+ continue;
+ }
+ else if (n->right == NULL)
+ {
+ n = n->left;
+ continue;
+ }
- if (height_left > height_right)
+ if (n->left->height > n->right->height)
n = n->left;
else
n = n->right;
--- /dev/null
+/**
+ * collectd - src/tests/test_utils_avltree.c
+ * Copyright (C) 2013 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 "utils_avltree.h"
+
+static int compare_total_count = 0;
+#define RESET_COUNTS() do { compare_total_count = 0; } while (0)
+
+static int compare_callback (void const *v0, void const *v1)
+{
+ assert (v0 != NULL);
+ assert (v1 != NULL);
+
+ compare_total_count++;
+ return (strcmp (v0, v1));
+}
+
+DEF_TEST(success)
+{
+ c_avl_tree_t *t;
+ char key_orig[] = "foo";
+ char value_orig[] = "bar";
+ char *key_ret = NULL;
+ char *value_ret = NULL;
+
+ RESET_COUNTS ();
+ t = c_avl_create (compare_callback);
+ OK (t != NULL);
+
+ OK (c_avl_insert (t, key_orig, value_orig) == 0);
+ OK (c_avl_size (t) == 1);
+
+ /* Key already exists. */
+ OK (c_avl_insert (t, "foo", "qux") > 0);
+
+ OK (c_avl_get (t, "foo", (void *) &value_ret) == 0);
+ OK (value_ret == &value_orig[0]);
+
+ key_ret = value_ret = NULL;
+ OK (c_avl_remove (t, "foo", (void *) &key_ret, (void *) &value_ret) == 0);
+ OK (key_ret == &key_orig[0]);
+ OK (value_ret == &value_orig[0]);
+ OK (c_avl_size (t) == 0);
+
+ c_avl_destroy (t);
+
+ return (0);
+}
+
+int main (void)
+{
+ RUN_TEST(success);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
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);
}
pthread_mutex_unlock (&cache_lock);
if (keys_len == 0)
+ {
+ /* realloc() may have been called for these. */
+ sfree (keys);
+ sfree (keys_time);
+ sfree (keys_interval);
return (0);
+ }
/* Call the "missing" callback for each value. Do this before removing the
* value from the cache, so that callbacks can still access the data stored,
if (status != 0)
{
ERROR ("uc_check_timeout: parse_identifier_vl (\"%s\") failed.", keys[i]);
- cache_free (ce);
continue;
}
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);
if (status != 0)
{
size_t i;
-
+
for (i = 0; i < number; i++)
{
sfree (names[i]);
}
sfree (names);
+ sfree (times);
return (-1);
}
*ret_names = names;
if (ret_times != NULL)
*ret_times = times;
+ else
+ sfree (times);
*ret_number = number;
return (0);
--- /dev/null
+/**
+ * collectd - src/tests/mock/utils_cache.c
+ * Copyright (C) 2013 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 "utils_cache.h"
+
+gauge_t *uc_get_rate (__attribute((unused)) data_set_t const *ds,
+ __attribute((unused)) value_list_t const *vl)
+{
+ return (NULL);
+}
--- /dev/null
+/**
+ * collectd - src/tests/test_utils_heap.c
+ * Copyright (C) 2013 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 "utils_heap.h"
+
+static int compare (void const *v0, void const *v1)
+{
+ int const *i0 = v0;
+ int const *i1 = v1;
+
+ if ((*i0) < (*i1))
+ return -1;
+ else if ((*i0) > (*i1))
+ return 1;
+ else
+ return 0;
+}
+
+DEF_TEST(simple)
+{
+ int values[] = { 9, 5, 6, 1, 3, 4, 0, 8, 2, 7 };
+ int i;
+ c_heap_t *h;
+
+ CHECK_NOT_NULL(h = c_heap_create (compare));
+ for (i = 0; i < 10; i++)
+ CHECK_ZERO(c_heap_insert (h, &values[i]));
+
+ for (i = 0; i < 5; i++)
+ {
+ int *ret = NULL;
+ CHECK_NOT_NULL(ret = c_heap_get_root(h));
+ OK(*ret == i);
+ }
+
+ CHECK_ZERO(c_heap_insert (h, &values[6] /* = 0 */));
+ CHECK_ZERO(c_heap_insert (h, &values[3] /* = 1 */));
+ CHECK_ZERO(c_heap_insert (h, &values[8] /* = 2 */));
+ CHECK_ZERO(c_heap_insert (h, &values[4] /* = 3 */));
+ CHECK_ZERO(c_heap_insert (h, &values[5] /* = 4 */));
+
+ for (i = 0; i < 10; i++)
+ {
+ int *ret = NULL;
+ CHECK_NOT_NULL(ret = c_heap_get_root(h));
+ OK(*ret == i);
+ }
+
+ c_heap_destroy(h);
+ return (0);
+}
+
+int main (void)
+{
+ RUN_TEST(simple);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
{
llentry_t *prev;
+ if ((l == NULL) || (e == NULL))
+ return;
+
prev = l->head;
while ((prev != NULL) && (prev->next != e))
prev = prev->next;
#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 */
--- /dev/null
+/**
+ * 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"
+
+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]);
+ STREQ(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);
+ STREQ(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 : */
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;
}
--- /dev/null
+/**
+ * collectd - src/tests/mock/utils_time.c
+ * Copyright (C) 2013 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 "utils_time.h"
+
+cdtime_t cdtime (void)
+{
+ return ((cdtime_t) 1542455354518929408ULL);
+}
+
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 = */ 0,
/* user_data = */ &ud);
free (name);
}
uint64_t blk_reserved;
uint64_t blk_used;
- if (ignorelist_match (il_device,
- (mnt_ptr->spec_device != NULL)
- ? mnt_ptr->spec_device
- : mnt_ptr->device))
+ char const *dev = (mnt_ptr->spec_device != NULL)
+ ? mnt_ptr->spec_device
+ : mnt_ptr->device;
+
+ if (ignorelist_match (il_device, dev))
continue;
if (ignorelist_match (il_mountpoint, mnt_ptr->dir))
continue;
if (by_device)
{
/* eg, /dev/hda1 -- strip off the "/dev/" */
- if (strncmp (mnt_ptr->spec_device, "/dev/", strlen ("/dev/")) == 0)
- sstrncpy (disk_name, mnt_ptr->spec_device + strlen ("/dev/"), sizeof (disk_name));
+ if (strncmp (dev, "/dev/", strlen ("/dev/")) == 0)
+ sstrncpy (disk_name, dev + strlen ("/dev/"), sizeof (disk_name));
else
- sstrncpy (disk_name, mnt_ptr->spec_device, sizeof (disk_name));
+ sstrncpy (disk_name, dev, sizeof (disk_name));
if (strlen(disk_name) < 1)
{
}
/* inode handling */
- if (report_inodes)
+ if (report_inodes && statbuf.f_files != 0 && statbuf.f_ffree != 0)
{
uint64_t inode_free;
uint64_t inode_reserved;
io_registry_entry_t disk;
io_registry_entry_t disk_child;
io_iterator_t disk_list;
- CFDictionaryRef props_dict;
+ CFMutableDictionaryRef props_dict, child_dict;
CFDictionaryRef stats_dict;
- CFDictionaryRef child_dict;
CFStringRef tmp_cf_string_ref;
kern_return_t status;
- signed long long read_ops;
- signed long long read_byt;
- signed long long read_tme;
- signed long long write_ops;
- signed long long write_byt;
- signed long long write_tme;
+ signed long long read_ops, read_byt, read_tme;
+ signed long long write_ops, write_byt, write_tme;
- int disk_major;
- int disk_minor;
+ int disk_major, disk_minor;
char disk_name[DATA_MAX_NAME_LEN];
- char disk_name_bsd[DATA_MAX_NAME_LEN];
+ char child_disk_name_bsd[DATA_MAX_NAME_LEN], props_disk_name_bsd[DATA_MAX_NAME_LEN];
/* Get the list of all disk objects. */
- if (IOServiceGetMatchingServices (io_master_port,
- IOServiceMatching (kIOBlockStorageDriverClass),
- &disk_list) != kIOReturnSuccess)
- {
+ if (IOServiceGetMatchingServices (io_master_port, IOServiceMatching (kIOBlockStorageDriverClass), &disk_list) != kIOReturnSuccess) {
ERROR ("disk plugin: IOServiceGetMatchingServices failed.");
return (-1);
}
- while ((disk = IOIteratorNext (disk_list)) != 0)
- {
+ while ((disk = IOIteratorNext (disk_list)) != 0) {
props_dict = NULL;
stats_dict = NULL;
child_dict = NULL;
- /* `disk_child' must be released */
- if ((status = IORegistryEntryGetChildEntry (disk, kIOServicePlane, &disk_child))
- != kIOReturnSuccess)
- {
- /* This fails for example for DVD/CD drives.. */
+ /* get child of disk entry and corresponding property dictionary */
+ if ((status = IORegistryEntryGetChildEntry (disk, kIOServicePlane, &disk_child)) != kIOReturnSuccess) {
+ /* This fails for example for DVD/CD drives, which we want to ignore anyway */
DEBUG ("IORegistryEntryGetChildEntry (disk) failed: 0x%08x", status);
IOObjectRelease (disk);
continue;
}
-
- /* We create `props_dict' => we need to release it later */
- if (IORegistryEntryCreateCFProperties (disk,
- (CFMutableDictionaryRef *) &props_dict,
- kCFAllocatorDefault,
- kNilOptions)
- != kIOReturnSuccess)
- {
- ERROR ("disk-plugin: IORegistryEntryCreateCFProperties failed.");
+ if (IORegistryEntryCreateCFProperties (disk_child, (CFMutableDictionaryRef *) &child_dict, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess || child_dict == NULL) {
+ ERROR ("disk plugin: IORegistryEntryCreateCFProperties (disk_child) failed.");
IOObjectRelease (disk_child);
IOObjectRelease (disk);
continue;
}
- if (props_dict == NULL)
- {
- DEBUG ("IORegistryEntryCreateCFProperties (disk) failed.");
- IOObjectRelease (disk_child);
- IOObjectRelease (disk);
- continue;
+ /* extract name and major/minor numbers */
+ memset (child_disk_name_bsd, 0, sizeof (child_disk_name_bsd));
+ tmp_cf_string_ref = (CFStringRef) CFDictionaryGetValue (child_dict, CFSTR(kIOBSDNameKey));
+ if (tmp_cf_string_ref) {
+ assert (CFGetTypeID (tmp_cf_string_ref) == CFStringGetTypeID ());
+ CFStringGetCString (tmp_cf_string_ref, child_disk_name_bsd, sizeof (child_disk_name_bsd), kCFStringEncodingUTF8);
}
+ disk_major = (int) dict_get_value (child_dict, kIOBSDMajorKey);
+ disk_minor = (int) dict_get_value (child_dict, kIOBSDMinorKey);
+ DEBUG ("disk plugin: child_disk_name_bsd=\"%s\" major=%d minor=%d", child_disk_name_bsd, disk_major, disk_minor);
+ CFRelease (child_dict);
+ IOObjectRelease (disk_child);
- /* tmp_cf_string_ref doesn't need to be released. */
- tmp_cf_string_ref = (CFStringRef) CFDictionaryGetValue (props_dict,
- CFSTR(kIOBSDNameKey));
- if (!tmp_cf_string_ref)
- {
- DEBUG ("disk plugin: CFDictionaryGetValue("
- "kIOBSDNameKey) failed.");
- CFRelease (props_dict);
- IOObjectRelease (disk_child);
+ /* get property dictionary of the disk entry itself */
+ if (IORegistryEntryCreateCFProperties (disk, (CFMutableDictionaryRef *) &props_dict, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess || props_dict == NULL) {
+ ERROR ("disk-plugin: IORegistryEntryCreateCFProperties failed.");
IOObjectRelease (disk);
continue;
}
- assert (CFGetTypeID (tmp_cf_string_ref) == CFStringGetTypeID ());
- memset (disk_name_bsd, 0, sizeof (disk_name_bsd));
- CFStringGetCString (tmp_cf_string_ref,
- disk_name_bsd, sizeof (disk_name_bsd),
- kCFStringEncodingUTF8);
- if (disk_name_bsd[0] == 0)
- {
- ERROR ("disk plugin: CFStringGetCString() failed.");
- CFRelease (props_dict);
- IOObjectRelease (disk_child);
- IOObjectRelease (disk);
- continue;
+ /* extract name and stats dictionary */
+ memset (props_disk_name_bsd, 0, sizeof (props_disk_name_bsd));
+ tmp_cf_string_ref = (CFStringRef) CFDictionaryGetValue (props_dict, CFSTR(kIOBSDNameKey));
+ if (tmp_cf_string_ref) {
+ assert (CFGetTypeID (tmp_cf_string_ref) == CFStringGetTypeID ());
+ CFStringGetCString (tmp_cf_string_ref, props_disk_name_bsd, sizeof (props_disk_name_bsd), kCFStringEncodingUTF8);
}
- DEBUG ("disk plugin: disk_name_bsd = \"%s\"", disk_name_bsd);
-
- stats_dict = (CFDictionaryRef) CFDictionaryGetValue (props_dict,
- CFSTR (kIOBlockStorageDriverStatisticsKey));
-
- if (stats_dict == NULL)
- {
- DEBUG ("disk plugin: CFDictionaryGetValue ("
- "%s) failed.",
- kIOBlockStorageDriverStatisticsKey);
+ stats_dict = (CFDictionaryRef) CFDictionaryGetValue (props_dict, CFSTR (kIOBlockStorageDriverStatisticsKey));
+ if (stats_dict == NULL) {
+ ERROR ("disk plugin: CFDictionaryGetValue (%s) failed.", kIOBlockStorageDriverStatisticsKey);
CFRelease (props_dict);
- IOObjectRelease (disk_child);
IOObjectRelease (disk);
continue;
}
-
- if (IORegistryEntryCreateCFProperties (disk_child,
- (CFMutableDictionaryRef *) &child_dict,
- kCFAllocatorDefault,
- kNilOptions)
- != kIOReturnSuccess)
- {
- DEBUG ("disk plugin: IORegistryEntryCreateCFProperties ("
- "disk_child) failed.");
- IOObjectRelease (disk_child);
- CFRelease (props_dict);
- IOObjectRelease (disk);
- continue;
+ DEBUG ("disk plugin: props_disk_name_bsd=\"%s\"", props_disk_name_bsd);
+
+ /* choose name */
+ if (use_bsd_name) {
+ if (child_disk_name_bsd[0] != 0)
+ sstrncpy (disk_name, child_disk_name_bsd, sizeof (disk_name));
+ else if (props_disk_name_bsd[0] != 0)
+ sstrncpy (disk_name, props_disk_name_bsd, sizeof (disk_name));
+ else {
+ ERROR ("disk plugin: can't find bsd disk name.");
+ ssnprintf (disk_name, sizeof (disk_name), "%i-%i", disk_major, disk_minor);
+ }
}
-
- /* kIOBSDNameKey */
- disk_major = (int) dict_get_value (child_dict,
- kIOBSDMajorKey);
- disk_minor = (int) dict_get_value (child_dict,
- kIOBSDMinorKey);
- read_ops = dict_get_value (stats_dict,
- kIOBlockStorageDriverStatisticsReadsKey);
- read_byt = dict_get_value (stats_dict,
- kIOBlockStorageDriverStatisticsBytesReadKey);
- read_tme = dict_get_value (stats_dict,
- kIOBlockStorageDriverStatisticsTotalReadTimeKey);
- write_ops = dict_get_value (stats_dict,
- kIOBlockStorageDriverStatisticsWritesKey);
- write_byt = dict_get_value (stats_dict,
- kIOBlockStorageDriverStatisticsBytesWrittenKey);
- /* This property describes the number of nanoseconds spent
- * performing writes since the block storage driver was
- * instantiated. It is one of the statistic entries listed
- * under the top-level kIOBlockStorageDriverStatisticsKey
- * property table. It has an OSNumber value. */
- write_tme = dict_get_value (stats_dict,
- kIOBlockStorageDriverStatisticsTotalWriteTimeKey);
-
- if (use_bsd_name)
- sstrncpy (disk_name, disk_name_bsd, sizeof (disk_name));
else
- ssnprintf (disk_name, sizeof (disk_name), "%i-%i",
- disk_major, disk_minor);
- DEBUG ("disk plugin: disk_name = \"%s\"", disk_name);
+ ssnprintf (disk_name, sizeof (disk_name), "%i-%i", disk_major, disk_minor);
+
+ /* extract the stats */
+ read_ops = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsReadsKey);
+ read_byt = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsBytesReadKey);
+ read_tme = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsTotalReadTimeKey);
+ write_ops = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsWritesKey);
+ write_byt = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsBytesWrittenKey);
+ write_tme = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsTotalWriteTimeKey);
+ CFRelease (props_dict);
+ IOObjectRelease (disk);
+ /* and submit */
+ DEBUG ("disk plugin: disk_name = \"%s\"", disk_name);
if ((read_byt != -1LL) || (write_byt != -1LL))
disk_submit (disk_name, "disk_octets", read_byt, write_byt);
if ((read_ops != -1LL) || (write_ops != -1LL))
disk_submit (disk_name, "disk_ops", read_ops, write_ops);
if ((read_tme != -1LL) || (write_tme != -1LL))
- disk_submit (disk_name, "disk_time",
- read_tme / 1000,
- write_tme / 1000);
+ disk_submit (disk_name, "disk_time", read_tme / 1000, write_tme / 1000);
- CFRelease (child_dict);
- IOObjectRelease (disk_child);
- CFRelease (props_dict);
- IOObjectRelease (disk);
}
IOObjectRelease (disk_list);
/* #endif HAVE_IOKIT_IOKITLIB_H */
collector_t *this = (collector_t *)arg;
while (1) {
- int loop = 1;
-
conn_t *connection;
pthread_mutex_lock (&conns_mutex);
log_debug ("collect: handling connection on fd #%i",
fileno (this->socket));
- while (loop) {
+ while (42) {
/* 256 bytes ought to be enough for anybody ;-) */
char line[256 + 1]; /* line + '\0' */
int len = 0;
errno = 0;
if (NULL == fgets (line, sizeof (line), this->socket)) {
- loop = 0;
-
if (0 != errno) {
char errbuf[1024];
log_err ("collect: reading from socket (fd #%i) "
else {
log_err ("collect: unknown type '%c'", line[0]);
}
- } /* while (loop) */
+ } /* while (42) */
log_debug ("Shutting down connection on fd #%i",
fileno (this->socket));
return (0);
} /* int email_init */
-static int email_shutdown (void)
+static void type_list_free (type_list_t *t)
{
- type_t *ptr = NULL;
+ type_t *this;
+ this = t->head;
+ while (this != NULL)
+ {
+ type_t *next = this->next;
+
+ sfree (this->name);
+ sfree (this);
+
+ this = next;
+ }
+
+ t->head = NULL;
+ t->tail = NULL;
+}
+
+static int email_shutdown (void)
+{
int i = 0;
if (connector != ((pthread_t) 0)) {
pthread_mutex_unlock (&conns_mutex);
- for (ptr = list_count.head; NULL != ptr; ptr = ptr->next) {
- free (ptr->name);
- free (ptr);
- }
-
- for (ptr = list_count_copy.head; NULL != ptr; ptr = ptr->next) {
- free (ptr->name);
- free (ptr);
- }
-
- for (ptr = list_size.head; NULL != ptr; ptr = ptr->next) {
- free (ptr->name);
- free (ptr);
- }
-
- for (ptr = list_size_copy.head; NULL != ptr; ptr = ptr->next) {
- free (ptr->name);
- free (ptr);
- }
-
- for (ptr = list_check.head; NULL != ptr; ptr = ptr->next) {
- free (ptr->name);
- free (ptr);
- }
-
- for (ptr = list_check_copy.head; NULL != ptr; ptr = ptr->next) {
- free (ptr->name);
- free (ptr);
- }
+ type_list_free (&list_count);
+ type_list_free (&list_count_copy);
+ type_list_free (&list_size);
+ type_list_free (&list_size_copy);
+ type_list_free (&list_check);
+ type_list_free (&list_check_copy);
unlink ((NULL == sock_file) ? SOCK_PATH : sock_file);
exit (-1);
}
- status = execvp (pl->exec, pl->argv);
+ execvp (pl->exec, pl->argv);
ERROR ("exec plugin: Failed to execute ``%s'': %s",
pl->exec, sstrerror (errno, errbuf, sizeof (errbuf)));
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)
struct addrinfo *ai_ptr;
int ai_return;
- socket_entry_t *sockets;
- size_t sockets_num;
+ socket_entry_t *sockets = NULL;
+ size_t sockets_num = 0;
int status;
-
- sockets = *ret_sockets;
- sockets_num = *ret_sockets_num;
+
+ if (*ret_sockets != NULL)
+ return (EINVAL);
memset (&ai_hints, 0, sizeof (ai_hints));
ai_hints.ai_flags = 0;
freeaddrinfo (ai_list);
- if ((*ret_sockets_num) >= sockets_num)
+ if (sockets_num == 0)
+ {
+ sfree (sockets);
return (-1);
+ }
*ret_sockets = sockets;
*ret_sockets_num = sockets_num;
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);
}
if ((map->ds_type == DS_TYPE_COUNTER)
|| (map->ds_type == DS_TYPE_ABSOLUTE))
val_copy = value_counter;
- if (map->ds_type == DS_TYPE_GAUGE)
+ else if (map->ds_type == DS_TYPE_GAUGE)
val_copy = value_gauge;
else if (map->ds_type == DS_TYPE_DERIVE)
val_copy = value_derive;
(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)))
+ {
+ free (dests);
return;
+ }
cipvs_submit_connections (pi, NULL, stats.conns);
cipvs_submit_if (pi, "if_packets", NULL, stats.inpkts, stats.outpkts);
static int cipvs_read (void)
{
struct ip_vs_get_services *services = NULL;
- int i = 0;
+ size_t i;
if (sockfd < 0)
return (-1);
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);
pthread_mutex_unlock (&java_callbacks_lock);
ERROR ("java plugin: cjni_callback_info_create: strdup failed.");
(*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
+ sfree (cbi);
return (NULL);
}
if (cbi->object == NULL)
{
ERROR ("java plugin: cjni_callback_info_create: NewGlobalRef failed.");
- free (cbi);
+ sfree (cbi->name);
+ sfree (cbi);
return (NULL);
}
if (cbi->class == NULL)
{
ERROR ("java plugin: cjni_callback_info_create: GetObjectClass failed.");
- free (cbi);
+ (*jvm_env)->DeleteGlobalRef (jvm_env, cbi->object);
+ sfree (cbi->name);
+ sfree (cbi);
return (NULL);
}
ERROR ("java plugin: cjni_callback_info_create: "
"Cannot find the `%s' method with signature `%s'.",
method_name, method_signature);
- free (cbi);
+ (*jvm_env)->DeleteGlobalRef (jvm_env, cbi->object);
+ sfree (cbi->name);
+ sfree (cbi);
return (NULL);
}
* 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);
if (fd < 0)
{
status = errno;
- fd = -1;
continue;
}
{
status = errno;
close (fd);
- fd = -1;
continue;
}
{
status = errno;
close (fd);
- fd = -1;
continue;
}
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))
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;
/* 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
noinst_LTLIBRARIES = liboconfig.la
-liboconfig_la_LDFLAGS = -version-info 0:0:0 $(LEXLIB)
+liboconfig_la_LDFLAGS = -avoid-version $(LEXLIB)
liboconfig_la_SOURCES = oconfig.c oconfig.h aux_types.h scanner.l parser.y
#include "oconfig.h"
extern FILE *yyin;
+extern int yyparse (void);
oconfig_item_t *ci_root;
const char *c_file;
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");
/* Lexer variables */
extern int yylineno;
extern char *yytext;
+extern int yylex (void);
extern oconfig_item_t *ci_root;
extern char *c_file;
*/
%{
+/* lex and yacc do some weird stuff, so turn off some warnings. */
+#if defined(__clang__)
+# pragma clang diagnostic ignored "-Wunused-function"
+# pragma clang diagnostic ignored "-Wunneeded-internal-declaration"
+#endif
+
#include <stdlib.h>
#include "oconfig.h"
#include "aux_types.h"
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;
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));
{
int num_counters;
int num_empty;
- int i;
+ size_t i;
if ((user_data == NULL) || (*user_data == NULL))
return (-1);
*/
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);
} /* while (status == 0) */
if (status != 0)
+ {
+ cmc_web_match_free (match);
return (status);
+ }
match->match = match_create_simple (match->regex, match->exclude_regex,
match->dstype);
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 */
uint16_t values[2];
int values_num;
const data_set_t *ds;
- int status;
+ int status = 0;
if ((host == NULL) || (slave == NULL) || (data == NULL))
return (EINVAL);
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);
else
values_num = 1;
- status = 0;
if (host->connection == NULL)
{
status = EBADF;
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
- status = 0;
if (strcasecmp ("Type", child->key) == 0)
status = cf_util_get_string_buffer (child,
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
- status = 0;
if (strcasecmp ("Instance", child->key) == 0)
status = cf_util_get_string_buffer (child,
{
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
--- /dev/null
+/**
+ * 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,
+ "plugin mqtt: 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;
+
+ 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;
+
+ 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 : */
plugin_register_complex_read (/* group = */ NULL, cb_name,
mysql_read,
- /* interval = */ NULL, &ud);
+ /* interval = */ 0, &ud);
}
else
{
else if (strcmp (key, "Innodb_buffer_pool_pages_dirty") == 0)
gauge_submit ("mysql_bpool_pages", "dirty", val, db);
else if (strcmp (key, "Innodb_buffer_pool_pages_flushed") == 0)
- counter_submit ("mysql_bpool_pages", "flushed", val, db);
+ counter_submit ("mysql_bpool_counters", "pages_flushed", val, db);
else if (strcmp (key, "Innodb_buffer_pool_pages_free") == 0)
gauge_submit ("mysql_bpool_pages", "free", val, db);
else if (strcmp (key, "Innodb_buffer_pool_pages_misc") == 0)
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);
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);
if (type == SOCKENT_TYPE_SERVER)
{
se->data.server.fd = NULL;
+ se->data.server.fd_num = 0;
#if HAVE_LIBGCRYPT
se->data.server.security_level = SECURITY_LEVEL_NONE;
se->data.server.auth_file = NULL;
if (se == NULL)
return (-1);
+ assert (se->data.server.fd == NULL);
+ assert (se->data.server.fd_num == 0);
+
node = se->node;
service = se->service;
char buffer[network_config_packet_size];
int buffer_len;
- int i;
- int status;
+ size_t i;
+ int status = 0;
receive_list_entry_t *private_list_head;
receive_list_entry_t *private_list_tail;
uint64_t private_list_length;
- assert (listen_sockets_num > 0);
+ assert (listen_sockets_num > 0);
private_list_head = NULL;
private_list_tail = NULL;
while (listen_loop == 0)
{
status = poll (listen_sockets_pollfd, listen_sockets_num, -1);
-
if (status <= 0)
{
char errbuf[1024];
if (errno == EINTR)
continue;
- ERROR ("poll failed: %s",
+ ERROR ("network plugin: poll(2) failed: %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
+ break;
}
for (i = 0; (i < listen_sockets_num) && (status > 0); i++)
if (buffer_len < 0)
{
char errbuf[1024];
- ERROR ("recv failed: %s",
- sstrerror (errno, errbuf,
- sizeof (errbuf)));
- return (-1);
+ status = (errno != 0) ? errno : -1;
+ ERROR ("network plugin: recv(2) failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ break;
}
stats_octets_rx += ((uint64_t) buffer_len);
if (ent == NULL)
{
ERROR ("network plugin: malloc failed.");
- return (-1);
+ status = ENOMEM;
+ break;
}
memset (ent, 0, sizeof (receive_list_entry_t));
ent->data = malloc (network_config_packet_size);
{
sfree (ent);
ERROR ("network plugin: malloc failed.");
- return (-1);
+ status = ENOMEM;
+ break;
}
ent->fd = listen_sockets_pollfd[i].fd;
ent->next = NULL;
private_list_tail = NULL;
private_list_length = 0;
}
+
+ status = 0;
} /* for (listen_sockets_pollfd) */
+
+ if (status != 0)
+ break;
} /* while (listen_loop == 0) */
/* Make sure everything is dispatched before exiting. */
receive_list_tail = private_list_tail;
receive_list_length += private_list_length;
- private_list_head = NULL;
- private_list_tail = NULL;
- private_list_length = 0;
-
pthread_cond_signal (&receive_list_cond);
pthread_mutex_unlock (&receive_list_lock);
}
- return (0);
+ return (status);
} /* }}} int network_receive */
static void *receive_thread (void __attribute__((unused)) *arg)
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);
case 42:
case 44:
proc40_names_num = 36;
+ break;
case 46:
case 47:
case 51:
"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.. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
(items_num + pkt_item_num) * res_item_size);
if (items == NULL)
{
- items = *res_data;
ERROR ("ntpd plugin: realloc failed.");
continue;
}
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));
if (endptr == NULL)
{
ERROR ("onewire plugin: Buffer is not a number: %s", buffer);
- status = -1;
continue;
}
if (endptr == NULL)
{
ERROR ("onewire plugin: Buffer is not a number: %s", buffer);
- status = -1;
continue;
}
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);
{
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);
st->name, st->url);
status = -1;
}
- else
+
+ if ((status == 0) && (ludpp->lud_host != NULL))
{
st->host = strdup (ludpp->lud_host);
}
status = plugin_register_complex_read (/* group = */ NULL,
/* name = */ callback_name,
/* callback = */ cldap_read_host,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user_data = */ &ud);
}
post_compress = 0;
pre_decompress = 0;
post_decompress = 0;
- overhead_rx = 0;
- overhead_tx = 0;
while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
static int openvpn_read (void)
{
FILE *fh;
- int i, vpn_read, read;
+ int i, read;
- vpn_read = read = 0;
+ read = 0;
/* call the right read function for every status entry in the list */
for (i = 0; i < vpn_num; i++)
{
+ int vpn_read = 0;
+
fh = fopen (vpn_list[i]->file, "r");
if (fh == NULL)
{
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;
}
if (NULL == (tmp = hv_fetch (hash, "value", 5, 0))) {
log_warn ("av2notification_meta: Skipping invalid "
"meta information.");
- free ((*m)->name);
free (*m);
continue;
}
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)
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
* `ts_wait'. */
time_calc (&ts_wait, &ts_int, &tv_begin, &tv_end);
- status = pthread_cond_timedwait (&ping_cond, &ping_lock, &ts_wait);
+ pthread_cond_timedwait (&ping_cond, &ping_lock, &ts_wait);
if (ping_thread_loop <= 0)
break;
} /* while (ping_thread_loop > 0) */
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;
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;
timeout.tv_sec=5;
timeout.tv_usec=0;
status = setsockopt (sd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof (timeout));
+ if (status != 0)
+ {
+ FUNC_ERROR ("setsockopt");
+ close (sd);
+ return (-1);
+ }
status = connect (sd, (struct sockaddr *) &item->sockaddr,
sizeof (item->sockaddr));
buffer[buffer_size] = 0;
} /* while (42) */
close (sd);
- sd = -1;
if (status < 0)
{
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';
}
}
return (0);
} /* }}} int powerdns_read_recursor */
-static int powerdns_config_add_string (const char *name, /* {{{ */
- char **dest,
- oconfig_item_t *ci)
-{
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("powerdns plugin: `%s' needs exactly one string argument.",
- name);
- return (-1);
- }
-
- sfree (*dest);
- *dest = strdup (ci->values[0].value.string);
- if (*dest == NULL)
- return (-1);
-
- return (0);
-} /* }}} int powerdns_config_add_string */
-
static int powerdns_config_add_collect (list_item_t *li, /* {{{ */
oconfig_item_t *ci)
{
if (strcasecmp ("Collect", option->key) == 0)
status = powerdns_config_add_collect (item, option);
else if (strcasecmp ("Socket", option->key) == 0)
- status = powerdns_config_add_string ("Socket", &socket_temp, option);
+ status = cf_util_get_string (option, &socket_temp);
else
{
ERROR ("powerdns plugin: Option `%s' not allowed here.", option->key);
if (status != 0)
{
+ sfree (socket_temp);
sfree (item);
return (-1);
}
DEBUG ("powerdns plugin: Add server: instance = %s;", item->instance);
+ sfree (socket_temp);
return (0);
} /* }}} int powerdns_config_add_server */
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;
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;
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;
+
+ return (ps);
+} /* int *ps_read_tasks_status */
-/* Read advanced virtual memory data from /proc/pid/status */
-static procstat_t *ps_read_vmem (int pid, procstat_t *ps)
+/* 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);
}
continue;
}
+ memset (&pse, 0, sizeof (pse));
pse.id = pid;
pse.age = 0;
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;
}
} /* if (process has argument list) */
+ memset (&pse, 0, sizeof (pse));
pse.id = procs[i].p_pid;
pse.age = 0;
pse.io_syscr = -1;
pse.io_syscw = -1;
+ pse.cswitch_vol = -1;
+ pse.cswitch_invol = -1;
+
ps_list_add (procs[i].p_comm, have_cmdline ? cmdline : NULL, &pse);
} /* if ((proc_ptr == NULL) || (proc_ptr->p_pid != procs[i].p_pid)) */
continue;
}
+ memset (&pse, 0, sizeof (pse));
pse.id = pid;
pse.age = 0;
pse.io_syscr = ps.io_syscr;
pse.io_syscw = ps.io_syscw;
+ pse.cswitch_vol = -1;
+ pse.cswitch_invol = -1;
+
switch (state)
{
case 'R': running++; break;
}
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;
}
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;
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;
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);
}
}
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;
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) {
}
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. */
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);
{
int offset;
int status;
- int i;
+ size_t i;
time_t t;
assert (0 == strcmp (ds->type, vl->type));
int offset;
int status;
time_t tt;
- int i;
+ size_t i;
memset (buffer, '\0', buffer_len);
new_rc = 1;
}
+ assert (value_time > 0); /* plugin_dispatch() ensures this. */
if (rc->last_value >= value_time)
{
pthread_mutex_unlock (&cache_lock);
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);
/* Query status with libatasmart */
smart_handle_disk (devpath);
+ udev_device_unref (dev);
}
udev_enumerate_unref (enumerate);
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;
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++)
{
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
- status = 0;
if (strcasecmp ("Type", option->key) == 0)
status = cf_util_get_string(option, &dd->type);
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.");
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,
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;
return (-1);
}
assert (ds->ds_num == data->values_len);
+ assert (data->values_len > 0);
instance_list_ptr = instance_list;
- value_table_ptr = malloc (sizeof (*value_table_ptr) * data->values_len);
+ 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++)
value_table_ptr[i] = value_table[i];
- vl.values_len = ds->ds_num;
+ vl.values_len = data->values_len;
vl.values = malloc (sizeof (*vl.values) * vl.values_len);
if (vl.values == NULL)
{
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];
_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
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);
}
+ assert (data->values_len > 0);
/* We need a copy of all the OIDs, because GETNEXT will destroy them. */
memcpy (oid_list, data->values, data->values_len * sizeof (oid_t));
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,
}
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)
for (vb = res->variables, i = 0; (vb != NULL); vb = vb->next_variable, i++)
{
/* Calculate value index from todo list */
- while (!oid_list_todo[i] && (i < oid_list_len))
+ while ((i < oid_list_len) && !oid_list_todo[i])
i++;
/* An instance is configured and the res variable we process is the
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;
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;
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);
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);
}
return (0);
} /* }}} int statsd_metric_add */
+static void statsd_metric_free (statsd_metric_t *metric) /* {{{ */
+{
+ if (metric == NULL)
+ return;
+
+ if (metric->latency != NULL)
+ {
+ latency_counter_destroy (metric->latency);
+ metric->latency = NULL;
+ }
+
+ if (metric->set != NULL)
+ {
+ void *key;
+ void *value;
+
+ while (c_avl_pick (metric->set, &key, &value) == 0)
+ {
+ sfree (key);
+ assert (value == NULL);
+ }
+
+ c_avl_destroy (metric->set);
+ metric->set = NULL;
+ }
+
+ sfree (metric);
+} /* }}} void statsd_metric_free */
+
static int statsd_parse_value (char const *str, value_t *ret_value) /* {{{ */
{
char *endptr = NULL;
else if (metric->type == STATSD_TIMER)
{
size_t i;
+ _Bool have_events = (metric->updates_num > 0);
- if (metric->updates_num == 0)
- return (0);
-
+ /* Make sure all timer metrics share the *same* timestamp. */
vl.time = cdtime ();
ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"%s-average", name);
- values[0].gauge = CDTIME_T_TO_DOUBLE (
- latency_counter_get_average (metric->latency));
+ values[0].gauge = have_events
+ ? CDTIME_T_TO_DOUBLE (latency_counter_get_average (metric->latency))
+ : NAN;
plugin_dispatch_values (&vl);
if (conf_timer_lower) {
ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"%s-lower", name);
- values[0].gauge = CDTIME_T_TO_DOUBLE (
- latency_counter_get_min (metric->latency));
+ values[0].gauge = have_events
+ ? CDTIME_T_TO_DOUBLE (latency_counter_get_min (metric->latency))
+ : NAN;
plugin_dispatch_values (&vl);
}
if (conf_timer_upper) {
ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"%s-upper", name);
- values[0].gauge = CDTIME_T_TO_DOUBLE (
- latency_counter_get_max (metric->latency));
+ values[0].gauge = have_events
+ ? CDTIME_T_TO_DOUBLE (latency_counter_get_max (metric->latency))
+ : NAN;
plugin_dispatch_values (&vl);
}
if (conf_timer_sum) {
ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"%s-sum", name);
- values[0].gauge = CDTIME_T_TO_DOUBLE (
- latency_counter_get_sum (metric->latency));
+ values[0].gauge = have_events
+ ? CDTIME_T_TO_DOUBLE (latency_counter_get_sum (metric->latency))
+ : NAN;
plugin_dispatch_values (&vl);
}
{
ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"%s-percentile-%.0f", name, conf_timer_percentile[i]);
- values[0].gauge = CDTIME_T_TO_DOUBLE (
- latency_counter_get_percentile (
- metric->latency, conf_timer_percentile[i]));
+ values[0].gauge = have_events
+ ? CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (metric->latency, conf_timer_percentile[i]))
+ : NAN;
plugin_dispatch_values (&vl);
}
}
sfree (name);
- sfree (metric);
+ statsd_metric_free (metric);
}
pthread_mutex_unlock (&metrics_lock);
if (total < used)
continue;
- swap_submit_usage (path, used, total - used, NULL, NAN);
+ swap_submit_usage (path, used * 1024.0, (total - used) * 1024.0,
+ NULL, NAN);
}
fclose (fh);
if (swap_used < 0.0)
return (EINVAL);
- swap_submit_usage (NULL, swap_used, swap_free,
- isnan (swap_cached) ? NULL : "cached", swap_cached);
+ swap_submit_usage (NULL, swap_used * 1024.0, swap_free * 1024.0,
+ isnan (swap_cached) ? NULL : "cached",
+ isnan (swap_cached) ? NAN : swap_cached * 1024.0);
return (0);
} /* }}} int swap_read_combined */
*/
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"))
if (NULL == tbl->sep) {
log_err ("Table \"%s\" does not specify any separator.", tbl->file);
status = 1;
+ } else {
+ strunescape (tbl->sep, strlen (tbl->sep) + 1);
}
- strunescape (tbl->sep, strlen (tbl->sep) + 1);
if (NULL == tbl->instance) {
tbl->instance = sstrdup (tbl->file);
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;
cdtime_t interval = 0;
char *plugin_instance = NULL;
int num_matches = 0;
- int status;
int i;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
return (-1);
}
- status = 0;
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
+ int status = 0;
if (strcasecmp ("Instance", option->key) == 0)
status = cf_util_get_string (option, &plugin_instance);
static int ctail_init (void)
{
- struct timespec cb_interval;
char str[255];
user_data_t ud;
size_t i;
return (-1);
}
+ memset(&ud, '\0', sizeof(ud));
+
for (i = 0; i < tail_match_list_num; 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);
#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) || (id->time_from >= fields_num))
+ assert (md->value_from >= 0);
+ if (((size_t) md->value_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));
for (i = 0; i < ci->children_num; ++i){
oconfig_item_t *option = ci->children + i;
- status = 0;
if (strcasecmp("Type", option->key) == 0)
status = cf_util_get_string(option, &md->type);
sfree(id);
}
-static int tcsv_config_add_instance_collect(instance_definition_t *id, oconfig_item_t *ci){
+static int tcsv_config_add_instance_collect(instance_definition_t *id, oconfig_item_t *ci) {
metric_definition_t *metric;
+ metric_definition_t **metric_list;
+ size_t metric_list_size;
int i;
- if (ci->values_num < 1){
+ if (ci->values_num < 1) {
WARNING("tail_csv plugin: The `Collect' config option needs at least one argument.");
return (-1);
}
- /* Verify string arguments */
- for (i = 0; i < ci->values_num; ++i)
- if (ci->values[i].type != OCONFIG_TYPE_STRING){
+ metric_list_size = id->metric_list_len + (size_t) ci->values_num;
+ metric_list = realloc (id->metric_list, sizeof (*id->metric_list) * metric_list_size);
+ if (metric_list == NULL)
+ return (-1);
+ id->metric_list = metric_list;
+
+ for (i = 0; i < ci->values_num; i++) {
+ char *metric_name;
+
+ if (ci->values[i].type != OCONFIG_TYPE_STRING) {
WARNING("tail_csv plugin: All arguments to `Collect' must be strings.");
- return (-1);
+ continue;
}
+ metric_name = ci->values[i].value.string;
- id->metric_list = (metric_definition_t **)malloc(sizeof(metric_definition_t *) * ci->values_num);
- if (id->metric_list == NULL)
- return (-1);
-
- for (i = 0; i < ci->values_num; ++i){
for (metric = metric_head; metric != NULL; metric = metric->next)
- if (strcasecmp(ci->values[i].value.string, metric->name) == 0)
+ if (strcasecmp(metric_name, metric->name) == 0)
break;
- if (metric == NULL){
- WARNING("tail_csv plugin: `Collect' argument not found `%s'.", ci->values[i].value.string);
- return (-1);
+ if (metric == NULL) {
+ WARNING ("tail_csv plugin: `Collect' argument not found `%s'.", metric_name);
+ continue;
}
- id->metric_list[i] = metric;
+ id->metric_list[id->metric_list_len] = metric;
id->metric_list_len++;
}
/* 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;
if (status != 0)
{
- tn_destroy ((void *) data);
+ tn_destroy ((void *) &data);
return (status);
}
gauge_t *rates;
int rates_failed;
- int i;
+ size_t i;
if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
return (-EINVAL);
}
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, "
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);
/* If this entry was created while reading the files (ant not when handling
* the configuration) remove it now. */
if ((pe->flags & (PORT_COLLECT_LOCAL
- | PORT_COLLECT_REMOTE
- | PORT_IS_LISTENING)) == 0)
+ | PORT_COLLECT_REMOTE
+ | PORT_IS_LISTENING)) == 0)
{
port_entry_t *next = pe->next;
DEBUG ("tcpconns plugin: Removing temporary entry "
- "for listening port %"PRIu16, pe->port);
+ "for listening port %"PRIu16, pe->port);
if (prev == NULL)
- port_list_head = next;
+ port_list_head = next;
else
- prev->next = next;
+ prev->next = next;
sfree (pe);
pe = next;
memset (pe->count_remote, '\0', sizeof (pe->count_remote));
pe->flags &= ~PORT_IS_LISTENING;
+ prev = pe;
pe = pe->next;
}
} /* void conn_reset_port_entry */
#endif
{
/* Read the pcb pointed to by `next' into `inpcb' */
- kread ((u_long) next, &inpcb, sizeof (inpcb));
+ status = kread ((u_long) next, &inpcb, sizeof (inpcb));
+ if (status != 0)
+ return (-1);
/* Advance `next' */
#if defined(__OpenBSD__) || (defined(__NetBSD_Version__) && __NetBSD_Version__ > 699002700)
continue;
#endif
- kread ((u_long) inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
+ status = kread ((u_long) inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
+ if (status != 0)
+ return (-1);
conn_handle_ports (ntohs(inpcb.inp_lport), ntohs(inpcb.inp_fport), tcpcb.t_state);
} /* while (next != head) */
/* Loop until we find the end of the package */
end_flag = 0;
- escape_flag = 0;
package_buffer_pos = 0;
while (end_flag == 0)
{
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);
--- /dev/null
+/**
+ * collectd - src/tests/macros.h
+ * 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"),
+ * 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>
+ */
+
+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 { \
+ int status; \
+ printf ("Testing %s ...\n", #func); \
+ status = test_ ## func (); \
+ printf ("%s.\n", (status == 0) ? "Success" : "FAILURE"); \
+ if (status != 0) { fail_count__++; } \
+} while (0)
+
+#define END_TEST exit ((fail_count__ == 0) ? 0 : 1);
+
+#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 { \
+ if (strcmp (expect, actual) != 0) { \
+ printf ("not ok %i - %s incorrect: expected \"%s\", got \"%s\"\n", \
+ ++check_count__, #actual, expect, actual); \
+ return (-1); \
+ } \
+ printf ("ok %i - %s evaluates to \"%s\"\n", ++check_count__, #actual, expect); \
+} while (0)
+
+#define EXPECT_INTEQ(expect, actual) do { \
+ if ((expect) != (actual)) {\
+ printf ("not ok %i - %s incorrect: expected %d, got %d\n", \
+ ++check_count__, #actual, expect, actual); \
+ return (-1); \
+ } \
+ printf ("ok %i - %s evaluates to %d\n", ++check_count__, #actual, expect); \
+} while (0)
+
+#define DBLEQ(expect, actual) do { \
+ double e = (expect); double a = (actual); \
+ if (isnan (e) && !isnan (a)) { \
+ printf ("not ok %i - %s incorrect: expected %.15g, got %.15g\n", \
+ ++check_count__, #actual, e, a); \
+ return (-1); \
+ } else if (!isnan (e) && (((e-a) < -DBL_PRECISION) || ((e-a) > DBL_PRECISION))) { \
+ printf ("not ok %i - %s incorrect: expected %.15g, got %.15g\n", \
+ ++check_count__, #actual, e, a); \
+ return (-1); \
+ } \
+ printf ("ok %i - %s evaluates to %.15g\n", ++check_count__, #actual, e); \
+} while (0)
+
+#define CHECK_NOT_NULL(expr) do { \
+ void *ptr_; \
+ ptr_ = (expr); \
+ OK1(ptr_ != NULL, #expr); \
+} while (0)
+
+#define CHECK_ZERO(expr) do { \
+ long status_; \
+ status_ = (long) (expr); \
+ OK1(status_ == 0L, #expr); \
+} while (0)
+++ /dev/null
-/**
- * collectd - src/tests/common_test.c
- * Copyright (C) 2013 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 "tests/macros.h"
-#include "common.h"
-
-DEF_TEST(sstrncpy)
-{
- char buffer[16] = "";
- char *ptr = &buffer[4];
- char *ret;
-
- buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0xff;
- buffer[12] = buffer[13] = buffer[14] = buffer[15] = 0xff;
-
- ret = sstrncpy (ptr, "foobar", 8);
- OK(ret == ptr);
- STREQ ("foobar", ptr);
- OK(buffer[3] == buffer[12]);
-
- ret = sstrncpy (ptr, "abc", 8);
- OK(ret == ptr);
- STREQ ("abc", ptr);
- OK(buffer[3] == buffer[12]);
-
- ret = sstrncpy (ptr, "collectd", 8);
- OK(ret == ptr);
- OK(ptr[7] == 0);
- STREQ ("collect", ptr);
- OK(buffer[3] == buffer[12]);
-
- return (0);
-}
-
-DEF_TEST(ssnprintf)
-{
- char buffer[16] = "";
- char *ptr = &buffer[4];
- int status;
-
- buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0xff;
- buffer[12] = buffer[13] = buffer[14] = buffer[15] = 0xff;
-
- status = ssnprintf (ptr, 8, "%i", 1337);
- OK(status == 4);
- STREQ ("1337", ptr);
-
- status = ssnprintf (ptr, 8, "%s", "collectd");
- OK(status == 8);
- OK(ptr[7] == 0);
- STREQ ("collect", ptr);
- OK(buffer[3] == buffer[12]);
-
- return (0);
-}
-
-DEF_TEST(sstrdup)
-{
- char *ptr;
-
- ptr = sstrdup ("collectd");
- OK(ptr != NULL);
- STREQ ("collectd", ptr);
-
- sfree(ptr);
- OK(ptr == NULL);
-
- ptr = sstrdup (NULL);
- OK(ptr == NULL);
-
- return (0);
-}
-
-DEF_TEST(strsplit)
-{
- char buffer[32];
- char *fields[8];
- int status;
-
- strncpy (buffer, "foo bar", sizeof (buffer));
- status = strsplit (buffer, fields, 8);
- OK(status == 2);
- STREQ ("foo", fields[0]);
- STREQ ("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]);
-
- 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]);
-
- strncpy (buffer, "\twith trailing\n", sizeof (buffer));
- status = strsplit (buffer, fields, 8);
- OK(status == 2);
- STREQ ("with", fields[0]);
- STREQ ("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]);
-
- strncpy (buffer, "single", sizeof (buffer));
- status = strsplit (buffer, fields, 8);
- OK(status == 1);
- STREQ ("single", fields[0]);
-
- strncpy (buffer, "", sizeof (buffer));
- status = strsplit (buffer, fields, 8);
- OK(status == 0);
-
- return (0);
-}
-
-DEF_TEST(strjoin)
-{
- char buffer[16];
- char *fields[4];
- int status;
-
- fields[0] = "foo";
- fields[1] = "bar";
- fields[2] = "baz";
- fields[3] = "qux";
-
- status = strjoin (buffer, sizeof (buffer), fields, 2, "!");
- OK(status == 7);
- STREQ ("foo!bar", buffer);
-
- status = strjoin (buffer, sizeof (buffer), fields, 1, "!");
- OK(status == 3);
- STREQ ("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);
-
- status = strjoin (buffer, sizeof (buffer), fields, 4, "");
- OK(status == 12);
- STREQ ("foobarbazqux", buffer);
-
- status = strjoin (buffer, sizeof (buffer), fields, 4, "!");
- OK(status == 15);
- STREQ ("foo!bar!baz!qux", buffer);
-
- fields[0] = "0123";
- fields[1] = "4567";
- fields[2] = "8901";
- fields[3] = "2345";
- status = strjoin (buffer, sizeof (buffer), fields, 4, "-");
- OK(status < 0);
-
- return (0);
-}
-
-DEF_TEST(strunescape)
-{
- char buffer[16];
- int status;
-
- strncpy (buffer, "foo\\tbar", sizeof (buffer));
- status = strunescape (buffer, sizeof (buffer));
- OK(status == 0);
- STREQ ("foo\tbar", buffer);
-
- strncpy (buffer, "\\tfoo\\r\\n", sizeof (buffer));
- status = strunescape (buffer, sizeof (buffer));
- OK(status == 0);
- STREQ ("\tfoo\r\n", buffer);
-
- strncpy (buffer, "With \\\"quotes\\\"", sizeof (buffer));
- status = strunescape (buffer, sizeof (buffer));
- OK(status == 0);
- STREQ ("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);
- return (0);
-
- /* Backslash at buffer end */
- strncpy (buffer, "\\t3\\56", sizeof (buffer));
- status = strunescape (buffer, 4);
- OK(status != 0);
- OK(buffer[0] == '\t');
- OK(buffer[1] == '3');
- OK(buffer[2] == 0);
- OK(buffer[3] == 0);
- OK(buffer[4] == '5');
- OK(buffer[5] == '6');
- OK(buffer[6] == '7');
-
- return (0);
-}
-
-int main (void)
-{
- RUN_TEST(sstrncpy);
- RUN_TEST(ssnprintf);
- RUN_TEST(sstrdup);
- RUN_TEST(strsplit);
- RUN_TEST(strjoin);
- RUN_TEST(strunescape);
-
- END_TEST;
-}
-
-/* vim: set sw=2 sts=2 et : */
+++ /dev/null
-/**
- * collectd - src/tests/macros.h
- * Copyright (C) 2013 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>
- */
-
-static int fail_count__ = 0;
-static int check_count__ = 0;
-
-#define DEF_TEST(func) static int test_##func ()
-
-#define RUN_TEST(func) do { \
- int status; \
- printf ("Testing %s ...\n", #func); \
- status = test_ ## func (); \
- printf ("%s.\n", (status == 0) ? "Success" : "FAILURE"); \
- if (status != 0) { fail_count__++; } \
-} while (0)
-
-#define END_TEST exit ((fail_count__ == 0) ? 0 : 1);
-
-#define OK1(cond, text) do { \
- _Bool result = (cond); \
- printf ("%s %i - %s\n", result ? "ok" : "not ok", ++check_count__, text); \
-} while (0)
-#define OK(cond) OK1(cond, #cond)
-
-#define STREQ(expect, actual) do { \
- if (strcmp (expect, actual) != 0) { \
- printf ("not ok %i - %s incorrect: expected \"%s\", got \"%s\"\n", \
- ++check_count__, #actual, expect, actual); \
- return (-1); \
- } \
- printf ("ok %i - %s evaluates to \"%s\"\n", ++check_count__, #actual, expect); \
-} while (0)
-
-#define CHECK_NOT_NULL(expr) do { \
- void *ptr_; \
- ptr_ = (expr); \
- OK1(ptr_ != NULL, #expr); \
-} while (0)
-
-#define CHECK_ZERO(expr) do { \
- long status_; \
- status_ = (long) (expr); \
- OK1(status_ == 0L, #expr); \
-} while (0)
+++ /dev/null
-/**
- * collectd - src/tests/mock/plugin.c
- * Copyright (C) 2013 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 "plugin.h"
-
-void plugin_log (int level, char const *format, ...)
-{
- char buffer[1024];
- va_list ap;
-
- va_start (ap, format);
- vsnprintf (buffer, sizeof (buffer), format, ap);
- va_end (ap);
-
- printf ("plugin_log (%i, \"%s\");\n", level, buffer);
-}
-
-/* vim: set sw=2 sts=2 et : */
+++ /dev/null
-/**
- * collectd - src/tests/mock/utils_cache.c
- * Copyright (C) 2013 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 "utils_cache.h"
-
-gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl)
-{
- return (NULL);
-}
+++ /dev/null
-/**
- * collectd - src/tests/mock/utils_time.c
- * Copyright (C) 2013 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 "utils_time.h"
-
-cdtime_t cdtime (void)
-{
- return (0);
-}
-
+++ /dev/null
-/**
- * collectd - src/tests/test_common.c
- * Copyright (C) 2013 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 "tests/macros.h"
-#include "common.h"
-
-DEF_TEST(sstrncpy)
-{
- char buffer[16] = "";
- char *ptr = &buffer[4];
- char *ret;
-
- buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0xff;
- buffer[12] = buffer[13] = buffer[14] = buffer[15] = 0xff;
-
- ret = sstrncpy (ptr, "foobar", 8);
- OK(ret == ptr);
- STREQ ("foobar", ptr);
- OK(buffer[3] == buffer[12]);
-
- ret = sstrncpy (ptr, "abc", 8);
- OK(ret == ptr);
- STREQ ("abc", ptr);
- OK(buffer[3] == buffer[12]);
-
- ret = sstrncpy (ptr, "collectd", 8);
- OK(ret == ptr);
- OK(ptr[7] == 0);
- STREQ ("collect", ptr);
- OK(buffer[3] == buffer[12]);
-
- return (0);
-}
-
-DEF_TEST(ssnprintf)
-{
- char buffer[16] = "";
- char *ptr = &buffer[4];
- int status;
-
- buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0xff;
- buffer[12] = buffer[13] = buffer[14] = buffer[15] = 0xff;
-
- status = ssnprintf (ptr, 8, "%i", 1337);
- OK(status == 4);
- STREQ ("1337", ptr);
-
- status = ssnprintf (ptr, 8, "%s", "collectd");
- OK(status == 8);
- OK(ptr[7] == 0);
- STREQ ("collect", ptr);
- OK(buffer[3] == buffer[12]);
-
- return (0);
-}
-
-DEF_TEST(sstrdup)
-{
- char *ptr;
-
- ptr = sstrdup ("collectd");
- OK(ptr != NULL);
- STREQ ("collectd", ptr);
-
- sfree(ptr);
- OK(ptr == NULL);
-
- ptr = sstrdup (NULL);
- OK(ptr == NULL);
-
- return (0);
-}
-
-DEF_TEST(strsplit)
-{
- char buffer[32];
- char *fields[8];
- int status;
-
- strncpy (buffer, "foo bar", sizeof (buffer));
- status = strsplit (buffer, fields, 8);
- OK(status == 2);
- STREQ ("foo", fields[0]);
- STREQ ("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]);
-
- 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]);
-
- strncpy (buffer, "\twith trailing\n", sizeof (buffer));
- status = strsplit (buffer, fields, 8);
- OK(status == 2);
- STREQ ("with", fields[0]);
- STREQ ("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]);
-
- strncpy (buffer, "single", sizeof (buffer));
- status = strsplit (buffer, fields, 8);
- OK(status == 1);
- STREQ ("single", fields[0]);
-
- strncpy (buffer, "", sizeof (buffer));
- status = strsplit (buffer, fields, 8);
- OK(status == 0);
-
- return (0);
-}
-
-DEF_TEST(strjoin)
-{
- char buffer[16];
- char *fields[4];
- int status;
-
- fields[0] = "foo";
- fields[1] = "bar";
- fields[2] = "baz";
- fields[3] = "qux";
-
- status = strjoin (buffer, sizeof (buffer), fields, 2, "!");
- OK(status == 7);
- STREQ ("foo!bar", buffer);
-
- status = strjoin (buffer, sizeof (buffer), fields, 1, "!");
- OK(status == 3);
- STREQ ("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);
-
- status = strjoin (buffer, sizeof (buffer), fields, 4, "");
- OK(status == 12);
- STREQ ("foobarbazqux", buffer);
-
- status = strjoin (buffer, sizeof (buffer), fields, 4, "!");
- OK(status == 15);
- STREQ ("foo!bar!baz!qux", buffer);
-
- fields[0] = "0123";
- fields[1] = "4567";
- fields[2] = "8901";
- fields[3] = "2345";
- status = strjoin (buffer, sizeof (buffer), fields, 4, "-");
- OK(status < 0);
-
- return (0);
-}
-
-DEF_TEST(strunescape)
-{
- char buffer[16];
- int status;
-
- strncpy (buffer, "foo\\tbar", sizeof (buffer));
- status = strunescape (buffer, sizeof (buffer));
- OK(status == 0);
- STREQ ("foo\tbar", buffer);
-
- strncpy (buffer, "\\tfoo\\r\\n", sizeof (buffer));
- status = strunescape (buffer, sizeof (buffer));
- OK(status == 0);
- STREQ ("\tfoo\r\n", buffer);
-
- strncpy (buffer, "With \\\"quotes\\\"", sizeof (buffer));
- status = strunescape (buffer, sizeof (buffer));
- OK(status == 0);
- STREQ ("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);
- return (0);
-
- /* Backslash at buffer end */
- strncpy (buffer, "\\t3\\56", sizeof (buffer));
- status = strunescape (buffer, 4);
- OK(status != 0);
- OK(buffer[0] == '\t');
- OK(buffer[1] == '3');
- OK(buffer[2] == 0);
- OK(buffer[3] == 0);
- OK(buffer[4] == '5');
- OK(buffer[5] == '6');
- OK(buffer[6] == '7');
-
- return (0);
-}
-
-int main (void)
-{
- RUN_TEST(sstrncpy);
- RUN_TEST(ssnprintf);
- RUN_TEST(sstrdup);
- RUN_TEST(strsplit);
- RUN_TEST(strjoin);
- RUN_TEST(strunescape);
-
- END_TEST;
-}
-
-/* vim: set sw=2 sts=2 et : */
+++ /dev/null
-/**
- * collectd - src/tests/test_utils_avltree.c
- * Copyright (C) 2013 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 "tests/macros.h"
-#include "collectd.h"
-#include "utils_avltree.h"
-
-static int compare_total_count = 0;
-#define RESET_COUNTS() do { compare_total_count = 0; } while (0)
-
-static int compare_callback (void const *v0, void const *v1)
-{
- assert (v0 != NULL);
- assert (v1 != NULL);
-
- compare_total_count++;
- return (strcmp (v0, v1));
-}
-
-DEF_TEST(success)
-{
- c_avl_tree_t *t;
- char key_orig[] = "foo";
- char value_orig[] = "bar";
- char *key_ret = NULL;
- char *value_ret = NULL;
-
- RESET_COUNTS ();
- t = c_avl_create (compare_callback);
- OK (t != NULL);
-
- OK (c_avl_insert (t, key_orig, value_orig) == 0);
- OK (c_avl_size (t) == 1);
-
- /* Key already exists. */
- OK (c_avl_insert (t, "foo", "qux") > 0);
-
- OK (c_avl_get (t, "foo", (void *) &value_ret) == 0);
- OK (value_ret == &value_orig[0]);
-
- key_ret = value_ret = NULL;
- OK (c_avl_remove (t, "foo", (void *) &key_ret, (void *) &value_ret) == 0);
- OK (key_ret == &key_orig[0]);
- OK (value_ret == &value_orig[0]);
- OK (c_avl_size (t) == 0);
-
- c_avl_destroy (t);
-
- return (0);
-}
-
-int main (void)
-{
- RUN_TEST(success);
-
- END_TEST;
-}
-
-/* vim: set sw=2 sts=2 et : */
+++ /dev/null
-/**
- * collectd - src/tests/test_utils_heap.c
- * Copyright (C) 2013 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 "collectd.h"
-#include "tests/macros.h"
-#include "utils_heap.h"
-
-static int compare (void const *v0, void const *v1)
-{
- int const *i0 = v0;
- int const *i1 = v1;
-
- if ((*i0) < (*i1))
- return -1;
- else if ((*i0) > (*i1))
- return 1;
- else
- return 0;
-}
-
-DEF_TEST(simple)
-{
- int values[] = { 9, 5, 6, 1, 3, 4, 0, 8, 2, 7 };
- int i;
- c_heap_t *h;
-
- CHECK_NOT_NULL(h = c_heap_create (compare));
- for (i = 0; i < 10; i++)
- CHECK_ZERO(c_heap_insert (h, &values[i]));
-
- for (i = 0; i < 5; i++)
- {
- int *ret = NULL;
- CHECK_NOT_NULL(ret = c_heap_get_root(h));
- OK(*ret == i);
- }
-
- CHECK_ZERO(c_heap_insert (h, &values[6] /* = 0 */));
- CHECK_ZERO(c_heap_insert (h, &values[3] /* = 1 */));
- CHECK_ZERO(c_heap_insert (h, &values[8] /* = 2 */));
- CHECK_ZERO(c_heap_insert (h, &values[4] /* = 3 */));
- CHECK_ZERO(c_heap_insert (h, &values[5] /* = 4 */));
-
- for (i = 0; i < 10; i++)
- {
- int *ret = NULL;
- CHECK_NOT_NULL(ret = c_heap_get_root(h));
- OK(*ret == i);
- }
-
- c_heap_destroy(h);
- return (0);
-}
-
-int main (void)
-{
- RUN_TEST(simple);
-
- END_TEST;
-}
-
-/* vim: set sw=2 sts=2 et : */
+++ /dev/null
-/**
- * collectd - src/tests/test_utils_mount.c
- * Copyright (C) 2013 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 "tests/macros.h"
-#include "collectd.h"
-#include "utils_mount.h"
-
-DEF_TEST(cu_mount_checkoption)
-{
- char line_opts[] = "foo=one,bar=two,qux=three";
- char *foo = strstr (line_opts, "foo");
- char *bar = strstr (line_opts, "bar");
- char *qux = strstr (line_opts, "qux");
-
- char line_bool[] = "one,two,three";
- char *one = strstr (line_bool, "one");
- char *two = strstr (line_bool, "two");
- char *three = strstr (line_bool, "three");
-
- /* Normal operation */
- OK (foo == cu_mount_checkoption (line_opts, "foo", 0));
- OK (bar == cu_mount_checkoption (line_opts, "bar", 0));
- OK (qux == cu_mount_checkoption (line_opts, "qux", 0));
- OK (NULL == cu_mount_checkoption (line_opts, "unknown", 0));
-
- OK (one == cu_mount_checkoption (line_bool, "one", 0));
- OK (two == cu_mount_checkoption (line_bool, "two", 0));
- OK (three == cu_mount_checkoption (line_bool, "three", 0));
- OK (NULL == cu_mount_checkoption (line_bool, "four", 0));
-
- /* Shorter and longer parts */
- OK (foo == cu_mount_checkoption (line_opts, "fo", 0));
- OK (bar == cu_mount_checkoption (line_opts, "bar=", 0));
- OK (qux == cu_mount_checkoption (line_opts, "qux=thr", 0));
-
- OK (one == cu_mount_checkoption (line_bool, "o", 0));
- OK (two == cu_mount_checkoption (line_bool, "tw", 0));
- OK (three == cu_mount_checkoption (line_bool, "thr", 0));
-
- /* "full" flag */
- OK (one == cu_mount_checkoption (line_bool, "one", 1));
- OK (two == cu_mount_checkoption (line_bool, "two", 1));
- OK (three == cu_mount_checkoption (line_bool, "three", 1));
- OK (NULL == cu_mount_checkoption (line_bool, "four", 1));
-
- OK (NULL == cu_mount_checkoption (line_bool, "o", 1));
- OK (NULL == cu_mount_checkoption (line_bool, "tw", 1));
- OK (NULL == cu_mount_checkoption (line_bool, "thr", 1));
-
- return (0);
-}
-DEF_TEST(cu_mount_getoptionvalue)
-{
- 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="));
- 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"));
- OK (NULL == cu_mount_getoptionvalue (line_bool, "four"));
-
- return (0);
-}
-
-int main (void)
-{
- RUN_TEST(cu_mount_checkoption);
- RUN_TEST(cu_mount_getoptionvalue);
-
- END_TEST;
-}
-
-/* vim: set sw=2 sts=2 et : */
+++ /dev/null
-/**
- * collectd - src/tests/test_utils_vl_lookup.c
- * Copyright (C) 2012 Florian 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 Forster <octo at collectd.org>
- **/
-
-#include "tests/macros.h"
-#include "collectd.h"
-#include "utils_vl_lookup.h"
-
-static _Bool expect_new_obj = 0;
-static _Bool have_new_obj = 0;
-
-static identifier_t last_class_ident;
-static identifier_t last_obj_ident;
-
-static data_source_t dsrc_test = { "value", DS_TYPE_DERIVE, 0.0, NAN };
-static data_set_t const ds_test = { "test", 1, &dsrc_test };
-
-static data_source_t dsrc_unknown = { "value", DS_TYPE_DERIVE, 0.0, NAN };
-static data_set_t const ds_unknown = { "unknown", 1, &dsrc_unknown };
-
-static int lookup_obj_callback (data_set_t const *ds,
- value_list_t const *vl,
- void *user_class, void *user_obj)
-{
- identifier_t *class = user_class;
- identifier_t *obj = user_obj;
-
- OK1(expect_new_obj == have_new_obj,
- (expect_new_obj ? "New obj is created." : "Updating existing obj."));
-
- memcpy (&last_class_ident, class, sizeof (last_class_ident));
- memcpy (&last_obj_ident, obj, sizeof (last_obj_ident));
-
- if (strcmp (obj->plugin_instance, "failure") == 0)
- return (-1);
-
- return (0);
-}
-
-static void *lookup_class_callback (data_set_t const *ds,
- value_list_t const *vl, void *user_class)
-{
- identifier_t *class = user_class;
- identifier_t *obj;
-
- OK(expect_new_obj);
-
- memcpy (&last_class_ident, class, sizeof (last_class_ident));
-
- obj = malloc (sizeof (*obj));
- strncpy (obj->host, vl->host, sizeof (obj->host));
- strncpy (obj->plugin, vl->plugin, sizeof (obj->plugin));
- strncpy (obj->plugin_instance, vl->plugin_instance, sizeof (obj->plugin_instance));
- strncpy (obj->type, vl->type, sizeof (obj->type));
- strncpy (obj->type_instance, vl->type_instance, sizeof (obj->type_instance));
-
- have_new_obj = 1;
-
- return ((void *) obj);
-}
-
-static void checked_lookup_add (lookup_t *obj, /* {{{ */
- char const *host,
- char const *plugin, char const *plugin_instance,
- char const *type, char const *type_instance,
- unsigned int group_by)
-{
- identifier_t ident;
- void *user_class;
-
- memset (&ident, 0, sizeof (ident));
- strncpy (ident.host, host, sizeof (ident.host));
- strncpy (ident.plugin, plugin, sizeof (ident.plugin));
- strncpy (ident.plugin_instance, plugin_instance, sizeof (ident.plugin_instance));
- strncpy (ident.type, type, sizeof (ident.type));
- strncpy (ident.type_instance, type_instance, sizeof (ident.type_instance));
-
- user_class = malloc (sizeof (ident));
- memmove (user_class, &ident, sizeof (ident));
-
- OK(lookup_add (obj, &ident, group_by, user_class) == 0);
-} /* }}} void test_add */
-
-static int checked_lookup_search (lookup_t *obj,
- char const *host,
- char const *plugin, char const *plugin_instance,
- char const *type, char const *type_instance,
- _Bool expect_new)
-{
- int status;
- value_list_t vl = VALUE_LIST_STATIC;
- data_set_t const *ds = &ds_unknown;
-
- strncpy (vl.host, host, sizeof (vl.host));
- strncpy (vl.plugin, plugin, sizeof (vl.plugin));
- strncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
- strncpy (vl.type, type, sizeof (vl.type));
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
-
- if (strcmp (vl.type, "test") == 0)
- ds = &ds_test;
-
- expect_new_obj = expect_new;
- have_new_obj = 0;
-
- status = lookup_search (obj, ds, &vl);
- 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 ();
-
- checked_lookup_add (obj, "/.*/", "test", "", "test", "/.*/", LU_GROUP_BY_HOST);
- checked_lookup_search (obj, "host0", "test", "", "test", "0",
- /* expect new = */ 1);
- checked_lookup_search (obj, "host0", "test", "", "test", "1",
- /* expect new = */ 0);
- checked_lookup_search (obj, "host1", "test", "", "test", "0",
- /* expect new = */ 1);
- checked_lookup_search (obj, "host1", "test", "", "test", "1",
- /* expect new = */ 0);
-
- lookup_destroy (obj);
- return (0);
-}
-
-DEF_TEST(group_by_any_host)
-{
- lookup_t *obj = checked_lookup_create ();
-
- checked_lookup_add (obj, "/.*/", "/.*/", "/.*/", "test", "/.*/", LU_GROUP_BY_HOST);
- checked_lookup_search (obj, "host0", "plugin0", "", "test", "0",
- /* expect new = */ 1);
- checked_lookup_search (obj, "host0", "plugin0", "", "test", "1",
- /* expect new = */ 0);
- checked_lookup_search (obj, "host0", "plugin1", "", "test", "0",
- /* expect new = */ 0);
- checked_lookup_search (obj, "host0", "plugin1", "", "test", "1",
- /* expect new = */ 0);
- checked_lookup_search (obj, "host1", "plugin0", "", "test", "0",
- /* expect new = */ 1);
- checked_lookup_search (obj, "host1", "plugin0", "", "test", "1",
- /* expect new = */ 0);
- checked_lookup_search (obj, "host1", "plugin1", "", "test", "0",
- /* expect new = */ 0);
- checked_lookup_search (obj, "host1", "plugin1", "", "test", "1",
- /* expect new = */ 0);
-
- lookup_destroy (obj);
- return (0);
-}
-
-DEF_TEST(multiple_lookups)
-{
- lookup_t *obj = checked_lookup_create ();
- int status;
-
- checked_lookup_add (obj, "/.*/", "plugin0", "", "test", "/.*/", LU_GROUP_BY_HOST);
- checked_lookup_add (obj, "/.*/", "/.*/", "", "test", "ti0", LU_GROUP_BY_HOST);
-
- status = checked_lookup_search (obj, "host0", "plugin1", "", "test", "",
- /* expect new = */ 0);
- assert (status == 0);
- status = checked_lookup_search (obj, "host0", "plugin0", "", "test", "",
- /* expect new = */ 1);
- assert (status == 1);
- status = checked_lookup_search (obj, "host0", "plugin1", "", "test", "ti0",
- /* expect new = */ 1);
- assert (status == 1);
- status = checked_lookup_search (obj, "host0", "plugin0", "", "test", "ti0",
- /* expect new = */ 0);
- assert (status == 2);
-
- lookup_destroy (obj);
- return (0);
-}
-
-DEF_TEST(regex)
-{
- lookup_t *obj = checked_lookup_create ();
-
- checked_lookup_add (obj, "/^db[0-9]\\./", "cpu", "/.*/", "cpu", "/.*/",
- LU_GROUP_BY_TYPE_INSTANCE);
- checked_lookup_search (obj, "db0.example.com", "cpu", "0", "cpu", "user",
- /* expect new = */ 1);
- checked_lookup_search (obj, "db0.example.com", "cpu", "0", "cpu", "idle",
- /* expect new = */ 1);
- checked_lookup_search (obj, "db0.example.com", "cpu", "1", "cpu", "user",
- /* expect new = */ 0);
- checked_lookup_search (obj, "db0.example.com", "cpu", "1", "cpu", "idle",
- /* expect new = */ 0);
- checked_lookup_search (obj, "app0.example.com", "cpu", "0", "cpu", "user",
- /* expect new = */ 0);
- checked_lookup_search (obj, "app0.example.com", "cpu", "0", "cpu", "idle",
- /* expect new = */ 0);
- checked_lookup_search (obj, "db1.example.com", "cpu", "0", "cpu", "user",
- /* expect new = */ 0);
- checked_lookup_search (obj, "db1.example.com", "cpu", "0", "cpu", "idle",
- /* expect new = */ 0);
- checked_lookup_search (obj, "db1.example.com", "cpu", "0", "cpu", "system",
- /* expect new = */ 1);
-
- lookup_destroy (obj);
- return (0);
-}
-
-int main (int argc, char **argv) /* {{{ */
-{
- RUN_TEST(group_by_specific_host);
- RUN_TEST(group_by_any_host);
- RUN_TEST(multiple_lookups);
- RUN_TEST(regex);
-
- END_TEST;
-} /* }}} int main */
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
- status = 0;
if (strcasecmp ("Instance", option->key) == 0)
status = ut_config_type_instance (&th, option);
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
- status = 0;
if (strcasecmp ("Type", option->key) == 0)
status = ut_config_type (&th, option);
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
- status = 0;
if (strcasecmp ("Type", option->key) == 0)
status = ut_config_type (&th, option);
if (state == STATE_OKAY)
{
if (state_old == STATE_MISSING)
- status = ssnprintf (buf, bufsize,
- ": Value is no longer missing.");
+ ssnprintf (buf, bufsize, ": Value is no longer missing.");
else
- status = ssnprintf (buf, bufsize,
+ ssnprintf (buf, bufsize,
": All data sources are within range again. "
"Current value of \"%s\" is %f.",
ds->ds[ds_index].name, values[ds_index]);
- buf += status;
- bufsize -= status;
}
else
{
{
if (!isnan (min) && !isnan (max))
{
- status = ssnprintf (buf, bufsize, ": Data source \"%s\" is currently "
+ ssnprintf (buf, bufsize, ": Data source \"%s\" is currently "
"%f. That is within the %s region of %f%s and %f%s.",
ds->ds[ds_index].name, values[ds_index],
(state == STATE_ERROR) ? "failure" : "warning",
}
else
{
- status = ssnprintf (buf, bufsize, ": Data source \"%s\" is currently "
- "%f. That is %s the %s threshold of %f%s.",
- ds->ds[ds_index].name, values[ds_index],
- isnan (min) ? "below" : "above",
- (state == STATE_ERROR) ? "failure" : "warning",
- isnan (min) ? max : min,
- ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "");
+ ssnprintf (buf, bufsize, ": Data source \"%s\" is currently "
+ "%f. That is %s the %s threshold of %f%s.",
+ ds->ds[ds_index].name, values[ds_index],
+ isnan (min) ? "below" : "above",
+ (state == STATE_ERROR) ? "failure" : "warning",
+ isnan (min) ? max : min,
+ ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "");
}
}
else if (th->flags & UT_FLAG_PERCENTAGE)
{
gauge_t value;
gauge_t sum;
- int i;
+ size_t i;
sum = 0.0;
for (i = 0; i < vl->values_len; i++)
else
value = 100.0 * values[ds_index] / sum;
- status = ssnprintf (buf, bufsize, ": Data source \"%s\" is currently "
+ ssnprintf (buf, bufsize, ": Data source \"%s\" is currently "
"%g (%.2f%%). That is %s the %s threshold of %.2f%%.",
ds->ds[ds_index].name, values[ds_index], value,
(value < min) ? "below" : "above",
}
else /* is not inverted */
{
- status = ssnprintf (buf, bufsize, ": Data source \"%s\" is currently "
- "%f. That is %s the %s threshold of %f.",
- ds->ds[ds_index].name, values[ds_index],
- (values[ds_index] < min) ? "below" : "above",
- (state == STATE_ERROR) ? "failure" : "warning",
- (values[ds_index] < min) ? min : max);
+ ssnprintf (buf, bufsize, ": Data source \"%s\" is currently "
+ "%f. That is %s the %s threshold of %f.",
+ ds->ds[ds_index].name, values[ds_index],
+ (values[ds_index] < min) ? "below" : "above",
+ (state == STATE_ERROR) ? "failure" : "warning",
+ (values[ds_index] < min) ? min : max);
}
- buf += status;
- bufsize -= status;
}
plugin_dispatch_notification (&n);
{ /* {{{ */
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));
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
- status = 0;
if (strcasecmp ("Type", option->key) == 0)
status = ut_config_type (&th, option);
unsigned int i;
unsigned int total_threads, total_cores;
+ if ((topology.num_threads == 0)
+ || (topology.num_cores == 0)
+ || (topology.num_packages == 0))
+ {
+ ERROR ("turbostat plugin: Invalid topology: %u threads, %u cores, %u packages",
+ topology.num_threads, topology.num_cores, topology.num_packages);
+ return -1;
+ }
+
total_threads = topology.num_threads * topology.num_cores * topology.num_packages;
*threads = calloc(total_threads, sizeof(struct thread_data));
if (*threads == NULL)
- goto err;
+ {
+ ERROR ("turbostat plugin: calloc failed");
+ return -1;
+ }
for (i = 0; i < total_threads; ++i)
(*threads)[i].cpu_id = topology.max_cpu_id + 1;
total_cores = topology.num_cores * topology.num_packages;
*cores = calloc(total_cores, sizeof(struct core_data));
if (*cores == NULL)
- goto err_clean_threads;
+ {
+ ERROR ("turbostat plugin: calloc failed");
+ sfree (threads);
+ return -1;
+ }
*packages = calloc(topology.num_packages, sizeof(struct pkg_data));
if (*packages == NULL)
- goto err_clean_cores;
+ {
+ ERROR ("turbostat plugin: calloc failed");
+ sfree (cores);
+ sfree (threads);
+ return -1;
+ }
return 0;
-
-err_clean_cores:
- free(*cores);
-err_clean_threads:
- free(*threads);
-err:
- ERROR("turbostat plugin: Failled to allocate memory for counters");
- return -1;
}
static void
#elif HAVE_UTMP_H
# include <utmp.h>
/* #endif HAVE_UTMP_H */
-
-#else
-# error "No applicable input method."
#endif
static void users_submit (gauge_t value)
#include "plugin.h"
#include "utils_parse_option.h"
-#define print_to_socket(fh, ...) \
- do { \
- if (fprintf (fh, __VA_ARGS__) < 0) { \
- char errbuf[1024]; \
- WARNING ("handle_flush: failed to write to socket #%i: %s", \
- fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
- return -1; \
- } \
- fflush(fh); \
- } while (0)
-
-static int add_to_array (char ***array, int *array_num, char *value)
-{
- char **temp;
-
- temp = (char **) realloc (*array, sizeof (char *) * (*array_num + 1));
- if (temp == NULL)
- return (-1);
-
- *array = temp;
- (*array)[*array_num] = value;
- (*array_num)++;
-
- return (0);
-} /* int add_to_array */
-
int handle_flush (FILE *fh, char *buffer)
{
int success = 0;
double timeout = 0.0;
char **plugins = NULL;
- int plugins_num = 0;
+ size_t plugins_num = 0;
char **identifiers = NULL;
- int identifiers_num = 0;
+ size_t identifiers_num = 0;
- int i;
+ size_t i;
+
+#define PRINT_TO_SOCK(fh, ...) \
+ do { \
+ if (fprintf (fh, __VA_ARGS__) < 0) { \
+ char errbuf[1024]; \
+ WARNING ("handle_flush: failed to write to socket #%i: %s", \
+ fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
+ strarray_free (plugins, plugins_num); \
+ strarray_free (identifiers, identifiers_num); \
+ return -1; \
+ } \
+ fflush(fh); \
+ } while (0)
if ((fh == NULL) || (buffer == NULL))
return (-1);
if (strncasecmp ("FLUSH", buffer, strlen ("FLUSH")) != 0)
{
- print_to_socket (fh, "-1 Cannot parse command.\n");
+ PRINT_TO_SOCK (fh, "-1 Cannot parse command.\n");
return (-1);
}
buffer += strlen ("FLUSH");
status = parse_option (&buffer, &opt_key, &opt_value);
if (status != 0)
{
- print_to_socket (fh, "-1 Parsing options failed.\n");
- sfree (plugins);
- sfree (identifiers);
+ PRINT_TO_SOCK (fh, "-1 Parsing options failed.\n");
+ strarray_free (plugins, plugins_num);
+ strarray_free (identifiers, identifiers_num);
return (-1);
}
if (strcasecmp ("plugin", opt_key) == 0)
- {
- add_to_array (&plugins, &plugins_num, opt_value);
- }
+ strarray_add (&plugins, &plugins_num, opt_value);
else if (strcasecmp ("identifier", opt_key) == 0)
- {
- add_to_array (&identifiers, &identifiers_num, opt_value);
- }
+ strarray_add (&identifiers, &identifiers_num, opt_value);
else if (strcasecmp ("timeout", opt_key) == 0)
{
char *endptr;
-
+
errno = 0;
endptr = NULL;
timeout = strtod (opt_value, &endptr);
if ((endptr == opt_value) || (errno != 0) || (!isfinite (timeout)))
{
- print_to_socket (fh, "-1 Invalid value for option `timeout': "
+ PRINT_TO_SOCK (fh, "-1 Invalid value for option `timeout': "
"%s\n", opt_value);
- sfree (plugins);
- sfree (identifiers);
+ strarray_free (plugins, plugins_num);
+ strarray_free (identifiers, identifiers_num);
return (-1);
}
else if (timeout < 0.0)
}
else
{
- print_to_socket (fh, "-1 Cannot parse option %s\n", opt_key);
- sfree (plugins);
- sfree (identifiers);
+ PRINT_TO_SOCK (fh, "-1 Cannot parse option %s\n", opt_key);
+ strarray_free (plugins, plugins_num);
+ strarray_free (identifiers, identifiers_num);
return (-1);
}
} /* while (*buffer != 0) */
- /* Add NULL entries for `any plugin' and/or `any value' if nothing was
- * specified. */
- if (plugins_num == 0)
- add_to_array (&plugins, &plugins_num, NULL);
-
- if (identifiers_num == 0)
- add_to_array (&identifiers, &identifiers_num, NULL);
-
- for (i = 0; i < plugins_num; i++)
+ for (i = 0; (i == 0) || (i < plugins_num); i++)
{
- char *plugin;
- int j;
+ char *plugin = NULL;
+ size_t j;
- plugin = plugins[i];
+ if (plugins_num != 0)
+ plugin = plugins[i];
- for (j = 0; j < identifiers_num; j++)
+ for (j = 0; (j == 0) || (j < identifiers_num); j++)
{
- char *identifier;
+ char *identifier = NULL;
int status;
- identifier = identifiers[j];
+ if (identifiers_num != 0)
+ identifier = identifiers[j];
+
status = plugin_flush (plugin,
DOUBLE_TO_CDTIME_T (timeout),
identifier);
}
}
- if ((success + error) > 0)
- {
- print_to_socket (fh, "0 Done: %i successful, %i errors\n",
- success, error);
- }
- else
- {
- plugin_flush (NULL, DOUBLE_TO_CDTIME_T (timeout), NULL);
- print_to_socket (fh, "0 Done\n");
- }
+ PRINT_TO_SOCK (fh, "0 Done: %i successful, %i errors\n",
+ success, error);
- sfree (plugins);
- sfree (identifiers);
+ strarray_free (plugins, plugins_num);
+ strarray_free (identifiers, identifiers_num);
return (0);
+#undef PRINT_TO_SOCK
} /* int handle_flush */
/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
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++)
{
char errbuf[1024]; \
WARNING ("handle_putval: failed to write to socket #%i: %s", \
fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
+ sfree (vl.values); \
return -1; \
} \
fflush(fh); \
} while (0)
-static int dispatch_values (const data_set_t *ds, value_list_t *vl,
- FILE *fh, char *buffer)
-{
- int status;
-
- status = parse_values (buffer, vl, ds);
- if (status != 0)
- {
- print_to_socket (fh, "-1 Parsing the values string failed.\n");
- return (-1);
- }
-
- plugin_dispatch_values (vl);
- return (0);
-} /* int dispatch_values */
-
static int set_option (value_list_t *vl, const char *key, const char *value)
{
if ((vl == NULL) || (key == NULL) || (value == NULL))
const data_set_t *ds;
value_list_t vl = VALUE_LIST_INIT;
+ vl.values = NULL;
DEBUG ("utils_cmd_putval: handle_putval (fh = %p, buffer = %s);",
(void *) fh, buffer);
/* parse_option failed, buffer has been modified.
* => we need to abort */
print_to_socket (fh, "-1 Misformatted option.\n");
+ sfree (vl.values);
return (-1);
}
else if (status == 0)
if (status != 0)
{
print_to_socket (fh, "-1 Misformatted value.\n");
+ sfree (vl.values);
return (-1);
}
assert (string != NULL);
- status = dispatch_values (ds, &vl, fh, string);
+ status = parse_values (string, &vl, ds);
if (status != 0)
{
- /* An error has already been printed. */
+ print_to_socket (fh, "-1 Parsing the values string failed.\n");
+ sfree (vl.values);
return (-1);
}
+
+ plugin_dispatch_values (&vl);
values_submitted++;
} /* while (*buffer != 0) */
/* Done parsing the options. */
values_submitted,
(values_submitted == 1) ? "value has" : "values have");
- sfree (vl.values);
-
+ sfree (vl.values);
return (0);
} /* int handle_putval */
assert (r != NULL);
assert (r_area->ds != NULL);
assert (((size_t) r_area->ds->ds_num) == r->values_num);
+ assert (r->values_num > 0);
- vl.values = (value_t *) calloc (r_area->ds->ds_num, sizeof (value_t));
+ vl.values = (value_t *) calloc (r->values_num, sizeof (value_t));
if (vl.values == NULL)
{
ERROR ("db query utils: malloc failed.");
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);
udb_result_preparation_area_t **next_r_area;
udb_result_t *r;
- q_area = (udb_query_preparation_area_t *)malloc (sizeof (*q_area));
+ q_area = malloc (sizeof (*q_area));
if (q_area == NULL)
return NULL;
-
memset (q_area, 0, sizeof (*q_area));
next_r_area = &q_area->result_prep_areas;
{
udb_result_preparation_area_t *r_area;
- r_area = (udb_result_preparation_area_t *)malloc (sizeof (*r_area));
+ r_area = malloc (sizeof (*r_area));
if (r_area == NULL)
{
- for (r_area = q_area->result_prep_areas;
- r_area != NULL; r_area = r_area->next)
+ udb_result_preparation_area_t *a = q_area->result_prep_areas;
+
+ while (a != NULL)
{
- free (r_area);
+ udb_result_preparation_area_t *next = a->next;
+ sfree (a);
+ a = next;
}
+
free (q_area);
return NULL;
}
# error "`struct udphdr' is unusable."
#endif
+#if HAVE_NETINET_IP6_H && HAVE_STRUCT_IP6_EXT
+# define HAVE_IPV6 1
+#endif
+
#include "utils_dns.h"
/*
if (ns <= 0)
return 4; /* probably compression loop */
do {
- if ((*off) >= sz)
+ if ((*off) >= ((off_t) sz))
break;
c = *(buf + (*off));
if (c > 191) {
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 */
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;
}
return 1;
}
-#if HAVE_NETINET_IP6_H
+#if HAVE_IPV6
static int
handle_ipv6 (struct ip6_hdr *ipv6, int len)
{
return (1); /* Success */
} /* int handle_ipv6 */
-/* #endif HAVE_NETINET_IP6_H */
+/* #endif HAVE_IPV6 */
-#else /* if !HAVE_NETINET_IP6_H */
+#else /* if !HAVE_IPV6 */
static int
handle_ipv6 (__attribute__((unused)) void *pkg,
__attribute__((unused)) int len)
{
return (0);
}
-#endif /* !HAVE_NETINET_IP6_H */
+#endif /* !HAVE_IPV6 */
static int
handle_ip(const struct ip *ip, int len)
unsigned int flags)
{
int status = 0;
- int i;
+ size_t i;
int buffer_pos = 0;
gauge_t *rates = NULL;
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);
}
#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);
- 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);
- 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)
if (this->rmatch != NULL)
{
regfree (this->rmatch);
+ sfree (this->rmatch);
this->rmatch = NULL;
}
#endif
/*
* 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) */
/*
#include "common.h"
#include <math.h>
+#include <limits.h>
+
+#ifndef LLONG_MAX
+# define LLONG_MAX 9223372036854775807LL
+#endif
#ifndef HISTOGRAM_NUM_BINS
# define HISTOGRAM_NUM_BINS 1000
#endif
-static const int HISTOGRAM_DEFAULT_BIN_WIDTH = 1;
+#ifndef HISTOGRAM_DEFAULT_BIN_WIDTH
+/* 1048576 = 2^20 ^= 1/1024 s */
+# define HISTOGRAM_DEFAULT_BIN_WIDTH 1048576
+#endif
struct latency_counter_s
{
cdtime_t min;
cdtime_t max;
- int bin_width;
+ cdtime_t bin_width;
int histogram[HISTOGRAM_NUM_BINS];
};
*
* So, if the required bin width is 300, then new bin width will be 512 as it is
* the next nearest power of 2.
-*
*/
-void change_bin_width (latency_counter_t *lc, size_t val) /* {{{ */
+void change_bin_width (latency_counter_t *lc, cdtime_t latency) /* {{{ */
{
- int i=0;
/* This function is called because the new value is above histogram's range.
* First find the required bin width:
* requiredBinWidth = (value + 1) / numBins
* then get the next nearest power of 2
* newBinWidth = 2^(ceil(log2(requiredBinWidth)))
*/
- double required_bin_width = (double)(val + 1) / HISTOGRAM_NUM_BINS;
- double required_bin_width_logbase2 = log(required_bin_width) / log(2.0);
- int new_bin_width = (int)(pow(2.0, ceil( required_bin_width_logbase2)));
- int old_bin_width = lc->bin_width;
+ double required_bin_width = ((double) (latency + 1)) / ((double) HISTOGRAM_NUM_BINS);
+ double required_bin_width_logbase2 = log (required_bin_width) / log (2.0);
+ cdtime_t new_bin_width = (cdtime_t) (pow (2.0, ceil (required_bin_width_logbase2)) + .5);
+ cdtime_t old_bin_width = lc->bin_width;
+
lc->bin_width = new_bin_width;
- /*
- * bin width has been increased, now iterate through all bins and move the
- * old bin's count to new bin.
- */
+ /* bin_width has been increased, now iterate through all bins and move the
+ * old bin's count to new bin. */
if (lc->num > 0) // if the histogram has data then iterate else skip
{
- double width_change_ratio = old_bin_width / new_bin_width;
- for (i=0; i<HISTOGRAM_NUM_BINS; i++)
+ double width_change_ratio = ((double) old_bin_width) / ((double) new_bin_width);
+ size_t i;
+
+ for (i = 0; i < HISTOGRAM_NUM_BINS; i++)
{
- int new_bin = (int)(i * width_change_ratio);
+ size_t new_bin = (size_t) (((double) i) * width_change_ratio);
if (i == new_bin)
continue;
+ assert (new_bin < i);
+
lc->histogram[new_bin] += lc->histogram[i];
lc->histogram[i] = 0;
}
- DEBUG("utils_latency: change_bin_width: fixed all bins");
}
- DEBUG("utils_latency: change_bin_width: val-[%zu], oldBinWidth-[%d], "
- "newBinWidth-[%d], required_bin_width-[%f], "
- "required_bin_width_logbase2-[%f]",
- val, old_bin_width, new_bin_width, required_bin_width,
- required_bin_width_logbase2);
-
+ DEBUG("utils_latency: change_bin_width: latency = %.3f; "
+ "old_bin_width = %.3f; new_bin_width = %.3f;",
+ CDTIME_T_TO_DOUBLE (latency),
+ CDTIME_T_TO_DOUBLE (old_bin_width),
+ CDTIME_T_TO_DOUBLE (new_bin_width));
} /* }}} void change_bin_width */
latency_counter_t *latency_counter_create () /* {{{ */
lc = malloc (sizeof (*lc));
if (lc == NULL)
return (NULL);
+ memset (lc, 0, sizeof (*lc));
latency_counter_reset (lc);
lc->bin_width = HISTOGRAM_DEFAULT_BIN_WIDTH;
void latency_counter_add (latency_counter_t *lc, cdtime_t latency) /* {{{ */
{
- size_t latency_ms;
+ cdtime_t bin;
- if ((lc == NULL) || (latency == 0))
+ if ((lc == NULL) || (latency == 0) || (latency > ((cdtime_t) LLONG_MAX)))
return;
lc->sum += latency;
/* A latency of _exactly_ 1.0 ms should be stored in the buffer 0, so
* subtract one from the cdtime_t value so that exactly 1.0 ms get sorted
* accordingly. */
- latency_ms = (size_t) CDTIME_T_TO_MS (latency - 1);
-
- int bin = (int)(latency_ms / lc->bin_width);
+ bin = (latency - 1) / lc->bin_width;
if (bin >= HISTOGRAM_NUM_BINS)
{
- change_bin_width(lc, latency_ms);
- bin = (int)(latency_ms / lc->bin_width);
+ change_bin_width (lc, latency);
+ bin = (latency - 1) / lc->bin_width;
if (bin >= HISTOGRAM_NUM_BINS)
{
- ERROR("utils_latency: latency_counter_add: Invalid bin %d", bin);
+ ERROR ("utils_latency: latency_counter_add: Invalid bin: %"PRIu64, bin);
return;
}
}
if (lc == NULL)
return;
- int bin_width = lc->bin_width;
+ cdtime_t bin_width = lc->bin_width;
memset (lc, 0, sizeof (*lc));
/* preserve bin width */
return (DOUBLE_TO_CDTIME_T (average));
} /* }}} cdtime_t latency_counter_get_average */
-cdtime_t latency_counter_get_percentile (latency_counter_t *lc,
+cdtime_t latency_counter_get_percentile (latency_counter_t *lc, /* {{{ */
double percent)
{
double percent_upper;
double percent_lower;
- double ms_upper;
- double ms_lower;
- double ms_interpolated;
+ double p;
+ cdtime_t latency_lower;
+ cdtime_t latency_interpolated;
int sum;
size_t i;
assert (percent_upper >= percent);
assert (percent_lower < percent);
- ms_upper = (double) ( (i + 1) * lc->bin_width );
- ms_lower = (double) ( i * lc->bin_width );
if (i == 0)
- return (MS_TO_CDTIME_T (ms_upper));
+ return (lc->bin_width);
+
+ latency_lower = ((cdtime_t) i) * lc->bin_width;
+ p = (percent - percent_lower) / (percent_upper - percent_lower);
- ms_interpolated = (((percent_upper - percent) * ms_lower)
- + ((percent - percent_lower) * ms_upper))
- / (percent_upper - percent_lower);
+ latency_interpolated = latency_lower
+ + DOUBLE_TO_CDTIME_T (p * CDTIME_T_TO_DOUBLE (lc->bin_width));
- return (MS_TO_CDTIME_T (ms_interpolated));
+ DEBUG ("latency_counter_get_percentile: latency_interpolated = %.3f",
+ CDTIME_T_TO_DOUBLE (latency_interpolated));
+ return (latency_interpolated);
} /* }}} cdtime_t latency_counter_get_percentile */
/* vim: set sw=2 sts=2 et fdm=marker : */
--- /dev/null
+/**
+ * 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));
+
+ DBLEQ (cases[i].min, CDTIME_T_TO_DOUBLE (latency_counter_get_min (l)));
+ DBLEQ (cases[i].max, CDTIME_T_TO_DOUBLE (latency_counter_get_max (l)));
+ DBLEQ (cases[i].sum, CDTIME_T_TO_DOUBLE (latency_counter_get_sum (l)));
+ DBLEQ (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));
+ }
+
+ DBLEQ ( 1.0, CDTIME_T_TO_DOUBLE (latency_counter_get_min (l)));
+ DBLEQ (100.0, CDTIME_T_TO_DOUBLE (latency_counter_get_max (l)));
+ DBLEQ (100.0 * 101.0 / 2.0, CDTIME_T_TO_DOUBLE (latency_counter_get_sum (l)));
+ DBLEQ ( 50.5, CDTIME_T_TO_DOUBLE (latency_counter_get_average (l)));
+
+ DBLEQ (50.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 50.0)));
+ DBLEQ (80.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 80.0)));
+ DBLEQ (95.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 95.0)));
+ DBLEQ (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 : */
* Niki W. Waibel <niki.waibel@gmx.net>
**/
-#if HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "collectd.h"
+#include "utils_mount.h"
+
+#include "common.h" /* sstrncpy() et alii */
+#include "plugin.h" /* ERROR() macro */
-#include "common.h"
#if HAVE_XFS_XQM_H
# include <xfs/xqm.h>
#define XFS_SUPER_MAGIC_STR "XFSB"
#define XFS_SUPER_MAGIC2_STR "BSFX"
#endif
-#include "plugin.h"
-#include "utils_mount.h"
-
#if HAVE_GETVFSSTAT
# if HAVE_SYS_TYPES_H
# include <sys/types.h>
--- /dev/null
+/**
+ * collectd - src/tests/test_utils_mount.c
+ * Copyright (C) 2013 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 "utils_mount.h"
+
+DEF_TEST(cu_mount_checkoption)
+{
+ char line_opts[] = "foo=one,bar=two,qux=three";
+ char *foo = strstr (line_opts, "foo");
+ char *bar = strstr (line_opts, "bar");
+ char *qux = strstr (line_opts, "qux");
+
+ char line_bool[] = "one,two,three";
+ char *one = strstr (line_bool, "one");
+ char *two = strstr (line_bool, "two");
+ char *three = strstr (line_bool, "three");
+
+ /* Normal operation */
+ OK (foo == cu_mount_checkoption (line_opts, "foo", 0));
+ OK (bar == cu_mount_checkoption (line_opts, "bar", 0));
+ OK (qux == cu_mount_checkoption (line_opts, "qux", 0));
+ OK (NULL == cu_mount_checkoption (line_opts, "unknown", 0));
+
+ OK (one == cu_mount_checkoption (line_bool, "one", 0));
+ OK (two == cu_mount_checkoption (line_bool, "two", 0));
+ OK (three == cu_mount_checkoption (line_bool, "three", 0));
+ OK (NULL == cu_mount_checkoption (line_bool, "four", 0));
+
+ /* Shorter and longer parts */
+ OK (foo == cu_mount_checkoption (line_opts, "fo", 0));
+ OK (bar == cu_mount_checkoption (line_opts, "bar=", 0));
+ OK (qux == cu_mount_checkoption (line_opts, "qux=thr", 0));
+
+ OK (one == cu_mount_checkoption (line_bool, "o", 0));
+ OK (two == cu_mount_checkoption (line_bool, "tw", 0));
+ OK (three == cu_mount_checkoption (line_bool, "thr", 0));
+
+ /* "full" flag */
+ OK (one == cu_mount_checkoption (line_bool, "one", 1));
+ OK (two == cu_mount_checkoption (line_bool, "two", 1));
+ OK (three == cu_mount_checkoption (line_bool, "three", 1));
+ OK (NULL == cu_mount_checkoption (line_bool, "four", 1));
+
+ OK (NULL == cu_mount_checkoption (line_bool, "o", 1));
+ OK (NULL == cu_mount_checkoption (line_bool, "tw", 1));
+ OK (NULL == cu_mount_checkoption (line_bool, "thr", 1));
+
+ return (0);
+}
+DEF_TEST(cu_mount_getoptionvalue)
+{
+ 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="));
+ 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"));
+ OK (NULL == cu_mount_getoptionvalue (line_bool, "four"));
+
+ return (0);
+}
+
+int main (void)
+{
+ RUN_TEST(cu_mount_checkoption);
+ RUN_TEST(cu_mount_getoptionvalue);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
int rra_max;
- int span;
-
int cdp_num;
int cdp_len;
int i, j;
- char buffer[128];
-
/* The stepsize we use here: If it is user-set, use it. If not, use the
* interval of the value-list. */
int ss;
}
rra_max = rts_num * rra_types_num;
+ assert (rra_max > 0);
- if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
+ if ((rra_def = malloc ((rra_max + 1) * sizeof (*rra_def))) == NULL)
return (-1);
- memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
+ memset (rra_def, 0, (rra_max + 1) * sizeof (*rra_def));
rra_num = 0;
cdp_len = 0;
for (i = 0; i < rts_num; i++)
{
- span = rts[i];
+ int span = rts[i];
if ((span / ss) < cfg->rrarows)
span = ss * cfg->rrarows;
for (j = 0; j < rra_types_num; j++)
{
+ char buffer[128];
int status;
if (rra_num >= rra_max)
}
}
+ if (rra_num <= 0)
+ {
+ sfree (rra_def);
+ return (0);
+ }
+
*ret = rra_def;
return (rra_num);
} /* }}} int rra_get */
const rrdcreate_config_t *cfg)
{
char **ds_def;
- int ds_num;
+ size_t ds_num;
char min[32];
char max[32];
char buffer[128];
- ds_def = (char **) malloc (ds->ds_num * sizeof (char *));
+ assert (ds->ds_num > 0);
+
+ ds_def = malloc (ds->ds_num * sizeof (*ds_def));
if (ds_def == NULL)
{
char errbuf[1024];
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
- memset (ds_def, '\0', ds->ds_num * sizeof (char *));
+ memset (ds_def, 0, ds->ds_num * sizeof (*ds_def));
for (ds_num = 0; ds_num < ds->ds_num; ds_num++)
{
return (-1);
}
+ if (ds_num <= 0)
+ {
+ sfree (ds_def);
+ return (0);
+ }
+
*ret = ds_def;
return (ds_num);
} /* }}} int ds_get */
{
char **argv;
int argc;
- char **rra_def;
+ char **rra_def = NULL;
int rra_num;
- char **ds_def;
+ char **ds_def = NULL;
int ds_num;
int status = 0;
time_t last_up;
if ((ds_num = ds_get (&ds_def, ds, vl, cfg)) < 1)
{
ERROR ("cu_rrd_create_file failed: Could not calculate DSes");
+ rra_free (rra_num, rra_def);
return (-1);
}
char errbuf[1024];
ERROR ("cu_rrd_create_file failed: %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
+ rra_free (rra_num, rra_def);
+ ds_free (ds_num, ds_def);
return (-1);
}
}
else /* synchronous */
{
- status = srrd_create (filename, stepsize, last_up,
- argc, (const char **) argv);
-
+ status = lock_file (filename);
if (status != 0)
{
- WARNING ("cu_rrd_create_file: srrd_create (%s) returned status %i.",
- filename, status);
+ if (status == EEXIST)
+ NOTICE ("cu_rrd_create_file: File \"%s\" is already being created.",
+ filename);
+ else
+ ERROR ("cu_rrd_create_file: Unable to lock file \"%s\".",
+ filename);
}
else
{
- DEBUG ("cu_rrd_create_file: Successfully created RRD file \"%s\".",
- filename);
+ status = srrd_create (filename, stepsize, last_up,
+ argc, (const char **) argv);
+
+ if (status != 0)
+ {
+ WARNING ("cu_rrd_create_file: srrd_create (%s) returned status %i.",
+ filename, status);
+ }
+ else
+ {
+ DEBUG ("cu_rrd_create_file: Successfully created RRD file \"%s\".",
+ filename);
+ }
+ unlock_file (filename);
}
}
--- /dev/null
+/**
+ * collectd - src/tests/test_utils_vl_lookup.c
+ * Copyright (C) 2012 Florian 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 Forster <octo at collectd.org>
+ **/
+
+#include "testing.h"
+#include "collectd.h"
+#include "utils_vl_lookup.h"
+
+static _Bool expect_new_obj = 0;
+static _Bool have_new_obj = 0;
+
+static identifier_t last_class_ident;
+static identifier_t last_obj_ident;
+
+static data_source_t dsrc_test = { "value", DS_TYPE_DERIVE, 0.0, NAN };
+static data_set_t const ds_test = { "test", 1, &dsrc_test };
+
+static data_source_t dsrc_unknown = { "value", DS_TYPE_DERIVE, 0.0, NAN };
+static data_set_t const ds_unknown = { "unknown", 1, &dsrc_unknown };
+
+static int lookup_obj_callback (data_set_t const *ds,
+ value_list_t const *vl,
+ void *user_class, void *user_obj)
+{
+ identifier_t *class = user_class;
+ identifier_t *obj = user_obj;
+
+ OK1(expect_new_obj == have_new_obj,
+ (expect_new_obj ? "New obj is created." : "Updating existing obj."));
+
+ memcpy (&last_class_ident, class, sizeof (last_class_ident));
+ memcpy (&last_obj_ident, obj, sizeof (last_obj_ident));
+
+ if (strcmp (obj->plugin_instance, "failure") == 0)
+ return (-1);
+
+ return (0);
+}
+
+static void *lookup_class_callback (data_set_t const *ds,
+ value_list_t const *vl, void *user_class)
+{
+ identifier_t *class = user_class;
+ identifier_t *obj;
+
+ assert (expect_new_obj);
+
+ memcpy (&last_class_ident, class, sizeof (last_class_ident));
+
+ obj = malloc (sizeof (*obj));
+ strncpy (obj->host, vl->host, sizeof (obj->host));
+ strncpy (obj->plugin, vl->plugin, sizeof (obj->plugin));
+ strncpy (obj->plugin_instance, vl->plugin_instance, sizeof (obj->plugin_instance));
+ strncpy (obj->type, vl->type, sizeof (obj->type));
+ strncpy (obj->type_instance, vl->type_instance, sizeof (obj->type_instance));
+
+ have_new_obj = 1;
+
+ return ((void *) 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,
+ unsigned int group_by)
+{
+ identifier_t ident;
+ void *user_class;
+
+ memset (&ident, 0, sizeof (ident));
+ strncpy (ident.host, host, sizeof (ident.host));
+ strncpy (ident.plugin, plugin, sizeof (ident.plugin));
+ strncpy (ident.plugin_instance, plugin_instance, sizeof (ident.plugin_instance));
+ strncpy (ident.type, type, sizeof (ident.type));
+ strncpy (ident.type_instance, type_instance, sizeof (ident.type_instance));
+
+ user_class = malloc (sizeof (ident));
+ memmove (user_class, &ident, sizeof (ident));
+
+ OK(lookup_add (obj, &ident, group_by, user_class) == 0);
+ return 0;
+} /* }}} int checked_lookup_add */
+
+static int checked_lookup_search (lookup_t *obj,
+ char const *host,
+ char const *plugin, char const *plugin_instance,
+ char const *type, char const *type_instance,
+ _Bool expect_new)
+{
+ int status;
+ value_list_t vl = VALUE_LIST_STATIC;
+ data_set_t const *ds = &ds_unknown;
+
+ strncpy (vl.host, host, sizeof (vl.host));
+ strncpy (vl.plugin, plugin, sizeof (vl.plugin));
+ strncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+ strncpy (vl.type, type, sizeof (vl.type));
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+ if (strcmp (vl.type, "test") == 0)
+ ds = &ds_test;
+
+ expect_new_obj = expect_new;
+ have_new_obj = 0;
+
+ status = lookup_search (obj, ds, &vl);
+ return (status);
+}
+
+DEF_TEST(group_by_specific_host)
+{
+ 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",
+ /* expect new = */ 1);
+ checked_lookup_search (obj, "host0", "test", "", "test", "1",
+ /* expect new = */ 0);
+ checked_lookup_search (obj, "host1", "test", "", "test", "0",
+ /* expect new = */ 1);
+ checked_lookup_search (obj, "host1", "test", "", "test", "1",
+ /* expect new = */ 0);
+
+ lookup_destroy (obj);
+ return (0);
+}
+
+DEF_TEST(group_by_any_host)
+{
+ 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",
+ /* expect new = */ 1);
+ checked_lookup_search (obj, "host0", "plugin0", "", "test", "1",
+ /* expect new = */ 0);
+ checked_lookup_search (obj, "host0", "plugin1", "", "test", "0",
+ /* expect new = */ 0);
+ checked_lookup_search (obj, "host0", "plugin1", "", "test", "1",
+ /* expect new = */ 0);
+ checked_lookup_search (obj, "host1", "plugin0", "", "test", "0",
+ /* expect new = */ 1);
+ checked_lookup_search (obj, "host1", "plugin0", "", "test", "1",
+ /* expect new = */ 0);
+ checked_lookup_search (obj, "host1", "plugin1", "", "test", "0",
+ /* expect new = */ 0);
+ checked_lookup_search (obj, "host1", "plugin1", "", "test", "1",
+ /* expect new = */ 0);
+
+ lookup_destroy (obj);
+ return (0);
+}
+
+DEF_TEST(multiple_lookups)
+{
+ 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);
+
+ status = checked_lookup_search (obj, "host0", "plugin1", "", "test", "",
+ /* expect new = */ 0);
+ assert (status == 0);
+ status = checked_lookup_search (obj, "host0", "plugin0", "", "test", "",
+ /* expect new = */ 1);
+ assert (status == 1);
+ status = checked_lookup_search (obj, "host0", "plugin1", "", "test", "ti0",
+ /* expect new = */ 1);
+ assert (status == 1);
+ status = checked_lookup_search (obj, "host0", "plugin0", "", "test", "ti0",
+ /* expect new = */ 0);
+ assert (status == 2);
+
+ lookup_destroy (obj);
+ return (0);
+}
+
+DEF_TEST(regex)
+{
+ 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);
+ checked_lookup_search (obj, "db0.example.com", "cpu", "0", "cpu", "user",
+ /* expect new = */ 1);
+ checked_lookup_search (obj, "db0.example.com", "cpu", "0", "cpu", "idle",
+ /* expect new = */ 1);
+ checked_lookup_search (obj, "db0.example.com", "cpu", "1", "cpu", "user",
+ /* expect new = */ 0);
+ checked_lookup_search (obj, "db0.example.com", "cpu", "1", "cpu", "idle",
+ /* expect new = */ 0);
+ checked_lookup_search (obj, "app0.example.com", "cpu", "0", "cpu", "user",
+ /* expect new = */ 0);
+ checked_lookup_search (obj, "app0.example.com", "cpu", "0", "cpu", "idle",
+ /* expect new = */ 0);
+ checked_lookup_search (obj, "db1.example.com", "cpu", "0", "cpu", "user",
+ /* expect new = */ 0);
+ checked_lookup_search (obj, "db1.example.com", "cpu", "0", "cpu", "idle",
+ /* expect new = */ 0);
+ checked_lookup_search (obj, "db1.example.com", "cpu", "0", "cpu", "system",
+ /* expect new = */ 1);
+
+ lookup_destroy (obj);
+ return (0);
+}
+
+int main (int argc, char **argv) /* {{{ */
+{
+ RUN_TEST(group_by_specific_host);
+ RUN_TEST(group_by_any_host);
+ RUN_TEST(multiple_lookups);
+ RUN_TEST(regex);
+
+ END_TEST;
+} /* }}} int main */
status = VSM_n_Arg (vd, conf->instance);
if (status < 0)
{
+ VSM_Delete (vd);
ERROR ("varnish plugin: VSM_n_Arg (\"%s\") failed "
"with status %i.",
conf->instance, status);
if (VSM_Open (vd))
#endif
{
- ERROR ("varnish plugin: Unable to load statistics.");
+ VSM_Delete (vd);
+ ERROR ("varnish plugin: Unable to open connection.");
return (-1);
}
#else /* if HAVE_VARNISH_V4 */
stats = VSC_Main(vd, NULL);
#endif
+ if (!stats)
+ {
+ VSM_Delete (vd);
+ ERROR ("varnish plugin: Unable to get statistics.");
+
+ return (-1);
+ }
+
varnish_monitor (conf, stats);
- VSM_Close (vd);
+ VSM_Delete (vd);
return (0);
} /* }}} */
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;
int new_size = sizeof (interface_devices[0]) * (nr_interface_devices+1);
char *path_copy, *address_copy, number_string[15];
+ if ((path == NULL) || (address == NULL))
+ return EINVAL;
+
path_copy = strdup (path);
if (!path_copy) return -1;
char *name;
int n, r;
+ if ((domname == NULL) || (devpath == NULL))
+ return 0;
+
n = sizeof (char) * (strlen (domname) + strlen (devpath) + 2);
name = malloc (n);
if (name == NULL) {
if (strncmp ("nr_", key, strlen ("nr_")) == 0)
{
char *inst = key + strlen ("nr_");
- value_t value = { .gauge = gauge };
- submit_one (NULL, "vmpage_number", inst, value);
+ if (strcmp(inst, "dirtied") == 0 || strcmp(inst, "written") == 0)
+ {
+ value_t value = { .derive = counter };
+ submit_one (NULL, "vmpage_action", inst, value);
+ }
+ else
+ {
+ value_t value = { .gauge = gauge };
+ submit_one (NULL, "vmpage_number", inst, value);
+ }
}
/*
/**
* 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;
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));
#undef APPEND
+ status = format_values (value_ptr, value_size, ds, vl, /* store rates = */ 0);
pthread_mutex_lock (&node->lock);
+ if (status != 0)
+ return (status);
if (node->conn == NULL)
{
node->conn = redisConnectWithTimeout ((char *)node->host, node->port, node->timeout);
if (node->conn == NULL)
{
- ERROR ("write_redis plugin: Connecting to host \"%s\" (port %i) failed.",
+ ERROR ("write_redis plugin: Connecting to host \"%s\" (port %i) failed: Unkown reason",
(node->host != NULL) ? node->host : "localhost",
(node->port != 0) ? node->port : 6379);
pthread_mutex_unlock (&node->lock);
return (-1);
}
+ else if (node->conn->err)
+ {
+ ERROR ("write_redis plugin: Connecting to host \"%s\" (port %i) failed: %s",
+ (node->host != NULL) ? node->host : "localhost",
+ (node->port != 0) ? node->port : 6379,
+ node->conn->errstr);
+ 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);
}
- assert (node->conn != NULL);
rr = redisCommand (node->conn, "ZADD %s %s %s", key, time, value);
+ if (rr == NULL)
+ WARNING("ZADD 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 %svalues %s",
+ (node->prefix != NULL) ? node->prefix : REDIS_DEFAULT_PREFIX,
+ ident);
if (rr==NULL)
- WARNING("ZADD command error. key:%s", key);
-
- rr = redisCommand (node->conn, "SADD collectd/values %s", ident);
- if (rr==NULL)
- WARNING("SADD command error. ident:%s", ident);
+ WARNING("SADD command error. ident:%s message:%s", ident, node->conn->errstr);
+ else
+ freeReplyObject (rr);
pthread_mutex_unlock (&node->lock);
node->timeout.tv_sec = 0;
node->timeout.tv_usec = 1000;
node->conn = NULL;
+ node->prefix = NULL;
+ node->database = 0;
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
WARNING ("write_redis plugin: Ignoring unknown config option \"%s\".",
child->key);
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);
} /* }}} 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 */
int *statuses)
{ /* {{{ */
int ret = -1;
- int i;
+ size_t i;
int status;
gauge_t values_copy[ds->ds_num];
gauge_t *values;
int status;
+ assert (vl->values_len > 0);
memset(statuses, 0, vl->values_len * sizeof(*statuses));
+
if (threshold_tree == NULL)
return 0;
int reference_count;
};
-static char *sensu_tags;
-static char **sensu_attrs;
+static char *sensu_tags = NULL;
+static char **sensu_attrs = NULL;
static size_t sensu_attrs_num;
static int add_str_to_list(struct str_list *strs,
{
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;
const char *p, *q;
size_t oldlen = strlen(old);
size_t count = strlen(new);
- size_t retlen = count;
+ size_t retlen;
size_t newlen = count;
int samesize = (oldlen == newlen);
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);
sensu_tags_arr.nb_strs = 0;
sensu_tags_arr.strs = NULL;
- sensu_tags = malloc(sizeof(char));
- if (sensu_tags == NULL) {
- ERROR("write_sensu plugin: Unable to alloc memory");
- return -1;
- }
- sensu_tags[0] = '\0';
for (i = 0; i < ci->children_num; i++) {
child = &ci->children[i];
if (strcasecmp("Node", child->key) == 0) {
sensu_config_node(child);
} else if (strcasecmp(child->key, "attribute") == 0) {
- char *key = NULL;
- char *val = NULL;
-
if (child->values_num != 2) {
WARNING("sensu attributes need both a key and a value.");
- free(sensu_tags);
- return -1;
+ continue;
}
if (child->values[0].type != OCONFIG_TYPE_STRING ||
- child->values[1].type != OCONFIG_TYPE_STRING) {
+ child->values[1].type != OCONFIG_TYPE_STRING) {
WARNING("sensu attribute needs string arguments.");
- free(sensu_tags);
- return -1;
- }
- if ((key = strdup(child->values[0].value.string)) == NULL) {
- ERROR("write_sensu plugin: Unable to alloc memory");
- free(sensu_tags);
- return -1;
- }
- if ((val = strdup(child->values[1].value.string)) == NULL) {
- free(sensu_tags);
- free(key);
- ERROR("write_sensu plugin: Unable to alloc memory");
- return -1;
+ continue;
}
- strarray_add(&sensu_attrs, &sensu_attrs_num, key);
- strarray_add(&sensu_attrs, &sensu_attrs_num, val);
- DEBUG("write_sensu: got attr: %s => %s", key, val);
- sfree(key);
- sfree(val);
+
+ strarray_add(&sensu_attrs, &sensu_attrs_num, child->values[0].value.string);
+ strarray_add(&sensu_attrs, &sensu_attrs_num, child->values[1].value.string);
+
+ DEBUG("write_sensu plugin: New attribute: %s => %s",
+ child->values[0].value.string,
+ child->values[1].value.string);
} else if (strcasecmp(child->key, "tag") == 0) {
char *tmp = NULL;
status = cf_util_get_string(child, &tmp);
}
}
if (sensu_tags_arr.nb_strs > 0) {
- free(sensu_tags);
+ sfree (sensu_tags);
sensu_tags = build_json_str_list("tags", &sensu_tags_arr);
free_str_list(&sensu_tags_arr);
if (sensu_tags == NULL) {
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))
{
--- /dev/null
+/**
+ * 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 */