From: Ruben Kerkhof Date: Tue, 26 Jun 2018 14:08:22 +0000 (+0200) Subject: Merge pull request #2837 from abays/fix-collectd-tg-dtime X-Git-Url: https://git.octo.it/?p=collectd.git;a=commitdiff_plain;h=7f07c55bac640c7a50d516248a3152235a14af59;hp=ffba5b8b514103329bd82f8d773194fb7744f55a Merge pull request #2837 from abays/fix-collectd-tg-dtime Use CLOCK_REALTIME for collectd-tg times (fixes issue 2219) --- diff --git a/AUTHORS b/AUTHORS index 4df743c5..409655ac 100644 --- a/AUTHORS +++ b/AUTHORS @@ -59,6 +59,9 @@ Andreas Henriksson Andy Parkins - battery plugin: sysfs code. +Andy Smith + - AMQP 1.0 plugin. + Anthony Dewhurst - zfs_arc plugin. @@ -286,7 +289,7 @@ Scott Sanders - Write-Graphite plugin. Sebastien Pahl - - AMQP plugin. + - AMQP 0.9 plugin. Serhiy Pshyk - intel_pmu plugin diff --git a/Makefile.am b/Makefile.am index e37716f6..190ce8ec 100644 --- a/Makefile.am +++ b/Makefile.am @@ -61,6 +61,7 @@ EXTRA_DIST = \ src/types.db \ src/types.db.pod \ src/valgrind.FreeBSD.suppress \ + src/valgrind.suppress \ testwrapper.sh \ version-gen.sh @@ -141,7 +142,8 @@ check_PROGRAMS = \ test_utils_subst \ test_utils_time \ test_utils_vl_lookup \ - test_libcollectd_network_parse + test_libcollectd_network_parse \ + test_utils_config_cores TESTS = $(check_PROGRAMS) @@ -193,6 +195,8 @@ endif collectd_SOURCES = \ + src/daemon/cmd.c \ + src/daemon/cmd.h \ src/daemon/collectd.c \ src/daemon/collectd.h \ src/daemon/configfile.c \ @@ -326,6 +330,11 @@ test_utils_subst_SOURCES = \ src/daemon/utils_subst.h test_utils_subst_LDADD = libplugin_mock.la +test_utils_config_cores_SOURCES = \ + src/utils_config_cores_test.c \ + src/testing.h +test_utils_config_cores_LDADD = libplugin_mock.la + libavltree_la_SOURCES = \ src/daemon/utils_avltree.c \ src/daemon/utils_avltree.h @@ -483,7 +492,8 @@ libcollectdclient_la_SOURCES = \ src/libcollectdclient/network.c \ src/libcollectdclient/network_buffer.c \ src/libcollectdclient/network_parse.c \ - src/libcollectdclient/server.c + src/libcollectdclient/server.c \ + src/libcollectdclient/collectd/stdendian.h libcollectdclient_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(srcdir)/src/libcollectdclient \ @@ -542,6 +552,20 @@ amqp_la_LIBADD = \ libformat_json.la endif +if BUILD_PLUGIN_AMQP1 +pkglib_LTLIBRARIES += amqp1.la +amqp1_la_SOURCES = \ + src/amqp1.c \ + src/utils_deq.h +amqp1_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBQPIDPROTON_CPPFLAGS) +amqp1_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBQPIDPROTON_LDFLAGS) +amqp1_la_LIBADD = \ + $(BUILD_WITH_LIBQPIDPROTON_LIBS) \ + libcmds.la \ + libformat_graphite.la \ + libformat_json.la +endif + if BUILD_PLUGIN_APACHE pkglib_LTLIBRARIES += apache.la apache_la_SOURCES = src/apache.c @@ -592,7 +616,7 @@ if BUILD_PLUGIN_BAROMETER pkglib_LTLIBRARIES += barometer.la barometer_la_SOURCES = src/barometer.c barometer_la_LDFLAGS = $(PLUGIN_LDFLAGS) -barometer_la_LIBADD = -lm +barometer_la_LIBADD = -lm $(BUILD_WITH_LIBI2C_LIBS) endif if BUILD_PLUGIN_BATTERY @@ -913,7 +937,10 @@ endif if BUILD_PLUGIN_INTEL_PMU pkglib_LTLIBRARIES += intel_pmu.la -intel_pmu_la_SOURCES = src/intel_pmu.c +intel_pmu_la_SOURCES = \ + src/intel_pmu.c \ + src/utils_config_cores.h \ + src/utils_config_cores.c intel_pmu_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBJEVENTS_CPPFLAGS) intel_pmu_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBJEVENTS_LDFLAGS) intel_pmu_la_LIBADD = $(BUILD_WITH_LIBJEVENTS_LIBS) @@ -921,7 +948,10 @@ endif if BUILD_PLUGIN_INTEL_RDT pkglib_LTLIBRARIES += intel_rdt.la -intel_rdt_la_SOURCES = src/intel_rdt.c +intel_rdt_la_SOURCES = \ + src/intel_rdt.c \ + src/utils_config_cores.h \ + src/utils_config_cores.c intel_rdt_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBPQOS_CPPFLAGS) intel_rdt_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBPQOS_LDFLAGS) intel_rdt_la_LIBADD = $(BUILD_WITH_LIBPQOS_LIBS) @@ -1528,7 +1558,7 @@ pkglib_LTLIBRARIES += snmp.la snmp_la_SOURCES = src/snmp.c snmp_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBNETSNMP_CPPFLAGS) snmp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBNETSNMP_LDFLAGS) -snmp_la_LIBADD = $(BUILD_WITH_LIBNETSNMP_LIBS) +snmp_la_LIBADD = libignorelist.la $(BUILD_WITH_LIBNETSNMP_LIBS) endif if BUILD_PLUGIN_SNMP_AGENT @@ -1537,6 +1567,23 @@ snmp_agent_la_SOURCES = src/snmp_agent.c snmp_agent_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBNETSNMPAGENT_CPPFLAGS) snmp_agent_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBNETSNMPAGENT_LDFLAGS) snmp_agent_la_LIBADD = $(BUILD_WITH_LIBNETSNMPAGENT_LIBS) + +test_plugin_snmp_agent_SOURCES = src/snmp_agent_test.c \ + src/daemon/utils_avltree.c \ + src/daemon/utils_llist.c \ + src/daemon/configfile.c \ + src/daemon/types_list.c +test_plugin_snmp_agent_CPPFLAGS = $(AM_CPPFLAGS) \ + $(BUILD_WITH_LIBNETSNMPAGENT_CPPFLAGS) +test_plugin_snmp_agent_LDFLAGS = $(PLUGIN_LDFLAGS) \ + $(BUILD_WITH_LIBNETSNMPAGENT_LDFLAGS) +test_plugin_snmp_agent_LDADD = liboconfig.la libplugin_mock.la \ + $(BUILD_WITH_LIBNETSNMPAGENT_LIBS) $(BUILD_WITH_LIBNETSNMP_LIBS) + +check_PROGRAMS += test_plugin_snmp_agent +TESTS += test_plugin_snmp_agent + + endif if BUILD_PLUGIN_STATSD @@ -1758,18 +1805,15 @@ virt_la_CFLAGS = $(AM_CFLAGS) \ virt_la_LDFLAGS = $(PLUGIN_LDFLAGS) virt_la_LIBADD = libignorelist.la $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS) -# TODO: enable once we support only modern libvirts which depends on libnl-3 -# the libvirt on wheezy is linked in libnl v1, and there is a small leak here, -# triggered by the library initialization. There are no means to avoid it, -# and libvirt switched to libnl3 anyway -#test_plugin_virt_SOURCES = src/virt_test.c -#test_plugin_virt_CPPFLAGS = $(AM_CPPFLAGS) \ -# $(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS) -#test_plugin_virt_LDFLAGS = $(PLUGIN_LDFLAGS) -#test_plugin_virt_LDADD = libplugin_mock.la \ -# $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS) -#check_PROGRAMS += test_plugin_virt -#TESTS += test_plugin_virt +test_plugin_virt_SOURCES = src/virt_test.c +test_plugin_virt_CPPFLAGS = $(AM_CPPFLAGS) \ + $(BUILD_WITH_LIBVIRT_CPPFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS) +test_plugin_virt_LDFLAGS = $(PLUGIN_LDFLAGS) \ + $(BUILD_WITH_LIBVIRT_LDFLAGS) $(BUILD_WITH_LIBXML2_LDFLAGS) +test_plugin_virt_LDADD = libplugin_mock.la \ + $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS) +check_PROGRAMS += test_plugin_virt +TESTS += test_plugin_virt endif if BUILD_PLUGIN_VMEM @@ -1984,9 +2028,9 @@ install-exec-hook: $(mkinstalldirs) $(DESTDIR)$(sysconfdir) if test -e $(DESTDIR)$(sysconfdir)/collectd.conf; \ then \ - $(INSTALL) -m 0640 $(srcdir)/src/collectd.conf $(DESTDIR)$(sysconfdir)/collectd.conf.pkg-orig; \ + $(INSTALL) -m 0640 $(builddir)/src/collectd.conf $(DESTDIR)$(sysconfdir)/collectd.conf.pkg-orig; \ else \ - $(INSTALL) -m 0640 $(srcdir)/src/collectd.conf $(DESTDIR)$(sysconfdir)/collectd.conf; \ + $(INSTALL) -m 0640 $(builddir)/src/collectd.conf $(DESTDIR)$(sysconfdir)/collectd.conf; \ fi; \ $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) $(INSTALL) -m 0644 $(srcdir)/src/types.db $(DESTDIR)$(pkgdatadir)/types.db; diff --git a/README b/README index 43df03b8..2210b2b9 100644 --- a/README +++ b/README @@ -465,7 +465,11 @@ Features - amqp Sends JSON-encoded data to an Advanced Message Queuing Protocol (AMQP) - server, such as RabbitMQ. + 0.9.1 server, such as RabbitMQ. + + - amqp1 + Sends JSON-encoded data to an Advanced Message Queuing Protocol (AMQP) + 1.0 server, such as Qpid Dispatch Router or Apache Artemis Broker. - csv Write to comma separated values (CSV) files. This needs lots of @@ -908,8 +912,14 @@ Prerequisites are supported. + * libqpid-proton (optional) + Used by the `amqp1' plugin for AMQP 1.0 connections, for example to + Qdrouterd. + + * librabbitmq (optional; also called “rabbitmq-c”) - Used by the `amqp' plugin for AMQP connections, for example to RabbitMQ. + Used by the `amqp' plugin for AMQP 0.9.1 connections, for example to + RabbitMQ. * librdkafka (optional; also called “rdkafka”) diff --git a/configure.ac b/configure.ac index 352a7b66..7a14e01b 100644 --- a/configure.ac +++ b/configure.ac @@ -766,10 +766,9 @@ AC_CHECK_FUNCS_ONCE([ \ AC_FUNC_STRERROR_R SAVE_CFLAGS="$CFLAGS" -# Emulate behavior of src/Makefile.am -if test "x$GCC" = "xyes"; then - CFLAGS="$CFLAGS -Wall -Werror" -fi +CFLAGS="-Wall -Werror" +SAVE_LDFAGS="$LDFLAGS" +LDFLAGS="" AC_CACHE_CHECK([for strtok_r], [c_cv_have_strtok_r_default], @@ -842,6 +841,7 @@ if test "x$c_cv_have_strtok_r_default" = "xno"; then fi CFLAGS="$SAVE_CFLAGS" +LDFLAGS="$SAVE_LDFLAGS" if test "x$c_cv_have_strtok_r_reentrant" = "xyes"; then CFLAGS="$CFLAGS -D_REENTRANT=1" fi @@ -1567,7 +1567,7 @@ if test "x$have_getmntent" = "xlibc"; then struct mntent *me; fh = setmntent ("/etc/mtab", "r"); me = getmntent (fh); - return(me->mnt_passno); + return me->mnt_passno; ]] ) ], @@ -1590,7 +1590,7 @@ if test "x$have_getmntent" = "xlibc"; then int status; fh = fopen ("/etc/mnttab", "r"); status = getmntent (fh, &mt); - return(status); + return status; ]] ) ], @@ -1878,14 +1878,23 @@ fi # libi2c-dev if test "x$ac_system" = "xLinux"; then + with_libi2c_libs="" + AC_CHECK_HEADERS([i2c/smbus.h], + [with_libi2c_libs="-li2c"] + ) AC_CHECK_DECL([i2c_smbus_read_i2c_block_data], [with_libi2c="yes"], [with_libi2c="no (symbol i2c_smbus_read_i2c_block_data not found - have you installed libi2c-dev ?)"], [[ #include #include + #if HAVE_I2C_SMBUS_H + # include + #endif ]] ) + BUILD_WITH_LIBI2C_LIBS="$with_libi2c_libs" + AC_SUBST([BUILD_WITH_LIBI2C_LIBS]) else with_libi2c="no (Linux only)" fi @@ -3049,18 +3058,33 @@ else PKG_CHECK_MODULES([LUA], [lua5.3], [with_liblua="yes"], [ - PKG_CHECK_MODULES([LUA], [lua-5.2], + PKG_CHECK_MODULES([LUA], [lua53], [with_liblua="yes"], [ - PKG_CHECK_MODULES([LUA], [lua5.2], + PKG_CHECK_MODULES([LUA], [lua-5.2], [with_liblua="yes"], [ - PKG_CHECK_MODULES([LUA], [lua-5.1], + PKG_CHECK_MODULES([LUA], [lua5.2], [with_liblua="yes"], [ - PKG_CHECK_MODULES([LUA], [lua5.1], + PKG_CHECK_MODULES([LUA], [lua52], [with_liblua="yes"], - [with_liblua="no (pkg-config cannot find liblua)"] + [ + PKG_CHECK_MODULES([LUA], [lua-5.1], + [with_liblua="yes"], + [ + PKG_CHECK_MODULES([LUA], [lua5.1], + [with_liblua="yes"], + [ + PKG_CHECK_MODULES([LUA], [lua51], + [with_liblua="yes"], + [with_liblua="no (pkg-config cannot find liblua)"] + ) + ] + ) + ] + ) + ] ) ] ) @@ -3660,6 +3684,18 @@ if test "x$with_libmnl" = "xyes"; then [[#include ]] ) + AC_CHECK_MEMBERS([struct rtnl_link_stats.rx_nohandler], + [], + [], + [[#include ]] + ) + + AC_CHECK_MEMBERS([struct rtnl_link_stats64.rx_nohandler], + [], + [], + [[#include ]] + ) + AC_CHECK_LIB([mnl], [mnl_nlmsg_get_payload], [with_libmnl="yes"], [with_libmnl="no (symbol 'mnl_nlmsg_get_payload' not found)"], @@ -3781,7 +3817,7 @@ if test "x$with_libnetsnmp" = "xyes"; then LDFLAGS="$LDFLAGS $with_libnetsnmp_ldflags" AC_CHECK_LIB([netsnmp], [init_snmp], - [with_libnetsmp="yes"], + [with_libnetsnmp="yes"], [with_libnetsnmp="no (libnetsnmp not found)"] ) @@ -3789,6 +3825,62 @@ if test "x$with_libnetsnmp" = "xyes"; then fi if test "x$with_libnetsnmp" = "xyes"; then + SAVE_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $with_libnetsnmp_ldflags" + + AC_CHECK_LIB([netsnmp], [netsnmp_get_version], + [with_libnetsnmp="yes"], + [with_libnetsnmp="no (couldn't get libnetsnmp version)"] + ) + + LDFLAGS="$SAVE_LDFLAGS" +fi + +if test "x$with_libnetsnmp" = "xyes"; then + SAVE_CPPFLAGS="$CPPFLAGS" + SAVE_LDFLAGS="$LDFLAGS" + SAVE_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $with_libnetsnmp_cppflags -Wall -Werror" + LDFLAGS="$LDFLAGS $with_libnetsnmp_ldflags" + LIBS="$LIBS -lnetsnmp" + + AC_CACHE_CHECK([whether netsnmp library has old API], + [c_cv_have_netsnmp_old_api], + [ + AC_LINK_IFELSE( + [ + AC_LANG_PROGRAM( + [[ + #include + #include + ]], + [[ + netsnmp_variable_list *key = SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);; + int val; + u_char type = ASN_INTEGER; + snmp_set_var_value(key, &val, sizeof(val)); + snmp_set_var_typed_value(key, type, &val, sizeof(val)); + return 0; + ]] + ) + ], + [c_cv_have_netsnmp_old_api="no"], + [c_cv_have_netsnmp_old_api="yes"] + ) + ] + ) + + if test "x$c_cv_have_netsnmp_old_api" = "xyes"; then + AC_DEFINE([HAVE_NETSNMP_OLD_API], [1], + ["Define 1 if you have old netsnmp API]") + fi + + CPPFLAGS="$SAVE_CPPFLAGS" + LDFLAGS="$SAVE_LDFLAGS" + LIBS="$SAVE_LIBS" +fi + +if test "x$with_libnetsnmp" = "xyes"; then BUILD_WITH_LIBNETSNMP_CPPFLAGS="$with_libnetsnmp_cppflags" BUILD_WITH_LIBNETSNMP_LDFLAGS="$with_libnetsnmp_ldflags" BUILD_WITH_LIBNETSNMP_LIBS="-lnetsnmp" @@ -3799,7 +3891,7 @@ AC_SUBST([BUILD_WITH_LIBNETSNMP_LDFLAGS]) AC_SUBST([BUILD_WITH_LIBNETSNMP_LIBS]) # }}} -# --with-libnetsmpagent {{{ +# --with-libnetsnmpagent {{{ AC_ARG_WITH([libnetsnmpagent], [AS_HELP_STRING([--with-libnetsnmpagent@<:@=PREFIX@:>@], [Path to libnetsnmpagent.])], [ @@ -4081,7 +4173,7 @@ if test "x$with_libpcap" = "xyes"; then [[#include ]], [[ int val = PCAP_ERROR_IFACE_NOT_UP; - return(val); + return val; ]] ) ], @@ -4686,6 +4778,56 @@ if test "$with_libpython" != "xno"; then fi # }}} --with-libpython +# --with-libqpid_proton {{{ +AC_ARG_WITH([libqpid_proton], + [AS_HELP_STRING([--with-libqpid_proton@<:@=PREFIX@:>@], [Path to libqpid_proton.])], + [ + if test "x$withval" != "xno" && test "x$withval" != "xyes"; then + with_libqpid_proton_cppflags="-I$withval/include" + with_libqpid_proton_ldflags="-L$withval/lib" + with_libqpid_proton="yes" + else + with_libqpid_proton="$withval" + fi + ], + [with_libqpid_proton="yes"] +) + +if test "x$with_libqpid_proton" = "xyes"; then + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_libqpid_proton_cppflags" + + AC_CHECK_HEADERS([proton/proactor.h], + [with_libqpid_proton="yes"], + [with_libqpid_proton="no (proton/proactor.h not found)"] + ) + + CPPFLAGS="$SAVE_CPPFLAGS" +fi + +if test "x$with_libqpid_proton" = "xyes"; then + SAVE_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $with_libqpid_proton_ldflags" + + AC_CHECK_LIB([qpid-proton], [pn_connection], + [with_libqpid_proton="yes"], + [with_libqpid_proton="no (Symbol 'pn_connection' not found)"]) + + LDFLAGS="$SAVE_LDFLAGS" +fi + +if test "x$with_libqpid_proton" = "xyes"; then + BUILD_WITH_LIBQPIDPROTON_CPPFLAGS="$with_libqpid_proton_cppflags" + BUILD_WITH_LIBQPIDPROTON_LDFLAGS="$with_libqpid_proton_ldflags" + BUILD_WITH_LIBQPIDPROTON_LIBS="-lqpid-proton" +fi + +AC_SUBST(BUILD_WITH_LIBQPIDPROTON_CPPFLAGS) +AC_SUBST(BUILD_WITH_LIBQPIDPROTON_LDFLAGS) +AC_SUBST(BUILD_WITH_LIBQPIDPROTON_LIBS) + +# }}} + # --with-librabbitmq {{{ AC_ARG_WITH([librabbitmq], [AS_HELP_STRING([--with-librabbitmq@<:@=PREFIX@:>@], [Path to librabbitmq.])], @@ -6511,6 +6653,7 @@ m4_divert_once([HELP_ENABLE], []) AC_PLUGIN([aggregation], [yes], [Aggregation plugin]) AC_PLUGIN([amqp], [$with_librabbitmq], [AMQP output plugin]) +AC_PLUGIN([amqp1], [$with_libqpid_proton], [AMQP 1.0 output plugin]) AC_PLUGIN([apache], [$with_libcurl], [Apache httpd statistics]) AC_PLUGIN([apcups], [yes], [Statistics of UPSes by APC]) AC_PLUGIN([apple_sensors], [$with_libiokit], [Apple hardware sensors]) @@ -6899,6 +7042,7 @@ AC_MSG_RESULT([ libpqos . . . . . . . $with_libpqos]) AC_MSG_RESULT([ libprotobuf . . . . . $with_libprotobuf]) AC_MSG_RESULT([ libprotobuf-c . . . . $with_libprotobuf_c]) AC_MSG_RESULT([ libpython . . . . . . $with_libpython]) +AC_MSG_RESULT([ libqpid-proton . . . $with_libqpid_proton]) AC_MSG_RESULT([ librabbitmq . . . . . $with_librabbitmq]) AC_MSG_RESULT([ libriemann-client . . $with_libriemann_client]) AC_MSG_RESULT([ librdkafka . . . . . $with_librdkafka]) @@ -6930,6 +7074,7 @@ AC_MSG_RESULT() AC_MSG_RESULT([ Modules:]) AC_MSG_RESULT([ aggregation . . . . . $enable_aggregation]) AC_MSG_RESULT([ amqp . . . . . . . $enable_amqp]) +AC_MSG_RESULT([ amqp1 . . . . . . . $enable_amqp1]) AC_MSG_RESULT([ apache . . . . . . . $enable_apache]) AC_MSG_RESULT([ apcups . . . . . . . $enable_apcups]) AC_MSG_RESULT([ apple_sensors . . . . $enable_apple_sensors]) diff --git a/contrib/redhat/collectd.spec b/contrib/redhat/collectd.spec index 3cefc1bd..6f86b7e8 100644 --- a/contrib/redhat/collectd.spec +++ b/contrib/redhat/collectd.spec @@ -38,9 +38,13 @@ %global _hardened_build 1 %{?perl_default_filter} +# disable collectd debug by default +%bcond_with debug + # plugins enabled by default %define with_aggregation 0%{!?_without_aggregation:1} %define with_amqp 0%{!?_without_amqp:1} +%define with_amqp1 0%{!?_without_amqp1:1} %define with_apache 0%{!?_without_apache:1} %define with_apcups 0%{!?_without_apcups:1} %define with_ascent 0%{!?_without_ascent:1} @@ -277,13 +281,24 @@ every 10 seconds by default. %if %{with_amqp} %package amqp -Summary: AMQP plugin for collectd +Summary: AMQP 0.9 plugin for collectd Group: System Environment/Daemons Requires: %{name}%{?_isa} = %{version}-%{release} BuildRequires: librabbitmq-devel %description amqp -The AMQP plugin transmits or receives values collected by collectd via the -Advanced Message Queuing Protocol (AMQP). +The AMQP 0.9 plugin transmits or receives values collected by collectd via the +Advanced Message Queuing Protocol v0.9 (AMQP). +%endif + +%if %{with_amqp1} +%package amqp1 +Summary: AMQP 1.0 plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: qpid-proton-c-devel +%description amqp1 +The AMQP 1.0 plugin transmits or receives values collected by collectd via the +Advanced Message Queuing Protocol v1.0 (AMQP1). %endif %if %{with_apache} @@ -1015,6 +1030,12 @@ Collectd utilities %define _with_amqp --disable-amqp %endif +%if %{with_amqp1} +%define _with_amqp1 --enable-amqp1 +%else +%define _with_amqp1 --disable-amqp1 +%endif + %if %{with_apache} %define _with_apache --enable-apache %else @@ -1872,8 +1893,15 @@ Collectd utilities %define _with_zookeeper --disable-zookeeper %endif +%if %{with debug} +%define _feature_debug --enable-debug +%else +%define _feature_debug --disable-debug +%endif + %configure CFLAGS="%{optflags} -DLT_LAZY_OR_NOW=\"RTLD_LAZY|RTLD_GLOBAL\"" \ %{?_python_config} \ + %{?_feature_debug} \ --disable-static \ --enable-all-plugins=yes \ --enable-match_empty_counter \ @@ -1888,6 +1916,7 @@ Collectd utilities --enable-target_v5upgrade \ %{?_with_aggregation} \ %{?_with_amqp} \ + %{?_with_amqp1} \ %{?_with_apache} \ %{?_with_apcups} \ %{?_with_apple_sensors} \ @@ -2399,6 +2428,11 @@ fi %{_libdir}/%{name}/amqp.so %endif +%if %{with_amqp1} +%files amqp1 +%{_libdir}/%{name}/amqp1.so +%endif + %if %{with_apache} %files apache %{_libdir}/%{name}/apache.so diff --git a/src/aggregation.c b/src/aggregation.c index 0ed97ae1..a8021996 100644 --- a/src/aggregation.c +++ b/src/aggregation.c @@ -48,12 +48,12 @@ struct aggregation_s /* {{{ */ char *set_plugin_instance; char *set_type_instance; - _Bool calc_num; - _Bool calc_sum; - _Bool calc_average; - _Bool calc_min; - _Bool calc_max; - _Bool calc_stddev; + bool calc_num; + bool calc_sum; + bool calc_average; + bool calc_min; + bool calc_max; + bool calc_stddev; }; /* }}} */ typedef struct aggregation_s aggregation_t; @@ -83,27 +83,25 @@ struct agg_instance_s /* {{{ */ agg_instance_t *next; }; /* }}} */ -static lookup_t *lookup = NULL; +static lookup_t *lookup; static pthread_mutex_t agg_instance_list_lock = PTHREAD_MUTEX_INITIALIZER; -static agg_instance_t *agg_instance_list_head = NULL; +static agg_instance_t *agg_instance_list_head; -static _Bool agg_is_regex(char const *str) /* {{{ */ +static bool agg_is_regex(char const *str) /* {{{ */ { - size_t len; - if (str == NULL) - return 0; + return false; - len = strlen(str); + size_t len = strlen(str); if (len < 3) - return 0; + return false; if ((str[0] == '/') && (str[len - 1] == '/')) - return 1; + return true; else - return 0; -} /* }}} _Bool agg_is_regex */ + return false; +} /* }}} bool agg_is_regex */ static void agg_destroy(aggregation_t *agg) /* {{{ */ { @@ -227,11 +225,9 @@ static int agg_instance_create_name(agg_instance_t *inst, /* {{{ */ static agg_instance_t *agg_instance_create(data_set_t const *ds, /* {{{ */ value_list_t const *vl, aggregation_t *agg) { - agg_instance_t *inst; - DEBUG("aggregation plugin: Creating new instance."); - inst = calloc(1, sizeof(*inst)); + agg_instance_t *inst = calloc(1, sizeof(*inst)); if (inst == NULL) { ERROR("aggregation plugin: calloc() failed."); return NULL; @@ -282,8 +278,6 @@ static agg_instance_t *agg_instance_create(data_set_t const *ds, /* {{{ */ * and non-zero otherwise. */ static int agg_instance_update(agg_instance_t *inst, /* {{{ */ data_set_t const *ds, value_list_t const *vl) { - gauge_t *rate; - if (ds->ds_num != 1) { ERROR("aggregation plugin: The \"%s\" type (data set) has more than one " "data source. This is currently not supported by this plugin. " @@ -292,7 +286,7 @@ static int agg_instance_update(agg_instance_t *inst, /* {{{ */ return EINVAL; } - rate = uc_get_rate(ds, vl); + gauge_t *rate = uc_get_rate(ds, vl); if (rate == NULL) { char ident[6 * DATA_MAX_NAME_LEN]; FORMAT_VL(ident, sizeof(ident), vl); @@ -328,16 +322,15 @@ static int agg_instance_read_func(agg_instance_t *inst, /* {{{ */ rate_to_value_state_t *state, value_list_t *vl, char const *pi_prefix, cdtime_t t) { - value_t v; - int status; - if (pi_prefix[0] != 0) subst_string(vl->plugin_instance, sizeof(vl->plugin_instance), pi_prefix, AGG_FUNC_PLACEHOLDER, func); else sstrncpy(vl->plugin_instance, func, sizeof(vl->plugin_instance)); - status = rate_to_value(&v, rate, state, inst->ds_type, t); + value_t v; + + int status = rate_to_value(&v, rate, state, inst->ds_type, t); if (status != 0) { /* If this is the first iteration and rate_to_value() was asked to return a * COUNTER or a DERIVE, it will return EAGAIN. Catch this and handle @@ -473,8 +466,6 @@ static void agg_lookup_free_obj_callback(void *user_obj) /* {{{ */ static int agg_config_handle_group_by(oconfig_item_t const *ci, /* {{{ */ aggregation_t *agg) { for (int i = 0; i < ci->values_num; i++) { - char const *value; - if (ci->values[i].type != OCONFIG_TYPE_STRING) { ERROR("aggregation plugin: Argument %i of the \"GroupBy\" option " "is not a string.", @@ -482,7 +473,7 @@ static int agg_config_handle_group_by(oconfig_item_t const *ci, /* {{{ */ continue; } - value = ci->values[i].value.string; + const char *value = ci->values[i].value.string; if (strcasecmp("Host", value) == 0) agg->group_by |= LU_GROUP_BY_HOST; @@ -580,7 +571,7 @@ static int agg_config_aggregation(oconfig_item_t *ci) /* {{{ */ agg->regex_fields |= LU_GROUP_BY_TYPE_INSTANCE; /* Sanity checking */ - _Bool is_valid = 1; + bool is_valid = true; if (strcmp("/.*/", agg->ident.type) == 0) /* {{{ */ { ERROR("aggregation plugin: It appears you did not specify the required " @@ -589,13 +580,13 @@ static int agg_config_aggregation(oconfig_item_t *ci) /* {{{ */ "Type \"%s\", TypeInstance \"%s\")", agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, agg->ident.type, agg->ident.type_instance); - is_valid = 0; + is_valid = false; } else if (strchr(agg->ident.type, '/') != NULL) { ERROR("aggregation plugin: The \"Type\" may not contain the '/' " "character. Especially, it may not be a regex. The current " "value is \"%s\".", agg->ident.type); - is_valid = 0; + is_valid = false; } /* }}} */ /* Check that there is at least one regex field without a grouping. {{{ */ @@ -608,7 +599,7 @@ static int agg_config_aggregation(oconfig_item_t *ci) /* {{{ */ "Type \"%s\", TypeInstance \"%s\")", agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, agg->ident.type, agg->ident.type_instance); - is_valid = 0; + is_valid = false; } /* }}} */ /* Check that all grouping fields are regular expressions. {{{ */ @@ -620,7 +611,7 @@ static int agg_config_aggregation(oconfig_item_t *ci) /* {{{ */ "Type \"%s\", TypeInstance \"%s\")", agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, agg->ident.type, agg->ident.type_instance); - is_valid = 0; + is_valid = false; } /* }}} */ if (!agg->calc_num && !agg->calc_sum && !agg->calc_average /* {{{ */ @@ -631,7 +622,7 @@ static int agg_config_aggregation(oconfig_item_t *ci) /* {{{ */ "Type \"%s\", TypeInstance \"%s\")", agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, agg->ident.type, agg->ident.type_instance); - is_valid = 0; + is_valid = false; } /* }}} */ if (!is_valid) { /* {{{ */ @@ -687,11 +678,8 @@ static int agg_config(oconfig_item_t *ci) /* {{{ */ static int agg_read(void) /* {{{ */ { - cdtime_t t; - int success; - - t = cdtime(); - success = 0; + cdtime_t t = cdtime(); + int success = 0; pthread_mutex_lock(&agg_instance_list_lock); @@ -708,9 +696,7 @@ static int agg_read(void) /* {{{ */ for (agg_instance_t *this = agg_instance_list_head; this != NULL; this = this->next) { - int status; - - status = agg_instance_read(this, t); + int status = agg_instance_read(this, t); if (status != 0) WARNING("aggregation plugin: Reading an aggregation instance " "failed with status %i.", @@ -726,9 +712,7 @@ static int agg_read(void) /* {{{ */ static int agg_write(data_set_t const *ds, value_list_t const *vl, /* {{{ */ __attribute__((unused)) user_data_t *user_data) { - _Bool created_by_aggregation = 0; - int status; - + bool created_by_aggregation = false; /* Ignore values that were created by the aggregation plugin to avoid weird * effects. */ (void)meta_data_get_boolean(vl->meta, "aggregation:created", @@ -736,6 +720,8 @@ static int agg_write(data_set_t const *ds, value_list_t const *vl, /* {{{ */ if (created_by_aggregation) return 0; + int status; + if (lookup == NULL) status = ENOENT; else { diff --git a/src/amqp.c b/src/amqp.c index 6c184488..281130b1 100644 --- a/src/amqp.c +++ b/src/amqp.c @@ -66,7 +66,7 @@ int amqp_socket_close(amqp_socket_t *); * Data types */ struct camqp_config_s { - _Bool publish; + bool publish; char *name; char *host; @@ -83,7 +83,7 @@ struct camqp_config_s { /* publish only */ uint8_t delivery_mode; - _Bool store_rates; + bool store_rates; int format; /* publish & graphite format only */ char *prefix; @@ -94,8 +94,8 @@ struct camqp_config_s { /* subscribe only */ char *exchange_type; char *queue; - _Bool queue_durable; - _Bool queue_auto_delete; + bool queue_durable; + bool queue_auto_delete; amqp_connection_state_t connection; pthread_mutex_t lock; @@ -111,9 +111,9 @@ static const char *def_user = "guest"; static const char *def_password = "guest"; static const char *def_exchange = "amq.fanout"; -static pthread_t *subscriber_threads = NULL; -static size_t subscriber_threads_num = 0; -static _Bool subscriber_threads_running = 1; +static pthread_t *subscriber_threads; +static size_t subscriber_threads_num; +static bool subscriber_threads_running = true; #define CONF(c, f) (((c)->f != NULL) ? (c)->f : def_##f) @@ -176,16 +176,16 @@ static char *camqp_bytes_cstring(amqp_bytes_t *in) /* {{{ */ return ret; } /* }}} char *camqp_bytes_cstring */ -static _Bool camqp_is_error(camqp_config_t *conf) /* {{{ */ +static bool camqp_is_error(camqp_config_t *conf) /* {{{ */ { amqp_rpc_reply_t r; r = amqp_get_rpc_reply(conf->connection); if (r.reply_type == AMQP_RESPONSE_NORMAL) - return 0; + return false; - return 1; -} /* }}} _Bool camqp_is_error */ + return true; +} /* }}} bool camqp_is_error */ static char *camqp_strerror(camqp_config_t *conf, /* {{{ */ char *buffer, size_t buffer_size) { @@ -396,7 +396,7 @@ static int camqp_setup_queue(camqp_config_t *conf) /* {{{ */ static int camqp_connect(camqp_config_t *conf) /* {{{ */ { - static time_t last_connect_time = 0; + static time_t last_connect_time; amqp_rpc_reply_t reply; int status; @@ -825,7 +825,7 @@ static int camqp_config_set_format(oconfig_item_t *ci, /* {{{ */ } /* }}} int config_set_string */ static int camqp_config_connection(oconfig_item_t *ci, /* {{{ */ - _Bool publish) { + bool publish) { camqp_config_t *conf; int status; @@ -850,7 +850,7 @@ static int camqp_config_connection(oconfig_item_t *ci, /* {{{ */ /* publish only */ conf->delivery_mode = CAMQP_DM_VOLATILE; - conf->store_rates = 0; + conf->store_rates = false; conf->graphite_flags = 0; /* publish & graphite only */ conf->prefix = NULL; @@ -859,8 +859,8 @@ static int camqp_config_connection(oconfig_item_t *ci, /* {{{ */ /* subscribe only */ conf->exchange_type = NULL; conf->queue = NULL; - conf->queue_durable = 0; - conf->queue_auto_delete = 1; + conf->queue_durable = false; + conf->queue_auto_delete = true; /* general */ conf->connection = NULL; pthread_mutex_init(&conf->lock, /* attr = */ NULL); @@ -902,7 +902,7 @@ static int camqp_config_connection(oconfig_item_t *ci, /* {{{ */ else if (strcasecmp("RoutingKey", child->key) == 0) status = cf_util_get_string(child, &conf->routing_key); else if ((strcasecmp("Persistent", child->key) == 0) && publish) { - _Bool tmp = 0; + bool tmp = 0; status = cf_util_get_boolean(child, &tmp); if (tmp) conf->delivery_mode = CAMQP_DM_PERSISTENT; @@ -998,9 +998,9 @@ static int camqp_config(oconfig_item_t *ci) /* {{{ */ oconfig_item_t *child = ci->children + i; if (strcasecmp("Publish", child->key) == 0) - camqp_config_connection(child, /* publish = */ 1); + camqp_config_connection(child, /* publish = */ true); else if (strcasecmp("Subscribe", child->key) == 0) - camqp_config_connection(child, /* publish = */ 0); + camqp_config_connection(child, /* publish = */ false); else WARNING("amqp plugin: Ignoring unknown config option \"%s\".", child->key); diff --git a/src/amqp1.c b/src/amqp1.c new file mode 100644 index 00000000..635af0f7 --- /dev/null +++ b/src/amqp1.c @@ -0,0 +1,772 @@ +/** + * collectd - src/amqp1.c + * Copyright(c) 2017 Red Hat Inc. + * + * 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: + * Andy Smith + */ + +#include "collectd.h" + +#include "common.h" +#include "plugin.h" +#include "utils_cmd_putval.h" +#include "utils_deq.h" +#include "utils_format_graphite.h" +#include "utils_format_json.h" +#include "utils_random.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define BUFSIZE 8192 +#define AMQP1_FORMAT_JSON 0 +#define AMQP1_FORMAT_COMMAND 1 +#define AMQP1_FORMAT_GRAPHITE 2 + +typedef struct amqp1_config_transport_s { + DEQ_LINKS(struct amqp1_config_transport_s); + char *name; + char *host; + char *port; + char *user; + char *password; + char *address; + int retry_delay; +} amqp1_config_transport_t; + +typedef struct amqp1_config_instance_s { + DEQ_LINKS(struct amqp1_config_instance_s); + char *name; + bool notify; + uint8_t format; + unsigned int graphite_flags; + bool store_rates; + char *prefix; + char *postfix; + char escape_char; + bool pre_settle; + char send_to[1024]; +} amqp1_config_instance_t; + +DEQ_DECLARE(amqp1_config_instance_t, amqp1_config_instance_list_t); + +typedef struct cd_message_s { + DEQ_LINKS(struct cd_message_s); + pn_rwbytes_t mbuf; + amqp1_config_instance_t *instance; +} cd_message_t; + +DEQ_DECLARE(cd_message_t, cd_message_list_t); + +/* + * Globals + */ +static pn_connection_t *conn; +static pn_link_t *sender; +static pn_proactor_t *proactor; +static pthread_mutex_t send_lock; +static cd_message_list_t out_messages; +static uint64_t cd_tag = 1; +static uint64_t acknowledged; +static amqp1_config_transport_t *transport; +static bool stopping; +static bool event_thread_running; +static pthread_t event_thread_id; + +/* + * Functions + */ +static void cd_message_free(cd_message_t *cdm) { + free(cdm->mbuf.start); + free(cdm); +} /* }}} void cd_message_free */ + +static int amqp1_send_out_messages(pn_link_t *link) /* {{{ */ +{ + uint64_t dtag; + cd_message_list_t to_send; + cd_message_t *cdm; + int link_credit = pn_link_credit(link); + int event_count = 0; + pn_delivery_t *dlv; + + if (stopping) { + return 0; + } + + DEQ_INIT(to_send); + + pthread_mutex_lock(&send_lock); + + if (link_credit > 0) { + dtag = cd_tag; + cdm = DEQ_HEAD(out_messages); + while (cdm) { + DEQ_REMOVE_HEAD(out_messages); + DEQ_INSERT_TAIL(to_send, cdm); + if (DEQ_SIZE(to_send) == (size_t)link_credit) + break; + cdm = DEQ_HEAD(out_messages); + } + cd_tag += DEQ_SIZE(to_send); + } + + pthread_mutex_unlock(&send_lock); + + /* message is already formatted and encoded */ + cdm = DEQ_HEAD(to_send); + while (cdm) { + DEQ_REMOVE_HEAD(to_send); + dtag++; + dlv = pn_delivery(link, pn_dtag((const char *)&dtag, sizeof(dtag))); + pn_link_send(link, cdm->mbuf.start, cdm->mbuf.size); + pn_link_advance(link); + if (cdm->instance->pre_settle == true) { + pn_delivery_settle(dlv); + } + event_count++; + cd_message_free(cdm); + cdm = DEQ_HEAD(to_send); + } + + return event_count; +} /* }}} int amqp1_send_out_messages */ + +static void check_condition(pn_event_t *e, pn_condition_t *cond) /* {{{ */ +{ + if (pn_condition_is_set(cond)) { + ERROR("amqp1 plugin: %s: %s: %s", pn_event_type_name(pn_event_type(e)), + pn_condition_get_name(cond), pn_condition_get_description(cond)); + pn_connection_close(pn_event_connection(e)); + conn = NULL; + } +} /* }}} void check_condition */ + +static bool handle(pn_event_t *event) /* {{{ */ +{ + + switch (pn_event_type(event)) { + + case PN_CONNECTION_INIT: { + conn = pn_event_connection(event); + pn_connection_set_container(conn, transport->name); + pn_connection_open(conn); + pn_session_t *ssn = pn_session(conn); + pn_session_open(ssn); + sender = pn_sender(ssn, "cd-sender"); + pn_link_set_snd_settle_mode(sender, PN_SND_MIXED); + pn_link_open(sender); + break; + } + + case PN_LINK_FLOW: { + /* peer has given us credit, send outbound messages */ + amqp1_send_out_messages(sender); + break; + } + + case PN_DELIVERY: { + /* acknowledgement from peer that a message was delivered */ + pn_delivery_t *dlv = pn_event_delivery(event); + if (pn_delivery_remote_state(dlv) == PN_ACCEPTED) { + pn_delivery_settle(dlv); + acknowledged++; + } + break; + } + + case PN_CONNECTION_WAKE: { + if (!stopping) { + amqp1_send_out_messages(sender); + } + break; + } + + case PN_TRANSPORT_CLOSED: { + check_condition(event, pn_transport_condition(pn_event_transport(event))); + break; + } + + case PN_CONNECTION_REMOTE_CLOSE: { + check_condition(event, + pn_session_remote_condition(pn_event_session(event))); + pn_connection_close(pn_event_connection(event)); + break; + } + + case PN_SESSION_REMOTE_CLOSE: { + check_condition(event, + pn_session_remote_condition(pn_event_session(event))); + pn_connection_close(pn_event_connection(event)); + break; + } + + case PN_LINK_REMOTE_CLOSE: + case PN_LINK_REMOTE_DETACH: { + check_condition(event, pn_link_remote_condition(pn_event_link(event))); + pn_connection_close(pn_event_connection(event)); + break; + } + + case PN_PROACTOR_INACTIVE: { + return false; + } + + default: + break; + } + return true; +} /* }}} bool handle */ + +static void *event_thread(void __attribute__((unused)) * arg) /* {{{ */ +{ + char addr[PN_MAX_ADDR]; + cd_message_t *cdm; + + /* setup proactor */ + proactor = pn_proactor(); + pn_proactor_addr(addr, sizeof(addr), transport->host, transport->port); + + while (!stopping) { + /* make connection */ + conn = pn_connection(); + if (transport->user != NULL) { + pn_connection_set_user(conn, transport->user); + pn_connection_set_password(conn, transport->password); + } + pn_proactor_connect(proactor, conn, addr); + + bool engine_running = true; + while (engine_running && !stopping) { + pn_event_batch_t *events = pn_proactor_wait(proactor); + pn_event_t *e; + while ((e = pn_event_batch_next(events))) { + engine_running = handle(e); + if (!engine_running) { + break; + } + } + pn_proactor_done(proactor, events); + } + + pn_proactor_release_connection(conn); + + DEBUG("amqp1 plugin: retrying connection"); + int delay = transport->retry_delay; + while (delay-- > 0 && !stopping) { + sleep(1.0); + } + } + + pn_proactor_disconnect(proactor, NULL); + + /* Free the remaining out_messages */ + cdm = DEQ_HEAD(out_messages); + while (cdm) { + DEQ_REMOVE_HEAD(out_messages); + cd_message_free(cdm); + cdm = DEQ_HEAD(out_messages); + } + + event_thread_running = false; + + return NULL; +} /* }}} void event_thread */ + +static int encqueue(cd_message_t *cdm, + amqp1_config_instance_t *instance) /* {{{ */ +{ + /* encode message */ + pn_message_t *message = pn_message(); + pn_message_set_address(message, instance->send_to); + pn_data_t *body = pn_message_body(message); + pn_data_clear(body); + pn_data_put_binary(body, pn_bytes(cdm->mbuf.size, cdm->mbuf.start)); + pn_data_exit(body); + + /* put_binary copies and stores so ok to use mbuf */ + cdm->mbuf.size = BUFSIZE; + + int status; + char *start; + while ((status = pn_message_encode(message, cdm->mbuf.start, + &cdm->mbuf.size)) == PN_OVERFLOW) { + DEBUG("amqp1 plugin: increasing message buffer size %zu", cdm->mbuf.size); + cdm->mbuf.size *= 2; + start = realloc(cdm->mbuf.start, cdm->mbuf.size); + if (start == NULL) { + status = -1; + break; + } else { + cdm->mbuf.start = start; + } + } + + if (status != 0) { + ERROR("amqp1 plugin: error encoding message: %s", + pn_error_text(pn_message_error(message))); + pn_message_free(message); + return -1; + } + + pthread_mutex_lock(&send_lock); + DEQ_INSERT_TAIL(out_messages, cdm); + pthread_mutex_unlock(&send_lock); + + pn_message_free(message); + + /* activate the sender */ + if (conn) { + pn_connection_wake(conn); + } + + return 0; +} /* }}} int encqueue */ + +static int amqp1_notify(notification_t const *n, + user_data_t *user_data) /* {{{ */ +{ + int status = 0; + size_t bfree = BUFSIZE; + size_t bfill = 0; + size_t bufsize = BUFSIZE; + + if (n == NULL || user_data == NULL) + return EINVAL; + + amqp1_config_instance_t *instance = user_data->data; + + if (instance->notify != true) { + ERROR("amqp1 plugin: write notification failed"); + } + + cd_message_t *cdm = malloc(sizeof(*cdm)); + if (cdm == NULL ){ + ERROR("amqp1 plugin: notify failed"); + return -1; + } + + DEQ_ITEM_INIT(cdm); + char *start = malloc(bufsize); + if (start == NULL) { + ERROR("amqp1 plugin: malloc failed"); + free(cdm); + return -1; + } + cdm->mbuf.size = bufsize; + cdm->mbuf.start = start; + cdm->instance = instance; + + switch (instance->format) { + case AMQP1_FORMAT_JSON: + format_json_initialize(cdm->mbuf.start, &bfill, &bfree); + status = format_json_notification(cdm->mbuf.start, bufsize, n); + if (status != 0) { + ERROR("amqp1 plugin: formatting notification failed"); + cd_message_free(cdm); + return status; + } + cdm->mbuf.size = strlen(cdm->mbuf.start); + if (cdm->mbuf.size >= BUFSIZE) { + ERROR("amqp1 plugin: notify format json failed"); + cd_message_free(cdm); + return -1; + } + break; + default: + ERROR("amqp1 plugin: Invalid notify format (%i).", instance->format); + cd_message_free(cdm); + return -1; + } + + /* encode message and place on outbound queue */ + status = encqueue(cdm, instance); + if (status != 0) { + ERROR("amqp1 plugin: notify enqueue failed"); + cd_message_free(cdm); + } + return status; + +} /* }}} int amqp1_notify */ + +static int amqp1_write(const data_set_t *ds, const value_list_t *vl, /* {{{ */ + user_data_t *user_data) { + int status = 0; + size_t bfree = BUFSIZE; + size_t bfill = 0; + size_t bufsize = BUFSIZE; + + if (ds == NULL || vl == NULL || transport == NULL || user_data == NULL) + return EINVAL; + + amqp1_config_instance_t *instance = user_data->data; + + if (instance->notify != false) { + ERROR("amqp1 plugin: write failed"); + } + + cd_message_t *cdm = malloc(sizeof(*cdm)); + if (cdm == NULL) { + ERROR("amqp1 plugin: malloc failed."); + return -1; + } + DEQ_ITEM_INIT(cdm); + char *start = malloc(bufsize); + if (start == NULL) { + ERROR("amqp1 plugin: malloc failed."); + free(cdm); + return -1; + } + cdm->mbuf.size = bufsize; + cdm->mbuf.start = start; + cdm->instance = instance; + + switch (instance->format) { + case AMQP1_FORMAT_COMMAND: + status = cmd_create_putval((char *)cdm->mbuf.start, bufsize, ds, vl); + if (status != 0) { + ERROR("amqp1 plugin: cmd_create_putval failed with status %i.", status); + cd_message_free(cdm); + return status; + } + cdm->mbuf.size = strlen(cdm->mbuf.start); + if (cdm->mbuf.size >= BUFSIZE) { + ERROR("amqp1 plugin: format cmd failed"); + cd_message_free(cdm); + return -1; + } + break; + case AMQP1_FORMAT_JSON: + format_json_initialize((char *)cdm->mbuf.start, &bfill, &bfree); + format_json_value_list((char *)cdm->mbuf.start, &bfill, &bfree, ds, vl, + instance->store_rates); + status= format_json_finalize((char *)cdm->mbuf.start, &bfill, &bfree); + if (status != 0) { + ERROR("amqp1 plugin: format_json_finalize failed with status %i.", status); + cd_message_free(cdm); + return(status); + } + cdm->mbuf.size = strlen(cdm->mbuf.start); + if (cdm->mbuf.size >= BUFSIZE) { + ERROR("amqp1 plugin: format graphite failed"); + cd_message_free(cdm); + return -1; + } + break; + case AMQP1_FORMAT_GRAPHITE: + status = format_graphite((char *)cdm->mbuf.start, bufsize, ds, vl, + instance->prefix, instance->postfix, + instance->escape_char, instance->graphite_flags); + if (status != 0) { + ERROR("amqp1 plugin: format_graphite failed with status %i.", status); + cd_message_free(cdm); + return status; + } + cdm->mbuf.size = strlen(cdm->mbuf.start); + if (cdm->mbuf.size >= BUFSIZE) { + ERROR("amqp1 plugin: format graphite failed"); + cd_message_free(cdm); + return -1; + } + break; + default: + ERROR("amqp1 plugin: Invalid write format (%i).", instance->format); + cd_message_free(cdm); + return -1; + } + + /* encode message and place on outbound queue */ + status = encqueue(cdm, instance); + if (status != 0) { + ERROR("amqp1 plugin: write enqueue failed"); + cd_message_free(cdm); + } + return status; + +} /* }}} int amqp1_write */ + +static void amqp1_config_transport_free(void *ptr) /* {{{ */ +{ + amqp1_config_transport_t *transport = ptr; + + if (transport == NULL) + return; + + sfree(transport->name); + sfree(transport->host); + sfree(transport->port); + sfree(transport->user); + sfree(transport->password); + sfree(transport->address); + + sfree(transport); +} /* }}} void amqp1_config_transport_free */ + +static void amqp1_config_instance_free(void *ptr) /* {{{ */ +{ + amqp1_config_instance_t *instance = ptr; + + if (instance == NULL) + return; + + sfree(instance->name); + sfree(instance->prefix); + sfree(instance->postfix); + + sfree(instance); +} /* }}} void amqp1_config_instance_free */ + +static int amqp1_config_instance(oconfig_item_t *ci) /* {{{ */ +{ + amqp1_config_instance_t *instance = calloc(1, sizeof(*instance)); + if (instance == NULL) { + ERROR("amqp1 plugin: calloc failed."); + return ENOMEM; + } + + int status = cf_util_get_string(ci, &instance->name); + if (status != 0) { + sfree(instance); + return status; + } + + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp("PreSettle", child->key) == 0) + status = cf_util_get_boolean(child, &instance->pre_settle); + else if (strcasecmp("Notify", child->key) == 0) + status = cf_util_get_boolean(child, &instance->notify); + else if (strcasecmp("Format", child->key) == 0) { + char *key = NULL; + status = cf_util_get_string(child, &key); + if (status != 0) + return status; + assert(key != NULL); + if (strcasecmp(key, "Command") == 0) { + instance->format = AMQP1_FORMAT_COMMAND; + } else if (strcasecmp(key, "Graphite") == 0) { + instance->format = AMQP1_FORMAT_GRAPHITE; + } else if (strcasecmp(key, "JSON") == 0) { + instance->format = AMQP1_FORMAT_JSON; + } else { + WARNING("amqp1 plugin: Invalid format string: %s", key); + } + sfree(key); + } else if (strcasecmp("StoreRates", child->key) == 0) + status = cf_util_get_boolean(child, &instance->store_rates); + else if (strcasecmp("GraphiteSeparateInstances", child->key) == 0) + status = cf_util_get_flag(child, &instance->graphite_flags, + GRAPHITE_SEPARATE_INSTANCES); + else if (strcasecmp("GraphiteAlwaysAppendDS", child->key) == 0) + status = cf_util_get_flag(child, &instance->graphite_flags, + GRAPHITE_ALWAYS_APPEND_DS); + else if (strcasecmp("GraphitePreserveSeparator", child->key) == 0) + status = cf_util_get_flag(child, &instance->graphite_flags, + GRAPHITE_PRESERVE_SEPARATOR); + else if (strcasecmp("GraphitePrefix", child->key) == 0) + status = cf_util_get_string(child, &instance->prefix); + else if (strcasecmp("GraphitePostfix", child->key) == 0) + status = cf_util_get_string(child, &instance->postfix); + else if (strcasecmp("GraphiteEscapeChar", child->key) == 0) { + char *tmp_buff = NULL; + status = cf_util_get_string(child, &tmp_buff); + if (status == 0) { + if (strlen(tmp_buff) > 1) + WARNING("amqp1 plugin: The option \"GraphiteEscapeChar\" handles " + "only one character. Others will be ignored."); + instance->escape_char = tmp_buff[0]; + } + sfree(tmp_buff); + } else + WARNING("amqp1 plugin: Ignoring unknown " + "instance configuration option " + "\"%s\".", + child->key); + if (status != 0) + break; + } + + if (status != 0) { + amqp1_config_instance_free(instance); + return status; + } else { + char tpname[DATA_MAX_NAME_LEN]; + status = snprintf(tpname, sizeof(tpname), "amqp1/%s", instance->name); + if ((status < 0) || (size_t)status >= sizeof(tpname)) { + ERROR("amqp1 plugin: Instance name would have been truncated."); + return -1; + } + status = snprintf(instance->send_to, sizeof(instance->send_to), "/%s/%s", + transport->address, instance->name); + if ((status < 0) || (size_t)status >= sizeof(instance->send_to)) { + ERROR("amqp1 plugin: send_to address would have been truncated."); + return -1; + } + if (instance->notify) { + status = plugin_register_notification( + tpname, amqp1_notify, + &(user_data_t){ + .data = instance, .free_func = amqp1_config_instance_free, + }); + } else { + status = plugin_register_write( + tpname, amqp1_write, + &(user_data_t){ + .data = instance, .free_func = amqp1_config_instance_free, + }); + } + + if (status != 0) { + amqp1_config_instance_free(instance); + } + } + + return status; +} /* }}} int amqp1_config_instance */ + +static int amqp1_config_transport(oconfig_item_t *ci) /* {{{ */ +{ + transport = calloc(1, sizeof(*transport)); + if (transport == NULL) { + ERROR("amqp1 plugin: calloc failed."); + return ENOMEM; + } + + /* Initialize transport configuration {{{ */ + transport->retry_delay = 1; + + int status = cf_util_get_string(ci, &transport->name); + if (status != 0) { + sfree(transport); + return status; + } + + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp("Host", child->key) == 0) + status = cf_util_get_string(child, &transport->host); + else if (strcasecmp("Port", child->key) == 0) + status = cf_util_get_string(child, &transport->port); + else if (strcasecmp("User", child->key) == 0) + status = cf_util_get_string(child, &transport->user); + else if (strcasecmp("Password", child->key) == 0) + status = cf_util_get_string(child, &transport->password); + else if (strcasecmp("Address", child->key) == 0) + status = cf_util_get_string(child, &transport->address); + else if (strcasecmp("RetryDelay", child->key) == 0) + status = cf_util_get_int(child, &transport->retry_delay); + else if (strcasecmp("Instance", child->key) == 0) + amqp1_config_instance(child); + else + WARNING("amqp1 plugin: Ignoring unknown " + "transport configuration option " + "\"%s\".", + child->key); + + if (status != 0) + break; + } + + if (status != 0) { + amqp1_config_transport_free(transport); + } + return status; +} /* }}} int amqp1_config_transport */ + +static int amqp1_config(oconfig_item_t *ci) /* {{{ */ +{ + + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp("Transport", child->key) == 0) + amqp1_config_transport(child); + else + WARNING("amqp1 plugin: Ignoring unknown config option \"%s\".", + child->key); + } + + return 0; +} /* }}} int amqp1_config */ + +static int amqp1_init(void) /* {{{ */ +{ + if (transport == NULL) { + ERROR("amqp1: init failed, no transport configured"); + return -1; + } + + if (proactor == NULL) { + pthread_mutex_init(&send_lock, /* attr = */ NULL); + /* start_thread */ + int status = + plugin_thread_create(&event_thread_id, NULL /* no attributes */, + event_thread, NULL /* no argument */, "handle"); + if (status != 0) { + ERROR("amqp1 plugin: pthread_create failed: %s", STRERRNO); + } else { + event_thread_running = true; + } + } + return 0; +} /* }}} int amqp1_init */ + +static int amqp1_shutdown(void) /* {{{ */ +{ + stopping = true; + + /* Stop the proactor thread */ + if (event_thread_running) { + DEBUG("amqp1 plugin: Shutting down proactor thread."); + pn_connection_wake(conn); + } + pthread_join(event_thread_id, NULL /* no return value */); + memset(&event_thread_id, 0, sizeof(event_thread_id)); + + DEBUG("amqp1 plugin: proactor thread exited."); + + if (transport) { + amqp1_config_transport_free(transport); + } + + return 0; +} /* }}} int amqp1_shutdown */ + +void module_register(void) { + plugin_register_complex_config("amqp1", amqp1_config); + plugin_register_init("amqp1", amqp1_init); + plugin_register_shutdown("amqp1", amqp1_shutdown); +} /* void module_register */ diff --git a/src/apache.c b/src/apache.c index 07b2b57d..5c67a388 100644 --- a/src/apache.c +++ b/src/apache.c @@ -40,8 +40,8 @@ struct apache_s { char *url; char *user; char *pass; - _Bool verify_peer; - _Bool verify_host; + bool verify_peer; + bool verify_host; char *cacert; char *ssl_ciphers; char *server; /* user specific server type */ @@ -82,23 +82,19 @@ static void apache_free(void *arg) { static size_t apache_curl_callback(void *buf, size_t size, size_t nmemb, void *user_data) { - size_t len = size * nmemb; - apache_t *st; - - st = user_data; + apache_t *st = user_data; if (st == NULL) { ERROR("apache plugin: apache_curl_callback: " "user_data pointer is NULL."); return 0; } + size_t len = size * nmemb; if (len == 0) return len; if ((st->apache_buffer_fill + len) >= st->apache_buffer_size) { - char *temp; - - temp = realloc(st->apache_buffer, st->apache_buffer_fill + len + 1); + char *temp = realloc(st->apache_buffer, st->apache_buffer_fill + len + 1); if (temp == NULL) { ERROR("apache plugin: realloc failed."); return 0; @@ -116,16 +112,14 @@ static size_t apache_curl_callback(void *buf, size_t size, size_t nmemb, static size_t apache_header_callback(void *buf, size_t size, size_t nmemb, void *user_data) { - size_t len = size * nmemb; - apache_t *st; - - st = user_data; + apache_t *st = user_data; if (st == NULL) { ERROR("apache plugin: apache_header_callback: " "user_data pointer is NULL."); return 0; } + size_t len = size * nmemb; if (len == 0) return len; @@ -158,10 +152,7 @@ static size_t apache_header_callback(void *buf, size_t size, size_t nmemb, * */ static int config_add(oconfig_item_t *ci) { - apache_t *st; - int status; - - st = calloc(1, sizeof(*st)); + apache_t *st = calloc(1, sizeof(*st)); if (st == NULL) { ERROR("apache plugin: calloc failed."); return -1; @@ -169,7 +160,7 @@ static int config_add(oconfig_item_t *ci) { st->timeout = -1; - status = cf_util_get_string(ci, &st->name); + int status = cf_util_get_string(ci, &st->name); if (status != 0) { sfree(st); return status; @@ -238,8 +229,6 @@ static int config_add(oconfig_item_t *ci) { } /* int config_add */ static int config(oconfig_item_t *ci) { - int status = 0; - for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; @@ -253,7 +242,7 @@ static int config(oconfig_item_t *ci) { child->key); } /* for (ci->children) */ - return status; + return 0; } /* int config */ /* initialize curl for each host */ @@ -308,10 +297,8 @@ static int init_host(apache_t *st) /* {{{ */ (st->pass == NULL) ? "" : st->pass); #else static char credentials[1024]; - int status; - - status = snprintf(credentials, sizeof(credentials), "%s:%s", st->user, - (st->pass == NULL) ? "" : st->pass); + int status = snprintf(credentials, sizeof(credentials), "%s:%s", st->user, + (st->pass == NULL) ? "" : st->pass); if ((status < 0) || ((size_t)status >= sizeof(credentials))) { ERROR("apache plugin: init_host: Returning an error " "because the credentials have been " @@ -479,28 +466,13 @@ static void submit_scoreboard(char *buf, apache_t *st) { static int apache_read_host(user_data_t *user_data) /* {{{ */ { - char *ptr; - char *saveptr; - char *line; - - char *fields[4]; - int fields_num; - - apache_t *st; - - st = user_data->data; - - int status; - - char *content_type; - static const char *text_plain = "text/plain"; + apache_t *st = user_data->data; assert(st->url != NULL); /* (Assured by `config_add') */ if (st->curl == NULL) { - status = init_host(st); - if (status != 0) + if (init_host(st) != 0) return -1; } assert(st->curl != NULL); @@ -521,7 +493,10 @@ static int apache_read_host(user_data_t *user_data) /* {{{ */ st->server_type = APACHE; } - status = curl_easy_getinfo(st->curl, CURLINFO_CONTENT_TYPE, &content_type); + char *content_type; + static const char *text_plain = "text/plain"; + int status = + curl_easy_getinfo(st->curl, CURLINFO_CONTENT_TYPE, &content_type); if ((status == CURLE_OK) && (content_type != NULL) && (strncasecmp(content_type, text_plain, strlen(text_plain)) != 0)) { WARNING("apache plugin: `Content-Type' response header is not `%s' " @@ -530,11 +505,14 @@ static int apache_read_host(user_data_t *user_data) /* {{{ */ text_plain, content_type); } - ptr = st->apache_buffer; - saveptr = NULL; + char *ptr = st->apache_buffer; + char *saveptr = NULL; + char *line; while ((line = strtok_r(ptr, "\n\r", &saveptr)) != NULL) { ptr = NULL; - fields_num = strsplit(line, fields, STATIC_ARRAY_SIZE(fields)); + char *fields[4]; + + int fields_num = strsplit(line, fields, STATIC_ARRAY_SIZE(fields)); if (fields_num == 3) { if ((strcmp(fields[0], "Total") == 0) && diff --git a/src/apcups.c b/src/apcups.c index 262fa424..2931d2c0 100644 --- a/src/apcups.c +++ b/src/apcups.c @@ -70,16 +70,16 @@ typedef struct { * Private variables */ /* Default values for contacting daemon */ -static char *conf_node = NULL; -static char *conf_service = NULL; +static char *conf_node; +static char *conf_service; /* Defaults to false for backwards compatibility. */ -static _Bool conf_report_seconds = 0; -static _Bool conf_persistent_conn = 1; +static bool conf_report_seconds; +static bool conf_persistent_conn = true; static int global_sockfd = -1; -static int count_retries = 0; -static int count_iterations = 0; +static int count_retries; +static int count_iterations; static int net_shutdown(int *fd) { uint16_t packet_size = 0; @@ -285,7 +285,7 @@ static int apc_query_server(char const *node, char const *service, "first %i iterations. Will close the socket " "in future iterations.", count_retries, count_iterations); - conf_persistent_conn = 0; + conf_persistent_conn = false; } while ((n = net_recv(&global_sockfd, recvline, sizeof(recvline) - 1)) > 0) { @@ -347,7 +347,7 @@ static int apc_query_server(char const *node, char const *service, } static int apcups_config(oconfig_item_t *ci) { - _Bool persistent_conn_set = 0; + bool persistent_conn_set = false; for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; @@ -360,7 +360,7 @@ static int apcups_config(oconfig_item_t *ci) { cf_util_get_boolean(child, &conf_report_seconds); else if (strcasecmp(child->key, "PersistentConnection") == 0) { cf_util_get_boolean(child, &conf_persistent_conn); - persistent_conn_set = 1; + persistent_conn_set = true; } else ERROR("apcups plugin: Unknown config option \"%s\".", child->key); } @@ -372,7 +372,7 @@ static int apcups_config(oconfig_item_t *ci) { "Apcupsd NIS socket timeout is %.3f seconds, " "PersistentConnection disabled by default.", interval, APCUPS_SERVER_TIMEOUT); - conf_persistent_conn = 0; + conf_persistent_conn = false; } } diff --git a/src/aquaero.c b/src/aquaero.c index beffc1a1..937742b0 100644 --- a/src/aquaero.c +++ b/src/aquaero.c @@ -30,7 +30,7 @@ * Private variables */ /* Default values for contacting daemon */ -static char *conf_device = NULL; +static char *conf_device; static int aquaero_config(oconfig_item_t *ci) { for (int i = 0; i < ci->children_num; i++) { diff --git a/src/ascent.c b/src/ascent.c index 36694f61..22358658 100644 --- a/src/ascent.c +++ b/src/ascent.c @@ -87,19 +87,19 @@ typedef struct player_info_s player_info_t; #define PLAYER_INFO_STATIC_INIT \ { -1, -1, -1, -1, -1 } -static char *url = NULL; -static char *user = NULL; -static char *pass = NULL; -static char *verify_peer = NULL; -static char *verify_host = NULL; -static char *cacert = NULL; -static char *timeout = NULL; - -static CURL *curl = NULL; - -static char *ascent_buffer = NULL; -static size_t ascent_buffer_size = 0; -static size_t ascent_buffer_fill = 0; +static char *url; +static char *user; +static char *pass; +static char *verify_peer; +static char *verify_host; +static char *cacert; +static char *timeout; + +static CURL *curl; + +static char *ascent_buffer; +static size_t ascent_buffer_size; +static size_t ascent_buffer_fill; static char ascent_curl_error[CURL_ERROR_SIZE]; static const char *config_keys[] = { diff --git a/src/barometer.c b/src/barometer.c index 6c6347c9..a54d998a 100644 --- a/src/barometer.c +++ b/src/barometer.c @@ -27,6 +27,9 @@ #include #include +#if HAVE_I2C_SMBUS_H +#include +#endif #include #include #include @@ -177,23 +180,23 @@ static const char *config_keys[] = { static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static char *config_device = NULL; /**< I2C bus device */ -static int config_oversample = 1; /**< averaging window */ +static char *config_device; /**< I2C bus device */ +static int config_oversample = 1; /**< averaging window */ -static double config_press_offset = 0.0; /**< pressure offset */ -static double config_temp_offset = 0.0; /**< temperature offset */ +static double config_press_offset; /**< pressure offset */ +static double config_temp_offset; /**< temperature offset */ static double config_altitude = NAN; /**< altitude */ -static int config_normalize = 0; /**< normalization method */ +static int config_normalize; /**< normalization method */ -static _Bool configured = 0; /**< the whole plugin config status */ +static bool configured; /**< the whole plugin config status */ static int i2c_bus_fd = -1; /**< I2C bus device FD */ static enum Sensor_type sensor_type = Sensor_none; /**< detected/used sensor type */ -static __s32 mpl3115_oversample = 0; /**< MPL3115 CTRL1 oversample setting */ +static __s32 mpl3115_oversample; /**< MPL3115 CTRL1 oversample setting */ // BMP085 configuration static unsigned bmp085_oversampling; /**< BMP085 oversampling (0-3) */ @@ -226,7 +229,7 @@ static short bmp085_MD; /* Used only for MPL115. MPL3115 supports real oversampling in the device so */ /* no need for any postprocessing. */ -static _Bool avg_initialized = 0; /**< already initialized by real values */ +static bool avg_initialized; /**< already initialized by real values */ typedef struct averaging_s { long int *ring_buffer; @@ -235,8 +238,8 @@ typedef struct averaging_s { int ring_buffer_head; } averaging_t; -static averaging_t pressure_averaging = {NULL, 0, 0L, 0}; -static averaging_t temperature_averaging = {NULL, 0, 0L, 0}; +static averaging_t pressure_averaging; +static averaging_t temperature_averaging; /** * Create / allocate averaging buffer @@ -313,11 +316,11 @@ static double averaging_add_sample(averaging_t *avg, long int sample) { typedef struct temperature_list_s { char *sensor_name; /**< sensor name/reference */ size_t num_values; /**< number of values (usually one) */ - _Bool initialized; /**< sensor already provides data */ + bool initialized; /**< sensor already provides data */ struct temperature_list_s *next; /**< next in the list */ } temperature_list_t; -static temperature_list_t *temp_list = NULL; +static temperature_list_t *temp_list; /* * Add new sensor to the temperature reference list @@ -1392,7 +1395,7 @@ static int MPL115_collectd_barometer_read(void) { config_oversample - 1); usleep(20000); } - avg_initialized = 1; + avg_initialized = true; } result = MPL115_read_averaged(&pressure, &temperature); @@ -1635,7 +1638,7 @@ static int collectd_barometer_init(void) { return -1; } - configured = 1; + configured = true; return 0; } diff --git a/src/battery.c b/src/battery.c index b6dea0f3..a74e7b64 100644 --- a/src/battery.c +++ b/src/battery.c @@ -72,9 +72,9 @@ int battery_read_statefs( void); /* defined in battery_statefs; used by StateFS backend */ -static _Bool report_percent = 0; -static _Bool report_degraded = 0; -static _Bool query_statefs = 0; +static bool report_percent; +static bool report_degraded; +static bool query_statefs; static void battery_submit2(char const *plugin_instance, /* {{{ */ char const *type, char const *type_instance, @@ -410,7 +410,7 @@ static int read_sysfs_callback(char const *dir, /* {{{ */ char const *plugin_instance; char buffer[32]; gauge_t v = NAN; - _Bool discharging = 0; + bool discharging = false; int status; /* Ignore non-battery directories, such as AC power. */ @@ -424,7 +424,7 @@ static int read_sysfs_callback(char const *dir, /* {{{ */ (void)sysfs_file_to_buffer(dir, power_supply, "status", buffer, sizeof(buffer)); if (strcasecmp("Discharging", buffer) == 0) - discharging = 1; + discharging = true; /* FIXME: This is a dirty hack for backwards compatibility: The battery * plugin, for a very long time, has had the plugin_instance @@ -522,8 +522,8 @@ static int read_acpi_callback(char const *dir, /* {{{ */ gauge_t capacity_charged = NAN; gauge_t capacity_full = NAN; gauge_t capacity_design = NAN; - _Bool charging = 0; - _Bool is_current = 0; + bool charging = false; + bool is_current = false; char const *plugin_instance; char filename[PATH_MAX]; @@ -560,9 +560,9 @@ static int read_acpi_callback(char const *dir, /* {{{ */ if ((strcmp(fields[0], "charging") == 0) && (strcmp(fields[1], "state:") == 0)) { if (strcmp(fields[2], "charging") == 0) - charging = 1; + charging = true; else - charging = 0; + charging = false; continue; } @@ -575,7 +575,7 @@ static int read_acpi_callback(char const *dir, /* {{{ */ strtogauge(fields[2], &power); if ((numfields >= 4) && (strcmp("mA", fields[3]) == 0)) - is_current = 1; + is_current = true; } else if ((strcmp(fields[0], "remaining") == 0) && (strcmp(fields[1], "capacity:") == 0)) strtogauge(fields[2], &capacity_charged); diff --git a/src/bind.c b/src/bind.c index b77a6418..b0126392 100644 --- a/src/bind.c +++ b/src/bind.c @@ -73,9 +73,9 @@ typedef int (*list_callback_t)(const char *name, value_t value, struct cb_view_s { char *name; - int qtypes; - int resolver_stats; - int cacherrsets; + _Bool qtypes; + _Bool resolver_stats; + _Bool cacherrsets; char **zones; size_t zones_num; @@ -104,25 +104,25 @@ typedef struct list_info_ptr_s list_info_ptr_t; /* FIXME: Enabled by default for backwards compatibility. */ /* TODO: Remove time parsing code. */ -static _Bool config_parse_time = 1; - -static char *url = NULL; -static int global_opcodes = 1; -static int global_qtypes = 1; -static int global_server_stats = 1; -static int global_zone_maint_stats = 1; -static int global_resolver_stats = 0; -static int global_memory_stats = 1; +static bool config_parse_time = true; + +static char *url; +static _Bool global_opcodes = 1; +static _Bool global_qtypes = 1; +static _Bool global_server_stats = 1; +static _Bool global_zone_maint_stats = 1; +static _Bool global_resolver_stats; +static _Bool global_memory_stats = 1; static int timeout = -1; -static cb_view_t *views = NULL; -static size_t views_num = 0; +static cb_view_t *views; +static size_t views_num; -static CURL *curl = NULL; +static CURL *curl; -static char *bind_buffer = NULL; -static size_t bind_buffer_size = 0; -static size_t bind_buffer_fill = 0; +static char *bind_buffer; +static size_t bind_buffer_size; +static size_t bind_buffer_fill; static char bind_curl_error[CURL_ERROR_SIZE]; /* Translation table for the `nsstats' values. */ @@ -274,9 +274,7 @@ static size_t bind_curl_callback(void *buf, size_t size, /* {{{ */ return len; if ((bind_buffer_fill + len) >= bind_buffer_size) { - char *temp; - - temp = realloc(bind_buffer, bind_buffer_fill + len + 1); + char *temp = realloc(bind_buffer, bind_buffer_fill + len + 1); if (temp == NULL) { ERROR("bind plugin: realloc failed."); return 0; @@ -335,17 +333,15 @@ static int bind_xml_list_callback(const char *name, /* {{{ */ static int bind_xml_read_derive(xmlDoc *doc, xmlNode *node, /* {{{ */ derive_t *ret_value) { - char *str_ptr; - value_t value; - int status; - - str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + char *str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if (str_ptr == NULL) { ERROR("bind plugin: bind_xml_read_derive: xmlNodeListGetString failed."); return -1; } - status = parse_value(str_ptr, &value, DS_TYPE_DERIVE); + value_t value; + + int status = parse_value(str_ptr, &value, DS_TYPE_DERIVE); if (status != 0) { ERROR("bind plugin: Parsing string \"%s\" to derive value failed.", str_ptr); @@ -360,17 +356,15 @@ static int bind_xml_read_derive(xmlDoc *doc, xmlNode *node, /* {{{ */ static int bind_xml_read_gauge(xmlDoc *doc, xmlNode *node, /* {{{ */ gauge_t *ret_value) { - char *str_ptr, *end_ptr; - double value; - - str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + char *str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if (str_ptr == NULL) { ERROR("bind plugin: bind_xml_read_gauge: xmlNodeListGetString failed."); return -1; } + char *end_ptr; errno = 0; - value = strtod(str_ptr, &end_ptr); + double value = strtod(str_ptr, &end_ptr); xmlFree(str_ptr); if (str_ptr == end_ptr || errno) { if (errno && (value < 0)) @@ -389,13 +383,8 @@ static int bind_xml_read_gauge(xmlDoc *doc, xmlNode *node, /* {{{ */ static int bind_xml_read_timestamp(const char *xpath_expression, /* {{{ */ xmlDoc *doc, xmlXPathContext *xpathCtx, time_t *ret_value) { - xmlXPathObject *xpathObj = NULL; - xmlNode *node; - char *str_ptr; - char *tmp; - struct tm tm = {0}; - - xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); + xmlXPathObject *xpathObj = + xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); if (xpathObj == NULL) { ERROR("bind plugin: Unable to evaluate XPath expression `%s'.", xpath_expression); @@ -413,7 +402,7 @@ static int bind_xml_read_timestamp(const char *xpath_expression, /* {{{ */ xpath_expression, xpathObj->nodesetval->nodeNr); } - node = xpathObj->nodesetval->nodeTab[0]; + xmlNode *node = xpathObj->nodesetval->nodeTab[0]; if (node->xmlChildrenNode == NULL) { ERROR("bind plugin: bind_xml_read_timestamp: " @@ -422,14 +411,15 @@ static int bind_xml_read_timestamp(const char *xpath_expression, /* {{{ */ return -1; } - str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + char *str_ptr = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if (str_ptr == NULL) { ERROR("bind plugin: bind_xml_read_timestamp: xmlNodeListGetString failed."); xmlXPathFreeObject(xpathObj); return -1; } - tmp = strptime(str_ptr, "%Y-%m-%dT%T", &tm); + struct tm tm = {0}; + char *tmp = strptime(str_ptr, "%Y-%m-%dT%T", &tm); xmlFree(str_ptr); if (tmp == NULL) { ERROR("bind plugin: bind_xml_read_timestamp: strptime failed."); @@ -474,25 +464,23 @@ static int bind_parse_generic_name_value(const char *xpath_expression, /* {{{ */ void *user_data, xmlDoc *doc, xmlXPathContext *xpathCtx, time_t current_time, int ds_type) { - xmlXPathObject *xpathObj = NULL; - int num_entries; - - xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); + xmlXPathObject *xpathObj = + xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); if (xpathObj == NULL) { ERROR("bind plugin: Unable to evaluate XPath expression `%s'.", xpath_expression); return -1; } - num_entries = 0; + int num_entries = 0; /* Iterate over all matching nodes. */ for (int i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++) { + xmlNode *name_node = NULL; xmlNode *counter = NULL; - xmlNode *parent; - parent = xpathObj->nodesetval->nodeTab[i]; + xmlNode *parent = xpathObj->nodesetval->nodeTab[i]; DEBUG("bind plugin: bind_parse_generic_name_value: parent->name = %s;", (char *)parent->name); @@ -555,32 +543,29 @@ static int bind_parse_generic_value_list(const char *xpath_expression, /* {{{ */ void *user_data, xmlDoc *doc, xmlXPathContext *xpathCtx, time_t current_time, int ds_type) { - xmlXPathObject *xpathObj = NULL; - int num_entries; - - xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); + xmlXPathObject *xpathObj = + xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); if (xpathObj == NULL) { ERROR("bind plugin: Unable to evaluate XPath expression `%s'.", xpath_expression); return -1; } - num_entries = 0; + int num_entries = 0; /* Iterate over all matching nodes. */ for (int i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++) { /* Iterate over all child nodes. */ for (xmlNode *child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; child != NULL; child = child->next) { - char *node_name; - value_t value; - int status; if (child->type != XML_ELEMENT_NODE) continue; - node_name = (char *)child->name; + char *node_name = (char *)child->name; + value_t value; + int status; if (ds_type == DS_TYPE_GAUGE) status = bind_xml_read_gauge(doc, child, &value.gauge); else @@ -617,17 +602,16 @@ static int bind_parse_generic_name_attr_value_list( const char *xpath_expression, /* {{{ */ list_callback_t list_callback, void *user_data, xmlDoc *doc, xmlXPathContext *xpathCtx, time_t current_time, int ds_type) { - xmlXPathObject *xpathObj = NULL; - int num_entries; - xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); + xmlXPathObject *xpathObj = + xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx); if (xpathObj == NULL) { ERROR("bind plugin: Unable to evaluate XPath expression `%s'.", xpath_expression); return -1; } - num_entries = 0; + int num_entries = 0; /* Iterate over all matching nodes. */ for (int i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++) { @@ -640,15 +624,15 @@ static int bind_parse_generic_name_attr_value_list( if (strncmp("counter", (char *)child->name, strlen("counter")) != 0) continue; - char *attr_name; - value_t value; - int status; - - attr_name = (char *)xmlGetProp(child, BAD_CAST "name"); + char *attr_name = (char *)xmlGetProp(child, BAD_CAST "name"); if (attr_name == NULL) { DEBUG("bind plugin: found without name."); continue; } + + value_t value; + int status; + if (ds_type == DS_TYPE_GAUGE) status = bind_xml_read_gauge(doc, child, &value.gauge); else @@ -677,9 +661,7 @@ static int bind_parse_generic_name_attr_value_list( static int bind_xml_stats_handle_zone(int version, xmlDoc *doc, /* {{{ */ xmlXPathContext *path_ctx, xmlNode *node, cb_view_t *view, time_t current_time) { - xmlXPathObject *path_obj; char *zone_name = NULL; - size_t j; if (version >= 3) { char *n = (char *)xmlGetProp(node, BAD_CAST "name"); @@ -691,7 +673,8 @@ static int bind_xml_stats_handle_zone(int version, xmlDoc *doc, /* {{{ */ xmlFree(n); xmlFree(c); } else { - path_obj = xmlXPathEvalExpression(BAD_CAST "name", path_ctx); + xmlXPathObject *path_obj = + xmlXPathEvalExpression(BAD_CAST "name", path_ctx); if (path_obj == NULL) { ERROR("bind plugin: xmlXPathEvalExpression failed."); return -1; @@ -712,13 +695,13 @@ static int bind_xml_stats_handle_zone(int version, xmlDoc *doc, /* {{{ */ return -1; } + size_t j; for (j = 0; j < view->zones_num; j++) { if (strcasecmp(zone_name, view->zones[j]) == 0) break; } xmlFree(zone_name); - zone_name = NULL; if (j >= view->zones_num) return 0; @@ -763,16 +746,14 @@ static int bind_xml_stats_handle_zone(int version, xmlDoc *doc, /* {{{ */ static int bind_xml_stats_search_zones(int version, xmlDoc *doc, /* {{{ */ xmlXPathContext *path_ctx, xmlNode *node, cb_view_t *view, time_t current_time) { - xmlXPathObject *zone_nodes = NULL; - xmlXPathContext *zone_path_context; - - zone_path_context = xmlXPathNewContext(doc); + xmlXPathContext *zone_path_context = xmlXPathNewContext(doc); if (zone_path_context == NULL) { ERROR("bind plugin: xmlXPathNewContext failed."); return -1; } - zone_nodes = xmlXPathEvalExpression(BAD_CAST "zones/zone", path_ctx); + xmlXPathObject *zone_nodes = + xmlXPathEvalExpression(BAD_CAST "zones/zone", path_ctx); if (zone_nodes == NULL) { ERROR("bind plugin: Cannot find any tags."); xmlXPathFreeContext(zone_path_context); @@ -817,8 +798,8 @@ static int bind_xml_stats_handle_view(int version, xmlDoc *doc, /* {{{ */ xmlFree(view_name); view_name = NULL; } else { - xmlXPathObject *path_obj; - path_obj = xmlXPathEvalExpression(BAD_CAST "name", path_ctx); + xmlXPathObject *path_obj = + xmlXPathEvalExpression(BAD_CAST "name", path_ctx); if (path_obj == NULL) { ERROR("bind plugin: xmlXPathEvalExpression failed."); return -1; @@ -927,18 +908,15 @@ static int bind_xml_stats_handle_view(int version, xmlDoc *doc, /* {{{ */ static int bind_xml_stats_search_views(int version, xmlDoc *doc, /* {{{ */ xmlXPathContext *xpathCtx, - xmlNode *statsnode, time_t current_time) { - xmlXPathObject *view_nodes = NULL; - xmlXPathContext *view_path_context; - - view_path_context = xmlXPathNewContext(doc); + xmlXPathContext *view_path_context = xmlXPathNewContext(doc); if (view_path_context == NULL) { ERROR("bind plugin: xmlXPathNewContext failed."); return -1; } - view_nodes = xmlXPathEvalExpression(BAD_CAST "views/view", xpathCtx); + xmlXPathObject *view_nodes = + xmlXPathEvalExpression(BAD_CAST "views/view", xpathCtx); if (view_nodes == NULL) { ERROR("bind plugin: Cannot find any tags."); xmlXPathFreeContext(view_path_context); @@ -946,9 +924,7 @@ static int bind_xml_stats_search_views(int version, xmlDoc *doc, /* {{{ */ } for (int i = 0; i < view_nodes->nodesetval->nodeNr; i++) { - xmlNode *node; - - node = view_nodes->nodesetval->nodeTab[i]; + xmlNode *node = view_nodes->nodesetval->nodeTab[i]; assert(node != NULL); view_path_context->node = node; @@ -963,8 +939,7 @@ static int bind_xml_stats_search_views(int version, xmlDoc *doc, /* {{{ */ } /* }}} int bind_xml_stats_search_views */ static void bind_xml_stats_v3(xmlDoc *doc, /* {{{ */ - xmlXPathContext *xpathCtx, xmlNode *statsnode, - time_t current_time) { + xmlXPathContext *xpathCtx, time_t current_time) { /* XPath: server/counters[@type='opcode'] * Variables: QUERY, IQUERY, NOTIFY, UPDATE, ... * Layout v3: @@ -1082,7 +1057,7 @@ static void bind_xml_stats_v3(xmlDoc *doc, /* {{{ */ } /* }}} bind_xml_stats_v3 */ static void bind_xml_stats_v1_v2(int version, xmlDoc *doc, /* {{{ */ - xmlXPathContext *xpathCtx, xmlNode *statsnode, + xmlXPathContext *xpathCtx, time_t current_time) { /* XPath: server/requests/opcode, server/counters[@type='opcode'] * Variables: QUERY, IQUERY, NOTIFY, UPDATE, ... @@ -1252,14 +1227,13 @@ static void bind_xml_stats_v1_v2(int version, xmlDoc *doc, /* {{{ */ static int bind_xml_stats(int version, xmlDoc *doc, /* {{{ */ xmlXPathContext *xpathCtx, xmlNode *statsnode) { time_t current_time = 0; - int status; xpathCtx->node = statsnode; /* TODO: Check `server/boot-time' to recognize server restarts. */ - status = bind_xml_read_timestamp("server/current-time", doc, xpathCtx, - ¤t_time); + int status = bind_xml_read_timestamp("server/current-time", doc, xpathCtx, + ¤t_time); if (status != 0) { ERROR("bind plugin: Reading `server/current-time' failed."); return -1; @@ -1267,9 +1241,9 @@ static int bind_xml_stats(int version, xmlDoc *doc, /* {{{ */ DEBUG("bind plugin: Current server time is %i.", (int)current_time); if (version == 3) { - bind_xml_stats_v3(doc, xpathCtx, statsnode, current_time); + bind_xml_stats_v3(doc, xpathCtx, current_time); } else { - bind_xml_stats_v1_v2(version, doc, xpathCtx, statsnode, current_time); + bind_xml_stats_v1_v2(version, doc, xpathCtx, current_time); } /* XPath: memory/summary @@ -1295,26 +1269,22 @@ static int bind_xml_stats(int version, xmlDoc *doc, /* {{{ */ } if (views_num > 0) - bind_xml_stats_search_views(version, doc, xpathCtx, statsnode, - current_time); + bind_xml_stats_search_views(version, doc, xpathCtx, current_time); return 0; } /* }}} int bind_xml_stats */ static int bind_xml(const char *data) /* {{{ */ { - xmlDoc *doc = NULL; - xmlXPathContext *xpathCtx = NULL; - xmlXPathObject *xpathObj = NULL; int ret = -1; - doc = xmlParseMemory(data, strlen(data)); + xmlDoc *doc = xmlParseMemory(data, strlen(data)); if (doc == NULL) { ERROR("bind plugin: xmlParseMemory failed."); return -1; } - xpathCtx = xmlXPathNewContext(doc); + xmlXPathContext *xpathCtx = xmlXPathNewContext(doc); if (xpathCtx == NULL) { ERROR("bind plugin: xmlXPathNewContext failed."); xmlFreeDoc(doc); @@ -1325,7 +1295,8 @@ static int bind_xml(const char *data) /* {{{ */ // version 3.* of statistics XML (since BIND9.9) // - xpathObj = xmlXPathEvalExpression(BAD_CAST "/statistics", xpathCtx); + xmlXPathObject *xpathObj = + xmlXPathEvalExpression(BAD_CAST "/statistics", xpathCtx); if (xpathObj == NULL || xpathObj->nodesetval == NULL || xpathObj->nodesetval->nodeNr == 0) { DEBUG("bind plugin: Statistics appears not to be v3"); @@ -1439,33 +1410,15 @@ static int bind_xml(const char *data) /* {{{ */ return ret; } /* }}} int bind_xml */ -static int bind_config_set_bool(const char *name, int *var, /* {{{ */ - oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) { - WARNING("bind plugin: The `%s' option needs " - "exactly one boolean argument.", - name); - return -1; - } - - if (ci->values[0].value.boolean) - *var = 1; - else - *var = 0; - return 0; -} /* }}} int bind_config_set_bool */ - static int bind_config_add_view_zone(cb_view_t *view, /* {{{ */ oconfig_item_t *ci) { - char **tmp; - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { WARNING("bind plugin: The `Zone' option needs " "exactly one string argument."); return -1; } - tmp = realloc(view->zones, sizeof(char *) * (view->zones_num + 1)); + char **tmp = realloc(view->zones, sizeof(char *) * (view->zones_num + 1)); if (tmp == NULL) { ERROR("bind plugin: realloc failed."); return -1; @@ -1484,14 +1437,12 @@ static int bind_config_add_view_zone(cb_view_t *view, /* {{{ */ static int bind_config_add_view(oconfig_item_t *ci) /* {{{ */ { - cb_view_t *tmp; - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { WARNING("bind plugin: `View' blocks need exactly one string argument."); return -1; } - tmp = realloc(views, sizeof(*views) * (views_num + 1)); + cb_view_t *tmp = realloc(views, sizeof(*views) * (views_num + 1)); if (tmp == NULL) { ERROR("bind plugin: realloc failed."); return -1; @@ -1517,11 +1468,11 @@ static int bind_config_add_view(oconfig_item_t *ci) /* {{{ */ oconfig_item_t *child = ci->children + i; if (strcasecmp("QTypes", child->key) == 0) - bind_config_set_bool("QTypes", &tmp->qtypes, child); + cf_util_get_boolean(child, &tmp->qtypes); else if (strcasecmp("ResolverStats", child->key) == 0) - bind_config_set_bool("ResolverStats", &tmp->resolver_stats, child); + cf_util_get_boolean(child, &tmp->resolver_stats); else if (strcasecmp("CacheRRSets", child->key) == 0) - bind_config_set_bool("CacheRRSets", &tmp->cacherrsets, child); + cf_util_get_boolean(child, &tmp->cacherrsets); else if (strcasecmp("Zone", child->key) == 0) bind_config_add_view_zone(tmp, child); else { @@ -1541,27 +1492,19 @@ static int bind_config(oconfig_item_t *ci) /* {{{ */ oconfig_item_t *child = ci->children + i; if (strcasecmp("Url", child->key) == 0) { - if ((child->values_num != 1) || - (child->values[0].type != OCONFIG_TYPE_STRING)) { - WARNING("bind plugin: The `Url' option needs " - "exactly one string argument."); - return -1; - } - - sfree(url); - url = strdup(child->values[0].value.string); + cf_util_get_string(child, &url); } else if (strcasecmp("OpCodes", child->key) == 0) - bind_config_set_bool("OpCodes", &global_opcodes, child); + cf_util_get_boolean(child, &global_opcodes); else if (strcasecmp("QTypes", child->key) == 0) - bind_config_set_bool("QTypes", &global_qtypes, child); + cf_util_get_boolean(child, &global_qtypes); else if (strcasecmp("ServerStats", child->key) == 0) - bind_config_set_bool("ServerStats", &global_server_stats, child); + cf_util_get_boolean(child, &global_server_stats); else if (strcasecmp("ZoneMaintStats", child->key) == 0) - bind_config_set_bool("ZoneMaintStats", &global_zone_maint_stats, child); + cf_util_get_boolean(child, &global_zone_maint_stats); else if (strcasecmp("ResolverStats", child->key) == 0) - bind_config_set_bool("ResolverStats", &global_resolver_stats, child); + cf_util_get_boolean(child, &global_resolver_stats); else if (strcasecmp("MemoryStats", child->key) == 0) - bind_config_set_bool("MemoryStats", &global_memory_stats, child); + cf_util_get_boolean(child, &global_memory_stats); else if (strcasecmp("View", child->key) == 0) bind_config_add_view(child); else if (strcasecmp("ParseTime", child->key) == 0) @@ -1606,8 +1549,6 @@ static int bind_init(void) /* {{{ */ static int bind_read(void) /* {{{ */ { - int status; - if (curl == NULL) { ERROR("bind plugin: I don't have a CURL object."); return -1; @@ -1622,7 +1563,7 @@ static int bind_read(void) /* {{{ */ return -1; } - status = bind_xml(bind_buffer); + int status = bind_xml(bind_buffer); if (status != 0) return -1; else diff --git a/src/ceph.c b/src/ceph.c index df4a720e..c7fc576a 100644 --- a/src/ceph.c +++ b/src/ceph.c @@ -148,7 +148,7 @@ enum perfcounter_type_d { }; /** Give user option to use default (long run = since daemon started) avg */ -static int long_run_latency_avg = 0; +static int long_run_latency_avg; /** * Give user option to use default type for special cases - @@ -161,10 +161,10 @@ static int long_run_latency_avg = 0; static int convert_special_metrics = 1; /** Array of daemons to monitor */ -static struct ceph_daemon **g_daemons = NULL; +static struct ceph_daemon **g_daemons; /** Number of elements in g_daemons */ -static size_t g_num_daemons = 0; +static size_t g_num_daemons; /** * A set of data that we build up in memory while parsing the JSON. @@ -281,7 +281,9 @@ static int ceph_cb_number(void *ctx, const char *number_val, * "rate", use the "sum" in the pair and assign that to the derive * value. */ if (convert_special_metrics && (state->depth > 2) && + state->stack[state->depth - 2] && (strcmp("filestore", state->stack[state->depth - 2]) == 0) && + state->stack[state->depth - 1] && (strcmp("journal_wr_bytes", state->stack[state->depth - 1]) == 0) && (strcmp("avgcount", state->key) == 0)) { DEBUG("ceph plugin: Skipping avgcount for filestore.JournalWrBytes"); @@ -404,8 +406,8 @@ static int compact_ds_name(char *buffer, size_t buffer_size, char const *src) { size_t src_len; char *ptr = buffer; size_t ptr_size = buffer_size; - _Bool append_plus = 0; - _Bool append_minus = 0; + bool append_plus = false; + bool append_minus = false; if ((buffer == NULL) || (buffer_size <= strlen("Minus")) || (src == NULL)) return EINVAL; @@ -415,11 +417,11 @@ static int compact_ds_name(char *buffer, size_t buffer_size, char const *src) { /* Remove trailing "+" and "-". */ if (src_copy[src_len - 1] == '+') { - append_plus = 1; + append_plus = true; src_len--; src_copy[src_len] = 0; } else if (src_copy[src_len - 1] == '-') { - append_minus = 1; + append_minus = true; src_len--; src_copy[src_len] = 0; } @@ -470,19 +472,19 @@ static int compact_ds_name(char *buffer, size_t buffer_size, char const *src) { return 0; } -static _Bool has_suffix(char const *str, char const *suffix) { +static bool has_suffix(char const *str, char const *suffix) { size_t str_len = strlen(str); size_t suffix_len = strlen(suffix); size_t offset; if (suffix_len > str_len) - return 0; + return false; offset = str_len - suffix_len; if (strcmp(str + offset, suffix) == 0) - return 1; + return true; - return 0; + return false; } static void cut_suffix(char *buffer, size_t buffer_size, char const *str, @@ -1140,8 +1142,8 @@ static int cconn_validate_revents(struct cconn *io, int revents) { } /** Handle a network event for a connection */ -static int cconn_handle_event(struct cconn *io) { - int ret; +static ssize_t cconn_handle_event(struct cconn *io) { + ssize_t ret; switch (io->state) { case CSTATE_UNCONNECTED: ERROR("ceph plugin: cconn_handle_event(name=%s) got to illegal " @@ -1156,7 +1158,7 @@ static int cconn_handle_event(struct cconn *io) { size_t cmd_len = strlen(cmd); RETRY_ON_EINTR( ret, write(io->asok, ((char *)&cmd) + io->amt, cmd_len - io->amt)); - DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,amt=%d,ret=%d)", + DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,amt=%d,ret=%zd)", io->d->name, io->state, io->amt, ret); if (ret < 0) { return ret; @@ -1178,7 +1180,7 @@ static int cconn_handle_event(struct cconn *io) { case CSTATE_READ_VERSION: { RETRY_ON_EINTR(ret, read(io->asok, ((char *)(&io->d->version)) + io->amt, sizeof(io->d->version) - io->amt)); - DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)", + DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%zd)", io->d->name, io->state, ret); if (ret < 0) { return ret; @@ -1204,7 +1206,7 @@ static int cconn_handle_event(struct cconn *io) { case CSTATE_READ_AMT: { RETRY_ON_EINTR(ret, read(io->asok, ((char *)(&io->json_len)) + io->amt, sizeof(io->json_len) - io->amt)); - DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)", + DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%zd)", io->d->name, io->state, ret); if (ret < 0) { return ret; @@ -1225,7 +1227,7 @@ static int cconn_handle_event(struct cconn *io) { case CSTATE_READ_JSON: { RETRY_ON_EINTR(ret, read(io->asok, io->json + io->amt, io->json_len - io->amt)); - DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)", + DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%zd)", io->d->name, io->state, ret); if (ret < 0) { return ret; @@ -1294,8 +1296,8 @@ static int cconn_prepare(struct cconn *io, struct pollfd *fds) { */ static int milli_diff(const struct timeval *t1, const struct timeval *t2) { int64_t ret; - int sec_diff = t1->tv_sec - t2->tv_sec; - int usec_diff = t1->tv_usec - t2->tv_usec; + long sec_diff = t1->tv_sec - t2->tv_sec; + long usec_diff = t1->tv_usec - t2->tv_usec; ret = usec_diff / 1000; ret += (sec_diff * 1000); return (ret > INT_MAX) ? INT_MAX : ((ret < INT_MIN) ? INT_MIN : (int)ret); @@ -1303,8 +1305,9 @@ static int milli_diff(const struct timeval *t1, const struct timeval *t2) { /** This handles the actual network I/O to talk to the Ceph daemons. */ -static int cconn_main_loop(uint32_t request_type) { - int ret, some_unreachable = 0; +static ssize_t cconn_main_loop(uint32_t request_type) { + int some_unreachable = 0; + ssize_t ret; struct timeval end_tv; struct cconn io_array[g_num_daemons]; @@ -1341,7 +1344,7 @@ static int cconn_main_loop(uint32_t request_type) { struct cconn *io = io_array + i; ret = cconn_prepare(io, fds + nfds); if (ret < 0) { - WARNING("ceph plugin: cconn_prepare(name=%s,i=%" PRIsz ",st=%d)=%d", + WARNING("ceph plugin: cconn_prepare(name=%s,i=%" PRIsz ",st=%d)=%zd", io->d->name, i, io->state, ret); cconn_close(io); io->request_type = ASOK_REQ_NONE; @@ -1365,7 +1368,7 @@ static int cconn_main_loop(uint32_t request_type) { } RETRY_ON_EINTR(ret, poll(fds, nfds, diff)); if (ret < 0) { - ERROR("ceph plugin: poll(2) error: %d", ret); + ERROR("ceph plugin: poll(2) error: %zd", ret); goto done; } for (int i = 0; i < nfds; ++i) { @@ -1386,7 +1389,7 @@ static int cconn_main_loop(uint32_t request_type) { ret = cconn_handle_event(io); if (ret) { WARNING("ceph plugin: cconn_handle_event(name=%s," - "i=%d,st=%d): error %d", + "i=%d,st=%d): error %zd", io->d->name, i, io->state, ret); cconn_close(io); io->request_type = ASOK_REQ_NONE; @@ -1407,7 +1410,7 @@ done: return ret; } -static int ceph_read(void) { return cconn_main_loop(ASOK_REQ_DATA); } +static int ceph_read(void) { return (int)cconn_main_loop(ASOK_REQ_DATA); } /******* lifecycle *******/ static int ceph_init(void) { @@ -1434,7 +1437,7 @@ static int ceph_init(void) { return ENOENT; } - return cconn_main_loop(ASOK_REQ_VERSION); + return (int)cconn_main_loop(ASOK_REQ_VERSION); } static int ceph_shutdown(void) { diff --git a/src/ceph_test.c b/src/ceph_test.c index 45467730..e4032929 100644 --- a/src/ceph_test.c +++ b/src/ceph_test.c @@ -39,7 +39,7 @@ static int test_handler(void *user, char const *val, char const *key) { size_t i; char status[1024]; - _Bool ok; + bool ok; /* special case for latency metrics. */ if (strcmp("filestore.example_latency", key) == 0) @@ -47,7 +47,7 @@ static int test_handler(void *user, char const *val, char const *key) { snprintf(status, sizeof(status), "unexpected call: test_handler(\"%s\") = \"%s\"", key, val); - ok = 0; + ok = false; for (i = 0; i < t->cases_num; i++) { if (strcmp(key, t->cases[i].key) != 0) @@ -57,12 +57,12 @@ static int test_handler(void *user, char const *val, char const *key) { snprintf(status, sizeof(status), "test_handler(\"%s\") = \"%s\", want \"%s\"", key, val, t->cases[i].value); - ok = 0; + ok = false; break; } snprintf(status, sizeof(status), "test_handler(\"%s\") = \"%s\"", key, val); - ok = 1; + ok = true; break; } diff --git a/src/cgroups.c b/src/cgroups.c index 4f34b3a9..7f24d12e 100644 --- a/src/cgroups.c +++ b/src/cgroups.c @@ -31,7 +31,7 @@ static char const *config_keys[] = {"CGroup", "IgnoreSelected"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static ignorelist_t *il_cgroup = NULL; +static ignorelist_t *il_cgroup; __attribute__((nonnull(1))) __attribute__((nonnull(2))) static void cgroups_submit_one(char const *plugin_instance, char const *type_instance, @@ -181,7 +181,7 @@ static int cgroups_config(const char *key, const char *value) { static int cgroups_read(void) { cu_mount_t *mnt_list = NULL; - _Bool cgroup_found = 0; + bool cgroup_found = false; if (cu_mount_getlist(&mnt_list) == NULL) { ERROR("cgroups plugin: cu_mount_getlist failed."); @@ -199,7 +199,7 @@ static int cgroups_read(void) { walk_directory(mnt_ptr->dir, read_cpuacct_root, /* user_data = */ NULL, /* include_hidden = */ 0); - cgroup_found = 1; + cgroup_found = true; /* It doesn't make sense to check other cpuacct mount-points * (if any), they contain the same data. */ break; diff --git a/src/collectd-nagios.c b/src/collectd-nagios.c index 89f73b83..54be36aa 100644 --- a/src/collectd-nagios.c +++ b/src/collectd-nagios.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -93,17 +94,17 @@ typedef struct range_s range_t; extern char *optarg; extern int optind, opterr, optopt; -static char *socket_file_g = NULL; -static char *value_string_g = NULL; -static char *hostname_g = NULL; +static char *socket_file_g; +static char *value_string_g; +static char *hostname_g; static range_t range_critical_g; static range_t range_warning_g; static int consolitation_g = CON_NONE; -static _Bool nan_is_error_g = 0; +static bool nan_is_error_g; -static char **match_ds_g = NULL; -static size_t match_ds_num_g = 0; +static char **match_ds_g; +static size_t match_ds_num_g; /* `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 @@ -637,7 +638,7 @@ int main(int argc, char **argv) { break; } case 'm': - nan_is_error_g = 1; + nan_is_error_g = true; break; default: usage(argv[0]); diff --git a/src/collectd-snmp.pod b/src/collectd-snmp.pod index d615088e..9d508d17 100644 --- a/src/collectd-snmp.pod +++ b/src/collectd-snmp.pod @@ -10,23 +10,24 @@ collectd-snmp - Documentation of collectd's C # ... - Type "voltage" Table false - Instance "input_line1" + Type "voltage" + TypeInstance "input_line1" Scale 0.1 Values "SNMPv2-SMI::enterprises.6050.5.4.1.1.2.1" - Type "users" Table false - Instance "" + Type "users" Shift -1 Values "HOST-RESOURCES-MIB::hrSystemNumUsers.0" - Type "if_octets" Table true - Instance "IF-MIB::ifDescr" + Type "if_octets" + TypeInstanceOID "IF-MIB::ifDescr" + #FilterOID "IF-MIB::ifOperStatus" + #FilterValues "1", "2" Values "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets" @@ -114,8 +115,9 @@ queried using the C SNMP command (see L) and transmitted to collectd. B value list is dispatched and, eventually, one file will be written. -When B is set to B, the OIDs given to B (see below) are -queried using the C SNMP command until the subtree is left. After all +When B
is set to B, the OIDs given to B, B, +B, B and B (see below) are queried using +the C SNMP command until the subtree is left. After all the lists (think: all columns of the table) have been read B values sets will be dispatches and, eventually, several files will be written. If you configure a B (see above) which needs more than one data source (for @@ -138,33 +140,66 @@ C and C. But, this is because of the B setting, not the B
setting. Since the semantic of B and B depends on this setting you -need to set it before setting them. Doing vice verse will result in undefined +need to set it before setting them. Doing vice versa will result in undefined behavior. -=item B I +=item B I -Sets the type-instance of the values that are dispatched. The meaning of this -setting depends on whether B
is set to I or I: +Use I as the plugin name of the values that are dispatched. +Defaults to C. -If B
is set to I, I is interpreted as an SNMP-prefix -that will return a list of values. Those values are then used as the actual -type-instance. An example would be the C subtree. -L from the SNMP distribution describes the format of OIDs. +=item B I -If B
is set to I and B is omitted, then "SUBID" will be -used as the instance. +Sets the plugin-instance of the values that are dispatched to I value. -If B
is set to I the actual string configured for I is -copied into the value-list. In this case I may be empty, i.Ee. -"". +When B
is set to I and B is set then this option +has no effect. -=item B I +Defaults to an empty string. + +=item B I + +Sets the type-instance of the values that are dispatched to I value. -If B
is set to I, you may feel the need to add something to the -instance of the files. If set, I is prepended to the instance as -determined by querying the agent. When B
is set to I this option +When B
is set to I and B is set then this option has no effect. +Defaults to an empty string. + +=item B I + +=item B I + +=item B I + +If B
is set to I, I is interpreted as an SNMP-prefix that will +return a list of values. Those values are then used as the actual type-instance, +plugin-instance or host of dispatched metrics. An example would be the +C subtree. L from the SNMP distribution describes +the format of OIDs. When option is set to empty string, then "SUBID" will be used +as the value. + +Prefix may be set for values with use of appropriate B, +B and B options. + +When B
is set to I these options has no effect. + +Defaults: When no one of these options is configured explicitly, +B defaults to an empty string. + +=item B + +=item B + +=item B + +These options are intented to be used together with B, +B and B respectively. + +If set, I is preprended to values received by querying the agent. + +When B
is set to I these options has no effect. + The C is an example where you need this setting: It has voltages of the inlets, outlets and the battery of an UPS. However, it doesn't provide a descriptive column for these voltages. In this case having 1, 2,E... as @@ -172,6 +207,25 @@ instances is not enough, because the inlet voltages and outlet voltages may both have the subids 1, 2,E... You can use this setting to distinguish between the different voltages. +=item B I + +Attention: this option exists for backwards compatibility only and will be +removed in next major release. Please use B / B +instead. + +The meaning of this setting depends on whether B
is set to I or +I. + +If B
is set to I, option behaves as B. +If B
is set to I, option behaves as B. + +Note what B
option must be set before setting B. + +=item B I + +Attention: this option exists for backwards compatibility only and will be +removed in next major release. Please use B instead. + =item B I [I ...] Configures the values to be queried from the SNMP host. The meaning slightly @@ -208,16 +262,39 @@ This value is not applied to counter-values. =item B I [, I ...] -The ignore values allows one to ignore Instances based on their name and the -patterns specified by the various values you've entered. The match is a +The ignore values allows one to ignore TypeInstances based on their name and +the patterns specified by the various values you've entered. The match is a glob-type shell matching. +When B
is set to I then this option has no effect. + =item B I The invertmatch value should be use in combination of the Ignore option. It changes the behaviour of the Ignore option, from a blacklist behaviour when InvertMatch is set to false, to a whitelist when specified to true. +=item B I + +=item B I [, I ...] + +=item B I + +When B
is set to I, these options allow to configure filtering +based on MIB values. + +The B declares I to fill table column with values. +The B declares values list to do match. Whether table row will be +collected or ignored depends on the B setting. +As with other plugins that use the daemon's ignorelist functionality, a string +that starts and ends with a slash is interpreted as a regular expression. + +If no selection is configured at all, B table rows are selected. + +When B
is set to I then these options has no effect. + +See B
and F for details. + =back =head2 The Host block diff --git a/src/collectd-tg.c b/src/collectd-tg.c index 511cf5bf..2d83bbfe 100644 --- a/src/collectd-tg.c +++ b/src/collectd-tg.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -61,12 +62,12 @@ static const char *conf_service = NET_DEFAULT_PORT; static lcc_network_t *net; -static c_heap_t *values_heap = NULL; +static c_heap_t *values_heap; static struct sigaction sigint_action; static struct sigaction sigterm_action; -static _Bool loop = 1; +static bool loop = true; __attribute__((noreturn)) static void exit_usage(int exit_status) /* {{{ */ { @@ -94,9 +95,9 @@ __attribute__((noreturn)) static void exit_usage(int exit_status) /* {{{ */ exit(exit_status); } /* }}} void exit_usage */ -static void signal_handler(int signal) /* {{{ */ +static void signal_handler(int __attribute__((unused)) signal) /* {{{ */ { - loop = 0; + loop = false; } /* }}} void signal_handler */ #if HAVE_CLOCK_GETTIME @@ -146,7 +147,8 @@ static int get_boundet_random(int min, int max) /* {{{ */ range = max - min; - return min + ((int)(((double)range) * ((double)random()) / (((double)RAND_MAX) + 1.0))); + return min + ((int)(((double)range) * ((double)random()) / + (((double)RAND_MAX) + 1.0))); } /* }}} int get_boundet_random */ static lcc_value_list_t *create_value_list(void) /* {{{ */ diff --git a/src/collectd.conf.in b/src/collectd.conf.in index 6ec61f32..74b6c888 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -90,6 +90,7 @@ #@BUILD_PLUGIN_AGGREGATION_TRUE@LoadPlugin aggregation #@BUILD_PLUGIN_AMQP_TRUE@LoadPlugin amqp +#@BUILD_PLUGIN_AMQP1_TRUE@LoadPlugin amqp1 #@BUILD_PLUGIN_APACHE_TRUE@LoadPlugin apache #@BUILD_PLUGIN_APCUPS_TRUE@LoadPlugin apcups #@BUILD_PLUGIN_APPLE_SENSORS_TRUE@LoadPlugin apple_sensors @@ -269,6 +270,29 @@ # # +# +# +# Host "localhost" +# Port "5672" +# User "guest" +# Password "guest" +# Address "collectd" +# RetryDelay 1 +# +# Format JSON +# PreSettle false +# +# +# Format JSON +# PreSettle true +# +# +# Format JSON +# PreSettle false +# +# +# + # # # URL "http://localhost/status?auto" @@ -666,6 +690,7 @@ # ReportSoftwareEvents true # EventList "/var/cache/pmu/GenuineIntel-6-2D-core.json" # HardwareEvents "L2_RQSTS.CODE_RD_HIT,L2_RQSTS.CODE_RD_MISS" "L2_RQSTS.ALL_CODE_RD" +# Cores "[0-3]" # # @@ -689,6 +714,9 @@ # NotifySensorNotPresent false # NotifyIPMIConnectionState false # SELEnabled false +# SELSensor "some_sensor" +# SELSensor "another_one" +# SELIgnoreSelected false # SELClearEvent false # # @@ -705,6 +733,9 @@ # NotifySensorNotPresent false # NotifyIPMIConnectionState false # SELEnabled false +# SELSensor "some_sensor" +# SELSensor "another_one" +# SELIgnoreSelected false # SELClearEvent false # # @@ -809,6 +840,8 @@ # RegisterType float # Type gauge # Instance "..." +# #Scale 1.0 +# #Shift 0.0 # # # @@ -1126,6 +1159,7 @@ # Timeout 0.9 # TTL 255 # SourceAddress "1.2.3.4" +# AddressFamily "any" # Device "eth0" # MaxMissed -1 # @@ -1236,6 +1270,11 @@ # Host "redis.example.com" # Port "6379" # Timeout 2000 +# +# #Database 0 +# Type "queue_length" +# Instance "myqueue" +# # # @@ -1298,21 +1337,31 @@ # # -# Type "voltage" # Table false -# Instance "input_line1" +# Type "voltage" +# TypeInstance "input_line1" # Values "SNMPv2-SMI::enterprises.6050.5.4.1.1.2.1" # # -# Type "users" # Table false -# Instance "" +# Type "users" +# TypeInstance "" # Values "HOST-RESOURCES-MIB::hrSystemNumUsers.0" # # +# Table true # Type "if_octets" +# TypeInstanceOID "IF-MIB::ifDescr" +# #TypeInstancePrefix "port" +# Values "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets" +# #FilterOID "IF-MIB::ifOperStatus" +# #FilterValues "1", "2" +# +# # Table true -# Instance "IF-MIB::ifDescr" +# Type "if_octets" +# Plugin "interface" +# PluginInstanceOID "IF-MIB::ifDescr" # Values "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets" # # @@ -1353,7 +1402,9 @@ # IndexOID "IF-MIB::ifIndex" # SizeOID "IF-MIB::ifNumber" # -# Instance true +# +# Source "PluginInstance" +# # Plugin "interface" # OIDs "IF-MIB::ifDescr" # @@ -1607,6 +1658,7 @@ # PluginInstanceFormat name # Instances 1 # ExtraStats "cpu_util disk disk_err domain_state fs_info job_stats_background pcpu perf vcpupin" +# PersistentNotification false # # diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index e9715126..75b956fe 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -530,9 +530,9 @@ are disabled by default. =head2 Plugin C The I can be used to communicate with other instances of -I or third party applications using an AMQP message broker. Values -are sent to or received from the broker, which handles routing, queueing and -possibly filtering out messages. +I or third party applications using an AMQP 0.9.1 message broker. +Values are sent to or received from the broker, which handles routing, +queueing and possibly filtering out messages. B @@ -738,6 +738,171 @@ is preserved, i.e. passed through. =back +=head2 Plugin C + +The I can be used to communicate with other instances of +I or third party applications using an AMQP 1.0 message +intermediary. Metric values or notifications are sent to the +messaging intermediary which may handle direct messaging or +queue based transfer. + +B + + + # Send values to an AMQP 1.0 intermediary + + Host "localhost" + Port "5672" + User "guest" + Password "guest" + Address "collectd" +# RetryDelay 1 + + Format "command" + PreSettle false + Notify false + # StoreRates false + # GraphitePrefix "collectd." + # GraphiteEscapeChar "_" + # GraphiteSeparateInstances false + # GraphiteAlwaysAppendDS false + # GraphitePreserveSeparator false + + + + +The plugin's configuration consists of a I that configures +communications to the AMQP 1.0 messaging bus and one or more I +corresponding to metric or event publishers to the messaging system. + +The address in the I block concatenated with the name given in the +I block starting tag will be used as the send-to address for +communications over the messaging link. + +The following options are accepted within each I block: + +=over 4 + +=item B I + +Hostname or IP-address of the AMQP 1.0 intermediary. Defaults to the +default behavior of the underlying communications library, +I, which is "localhost". + +=item B I + +Service name or port number on which the AMQP 1.0 intermediary accepts +connections. This argument must be a string, even if the numeric form +is used. Defaults to "5672". + +=item B I + +=item B I + +Credentials used to authenticate to the AMQP 1.0 intermediary. By +default "guest"/"guest" is used. + +=item B
I
+ +This option specifies the prefix for the send-to value in the message. +By default, "collectd" will be used. + +=item B I + +When the AMQP1 connection is lost, defines the time in seconds to wait +before attempting to reconnect. Defaults to 1, which implies attempt +to reconnect at 1 second intervals. + +=back + +The following options are accepted within each I block: + +=over 4 + +=item B B|B|B + +Selects the format in which messages are sent to the intermediary. If set to +B (the default), values are sent as C commands which are +identical to the syntax used by the I and I. In this +case, the C header field will be set to C. + +If set to B, the values are encoded in the I, +an easy and straight forward exchange format. The C header field +will be set to C. + +If set to B, values are encoded in the I format, which is +" \n". The C header field will be set to +C. + +A subscribing client I use the C header field to +determine how to decode the values. + +=item B B|B + +If set to B (the default), the plugin will wait for a message +acknowledgement from the messaging bus before sending the next +message. This indicates transfer of ownership to the messaging +system. If set to B, the plugin will not wait for a message +acknowledgement and the message may be dropped prior to transfer of +ownership. + +=item B B|B + +If set to B (the default), the plugin will service the +instance write call back as a value list. If set to B the +plugin will service the instance as a write notification callback +for alert formatting. + +=item B B|B + +Determines whether or not C, C and C data sources +are converted to a I (i.e. a C value). If set to B (the +default), no conversion is performed. Otherwise the conversion is performed +using the internal value cache. + +Please note that currently this option is only used if the B option has +been set to B. + +=item B + +A prefix can be added in the metric name when outputting in the I format. +It's added before the I name. +Metric name will be "" + +=item B + +A postfix can be added in the metric name when outputting in the I format. +It's added after the I name. +Metric name will be "" + +=item B + +Specify a character to replace dots (.) in the host part of the metric name. +In I metric name, dots are used as separators between different +metric parts (host, plugin, type). +Default is "_" (I). + +=item B B|B + +If set to B, the plugin instance and type instance will be in their own +path component, for example C. If set to B (the +default), the plugin and plugin instance (and likewise the type and type +instance) are put into one component, for example C. + +=item B B|B + +If set to B, append the name of the I (DS) to the "metric" +identifier. If set to B (the default), this is only done when there is +more than one DS. + +=item B B|B + +If set to B (the default) the C<.> (dot) character is replaced with +I. Otherwise, if set to B, the C<.> (dot) character +is preserved, i.e. passed through. + +=back + =head2 Plugin C To configure the C-plugin you first need to configure the Apache @@ -3182,6 +3347,7 @@ B ReportSoftwareEvents true EventList "/var/cache/pmu/GenuineIntel-6-2D-core.json" HardwareEvents "L2_RQSTS.CODE_RD_HIT,L2_RQSTS.CODE_RD_MISS" "L2_RQSTS.ALL_CODE_RD" + Cores "0-3" "4,6" "[12-15]" B @@ -3253,6 +3419,23 @@ event_download.py script to download event list for current CPU. This field is a list of event names or groups of comma separated event names. This option requires B option to be configured. +=item B I + +All events are reported on a per core basis. Monitoring of the events can be +configured for a group of cores (aggregated statistics). This field defines +groups of cores on which to monitor supported events. The field is represented +as list of strings with core group values. Each string represents a list of +cores in a group. If a group is enclosed in square brackets each core is added +individually to a separate group (that is statistics are not aggregated). +Allowed formats are: + 0,1,2,3 + 0-10,20-18 + 1,3,5-8,10,0x10-12 + [4-15,32-63] + +If an empty string is provided as value for this field default cores +configuration is applied - that is separate group is created for each core. + =back =head2 Plugin C @@ -3453,8 +3636,23 @@ a notification is sent. Defaults to B. If system event log (SEL) is enabled, plugin will listen for sensor threshold and discrete events. When event is received the notification is sent. +SEL event filtering can be configured using B and B +config options. Defaults to B. +=item B I + +Selects sensors to get events from or to ignore, depending on B. + +See F for details. + +=item B I|I + +If no configuration is given, the B plugin will pass events from all +sensors. This option enables you to do that: By setting B +to I the effect of B is inverted: All events from selected +sensors are ignored and all events from other sensors are passed. + =item B I|I If SEL clear event is enabled, plugin will delete event from SEL list after @@ -4059,8 +4257,9 @@ which the sizes of physical memory vary. The B connects to a Modbus "slave" via Modbus/TCP or Modbus/RTU and reads register values. It supports reading single registers (unsigned 16Ebit -values), large integer values (unsigned 32Ebit values) and floating point -values (two registers interpreted as IEEE floats in big endian notation). +values), large integer values (unsigned 32Ebit and 64Ebit values) and +floating point values (two registers interpreted as IEEE floats in big endian +notation). B @@ -4070,6 +4269,8 @@ B RegisterCmd ReadHolding Type voltage Instance "input-1" + #Scale 1.0 + #Shift 0.0 @@ -4128,7 +4329,7 @@ Configures the base register to read from the device. If the option B has been set to B or B, this and the next register will be read (the register number is increased by one). -=item B B|B|B|B|B|B|B|B +=item B B|B|B|B|B|B|B|B|B|B Specifies what kind of data is returned by the device. This defaults to B. If the type is B, B, B, B, @@ -4140,7 +4341,10 @@ significant 16Ebits are in the register at B. For B, B, or B, the high and low order registers are swapped with the most significant 16Ebits in the B and the least significant 16Ebits in -B. +B. If the type is B or B, four 16Ebit +registers at B, B, B and +B will be read and the data combined into one +64Evalue. =item B B|B @@ -4155,9 +4359,19 @@ supported. =item B I -Sets the type instance to use when dispatching the value to I. If +Sets the type instance to use when dispatching the value to I. If unset, an empty string (no type instance) is used. +=item B I + +The values taken from device are multiplied by I. The field is optional +and the default is B<1.0>. + +=item B I + +I is added to values from device after they have been multiplied by +B value. The field is optional and the default value is B<0.0>. + =back =item EB IE blocks @@ -6185,6 +6399,11 @@ long string is used so that the packet size of an ICMPv4 packet is exactly Sets the source address to use. I may either be a numerical network address or a network hostname. +=item B I + +Sets the address family to use. I may be "any", "ipv4" or "ipv6". This +option will be ignored if you set a B. + =item B I Sets the outgoing network device to be used. I has to specify an @@ -6875,8 +7094,8 @@ B CollectFileDescriptor false - CollectContextSwitch true - + CollectContextSwitch true + =over 4 @@ -7062,25 +7281,26 @@ Defaults to B. =head2 Plugin C -The I connects to one or more Redis servers and gathers -information about each server's state. For each server there is a I block -which configures the connection parameters for this node. +The I connects to one or more Redis servers, gathers +information about each server's state and executes user-defined queries. +For each server there is a I block which configures the connection +parameters and set of user-defined queries for this node. Host "localhost" Port "6379" Timeout 2000 + ReportCommandStats false + ReportCpuUsage true + #Database 0 Type "queue_length" Instance "myqueue" - + -The information shown in the synopsis above is the I -which is used by the plugin if no configuration is present. - =over 4 =item B I @@ -7088,7 +7308,9 @@ which is used by the plugin if no configuration is present. The B block identifies a new Redis node, that is a new Redis instance running in an specified host and port. The name for node is a canonical identifier which is used as I. It is limited to -64Echaracters in length. +128Echaracters in length. + +When no B is configured explicitly, plugin connects to "localhost:6379". =item B I @@ -7108,25 +7330,47 @@ Use I to authenticate when connecting to I. =item B I The B option set the socket timeout for node response. Since the Redis -read function is blocking, you should keep this value as low as possible. Keep -in mind that the sum of all B values for all B should be lower -than B defined globally. +read function is blocking, you should keep this value as low as possible. +It is expected what B values should be lower than B defined +globally. + +Defaults to 2000 (2 seconds). + +=item B B|B + +Enables or disables reporting of statistics based on the command type, including +rate of command calls and average CPU time consumed by command processing. +Defaults to B. + +=item B B|B + +Enables or disables reporting of CPU consumption statistics. +Defaults to B. =item B I The B block identifies a query to execute against the redis server. -There may be an arbitrary number of queries to execute. +There may be an arbitrary number of queries to execute. Each query should +return single string or integer. =item B I -Within a query definition, a valid collectd type to use as when submitting +Within a query definition, a valid I to use as when submitting the result of the query. When not supplied, will default to B. +Currently only types with one datasource are supported. +See L for more details on types and their configuration. + =item B I Within a query definition, an optional type instance to use when submitting the result of the query. When not supplied will default to the escaped -command, up to 64 chars. +command, up to 128 chars. + +=item B I + +This index selects the Redis logical database to use for query. Defaults +to C<0>. =back @@ -7566,7 +7810,9 @@ B IndexOID "IF-MIB::ifIndex" SizeOID "IF-MIB::ifNumber" - Instance true + + Source "PluginInstance" + Plugin "interface" OIDs "IF-MIB::ifDescr" @@ -7577,12 +7823,44 @@ B OIDs "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets"
+ + + + Source "PluginInstance" + + Plugin "virt" + OIDs "LIBVIRT-HYPERVISOR-MIB::lvhAffinityDomainName" + + + Plugin "virt" + + Source "TypeInstance" + Regex "^vcpu_([0-9]{1,3})-cpu_[0-9]{1,3}$" + Group 1 + + OIDs "LIBVIRT-HYPERVISOR-MIB::lvhVCPUIndex" + + + Plugin "virt" + + Source "TypeInstance" + Regex "^vcpu_[0-9]{1,3}-cpu_([0-9]{1,3})$" + Group 1 + + OIDs "LIBVIRT-HYPERVISOR-MIB::lvhCPUIndex" + + + Plugin "virt" + Type "cpu_affinity" + OIDs "LIBVIRT-HYPERVISOR-MIB::lvhCPUAffinity" + +
There are two types of blocks that can be contained in the CPluginE snmp_agentE> block: B and B: -=head3 The B block +=head3 B block The B block defines a list OIDs that are to be handled. This block can define scalar or table OIDs. If B block is defined inside of B
@@ -7591,11 +7869,34 @@ The following options can be set: =over 4 -=item B I +=item B block + +B block contains all data needed for proper index build of snmp table. +In case more than +one table B block has B block present then multiple key index is +built. If B block defines scalar data type B has no effect and can +be omitted. + +=over 8 + +=item B I -When B is set to B, the value for requested OID is copied from -plugin instance field of corresponding collectd value. If B block defines -scalar data type B has no effect and can be omitted. +B can be set to one of the following values: "Hostname", "Plugin", +"PluginInstance", "Type", "TypeInstance". This value indicates which field of +corresponding collectd metric is taken as a SNMP table index. + +=item B I + +B option can also be used to parse strings or numbers out of +specific field. For example: type-instance field which is "vcpu1-cpu2" can be +parsed into two numeric fields CPU = 2 and VCPU = 1 and can be later used +as a table index. + +=item B I + +B number can be specified in case groups are used in regex. + +=back =item B I @@ -8918,6 +9219,12 @@ B: I metrics can't be collected if I plugin is enabled. =back +=item B B|B +Override default configuration to only send notifications when there is a change +in the lifecycle state of a domain. When set to true notifications will be sent +for every read cycle. Default is false. Does not affect the stats being +dispatched. + =back =head2 Plugin C diff --git a/src/collectdmon.c b/src/collectdmon.c index 4a7d1a6b..0e2b0214 100644 --- a/src/collectdmon.c +++ b/src/collectdmon.c @@ -71,11 +71,11 @@ #define WCOREDUMP(s) 0 #endif /* ! WCOREDUMP */ -static int loop = 0; -static int restart = 0; +static int loop; +static int restart; -static const char *pidfile = NULL; -static pid_t collectd_pid = 0; +static const char *pidfile; +static pid_t collectd_pid; __attribute__((noreturn)) static void exit_usage(const char *name) { printf("Usage: %s [-- ]\n" @@ -95,26 +95,26 @@ __attribute__((noreturn)) static void exit_usage(const char *name) { } /* exit_usage */ static int pidfile_create(void) { - FILE *file = NULL; + FILE *file; - if (NULL == pidfile) + if (pidfile == NULL) pidfile = COLLECTDMON_PIDFILE; - if (NULL == (file = fopen(pidfile, "w"))) { + if ((file = fopen(pidfile, "w")) == NULL) { syslog(LOG_ERR, "Error: couldn't open PID-file (%s) for writing: %s", pidfile, strerror(errno)); return -1; } - fprintf(file, "%i\n", (int)getpid()); + fprintf(file, "%d\n", (int)getpid()); fclose(file); return 0; } /* pidfile_create */ static int pidfile_delete(void) { - assert(NULL != pidfile); + assert(pidfile); - if (0 != unlink(pidfile)) { + if (unlink(pidfile) != 0) { syslog(LOG_ERR, "Error: couldn't delete PID-file (%s): %s", pidfile, strerror(errno)); return -1; @@ -123,41 +123,37 @@ static int pidfile_delete(void) { } /* pidfile_remove */ static int daemonize(void) { - struct rlimit rl; - int dev_null; - - pid_t pid = 0; - int i = 0; - - if (0 != chdir("/")) { + if (chdir("/") != 0) { fprintf(stderr, "Error: chdir() failed: %s\n", strerror(errno)); return -1; } - if (0 != getrlimit(RLIMIT_NOFILE, &rl)) { + struct rlimit rl; + if (getrlimit(RLIMIT_NOFILE, &rl) != 0) { fprintf(stderr, "Error: getrlimit() failed: %s\n", strerror(errno)); return -1; } - if (0 > (pid = fork())) { + pid_t pid = fork(); + if (pid < 0) { fprintf(stderr, "Error: fork() failed: %s\n", strerror(errno)); return -1; } else if (pid != 0) { exit(0); } - if (0 != pidfile_create()) + if (pidfile_create() != 0) return -1; setsid(); - if (RLIM_INFINITY == rl.rlim_max) + if (rl.rlim_max == RLIM_INFINITY) rl.rlim_max = 1024; - for (i = 0; i < (int)rl.rlim_max; ++i) + for (int i = 0; i < (int)rl.rlim_max; ++i) close(i); - dev_null = open("/dev/null", O_RDWR); + int dev_null = open("/dev/null", O_RDWR); if (dev_null == -1) { syslog(LOG_ERR, "Error: couldn't open /dev/null: %s", strerror(errno)); return -1; @@ -192,9 +188,9 @@ static int daemonize(void) { } /* daemonize */ static int collectd_start(char **argv) { - pid_t pid = 0; + pid_t pid = fork(); - if (0 > (pid = fork())) { + if (pid < 0) { syslog(LOG_ERR, "Error: fork() failed: %s", strerror(errno)); return -1; } else if (pid != 0) { @@ -208,10 +204,10 @@ static int collectd_start(char **argv) { } /* collectd_start */ static int collectd_stop(void) { - if (0 == collectd_pid) + if (collectd_pid == 0) return 0; - if (0 != kill(collectd_pid, SIGTERM)) { + if (kill(collectd_pid, SIGTERM) != 0) { syslog(LOG_ERR, "Error: kill() failed: %s", strerror(errno)); return -1; } @@ -230,7 +226,7 @@ static void sig_hup_handler(int __attribute__((unused)) signo) { static void log_status(int status) { if (WIFEXITED(status)) { - if (0 == WEXITSTATUS(status)) + if (WEXITSTATUS(status) == 0) syslog(LOG_INFO, "Info: collectd terminated with exit status %i", WEXITSTATUS(status)); else @@ -246,24 +242,24 @@ static void log_status(int status) { static void check_respawn(void) { time_t t = time(NULL); - static time_t timestamp = 0; - static int counter = 0; + static time_t timestamp; + static int counter; - if ((t - 120) < timestamp) + if (timestamp >= t - 120) ++counter; else { timestamp = t; counter = 0; } - if (10 < counter) { + if (counter >= 10) { unsigned int time_left = 300; syslog(LOG_ERR, "Error: collectd is respawning too fast - " "disabled for %i seconds", time_left); - while ((0 < (time_left = sleep(time_left))) && (0 == loop)) + while (((time_left = sleep(time_left)) > 0) && loop == 0) ; } return; @@ -274,15 +270,13 @@ int main(int argc, char **argv) { char *collectd = NULL; char **collectd_argv = NULL; - struct sigaction sa; - int i = 0; /* parse command line options */ while (42) { int c = getopt(argc, argv, "hc:P:"); - if (-1 == c) + if (c == -1) break; switch (c) { @@ -299,19 +293,19 @@ int main(int argc, char **argv) { } for (i = optind; i < argc; ++i) - if (0 == strcmp(argv[i], "-f")) + if (strcmp(argv[i], "-f") == 0) break; /* i < argc => -f already present */ collectd_argc = 1 + argc - optind + ((i < argc) ? 0 : 1); - collectd_argv = (char **)calloc(collectd_argc + 1, sizeof(char *)); + collectd_argv = calloc(collectd_argc + 1, sizeof(*collectd_argv)); - if (NULL == collectd_argv) { + if (collectd_argv == NULL) { fprintf(stderr, "Out of memory."); return 3; } - collectd_argv[0] = (NULL == collectd) ? "collectd" : collectd; + collectd_argv[0] = (collectd == NULL) ? "collectd" : collectd; if (i == argc) collectd_argv[collectd_argc - 1] = "-f"; @@ -323,22 +317,23 @@ int main(int argc, char **argv) { openlog("collectdmon", LOG_CONS | LOG_PID, LOG_DAEMON); - if (-1 == daemonize()) { + if (daemonize() == -1) { free(collectd_argv); return 1; } - sa.sa_handler = sig_int_term_handler; - sa.sa_flags = 0; + struct sigaction sa = { + .sa_handler = sig_int_term_handler, .sa_flags = 0, + }; sigemptyset(&sa.sa_mask); - if (0 != sigaction(SIGINT, &sa, NULL)) { + if (sigaction(SIGINT, &sa, NULL) != 0) { syslog(LOG_ERR, "Error: sigaction() failed: %s", strerror(errno)); free(collectd_argv); return 1; } - if (0 != sigaction(SIGTERM, &sa, NULL)) { + if (sigaction(SIGTERM, &sa, NULL) != 0) { syslog(LOG_ERR, "Error: sigaction() failed: %s", strerror(errno)); free(collectd_argv); return 1; @@ -346,24 +341,24 @@ int main(int argc, char **argv) { sa.sa_handler = sig_hup_handler; - if (0 != sigaction(SIGHUP, &sa, NULL)) { + if (sigaction(SIGHUP, &sa, NULL) != 0) { syslog(LOG_ERR, "Error: sigaction() failed: %s", strerror(errno)); free(collectd_argv); return 1; } - while (0 == loop) { + while (loop == 0) { int status = 0; - if (0 != collectd_start(collectd_argv)) { + if (collectd_start(collectd_argv) != 0) { syslog(LOG_ERR, "Error: failed to start collectd."); break; } - assert(0 < collectd_pid); + assert(collectd_pid >= 0); while ((collectd_pid != waitpid(collectd_pid, &status, 0)) && - (EINTR == errno)) - if ((0 != loop) || (0 != restart)) + errno == EINTR) + if (loop != 0 || restart != 0) collectd_stop(); collectd_pid = 0; @@ -371,10 +366,10 @@ int main(int argc, char **argv) { log_status(status); check_respawn(); - if (0 != restart) { + if (restart != 0) { syslog(LOG_INFO, "Info: restarting collectd"); restart = 0; - } else if (0 == loop) + } else if (loop == 0) syslog(LOG_WARNING, "Warning: restarting collectd"); } diff --git a/src/conntrack.c b/src/conntrack.c index 3cd2deee..29c7003e 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -41,7 +41,7 @@ static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); Each table/chain combo that will be queried goes into this list */ -static int old_files = 0; +static int old_files; static int conntrack_config(const char *key, const char *value) { if (strcmp(key, "OldFiles") == 0) diff --git a/src/cpu.c b/src/cpu.c index 8480f11a..2a697129 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -183,23 +183,23 @@ static int pnumcpu; struct cpu_state_s { value_to_rate_state_t conv; gauge_t rate; - _Bool has_value; + bool has_value; }; typedef struct cpu_state_s cpu_state_t; -static cpu_state_t *cpu_states = NULL; -static size_t cpu_states_num = 0; /* #cpu_states allocated */ +static cpu_state_t *cpu_states; +static size_t cpu_states_num; /* #cpu_states allocated */ /* Highest CPU number in the current iteration. Used by the dispatch logic to * determine how many CPUs there were. Reset to 0 by cpu_reset(). */ -static size_t global_cpu_num = 0; +static size_t global_cpu_num; -static _Bool report_by_cpu = 1; -static _Bool report_by_state = 1; -static _Bool report_percent = 0; -static _Bool report_num_cpu = 0; -static _Bool report_guest = 0; -static _Bool subtract_guest = 1; +static bool report_by_cpu = true; +static bool report_by_state = true; +static bool report_percent; +static bool report_num_cpu; +static bool report_guest; +static bool subtract_guest = true; static const char *config_keys[] = {"ReportByCpu", "ReportByState", "ReportNumCpu", "ValuesPercentage", @@ -209,17 +209,17 @@ static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); static int cpu_config(char const *key, char const *value) /* {{{ */ { if (strcasecmp(key, "ReportByCpu") == 0) - report_by_cpu = IS_TRUE(value) ? 1 : 0; + report_by_cpu = IS_TRUE(value); else if (strcasecmp(key, "ValuesPercentage") == 0) - report_percent = IS_TRUE(value) ? 1 : 0; + report_percent = IS_TRUE(value); else if (strcasecmp(key, "ReportByState") == 0) - report_by_state = IS_TRUE(value) ? 1 : 0; + report_by_state = IS_TRUE(value); else if (strcasecmp(key, "ReportNumCpu") == 0) - report_num_cpu = IS_TRUE(value) ? 1 : 0; + report_num_cpu = IS_TRUE(value); else if (strcasecmp(key, "ReportGuestState") == 0) - report_guest = IS_TRUE(value) ? 1 : 0; + report_guest = IS_TRUE(value); else if (strcasecmp(key, "SubtractGuestState") == 0) - subtract_guest = IS_TRUE(value) ? 1 : 0; + subtract_guest = IS_TRUE(value); else return -1; @@ -431,7 +431,7 @@ static void aggregate(gauge_t *sum_by_state) /* {{{ */ } if (!isnan(this_cpu_states[COLLECTD_CPU_STATE_ACTIVE].rate)) - this_cpu_states[COLLECTD_CPU_STATE_ACTIVE].has_value = 1; + this_cpu_states[COLLECTD_CPU_STATE_ACTIVE].has_value = true; RATE_ADD(sum_by_state[COLLECTD_CPU_STATE_ACTIVE], this_cpu_states[COLLECTD_CPU_STATE_ACTIVE].rate); @@ -505,7 +505,7 @@ static void cpu_commit_num_cpu(gauge_t value) /* {{{ */ static void cpu_reset(void) /* {{{ */ { for (size_t i = 0; i < cpu_states_num; i++) - cpu_states[i].has_value = 0; + cpu_states[i].has_value = false; global_cpu_num = 0; } /* }}} void cpu_reset */ @@ -588,7 +588,7 @@ static int cpu_stage(size_t cpu_num, size_t state, derive_t d, return status; s->rate = rate; - s->has_value = 1; + s->has_value = true; return 0; } /* }}} int cpu_stage */ diff --git a/src/cpufreq.c b/src/cpufreq.c index 0139947e..851aad42 100644 --- a/src/cpufreq.c +++ b/src/cpufreq.c @@ -25,7 +25,7 @@ #include "common.h" #include "plugin.h" -static int num_cpu = 0; +static int num_cpu; static int cpufreq_init(void) { int status; diff --git a/src/csv.c b/src/csv.c index f5126d26..88726bba 100644 --- a/src/csv.c +++ b/src/csv.c @@ -33,9 +33,9 @@ static const char *config_keys[] = {"DataDir", "StoreRates"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static char *datadir = NULL; -static int store_rates = 0; -static int use_stdio = 0; +static char *datadir; +static int store_rates; +static int use_stdio; static int value_list_to_string(char *buffer, int buffer_len, const data_set_t *ds, const value_list_t *vl) { @@ -190,12 +190,12 @@ static int csv_config(const char *key, const char *value) { } datadir = strdup(value); if (datadir != NULL) { - int len = strlen(datadir); + size_t len = strlen(datadir); while ((len > 0) && (datadir[len - 1] == '/')) { len--; datadir[len] = '\0'; } - if (len <= 0) { + if (len == 0) { free(datadir); datadir = NULL; } diff --git a/src/curl.c b/src/curl.c index 35ec1f83..4bfd1e4d 100644 --- a/src/curl.c +++ b/src/curl.c @@ -60,14 +60,14 @@ struct web_page_s /* {{{ */ char *user; char *pass; char *credentials; - _Bool digest; - _Bool verify_peer; - _Bool verify_host; + bool digest; + bool verify_peer; + bool verify_host; char *cacert; struct curl_slist *headers; char *post_body; - _Bool response_time; - _Bool response_code; + bool response_time; + bool response_code; int timeout; curl_stats_t *stats; @@ -85,8 +85,7 @@ struct web_page_s /* {{{ */ /* * Global variables; */ -/* static CURLM *curl = NULL; */ -static web_page_t *pages_g = NULL; +static web_page_t *pages_g; /* * Private functions @@ -418,11 +417,11 @@ static int cc_config_add_page(oconfig_item_t *ci) /* {{{ */ page->url = NULL; page->user = NULL; page->pass = NULL; - page->digest = 0; - page->verify_peer = 1; - page->verify_host = 1; - page->response_time = 0; - page->response_code = 0; + page->digest = false; + page->verify_peer = true; + page->verify_host = true; + page->response_time = false; + page->response_code = false; page->timeout = -1; page->stats = NULL; diff --git a/src/curl_json.c b/src/curl_json.c index 09a606a8..f0badc99 100644 --- a/src/curl_json.c +++ b/src/curl_json.c @@ -74,7 +74,7 @@ typedef struct { * exists for this part of the JSON structure. */ typedef struct { cj_tree_entry_t *entry; - _Bool in_array; + bool in_array; int index; char name[DATA_MAX_NAME_LEN]; } cj_state_t; @@ -91,9 +91,9 @@ struct cj_s /* {{{ */ char *user; char *pass; char *credentials; - _Bool digest; - _Bool verify_peer; - _Bool verify_host; + bool digest; + bool verify_peer; + bool verify_host; char *cacert; struct curl_slist *headers; char *post_body; @@ -325,7 +325,7 @@ static int cj_cb_start_array(void *ctx) { return CJ_CB_ABORT; } db->depth++; - db->state[db->depth].in_array = 1; + db->state[db->depth].in_array = true; db->state[db->depth].index = 0; cj_load_key(db, "0"); @@ -335,7 +335,7 @@ static int cj_cb_start_array(void *ctx) { static int cj_cb_end_array(void *ctx) { cj_t *db = (cj_t *)ctx; - db->state[db->depth].in_array = 0; + db->state[db->depth].in_array = false; return cj_cb_end(ctx); } diff --git a/src/curl_json_test.c b/src/curl_json_test.c index e8f8f6bb..6c8640c2 100644 --- a/src/curl_json_test.c +++ b/src/curl_json_test.c @@ -139,7 +139,7 @@ DEF_TEST(parse) { return 0; } -int main(int argc, char **argv) { +int main(void) { cj_submit = test_submit; RUN_TEST(parse); diff --git a/src/curl_xml.c b/src/curl_xml.c index 19ae5f46..654bb671 100644 --- a/src/curl_xml.c +++ b/src/curl_xml.c @@ -79,9 +79,9 @@ struct cx_s /* {{{ */ char *user; char *pass; char *credentials; - _Bool digest; - _Bool verify_peer; - _Bool verify_host; + bool digest; + bool verify_peer; + bool verify_host; char *cacert; char *post_body; int timeout; diff --git a/src/daemon/cmd.c b/src/daemon/cmd.c new file mode 100644 index 00000000..7b779955 --- /dev/null +++ b/src/daemon/cmd.c @@ -0,0 +1,271 @@ +/** + * collectd - src/daemon/cmd.c + * Copyright (C) 2005-2007 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. + **/ + +#include "cmd.h" +#include "collectd.h" + +#include "common.h" +#include + +static void *do_flush(void __attribute__((unused)) * arg) { + INFO("Flushing all data."); + plugin_flush(/* plugin = */ NULL, + /* timeout = */ 0, + /* ident = */ NULL); + INFO("Finished flushing all data."); + pthread_exit(NULL); + return NULL; +} + +static void sig_int_handler(int __attribute__((unused)) signal) { + stop_collectd(); +} + +static void sig_term_handler(int __attribute__((unused)) signal) { + stop_collectd(); +} + +static void sig_usr1_handler(int __attribute__((unused)) signal) { + pthread_t thread; + pthread_attr_t attr; + + /* flushing the data might take a while, + * so it should be done asynchronously */ + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&thread, &attr, do_flush, NULL); + pthread_attr_destroy(&attr); +} + +#if COLLECT_DAEMON +static int pidfile_create(void) { + FILE *fh; + const char *file = global_option_get("PIDFile"); + + if ((fh = fopen(file, "w")) == NULL) { + ERROR("fopen (%s): %s", file, STRERRNO); + return 1; + } + + fprintf(fh, "%i\n", (int)getpid()); + fclose(fh); + + return 0; +} /* static int pidfile_create (const char *file) */ + +static int pidfile_remove(void) { + const char *file = global_option_get("PIDFile"); + if (file == NULL) + return 0; + + return unlink(file); +} /* static int pidfile_remove (const char *file) */ +#endif /* COLLECT_DAEMON */ + +#ifdef KERNEL_LINUX +static int notify_upstart(void) { + 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; + } + + NOTICE("Upstart detected, stopping now to signal readiness."); + raise(SIGSTOP); + unsetenv("UPSTART_JOB"); + + return 1; +} + +static int notify_systemd(void) { + size_t su_size; + const char *notifysocket = getenv("NOTIFY_SOCKET"); + if (notifysocket == NULL) + return 0; + + 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 readiness."); + + unsetenv("NOTIFY_SOCKET"); + + int fd; +#if defined(SOCK_CLOEXEC) + fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, /* protocol = */ 0); +#else + fd = socket(AF_UNIX, SOCK_DGRAM, /* protocol = */ 0); +#endif + if (fd < 0) { + ERROR("creating UNIX socket failed: %s", STRERRNO); + return 0; + } + + struct sockaddr_un su = {0}; + su.sun_family = AF_UNIX; + if (notifysocket[0] != '@') { + /* regular UNIX socket */ + sstrncpy(su.sun_path, notifysocket, sizeof(su.sun_path)); + su_size = sizeof(su); + } else { + /* Linux abstract namespace socket: specify address as "\0foo", i.e. + * start with a null byte. Since null bytes have no special meaning in + * that case, we have to set su_size correctly to cover only the bytes + * that are part of the address. */ + sstrncpy(su.sun_path, notifysocket, sizeof(su.sun_path)); + su.sun_path[0] = 0; + su_size = sizeof(sa_family_t) + strlen(notifysocket); + if (su_size > sizeof(su)) + su_size = sizeof(su); + } + + const char buffer[] = "READY=1\n"; + if (sendto(fd, buffer, strlen(buffer), MSG_NOSIGNAL, (void *)&su, + (socklen_t)su_size) < 0) { + ERROR("sendto(\"%s\") failed: %s", notifysocket, STRERRNO); + close(fd); + return 0; + } + + unsetenv("NOTIFY_SOCKET"); + close(fd); + return 1; +} +#endif /* KERNEL_LINUX */ + +int main(int argc, char **argv) { + struct cmdline_config config = init_config(argc, argv); + +#if COLLECT_DAEMON + /* + * fork off child + */ + struct sigaction sig_chld_action = {.sa_handler = SIG_IGN}; + + sigaction(SIGCHLD, &sig_chld_action, NULL); + + /* + * Only daemonize if we're not being supervised + * by upstart or systemd (when using Linux). + */ + if (config.daemonize +#ifdef KERNEL_LINUX + && notify_upstart() == 0 && notify_systemd() == 0 +#endif + ) { + pid_t pid; + if ((pid = fork()) == -1) { + /* error */ + fprintf(stderr, "fork: %s", STRERRNO); + return 1; + } else if (pid != 0) { + /* parent */ + /* printf ("Running (PID %i)\n", pid); */ + return 0; + } + + /* Detach from session */ + setsid(); + + /* Write pidfile */ + if (pidfile_create()) + exit(2); + + /* close standard descriptors */ + close(2); + close(1); + close(0); + + int status = open("/dev/null", O_RDWR); + if (status != 0) { + ERROR("Error: Could not connect `STDIN' to `/dev/null' (status %d)", + status); + return 1; + } + + status = dup(0); + if (status != 1) { + ERROR("Error: Could not connect `STDOUT' to `/dev/null' (status %d)", + status); + return 1; + } + + status = dup(0); + if (status != 2) { + ERROR("Error: Could not connect `STDERR' to `/dev/null', (status %d)", + status); + return 1; + } + } /* if (config.daemonize) */ +#endif /* COLLECT_DAEMON */ + + struct sigaction sig_pipe_action = {.sa_handler = SIG_IGN}; + + sigaction(SIGPIPE, &sig_pipe_action, NULL); + + /* + * install signal handlers + */ + struct sigaction sig_int_action = {.sa_handler = sig_int_handler}; + + if (sigaction(SIGINT, &sig_int_action, NULL) != 0) { + ERROR("Error: Failed to install a signal handler for signal INT: %s", + STRERRNO); + return 1; + } + + struct sigaction sig_term_action = {.sa_handler = sig_term_handler}; + + if (sigaction(SIGTERM, &sig_term_action, NULL) != 0) { + ERROR("Error: Failed to install a signal handler for signal TERM: %s", + STRERRNO); + return 1; + } + + struct sigaction sig_usr1_action = {.sa_handler = sig_usr1_handler}; + + if (sigaction(SIGUSR1, &sig_usr1_action, NULL) != 0) { + ERROR("Error: Failed to install a signal handler for signal USR1: %s", + STRERRNO); + return 1; + } + + int exit_status = run_loop(config.test_readall); + +#if COLLECT_DAEMON + if (config.daemonize) + pidfile_remove(); +#endif /* COLLECT_DAEMON */ + + return exit_status; +} /* int main */ diff --git a/src/daemon/cmd.h b/src/daemon/cmd.h new file mode 100644 index 00000000..152ee63e --- /dev/null +++ b/src/daemon/cmd.h @@ -0,0 +1,41 @@ +/** + * collectd - src/daemon/cmd.h + * Copyright (C) 2018 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. + **/ + +#ifndef CMD_H +#define CMD_H + +#include + +struct cmdline_config { + bool test_config; + bool test_readall; + bool create_basedir; + const char *configfile; + bool daemonize; +}; + +void stop_collectd(void); +struct cmdline_config init_config(int argc, char **argv); +int run_loop(bool test_readall); + +#endif /* CMD_H */ diff --git a/src/daemon/collectd.c b/src/daemon/collectd.c index e63c8466..b4668e06 100644 --- a/src/daemon/collectd.c +++ b/src/daemon/collectd.c @@ -25,6 +25,7 @@ * Alvaro Barcellos **/ +#include "cmd.h" #include "collectd.h" #include "common.h" @@ -33,7 +34,6 @@ #include #include -#include #if HAVE_LOCALE_H #include @@ -51,37 +51,11 @@ #define COLLECTD_LOCALE "C" #endif -static int loop = 0; - -static void *do_flush(void __attribute__((unused)) * arg) { - INFO("Flushing all data."); - plugin_flush(/* plugin = */ NULL, - /* timeout = */ 0, - /* ident = */ NULL); - INFO("Finished flushing all data."); - pthread_exit(NULL); - return NULL; -} - -static void sig_int_handler(int __attribute__((unused)) signal) { loop++; } - -static void sig_term_handler(int __attribute__((unused)) signal) { loop++; } - -static void sig_usr1_handler(int __attribute__((unused)) signal) { - pthread_t thread; - pthread_attr_t attr; - - /* flushing the data might take a while, - * so it should be done asynchronously */ - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&thread, &attr, do_flush, NULL); - pthread_attr_destroy(&attr); -} +static int loop; static int init_hostname(void) { const char *str = global_option_get("Hostname"); - if ((str != NULL) && (str[0] != 0)) { + if (str && str[0] != '\0') { hostname_set(str); return 0; } @@ -118,8 +92,7 @@ static int init_hostname(void) { return -1; } - for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; - ai_ptr = ai_ptr->ai_next) { + for (struct addrinfo *ai_ptr = ai_list; ai_ptr; ai_ptr = ai_ptr->ai_next) { if (ai_ptr->ai_canonname == NULL) continue; @@ -132,13 +105,11 @@ static int init_hostname(void) { } /* int init_hostname */ static int init_global_variables(void) { - char const *str; - interval_g = cf_get_default_interval(); assert(interval_g > 0); DEBUG("interval_g = %.3f;", CDTIME_T_TO_DOUBLE(interval_g)); - str = global_option_get("Timeout"); + const char *str = global_option_get("Timeout"); if (str == NULL) str = "2"; timeout_g = atoi(str); @@ -156,18 +127,14 @@ static int init_global_variables(void) { return 0; } /* int init_global_variables */ -static int change_basedir(const char *orig_dir, _Bool create) { - char *dir; - size_t dirlen; - int status; - - dir = strdup(orig_dir); +static int change_basedir(const char *orig_dir, bool create) { + char *dir = strdup(orig_dir); if (dir == NULL) { ERROR("strdup failed: %s", STRERRNO); return -1; } - dirlen = strlen(dir); + size_t dirlen = strlen(dir); while ((dirlen > 0) && (dir[dirlen - 1] == '/')) dir[--dirlen] = '\0'; @@ -176,7 +143,7 @@ static int change_basedir(const char *orig_dir, _Bool create) { return -1; } - status = chdir(dir); + int status = chdir(dir); if (status == 0) { free(dir); return 0; @@ -211,8 +178,7 @@ static void update_kstat(void) { if ((kc = kstat_open()) == NULL) ERROR("Unable to open kstat control structure"); } else { - kid_t kid; - kid = kstat_chain_update(kc); + kid_t kid = kstat_chain_update(kc); if (kid > 0) { INFO("kstat chain has been updated"); plugin_init_all(); @@ -225,9 +191,6 @@ static void update_kstat(void) { } /* static void update_kstat (void) */ #endif /* HAVE_LIBKSTAT */ -/* TODO - * Remove all settings but `-f' and `-C' - */ __attribute__((noreturn)) static void exit_usage(int status) { printf("Usage: " PACKAGE_NAME " [OPTIONS]\n\n" @@ -292,13 +255,9 @@ static int do_init(void) { static int do_loop(void) { cdtime_t interval = cf_get_default_interval(); - cdtime_t wait_until; - - wait_until = cdtime() + interval; + cdtime_t wait_until = cdtime() + interval; while (loop == 0) { - cdtime_t now; - #if HAVE_LIBKSTAT update_kstat(); #endif @@ -306,7 +265,7 @@ static int do_loop(void) { /* Issue all plugins */ plugin_read_all(); - now = cdtime(); + cdtime_t now = cdtime(); if (now >= wait_until) { WARNING("Not sleeping because the next interval is " "%.3f seconds in the past!", @@ -333,150 +292,33 @@ static int do_shutdown(void) { return plugin_shutdown_all(); } /* int do_shutdown */ -#if COLLECT_DAEMON -static int pidfile_create(void) { - FILE *fh; - const char *file = global_option_get("PIDFile"); - - if ((fh = fopen(file, "w")) == NULL) { - ERROR("fopen (%s): %s", file, STRERRNO); - return 1; - } - - fprintf(fh, "%i\n", (int)getpid()); - fclose(fh); - - return 0; -} /* static int pidfile_create (const char *file) */ - -static int pidfile_remove(void) { - const char *file = global_option_get("PIDFile"); - if (file == NULL) - return 0; - - return unlink(file); -} /* static int pidfile_remove (const char *file) */ -#endif /* COLLECT_DAEMON */ - -#ifdef KERNEL_LINUX -static int notify_upstart(void) { - 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; - } - - NOTICE("Upstart detected, stopping now to signal readiness."); - raise(SIGSTOP); - unsetenv("UPSTART_JOB"); - - return 1; -} - -static int notify_systemd(void) { - int fd; - const char *notifysocket; - struct sockaddr_un su = {0}; - size_t su_size; - char buffer[] = "READY=1\n"; - - notifysocket = getenv("NOTIFY_SOCKET"); - if (notifysocket == NULL) - return 0; - - 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 readiness."); - - unsetenv("NOTIFY_SOCKET"); - -#if defined(SOCK_CLOEXEC) - fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, /* protocol = */ 0); -#else - fd = socket(AF_UNIX, SOCK_DGRAM, /* protocol = */ 0); -#endif - if (fd < 0) { - ERROR("creating UNIX socket failed: %s", STRERRNO); - return 0; - } - - su.sun_family = AF_UNIX; - if (notifysocket[0] != '@') { - /* regular UNIX socket */ - sstrncpy(su.sun_path, notifysocket, sizeof(su.sun_path)); - su_size = sizeof(su); - } else { - /* Linux abstract namespace socket: specify address as "\0foo", i.e. - * start with a null byte. Since null bytes have no special meaning in - * that case, we have to set su_size correctly to cover only the bytes - * that are part of the address. */ - sstrncpy(su.sun_path, notifysocket, sizeof(su.sun_path)); - su.sun_path[0] = 0; - su_size = sizeof(sa_family_t) + strlen(notifysocket); - if (su_size > sizeof(su)) - su_size = sizeof(su); - } - - if (sendto(fd, buffer, strlen(buffer), MSG_NOSIGNAL, (void *)&su, - (socklen_t)su_size) < 0) { - ERROR("sendto(\"%s\") failed: %s", notifysocket, STRERRNO); - close(fd); - return 0; - } - - unsetenv("NOTIFY_SOCKET"); - close(fd); - return 1; -} -#endif /* KERNEL_LINUX */ - -struct cmdline_config { - _Bool test_config; - _Bool test_readall; - _Bool create_basedir; - const char *configfile; - _Bool daemonize; -}; - static void read_cmdline(int argc, char **argv, struct cmdline_config *config) { /* read options */ while (1) { - int c; - c = getopt(argc, argv, "htTC:" + int c = getopt(argc, argv, "htTC:" #if COLLECT_DAEMON - "fP:" + "fP:" #endif - ); + ); if (c == -1) break; switch (c) { case 'B': - config->create_basedir = 0; + config->create_basedir = false; break; case 'C': config->configfile = optarg; break; case 't': - config->test_config = 1; + config->test_config = true; break; case 'T': - config->test_readall = 1; + config->test_readall = true; global_option_set("ReadThreads", "-1", 1); #if COLLECT_DAEMON - config->daemonize = 0; + config->daemonize = false; #endif /* COLLECT_DAEMON */ break; #if COLLECT_DAEMON @@ -484,12 +326,11 @@ static void read_cmdline(int argc, char **argv, struct cmdline_config *config) { global_option_set("PIDFile", optarg, 1); break; case 'f': - config->daemonize = 0; + config->daemonize = false; break; #endif /* COLLECT_DAEMON */ case 'h': exit_usage(0); - break; default: exit_usage(1); } /* switch (c) */ @@ -497,7 +338,6 @@ static void read_cmdline(int argc, char **argv, struct cmdline_config *config) { } static int configure_collectd(struct cmdline_config *config) { - const char *basedir; /* * Read options from the config file, the environment and the command * line (in that order, with later options overwriting previous ones in @@ -514,6 +354,7 @@ static int configure_collectd(struct cmdline_config *config) { * Change directory. We do this _after_ reading the config and loading * modules to relative paths work as expected. */ + const char *basedir; if ((basedir = global_option_get("BaseDir")) == NULL) { fprintf(stderr, "Don't have a basedir to use. This should not happen. Ever."); @@ -535,20 +376,17 @@ static int configure_collectd(struct cmdline_config *config) { return 0; } -int main(int argc, char **argv) { -#if COLLECT_DAEMON - pid_t pid; -#endif - int exit_status = 0; +void stop_collectd(void) { loop++; } +struct cmdline_config init_config(int argc, char **argv) { struct cmdline_config config = { - .daemonize = 1, .create_basedir = 1, .configfile = CONFIGFILE, + .daemonize = true, .create_basedir = true, .configfile = CONFIGFILE, }; read_cmdline(argc, argv, &config); if (config.test_config) - return 0; + exit(EXIT_SUCCESS); if (optind < argc) exit_usage(1); @@ -558,110 +396,18 @@ int main(int argc, char **argv) { if (configure_collectd(&config) != 0) exit(EXIT_FAILURE); -#if COLLECT_DAEMON - /* - * fork off child - */ - struct sigaction sig_chld_action = {.sa_handler = SIG_IGN}; - - sigaction(SIGCHLD, &sig_chld_action, NULL); - - /* - * Only daemonize if we're not being supervised - * by upstart or systemd (when using Linux). - */ - if (config.daemonize -#ifdef KERNEL_LINUX - && notify_upstart() == 0 && notify_systemd() == 0 -#endif - ) { - int status; - - if ((pid = fork()) == -1) { - /* error */ - fprintf(stderr, "fork: %s", STRERRNO); - return 1; - } else if (pid != 0) { - /* parent */ - /* printf ("Running (PID %i)\n", pid); */ - return 0; - } - - /* Detach from session */ - setsid(); - - /* Write pidfile */ - if (pidfile_create()) - exit(2); - - /* close standard descriptors */ - close(2); - close(1); - close(0); - - status = open("/dev/null", O_RDWR); - if (status != 0) { - ERROR("Error: Could not connect `STDIN' to `/dev/null' (status %d)", - status); - return 1; - } - - status = dup(0); - if (status != 1) { - ERROR("Error: Could not connect `STDOUT' to `/dev/null' (status %d)", - status); - return 1; - } - - status = dup(0); - if (status != 2) { - ERROR("Error: Could not connect `STDERR' to `/dev/null', (status %d)", - status); - return 1; - } - } /* if (config.daemonize) */ -#endif /* COLLECT_DAEMON */ - - struct sigaction sig_pipe_action = {.sa_handler = SIG_IGN}; - - sigaction(SIGPIPE, &sig_pipe_action, NULL); - - /* - * install signal handlers - */ - struct sigaction sig_int_action = {.sa_handler = sig_int_handler}; - - if (0 != sigaction(SIGINT, &sig_int_action, NULL)) { - ERROR("Error: Failed to install a signal handler for signal INT: %s", - STRERRNO); - return 1; - } - - struct sigaction sig_term_action = {.sa_handler = sig_term_handler}; - - if (0 != sigaction(SIGTERM, &sig_term_action, NULL)) { - ERROR("Error: Failed to install a signal handler for signal TERM: %s", - STRERRNO); - return 1; - } - - struct sigaction sig_usr1_action = {.sa_handler = sig_usr1_handler}; + return config; +} - if (0 != sigaction(SIGUSR1, &sig_usr1_action, NULL)) { - ERROR("Error: Failed to install a signal handler for signal USR1: %s", - STRERRNO); - return 1; - } +int run_loop(bool test_readall) { + int exit_status = 0; - /* - * run the actual loops - */ if (do_init() != 0) { ERROR("Error: one or more plugin init callbacks failed."); exit_status = 1; } - if (config.test_readall) { + if (test_readall) { if (plugin_read_all_once() != 0) { ERROR("Error: one or more plugin read callbacks failed."); exit_status = 1; @@ -679,10 +425,5 @@ int main(int argc, char **argv) { exit_status = 1; } -#if COLLECT_DAEMON - if (config.daemonize) - pidfile_remove(); -#endif /* COLLECT_DAEMON */ - return exit_status; -} /* int main */ +} /* int run_loop */ diff --git a/src/daemon/collectd.h b/src/daemon/collectd.h index 0558aa40..459da4dc 100644 --- a/src/daemon/collectd.h +++ b/src/daemon/collectd.h @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -239,26 +240,6 @@ #define __attribute__(x) /**/ #endif -#if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__ -#undef strcpy -#undef strcat -#undef strtok -#pragma GCC poison strcpy strcat strtok -#endif - -/* - * Special hack for the perl plugin: Because the later included perl.h defines - * a macro which is never used, but contains `sprintf', we cannot poison that - * identifies just yet. The parl plugin will do that itself once perl.h is - * included. - */ -#ifndef DONT_POISON_SPRINTF_YET -#if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__ -#undef sprintf -#pragma GCC poison sprintf -#endif -#endif - #ifndef GAUGE_FORMAT #define GAUGE_FORMAT "%.15g" #endif diff --git a/src/daemon/common.c b/src/daemon/common.c index fbbb6085..76c7036d 100644 --- a/src/daemon/common.c +++ b/src/daemon/common.c @@ -417,7 +417,7 @@ int strunescape(char *buf, size_t buf_len) { continue; if (((i + 1) >= buf_len) || (buf[i + 1] == 0)) { - ERROR("string unescape: backslash found at end of string."); + P_ERROR("string unescape: backslash found at end of string."); /* Ensure null-byte at the end of the buffer. */ buf[i] = 0; return -1; @@ -544,9 +544,8 @@ int timeval_cmp(struct timeval tv0, struct timeval tv1, struct timeval *delta) { int check_create_dir(const char *file_orig) { struct stat statbuf; - char file_copy[512]; - char dir[512]; - int dir_len = 512; + char file_copy[PATH_MAX]; + char dir[PATH_MAX]; char *fields[16]; int fields_num; char *ptr; @@ -563,8 +562,10 @@ int check_create_dir(const char *file_orig) { if ((len = strlen(file_orig)) < 1) return -1; - else if (len >= sizeof(file_copy)) + else if (len >= sizeof(file_copy)) { + ERROR("check_create_dir: name (%s) is too long.", file_orig); return -1; + } /* * If `file_orig' ends in a slash the last component is a directory, @@ -605,9 +606,9 @@ int check_create_dir(const char *file_orig) { * behavior. */ if (fields[i][0] == '.') { - ERROR("Cowardly refusing to create a directory that " - "begins with a `.' (dot): `%s'", - file_orig); + P_ERROR("Cowardly refusing to create a directory that " + "begins with a `.' (dot): `%s'", + file_orig); return -2; } @@ -615,9 +616,10 @@ int check_create_dir(const char *file_orig) { * Join the components together again */ dir[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); + if (strjoin(dir + path_is_absolute, + (size_t)(sizeof(dir) - path_is_absolute), fields, + (size_t)(i + 1), "/") < 0) { + P_ERROR("strjoin failed: `%s', component #%i", file_orig, i); return -1; } @@ -633,16 +635,16 @@ int check_create_dir(const char *file_orig) { if (EEXIST == errno) continue; - ERROR("check_create_dir: mkdir (%s): %s", dir, STRERRNO); + P_ERROR("check_create_dir: mkdir (%s): %s", dir, STRERRNO); return -1; } else { - ERROR("check_create_dir: stat (%s): %s", dir, STRERRNO); + P_ERROR("check_create_dir: stat (%s): %s", dir, STRERRNO); return -1; } } else if (!S_ISDIR(statbuf.st_mode)) { - ERROR("check_create_dir: `%s' exists but is not " - "a directory!", - dir); + P_ERROR("check_create_dir: `%s' exists but is not " + "a directory!", + dir); return -1; } break; @@ -665,12 +667,12 @@ int get_kstat(kstat_t **ksp_ptr, char *module, int instance, char *name) { *ksp_ptr = kstat_lookup(kc, module, instance, name); if (*ksp_ptr == NULL) { - ERROR("get_kstat: Cound not find kstat %s", ident); + P_ERROR("get_kstat: Cound not find kstat %s", ident); return -1; } if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED) { - ERROR("get_kstat: kstat %s has wrong type", ident); + P_ERROR("get_kstat: kstat %s has wrong type", ident); *ksp_ptr = NULL; return -1; } @@ -681,12 +683,12 @@ int get_kstat(kstat_t **ksp_ptr, char *module, int instance, char *name) { #endif if (kstat_read(kc, *ksp_ptr, NULL) == -1) { - ERROR("get_kstat: kstat %s could not be read", ident); + P_ERROR("get_kstat: kstat %s could not be read", ident); return -1; } if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED) { - ERROR("get_kstat: kstat %s has wrong type", ident); + P_ERROR("get_kstat: kstat %s has wrong type", ident); return -1; } @@ -698,12 +700,12 @@ long long get_kstat_value(kstat_t *ksp, char *name) { long long retval = -1LL; if (ksp == NULL) { - ERROR("get_kstat_value (\"%s\"): ksp is NULL.", name); + P_ERROR("get_kstat_value (\"%s\"): ksp is NULL.", name); return -1LL; } else if (ksp->ks_type != KSTAT_TYPE_NAMED) { - ERROR("get_kstat_value (\"%s\"): ksp->ks_type (%#x) " - "is not KSTAT_TYPE_NAMED (%#x).", - name, (unsigned int)ksp->ks_type, (unsigned int)KSTAT_TYPE_NAMED); + P_ERROR("get_kstat_value (\"%s\"): ksp->ks_type (%#x) " + "is not KSTAT_TYPE_NAMED (%#x).", + name, (unsigned int)ksp->ks_type, (unsigned int)KSTAT_TYPE_NAMED); return -1LL; } @@ -721,7 +723,7 @@ long long get_kstat_value(kstat_t *ksp, char *name) { else if (kn->data_type == KSTAT_DATA_UINT64) retval = (long long)kn->value.ui64; /* XXX: Might overflow! */ else - WARNING("get_kstat_value: Not a numeric value: %s", name); + P_WARNING("get_kstat_value: Not a numeric value: %s", name); return retval; } @@ -857,7 +859,7 @@ int format_name(char *ret, int ret_len, const char *hostname, int format_values(char *ret, size_t ret_len, /* {{{ */ const data_set_t *ds, const value_list_t *vl, - _Bool store_rates) { + bool store_rates) { size_t offset = 0; int status; gauge_t *rates = NULL; @@ -1033,19 +1035,19 @@ int parse_value(const char *value_orig, value_t *ret_value, int ds_type) { default: sfree(value); - ERROR("parse_value: Invalid data source type: %i.", ds_type); + P_ERROR("parse_value: Invalid data source type: %i.", ds_type); return -1; } if (value == endptr) { - ERROR("parse_value: Failed to parse string as %s: \"%s\".", - DS_TYPE_TO_STRING(ds_type), value); + P_ERROR("parse_value: Failed to parse string as %s: \"%s\".", + DS_TYPE_TO_STRING(ds_type), value); sfree(value); return -1; } else if ((NULL != endptr) && ('\0' != *endptr)) - INFO("parse_value: Ignoring trailing garbage \"%s\" after %s value. " - "Input string was \"%s\".", - endptr, DS_TYPE_TO_STRING(ds_type), value_orig); + P_INFO("parse_value: Ignoring trailing garbage \"%s\" after %s value. " + "Input string was \"%s\".", + endptr, DS_TYPE_TO_STRING(ds_type), value_orig); sfree(value); return 0; @@ -1210,7 +1212,7 @@ int walk_directory(const char *dir, dirwalk_callback_f callback, failure = 0; if ((dh = opendir(dir)) == NULL) { - ERROR("walk_directory: Cannot open '%s': %s", dir, STRERRNO); + P_ERROR("walk_directory: Cannot open '%s': %s", dir, STRERRNO); return -1; } @@ -1250,7 +1252,7 @@ ssize_t read_file_contents(const char *filename, char *buf, size_t bufsize) { ret = (ssize_t)fread(buf, 1, bufsize, fh); if ((ret == 0) && (ferror(fh) != 0)) { - ERROR("read_file_contents: Reading file \"%s\" failed.", filename); + P_ERROR("read_file_contents: Reading file \"%s\" failed.", filename); ret = -1; } @@ -1409,8 +1411,8 @@ int service_name_to_port_number(const char *service_name) { status = getaddrinfo(/* node = */ NULL, service_name, &ai_hints, &ai_list); if (status != 0) { - ERROR("service_name_to_port_number: getaddrinfo failed: %s", - gai_strerror(status)); + P_ERROR("service_name_to_port_number: getaddrinfo failed: %s", + gai_strerror(status)); return -1; } @@ -1448,7 +1450,7 @@ void set_sock_opts(int sockfd) /* {{{ */ status = getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &socktype, &(socklen_t){sizeof(socktype)}); if (status != 0) { - WARNING("set_sock_opts: failed to determine socket type"); + P_WARNING("set_sock_opts: failed to determine socket type"); return; } @@ -1456,14 +1458,14 @@ void set_sock_opts(int sockfd) /* {{{ */ status = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &(int){1}, sizeof(int)); if (status != 0) - WARNING("set_sock_opts: failed to set socket keepalive flag"); + P_WARNING("set_sock_opts: failed to set socket keepalive flag"); #ifdef TCP_KEEPIDLE int tcp_keepidle = ((CDTIME_T_TO_MS(plugin_get_interval()) - 1) / 100 + 1); status = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &tcp_keepidle, sizeof(tcp_keepidle)); if (status != 0) - WARNING("set_sock_opts: failed to set socket tcp keepalive time"); + P_WARNING("set_sock_opts: failed to set socket tcp keepalive time"); #endif #ifdef TCP_KEEPINTVL @@ -1472,7 +1474,7 @@ void set_sock_opts(int sockfd) /* {{{ */ status = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, &tcp_keepintvl, sizeof(tcp_keepintvl)); if (status != 0) - WARNING("set_sock_opts: failed to set socket tcp keepalive interval"); + P_WARNING("set_sock_opts: failed to set socket tcp keepalive interval"); #endif } } /* }}} void set_sock_opts */ @@ -1556,12 +1558,12 @@ int check_capability(int arg) /* {{{ */ return -1; if (!(cap = cap_get_proc())) { - ERROR("check_capability: cap_get_proc failed."); + P_ERROR("check_capability: cap_get_proc failed."); return -1; } if (cap_get_flag(cap, cap_value, CAP_EFFECTIVE, &cap_flag_value) < 0) { - ERROR("check_capability: cap_get_flag failed."); + P_ERROR("check_capability: cap_get_flag failed."); cap_free(cap); return -1; } @@ -1572,8 +1574,8 @@ int check_capability(int arg) /* {{{ */ #else int check_capability(__attribute__((unused)) int arg) /* {{{ */ { - WARNING("check_capability: unsupported capability implementation. " - "Some plugin(s) may require elevated privileges to work properly."); + P_WARNING("check_capability: unsupported capability implementation. " + "Some plugin(s) may require elevated privileges to work properly."); return 0; } /* }}} int check_capability */ #endif /* HAVE_CAPABILITY */ diff --git a/src/daemon/common.h b/src/daemon/common.h index e3643626..db1b4650 100644 --- a/src/daemon/common.h +++ b/src/daemon/common.h @@ -319,7 +319,7 @@ int format_name(char *ret, int ret_len, const char *hostname, format_name(ret, ret_len, (vl)->host, (vl)->plugin, (vl)->plugin_instance, \ (vl)->type, (vl)->type_instance) int format_values(char *ret, size_t ret_len, const data_set_t *ds, - const value_list_t *vl, _Bool store_rates); + const value_list_t *vl, bool store_rates); int parse_identifier(char *str, char **ret_host, char **ret_plugin, char **ret_plugin_instance, char **ret_type, @@ -386,12 +386,10 @@ int strtogauge(const char *string, gauge_t *ret_value); int strarray_add(char ***ret_array, size_t *ret_array_len, char const *str); void strarray_free(char **array, size_t array_len); -#ifdef HAVE_SYS_CAPABILITY_H /** Check if the current process benefits from the capability passed in * argument. Returns zero if it does, less than zero if it doesn't or on error. * See capabilities(7) for the list of possible capabilities. * */ int check_capability(int arg); -#endif /* HAVE_SYS_CAPABILITY_H */ #endif /* COMMON_H */ diff --git a/src/daemon/configfile.c b/src/daemon/configfile.c index e61128eb..d9038002 100644 --- a/src/daemon/configfile.c +++ b/src/daemon/configfile.c @@ -76,7 +76,7 @@ typedef struct cf_value_map_s { typedef struct cf_global_option_s { const char *key; char *value; - _Bool from_cli; /* value set from CLI */ + bool from_cli; /* value set from CLI */ const char *def; } cf_global_option_t; @@ -91,8 +91,8 @@ static int dispatch_block_plugin(oconfig_item_t *ci); /* * Private variables */ -static cf_callback_t *first_callback = NULL; -static cf_complex_callback_t *complex_callback_head = NULL; +static cf_callback_t *first_callback; +static cf_complex_callback_t *complex_callback_head; static cf_value_map_t cf_value_map[] = {{"TypesDB", dispatch_value_typesdb}, {"PluginDir", dispatch_value_plugindir}, @@ -190,8 +190,12 @@ static int cf_dispatch(const char *type, const char *orig_key, } /* int cf_dispatch */ static int dispatch_global_option(const oconfig_item_t *ci) { - if (ci->values_num != 1) + if (ci->values_num != 1) { + ERROR("configfile: Global option `%s' needs exactly one argument.", + ci->key); return -1; + } + if (ci->values[0].type == OCONFIG_TYPE_STRING) return global_option_set(ci->key, ci->values[0].value.string, 0); else if (ci->values[0].type == OCONFIG_TYPE_NUMBER) { @@ -205,6 +209,8 @@ static int dispatch_global_option(const oconfig_item_t *ci) { return global_option_set(ci->key, "false", 0); } + ERROR("configfile: Global option `%s' argument has unknown type.", ci->key); + return -1; } /* int dispatch_global_option */ @@ -234,37 +240,37 @@ static int dispatch_value_typesdb(oconfig_item_t *ci) { static int dispatch_value_plugindir(oconfig_item_t *ci) { assert(strcasecmp(ci->key, "PluginDir") == 0); - if (ci->values_num != 1) - return -1; - if (ci->values[0].type != OCONFIG_TYPE_STRING) + if (ci->values_num != 1 || ci->values[0].type != OCONFIG_TYPE_STRING) { + ERROR("configfile: The `PluginDir' option needs exactly one string " + "argument."); return -1; + } plugin_set_dir(ci->values[0].value.string); return 0; } static int dispatch_loadplugin(oconfig_item_t *ci) { - const char *name; - _Bool global = 0; - plugin_ctx_t ctx = {0}; - plugin_ctx_t old_ctx; - int ret_val; + bool global = false; assert(strcasecmp(ci->key, "LoadPlugin") == 0); - if (ci->values_num != 1) - return -1; - if (ci->values[0].type != OCONFIG_TYPE_STRING) + if (ci->values_num != 1 || ci->values[0].type != OCONFIG_TYPE_STRING) { + ERROR("configfile: The `LoadPlugin' block needs exactly one string " + "argument."); return -1; + } - name = ci->values[0].value.string; + const char *name = ci->values[0].value.string; if (strcmp("libvirt", name) == 0) name = "virt"; /* default to the global interval set before loading this plugin */ - ctx.interval = cf_get_default_interval(); - ctx.flush_interval = 0; - ctx.flush_timeout = 0; + plugin_ctx_t ctx = { + .interval = cf_get_default_interval(), .name = strdup(name), + }; + if (ctx.name == NULL) + return ENOMEM; for (int i = 0; i < ci->children_num; ++i) { oconfig_item_t *child = ci->children + i; @@ -280,12 +286,12 @@ static int dispatch_loadplugin(oconfig_item_t *ci) { else { WARNING("Ignoring unknown LoadPlugin option \"%s\" " "for plugin \"%s\"", - child->key, ci->values[0].value.string); + child->key, name); } } - old_ctx = plugin_set_ctx(ctx); - ret_val = plugin_load(name, global); + plugin_ctx_t old_ctx = plugin_set_ctx(ctx); + int ret_val = plugin_load(name, global); /* reset to the "global" context */ plugin_set_ctx(old_ctx); @@ -333,6 +339,9 @@ static int dispatch_value(oconfig_item_t *ci) { break; } + if (ret != 0) + return ret; + for (int i = 0; i < cf_global_options_num; i++) if (strcasecmp(cf_global_options[i].key, ci->key) == 0) { ret = dispatch_global_option(ci); @@ -343,16 +352,18 @@ static int dispatch_value(oconfig_item_t *ci) { } /* int dispatch_value */ static int dispatch_block_plugin(oconfig_item_t *ci) { - const char *name; + assert(strcasecmp(ci->key, "Plugin") == 0); - if (strcasecmp(ci->key, "Plugin") != 0) - return -1; - if (ci->values_num < 1) + if (ci->values_num < 1) { + ERROR("configfile: The `Plugin' block requires arguments."); return -1; - if (ci->values[0].type != OCONFIG_TYPE_STRING) + } + if (ci->values[0].type != OCONFIG_TYPE_STRING) { + ERROR("configfile: First argument of `Plugin' block should be a string."); return -1; + } - name = ci->values[0].value.string; + const char *name = ci->values[0].value.string; if (strcmp("libvirt", name) == 0) { /* TODO(octo): Remove this legacy. */ WARNING("The \"libvirt\" plugin has been renamed to \"virt\" to avoid " @@ -372,7 +383,7 @@ static int dispatch_block_plugin(oconfig_item_t *ci) { ctx.interval = cf_get_default_interval(); old_ctx = plugin_set_ctx(ctx); - status = plugin_load(name, /* flags = */ 0); + status = plugin_load(name, /* flags = */ false); /* reset to the "global" context */ plugin_set_ctx(old_ctx); @@ -826,7 +837,7 @@ static oconfig_item_t *cf_read_generic(const char *path, const char *pattern, /* * Public functions */ -int global_option_set(const char *option, const char *value, _Bool from_cli) { +int global_option_set(const char *option, const char *value, bool from_cli) { int i; DEBUG("option = %s; value = %s;", option, value); @@ -1035,16 +1046,12 @@ int cf_read(const char *filename) { * success. */ int cf_util_get_string(const oconfig_item_t *ci, char **ret_string) /* {{{ */ { - char *string; - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - ERROR("cf_util_get_string: The %s option requires " - "exactly one string argument.", - ci->key); + P_ERROR("The `%s' option requires exactly one string argument.", ci->key); return -1; } - string = strdup(ci->values[0].value.string); + char *string = strdup(ci->values[0].value.string); if (string == NULL) return -1; @@ -1063,9 +1070,7 @@ int cf_util_get_string_buffer(const oconfig_item_t *ci, char *buffer, /* {{{ */ return EINVAL; if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - ERROR("cf_util_get_string_buffer: The %s option requires " - "exactly one string argument.", - ci->key); + P_ERROR("The `%s' option requires exactly one string argument.", ci->key); return -1; } @@ -1082,9 +1087,7 @@ int cf_util_get_int(const oconfig_item_t *ci, int *ret_value) /* {{{ */ return EINVAL; if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) { - ERROR("cf_util_get_int: The %s option requires " - "exactly one numeric argument.", - ci->key); + P_ERROR("The `%s' option requires exactly one numeric argument.", ci->key); return -1; } @@ -1099,9 +1102,7 @@ int cf_util_get_double(const oconfig_item_t *ci, double *ret_value) /* {{{ */ return EINVAL; if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) { - ERROR("cf_util_get_double: The %s option requires " - "exactly one numeric argument.", - ci->key); + P_ERROR("The `%s' option requires exactly one numeric argument.", ci->key); return -1; } @@ -1110,37 +1111,35 @@ int cf_util_get_double(const oconfig_item_t *ci, double *ret_value) /* {{{ */ return 0; } /* }}} int cf_util_get_double */ -int cf_util_get_boolean(const oconfig_item_t *ci, _Bool *ret_bool) /* {{{ */ +int cf_util_get_boolean(const oconfig_item_t *ci, bool *ret_bool) /* {{{ */ { if ((ci == NULL) || (ret_bool == NULL)) return EINVAL; if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN) && (ci->values[0].type != OCONFIG_TYPE_STRING))) { - ERROR("cf_util_get_boolean: The %s option requires " - "exactly one boolean argument.", - ci->key); + P_ERROR("The `%s' option requires exactly one boolean argument.", ci->key); return -1; } switch (ci->values[0].type) { case OCONFIG_TYPE_BOOLEAN: - *ret_bool = ci->values[0].value.boolean ? 1 : 0; + *ret_bool = ci->values[0].value.boolean ? true : false; break; case OCONFIG_TYPE_STRING: - WARNING("cf_util_get_boolean: Using string value `%s' for boolean option " - "`%s' is deprecated and will be removed in future releases. " - "Use unquoted true or false instead.", - ci->values[0].value.string, ci->key); + P_WARNING("Using string value `%s' for boolean option `%s' is deprecated " + "and will be removed in future releases. Use unquoted true or " + "false instead.", + ci->values[0].value.string, ci->key); if (IS_TRUE(ci->values[0].value.string)) - *ret_bool = 1; + *ret_bool = true; else if (IS_FALSE(ci->values[0].value.string)) - *ret_bool = 0; + *ret_bool = false; else { - ERROR("cf_util_get_boolean: Cannot parse string value `%s' of the `%s' " - "option as a boolean value.", - ci->values[0].value.string, ci->key); + P_ERROR("Cannot parse string value `%s' of the `%s' option as a boolean " + "value.", + ci->values[0].value.string, ci->key); return -1; } break; @@ -1152,12 +1151,11 @@ int cf_util_get_boolean(const oconfig_item_t *ci, _Bool *ret_bool) /* {{{ */ int cf_util_get_flag(const oconfig_item_t *ci, /* {{{ */ unsigned int *ret_value, unsigned int flag) { int status; - _Bool b; if (ret_value == NULL) return EINVAL; - b = 0; + bool b = false; status = cf_util_get_boolean(ci, &b); if (status != 0) return status; @@ -1182,9 +1180,7 @@ int cf_util_get_port_number(const oconfig_item_t *ci) /* {{{ */ if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_STRING) && (ci->values[0].type != OCONFIG_TYPE_NUMBER))) { - ERROR("cf_util_get_port_number: The \"%s\" option requires " - "exactly one string argument.", - ci->key); + P_ERROR("The `%s' option requires exactly one string argument.", ci->key); return -1; } @@ -1194,11 +1190,9 @@ int cf_util_get_port_number(const oconfig_item_t *ci) /* {{{ */ assert(ci->values[0].type == OCONFIG_TYPE_NUMBER); tmp = (int)(ci->values[0].value.number + 0.5); if ((tmp < 1) || (tmp > 65535)) { - ERROR("cf_util_get_port_number: The \"%s\" option requires " - "a service name or a port number. The number " - "you specified, %i, is not in the valid " - "range of 1-65535.", - ci->key, tmp); + P_ERROR("The `%s' option requires a service name or a port number. The " + "number you specified, %i, is not in the valid range of 1-65535.", + ci->key, tmp); return -1; } @@ -1212,18 +1206,15 @@ int cf_util_get_service(const oconfig_item_t *ci, char **ret_string) /* {{{ */ int status; if (ci->values_num != 1) { - ERROR("cf_util_get_service: The %s option requires exactly " - "one argument.", - ci->key); + P_ERROR("The `%s` option requires exactly one argument.", ci->key); return -1; } if (ci->values[0].type == OCONFIG_TYPE_STRING) return cf_util_get_string(ci, ret_string); if (ci->values[0].type != OCONFIG_TYPE_NUMBER) { - ERROR("cf_util_get_service: The %s option requires " - "exactly one string or numeric argument.", - ci->key); + P_ERROR("The `%s` option requires exactly one string or numeric argument.", + ci->key); } port = 0; @@ -1231,16 +1222,14 @@ int cf_util_get_service(const oconfig_item_t *ci, char **ret_string) /* {{{ */ if (status != 0) return status; else if ((port < 1) || (port > 65535)) { - ERROR("cf_util_get_service: The port number given " - "for the %s option is out of " - "range (%i).", - ci->key, port); + P_ERROR("The port number given for the `%s` option is out of range (%i).", + ci->key, port); return -1; } service = malloc(6); if (service == NULL) { - ERROR("cf_util_get_service: Out of memory."); + P_ERROR("cf_util_get_service: Out of memory."); return -1; } snprintf(service, 6, "%i", port); @@ -1257,16 +1246,13 @@ int cf_util_get_cdtime(const oconfig_item_t *ci, cdtime_t *ret_value) /* {{{ */ return EINVAL; if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) { - ERROR("cf_util_get_cdtime: The %s option requires " - "exactly one numeric argument.", - ci->key); + P_ERROR("The `%s' option requires exactly one numeric argument.", ci->key); return -1; } if (ci->values[0].value.number < 0.0) { - ERROR("cf_util_get_cdtime: The numeric argument of the %s " - "option must not be negative.", - ci->key); + P_ERROR("The numeric argument of the `%s' option must not be negative.", + ci->key); return -1; } diff --git a/src/daemon/configfile.h b/src/daemon/configfile.h index 7cebb97e..108609cb 100644 --- a/src/daemon/configfile.h +++ b/src/daemon/configfile.h @@ -89,7 +89,7 @@ int cf_register_complex(const char *type, int (*callback)(oconfig_item_t *)); */ int cf_read(const char *filename); -int global_option_set(const char *option, const char *value, _Bool from_cli); +int global_option_set(const char *option, const char *value, bool from_cli); const char *global_option_get(const char *option); long global_option_get_long(const char *option, long default_value); @@ -115,7 +115,7 @@ int cf_util_get_double(const oconfig_item_t *ci, double *ret_value); /* Assures the config option is a boolean and assignes it to `ret_bool'. * Otherwise, `ret_bool' is not changed and non-zero is returned. */ -int cf_util_get_boolean(const oconfig_item_t *ci, _Bool *ret_bool); +int cf_util_get_boolean(const oconfig_item_t *ci, bool *ret_bool); /* Assures the config option is a boolean and set or unset the given flag in * `ret_value' as appropriate. Returns non-zero on error. */ diff --git a/src/daemon/filter_chain.c b/src/daemon/filter_chain.c index 1352f5b3..a0a76876 100644 --- a/src/daemon/filter_chain.c +++ b/src/daemon/filter_chain.c @@ -693,7 +693,7 @@ static int fc_bit_write_invoke(const data_set_t *ds, /* {{{ */ static int fc_init_once(void) /* {{{ */ { - static int done = 0; + static int done; target_proc_t tproc = {0}; if (done != 0) diff --git a/src/daemon/meta_data.c b/src/daemon/meta_data.c index 4d59b712..08f682e9 100644 --- a/src/daemon/meta_data.c +++ b/src/daemon/meta_data.c @@ -40,7 +40,7 @@ union meta_value_u { int64_t mv_signed_int; uint64_t mv_unsigned_int; double mv_double; - _Bool mv_boolean; + bool mv_boolean; }; typedef union meta_value_u meta_value_t; @@ -524,7 +524,7 @@ int meta_data_add_double(meta_data_t *md, /* {{{ */ } /* }}} int meta_data_add_double */ int meta_data_add_boolean(meta_data_t *md, /* {{{ */ - const char *key, _Bool value) { + const char *key, bool value) { meta_entry_t *e; if ((md == NULL) || (key == NULL)) @@ -661,7 +661,7 @@ int meta_data_get_double(meta_data_t *md, /* {{{ */ } /* }}} int meta_data_get_double */ int meta_data_get_boolean(meta_data_t *md, /* {{{ */ - const char *key, _Bool *value) { + const char *key, bool *value) { meta_entry_t *e; if ((md == NULL) || (key == NULL) || (value == NULL)) diff --git a/src/daemon/meta_data.h b/src/daemon/meta_data.h index 50fdb8d6..203b1460 100644 --- a/src/daemon/meta_data.h +++ b/src/daemon/meta_data.h @@ -56,14 +56,14 @@ int meta_data_add_signed_int(meta_data_t *md, const char *key, int64_t value); int meta_data_add_unsigned_int(meta_data_t *md, const char *key, uint64_t value); int meta_data_add_double(meta_data_t *md, const char *key, double value); -int meta_data_add_boolean(meta_data_t *md, const char *key, _Bool value); +int meta_data_add_boolean(meta_data_t *md, const char *key, bool value); int meta_data_get_string(meta_data_t *md, const char *key, char **value); int meta_data_get_signed_int(meta_data_t *md, const char *key, int64_t *value); int meta_data_get_unsigned_int(meta_data_t *md, const char *key, uint64_t *value); int meta_data_get_double(meta_data_t *md, const char *key, double *value); -int meta_data_get_boolean(meta_data_t *md, const char *key, _Bool *value); +int meta_data_get_boolean(meta_data_t *md, const char *key, bool *value); /* Returns the value as a string, regardless of the type. */ int meta_data_as_string(meta_data_t *md, const char *key, char **value); diff --git a/src/daemon/meta_data_test.c b/src/daemon/meta_data_test.c index bcd457d4..ca808364 100644 --- a/src/daemon/meta_data_test.c +++ b/src/daemon/meta_data_test.c @@ -24,9 +24,10 @@ * Florian octo Forster */ -#include "common.h" /* for STATIC_ARRAY_SIZE */ #include "collectd.h" +#include "common.h" /* for STATIC_ARRAY_SIZE */ + #include "meta_data.h" #include "testing.h" @@ -37,7 +38,7 @@ DEF_TEST(base) { int64_t si; uint64_t ui; double d; - _Bool b; + bool b; CHECK_NOT_NULL(m = meta_data_create()); diff --git a/src/daemon/plugin.c b/src/daemon/plugin.c index 438366c2..92e1ab26 100644 --- a/src/daemon/plugin.c +++ b/src/daemon/plugin.c @@ -94,7 +94,7 @@ typedef struct flush_callback_s flush_callback_t; /* * Private variables */ -static c_avl_tree_t *plugins_loaded = NULL; +static c_avl_tree_t *plugins_loaded; static llist_t *list_init; static llist_t *list_write; @@ -104,42 +104,42 @@ static llist_t *list_shutdown; static llist_t *list_log; static llist_t *list_notification; -static fc_chain_t *pre_cache_chain = NULL; -static fc_chain_t *post_cache_chain = NULL; +static fc_chain_t *pre_cache_chain; +static fc_chain_t *post_cache_chain; static c_avl_tree_t *data_sets; -static char *plugindir = NULL; +static char *plugindir; #ifndef DEFAULT_MAX_READ_INTERVAL #define DEFAULT_MAX_READ_INTERVAL TIME_T_TO_CDTIME_T_STATIC(86400) #endif -static c_heap_t *read_heap = NULL; +static c_heap_t *read_heap; static llist_t *read_list; static int read_loop = 1; static pthread_mutex_t read_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t read_cond = PTHREAD_COND_INITIALIZER; -static pthread_t *read_threads = NULL; -static size_t read_threads_num = 0; +static pthread_t *read_threads; +static size_t read_threads_num; static cdtime_t max_read_interval = DEFAULT_MAX_READ_INTERVAL; static write_queue_t *write_queue_head; static write_queue_t *write_queue_tail; -static long write_queue_length = 0; -static _Bool write_loop = 1; +static long write_queue_length; +static bool write_loop = true; static pthread_mutex_t write_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t write_cond = PTHREAD_COND_INITIALIZER; -static pthread_t *write_threads = NULL; -static size_t write_threads_num = 0; +static pthread_t *write_threads; +static size_t write_threads_num; static pthread_key_t plugin_ctx_key; -static _Bool plugin_ctx_key_initialized = 0; +static bool plugin_ctx_key_initialized; -static long write_limit_high = 0; -static long write_limit_low = 0; +static long write_limit_high; +static long write_limit_low; -static derive_t stats_values_dropped = 0; -static _Bool record_statistics = 0; +static derive_t stats_values_dropped; +static bool record_statistics; /* * Static functions @@ -346,19 +346,22 @@ static void log_list_callbacks(llist_t **list, /* {{{ */ static int create_register_callback(llist_t **list, /* {{{ */ const char *name, void *callback, user_data_t const *ud) { - callback_func_t *cf; - cf = calloc(1, sizeof(*cf)); + if (name == NULL || callback == NULL) + return EINVAL; + + callback_func_t *cf = calloc(1, sizeof(*cf)); if (cf == NULL) { free_userdata(ud); ERROR("plugin: create_register_callback: calloc failed."); - return -1; + return ENOMEM; } cf->cf_callback = callback; if (ud == NULL) { - cf->cf_udata.data = NULL; - cf->cf_udata.free_func = NULL; + cf->cf_udata = (user_data_t){ + .data = NULL, .free_func = NULL, + }; } else { cf->cf_udata = *ud; } @@ -391,7 +394,7 @@ static int plugin_unregister(llist_t *list, const char *name) /* {{{ */ /* plugin_load_file loads the shared object "file" and calls its * "module_register" function. Returns zero on success, non-zero otherwise. */ -static int plugin_load_file(char const *file, _Bool global) { +static int plugin_load_file(char const *file, bool global) { int flags = RTLD_NOW; if (global) flags |= RTLD_GLOBAL; @@ -861,7 +864,7 @@ static void stop_write_threads(void) /* {{{ */ INFO("collectd: Stopping %" PRIsz " write threads.", write_threads_num); pthread_mutex_lock(&write_lock); - write_loop = 0; + write_loop = false; DEBUG("plugin: stop_write_threads: Signalling `write_cond'"); pthread_cond_broadcast(&write_cond); pthread_mutex_unlock(&write_lock); @@ -912,7 +915,7 @@ void plugin_set_dir(const char *dir) { ERROR("plugin_set_dir: strdup(\"%s\") failed", dir); } -static _Bool plugin_is_loaded(char const *name) { +static bool plugin_is_loaded(char const *name) { int status; if (plugins_loaded == NULL) @@ -954,7 +957,7 @@ static void plugin_free_loaded(void) { } #define BUFSIZE 512 -int plugin_load(char const *plugin_name, _Bool global) { +int plugin_load(char const *plugin_name, bool global) { DIR *dh; const char *dir; char filename[BUFSIZE] = ""; @@ -988,7 +991,7 @@ int plugin_load(char const *plugin_name, _Bool global) { */ if ((strcasecmp("perl", plugin_name) == 0) || (strcasecmp("python", plugin_name) == 0)) - global = 1; + global = true; /* `cpu' should not match `cpufreq'. To solve this we add `.so' to the * type when matching the filename */ @@ -1545,7 +1548,7 @@ int plugin_init_all(void) { uc_init(); if (IS_TRUE(global_option_get("CollectInternalStats"))) { - record_statistics = 1; + record_statistics = true; plugin_register_read("collectd", plugin_update_internal_statistics); } @@ -1714,8 +1717,12 @@ int plugin_write(const char *plugin, /* {{{ */ callback_func_t *cf = le->value; plugin_write_cb callback; - /* do not switch plugin context; rather keep the context (interval) - * information of the calling read plugin */ + /* Keep the read plugin's interval and flush information but update the + * plugin name. */ + plugin_ctx_t old_ctx = plugin_get_ctx(); + plugin_ctx_t ctx = old_ctx; + ctx.name = cf->cf_ctx.name; + plugin_set_ctx(ctx); DEBUG("plugin: plugin_write: Writing values via %s.", le->key); callback = cf->cf_callback; @@ -1725,6 +1732,7 @@ int plugin_write(const char *plugin, /* {{{ */ else success++; + plugin_set_ctx(old_ctx); le = le->next; } @@ -1890,7 +1898,7 @@ static int plugin_dispatch_values_internal(value_list_t *vl) { int status; static c_complain_t no_write_complaint = C_COMPLAIN_INIT_STATIC; - _Bool free_meta_data = 0; + bool free_meta_data = false; assert(vl != NULL); @@ -1910,7 +1918,7 @@ static int plugin_dispatch_values_internal(value_list_t *vl) { * this case matches and targets may add some and the calling function * may not expect (and therefore free) that data. */ if (vl->meta == NULL) - free_meta_data = 1; + free_meta_data = true; if (list_write == NULL) c_complain_once(LOG_WARNING, &no_write_complaint, @@ -1994,7 +2002,7 @@ static int plugin_dispatch_values_internal(value_list_t *vl) { } else fc_default_action(ds, vl); - if ((free_meta_data != 0) && (vl->meta != NULL)) { + if ((free_meta_data == true) && (vl->meta != NULL)) { meta_data_destroy(vl->meta); vl->meta = NULL; } @@ -2023,9 +2031,9 @@ static double get_drop_probability(void) /* {{{ */ return (double)pos / (double)size; } /* }}} double get_drop_probability */ -static _Bool check_drop_value(void) /* {{{ */ +static bool check_drop_value(void) /* {{{ */ { - static cdtime_t last_message_time = 0; + static cdtime_t last_message_time; static pthread_mutex_t last_message_lock = PTHREAD_MUTEX_INITIALIZER; double p; @@ -2033,11 +2041,11 @@ static _Bool check_drop_value(void) /* {{{ */ int status; if (write_limit_high == 0) - return 0; + return false; p = get_drop_probability(); if (p == 0.0) - return 0; + return false; status = pthread_mutex_trylock(&last_message_lock); if (status == 0) { @@ -2054,14 +2062,14 @@ static _Bool check_drop_value(void) /* {{{ */ } if (p == 1.0) - return 1; + return true; q = cdrand_d(); if (q > p) - return 1; + return true; else - return 0; -} /* }}} _Bool check_drop_value */ + return false; +} /* }}} bool check_drop_value */ int plugin_dispatch_values(value_list_t const *vl) { int status; @@ -2089,7 +2097,7 @@ int plugin_dispatch_values(value_list_t const *vl) { __attribute__((sentinel)) int plugin_dispatch_multivalue(value_list_t const *template, /* {{{ */ - _Bool store_percentage, int store_type, ...) { + bool store_percentage, int store_type, ...) { value_list_t *vl; int failed = 0; gauge_t sum = 0.0; @@ -2236,6 +2244,21 @@ void plugin_log(int level, const char *format, ...) { } } /* void plugin_log */ +void daemon_log(int level, const char *format, ...) { + char msg[1024] = ""; // Size inherits from plugin_log() + + char const *name = plugin_get_ctx().name; + if (name == NULL) + name = "UNKNOWN"; + + va_list ap; + va_start(ap, format); + vsnprintf(msg, sizeof(msg), format, ap); + va_end(ap); + + plugin_log(level, "%s plugin: %s", name, msg); +} /* void daemon_log */ + int parse_log_severity(const char *severity) { int log_level = -1; @@ -2330,7 +2353,7 @@ static int plugin_notification_meta_add(notification_t *n, const char *name, break; } case NM_TYPE_BOOLEAN: { - meta->nm_value.nm_boolean = *((_Bool *)value); + meta->nm_value.nm_boolean = *((bool *)value); break; } default: { @@ -2375,7 +2398,7 @@ int plugin_notification_meta_add_double(notification_t *n, const char *name, } int plugin_notification_meta_add_boolean(notification_t *n, const char *name, - _Bool value) { + bool value) { return plugin_notification_meta_add(n, name, NM_TYPE_BOOLEAN, &value); } @@ -2460,7 +2483,7 @@ static plugin_ctx_t *plugin_ctx_create(void) { void plugin_init_ctx(void) { pthread_key_create(&plugin_ctx_key, plugin_ctx_destructor); - plugin_ctx_key_initialized = 1; + plugin_ctx_key_initialized = true; } /* void plugin_init_ctx */ plugin_ctx_t plugin_get_ctx(void) { diff --git a/src/daemon/plugin.h b/src/daemon/plugin.h index a9ee72d4..871eccdc 100644 --- a/src/daemon/plugin.h +++ b/src/daemon/plugin.h @@ -147,7 +147,7 @@ typedef struct notification_meta_s { int64_t nm_signed_int; uint64_t nm_unsigned_int; double nm_double; - _Bool nm_boolean; + bool nm_boolean; } nm_value; struct notification_meta_s *next; } notification_meta_t; @@ -171,6 +171,7 @@ struct user_data_s { typedef struct user_data_s user_data_t; struct plugin_ctx_s { + char *name; cdtime_t interval; cdtime_t flush_interval; cdtime_t flush_timeout; @@ -230,7 +231,7 @@ void plugin_set_dir(const char *dir); * Re-loading an already loaded module is detected and zero is returned in * this case. */ -int plugin_load(const char *name, _Bool global); +int plugin_load(const char *name, bool global); int plugin_init_all(void); void plugin_read_all(void); @@ -346,7 +347,7 @@ int plugin_dispatch_values(value_list_t const *vl); * plugin_dispatch_multivalue * * SYNOPSIS - * plugin_dispatch_multivalue (vl, 1, DS_TYPE_GAUGE, + * plugin_dispatch_multivalue (vl, true, DS_TYPE_GAUGE, * "free", 42.0, * "used", 58.0, * NULL); @@ -374,7 +375,7 @@ int plugin_dispatch_values(value_list_t const *vl); * The number of values it failed to dispatch (zero on success). */ __attribute__((sentinel)) int plugin_dispatch_multivalue(value_list_t const *vl, - _Bool store_percentage, + bool store_percentage, int store_type, ...); int plugin_dispatch_missing(const value_list_t *vl); @@ -398,6 +399,15 @@ int parse_notif_severity(const char *severity); #define DEBUG(...) /* noop */ #endif /* ! COLLECT_DEBUG */ +/* This will log messages, prefixed by plugin name */ +void daemon_log(int level, const char *format, ...) + __attribute__((format(printf, 2, 3))); + +#define P_ERROR(...) daemon_log(LOG_ERR, __VA_ARGS__) +#define P_WARNING(...) daemon_log(LOG_WARNING, __VA_ARGS__) +#define P_NOTICE(...) daemon_log(LOG_NOTICE, __VA_ARGS__) +#define P_INFO(...) daemon_log(LOG_INFO, __VA_ARGS__) + const data_set_t *plugin_get_ds(const char *name); int plugin_notification_meta_add_string(notification_t *n, const char *name, @@ -409,7 +419,7 @@ int plugin_notification_meta_add_unsigned_int(notification_t *n, int plugin_notification_meta_add_double(notification_t *n, const char *name, double value); int plugin_notification_meta_add_boolean(notification_t *n, const char *name, - _Bool value); + bool value); int plugin_notification_meta_copy(notification_t *dst, const notification_t *src); diff --git a/src/daemon/plugin_mock.c b/src/daemon/plugin_mock.c index 96bf3826..1624f0ea 100644 --- a/src/daemon/plugin_mock.c +++ b/src/daemon/plugin_mock.c @@ -39,7 +39,7 @@ char *hostname_g = "example.com"; void plugin_set_dir(const char *dir) { /* nop */ } -int plugin_load(const char *name, _Bool global) { return ENOTSUP; } +int plugin_load(const char *name, bool global) { return ENOTSUP; } int plugin_register_config(const char *name, int (*callback)(const char *key, const char *val), @@ -56,7 +56,19 @@ int plugin_register_init(const char *name, plugin_init_cb callback) { return ENOTSUP; } -int plugin_register_read(const char *name, int (*callback)(void)) { +int plugin_register_read(__attribute__((unused)) const char *name, + __attribute__((unused)) int (*callback)(void)) { + return ENOTSUP; +} + +int plugin_register_write(__attribute__((unused)) const char *name, + __attribute__((unused)) plugin_write_cb callback, + __attribute__((unused)) user_data_t const *ud) { + return ENOTSUP; +} + +int plugin_register_missing(const char *name, plugin_missing_cb callback, + user_data_t const *ud) { return ENOTSUP; } @@ -75,6 +87,65 @@ int plugin_register_data_set(const data_set_t *ds) { return ENOTSUP; } int plugin_dispatch_values(value_list_t const *vl) { return ENOTSUP; } +int plugin_dispatch_notification(__attribute__((unused)) + const notification_t *notif) { + return ENOTSUP; +} + +int plugin_notification_meta_add_string(__attribute__((unused)) + notification_t *n, + __attribute__((unused)) + const char *name, + __attribute__((unused)) + const char *value) { + return ENOTSUP; +} + +int plugin_notification_meta_add_signed_int(__attribute__((unused)) + notification_t *n, + __attribute__((unused)) + const char *name, + __attribute__((unused)) + int64_t value) { + return ENOTSUP; +} + +int plugin_notification_meta_add_unsigned_int(__attribute__((unused)) + notification_t *n, + __attribute__((unused)) + const char *name, + __attribute__((unused)) + uint64_t value) { + return ENOTSUP; +} + +int plugin_notification_meta_add_double(__attribute__((unused)) + notification_t *n, + __attribute__((unused)) + const char *name, + __attribute__((unused)) double value) { + return ENOTSUP; +} + +int plugin_notification_meta_add_boolean(__attribute__((unused)) + notification_t *n, + __attribute__((unused)) + const char *name, + __attribute__((unused)) _Bool value) { + return ENOTSUP; +} + +int plugin_notification_meta_copy(__attribute__((unused)) notification_t *dst, + __attribute__((unused)) + const notification_t *src) { + return ENOTSUP; +} + +int plugin_notification_meta_free(__attribute__((unused)) + notification_meta_t *n) { + return ENOTSUP; +} + int plugin_flush(const char *plugin, cdtime_t timeout, const char *identifier) { return ENOTSUP; } @@ -99,6 +170,17 @@ void plugin_log(int level, char const *format, ...) { printf("plugin_log (%i, \"%s\");\n", level, buffer); } +void daemon_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("daemon_log (%i, \"%s\");\n", level, buffer); +} + void plugin_init_ctx(void) { /* nop */ } diff --git a/src/daemon/utils_avltree_test.c b/src/daemon/utils_avltree_test.c index bb30f9d6..3171246a 100644 --- a/src/daemon/utils_avltree_test.c +++ b/src/daemon/utils_avltree_test.c @@ -24,13 +24,14 @@ * Florian octo Forster */ -#include "common.h" /* STATIC_ARRAY_SIZE */ #include "collectd.h" +#include "common.h" /* STATIC_ARRAY_SIZE */ #include "testing.h" #include "utils_avltree.h" -static int compare_total_count = 0; +static int compare_total_count; + #define RESET_COUNTS() \ do { \ compare_total_count = 0; \ diff --git a/src/daemon/utils_cache.c b/src/daemon/utils_cache.c index b756d3b6..610c11e5 100644 --- a/src/daemon/utils_cache.c +++ b/src/daemon/utils_cache.c @@ -76,7 +76,7 @@ struct uc_iter_s { cache_entry_t *entry; }; -static c_avl_tree_t *cache_tree = NULL; +static c_avl_tree_t *cache_tree; static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER; static int cache_compare(const cache_entry_t *a, const cache_entry_t *b) { @@ -998,7 +998,7 @@ int uc_meta_data_exists(const value_list_t *vl, const value_list_t *vl, const char *key, double value) UC_WRAP(meta_data_add_double) int uc_meta_data_add_boolean( const value_list_t *vl, const char *key, - _Bool value) UC_WRAP(meta_data_add_boolean) + bool value) UC_WRAP(meta_data_add_boolean) int uc_meta_data_get_string(const value_list_t *vl, const char *key, @@ -1014,6 +1014,6 @@ int uc_meta_data_exists(const value_list_t *vl, const char *key, double *value) UC_WRAP(meta_data_get_double) int uc_meta_data_get_boolean( const value_list_t *vl, - const char *key, _Bool *value) + const char *key, bool *value) UC_WRAP(meta_data_get_boolean) #undef UC_WRAP diff --git a/src/daemon/utils_cache.h b/src/daemon/utils_cache.h index 08c2f10a..7200906d 100644 --- a/src/daemon/utils_cache.h +++ b/src/daemon/utils_cache.h @@ -42,7 +42,8 @@ int uc_update(const data_set_t *ds, const value_list_t *vl); int uc_get_rate_by_name(const char *name, gauge_t **ret_values, size_t *ret_values_num); gauge_t *uc_get_rate(const data_set_t *ds, const value_list_t *vl); -int uc_get_value_by_name(const char *name, value_t **ret_values, size_t *ret_values_num); +int uc_get_value_by_name(const char *name, value_t **ret_values, + size_t *ret_values_num); value_t *uc_get_value(const data_set_t *ds, const value_list_t *vl); size_t uc_get_size(void); @@ -124,7 +125,7 @@ int uc_meta_data_add_unsigned_int(const value_list_t *vl, const char *key, int uc_meta_data_add_double(const value_list_t *vl, const char *key, double value); int uc_meta_data_add_boolean(const value_list_t *vl, const char *key, - _Bool value); + bool value); int uc_meta_data_get_string(const value_list_t *vl, const char *key, char **value); @@ -135,6 +136,6 @@ int uc_meta_data_get_unsigned_int(const value_list_t *vl, const char *key, int uc_meta_data_get_double(const value_list_t *vl, const char *key, double *value); int uc_meta_data_get_boolean(const value_list_t *vl, const char *key, - _Bool *value); + bool *value); #endif /* !UTILS_CACHE_H */ diff --git a/src/daemon/utils_cache_mock.c b/src/daemon/utils_cache_mock.c index 5389d126..1495a803 100644 --- a/src/daemon/utils_cache_mock.c +++ b/src/daemon/utils_cache_mock.c @@ -24,8 +24,8 @@ * Florian octo Forster */ -#include #include "utils_cache.h" +#include gauge_t *uc_get_rate(__attribute__((unused)) data_set_t const *ds, __attribute__((unused)) value_list_t const *vl) { @@ -41,3 +41,8 @@ int uc_get_rate_by_name(const char *name, gauge_t **ret_values, int uc_get_names(char ***ret_names, cdtime_t **ret_times, size_t *ret_number) { return ENOTSUP; } + +int uc_get_value_by_name(const char *name, value_t **ret_values, + size_t *ret_values_num) { + return ENOTSUP; +} diff --git a/src/daemon/utils_complain.c b/src/daemon/utils_complain.c index d2162ba7..e34cf6fc 100644 --- a/src/daemon/utils_complain.c +++ b/src/daemon/utils_complain.c @@ -64,7 +64,7 @@ void c_complain(int level, c_complain_t *c, const char *format, ...) { va_start(ap, format); if (vcomplain(level, c, format, ap)) - c->complained_once = 1; + c->complained_once = true; va_end(ap); } /* c_complain */ @@ -76,7 +76,7 @@ void c_complain_once(int level, c_complain_t *c, const char *format, ...) { va_start(ap, format); if (vcomplain(level, c, format, ap)) - c->complained_once = 1; + c->complained_once = true; va_end(ap); } /* c_complain_once */ @@ -88,7 +88,7 @@ void c_do_release(int level, c_complain_t *c, const char *format, ...) { return; c->interval = 0; - c->complained_once = 0; + c->complained_once = false; va_start(ap, format); vsnprintf(message, sizeof(message), format, ap); diff --git a/src/daemon/utils_complain.h b/src/daemon/utils_complain.h index 46d3a198..88387be4 100644 --- a/src/daemon/utils_complain.h +++ b/src/daemon/utils_complain.h @@ -39,7 +39,7 @@ typedef struct { * 0 indicates that the complaint is no longer valid. */ cdtime_t interval; - _Bool complained_once; + bool complained_once; } c_complain_t; #define C_COMPLAIN_INIT_STATIC \ @@ -48,7 +48,7 @@ typedef struct { do { \ (c)->last = 0; \ (c)->interval = 0; \ - (c)->complained_once = 0; \ + (c)->complained_once = false; \ } while (0) /* diff --git a/src/daemon/utils_random.c b/src/daemon/utils_random.c index cf926f9c..7a9ce7be 100644 --- a/src/daemon/utils_random.c +++ b/src/daemon/utils_random.c @@ -32,7 +32,7 @@ #include static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; -static _Bool have_seed = 0; +static bool have_seed; static unsigned short seed[3]; static void cdrand_seed(void) { @@ -47,7 +47,7 @@ static void cdrand_seed(void) { seed[1] = (unsigned short)(t >> 16); seed[2] = (unsigned short)(t >> 32); - have_seed = 1; + have_seed = true; } double cdrand_d(void) { diff --git a/src/daemon/utils_subst.c b/src/daemon/utils_subst.c index 546ca186..28924e44 100644 --- a/src/daemon/utils_subst.c +++ b/src/daemon/utils_subst.c @@ -90,28 +90,6 @@ char *subst(char *buf, size_t buflen, const char *string, size_t off1, return buf; } /* subst */ -char *asubst(const char *string, int off1, int off2, const char *replacement) { - char *buf; - int len; - - char *ret; - - if ((NULL == string) || (0 > off1) || (0 > off2) || (off1 > off2) || - (NULL == replacement)) - return NULL; - - len = off1 + strlen(replacement) + strlen(string) - off2 + 1; - - buf = malloc(len); - if (NULL == buf) - return NULL; - - ret = subst(buf, len, string, off1, off2, replacement); - if (NULL == ret) - free(buf); - return ret; -} /* asubst */ - char *subst_string(char *buf, size_t buflen, const char *string, const char *needle, const char *replacement) { size_t needle_len; diff --git a/src/daemon/utils_subst.h b/src/daemon/utils_subst.h index a10b2589..7807555c 100644 --- a/src/daemon/utils_subst.h +++ b/src/daemon/utils_subst.h @@ -70,17 +70,6 @@ char *subst(char *buf, size_t buflen, const char *string, size_t off1, size_t off2, const char *replacement); /* - * asubst: - * - * This function is very similar to subst(). It differs in that it - * automatically allocates the memory required for the return value which the - * user then has to free himself. - * - * Returns the newly allocated result string on success, NULL else. - */ -char *asubst(const char *string, int off1, int off2, const char *replacement); - -/* * subst_string: * * Works like `subst', but instead of specifying start and end offsets you diff --git a/src/daemon/utils_time.c b/src/daemon/utils_time.c index a807c7f9..4637122e 100644 --- a/src/daemon/utils_time.c +++ b/src/daemon/utils_time.c @@ -144,9 +144,9 @@ static int format_zone(char *buffer, size_t buffer_size, } /* }}} int format_zone */ int format_rfc3339(char *buffer, size_t buffer_size, struct tm const *t_tm, - long nsec, _Bool print_nano, char const *zone) /* {{{ */ + long nsec, bool print_nano, char const *zone) /* {{{ */ { - int len; + size_t len; char *pos = buffer; size_t size_left = buffer_size; @@ -167,7 +167,7 @@ int format_rfc3339(char *buffer, size_t buffer_size, struct tm const *t_tm, } /* }}} int format_rfc3339 */ int format_rfc3339_utc(char *buffer, size_t buffer_size, cdtime_t t, - _Bool print_nano) /* {{{ */ + bool print_nano) /* {{{ */ { struct tm t_tm; long nsec = 0; @@ -181,7 +181,7 @@ int format_rfc3339_utc(char *buffer, size_t buffer_size, cdtime_t t, } /* }}} int format_rfc3339_utc */ int format_rfc3339_local(char *buffer, size_t buffer_size, cdtime_t t, - _Bool print_nano) /* {{{ */ + bool print_nano) /* {{{ */ { struct tm t_tm; long nsec = 0; diff --git a/src/dbi.c b/src/dbi.c index 60324e86..1909d8ca 100644 --- a/src/dbi.c +++ b/src/dbi.c @@ -54,7 +54,7 @@ struct cdbi_driver_option_s /* {{{ */ char *string; int numeric; } value; - _Bool is_numeric; + bool is_numeric; }; typedef struct cdbi_driver_option_s cdbi_driver_option_t; /* }}} */ @@ -83,12 +83,12 @@ typedef struct cdbi_database_s cdbi_database_t; /* }}} */ * Global variables */ #if !defined(HAVE_LEGACY_LIBDBI) || !HAVE_LEGACY_LIBDBI -static dbi_inst dbi_instance = 0; +static dbi_inst dbi_instance; #endif -static udb_query_t **queries = NULL; -static size_t queries_num = 0; -static cdbi_database_t **databases = NULL; -static size_t databases_num = 0; +static udb_query_t **queries; +static size_t queries_num; +static cdbi_database_t **databases; +static size_t databases_num; static int cdbi_read_database(user_data_t *ud); @@ -258,7 +258,7 @@ static int cdbi_config_add_database_driver_option(cdbi_database_t *db, /* {{{ */ } else { assert(ci->values[1].type == OCONFIG_TYPE_NUMBER); option->value.numeric = (int)(ci->values[1].value.number + .5); - option->is_numeric = 1; + option->is_numeric = true; } db->driver_options_num++; @@ -407,7 +407,7 @@ static int cdbi_config(oconfig_item_t *ci) /* {{{ */ static int cdbi_init(void) /* {{{ */ { - static int did_init = 0; + static int did_init; int status; if (did_init != 0) @@ -547,12 +547,18 @@ static int cdbi_read_database_query(cdbi_database_t *db, /* {{{ */ sstrncpy(column_names[i], column_name, DATA_MAX_NAME_LEN); } /* }}} for (i = 0; i < column_num; i++) */ - udb_query_prepare_result( + status = udb_query_prepare_result( q, prep_area, (db->host ? db->host : hostname_g), /* plugin = */ (db->plugin_name != NULL) ? db->plugin_name : "dbi", db->name, column_names, column_num, /* interval = */ (db->interval > 0) ? db->interval : 0); + if (status != 0) { + ERROR("dbi plugin: udb_query_prepare_result failed with status %i.", + status); + BAIL_OUT(-1); + } + /* 0 = error; 1 = success; */ status = dbi_result_first_row(res); /* {{{ */ if (status != 1) { diff --git a/src/df.c b/src/df.c index e1d5b513..8877b740 100644 --- a/src/df.c +++ b/src/df.c @@ -51,14 +51,14 @@ static const char *config_keys[] = { "ReportByDevice", "ReportInodes", "ValuesAbsolute", "ValuesPercentage"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static ignorelist_t *il_device = NULL; -static ignorelist_t *il_mountpoint = NULL; -static ignorelist_t *il_fstype = NULL; +static ignorelist_t *il_device; +static ignorelist_t *il_mountpoint; +static ignorelist_t *il_fstype; -static _Bool by_device = 0; -static _Bool report_inodes = 0; -static _Bool values_absolute = 1; -static _Bool values_percentage = 0; +static bool by_device; +static bool report_inodes; +static bool values_absolute = true; +static bool values_percentage; static int df_init(void) { if (il_device == NULL) @@ -99,28 +99,28 @@ static int df_config(const char *key, const char *value) { return 0; } else if (strcasecmp(key, "ReportByDevice") == 0) { if (IS_TRUE(value)) - by_device = 1; + by_device = true; return 0; } else if (strcasecmp(key, "ReportInodes") == 0) { if (IS_TRUE(value)) - report_inodes = 1; + report_inodes = true; else - report_inodes = 0; + report_inodes = false; return 0; } else if (strcasecmp(key, "ValuesAbsolute") == 0) { if (IS_TRUE(value)) - values_absolute = 1; + values_absolute = true; else - values_absolute = 0; + values_absolute = false; return 0; } else if (strcasecmp(key, "ValuesPercentage") == 0) { if (IS_TRUE(value)) - values_percentage = 1; + values_percentage = true; else - values_percentage = 0; + values_percentage = false; return 0; } @@ -225,12 +225,10 @@ static int df_read(void) { if (strcmp(mnt_ptr->dir, "/") == 0) sstrncpy(disk_name, "root", sizeof(disk_name)); else { - int len; - sstrncpy(disk_name, mnt_ptr->dir + 1, sizeof(disk_name)); - len = strlen(disk_name); + size_t len = strlen(disk_name); - for (int i = 0; i < len; i++) + for (size_t i = 0; i < len; i++) if (disk_name[i] == '/') disk_name[i] = '-'; } diff --git a/src/disk.c b/src/disk.c index 116fc244..206862ba 100644 --- a/src/disk.c +++ b/src/disk.c @@ -82,7 +82,7 @@ static mach_port_t io_master_port = MACH_PORT_NULL; /* This defaults to false for backwards compatibility. Please fix in the next * major version. */ -static _Bool use_bsd_name = 0; +static bool use_bsd_name; /* #endif HAVE_IOKIT_IOKITLIB_H */ #elif KERNEL_LINUX @@ -106,9 +106,9 @@ typedef struct diskstats { derive_t avg_read_time; derive_t avg_write_time; - _Bool has_merged; - _Bool has_in_progress; - _Bool has_io_time; + bool has_merged; + bool has_in_progress; + bool has_io_time; struct diskstats *next; } diskstats_t; @@ -126,7 +126,7 @@ static struct gmesh geom_tree; #define MAX_NUMDISK 1024 extern kstat_ctl_t *kc; static kstat_t *ksp[MAX_NUMDISK]; -static int numdisk = 0; +static int numdisk; /* #endif HAVE_LIBKSTAT */ #elif defined(HAVE_LIBSTATGRAB) @@ -145,7 +145,7 @@ static int pnumdisk; #if HAVE_LIBUDEV_H #include -static char *conf_udev_name_attr = NULL; +static char *conf_udev_name_attr; static struct udev *handle_udev; #endif @@ -153,7 +153,7 @@ static const char *config_keys[] = {"Disk", "UseBSDName", "IgnoreSelected", "UdevNameAttr"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static ignorelist_t *ignorelist = NULL; +static ignorelist_t *ignorelist; static int disk_config(const char *key, const char *value) { if (ignorelist == NULL) @@ -170,7 +170,7 @@ static int disk_config(const char *key, const char *value) { ignorelist_set_invert(ignorelist, invert); } else if (strcasecmp("UseBSDName", key) == 0) { #if HAVE_IOKIT_IOKITLIB_H - use_bsd_name = IS_TRUE(value) ? 1 : 0; + use_bsd_name = IS_TRUE(value); #else WARNING("disk plugin: The \"UseBSDName\" option is only supported " "on Mach / Mac OS X and will be ignored."); @@ -817,13 +817,13 @@ static int disk_read(void) { ds->write_time = write_time; if (read_merged || write_merged) - ds->has_merged = 1; + ds->has_merged = true; if (in_progress) - ds->has_in_progress = 1; + ds->has_in_progress = true; if (io_time) - ds->has_io_time = 1; + ds->has_io_time = true; } /* if (is_disk) */ diff --git a/src/dns.c b/src/dns.c index 3ab456b5..bd6820fa 100644 --- a/src/dns.c +++ b/src/dns.c @@ -57,7 +57,7 @@ static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); static int select_numeric_qtype = 1; #define PCAP_SNAPLEN 1460 -static char *pcap_device = NULL; +static char *pcap_device; static derive_t tr_queries; static derive_t tr_responses; @@ -66,7 +66,7 @@ static counter_list_t *opcode_list; static counter_list_t *rcode_list; static pthread_t listen_thread; -static int listen_thread_init = 0; +static int listen_thread_init; /* The `traffic' mutex if for `tr_queries' and `tr_responses' */ static pthread_mutex_t traffic_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t qtype_mutex = PTHREAD_MUTEX_INITIALIZER; diff --git a/src/dpdkevents.c b/src/dpdkevents.c index 064dce16..9970be0c 100644 --- a/src/dpdkevents.c +++ b/src/dpdkevents.c @@ -66,19 +66,19 @@ typedef struct dpdk_ka_monitor_s { typedef struct dpdk_link_status_config_s { int enabled; - _Bool send_updated; + bool send_updated; uint32_t enabled_port_mask; char port_name[RTE_MAX_ETHPORTS][DATA_MAX_NAME_LEN]; - _Bool notify; + bool notify; } dpdk_link_status_config_t; typedef struct dpdk_keep_alive_config_s { int enabled; - _Bool send_updated; + bool send_updated; uint128_t lcore_mask; dpdk_keepalive_shm_t *shm; char shm_name[DATA_MAX_NAME_LEN]; - _Bool notify; + bool notify; int fd; } dpdk_keep_alive_config_t; @@ -185,8 +185,8 @@ static void dpdk_events_default_config(void) { /* Link Status */ ec->config.link_status.enabled = 1; ec->config.link_status.enabled_port_mask = ~0; - ec->config.link_status.send_updated = 1; - ec->config.link_status.notify = 0; + ec->config.link_status.send_updated = true; + ec->config.link_status.notify = false; for (int i = 0; i < RTE_MAX_ETHPORTS; i++) { ec->config.link_status.port_name[i][0] = 0; @@ -194,8 +194,8 @@ static void dpdk_events_default_config(void) { /* Keep Alive */ ec->config.keep_alive.enabled = 1; - ec->config.keep_alive.send_updated = 1; - ec->config.keep_alive.notify = 0; + ec->config.keep_alive.send_updated = true; + ec->config.keep_alive.notify = false; /* by default enable 128 cores */ memset(&ec->config.keep_alive.lcore_mask, 1, sizeof(ec->config.keep_alive.lcore_mask)); @@ -428,7 +428,7 @@ static int dpdk_helper_link_status_get(dpdk_helper_ctx_t *phc) { } ec->nb_ports = nb_ports > RTE_MAX_ETHPORTS ? RTE_MAX_ETHPORTS : nb_ports; - for (int i = 0; i < ec->nb_ports; i++) { + for (unsigned int i = 0; i < ec->nb_ports; i++) { if (ec->config.link_status.enabled_port_mask & (1 << i)) { struct rte_eth_link link; ec->link_info[i].read_time = cdtime(); @@ -497,7 +497,7 @@ static int dpdk_events_link_status_dispatch(dpdk_helper_ctx_t *phc) { ec->nb_ports); /* dispatch Link Status values to collectd */ - for (int i = 0; i < ec->nb_ports; i++) { + for (unsigned int i = 0; i < ec->nb_ports; i++) { if (ec->config.link_status.enabled_port_mask & (1 << i)) { if (!ec->config.link_status.send_updated || ec->link_info[i].status_updated) { diff --git a/src/email.c b/src/email.c index d94c542f..f8a94fb6 100644 --- a/src/email.c +++ b/src/email.c @@ -111,13 +111,13 @@ static const char *config_keys[] = {"SocketFile", "SocketGroup", "SocketPerms", static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); /* socket configuration */ -static char *sock_file = NULL; -static char *sock_group = NULL; +static char *sock_file; +static char *sock_group; static int sock_perms = S_IRWXU | S_IRWXG; static int max_conns = MAX_CONNS; /* state of the plugin */ -static int disabled = 0; +static int disabled; /* thread managing "client" connections */ static pthread_t connector = (pthread_t)0; @@ -134,7 +134,7 @@ static conn_list_t conns; static pthread_cond_t collector_available = PTHREAD_COND_INITIALIZER; /* collector threads */ -static collector_t **collectors = NULL; +static collector_t **collectors; static pthread_mutex_t available_mutex = PTHREAD_MUTEX_INITIALIZER; static int available_collectors; @@ -260,7 +260,6 @@ static void *collect(void *arg) { while (42) { /* 256 bytes ought to be enough for anybody ;-) */ char line[256 + 1]; /* line + '\0' */ - int len = 0; errno = 0; if (fgets(line, sizeof(line), this->socket) == NULL) { @@ -272,7 +271,7 @@ static void *collect(void *arg) { break; } - len = strlen(line); + size_t len = strlen(line); if ((line[len - 1] != '\n') && (line[len - 1] != '\r')) { log_warn("collect: line too long (> %" PRIsz " characters): " "'%s' (truncated)", @@ -287,7 +286,7 @@ static void *collect(void *arg) { continue; } - line[len - 1] = 0; + line[len - 1] = '\0'; log_debug("collect: line = '%s'", line); diff --git a/src/ethstat.c b/src/ethstat.c index c5b02d3e..0d4c7e15 100644 --- a/src/ethstat.c +++ b/src/ethstat.c @@ -48,12 +48,12 @@ struct value_map_s { }; typedef struct value_map_s value_map_t; -static char **interfaces = NULL; -static size_t interfaces_num = 0; +static char **interfaces; +static size_t interfaces_num; -static c_avl_tree_t *value_map = NULL; +static c_avl_tree_t *value_map; -static _Bool collect_mapped_only = 0; +static bool collect_mapped_only; static int ethstat_add_interface(const oconfig_item_t *ci) /* {{{ */ { diff --git a/src/exec.c b/src/exec.c index 36f2d4da..b145e813 100644 --- a/src/exec.c +++ b/src/exec.c @@ -80,7 +80,7 @@ typedef struct program_list_and_notification_s { /* * Private variables */ -static program_list_t *pl_head = NULL; +static program_list_t *pl_head; static pthread_mutex_t pl_lock = PTHREAD_MUTEX_INITIALIZER; /* diff --git a/src/fhcount.c b/src/fhcount.c index 97f0438c..9bcb9115 100644 --- a/src/fhcount.c +++ b/src/fhcount.c @@ -25,25 +25,25 @@ static const char *config_keys[] = {"ValuesAbsolute", "ValuesPercentage"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static _Bool values_absolute = 1; -static _Bool values_percentage = 0; +static bool values_absolute = true; +static bool values_percentage; static int fhcount_config(const char *key, const char *value) { int ret = -1; if (strcasecmp(key, "ValuesAbsolute") == 0) { if (IS_TRUE(value)) { - values_absolute = 1; + values_absolute = true; } else { - values_absolute = 0; + values_absolute = false; } ret = 0; } else if (strcasecmp(key, "ValuesPercentage") == 0) { if (IS_TRUE(value)) { - values_percentage = 1; + values_percentage = true; } else { - values_percentage = 0; + values_percentage = false; } ret = 0; diff --git a/src/filecount.c b/src/filecount.c index 67308f41..9091ff55 100644 --- a/src/filecount.c +++ b/src/filecount.c @@ -60,8 +60,8 @@ struct fc_directory_conf_s { }; typedef struct fc_directory_conf_s fc_directory_conf_t; -static fc_directory_conf_t **directories = NULL; -static size_t directories_num = 0; +static fc_directory_conf_t **directories; +static size_t directories_num; static void fc_free_dir(fc_directory_conf_t *dir) { sfree(dir->path); @@ -154,26 +154,6 @@ static int fc_config_add_dir_instance(fc_directory_conf_t *dir, return fc_config_set_instance(dir, ci->values[0].value.string); } /* int fc_config_add_dir_instance */ -static int fc_config_add_dir_name(fc_directory_conf_t *dir, - oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - WARNING("filecount plugin: The `Name' config option needs exactly one " - "string argument."); - return -1; - } - - char *temp = strdup(ci->values[0].value.string); - if (temp == NULL) { - ERROR("filecount plugin: strdup failed."); - return -1; - } - - sfree(dir->name); - dir->name = temp; - - return 0; -} /* int fc_config_add_dir_name */ - static int fc_config_add_dir_mtime(fc_directory_conf_t *dir, oconfig_item_t *ci) { if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_STRING) && @@ -369,7 +349,7 @@ static int fc_config_add_dir(oconfig_item_t *ci) { else if (strcasecmp("Instance", option->key) == 0) status = fc_config_add_dir_instance(dir, option); else if (strcasecmp("Name", option->key) == 0) - status = fc_config_add_dir_name(dir, option); + status = cf_util_get_string(option, &dir->name); else if (strcasecmp("MTime", option->key) == 0) status = fc_config_add_dir_mtime(dir, option); else if (strcasecmp("Size", option->key) == 0) diff --git a/src/gmond.c b/src/gmond.c index cb005fd9..2bca05ad 100644 --- a/src/gmond.c +++ b/src/gmond.c @@ -84,19 +84,19 @@ struct metric_map_s { typedef struct metric_map_s metric_map_t; #define MC_RECEIVE_GROUP_DEFAULT "239.2.11.71" -static char *mc_receive_group = NULL; +static char *mc_receive_group; #define MC_RECEIVE_PORT_DEFAULT "8649" -static char *mc_receive_port = NULL; +static char *mc_receive_port; -static struct pollfd *mc_receive_sockets = NULL; -static size_t mc_receive_sockets_num = 0; +static struct pollfd *mc_receive_sockets; +static size_t mc_receive_sockets_num; -static socket_entry_t *mc_send_sockets = NULL; -static size_t mc_send_sockets_num = 0; +static socket_entry_t *mc_send_sockets; +static size_t mc_send_sockets_num; static pthread_mutex_t mc_send_sockets_lock = PTHREAD_MUTEX_INITIALIZER; -static int mc_receive_thread_loop = 0; -static int mc_receive_thread_running = 0; +static int mc_receive_thread_loop; +static int mc_receive_thread_running; static pthread_t mc_receive_thread_id; static metric_map_t metric_map_default[] = @@ -122,8 +122,8 @@ static metric_map_t metric_map_default[] = {"pkts_out", "if_packets", "", "tx", -1, -1}}; static size_t metric_map_len_default = STATIC_ARRAY_SIZE(metric_map_default); -static metric_map_t *metric_map = NULL; -static size_t metric_map_len = 0; +static metric_map_t *metric_map; +static size_t metric_map_len; static c_avl_tree_t *staging_tree; static pthread_mutex_t staging_lock = PTHREAD_MUTEX_INITIALIZER; @@ -833,28 +833,6 @@ static int mc_receive_thread_stop(void) /* {{{ */ * * */ -static int gmond_config_set_string(oconfig_item_t *ci, char **str) /* {{{ */ -{ - char *tmp; - - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - WARNING("gmond plugin: The `%s' option needs " - "exactly one string argument.", - ci->key); - return -1; - } - - tmp = strdup(ci->values[0].value.string); - if (tmp == NULL) { - ERROR("gmond plugin: strdup failed."); - return -1; - } - - sfree(*str); - *str = tmp; - return 0; -} /* }}} int gmond_config_set_string */ - static int gmond_config_add_metric(oconfig_item_t *ci) /* {{{ */ { metric_map_t *map; @@ -889,11 +867,11 @@ static int gmond_config_add_metric(oconfig_item_t *ci) /* {{{ */ for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; if (strcasecmp("Type", child->key) == 0) - gmond_config_set_string(child, &map->type); + cf_util_get_string(child, &map->type); else if (strcasecmp("TypeInstance", child->key) == 0) - gmond_config_set_string(child, &map->type_instance); + cf_util_get_string(child, &map->type_instance); else if (strcasecmp("DataSource", child->key) == 0) - gmond_config_set_string(child, &map->ds_name); + cf_util_get_string(child, &map->ds_name); else { WARNING("gmond plugin: Unknown configuration option `%s' ignored.", child->key); diff --git a/src/grpc.cc b/src/grpc.cc index 977c5b2c..17168ec2 100644 --- a/src/grpc.cc +++ b/src/grpc.cc @@ -664,7 +664,7 @@ static int c_grpc_config_listen(oconfig_item_t *ci) { } pkcp.cert_chain = read_file(cert); } else if (!strcasecmp("VerifyPeer", child->key)) { - _Bool verify = 0; + bool verify = false; if (cf_util_get_boolean(child, &verify)) { return -1; } diff --git a/src/hddtemp.c b/src/hddtemp.c index 36c41289..80daf15b 100644 --- a/src/hddtemp.c +++ b/src/hddtemp.c @@ -53,7 +53,7 @@ static const char *config_keys[] = {"Host", "Port"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static char *hddtemp_host = NULL; +static char *hddtemp_host; static char hddtemp_port[16]; /* diff --git a/src/hugepages.c b/src/hugepages.c index 29a7f9e0..dd897356 100644 --- a/src/hugepages.c +++ b/src/hugepages.c @@ -35,12 +35,12 @@ static const char g_plugin_name[] = "hugepages"; -static _Bool g_flag_rpt_numa = 1; -static _Bool g_flag_rpt_mm = 1; +static bool g_flag_rpt_numa = true; +static bool g_flag_rpt_mm = true; -static _Bool g_values_pages = 1; -static _Bool g_values_bytes = 0; -static _Bool g_values_percent = 0; +static bool g_values_pages = true; +static bool g_values_bytes; +static bool g_values_percent; #define HP_HAVE_NR 0x01 #define HP_HAVE_SURPLUS 0x02 @@ -102,20 +102,20 @@ static void submit_hp(const struct entry_info *info) { if (g_values_pages) { sstrncpy(vl.type, "vmpage_number", sizeof(vl.type)); - plugin_dispatch_multivalue(&vl, /* store_percentage = */ 0, DS_TYPE_GAUGE, - "free", free, "used", used, NULL); + plugin_dispatch_multivalue(&vl, /* store_percentage = */ false, + DS_TYPE_GAUGE, "free", free, "used", used, NULL); } if (g_values_bytes) { gauge_t page_size = (gauge_t)(1024 * info->page_size_kb); sstrncpy(vl.type, "memory", sizeof(vl.type)); - plugin_dispatch_multivalue(&vl, /* store_percentage = */ 0, DS_TYPE_GAUGE, - "free", free * page_size, "used", + plugin_dispatch_multivalue(&vl, /* store_percentage = */ false, + DS_TYPE_GAUGE, "free", free * page_size, "used", used * page_size, NULL); } if (g_values_percent) { sstrncpy(vl.type, "percent", sizeof(vl.type)); - plugin_dispatch_multivalue(&vl, /* store_percentage = */ 1, DS_TYPE_GAUGE, - "free", free, "used", used, NULL); + plugin_dispatch_multivalue(&vl, /* store_percentage = */ true, + DS_TYPE_GAUGE, "free", free, "used", used, NULL); } } diff --git a/src/intel_pmu.c b/src/intel_pmu.c index d868c892..c9bbb50c 100644 --- a/src/intel_pmu.c +++ b/src/intel_pmu.c @@ -1,7 +1,7 @@ /** * collectd - src/intel_pmu.c * - * Copyright(c) 2017 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2018 Intel Corporation. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,11 +23,14 @@ * * Authors: * Serhiy Pshyk + * Kamil Wiatrowski **/ #include "collectd.h" #include "common.h" +#include "utils_config_cores.h" + #include #include @@ -64,12 +67,13 @@ struct event_info { typedef struct event_info event_info_t; struct intel_pmu_ctx_s { - _Bool hw_cache_events; - _Bool kernel_pmu_events; - _Bool sw_events; + bool hw_cache_events; + bool kernel_pmu_events; + bool sw_events; char event_list_fn[PATH_MAX]; char **hw_events; size_t hw_events_count; + core_groups_list_t cores; struct eventlist *event_list; }; typedef struct intel_pmu_ctx_s intel_pmu_ctx_t; @@ -197,8 +201,61 @@ static void pmu_dump_config(void) { } } +static void pmu_dump_cgroups(void) { + + DEBUG(PMU_PLUGIN ": Core groups:"); + + for (size_t i = 0; i < g_ctx.cores.num_cgroups; i++) { + core_group_t *cgroup = g_ctx.cores.cgroups + i; + const size_t cores_size = cgroup->num_cores * 4 + 1; + char *cores = calloc(cores_size, sizeof(*cores)); + if (cores == NULL) { + DEBUG(PMU_PLUGIN ": Failed to allocate string to list cores."); + return; + } + for (size_t j = 0; j < cgroup->num_cores; j++) + if (snprintf(cores + strlen(cores), cores_size - strlen(cores), " %d", + cgroup->cores[j]) < 0) { + DEBUG(PMU_PLUGIN ": Failed to write list of cores to string."); + sfree(cores); + return; + } + + DEBUG(PMU_PLUGIN ": group[%" PRIsz "]", i); + DEBUG(PMU_PLUGIN ": description: %s", cgroup->desc); + DEBUG(PMU_PLUGIN ": cores count: %" PRIsz, cgroup->num_cores); + DEBUG(PMU_PLUGIN ": cores :%s", cores); + sfree(cores); + } +} + #endif /* COLLECT_DEBUG */ +static int pmu_validate_cgroups(core_group_t *cgroups, size_t len, + int max_cores) { + /* i - group index, j - core index */ + for (size_t i = 0; i < len; i++) { + for (size_t j = 0; j < cgroups[i].num_cores; j++) { + int core = (int)cgroups[i].cores[j]; + + /* Core index cannot exceed number of cores in system, + note that max_cores include both online and offline CPUs. */ + if (core >= max_cores) { + ERROR(PMU_PLUGIN ": Core %d is not valid, max core index: %d.", core, + max_cores - 1); + return -1; + } + } + /* Check if cores are set in remaining groups */ + for (size_t k = i + 1; k < len; k++) + if (config_cores_cmp_cgroups(&cgroups[i], &cgroups[k]) != 0) { + ERROR(PMU_PLUGIN ": Same cores cannot be set in different groups."); + return -1; + } + } + return 0; +} + static int pmu_config_hw_events(oconfig_item_t *ci) { if (strcasecmp("HardwareEvents", ci->key) != 0) { @@ -253,6 +310,8 @@ static int pmu_config(oconfig_item_t *ci) { ret = pmu_config_hw_events(child); } else if (strcasecmp("ReportSoftwareEvents", child->key) == 0) { ret = cf_util_get_boolean(child, &g_ctx.sw_events); + } else if (strcasecmp("Cores", child->key) == 0) { + ret = config_cores_parse(child, &g_ctx.cores); } else { ERROR(PMU_PLUGIN ": Unknown configuration parameter \"%s\".", child->key); ret = -1; @@ -271,20 +330,17 @@ static int pmu_config(oconfig_item_t *ci) { return 0; } -static void pmu_submit_counter(int cpu, char *event, counter_t value, - meta_data_t *meta) { +static void pmu_submit_counter(const char *cgroup, const char *event, + counter_t value, meta_data_t *meta) { value_list_t vl = VALUE_LIST_INIT; vl.values = &(value_t){.counter = value}; vl.values_len = 1; sstrncpy(vl.plugin, PMU_PLUGIN, sizeof(vl.plugin)); - if (cpu == -1) { - snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "all"); - } else { + sstrncpy(vl.plugin_instance, cgroup, sizeof(vl.plugin_instance)); + if (meta) vl.meta = meta; - snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%d", cpu); - } sstrncpy(vl.type, "counter", sizeof(vl.type)); sstrncpy(vl.type_instance, event, sizeof(vl.type_instance)); @@ -317,49 +373,65 @@ static void pmu_dispatch_data(void) { struct event *e; for (e = g_ctx.event_list->eventlist; e; e = e->next) { - uint64_t all_value = 0; - int event_enabled = 0; - for (int i = 0; i < g_ctx.event_list->num_cpus; i++) { - - if (e->efd[i].fd < 0) - continue; - - event_enabled++; - - /* If there are more events than counters, the kernel uses time - * multiplexing. With multiplexing, at the end of the run, - * the counter is scaled basing on total time enabled vs time running. - * final_count = raw_count * time_enabled/time_running - */ - uint64_t value = event_scaled_value(e, i); - all_value += value; - - /* get meta data with information about scaling */ - meta_data_t *meta = pmu_meta_data_create(&e->efd[i]); - - /* dispatch per CPU value */ - pmu_submit_counter(i, e->event, value, meta); - - meta_data_destroy(meta); - } + for (size_t i = 0; i < g_ctx.cores.num_cgroups; i++) { + core_group_t *cgroup = g_ctx.cores.cgroups + i; + uint64_t cgroup_value = 0; + int event_enabled_cgroup = 0; + meta_data_t *meta = NULL; + + for (size_t j = 0; j < cgroup->num_cores; j++) { + int core = (int)cgroup->cores[j]; + if (e->efd[core].fd < 0) + continue; + + event_enabled_cgroup++; + + /* If there are more events than counters, the kernel uses time + * multiplexing. With multiplexing, at the end of the run, + * the counter is scaled basing on total time enabled vs time running. + * final_count = raw_count * time_enabled/time_running + */ + uint64_t value = event_scaled_value(e, core); + cgroup_value += value; + + /* get meta data with information about scaling */ + if (cgroup->num_cores == 1) + meta = pmu_meta_data_create(&e->efd[core]); + } - if (event_enabled > 0) { - DEBUG(PMU_PLUGIN ": %-20s %'10lu", e->event, all_value); - /* dispatch all CPU value */ - pmu_submit_counter(-1, e->event, all_value, NULL); + if (event_enabled_cgroup > 0) { + DEBUG(PMU_PLUGIN ": %s/%s = %lu", e->event, cgroup->desc, cgroup_value); + /* dispatch per core group value */ + pmu_submit_counter(cgroup->desc, e->event, cgroup_value, meta); + meta_data_destroy(meta); + } } } } static int pmu_read(__attribute__((unused)) user_data_t *ud) { int ret; + struct event *e; DEBUG(PMU_PLUGIN ": %s:%d", __FUNCTION__, __LINE__); - ret = read_all_events(g_ctx.event_list); - if (ret != 0) { - ERROR(PMU_PLUGIN ": Failed to read values of all events."); - return ret; + /* read all events only for configured cores */ + for (e = g_ctx.event_list->eventlist; e; e = e->next) { + for (size_t i = 0; i < g_ctx.cores.num_cgroups; i++) { + core_group_t *cgroup = g_ctx.cores.cgroups + i; + for (size_t j = 0; j < cgroup->num_cores; j++) { + int core = (int)cgroup->cores[j]; + if (e->efd[core].fd < 0) + continue; + + ret = read_event(e, core); + if (ret != 0) { + ERROR(PMU_PLUGIN ": Failed to read value of %s/%d event.", e->event, + core); + return ret; + } + } + } } pmu_dispatch_data(); @@ -404,7 +476,7 @@ static int pmu_add_hw_events(struct eventlist *el, char **e, size_t count) { if (!events) return -1; - char *s, *tmp; + char *s, *tmp = NULL; for (s = strtok_r(events, ",", &tmp); s; s = strtok_r(NULL, ",", &tmp)) { /* Allocate memory for event struct that contains array of efd structs @@ -460,6 +532,7 @@ static void pmu_free_events(struct eventlist *el) { while (e) { struct event *next = e->next; + sfree(e->event); sfree(e); e = next; } @@ -474,13 +547,18 @@ static int pmu_setup_events(struct eventlist *el, bool measure_all, for (e = el->eventlist; e; e = e->next) { - for (int i = 0; i < el->num_cpus; i++) { - if (setup_event(e, i, leader, measure_all, measure_pid) < 0) { - WARNING(PMU_PLUGIN ": perf event '%s' is not available (cpu=%d).", - e->event, i); - } else { - /* success if at least one event was set */ - ret = 0; + for (size_t i = 0; i < g_ctx.cores.num_cgroups; i++) { + core_group_t *cgroup = g_ctx.cores.cgroups + i; + for (size_t j = 0; j < cgroup->num_cores; j++) { + int core = (int)cgroup->cores[j]; + + if (setup_event(e, core, leader, measure_all, measure_pid) < 0) { + WARNING(PMU_PLUGIN ": perf event '%s' is not available (cpu=%d).", + e->event, core); + } else { + /* success if at least one event was set */ + ret = 0; + } } } @@ -504,6 +582,24 @@ static int pmu_init(void) { return -ENOMEM; } + if (g_ctx.cores.num_cgroups == 0) { + ret = config_cores_default(g_ctx.event_list->num_cpus, &g_ctx.cores); + if (ret != 0) { + ERROR(PMU_PLUGIN ": Failed to set default core groups."); + goto init_error; + } + } else { + ret = pmu_validate_cgroups(g_ctx.cores.cgroups, g_ctx.cores.num_cgroups, + g_ctx.event_list->num_cpus); + if (ret != 0) { + ERROR(PMU_PLUGIN ": Invalid core groups configuration."); + goto init_error; + } + } +#if COLLECT_DEBUG + pmu_dump_cgroups(); +#endif + if (g_ctx.hw_cache_events) { ret = pmu_add_events(g_ctx.event_list, PERF_TYPE_HW_CACHE, g_hw_cache_events, @@ -579,6 +675,8 @@ init_error: sfree(g_ctx.hw_events); g_ctx.hw_events_count = 0; + config_cores_cleanup(&g_ctx.cores); + return ret; } @@ -594,6 +692,8 @@ static int pmu_shutdown(void) { sfree(g_ctx.hw_events); g_ctx.hw_events_count = 0; + config_cores_cleanup(&g_ctx.cores); + return 0; } diff --git a/src/intel_rdt.c b/src/intel_rdt.c index 29c02fe5..62ce9b80 100644 --- a/src/intel_rdt.c +++ b/src/intel_rdt.c @@ -1,7 +1,7 @@ /** * collectd - src/intel_rdt.c * - * Copyright(c) 2016 Intel Corporation. All rights reserved. + * Copyright(c) 2016-2018 Intel Corporation. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,6 +27,7 @@ #include "collectd.h" #include "common.h" +#include "utils_config_cores.h" #include @@ -41,16 +42,9 @@ typedef enum { CONFIGURATION_ERROR, } rdt_config_status; -struct rdt_core_group_s { - char *desc; - size_t num_cores; - unsigned *cores; - enum pqos_mon_event events; -}; -typedef struct rdt_core_group_s rdt_core_group_t; - struct rdt_ctx_s { - rdt_core_group_t cgroups[RDT_MAX_CORES]; + core_groups_list_t cores; + enum pqos_mon_event events[RDT_MAX_CORES]; struct pqos_mon_data *pgroups[RDT_MAX_CORES]; size_t num_groups; const struct pqos_cpuinfo *pqos_cpu; @@ -59,247 +53,10 @@ struct rdt_ctx_s { }; typedef struct rdt_ctx_s rdt_ctx_t; -static rdt_ctx_t *g_rdt = NULL; +static rdt_ctx_t *g_rdt; static rdt_config_status g_state = UNKNOWN; -static int isdup(const uint64_t *nums, size_t size, uint64_t val) { - for (size_t i = 0; i < size; i++) - if (nums[i] == val) - return 1; - return 0; -} - -static int strtouint64(const char *s, uint64_t *n) { - char *endptr = NULL; - - assert(s != NULL); - assert(n != NULL); - - *n = strtoull(s, &endptr, 0); - - if (!(*s != '\0' && *endptr == '\0')) { - DEBUG(RDT_PLUGIN ": Error converting '%s' to unsigned number.", s); - return -EINVAL; - } - - return 0; -} - -/* - * NAME - * strlisttonums - * - * DESCRIPTION - * Converts string of characters representing list of numbers into array of - * numbers. Allowed formats are: - * 0,1,2,3 - * 0-10,20-18 - * 1,3,5-8,10,0x10-12 - * - * Numbers can be in decimal or hexadecimal format. - * - * PARAMETERS - * `s' String representing list of unsigned numbers. - * `nums' Array to put converted numeric values into. - * `max' Maximum number of elements that nums can accommodate. - * - * RETURN VALUE - * Number of elements placed into nums. - */ -static size_t strlisttonums(char *s, uint64_t *nums, size_t max) { - int ret; - size_t index = 0; - char *saveptr = NULL; - - if (s == NULL || nums == NULL || max == 0) - return index; - - for (;;) { - char *p = NULL; - char *token = NULL; - - token = strtok_r(s, ",", &saveptr); - if (token == NULL) - break; - - s = NULL; - - while (isspace(*token)) - token++; - if (*token == '\0') - continue; - - p = strchr(token, '-'); - if (p != NULL) { - uint64_t n, start, end; - *p = '\0'; - ret = strtouint64(token, &start); - if (ret < 0) - return 0; - ret = strtouint64(p + 1, &end); - if (ret < 0) - return 0; - if (start > end) { - return 0; - } - for (n = start; n <= end; n++) { - if (!(isdup(nums, index, n))) { - nums[index] = n; - index++; - } - if (index >= max) - return index; - } - } else { - uint64_t val; - - ret = strtouint64(token, &val); - if (ret < 0) - return 0; - - if (!(isdup(nums, index, val))) { - nums[index] = val; - index++; - } - if (index >= max) - return index; - } - } - - return index; -} - -/* - * NAME - * cgroup_cmp - * - * DESCRIPTION - * Function to compare cores in 2 core groups. - * - * PARAMETERS - * `cg_a' Pointer to core group a. - * `cg_b' Pointer to core group b. - * - * RETURN VALUE - * 1 if both groups contain the same cores - * 0 if none of their cores match - * -1 if some but not all cores match - */ -static int cgroup_cmp(const rdt_core_group_t *cg_a, - const rdt_core_group_t *cg_b) { - int found = 0; - - assert(cg_a != NULL); - assert(cg_b != NULL); - - const int sz_a = cg_a->num_cores; - const int sz_b = cg_b->num_cores; - const unsigned *tab_a = cg_a->cores; - const unsigned *tab_b = cg_b->cores; - - for (int i = 0; i < sz_a; i++) { - for (int j = 0; j < sz_b; j++) - if (tab_a[i] == tab_b[j]) - found++; - } - /* if no cores are the same */ - if (!found) - return 0; - /* if group contains same cores */ - if (sz_a == sz_b && sz_b == found) - return 1; - /* if not all cores are the same */ - return -1; -} - -static int cgroup_set(rdt_core_group_t *cg, char *desc, uint64_t *cores, - size_t num_cores) { - assert(cg != NULL); - assert(desc != NULL); - assert(cores != NULL); - assert(num_cores > 0); - - cg->cores = calloc(num_cores, sizeof(unsigned)); - if (cg->cores == NULL) { - ERROR(RDT_PLUGIN ": Error allocating core group table"); - return -ENOMEM; - } - cg->num_cores = num_cores; - cg->desc = strdup(desc); - if (cg->desc == NULL) { - ERROR(RDT_PLUGIN ": Error allocating core group description"); - sfree(cg->cores); - return -ENOMEM; - } - - for (size_t i = 0; i < num_cores; i++) - cg->cores[i] = (unsigned)cores[i]; - - return 0; -} - -/* - * NAME - * oconfig_to_cgroups - * - * DESCRIPTION - * Function to set the descriptions and cores for each core group. - * Takes a config option containing list of strings that are used to set - * core group values. - * - * PARAMETERS - * `item' Config option containing core groups. - * `groups' Table of core groups to set values in. - * `max_groups' Maximum number of core groups allowed. - * - * RETURN VALUE - * On success, the number of core groups set up. On error, appropriate - * negative error value. - */ -static int oconfig_to_cgroups(oconfig_item_t *item, rdt_core_group_t *groups, - size_t max_groups) { - int index = 0; - - assert(groups != NULL); - assert(max_groups > 0); - assert(item != NULL); - - for (int j = 0; j < item->values_num; j++) { - int ret; - size_t n; - uint64_t cores[RDT_MAX_CORES] = {0}; - char value[DATA_MAX_NAME_LEN]; - - if ((item->values[j].value.string == NULL) || - (strlen(item->values[j].value.string) == 0)) - continue; - - sstrncpy(value, item->values[j].value.string, sizeof(value)); - - n = strlisttonums(value, cores, STATIC_ARRAY_SIZE(cores)); - if (n == 0) { - ERROR(RDT_PLUGIN ": Error parsing core group (%s)", - item->values[j].value.string); - return -EINVAL; - } - - /* set core group info */ - ret = cgroup_set(&groups[index], item->values[j].value.string, cores, n); - if (ret < 0) - return ret; - - index++; - - if (index >= max_groups) { - WARNING(RDT_PLUGIN ": Too many core groups configured"); - return index; - } - } - - return index; -} - #if COLLECT_DEBUG static void rdt_dump_cgroups(void) { char cores[RDT_MAX_CORES * 4]; @@ -310,18 +67,19 @@ static void rdt_dump_cgroups(void) { DEBUG(RDT_PLUGIN ": Core Groups Dump"); DEBUG(RDT_PLUGIN ": groups count: %" PRIsz, g_rdt->num_groups); - for (int i = 0; i < g_rdt->num_groups; i++) { + for (size_t i = 0; i < g_rdt->num_groups; i++) { + core_group_t *cgroup = g_rdt->cores.cgroups + i; memset(cores, 0, sizeof(cores)); - for (int j = 0; j < g_rdt->cgroups[i].num_cores; j++) { + for (int j = 0; j < cgroup->num_cores; j++) { snprintf(cores + strlen(cores), sizeof(cores) - strlen(cores) - 1, " %d", - g_rdt->cgroups[i].cores[j]); + cgroup->cores[j]); } - DEBUG(RDT_PLUGIN ": group[%d]:", i); - DEBUG(RDT_PLUGIN ": description: %s", g_rdt->cgroups[i].desc); + DEBUG(RDT_PLUGIN ": group[%zu]:", i); + DEBUG(RDT_PLUGIN ": description: %s", cgroup->desc); DEBUG(RDT_PLUGIN ": cores: %s", cores); - DEBUG(RDT_PLUGIN ": events: 0x%X", g_rdt->cgroups[i].events); + DEBUG(RDT_PLUGIN ": events: 0x%X", g_rdt->events[i]); } return; @@ -350,45 +108,59 @@ static void rdt_dump_data(void) { double mbr = bytes_to_mb(pv->mbm_remote_delta); double mbl = bytes_to_mb(pv->mbm_local_delta); - DEBUG(" [%s] %8u %10.1f %10.1f %10.1f", g_rdt->cgroups[i].desc, + DEBUG(" [%s] %8u %10.1f %10.1f %10.1f", g_rdt->cores.cgroups[i].desc, g_rdt->pgroups[i]->poll_ctx[0].rmid, llc, mbl, mbr); } } #endif /* COLLECT_DEBUG */ static void rdt_free_cgroups(void) { + config_cores_cleanup(&g_rdt->cores); for (int i = 0; i < RDT_MAX_CORES; i++) { - sfree(g_rdt->cgroups[i].desc); - - sfree(g_rdt->cgroups[i].cores); - g_rdt->cgroups[i].num_cores = 0; - sfree(g_rdt->pgroups[i]); } } static int rdt_default_cgroups(void) { - int ret; + unsigned num_cores = g_rdt->pqos_cpu->num_cores; + + g_rdt->cores.cgroups = calloc(num_cores, sizeof(*(g_rdt->cores.cgroups))); + if (g_rdt->cores.cgroups == NULL) { + ERROR(RDT_PLUGIN ": Error allocating core groups array"); + return -ENOMEM; + } + g_rdt->cores.num_cgroups = num_cores; /* configure each core in separate group */ - for (unsigned i = 0; i < g_rdt->pqos_cpu->num_cores; i++) { + for (unsigned i = 0; i < num_cores; i++) { + core_group_t *cgroup = g_rdt->cores.cgroups + i; char desc[DATA_MAX_NAME_LEN]; - uint64_t core = i; - - snprintf(desc, sizeof(desc), "%d", g_rdt->pqos_cpu->cores[i].lcore); /* set core group info */ - ret = cgroup_set(&g_rdt->cgroups[i], desc, &core, 1); - if (ret < 0) - return ret; + cgroup->cores = calloc(1, sizeof(*(cgroup->cores))); + if (cgroup->cores == NULL) { + ERROR(RDT_PLUGIN ": Error allocating cores array"); + rdt_free_cgroups(); + return -ENOMEM; + } + cgroup->num_cores = 1; + cgroup->cores[0] = i; + + snprintf(desc, sizeof(desc), "%d", g_rdt->pqos_cpu->cores[i].lcore); + cgroup->desc = strdup(desc); + if (cgroup->desc == NULL) { + ERROR(RDT_PLUGIN ": Error allocating core group description"); + rdt_free_cgroups(); + return -ENOMEM; + } } - return g_rdt->pqos_cpu->num_cores; + return num_cores; } -static int rdt_is_core_id_valid(int core_id) { +static int rdt_is_core_id_valid(unsigned int core_id) { - for (int i = 0; i < g_rdt->pqos_cpu->num_cores; i++) + for (unsigned int i = 0; i < g_rdt->pqos_cpu->num_cores; i++) if (core_id == g_rdt->pqos_cpu->cores[i].lcore) return 1; @@ -396,38 +168,23 @@ static int rdt_is_core_id_valid(int core_id) { } static int rdt_config_cgroups(oconfig_item_t *item) { - int n = 0; + size_t n = 0; enum pqos_mon_event events = 0; - if (item == NULL) { - DEBUG(RDT_PLUGIN ": cgroups_config: Invalid argument."); - return -EINVAL; - } - - DEBUG(RDT_PLUGIN ": Core groups [%d]:", item->values_num); - for (int j = 0; j < item->values_num; j++) { - if (item->values[j].type != OCONFIG_TYPE_STRING) { - ERROR(RDT_PLUGIN ": given core group value is not a string [idx=%d]", j); - return -EINVAL; - } - DEBUG(RDT_PLUGIN ": [%d]: %s", j, item->values[j].value.string); - } - - n = oconfig_to_cgroups(item, g_rdt->cgroups, g_rdt->pqos_cpu->num_cores); - if (n < 0) { + if (config_cores_parse(item, &g_rdt->cores) < 0) { rdt_free_cgroups(); ERROR(RDT_PLUGIN ": Error parsing core groups configuration."); return -EINVAL; } + n = g_rdt->cores.num_cgroups; /* validate configured core id values */ - for (int group_idx = 0; group_idx < n; group_idx++) { - for (int core_idx = 0; core_idx < g_rdt->cgroups[group_idx].num_cores; - core_idx++) { - if (!rdt_is_core_id_valid(g_rdt->cgroups[group_idx].cores[core_idx])) { - ERROR(RDT_PLUGIN ": Core group '%s' contains invalid core id '%d'", - g_rdt->cgroups[group_idx].desc, - (int)g_rdt->cgroups[group_idx].cores[core_idx]); + for (size_t group_idx = 0; group_idx < n; group_idx++) { + core_group_t *cgroup = g_rdt->cores.cgroups + group_idx; + for (size_t core_idx = 0; core_idx < cgroup->num_cores; core_idx++) { + if (!rdt_is_core_id_valid(cgroup->cores[core_idx])) { + ERROR(RDT_PLUGIN ": Core group '%s' contains invalid core id '%u'", + cgroup->desc, cgroup->cores[core_idx]); rdt_free_cgroups(); return -EINVAL; } @@ -436,18 +193,19 @@ static int rdt_config_cgroups(oconfig_item_t *item) { if (n == 0) { /* create default core groups if "Cores" config option is empty */ - n = rdt_default_cgroups(); - if (n < 0) { + int ret = rdt_default_cgroups(); + if (ret < 0) { rdt_free_cgroups(); ERROR(RDT_PLUGIN ": Error creating default core groups configuration."); - return n; + return ret; } + n = (size_t)ret; INFO(RDT_PLUGIN ": No core groups configured. Default core groups created."); } /* Get all available events on this platform */ - for (int i = 0; i < g_rdt->cap_mon->u.mon->num_events; i++) + for (unsigned int i = 0; i < g_rdt->cap_mon->u.mon->num_events; i++) events |= g_rdt->cap_mon->u.mon->events[i].type; events &= ~(PQOS_PERF_EVENT_LLC_MISS); @@ -457,10 +215,11 @@ static int rdt_config_cgroups(oconfig_item_t *item) { DEBUG(RDT_PLUGIN ": Available events to monitor: %#x", events); g_rdt->num_groups = n; - for (int i = 0; i < n; i++) { - for (int j = 0; j < i; j++) { + for (size_t i = 0; i < n; i++) { + for (size_t j = 0; j < i; j++) { int found = 0; - found = cgroup_cmp(&g_rdt->cgroups[j], &g_rdt->cgroups[i]); + found = config_cores_cmp_cgroups(&g_rdt->cores.cgroups[j], + &g_rdt->cores.cgroups[i]); if (found != 0) { rdt_free_cgroups(); ERROR(RDT_PLUGIN ": Cannot monitor same cores in different groups."); @@ -468,7 +227,7 @@ static int rdt_config_cgroups(oconfig_item_t *item) { } } - g_rdt->cgroups[i].events = events; + g_rdt->events[i] = events; g_rdt->pgroups[i] = calloc(1, sizeof(*g_rdt->pgroups[i])); if (g_rdt->pgroups[i] == NULL) { rdt_free_cgroups(); @@ -577,8 +336,8 @@ static int rdt_config(oconfig_item_t *ci) { return 0; } -static void rdt_submit_derive(char *cgroup, char *type, char *type_instance, - derive_t value) { +static void rdt_submit_derive(const char *cgroup, const char *type, + const char *type_instance, derive_t value) { value_list_t vl = VALUE_LIST_INIT; vl.values = &(value_t){.derive = value}; @@ -593,8 +352,8 @@ static void rdt_submit_derive(char *cgroup, char *type, char *type_instance, plugin_dispatch_values(&vl); } -static void rdt_submit_gauge(char *cgroup, char *type, char *type_instance, - gauge_t value) { +static void rdt_submit_gauge(const char *cgroup, const char *type, + const char *type_instance, gauge_t value) { value_list_t vl = VALUE_LIST_INIT; vl.values = &(value_t){.gauge = value}; @@ -627,7 +386,9 @@ static int rdt_read(__attribute__((unused)) user_data_t *ud) { rdt_dump_data(); #endif /* COLLECT_DEBUG */ - for (int i = 0; i < g_rdt->num_groups; i++) { + for (size_t i = 0; i < g_rdt->num_groups; i++) { + core_group_t *cgroup = g_rdt->cores.cgroups + i; + enum pqos_mon_event mbm_events = (PQOS_MON_EVENT_LMEM_BW | PQOS_MON_EVENT_TMEM_BW | PQOS_MON_EVENT_RMEM_BW); @@ -636,16 +397,16 @@ static int rdt_read(__attribute__((unused)) user_data_t *ud) { /* Submit only monitored events data */ - if (g_rdt->cgroups[i].events & PQOS_MON_EVENT_L3_OCCUP) - rdt_submit_gauge(g_rdt->cgroups[i].desc, "bytes", "llc", pv->llc); + if (g_rdt->events[i] & PQOS_MON_EVENT_L3_OCCUP) + rdt_submit_gauge(cgroup->desc, "bytes", "llc", pv->llc); - if (g_rdt->cgroups[i].events & PQOS_PERF_EVENT_IPC) - rdt_submit_gauge(g_rdt->cgroups[i].desc, "ipc", NULL, pv->ipc); + if (g_rdt->events[i] & PQOS_PERF_EVENT_IPC) + rdt_submit_gauge(cgroup->desc, "ipc", NULL, pv->ipc); - if (g_rdt->cgroups[i].events & mbm_events) { - rdt_submit_derive(g_rdt->cgroups[i].desc, "memory_bandwidth", "local", + if (g_rdt->events[i] & mbm_events) { + rdt_submit_derive(cgroup->desc, "memory_bandwidth", "local", pv->mbm_local_delta); - rdt_submit_derive(g_rdt->cgroups[i].desc, "memory_bandwidth", "remote", + rdt_submit_derive(cgroup->desc, "memory_bandwidth", "remote", pv->mbm_remote_delta); } } @@ -664,11 +425,11 @@ static int rdt_init(void) { return ret; /* Start monitoring */ - for (int i = 0; i < g_rdt->num_groups; i++) { - rdt_core_group_t *cg = &g_rdt->cgroups[i]; + for (size_t i = 0; i < g_rdt->num_groups; i++) { + core_group_t *cg = g_rdt->cores.cgroups + i; - ret = pqos_mon_start(cg->num_cores, cg->cores, cg->events, (void *)cg->desc, - g_rdt->pgroups[i]); + ret = pqos_mon_start(cg->num_cores, cg->cores, g_rdt->events[i], + (void *)cg->desc, g_rdt->pgroups[i]); if (ret != PQOS_RETVAL_OK) ERROR(RDT_PLUGIN ": Error starting monitoring group %s (pqos status=%d)", @@ -687,7 +448,7 @@ static int rdt_shutdown(void) { return 0; /* Stop monitoring */ - for (int i = 0; i < g_rdt->num_groups; i++) { + for (size_t i = 0; i < g_rdt->num_groups; i++) { pqos_mon_stop(g_rdt->pgroups[i]); } diff --git a/src/interface.c b/src/interface.c index c45ef660..86110b0c 100644 --- a/src/interface.c +++ b/src/interface.c @@ -86,9 +86,9 @@ static const char *config_keys[] = { }; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static ignorelist_t *ignorelist = NULL; +static ignorelist_t *ignorelist; -static _Bool report_inactive = 1; +static bool report_inactive = true; #ifdef HAVE_LIBKSTAT #if HAVE_KSTAT_H @@ -97,8 +97,8 @@ static _Bool report_inactive = 1; #define MAX_NUMIF 256 extern kstat_ctl_t *kc; static kstat_t *ksp[MAX_NUMIF]; -static int numif = 0; -static _Bool unique_name = 0; +static int numif; +static bool unique_name; #endif /* HAVE_LIBKSTAT */ static int interface_config(const char *key, const char *value) { @@ -117,7 +117,7 @@ static int interface_config(const char *key, const char *value) { else if (strcasecmp(key, "UniqueName") == 0) { #ifdef HAVE_LIBKSTAT if (IS_TRUE(value)) - unique_name = 1; + unique_name = true; #else WARNING("interface plugin: the \"UniqueName\" option is only valid on " "Solaris."); diff --git a/src/ipmi.c b/src/ipmi.c index 6a72b2b7..fb99bad1 100644 --- a/src/ipmi.c +++ b/src/ipmi.c @@ -49,12 +49,13 @@ typedef struct c_ipmi_sensor_list_s c_ipmi_sensor_list_t; struct c_ipmi_instance_s { char *name; ignorelist_t *ignorelist; - _Bool notify_add; - _Bool notify_remove; - _Bool notify_notpresent; - _Bool notify_conn; - _Bool sel_enabled; - _Bool sel_clear_event; + ignorelist_t *sel_ignorelist; + bool notify_add; + bool notify_remove; + bool notify_notpresent; + bool notify_conn; + bool sel_enabled; + bool sel_clear_event; char *host; char *connaddr; @@ -62,12 +63,12 @@ struct c_ipmi_instance_s { char *password; unsigned int authtype; - _Bool connected; + bool connected; ipmi_con_t *connection; pthread_mutex_t sensor_list_lock; c_ipmi_sensor_list_t *sensor_list; - _Bool active; + bool active; pthread_t thread_id; int init_in_progress; @@ -95,8 +96,8 @@ typedef struct c_ipmi_db_type_map_s c_ipmi_db_type_map_t; /* * Module global variables */ -static os_handler_t *os_handler = NULL; -static c_ipmi_instance_t *instances = NULL; +static os_handler_t *os_handler; +static c_ipmi_instance_t *instances; /* * Misc private functions @@ -357,7 +358,7 @@ static const char *sensor_unit_to_type(ipmi_sensor_t *sensor) { /* find the db type by using sensor base unit type */ enum ipmi_unit_type_e ipmi_type = ipmi_sensor_get_base_unit(sensor); - for (int i = 0; i < STATIC_ARRAY_SIZE(ipmi_db_type_map); i++) + for (size_t i = 0; i < STATIC_ARRAY_SIZE(ipmi_db_type_map); i++) if (ipmi_db_type_map[i].type == ipmi_type) return ipmi_db_type_map[i].type_name; @@ -770,6 +771,40 @@ static int sensor_discrete_event_handler(ipmi_sensor_t *sensor, return IPMI_EVENT_NOT_HANDLED; } /* int sensor_discrete_event_handler */ +static int sel_list_add(c_ipmi_instance_t *st, ipmi_sensor_t *sensor) { + char sensor_name[DATA_MAX_NAME_LEN] = {0}; + int status = 0; + + /* Check if sensor on sel_ignorelist */ + sensor_get_name(sensor, sensor_name, sizeof(sensor_name)); + if (ignorelist_match(st->sel_ignorelist, sensor_name) != 0) + return 0; + + /* register threshold event if threshold sensor support events */ + if (ipmi_sensor_get_event_reading_type(sensor) == + IPMI_EVENT_READING_TYPE_THRESHOLD) + status = ipmi_sensor_add_threshold_event_handler( + sensor, sensor_threshold_event_handler, st); + /* register discrete handler if discrete/specific sensor support events */ + else if (ipmi_sensor_get_event_support(sensor) != IPMI_EVENT_SUPPORT_NONE) + status = ipmi_sensor_add_discrete_event_handler( + sensor, sensor_discrete_event_handler, st); + + if (status) + ERROR("Unable to add sensor %s event handler, status: %d", sensor_name, + status); + return status; +} + +static void sel_list_remove(c_ipmi_instance_t *st, ipmi_sensor_t *sensor) { + if (ipmi_sensor_get_event_reading_type(sensor) == + IPMI_EVENT_READING_TYPE_THRESHOLD) + ipmi_sensor_remove_threshold_event_handler( + sensor, sensor_threshold_event_handler, st); + else + ipmi_sensor_remove_discrete_event_handler( + sensor, sensor_discrete_event_handler, st); +} /* * Entity handlers */ @@ -782,37 +817,12 @@ entity_sensor_update_handler(enum ipmi_update_e op, if ((op == IPMI_ADDED) || (op == IPMI_CHANGED)) { /* Will check for duplicate entries.. */ sensor_list_add(st, sensor); - - if (st->sel_enabled) { - int status = 0; - /* register threshold event handler */ - if (ipmi_sensor_get_event_reading_type(sensor) == - IPMI_EVENT_READING_TYPE_THRESHOLD) - status = ipmi_sensor_add_threshold_event_handler( - sensor, sensor_threshold_event_handler, st); - /* register discrete handler if discrete/specific sensor support events */ - else if (ipmi_sensor_get_event_support(sensor) != IPMI_EVENT_SUPPORT_NONE) - status = ipmi_sensor_add_discrete_event_handler( - sensor, sensor_discrete_event_handler, st); - - if (status) { - char buf[DATA_MAX_NAME_LEN] = {0}; - sensor_get_name(sensor, buf, sizeof(buf)); - ERROR("Unable to add sensor %s event handler, status: %d", buf, status); - } - } + if (st->sel_enabled) + sel_list_add(st, sensor); } else if (op == IPMI_DELETED) { sensor_list_remove(st, sensor); - - if (st->sel_enabled) { - if (ipmi_sensor_get_event_reading_type(sensor) == - IPMI_EVENT_READING_TYPE_THRESHOLD) - ipmi_sensor_remove_threshold_event_handler( - sensor, sensor_threshold_event_handler, st); - else - ipmi_sensor_remove_discrete_event_handler( - sensor, sensor_discrete_event_handler, st); - } + if (st->sel_enabled) + sel_list_remove(st, sensor); } } /* void entity_sensor_update_handler */ @@ -884,7 +894,7 @@ static void domain_connection_change_handler(ipmi_domain_t *domain, int err, plugin_dispatch_notification(&n); } - st->connected = 0; + st->connected = false; return; } @@ -896,7 +906,7 @@ static void domain_connection_change_handler(ipmi_domain_t *domain, int err, plugin_dispatch_notification(&n); } - st->connected = 1; + st->connected = true; int status = ipmi_domain_add_entity_update_handler( domain, domain_entity_update_handler, /* user data = */ st); @@ -965,11 +975,11 @@ static void *c_ipmi_thread_main(void *user_data) { int status = c_ipmi_thread_init(st); if (status != 0) { ERROR("ipmi plugin: c_ipmi_thread_init failed."); - st->active = 0; + st->active = false; return (void *)-1; } - while (st->active != 0) { + while (st->active) { struct timeval tv = {1, 0}; os_handler->perform_one_op(os_handler, &tv); } @@ -1000,6 +1010,15 @@ static c_ipmi_instance_t *c_ipmi_init_instance() { return NULL; } + st->sel_ignorelist = ignorelist_create(/* invert = */ 1); + if (st->sel_ignorelist == NULL) { + ignorelist_free(st->ignorelist); + sfree(st->name); + sfree(st); + ERROR("ipmi plugin: SEL ignorelist_create() failed."); + return NULL; + } + st->sensor_list = NULL; pthread_mutex_init(&st->sensor_list_lock, /* attr = */ NULL); @@ -1026,6 +1045,7 @@ static void c_ipmi_free_instance(c_ipmi_instance_t *st) { sfree(st->username); sfree(st->password); + ignorelist_free(st->sel_ignorelist); ignorelist_free(st->ignorelist); pthread_mutex_destroy(&st->sensor_list_lock); sfree(st); @@ -1062,10 +1082,15 @@ static int c_ipmi_config_add_instance(oconfig_item_t *ci) { for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; - if (strcasecmp("Sensor", child->key) == 0) - ignorelist_add(st->ignorelist, child->values[0].value.string); - else if (strcasecmp("IgnoreSelected", child->key) == 0) { - _Bool t; + if (strcasecmp("Sensor", child->key) == 0) { + char *value = NULL; + status = cf_util_get_string(child, &value); + if (status != 0) + break; + ignorelist_add(st->ignorelist, value); + sfree(value); + } else if (strcasecmp("IgnoreSelected", child->key) == 0) { + bool t; status = cf_util_get_boolean(child, &t); if (status != 0) break; @@ -1078,6 +1103,19 @@ static int c_ipmi_config_add_instance(oconfig_item_t *ci) { status = cf_util_get_boolean(child, &st->notify_remove); } else if (strcasecmp("NotifySensorNotPresent", child->key) == 0) { status = cf_util_get_boolean(child, &st->notify_notpresent); + } else if (strcasecmp("SELSensor", child->key) == 0) { + char *value = NULL; + status = cf_util_get_string(child, &value); + if (status != 0) + break; + ignorelist_add(st->sel_ignorelist, value); + sfree(value); + } else if (strcasecmp("SELIgnoreSelected", child->key) == 0) { + bool t; + status = cf_util_get_boolean(child, &t); + if (status != 0) + break; + ignorelist_set_invert(st->sel_ignorelist, /* invert = */ !t); } else if (strcasecmp("SELEnabled", child->key) == 0) { status = cf_util_get_boolean(child, &st->sel_enabled); } else if (strcasecmp("SELClearEvent", child->key) == 0) { @@ -1124,7 +1162,7 @@ static int c_ipmi_config_add_instance(oconfig_item_t *ci) { } /* int c_ipmi_config_add_instance */ static int c_ipmi_config(oconfig_item_t *ci) { - _Bool have_instance_block = 0; + bool have_instance_block = 0; for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; @@ -1158,12 +1196,12 @@ static int c_ipmi_config(oconfig_item_t *ci) { static int c_ipmi_read(user_data_t *user_data) { c_ipmi_instance_t *st = user_data->data; - if (st->active == 0) { + if (st->active == false) { INFO("ipmi plugin: c_ipmi_read: I'm not active, returning false."); return -1; } - if (st->connected == 0) + if (st->connected == false) return 0; sensor_list_read_all(st); @@ -1234,14 +1272,14 @@ static int c_ipmi_init(void) { } st->init_in_progress = cycles; - st->active = 1; + st->active = true; status = plugin_thread_create(&st->thread_id, /* attr = */ NULL, c_ipmi_thread_main, /* user data = */ (void *)st, "ipmi"); if (status != 0) { - st->active = 0; + st->active = false; st->thread_id = (pthread_t){0}; plugin_unregister_read(callback_name); @@ -1263,7 +1301,7 @@ static int c_ipmi_shutdown(void) { c_ipmi_instance_t *next = st->next; st->next = NULL; - st->active = 0; + st->active = false; if (!pthread_equal(st->thread_id, (pthread_t){0})) { pthread_join(st->thread_id, NULL); diff --git a/src/iptables.c b/src/iptables.c index bc75d7bc..225ed2c1 100644 --- a/src/iptables.c +++ b/src/iptables.c @@ -86,8 +86,8 @@ typedef struct { char name[64]; } ip_chain_t; -static ip_chain_t **chain_list = NULL; -static int chain_num = 0; +static ip_chain_t **chain_list; +static int chain_num; static int iptables_config(const char *key, const char *value) { /* int ip_value; */ @@ -103,9 +103,7 @@ static int iptables_config(const char *key, const char *value) { ip_chain_t temp = {0}; ip_chain_t *final, **list; char *table; - int table_len; char *chain; - int chain_len; char *value_copy; char *fields[4]; @@ -136,16 +134,16 @@ static int iptables_config(const char *key, const char *value) { table = fields[0]; chain = fields[1]; - table_len = strlen(table) + 1; - if ((unsigned int)table_len > sizeof(temp.table)) { + size_t table_len = strlen(table) + 1; + if (table_len > sizeof(temp.table)) { ERROR("Table `%s' too long.", table); free(value_copy); return 1; } sstrncpy(temp.table, table, table_len); - chain_len = strlen(chain) + 1; - if ((unsigned int)chain_len > sizeof(temp.chain)) { + size_t chain_len = strlen(chain) + 1; + if (chain_len > sizeof(temp.chain)) { ERROR("Chain `%s' too long.", chain); free(value_copy); return 1; diff --git a/src/irq.c b/src/irq.c index f8cf37ca..aa6ac04b 100644 --- a/src/irq.c +++ b/src/irq.c @@ -37,7 +37,7 @@ static const char *config_keys[] = {"Irq", "IgnoreSelected"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static ignorelist_t *ignorelist = NULL; +static ignorelist_t *ignorelist; /* * Private functions diff --git a/src/java.c b/src/java.c index a35ca46c..3f4b3d1a 100644 --- a/src/java.c +++ b/src/java.c @@ -77,23 +77,23 @@ typedef struct cjni_callback_info_s cjni_callback_info_t; /* * Global variables */ -static JavaVM *jvm = NULL; +static JavaVM *jvm; static pthread_key_t jvm_env_key; /* Configuration options for the JVM. */ -static char **jvm_argv = NULL; -static size_t jvm_argc = 0; +static char **jvm_argv; +static size_t jvm_argc; /* List of class names to load */ -static java_plugin_class_t *java_classes_list = NULL; +static java_plugin_class_t *java_classes_list; static size_t java_classes_list_len; /* List of config, init, and shutdown callbacks. */ -static cjni_callback_info_t *java_callbacks = NULL; -static size_t java_callbacks_num = 0; +static cjni_callback_info_t *java_callbacks; +static size_t java_callbacks_num; static pthread_mutex_t java_callbacks_lock = PTHREAD_MUTEX_INITIALIZER; -static oconfig_item_t *config_block = NULL; +static oconfig_item_t *config_block; /* * Prototypes @@ -1009,9 +1009,8 @@ static int jtoc_values_array(JNIEnv *jvm_env, /* {{{ */ jobjectArray o_number_array; value_t *values; - int values_num; - values_num = ds->ds_num; + size_t values_num = ds->ds_num; values = NULL; o_number_array = NULL; @@ -1064,7 +1063,7 @@ static int jtoc_values_array(JNIEnv *jvm_env, /* {{{ */ BAIL_OUT(-1); } - for (int i = 0; i < values_num; i++) { + for (size_t i = 0; i < values_num; i++) { jobject o_number; int status; @@ -1072,7 +1071,7 @@ static int jtoc_values_array(JNIEnv *jvm_env, /* {{{ */ (*jvm_env)->GetObjectArrayElement(jvm_env, o_number_array, (jsize)i); if (o_number == NULL) { ERROR("java plugin: jtoc_values_array: " - "GetObjectArrayElement (%i) failed.", + "GetObjectArrayElement (%zu) failed.", i); BAIL_OUT(-1); } @@ -1080,7 +1079,7 @@ static int jtoc_values_array(JNIEnv *jvm_env, /* {{{ */ status = jtoc_value(jvm_env, values + i, ds->ds[i].type, o_number); if (status != 0) { ERROR("java plugin: jtoc_values_array: " - "jtoc_value (%i) failed.", + "jtoc_value (%zu) failed.", i); BAIL_OUT(-1); } diff --git a/src/libcollectdclient/collectd/stdendian.h b/src/libcollectdclient/collectd/stdendian.h new file mode 100644 index 00000000..9ab0fb59 --- /dev/null +++ b/src/libcollectdclient/collectd/stdendian.h @@ -0,0 +1,262 @@ +/* + * stdendian.h + * + * This header defines the following endian macros as defined here: + * http://austingroupbugs.net/view.php?id=162 + * + * BYTE_ORDER this macro shall have a value equal to one + * of the *_ENDIAN macros in this header. + * LITTLE_ENDIAN if BYTE_ORDER == LITTLE_ENDIAN, the host + * byte order is from least significant to + * most significant. + * BIG_ENDIAN if BYTE_ORDER == BIG_ENDIAN, the host byte + * order is from most significant to least + * significant. + * + * The following are defined as macros: + * + * uint16_t bswap16(uint16_t x); + * uint32_t bswap32(uint32_t x); + * uint64_t bswap64(uint64_t x); + + * uint16_t htobe16(uint16_t x); + * uint16_t htole16(uint16_t x); + * uint16_t be16toh(uint16_t x); + * uint16_t le16toh(uint16_t x); + * + * uint32_t htobe32(uint32_t x); + * uint32_t htole32(uint32_t x); + * uint32_t be32toh(uint32_t x); + * uint32_t le32toh(uint32_t x); + * + * uint64_t htobe64(uint64_t x); + * uint64_t htole64(uint64_t x); + * uint64_t be64toh(uint64_t x); + * uint64_t le64toh(uint64_t x); + * + * The header defines the following macro for OpenCL compatibility + * + https://www.khronos.org/registry/cl/sdk/2.0/docs/man/xhtml/preprocessorDirectives.html + * + * __ENDIAN_LITTLE__ if BYTE_ORDER == LITTLE_ENDIAN then this + * macro is present for OpenCL compatibility + * + * The implementation provides a uniform interface to endian macros using only + * system headers on recent Linux, Darwin, FreeBSD, Solaris and Windows + systems. + * + * This approach is intended to avoid the need for preflight configure + scripts. + * An alternative approach would be to test compiler CPU architecture marcros. + * + * This header has had *limited* testing on recent C11/C++11 compilers and is + * based on the austin bug tracker interface, manpages, and headers present in + * Linux, FreeBSD, Windows, Solaris and Darwin. + * + * The header uses __builtin_bswapXX intrinsic with GCC/Clang (__GNUC__) on + * platforms that do not provide bswap16, bswap32, bswap64 (Darwin) + * + * Public Domain. + */ + +#if HAVE_STDINT_H +#include +#endif + +/* Linux / GLIBC */ +#if defined(__linux__) || defined(__GLIBC__) +#include +#include +#define __ENDIAN_DEFINED 1 +#define __BSWAP_DEFINED 1 +#define __HOSTSWAP_DEFINED 1 +#define _BYTE_ORDER __BYTE_ORDER +#define _LITTLE_ENDIAN __LITTLE_ENDIAN +#define _BIG_ENDIAN __BIG_ENDIAN +#define bswap16(x) bswap_16(x) +#define bswap32(x) bswap_32(x) +#define bswap64(x) bswap_64(x) +#endif /* __linux__ || __GLIBC__ */ + +/* BSD */ +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \ + defined(__OpenBSD__) +#include +#define __ENDIAN_DEFINED 1 +#define __BSWAP_DEFINED 1 +#define __HOSTSWAP_DEFINED 1 +#endif /* BSD */ + +/* Solaris */ +#if defined(sun) +#include +#include +#define bswap16(x) BSWAP_16(x) +#define bswap32(x) BSWAP_32(x) +#define bswap64(x) BSWAP_64(x) +/* sun headers don't set a value for _LITTLE_ENDIAN or _BIG_ENDIAN */ +#if defined(_LITTLE_ENDIAN) +#undef _LITTLE_ENDIAN +#define _LITTLE_ENDIAN 1234 +#define _BIG_ENDIAN 4321 +#define _BYTE_ORDER _LITTLE_ENDIAN +#elif defined(_BIG_ENDIAN) +#undef _BIG_ENDIAN +#define _LITTLE_ENDIAN 1234 +#define _BIG_ENDIAN 4321 +#define _BYTE_ORDER _BIG_ENDIAN +#endif +#define __ENDIAN_DEFINED 1 +#endif /* sun */ + +/* AIX */ +#if defined(_AIX) +#include +#if BYTE_ORDER == LITTLE_ENDIAN +#define _LITTLE_ENDIAN 1234 +#define _BIG_ENDIAN 4321 +#define _BYTE_ORDER _LITTLE_ENDIAN +#elif BYTE_ORDER == BIG_ENDIAN +#define _LITTLE_ENDIAN 1234 +#define _BIG_ENDIAN 4321 +#define _BYTE_ORDER _BIG_ENDIAN +#else +#error Could not determine CPU byte order for AIX +#endif +#define __ENDIAN_DEFINED 1 +#endif /* AIX */ + +/* Windows */ +#if defined(_WIN32) || defined(_MSC_VER) +/* assumes all Microsoft targets are little endian */ +#define _LITTLE_ENDIAN 1234 +#define _BIG_ENDIAN 4321 +#define _BYTE_ORDER _LITTLE_ENDIAN +#define __ENDIAN_DEFINED 1 +#endif /* _MSC_VER */ + +/* OS X */ +#if defined(__APPLE__) +#include +#define _BYTE_ORDER BYTE_ORDER +#define _LITTLE_ENDIAN LITTLE_ENDIAN +#define _BIG_ENDIAN BIG_ENDIAN +#define __ENDIAN_DEFINED 1 +#endif /* __APPLE__ */ + +/* OpenCL */ +#if defined(__OPENCL_VERSION__) +#define _LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#if defined(__ENDIAN_LITTLE__) +#define _BYTE_ORDER _LITTLE_ENDIAN +#else +#define _BYTE_ORDER _BIG_ENDIAN +#endif +#define bswap16(x) as_ushort(as_uchar2(ushort(x)).s1s0) +#define bswap32(x) as_uint(as_uchar4(uint(x)).s3s2s1s0) +#define bswap64(x) as_ulong(as_uchar8(ulong(x)).s7s6s5s4s3s2s1s0) +#define __ENDIAN_DEFINED 1 +#define __BSWAP_DEFINED 1 +#endif + +/* Unknown */ +#if !__ENDIAN_DEFINED +#error Could not determine CPU byte order +#endif + +/* POSIX - http://austingroupbugs.net/view.php?id=162 */ +#ifndef BYTE_ORDER +#define BYTE_ORDER _BYTE_ORDER +#endif +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN _LITTLE_ENDIAN +#endif +#ifndef BIG_ENDIAN +#define BIG_ENDIAN _BIG_ENDIAN +#endif + +/* OpenCL compatibility - define __ENDIAN_LITTLE__ on little endian systems */ +#if _BYTE_ORDER == _LITTLE_ENDIAN +#if !defined(__ENDIAN_LITTLE__) +#define __ENDIAN_LITTLE__ 1 +#endif +#endif + +/* Byte swap macros */ +#if !__BSWAP_DEFINED + +#ifndef bswap16 +/* handle missing __builtin_bswap16 + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52624 */ +#if defined __GNUC__ +#define bswap16(x) __builtin_bswap16(x) +#else +#define bswap16(x) \ + ((uint16_t)((((uint16_t)(x)&0xff00) >> 8) | (((uint16_t)(x)&0x00ff) << 8))) +#endif +#endif + +#ifndef bswap32 +#if defined __GNUC__ +#define bswap32(x) __builtin_bswap32(x) +#else +#define bswap32(x) \ + ((uint32_t)( \ + (((uint32_t)(x)&0xff000000) >> 24) | (((uint32_t)(x)&0x00ff0000) >> 8) | \ + (((uint32_t)(x)&0x0000ff00) << 8) | (((uint32_t)(x)&0x000000ff) << 24))) +#endif +#endif + +#ifndef bswap64 +#if defined __GNUC__ +#define bswap64(x) __builtin_bswap64(x) +#else +#define bswap64(x) \ + ((uint64_t)((((uint64_t)(x)&0xff00000000000000ull) >> 56) | \ + (((uint64_t)(x)&0x00ff000000000000ull) >> 40) | \ + (((uint64_t)(x)&0x0000ff0000000000ull) >> 24) | \ + (((uint64_t)(x)&0x000000ff00000000ull) >> 8) | \ + (((uint64_t)(x)&0x00000000ff000000ull) << 8) | \ + (((uint64_t)(x)&0x0000000000ff0000ull) << 24) | \ + (((uint64_t)(x)&0x000000000000ff00ull) << 40) | \ + (((uint64_t)(x)&0x00000000000000ffull) << 56))) +#endif +#endif + +#endif + +/* Host swap macros */ +#ifndef __HOSTSWAP_DEFINED +#if _BYTE_ORDER == _LITTLE_ENDIAN +#define htobe16(x) bswap16((x)) +#define htole16(x) ((uint16_t)(x)) +#define be16toh(x) bswap16((x)) +#define le16toh(x) ((uint16_t)(x)) + +#define htobe32(x) bswap32((x)) +#define htole32(x) ((uint32_t)(x)) +#define be32toh(x) bswap32((x)) +#define le32toh(x) ((uint32_t)(x)) + +#define htobe64(x) bswap64((x)) +#define htole64(x) ((uint64_t)(x)) +#define be64toh(x) bswap64((x)) +#define le64toh(x) ((uint64_t)(x)) +#elif _BYTE_ORDER == _BIG_ENDIAN +#define htobe16(x) ((uint16_t)(x)) +#define htole16(x) bswap16((x)) +#define be16toh(x) ((uint16_t)(x)) +#define le16toh(x) bswap16((x)) + +#define htobe32(x) ((uint32_t)(x)) +#define htole32(x) bswap32((x)) +#define be32toh(x) ((uint32_t)(x)) +#define le64toh(x) bswap64((x)) + +#define htobe64(x) ((uint64_t)(x)) +#define htole64(x) bswap64((x)) +#define be64toh(x) ((uint64_t)(x)) +#define le32toh(x) bswap32((x)) +#endif +#endif diff --git a/src/libcollectdclient/network_buffer.c b/src/libcollectdclient/network_buffer.c index a0f8cfdc..5a1ee8d0 100644 --- a/src/libcollectdclient/network_buffer.c +++ b/src/libcollectdclient/network_buffer.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -122,40 +123,40 @@ struct lcc_network_buffer_s { /* * Private functions */ -static _Bool have_gcrypt(void) /* {{{ */ +static bool have_gcrypt(void) /* {{{ */ { - static _Bool result = 0; - static _Bool need_init = 1; + static bool result; + static bool need_init = true; if (!need_init) return result; - need_init = 0; + need_init = false; #if HAVE_GCRYPT_H #if GCRYPT_VERSION_NUMBER < 0x010600 if (gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread)) - return 0; + return false; #endif if (!gcry_check_version(GCRYPT_VERSION)) - return 0; + return false; if (!gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0)) - return 0; + return false; gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); - result = 1; - return 1; + result = true; + return true; #else - return 0; + return false; #endif -} /* }}} _Bool have_gcrypt */ +} /* }}} bool have_gcrypt */ #ifndef HAVE_HTONLL static uint64_t htonll(uint64_t val) /* {{{ */ { - static int config = 0; + static int config; uint32_t hi; uint32_t lo; @@ -185,7 +186,7 @@ static uint64_t htonll(uint64_t val) /* {{{ */ static double htond(double val) /* {{{ */ { - static int config = 0; + static int config; union { uint8_t byte[8]; diff --git a/src/libcollectdclient/network_parse.c b/src/libcollectdclient/network_parse.c index ce1bebcc..a8f6bd61 100644 --- a/src/libcollectdclient/network_parse.c +++ b/src/libcollectdclient/network_parse.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -45,7 +46,7 @@ #elif HAVE_SYS_ENDIAN_H #include #else /* fallback */ -#include "stdendian.h" +#include "collectd/stdendian.h" #endif #if HAVE_GCRYPT_H @@ -68,7 +69,7 @@ static int network_parse(void *data, size_t data_size, lcc_security_level_t sl, lcc_network_parse_options_t const *opts); #if HAVE_GCRYPT_H -static int init_gcrypt() { +static int init_gcrypt(void) { /* http://lists.gnupg.org/pipermail/gcrypt-devel/2003-August/000458.html * Because you can't know in a library whether another library has * already initialized the library */ @@ -220,7 +221,7 @@ static int parse_time(uint16_t type, void *payload, size_t payload_size, static double ntohd(double val) /* {{{ */ { - static int config = 0; + static int config; union { uint8_t byte[8]; diff --git a/src/libcollectdclient/server.c b/src/libcollectdclient/server.c index 0e6d7779..1095ebaf 100644 --- a/src/libcollectdclient/server.c +++ b/src/libcollectdclient/server.c @@ -33,7 +33,9 @@ #include "collectd/network_parse.h" /* for lcc_network_parse_options_t */ #include "collectd/server.h" +// clang-format off #include +#include #include #include #include @@ -41,11 +43,12 @@ #include #include #include +// clang-format on #include #define DEBUG(...) printf(__VA_ARGS__) -static _Bool is_multicast(struct addrinfo const *ai) { +static bool is_multicast(struct addrinfo const *ai) { if (ai->ai_family == AF_INET) { struct sockaddr_in *addr = (struct sockaddr_in *)ai->ai_addr; return IN_MULTICAST(ntohl(addr->sin_addr.s_addr)); @@ -175,7 +178,7 @@ static int server_open(lcc_listener_t *srv) { } int lcc_listen_and_write(lcc_listener_t srv) { - _Bool close_socket = 0; + bool close_socket = 0; if (srv.conn < 0) { int status = server_open(&srv); diff --git a/src/liboconfig/parser.y b/src/liboconfig/parser.y index 90f51de7..1b2d6ccd 100644 --- a/src/liboconfig/parser.y +++ b/src/liboconfig/parser.y @@ -265,21 +265,19 @@ static void yyerror(const char *s) static char *unquote (const char *orig) { char *ret = strdup (orig); - int len; - if (ret == NULL) - return (NULL); + return NULL; - len = strlen (ret); + size_t len = strlen (ret); if ((len < 2) || (ret[0] != '"') || (ret[len - 1] != '"')) - return (ret); + return ret; len -= 2; memmove (ret, ret + 1, len); ret[len] = 0; - for (int i = 0; i < len; i++) + for (size_t i = 0; i < len; i++) { if (ret[i] == '\\') { @@ -288,5 +286,5 @@ static char *unquote (const char *orig) } } - return (ret); + return ret; } /* char *unquote */ diff --git a/src/liboconfig/scanner.l b/src/liboconfig/scanner.l index 48580031..cfd9a5c9 100644 --- a/src/liboconfig/scanner.l +++ b/src/liboconfig/scanner.l @@ -40,9 +40,9 @@ /* multiline string buffer */ -static char *ml_buffer = NULL; -static int ml_pos = 0; -static int ml_len = 0; +static char *ml_buffer; +static size_t ml_pos; +static size_t ml_len; #define ml_free (ml_len - ml_pos) @@ -110,12 +110,12 @@ IPV6_ADDR ({IPV6_BASE})|(\[{IPV6_BASE}\](:{PORT})?) {UNQUOTED_STRING} {yylval.string = yytext; return (UNQUOTED_STRING);} \"{QUOTED_STRING}\\{EOL} { - int len = strlen (yytext); + size_t len = strlen (yytext); ml_pos = 0; /* remove "\\" */ - if ('\r' == yytext[len - 2]) + if (yytext[len - 2] == '\r') len -= 3; else len -= 2; @@ -126,10 +126,10 @@ IPV6_ADDR ({IPV6_BASE})|(\[{IPV6_BASE}\](:{PORT})?) } ^{WHITE_SPACE}+ {/* remove leading white-space */} {NON_WHITE_SPACE}{QUOTED_STRING}\\{EOL} { - int len = strlen (yytext); + size_t len = strlen (yytext); /* remove "\\" */ - if ('\r' == yytext[len - 2]) + if (yytext[len - 2] == '\r') len -= 3; else len -= 2; @@ -147,18 +147,17 @@ IPV6_ADDR ({IPV6_BASE})|(\[{IPV6_BASE}\](:{PORT})?) %% static void ml_append (char *string) { - int len = strlen (string); - int s; + size_t len = strlen (string); if (ml_free <= len) { ml_len += len - ml_free + 1; ml_buffer = realloc (ml_buffer, ml_len); - if (NULL == ml_buffer) + if (ml_buffer == NULL) YY_FATAL_ERROR ("out of dynamic memory in ml_append"); } - s = snprintf (ml_buffer + ml_pos, ml_free, "%s", string); - if ((0 > s) || (ml_free <= s)) + int s = snprintf(ml_buffer + ml_pos, ml_free, "%s", string); + if (s < 0 || (size_t)s >= ml_free) YY_FATAL_ERROR ("failed to write to multiline buffer"); ml_pos += s; diff --git a/src/load.c b/src/load.c index 83aca5ee..858d9bea 100644 --- a/src/load.c +++ b/src/load.c @@ -55,7 +55,7 @@ #include #endif /* HAVE_PERFSTAT */ -static _Bool report_relative_load = 0; +static bool report_relative_load; static const char *config_keys[] = {"ReportRelative"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); @@ -63,7 +63,7 @@ static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); static int load_config(const char *key, const char *value) { if (strcasecmp(key, "ReportRelative") == 0) #ifdef _SC_NPROCESSORS_ONLN - report_relative_load = IS_TRUE(value) ? 1 : 0; + report_relative_load = IS_TRUE(value); #else WARNING("load plugin: The \"ReportRelative\" configuration " "is not available, because I can't determine the " diff --git a/src/log_logstash.c b/src/log_logstash.c index de34b0ea..8f3063f3 100644 --- a/src/log_logstash.c +++ b/src/log_logstash.c @@ -49,7 +49,7 @@ static int log_level = LOG_INFO; static pthread_mutex_t file_lock = PTHREAD_MUTEX_INITIALIZER; -static char *log_file = NULL; +static char *log_file; static const char *config_keys[] = {"LogLevel", "File"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); @@ -75,7 +75,7 @@ static int log_logstash_config(const char *key, const char *value) { static void log_logstash_print(yajl_gen g, int severity, cdtime_t timestamp_time) { FILE *fh; - _Bool do_close = 0; + bool do_close = false; struct tm timestamp_tm; char timestamp_str[64]; const unsigned char *buf; @@ -150,13 +150,13 @@ static void log_logstash_print(yajl_gen g, int severity, fh = stderr; } else if (strcasecmp(log_file, "stdout") == 0) { fh = stdout; - do_close = 0; + do_close = false; } else if (strcasecmp(log_file, "stderr") == 0) { fh = stderr; - do_close = 0; + do_close = false; } else { fh = fopen(log_file, "a"); - do_close = 1; + do_close = true; } if (fh == NULL) { diff --git a/src/logfile.c b/src/logfile.c index 66922870..fa56a1bc 100644 --- a/src/logfile.c +++ b/src/logfile.c @@ -39,9 +39,9 @@ static int log_level = LOG_INFO; static pthread_mutex_t file_lock = PTHREAD_MUTEX_INITIALIZER; -static char *log_file = NULL; +static char *log_file; static int print_timestamp = 1; -static int print_severity = 0; +static int print_severity; static const char *config_keys[] = {"LogLevel", "File", "Timestamp", "PrintSeverity"}; @@ -77,7 +77,7 @@ static int logfile_config(const char *key, const char *value) { static void logfile_print(const char *msg, int severity, cdtime_t timestamp_time) { FILE *fh; - _Bool do_close = 0; + bool do_close = false; char timestamp_str[64]; char level_str[16] = ""; @@ -122,7 +122,7 @@ static void logfile_print(const char *msg, int severity, fh = stdout; else { fh = fopen(log_file, "a"); - do_close = 1; + do_close = true; } if (fh == NULL) { diff --git a/src/lpar.c b/src/lpar.c index c4189b7d..df18b525 100644 --- a/src/lpar.c +++ b/src/lpar.c @@ -40,10 +40,10 @@ static const char *config_keys[] = {"CpuPoolStats", "ReportBySerial"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static _Bool pool_stats = 0; -static _Bool report_by_serial = 0; +static bool pool_stats; +static bool report_by_serial; #if PERFSTAT_SUPPORTS_DONATION -static _Bool donate_flag = 0; +static bool donate_flag; #endif static char serial[SYS_NMLN]; @@ -52,14 +52,14 @@ static perfstat_partition_total_t lparstats_old; static int lpar_config(const char *key, const char *value) { if (strcasecmp("CpuPoolStats", key) == 0) { if (IS_TRUE(value)) - pool_stats = 1; + pool_stats = true; else - pool_stats = 0; + pool_stats = false; } else if (strcasecmp("ReportBySerial", key) == 0) { if (IS_TRUE(value)) - report_by_serial = 1; + report_by_serial = true; else - report_by_serial = 0; + report_by_serial = false; } else { return -1; } @@ -84,14 +84,14 @@ static int lpar_init(void) { #if PERFSTAT_SUPPORTS_DONATION if (!lparstats_old.type.b.shared_enabled && lparstats_old.type.b.donate_enabled) { - donate_flag = 1; + donate_flag = true; } #endif if (pool_stats && !lparstats_old.type.b.pool_util_authority) { WARNING("lpar plugin: This partition does not have pool authority. " "Disabling CPU pool statistics collection."); - pool_stats = 0; + pool_stats = false; } return 0; diff --git a/src/lua.c b/src/lua.c index 8cfb7045..f66d8526 100644 --- a/src/lua.c +++ b/src/lua.c @@ -28,27 +28,18 @@ * Ruben Kerkhof **/ -/* defines a macro using "sprintf". Although not used here, - * GCC will complain about the macro definition. */ -#define DONT_POISON_SPRINTF_YET - +#include "collectd.h" #include "common.h" #include "plugin.h" -#include "collectd.h" +#include "utils_lua.h" /* Include the Lua API header files. */ #include #include #include -#include "utils_lua.h" #include -#if COLLECT_DEBUG && __GNUC__ -#undef sprintf -#pragma GCC poison sprintf -#endif - typedef struct lua_script_s { char *script_path; lua_State *lua_state; diff --git a/src/madwifi.c b/src/madwifi.c index 1a387b78..60ac3c8c 100644 --- a/src/madwifi.c +++ b/src/madwifi.c @@ -99,8 +99,8 @@ #error "No applicable input method." #endif -#include #include "madwifi.h" +#include struct stat_spec { uint16_t flags; @@ -347,10 +347,10 @@ static const char *config_keys[] = {"Interface", "IgnoreSelected", "Source", "MiscAdd", "MiscRemove", "MiscSet"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static ignorelist_t *ignorelist = NULL; +static ignorelist_t *ignorelist; static int use_sysfs = 1; -static int init_state = 0; +static int init_state; static inline int item_watched(int i) { assert(i >= 0); diff --git a/src/match_regex.c b/src/match_regex.c index dd4018b0..ed1e3295 100644 --- a/src/match_regex.c +++ b/src/match_regex.c @@ -66,7 +66,7 @@ struct mr_match_s { mr_regex_t *type; mr_regex_t *type_instance; llist_t *meta; /* Maps each meta key into mr_regex_t* */ - _Bool invert; + bool invert; }; /* @@ -245,7 +245,7 @@ static int mr_create(const oconfig_item_t *ci, void **user_data) /* {{{ */ return -ENOMEM; } - m->invert = 0; + m->invert = false; status = 0; for (int i = 0; i < ci->children_num; i++) { diff --git a/src/mbmon.c b/src/mbmon.c index f58d01ec..63a300de 100644 --- a/src/mbmon.c +++ b/src/mbmon.c @@ -38,8 +38,8 @@ static const char *config_keys[] = {"Host", "Port", NULL}; static int config_keys_num = 2; -static char *mbmon_host = NULL; -static char *mbmon_port = NULL; +static char *mbmon_host; +static char *mbmon_port; /* * NAME diff --git a/src/mcelog.c b/src/mcelog.c index 1a92a065..4e514004 100644 --- a/src/mcelog.c +++ b/src/mcelog.c @@ -56,7 +56,7 @@ typedef struct mcelog_config_s { pthread_t tid; /* poll thread id */ llist_t *dimms_list; /* DIMMs list */ pthread_mutex_t dimms_lock; /* lock for dimms cache */ - _Bool persist; + bool persist; } mcelog_config_t; typedef struct socket_adapter_s socket_adapter_t; @@ -90,7 +90,7 @@ static int socket_reinit(socket_adapter_t *self); static int socket_receive(socket_adapter_t *self, FILE **p_file); static mcelog_config_t g_mcelog_config = { - .logfile = "/var/log/mcelog", .persist = 0, + .logfile = "/var/log/mcelog", .persist = false, }; static socket_adapter_t socket_adapter = { @@ -106,8 +106,8 @@ static socket_adapter_t socket_adapter = { .receive = socket_receive, }; -static _Bool mcelog_thread_running; -static _Bool mcelog_apply_defaults; +static bool mcelog_thread_running; +static bool mcelog_apply_defaults; static void mcelog_free_dimms_list_records(llist_t *dimms_list) { diff --git a/src/md.c b/src/md.c index b8df328e..0a015c7b 100644 --- a/src/md.c +++ b/src/md.c @@ -40,7 +40,7 @@ static const char *config_keys[] = {"Device", "IgnoreSelected"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static ignorelist_t *ignorelist = NULL; +static ignorelist_t *ignorelist; static int md_config(const char *key, const char *value) { if (ignorelist == NULL) diff --git a/src/memcachec.c b/src/memcachec.c index bd088ecd..f293aa1b 100644 --- a/src/memcachec.c +++ b/src/memcachec.c @@ -68,7 +68,7 @@ struct web_page_s /* {{{ */ /* * Global variables; */ -static web_page_t *pages_g = NULL; +static web_page_t *pages_g; /* * Private functions @@ -123,21 +123,6 @@ static int cmc_page_init_memc(web_page_t *wp) /* {{{ */ return 0; } /* }}} int cmc_page_init_memc */ -static int cmc_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("memcachec 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 cmc_config_add_string */ - static int cmc_config_add_match_dstype(int *dstype_ret, /* {{{ */ oconfig_item_t *ci) { int dstype; @@ -204,16 +189,15 @@ static int cmc_config_add_match(web_page_t *page, /* {{{ */ oconfig_item_t *child = ci->children + i; if (strcasecmp("Regex", child->key) == 0) - status = cmc_config_add_string("Regex", &match->regex, child); + status = cf_util_get_string(child, &match->regex); else if (strcasecmp("ExcludeRegex", child->key) == 0) - status = - cmc_config_add_string("ExcludeRegex", &match->exclude_regex, child); + status = cf_util_get_string(child, &match->exclude_regex); else if (strcasecmp("DSType", child->key) == 0) status = cmc_config_add_match_dstype(&match->dstype, child); else if (strcasecmp("Type", child->key) == 0) - status = cmc_config_add_string("Type", &match->type, child); + status = cf_util_get_string(child, &match->type); else if (strcasecmp("Instance", child->key) == 0) - status = cmc_config_add_string("Instance", &match->instance, child); + status = cf_util_get_string(child, &match->instance); else { WARNING("memcachec plugin: Option `%s' not allowed here.", child->key); status = -1; @@ -301,11 +285,11 @@ static int cmc_config_add_page(oconfig_item_t *ci) /* {{{ */ oconfig_item_t *child = ci->children + i; if (strcasecmp("Server", child->key) == 0) - status = cmc_config_add_string("Server", &page->server, child); + status = cf_util_get_string(child, &page->server); else if (strcasecmp("Key", child->key) == 0) - status = cmc_config_add_string("Key", &page->key, child); + status = cf_util_get_string(child, &page->key); else if (strcasecmp("Plugin", child->key) == 0) - status = cmc_config_add_string("Plugin", &page->plugin_name, child); + status = cf_util_get_string(child, &page->plugin_name); else if (strcasecmp("Match", child->key) == 0) /* Be liberal with failing matches => don't set `status'. */ cmc_config_add_match(page, child); @@ -412,7 +396,7 @@ static void cmc_submit(const web_page_t *wp, const web_match_t *wm, /* {{{ */ vl.values = &value; vl.values_len = 1; sstrncpy(vl.plugin, (wp->plugin_name != NULL) ? wp->plugin_name : "memcachec", - sizeof (vl.plugin)); + sizeof(vl.plugin)); sstrncpy(vl.plugin_instance, wp->instance, sizeof(vl.plugin_instance)); sstrncpy(vl.type, wm->type, sizeof(vl.type)); sstrncpy(vl.type_instance, wm->instance, sizeof(vl.type_instance)); diff --git a/src/memcached.c b/src/memcached.c index 635088eb..4ff70f7c 100644 --- a/src/memcached.c +++ b/src/memcached.c @@ -69,7 +69,7 @@ struct memcached_s { }; typedef struct memcached_s memcached_t; -static _Bool memcached_have_instances = 0; +static bool memcached_have_instances; static void memcached_free(void *arg) { memcached_t *st = arg; @@ -475,7 +475,7 @@ static int memcached_read(user_data_t *user_data) { if (strsplit(line, fields, 3) != 3) continue; - int name_len = strlen(fields[1]); + size_t name_len = strlen(fields[1]); if (name_len == 0) continue; @@ -702,7 +702,7 @@ static int config_add_instance(oconfig_item_t *ci) { int status = 0; /* Disable automatic generation of default instance in the init callback. */ - memcached_have_instances = 1; + memcached_have_instances = true; memcached_t *st = calloc(1, sizeof(*st)); if (st == NULL) { @@ -755,7 +755,7 @@ static int config_add_instance(oconfig_item_t *ci) { } /* int config_add_instance */ static int memcached_config(oconfig_item_t *ci) { - _Bool have_instance_block = 0; + bool have_instance_block = 0; for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; @@ -797,7 +797,7 @@ static int memcached_init(void) { int status = memcached_add_read_callback(st); if (status == 0) - memcached_have_instances = 1; + memcached_have_instances = true; return status; } /* int memcached_init */ diff --git a/src/memory.c b/src/memory.c index 80b11049..cc95496a 100644 --- a/src/memory.c +++ b/src/memory.c @@ -94,8 +94,8 @@ static int pagesize; #error "No applicable input method." #endif -static _Bool values_absolute = 1; -static _Bool values_percentage = 0; +static bool values_absolute = true; +static bool values_percentage; static int memory_config(oconfig_item_t *ci) /* {{{ */ { @@ -163,9 +163,9 @@ static int memory_init(void) { #define MEMORY_SUBMIT(...) \ do { \ if (values_absolute) \ - plugin_dispatch_multivalue(vl, 0, DS_TYPE_GAUGE, __VA_ARGS__, NULL); \ + plugin_dispatch_multivalue(vl, false, DS_TYPE_GAUGE, __VA_ARGS__, NULL); \ if (values_percentage) \ - plugin_dispatch_multivalue(vl, 1, DS_TYPE_GAUGE, __VA_ARGS__, NULL); \ + plugin_dispatch_multivalue(vl, true, DS_TYPE_GAUGE, __VA_ARGS__, NULL); \ } while (0) static int memory_read_internal(value_list_t *vl) { @@ -268,7 +268,7 @@ static int memory_read_internal(value_list_t *vl) { char *fields[8]; int numfields; - _Bool detailed_slab_info = 0; + bool detailed_slab_info = false; gauge_t mem_total = 0; gauge_t mem_used = 0; @@ -299,10 +299,10 @@ static int memory_read_internal(value_list_t *vl) { val = &mem_slab_total; else if (strncasecmp(buffer, "SReclaimable:", 13) == 0) { val = &mem_slab_reclaimable; - detailed_slab_info = 1; + detailed_slab_info = true; } else if (strncasecmp(buffer, "SUnreclaim:", 11) == 0) { val = &mem_slab_unreclaimable; - detailed_slab_info = 1; + detailed_slab_info = true; } else continue; diff --git a/src/mic.c b/src/mic.c index 3f9521d8..4f4a9bac 100644 --- a/src/mic.c +++ b/src/mic.c @@ -35,8 +35,8 @@ #define MAX_CORES 256 static MicDeviceOnSystem mics[MAX_MICS]; -static U32 num_mics = 0; -static HANDLE mic_handle = NULL; +static U32 num_mics; +static HANDLE mic_handle; static int const therm_ids[] = { eMicThermalDie, eMicThermalDevMem, eMicThermalFin, eMicThermalFout, @@ -50,13 +50,13 @@ static const char *config_keys[] = { "ShowPower", "Power", "IgnoreSelectedPower"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static _Bool show_cpu = 1; -static _Bool show_cpu_cores = 1; -static _Bool show_memory = 1; -static _Bool show_temps = 1; -static ignorelist_t *temp_ignore = NULL; -static _Bool show_power = 1; -static ignorelist_t *power_ignore = NULL; +static bool show_cpu = true; +static bool show_cpu_cores = true; +static bool show_memory = true; +static bool show_temps = true; +static ignorelist_t *temp_ignore; +static bool show_power = true; +static ignorelist_t *power_ignore; static int mic_init(void) { U32 ret; diff --git a/src/modbus.c b/src/modbus.c index daa3c028..bb9eaa0f 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -80,6 +80,8 @@ enum mb_register_type_e /* {{{ */ REG_TYPE_UINT16, REG_TYPE_UINT32, REG_TYPE_UINT32_CDAB, + REG_TYPE_INT64, + REG_TYPE_UINT64, REG_TYPE_FLOAT, REG_TYPE_FLOAT_CDAB }; /* }}} */ @@ -105,6 +107,8 @@ struct mb_data_s /* {{{ */ mb_mreg_type_t modbus_register_type; char type[DATA_MAX_NAME_LEN]; char instance[DATA_MAX_NAME_LEN]; + double scale; + double shift; mb_data_t *next; }; /* }}} */ @@ -135,7 +139,7 @@ struct mb_host_s /* {{{ */ #else modbus_t *connection; #endif - _Bool is_connected; + bool is_connected; }; /* }}} */ typedef struct mb_host_s mb_host_t; @@ -152,7 +156,7 @@ struct mb_data_group_s /* {{{ */ /* * Global variables */ -static mb_data_t *data_definitions = NULL; +static mb_data_t *data_definitions; /* * Functions @@ -332,7 +336,7 @@ static int mb_init_connection(mb_host_t *host) /* {{{ */ return status; } - host->is_connected = 1; + host->is_connected = true; return 0; } /* }}} int mb_init_connection */ /* #endif LEGACY_LIBMODBUS */ @@ -392,21 +396,21 @@ static int mb_init_connection(mb_host_t *host) /* {{{ */ } /* }}} int mb_init_connection */ #endif /* !LEGACY_LIBMODBUS */ -#define CAST_TO_VALUE_T(ds, vt, raw) \ +#define CAST_TO_VALUE_T(ds, vt, raw, scale, shift) \ do { \ if ((ds)->ds[0].type == DS_TYPE_COUNTER) \ - (vt).counter = (counter_t)(raw); \ + (vt).counter = (((counter_t)(raw)*scale) + shift); \ else if ((ds)->ds[0].type == DS_TYPE_GAUGE) \ - (vt).gauge = (gauge_t)(raw); \ + (vt).gauge = (((gauge_t)(raw)*scale) + shift); \ else if ((ds)->ds[0].type == DS_TYPE_DERIVE) \ - (vt).derive = (derive_t)(raw); \ + (vt).derive = (((derive_t)(raw)*scale) + shift); \ else /* if (ds->ds[0].type == DS_TYPE_ABSOLUTE) */ \ - (vt).absolute = (absolute_t)(raw); \ + (vt).absolute = (((absolute_t)(raw)*scale) + shift); \ } while (0) static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ mb_data_t *data) { - uint16_t values[2] = {0}; + uint16_t values[4] = {0}; int values_num; const data_set_t *ds; int status = 0; @@ -431,11 +435,13 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ (data->register_type != REG_TYPE_INT32) && (data->register_type != REG_TYPE_INT32_CDAB) && (data->register_type != REG_TYPE_UINT32) && - (data->register_type != REG_TYPE_UINT32_CDAB)) { + (data->register_type != REG_TYPE_UINT32_CDAB) && + (data->register_type != REG_TYPE_INT64) && + (data->register_type != REG_TYPE_UINT64)) { NOTICE( "Modbus plugin: The data source of type \"%s\" is %s, not gauge. " "This will most likely result in problems, because the register type " - "is not UINT32.", + "is not UINT32 or UINT64.", data->type, DS_TYPE_TO_STRING(ds->ds[0].type)); } @@ -446,6 +452,9 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ (data->register_type == REG_TYPE_FLOAT) || (data->register_type == REG_TYPE_FLOAT_CDAB)) values_num = 2; + else if ((data->register_type == REG_TYPE_INT64) || + (data->register_type == REG_TYPE_UINT64)) + values_num = 4; else values_num = 1; @@ -465,7 +474,7 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ if (status != 0) { ERROR("Modbus plugin: mb_init_connection (%s/%s) failed. ", host->host, host->node); - host->is_connected = 0; + host->is_connected = false; host->connection = NULL; return -1; } @@ -530,7 +539,7 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ "Returned float value is %g", (double)float_value); - CAST_TO_VALUE_T(ds, vt, float_value); + CAST_TO_VALUE_T(ds, vt, float_value, data->scale, data->shift); mb_submit(host, slave, data, vt); } else if (data->register_type == REG_TYPE_FLOAT_CDAB) { float float_value; @@ -541,7 +550,7 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ "Returned float value is %g", (double)float_value); - CAST_TO_VALUE_T(ds, vt, float_value); + CAST_TO_VALUE_T(ds, vt, float_value, data->scale, data->shift); mb_submit(host, slave, data, vt); } else if (data->register_type == REG_TYPE_INT32) { union { @@ -555,7 +564,7 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ "Returned int32 value is %" PRIi32, v.i32); - CAST_TO_VALUE_T(ds, vt, v.i32); + CAST_TO_VALUE_T(ds, vt, v.i32, data->scale, data->shift); mb_submit(host, slave, data, vt); } else if (data->register_type == REG_TYPE_INT32_CDAB) { union { @@ -569,7 +578,7 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ "Returned int32 value is %" PRIi32, v.i32); - CAST_TO_VALUE_T(ds, vt, v.i32); + CAST_TO_VALUE_T(ds, vt, v.i32, data->scale, data->shift); mb_submit(host, slave, data, vt); } else if (data->register_type == REG_TYPE_INT16) { union { @@ -584,7 +593,7 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ "Returned int16 value is %" PRIi16, v.i16); - CAST_TO_VALUE_T(ds, vt, v.i16); + CAST_TO_VALUE_T(ds, vt, v.i16, data->scale, data->shift); mb_submit(host, slave, data, vt); } else if (data->register_type == REG_TYPE_UINT32) { uint32_t v32; @@ -595,7 +604,7 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ "Returned uint32 value is %" PRIu32, v32); - CAST_TO_VALUE_T(ds, vt, v32); + CAST_TO_VALUE_T(ds, vt, v32, data->scale, data->shift); mb_submit(host, slave, data, vt); } else if (data->register_type == REG_TYPE_UINT32_CDAB) { uint32_t v32; @@ -606,7 +615,34 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ "Returned uint32 value is %" PRIu32, v32); - CAST_TO_VALUE_T(ds, vt, v32); + CAST_TO_VALUE_T(ds, vt, v32, data->scale, data->shift); + mb_submit(host, slave, data, vt); + } else if (data->register_type == REG_TYPE_UINT64) { + uint64_t v64; + value_t vt; + + v64 = (((uint64_t)values[0]) << 48) | (((uint64_t)values[1]) << 32) | + (((uint64_t)values[2]) << 16) | (((uint64_t)values[3])); + DEBUG("Modbus plugin: mb_read_data: " + "Returned uint64 value is %" PRIu64, + v64); + + CAST_TO_VALUE_T(ds, vt, v64, data->scale, data->shift); + mb_submit(host, slave, data, vt); + } else if (data->register_type == REG_TYPE_INT64) { + union { + uint64_t u64; + int64_t i64; + } v; + value_t vt; + + v.u64 = (((uint64_t)values[0]) << 48) | (((uint64_t)values[1]) << 32) | + (((uint64_t)values[2]) << 16) | ((uint64_t)values[3]); + DEBUG("Modbus plugin: mb_read_data: " + "Returned uint64 value is %" PRIi64, + v.i64); + + CAST_TO_VALUE_T(ds, vt, v.i64, data->scale, data->shift); mb_submit(host, slave, data, vt); } else /* if (data->register_type == REG_TYPE_UINT16) */ { @@ -616,7 +652,7 @@ static int mb_read_data(mb_host_t *host, mb_slave_t *slave, /* {{{ */ "Returned uint16 value is %" PRIu16, values[0]); - CAST_TO_VALUE_T(ds, vt, values[0]); + CAST_TO_VALUE_T(ds, vt, values[0], data->scale, data->shift); mb_submit(host, slave, data, vt); } @@ -723,6 +759,8 @@ static int mb_config_add_data(oconfig_item_t *ci) /* {{{ */ data.name = NULL; data.register_type = REG_TYPE_UINT16; data.next = NULL; + data.scale = 1; + data.shift = 0; status = cf_util_get_string(ci, &data.name); if (status != 0) @@ -736,6 +774,10 @@ static int mb_config_add_data(oconfig_item_t *ci) /* {{{ */ else if (strcasecmp("Instance", child->key) == 0) status = cf_util_get_string_buffer(child, data.instance, sizeof(data.instance)); + else if (strcasecmp("Scale", child->key) == 0) + status = cf_util_get_double(child, &data.scale); + else if (strcasecmp("Shift", child->key) == 0) + status = cf_util_get_double(child, &data.shift); else if (strcasecmp("RegisterBase", child->key) == 0) status = cf_util_get_int(child, &data.register_base); else if (strcasecmp("RegisterType", child->key) == 0) { @@ -759,6 +801,10 @@ static int mb_config_add_data(oconfig_item_t *ci) /* {{{ */ data.register_type = REG_TYPE_FLOAT; else if (strcasecmp("FloatLE", tmp) == 0) data.register_type = REG_TYPE_FLOAT_CDAB; + else if (strcasecmp("Uint64", tmp) == 0) + data.register_type = REG_TYPE_UINT64; + else if (strcasecmp("Int64", tmp) == 0) + data.register_type = REG_TYPE_INT64; else { ERROR("Modbus plugin: The register type \"%s\" is unknown.", tmp); status = -1; diff --git a/src/mqtt.c b/src/mqtt.c index d134c381..48c34edc 100644 --- a/src/mqtt.c +++ b/src/mqtt.c @@ -54,11 +54,11 @@ * Data types */ struct mqtt_client_conf { - _Bool publish; + bool publish; char *name; struct mosquitto *mosq; - _Bool connected; + bool connected; char *host; int port; @@ -74,22 +74,22 @@ struct mqtt_client_conf { /* For publishing */ char *topic_prefix; - _Bool store_rates; - _Bool retain; + bool store_rates; + bool retain; /* For subscribing */ pthread_t thread; - _Bool loop; + bool loop; char *topic; - _Bool clean_session; + 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; +static mqtt_client_conf_t **subscribers; +static size_t subscribers_num; /* * Functions @@ -141,7 +141,7 @@ static void mqtt_free(mqtt_client_conf_t *conf) { if (conf->connected) (void)mosquitto_disconnect(conf->mosq); - conf->connected = 0; + conf->connected = false; (void)mosquitto_destroy(conf->mosq); sfree(conf->host); @@ -252,7 +252,7 @@ static int mqtt_reconnect(mqtt_client_conf_t *conf) { return -1; } - conf->connected = 1; + conf->connected = true; c_release(LOG_INFO, &conf->complaint_cantpublish, "mqtt plugin: successfully reconnected to broker \"%s:%d\"", @@ -366,7 +366,7 @@ static int mqtt_connect(mqtt_client_conf_t *conf) { } } - conf->connected = 1; + conf->connected = true; return 0; } /* mqtt_connect */ @@ -393,14 +393,14 @@ static void *subscribers_thread(void *arg) { /* max_packets = */ 100); #endif if (status == MOSQ_ERR_CONN_LOST) { - conf->connected = 0; + conf->connected = false; 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; + conf->connected = false; continue; } @@ -438,7 +438,7 @@ static int publish(mqtt_client_conf_t *conf, char const *topic, /* 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; + conf->connected = false; mosquitto_disconnect(conf->mosq); pthread_mutex_unlock(&conf->lock); @@ -532,7 +532,7 @@ static int mqtt_config_publisher(oconfig_item_t *ci) { ERROR("mqtt plugin: calloc failed."); return -1; } - conf->publish = 1; + conf->publish = true; conf->name = NULL; status = cf_util_get_string(ci, &conf->name); @@ -546,7 +546,7 @@ static int mqtt_config_publisher(oconfig_item_t *ci) { conf->client_id = NULL; conf->qos = 0; conf->topic_prefix = strdup(MQTT_DEFAULT_TOPIC_PREFIX); - conf->store_rates = 1; + conf->store_rates = true; status = pthread_mutex_init(&conf->lock, NULL); if (status != 0) { @@ -631,7 +631,7 @@ static int mqtt_config_subscriber(oconfig_item_t *ci) { ERROR("mqtt plugin: calloc failed."); return -1; } - conf->publish = 0; + conf->publish = false; conf->name = NULL; status = cf_util_get_string(ci, &conf->name); @@ -645,7 +645,7 @@ static int mqtt_config_subscriber(oconfig_item_t *ci) { conf->client_id = NULL; conf->qos = 2; conf->topic = strdup(MQTT_DEFAULT_TOPIC); - conf->clean_session = 1; + conf->clean_session = true; status = pthread_mutex_init(&conf->lock, NULL); if (status != 0) { diff --git a/src/mysql.c b/src/mysql.c index 448f7cba..e7ffb489 100644 --- a/src/mysql.c +++ b/src/mysql.c @@ -58,17 +58,17 @@ struct mysql_database_s /* {{{ */ int port; int timeout; - _Bool master_stats; - _Bool slave_stats; - _Bool innodb_stats; - _Bool wsrep_stats; + bool master_stats; + bool slave_stats; + bool innodb_stats; + bool wsrep_stats; - _Bool slave_notif; - _Bool slave_io_running; - _Bool slave_sql_running; + bool slave_notif; + bool slave_io_running; + bool slave_sql_running; MYSQL *con; - _Bool is_connected; + bool is_connected; }; typedef struct mysql_database_s mysql_database_t; /* }}} */ @@ -147,8 +147,8 @@ static int mysql_config_database(oconfig_item_t *ci) /* {{{ */ db->timeout = 0; /* trigger a notification, if it's not running */ - db->slave_io_running = 1; - db->slave_sql_running = 1; + db->slave_io_running = true; + db->slave_sql_running = true; status = cf_util_get_string(ci, &db->instance); if (status != 0) { @@ -268,7 +268,7 @@ static MYSQL *getconnection(mysql_database_t *db) { WARNING("mysql plugin: Lost connection to instance \"%s\": %s", db->instance, mysql_error(db->con)); } - db->is_connected = 0; + db->is_connected = false; /* Close the old connection before initializing a new one. */ if (db->con != NULL) { @@ -305,7 +305,7 @@ static MYSQL *getconnection(mysql_database_t *db) { mysql_get_host_info(db->con), (cipher != NULL) ? cipher : "", mysql_get_server_info(db->con), mysql_get_proto_info(db->con)); - db->is_connected = 1; + db->is_connected = true; return db->con; } /* static MYSQL *getconnection (mysql_database_t *db) */ @@ -363,7 +363,7 @@ static void traffic_submit(derive_t rx, derive_t tx, mysql_database_t *db) { static MYSQL_RES *exec_query(MYSQL *con, const char *query) { MYSQL_RES *res; - int query_len = strlen(query); + size_t query_len = strlen(query); if (mysql_real_query(con, query, query_len)) { ERROR("mysql plugin: Failed to execute query: %s", mysql_error(con)); @@ -503,14 +503,14 @@ static int mysql_read_slave_stats(mysql_database_t *db, MYSQL *con) { snprintf(n.message, sizeof(n.message), "slave I/O thread not started or not connected to master"); plugin_dispatch_notification(&n); - db->slave_io_running = 0; + db->slave_io_running = false; } else if (((io != NULL) && (strcasecmp(io, "yes") == 0)) && (!db->slave_io_running)) { n.severity = NOTIF_OKAY; snprintf(n.message, sizeof(n.message), "slave I/O thread started and connected to master"); plugin_dispatch_notification(&n); - db->slave_io_running = 1; + db->slave_io_running = true; } if (((sql == NULL) || (strcasecmp(sql, "yes") != 0)) && @@ -518,13 +518,13 @@ static int mysql_read_slave_stats(mysql_database_t *db, MYSQL *con) { n.severity = NOTIF_WARNING; snprintf(n.message, sizeof(n.message), "slave SQL thread not started"); plugin_dispatch_notification(&n); - db->slave_sql_running = 0; + db->slave_sql_running = false; } else if (((sql != NULL) && (strcasecmp(sql, "yes") == 0)) && (!db->slave_sql_running)) { n.severity = NOTIF_OKAY; snprintf(n.message, sizeof(n.message), "slave SQL thread started"); plugin_dispatch_notification(&n); - db->slave_sql_running = 1; + db->slave_sql_running = true; } } diff --git a/src/netapp.c b/src/netapp.c index 44fb9768..62600ca2 100644 --- a/src/netapp.c +++ b/src/netapp.c @@ -2229,42 +2229,6 @@ static int cna_query_system(host_config_t *host) /* {{{ */ /* * Configuration handling */ -/* Sets a given flag if the boolean argument is true and unsets the flag if it - * is false. On error, the flag-field is not changed. */ -static int cna_config_bool_to_flag(const oconfig_item_t *ci, /* {{{ */ - uint32_t *flags, uint32_t flag) { - if ((ci == NULL) || (flags == NULL)) - return EINVAL; - - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) { - WARNING("netapp plugin: The %s option needs exactly one boolean argument.", - ci->key); - return -1; - } - - if (ci->values[0].value.boolean) - *flags |= flag; - else - *flags &= ~flag; - - return 0; -} /* }}} int cna_config_bool_to_flag */ - -/* Handling of the "Interval" option which is allowed in every block. */ -static int cna_config_get_interval(const oconfig_item_t *ci, /* {{{ */ - cna_interval_t *out_interval) { - cdtime_t tmp = 0; - int status; - - status = cf_util_get_cdtime(ci, &tmp); - if (status != 0) - return status; - - out_interval->interval = tmp; - out_interval->last_read = 0; - - return 0; -} /* }}} int cna_config_get_interval */ /* Handling of the "GetIO", "GetOps" and "GetLatency" options within a * block. */ @@ -2385,7 +2349,7 @@ static int cna_config_volume_performance(host_config_t *host, /* {{{ */ /* if (!item || !item->key || !*item->key) continue; */ if (strcasecmp(item->key, "Interval") == 0) - cna_config_get_interval(item, &cfg_volume_perf->interval); + cf_util_get_cdtime(item, &cfg_volume_perf->interval.interval); else if (!strcasecmp(item->key, "GetIO")) cna_config_volume_perf_option(cfg_volume_perf, item); else if (!strcasecmp(item->key, "GetOps")) @@ -2481,7 +2445,7 @@ static int cna_config_quota(host_config_t *host, oconfig_item_t *ci) /* {{{ */ oconfig_item_t *item = ci->children + i; if (strcasecmp(item->key, "Interval") == 0) - cna_config_get_interval(item, &cfg_quota->interval); + cf_util_get_cdtime(item, &cfg_quota->interval.interval); else WARNING("netapp plugin: The option %s is not allowed within " "`Quota' blocks.", @@ -2517,9 +2481,9 @@ static int cna_config_disk(host_config_t *host, oconfig_item_t *ci) { /* {{{ */ /* if (!item || !item->key || !*item->key) continue; */ if (strcasecmp(item->key, "Interval") == 0) - cna_config_get_interval(item, &cfg_disk->interval); + cf_util_get_cdtime(item, &cfg_disk->interval.interval); else if (strcasecmp(item->key, "GetBusy") == 0) - cna_config_bool_to_flag(item, &cfg_disk->flags, CFG_DISK_BUSIEST); + cf_util_get_flag(item, &cfg_disk->flags, CFG_DISK_BUSIEST); } if ((cfg_disk->flags & CFG_DISK_ALL) == 0) { @@ -2556,15 +2520,15 @@ static int cna_config_wafl(host_config_t *host, oconfig_item_t *ci) /* {{{ */ oconfig_item_t *item = ci->children + i; if (strcasecmp(item->key, "Interval") == 0) - cna_config_get_interval(item, &cfg_wafl->interval); + cf_util_get_cdtime(item, &cfg_wafl->interval.interval); else if (!strcasecmp(item->key, "GetNameCache")) - cna_config_bool_to_flag(item, &cfg_wafl->flags, CFG_WAFL_NAME_CACHE); + cf_util_get_flag(item, &cfg_wafl->flags, CFG_WAFL_NAME_CACHE); else if (!strcasecmp(item->key, "GetDirCache")) - cna_config_bool_to_flag(item, &cfg_wafl->flags, CFG_WAFL_DIR_CACHE); + cf_util_get_flag(item, &cfg_wafl->flags, CFG_WAFL_DIR_CACHE); else if (!strcasecmp(item->key, "GetBufferCache")) - cna_config_bool_to_flag(item, &cfg_wafl->flags, CFG_WAFL_BUF_CACHE); + cf_util_get_flag(item, &cfg_wafl->flags, CFG_WAFL_BUF_CACHE); else if (!strcasecmp(item->key, "GetInodeCache")) - cna_config_bool_to_flag(item, &cfg_wafl->flags, CFG_WAFL_INODE_CACHE); + cf_util_get_flag(item, &cfg_wafl->flags, CFG_WAFL_INODE_CACHE); else WARNING("netapp plugin: The %s config option is not allowed within " "`WAFL' blocks.", @@ -2636,7 +2600,7 @@ static int cna_config_volume_usage(host_config_t *host, /* {{{ */ /* if (!item || !item->key || !*item->key) continue; */ if (strcasecmp(item->key, "Interval") == 0) - cna_config_get_interval(item, &cfg_volume_usage->interval); + cf_util_get_cdtime(item, &cfg_volume_usage->interval.interval); else if (!strcasecmp(item->key, "GetCapacity")) cna_config_volume_usage_option(cfg_volume_usage, item); else if (!strcasecmp(item->key, "GetSnapshot")) @@ -2677,7 +2641,7 @@ static int cna_config_snapvault(host_config_t *host, /* {{{ */ oconfig_item_t *item = ci->children + i; if (strcasecmp(item->key, "Interval") == 0) - cna_config_get_interval(item, &cfg_snapvault->interval); + cf_util_get_cdtime(item, &cfg_snapvault->interval.interval); else WARNING("netapp plugin: The option %s is not allowed within " "`SnapVault' blocks.", @@ -2712,15 +2676,15 @@ static int cna_config_system(host_config_t *host, /* {{{ */ oconfig_item_t *item = ci->children + i; if (strcasecmp(item->key, "Interval") == 0) { - cna_config_get_interval(item, &cfg_system->interval); + cf_util_get_cdtime(item, &cfg_system->interval.interval); } else if (!strcasecmp(item->key, "GetCPULoad")) { - cna_config_bool_to_flag(item, &cfg_system->flags, CFG_SYSTEM_CPU); + cf_util_get_flag(item, &cfg_system->flags, CFG_SYSTEM_CPU); } else if (!strcasecmp(item->key, "GetInterfaces")) { - cna_config_bool_to_flag(item, &cfg_system->flags, CFG_SYSTEM_NET); + cf_util_get_flag(item, &cfg_system->flags, CFG_SYSTEM_NET); } else if (!strcasecmp(item->key, "GetDiskOps")) { - cna_config_bool_to_flag(item, &cfg_system->flags, CFG_SYSTEM_OPS); + cf_util_get_flag(item, &cfg_system->flags, CFG_SYSTEM_OPS); } else if (!strcasecmp(item->key, "GetDiskIO")) { - cna_config_bool_to_flag(item, &cfg_system->flags, CFG_SYSTEM_DISK); + cf_util_get_flag(item, &cfg_system->flags, CFG_SYSTEM_DISK); } else { WARNING("netapp plugin: The %s config option is not allowed within " "`System' blocks.", @@ -2842,11 +2806,11 @@ static int cna_register_host(host_config_t *host) /* {{{ */ static int cna_config_host(host_config_t *host, /* {{{ */ const oconfig_item_t *ci) { oconfig_item_t *item; - _Bool is_vfiler = 0; + bool is_vfiler = false; int status; if (!strcasecmp(ci->key, "VFiler")) - is_vfiler = 1; + is_vfiler = true; if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { WARNING("netapp plugin: \"%s\" needs exactly one string argument. Ignoring " diff --git a/src/netlink.c b/src/netlink.c index 1978eb43..a1f52a45 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -56,6 +56,7 @@ struct ir_link_stats_storage_s { uint64_t tx_dropped; uint64_t multicast; uint64_t collisions; + uint64_t rx_nohandler; uint64_t rx_length_errors; uint64_t rx_over_errors; @@ -91,12 +92,12 @@ struct qos_stats { }; static int ir_ignorelist_invert = 1; -static ir_ignorelist_t *ir_ignorelist_head = NULL; +static ir_ignorelist_t *ir_ignorelist_head; static struct mnl_socket *nl; -static char **iflist = NULL; -static size_t iflist_len = 0; +static char **iflist; +static size_t iflist_len; static const char *config_keys[] = {"Interface", "VerboseInterface", "QDisc", "Class", @@ -253,6 +254,10 @@ static void check_ignorelist_and_submit(const char *dev, submit_two(dev, "if_dropped", NULL, stats->rx_dropped, stats->tx_dropped); submit_one(dev, "if_multicast", NULL, stats->multicast); submit_one(dev, "if_collisions", NULL, stats->collisions); +#if defined(HAVE_STRUCT_RTNL_LINK_STATS_RX_NOHANDLER) || \ + defined(HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER) + submit_one(dev, "if_rx_nohandler", NULL, stats->rx_nohandler); +#endif submit_one(dev, "if_rx_errors", "length", stats->rx_length_errors); submit_one(dev, "if_rx_errors", "over", stats->rx_over_errors); @@ -304,6 +309,9 @@ static void check_ignorelist_and_submit64(const char *dev, struct ir_link_stats_storage_s s; COPY_RTNL_LINK_STATS(&s, stats); +#ifdef HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER + COPY_RTNL_LINK_VALUE(&s, stats, rx_nohandler); +#endif check_ignorelist_and_submit(dev, &s); } @@ -314,6 +322,9 @@ static void check_ignorelist_and_submit32(const char *dev, struct ir_link_stats_storage_s s; COPY_RTNL_LINK_STATS(&s, stats); +#ifdef HAVE_STRUCT_RTNL_LINK_STATS_RX_NOHANDLER + COPY_RTNL_LINK_VALUE(&s, stats, rx_nohandler); +#endif check_ignorelist_and_submit(dev, &s); } @@ -357,10 +368,10 @@ static int link_filter_cb(const struct nlmsghdr *nlh, if (mnl_attr_get_type(attr) != IFLA_STATS64) continue; - if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*stats.stats64)) < 0) { - ERROR("netlink plugin: link_filter_cb: IFLA_STATS64 mnl_attr_validate2 " - "failed: %s", - STRERRNO); + uint16_t attr_len = mnl_attr_get_payload_len(attr); + if (attr_len < sizeof(*stats.stats64)) { + ERROR("netlink plugin: link_filter_cb: IFLA_STATS64 attribute has " + "insufficient data."); return MNL_CB_ERROR; } stats.stats64 = mnl_attr_get_payload(attr); @@ -374,10 +385,10 @@ static int link_filter_cb(const struct nlmsghdr *nlh, if (mnl_attr_get_type(attr) != IFLA_STATS) continue; - if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, sizeof(*stats.stats32)) < 0) { - ERROR("netlink plugin: link_filter_cb: IFLA_STATS mnl_attr_validate2 " - "failed: %s", - STRERRNO); + uint16_t attr_len = mnl_attr_get_payload_len(attr); + if (attr_len < sizeof(*stats.stats32)) { + ERROR("netlink plugin: link_filter_cb: IFLA_STATS attribute has " + "insufficient data."); return MNL_CB_ERROR; } stats.stats32 = mnl_attr_get_payload(attr); @@ -438,7 +449,7 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) { const char *tc_type; char tc_inst[DATA_MAX_NAME_LEN]; - _Bool stats_submitted = 0; + bool stats_submitted = false; if (nlh->nlmsg_type == RTM_NEWQDISC) tc_type = "qdisc"; @@ -528,9 +539,15 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) { if (q_stats.bs != NULL || q_stats.qs != NULL) { char type_instance[DATA_MAX_NAME_LEN]; - stats_submitted = 1; + stats_submitted = true; - snprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type, tc_inst); + int r = snprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type, + tc_inst); + if ((size_t)r >= sizeof(type_instance)) { + ERROR("netlink plugin: type_instance truncated to %zu bytes, need %d", + sizeof(type_instance), r); + return MNL_CB_ERROR; + } if (q_stats.bs != NULL) { submit_one(dev, "ipt_bytes", type_instance, q_stats.bs->bytes); @@ -563,7 +580,13 @@ static int qos_filter_cb(const struct nlmsghdr *nlh, void *args) { if (!stats_submitted && ts != NULL) { char type_instance[DATA_MAX_NAME_LEN]; - snprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type, tc_inst); + int r = snprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type, + tc_inst); + if ((size_t)r >= sizeof(type_instance)) { + ERROR("netlink plugin: type_instance truncated to %zu bytes, need %d", + sizeof(type_instance), r); + return MNL_CB_ERROR; + } submit_one(dev, "ipt_bytes", type_instance, ts->bytes); submit_one(dev, "ipt_packets", type_instance, ts->packets); diff --git a/src/network.c b/src/network.c index fcacd38a..84ba00b5 100644 --- a/src/network.c +++ b/src/network.c @@ -261,30 +261,30 @@ typedef struct receive_list_entry_s receive_list_entry_t; /* * Private variables */ -static int network_config_ttl = 0; +static int network_config_ttl; /* Ethernet - (IPv6 + UDP) = 1500 - (40 + 8) = 1452 */ static size_t network_config_packet_size = 1452; -static _Bool network_config_forward = 0; -static _Bool network_config_stats = 0; +static bool network_config_forward; +static bool network_config_stats; -static sockent_t *sending_sockets = NULL; +static sockent_t *sending_sockets; -static receive_list_entry_t *receive_list_head = NULL; -static receive_list_entry_t *receive_list_tail = NULL; +static receive_list_entry_t *receive_list_head; +static receive_list_entry_t *receive_list_tail; static pthread_mutex_t receive_list_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t receive_list_cond = PTHREAD_COND_INITIALIZER; -static uint64_t receive_list_length = 0; +static uint64_t receive_list_length; -static sockent_t *listen_sockets = NULL; -static struct pollfd *listen_sockets_pollfd = NULL; -static size_t listen_sockets_num = 0; +static sockent_t *listen_sockets; +static struct pollfd *listen_sockets_pollfd; +static size_t listen_sockets_num; /* The receive and dispatch threads will run as long as `listen_loop' is set to * zero. */ -static int listen_loop = 0; -static int receive_thread_running = 0; +static int listen_loop; +static int receive_thread_running; static pthread_t receive_thread_id; -static int dispatch_thread_running = 0; +static int dispatch_thread_running; static pthread_t dispatch_thread_id; /* Buffer in which to-be-sent network packets are constructed. */ @@ -301,20 +301,20 @@ static pthread_mutex_t send_buffer_lock = PTHREAD_MUTEX_INITIALIZER; * example). Only if neither is true, the stats_lock is acquired. The counters * are always read without holding a lock in the hope that writing 8 bytes to * memory is an atomic operation. */ -static derive_t stats_octets_rx = 0; -static derive_t stats_octets_tx = 0; -static derive_t stats_packets_rx = 0; -static derive_t stats_packets_tx = 0; -static derive_t stats_values_dispatched = 0; -static derive_t stats_values_not_dispatched = 0; -static derive_t stats_values_sent = 0; -static derive_t stats_values_not_sent = 0; +static derive_t stats_octets_rx; +static derive_t stats_octets_tx; +static derive_t stats_packets_rx; +static derive_t stats_packets_tx; +static derive_t stats_values_dispatched; +static derive_t stats_values_not_dispatched; +static derive_t stats_values_sent; +static derive_t stats_values_not_sent; static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER; /* * Private functions */ -static _Bool check_receive_okay(const value_list_t *vl) /* {{{ */ +static bool check_receive_okay(const value_list_t *vl) /* {{{ */ { uint64_t time_sent = 0; int status; @@ -327,11 +327,11 @@ static _Bool check_receive_okay(const value_list_t *vl) /* {{{ */ return 0; return 1; -} /* }}} _Bool check_receive_okay */ +} /* }}} bool check_receive_okay */ -static _Bool check_send_okay(const value_list_t *vl) /* {{{ */ +static bool check_send_okay(const value_list_t *vl) /* {{{ */ { - _Bool received = 0; + bool received = 0; int status; if (network_config_forward) @@ -353,22 +353,22 @@ static _Bool check_send_okay(const value_list_t *vl) /* {{{ */ /* By default, only *send* value lists that were not *received* by the * network plugin. */ return !received; -} /* }}} _Bool check_send_okay */ +} /* }}} bool check_send_okay */ -static _Bool check_notify_received(const notification_t *n) /* {{{ */ +static bool check_notify_received(const notification_t *n) /* {{{ */ { for (notification_meta_t *ptr = n->meta; ptr != NULL; ptr = ptr->next) if ((strcmp("network:received", ptr->name) == 0) && (ptr->type == NM_TYPE_BOOLEAN)) - return (_Bool)ptr->nm_value.nm_boolean; + return (bool)ptr->nm_value.nm_boolean; return 0; -} /* }}} _Bool check_notify_received */ +} /* }}} bool check_notify_received */ -static _Bool check_send_notify_okay(const notification_t *n) /* {{{ */ +static bool check_send_notify_okay(const notification_t *n) /* {{{ */ { static c_complain_t complain_forwarding = C_COMPLAIN_INIT_STATIC; - _Bool received = 0; + bool received = 0; if (n->meta == NULL) return 1; @@ -388,7 +388,7 @@ static _Bool check_send_notify_okay(const notification_t *n) /* {{{ */ /* By default, only *send* value lists that were not *received* by the * network plugin. */ return !received; -} /* }}} _Bool check_send_notify_okay */ +} /* }}} bool check_send_notify_okay */ static int network_dispatch_values(value_list_t *vl, /* {{{ */ const char *username) { @@ -1113,7 +1113,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ void **ret_buffer, size_t *ret_buffer_size, int flags) { - static int warning_has_been_printed = 0; + static int warning_has_been_printed; char *buffer; size_t buffer_size; @@ -1268,7 +1268,7 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ void **ret_buffer, size_t *ret_buffer_size, int flags) { - static int warning_has_been_printed = 0; + static int warning_has_been_printed; char *buffer; size_t buffer_size; @@ -1924,7 +1924,7 @@ static int sockent_client_connect(sockent_t *se) /* {{{ */ struct sockent_client *client; struct addrinfo *ai_list; int status; - _Bool reconnect = 0; + bool reconnect = false; cdtime_t now; if ((se == NULL) || (se->type != SOCKENT_TYPE_CLIENT)) @@ -1938,7 +1938,7 @@ static int sockent_client_connect(sockent_t *se) /* {{{ */ "next_resolve_reconnect = %lf", CDTIME_T_TO_DOUBLE(client->resolve_interval), CDTIME_T_TO_DOUBLE(client->next_resolve_reconnect)); - reconnect = 1; + reconnect = true; } if (client->fd >= 0 && !reconnect) /* already connected and not stale*/ @@ -3096,13 +3096,13 @@ static int network_stats_read(void) /* {{{ */ } /* }}} int network_stats_read */ static int network_init(void) { - static _Bool have_init = 0; + static bool have_init; /* Check if we were already initialized. If so, just return - there's * nothing more to do (for now, that is). */ if (have_init) return 0; - have_init = 1; + have_init = true; if (network_config_stats) plugin_register_read("network", network_stats_read); diff --git a/src/nfs.c b/src/nfs.c index f50a3524..e1987f1f 100644 --- a/src/nfs.c +++ b/src/nfs.c @@ -33,9 +33,9 @@ static const char *config_keys[] = {"ReportV2", "ReportV3", "ReportV4"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static _Bool report_v2 = 1; -static _Bool report_v3 = 1; -static _Bool report_v4 = 1; +static bool report_v2 = true; +static bool report_v3 = true; +static bool report_v4 = true; /* see /proc/net/rpc/nfs @@ -409,7 +409,7 @@ static int nfs_submit_fields_safe(int nfs_version, const char *instance, static int nfs_submit_nfs4_server(const char *instance, char **fields, size_t fields_num) { - static int suppress_warning = 0; + static int suppress_warning; size_t proc4x_names_num; switch (fields_num) { @@ -451,7 +451,7 @@ static int nfs_submit_nfs4_client(const char *instance, char **fields, size_t fields_num) { size_t proc40_names_num, proc4x_names_num; - static int suppress_warning = 0; + static int suppress_warning; switch (fields_num) { case 34: diff --git a/src/nginx.c b/src/nginx.c index 88118b9b..e5ca89c0 100644 --- a/src/nginx.c +++ b/src/nginx.c @@ -33,18 +33,18 @@ #include -static char *url = NULL; -static char *user = NULL; -static char *pass = NULL; -static char *verify_peer = NULL; -static char *verify_host = NULL; -static char *cacert = NULL; -static char *timeout = NULL; +static char *url; +static char *user; +static char *pass; +static char *verify_peer; +static char *verify_host; +static char *cacert; +static char *timeout; -static CURL *curl = NULL; +static CURL *curl; static char nginx_buffer[16384]; -static size_t nginx_buffer_len = 0; +static size_t nginx_buffer_len; static char nginx_curl_error[CURL_ERROR_SIZE]; static const char *config_keys[] = { diff --git a/src/notify_email.c b/src/notify_email.c index 52cc8384..6b32ad9a 100644 --- a/src/notify_email.c +++ b/src/notify_email.c @@ -38,19 +38,19 @@ static const char *config_keys[] = {"SMTPServer", "SMTPPort", "SMTPUser", static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); static char **recipients; -static int recipients_len = 0; +static int recipients_len; static smtp_session_t session; static pthread_mutex_t session_lock = PTHREAD_MUTEX_INITIALIZER; static smtp_message_t message; -static auth_context_t authctx = NULL; +static auth_context_t authctx; static int smtp_port = 25; -static char *smtp_host = NULL; -static char *smtp_user = NULL; -static char *smtp_password = NULL; -static char *email_from = NULL; -static char *email_subject = NULL; +static char *smtp_host; +static char *smtp_user; +static char *smtp_password; +static char *email_from; +static char *email_subject; #define DEFAULT_SMTP_HOST "localhost" #define DEFAULT_SMTP_FROM "root@localhost" diff --git a/src/ntpd.c b/src/ntpd.c index ed3c0422..ef634988 100644 --- a/src/ntpd.c +++ b/src/ntpd.c @@ -56,17 +56,17 @@ static const char *config_keys[] = {"Host", "Port", "ReverseLookups", "IncludeUnitID"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static _Bool do_reverse_lookups = 1; +static bool do_reverse_lookups = true; /* This option only exists for backward compatibility. If it is false and two * ntpd peers use the same refclock driver, the plugin will try to write * simultaneous measurements from both to the same type instance. */ -static _Bool include_unit_id = 0; +static bool include_unit_id; #define NTPD_DEFAULT_HOST "localhost" #define NTPD_DEFAULT_PORT "123" static int sock_descr = -1; -static char *ntpd_host = NULL; +static char *ntpd_host; static char ntpd_port[16]; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -251,7 +251,7 @@ static const char *refclock_names[] = { "CHRONOLOG", "DUMBCLOCK", "ULINK_M320", "PCF", /* 32-35 */ "WWV_AUDIO", "GPS_FG", "HOPF_S", "HOPF_P", /* 36-39 */ "JJY", "TT_IRIG", "GPS_ZYFER", "GPS_RIPENCC", /* 40-43 */ - "NEOCLK4X" /* 44 */ + "NEOCLK4X", "PCI_TSYNC", "GPSD_JSON" /* 44-46 */ }; static size_t refclock_names_num = STATIC_ARRAY_SIZE(refclock_names); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -272,14 +272,14 @@ static int ntpd_config(const char *key, const char *value) { sstrncpy(ntpd_port, value, sizeof(ntpd_port)); } else if (strcasecmp(key, "ReverseLookups") == 0) { if (IS_TRUE(value)) - do_reverse_lookups = 1; + do_reverse_lookups = true; else - do_reverse_lookups = 0; + do_reverse_lookups = false; } else if (strcasecmp(key, "IncludeUnitID") == 0) { if (IS_TRUE(value)) - include_unit_id = 1; + include_unit_id = true; else - include_unit_id = 0; + include_unit_id = false; } else { return -1; } @@ -717,7 +717,7 @@ ntpd_get_refclock_id(struct info_peer_summary const *peer_info) { static int ntpd_get_name_from_address(char *buffer, size_t buffer_size, struct info_peer_summary const *peer_info, - _Bool do_reverse_lookup) { + bool do_reverse_lookup) { struct sockaddr_storage sa = {0}; socklen_t sa_len; int flags = 0; @@ -779,17 +779,6 @@ static int ntpd_get_name_refclock(char *buffer, size_t buffer_size, return 0; } /* int ntpd_get_name_refclock */ -static int ntpd_get_name(char *buffer, size_t buffer_size, - struct info_peer_summary const *peer_info) { - uint32_t addr = ntohl(peer_info->srcadr); - - if (!peer_info->v6_flag && ((addr & REFCLOCK_MASK) == REFCLOCK_ADDR)) - return ntpd_get_name_refclock(buffer, buffer_size, peer_info); - else - return ntpd_get_name_from_address(buffer, buffer_size, peer_info, - do_reverse_lookups); -} /* int ntpd_addr_to_name */ - static int ntpd_read(void) { struct info_kernel *ik; int ik_num; @@ -877,7 +866,15 @@ static int ntpd_read(void) { ptr = ps + i; - status = ntpd_get_name(peername, sizeof(peername), ptr); + int is_refclock = !ptr->v6_flag && + ((ntohl(ptr->srcadr) & REFCLOCK_MASK) == REFCLOCK_ADDR); + + if (is_refclock) + status = ntpd_get_name_refclock(peername, sizeof(peername), ptr); + else + status = ntpd_get_name_from_address(peername, sizeof(peername), ptr, + do_reverse_lookups); + if (status != 0) { ERROR("ntpd plugin: Determining name of peer failed."); continue; @@ -895,6 +892,8 @@ static int ntpd_read(void) { M_LFPTOD(ntohl(ptr->offset_int), ntohl(ptr->offset_frc), offset); DEBUG("peer %i:\n" + " is_refclock= %d\n" + " refclock_id= %d\n" " peername = %s\n" " srcadr = 0x%08x\n" " reach = 0%03o\n" @@ -903,16 +902,19 @@ static int ntpd_read(void) { " offset_frc = %i\n" " offset = %f\n" " dispersion = %f\n", - i, peername, ntohl(ptr->srcadr), ptr->reach, ntpd_read_fp(ptr->delay), + i, is_refclock, (is_refclock > 0) ? refclock_id : 0, peername, + ntohl(ptr->srcadr), ptr->reach, ntpd_read_fp(ptr->delay), ntohl(ptr->offset_int), ntohl(ptr->offset_frc), offset, ntpd_read_fp(ptr->dispersion)); - if (refclock_id != - 1) /* not the system clock (offset will always be zero.. */ - ntpd_submit_reach("time_offset", peername, ptr->reach, offset); ntpd_submit_reach("time_dispersion", peername, ptr->reach, ntpd_read_fp(ptr->dispersion)); - if (refclock_id == 0) /* not a reference clock */ + + /* not the system clock (offset will always be zero) */ + if (!(is_refclock && refclock_id == 1)) + ntpd_submit_reach("time_offset", peername, ptr->reach, offset); + + if (!is_refclock) /* not a reference clock */ ntpd_submit_reach("delay", peername, ptr->reach, ntpd_read_fp(ptr->delay)); } diff --git a/src/nut.c b/src/nut.c index 58c7d797..997d1a50 100644 --- a/src/nut.c +++ b/src/nut.c @@ -53,11 +53,11 @@ struct nut_ups_s { static const char *config_keys[] = {"UPS", "FORCESSL", "VERIFYPEER", "CAPATH", "CONNECTTIMEOUT"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static int force_ssl = 0; // Initialized to default of 0 (false) -static int verify_peer = 0; // Initialized to default of 0 (false) +static int force_ssl; // Initialized to default of 0 (false) +static int verify_peer; // Initialized to default of 0 (false) static int ssl_flags = UPSCLI_CONN_TRYSSL; static int connect_timeout = -1; -static char *ca_path = NULL; +static char *ca_path; static int nut_read(user_data_t *user_data); @@ -144,8 +144,7 @@ static int nut_verify_peer(const char *value) { static int nut_ca_path(const char *value) { if (value != NULL && strcmp(value, "") != 0) { - ca_path = malloc(strlen(value) + 1); - strncpy(ca_path, value, (strlen(value) + 1)); + ca_path = strdup(value); } else { ca_path = NULL; // Should alread be set to NULL from initialization } diff --git a/src/olsrd.c b/src/olsrd.c index eb640771..df052889 100644 --- a/src/olsrd.c +++ b/src/olsrd.c @@ -41,8 +41,8 @@ static const char *config_keys[] = {"Host", "Port", "CollectLinks", "CollectRoutes", "CollectTopology"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static char *config_node = NULL; -static char *config_service = NULL; +static char *config_node; +static char *config_service; #define OLSRD_WANT_NOT 0 #define OLSRD_WANT_SUMMARY 1 diff --git a/src/onewire.c b/src/onewire.c index c2037518..49c6aa37 100644 --- a/src/onewire.c +++ b/src/onewire.c @@ -86,9 +86,9 @@ static ow_family_features_t ow_family_features[] = { /* features_num = */ 1}}; static int ow_family_features_num = STATIC_ARRAY_SIZE(ow_family_features); -static char *device_g = NULL; -static cdtime_t ow_interval = 0; -static _Bool direct_access = 0; +static char *device_g; +static cdtime_t ow_interval; +static bool direct_access; static const char *config_keys[] = {"Device", "IgnoreSelected", "Sensor", "Interval"}; @@ -96,7 +96,7 @@ static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); static ignorelist_t *sensor_list; -static _Bool regex_direct_initialized = 0; +static bool regex_direct_initialized; static regex_t regex_direct; /** @@ -109,7 +109,7 @@ typedef struct direct_access_element_s { struct direct_access_element_s *next; /**< Next in the list */ } direct_access_element_t; -static direct_access_element_t *direct_list = NULL; +static direct_access_element_t *direct_list; /* =================================================================================== */ @@ -171,7 +171,7 @@ static int direct_list_insert(const char *config) { direct_list_element_free(element); return 1; } - regex_direct_initialized = 1; + regex_direct_initialized = true; DEBUG("onewire plugin: Compiled regex!!"); } @@ -246,7 +246,7 @@ static int cow_load_config(const char *key, const char *value) { } } else { DEBUG("onewire plugin: %s is a direct access", value); - direct_access = 1; + direct_access = true; } } else if (strcasecmp(key, "IgnoreSelected") == 0) { ignorelist_set_invert(sensor_list, 1); diff --git a/src/openldap.c b/src/openldap.c index afe2479e..3897cd16 100644 --- a/src/openldap.c +++ b/src/openldap.c @@ -47,10 +47,10 @@ struct cldap_s /* {{{ */ char *password; char *cacert; char *host; - _Bool starttls; + bool starttls; int timeout; char *url; - _Bool verifyhost; + bool verifyhost; int version; LDAP *ld; @@ -105,12 +105,12 @@ static int cldap_init_host(cldap_t *st) /* {{{ */ if (st->cacert != NULL) ldap_set_option(st->ld, LDAP_OPT_X_TLS_CACERTFILE, st->cacert); - if (st->verifyhost == 0) { + if (st->verifyhost == false) { int never = LDAP_OPT_X_TLS_NEVER; ldap_set_option(st->ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &never); } - if (st->starttls != 0) { + if (st->starttls) { rc = ldap_start_tls_s(st->ld, NULL, NULL); if (rc != LDAP_SUCCESS) { ERROR("openldap plugin: Failed to start tls on %s: %s", st->url, @@ -397,9 +397,9 @@ static int cldap_config_add(oconfig_item_t *ci) /* {{{ */ return status; } - st->starttls = 0; + st->starttls = false; st->timeout = (long)CDTIME_T_TO_TIME_T(plugin_get_interval()); - st->verifyhost = 1; + st->verifyhost = true; st->version = LDAP_VERSION3; for (int i = 0; i < ci->children_num; i++) { diff --git a/src/openvpn.c b/src/openvpn.c index 608bef60..193a9b43 100644 --- a/src/openvpn.c +++ b/src/openvpn.c @@ -80,10 +80,10 @@ struct vpn_status_s { }; typedef struct vpn_status_s vpn_status_t; -static _Bool new_naming_schema = 0; -static _Bool collect_compression = 1; -static _Bool collect_user_count = 0; -static _Bool collect_individual_users = 1; +static bool new_naming_schema; +static bool collect_compression = true; +static bool collect_user_count; +static bool collect_individual_users = true; static const char *config_keys[] = { "StatusFile", "Compression", /* old, deprecated name */ @@ -247,7 +247,7 @@ static int multi1_read(const char *name, FILE *fh) { char *fields[10]; const int max_fields = STATIC_ARRAY_SIZE(fields); long long sum_users = 0; - _Bool found_header = 0; + bool found_header = false; /* read the file until the "ROUTING TABLE" line is found (no more info after) */ @@ -256,12 +256,12 @@ static int multi1_read(const char *name, FILE *fh) { break; if (strcmp(buffer, V1HEADER) == 0) { - found_header = 1; + found_header = true; continue; } /* skip the first lines until the client list section is found */ - if (found_header == 0) + if (found_header == false) /* we can't start reading data until this string is found */ continue; @@ -292,7 +292,7 @@ static int multi1_read(const char *name, FILE *fh) { if (ferror(fh)) return -1; - if (found_header == 0) { + if (found_header == false) { NOTICE("openvpn plugin: Unknown file format in instance %s, please " "report this as bug. Make sure to include " "your status file, so the plugin can " @@ -320,7 +320,7 @@ static int multi2_read(const char *name, FILE *fh) { const int max_fields = STATIC_ARRAY_SIZE(fields); long long sum_users = 0; - _Bool found_header = 0; + bool found_header = false; int idx_cname = 0; int idx_bytes_recv = 0; int idx_bytes_sent = 0; @@ -330,7 +330,7 @@ static int multi2_read(const char *name, FILE *fh) { int fields_num = openvpn_strsplit(buffer, fields, max_fields); /* Try to find section header */ - if (found_header == 0) { + if (found_header == false) { if (fields_num < 2) continue; if (strcmp(fields[0], "HEADER") != 0) @@ -358,7 +358,7 @@ static int multi2_read(const char *name, FILE *fh) { /* Data row has 1 field ("HEADER") less than header row */ columns = fields_num - 1; - found_header = 1; + found_header = true; continue; } @@ -404,7 +404,7 @@ static int multi2_read(const char *name, FILE *fh) { if (ferror(fh)) return -1; - if (found_header == 0) { + if (found_header == false) { NOTICE("openvpn plugin: Unknown file format in instance %s, please " "report this as bug. Make sure to include " "your status file, so the plugin can " @@ -519,29 +519,29 @@ static int openvpn_config(const char *key, const char *value) { (strcasecmp("Compression", key) == 0)) /* old, deprecated name */ { if (IS_FALSE(value)) - collect_compression = 0; + collect_compression = false; else - collect_compression = 1; + collect_compression = true; } /* if (strcasecmp ("CollectCompression", key) == 0) */ else if (strcasecmp("ImprovedNamingSchema", key) == 0) { if (IS_TRUE(value)) { DEBUG("openvpn plugin: using the new naming schema"); - new_naming_schema = 1; + new_naming_schema = true; } else { - new_naming_schema = 0; + new_naming_schema = false; } } /* if (strcasecmp ("ImprovedNamingSchema", key) == 0) */ else if (strcasecmp("CollectUserCount", key) == 0) { if (IS_TRUE(value)) - collect_user_count = 1; + collect_user_count = true; else - collect_user_count = 0; + collect_user_count = false; } /* if (strcasecmp("CollectUserCount", key) == 0) */ else if (strcasecmp("CollectIndividualUsers", key) == 0) { if (IS_FALSE(value)) - collect_individual_users = 0; + collect_individual_users = false; else - collect_individual_users = 1; + collect_individual_users = true; } /* if (strcasecmp("CollectIndividualUsers", key) == 0) */ else { return -1; diff --git a/src/oracle.c b/src/oracle.c index bf6aef58..4bca8387 100644 --- a/src/oracle.c +++ b/src/oracle.c @@ -75,10 +75,10 @@ typedef struct o_database_s o_database_t; /* * Global variables */ -static udb_query_t **queries = NULL; -static size_t queries_num = 0; -static o_database_t **databases = NULL; -static size_t databases_num = 0; +static udb_query_t **queries; +static size_t queries_num; +static o_database_t **databases; +static size_t databases_num; OCIEnv *oci_env = NULL; OCIError *oci_error = NULL; @@ -583,6 +583,8 @@ static int o_read_database_query(o_database_t *db, /* {{{ */ } } /* }}} while (42) */ + udb_query_finish_result(q, prep_area); + /* DEBUG ("oracle plugin: o_read_database_query: This statement succeeded: * %s", q->statement); */ FREE_ALL; diff --git a/src/ovs_events.c b/src/ovs_events.c index ef59b4c2..ba3238b6 100644 --- a/src/ovs_events.c +++ b/src/ovs_events.c @@ -66,7 +66,7 @@ typedef struct ovs_events_iface_list_s ovs_events_iface_list_t; /* OVS events configuration data */ struct ovs_events_config_s { - _Bool send_notification; /* sent notification to collectd? */ + bool send_notification; /* sent notification to collectd? */ char ovs_db_node[OVS_DB_ADDR_NODE_SIZE]; /* OVS DB node */ char ovs_db_serv[OVS_DB_ADDR_SERVICE_SIZE]; /* OVS DB service */ char ovs_db_unix[OVS_DB_ADDR_UNIX_SIZE]; /* OVS DB unix socket path */ @@ -80,7 +80,7 @@ struct ovs_events_ctx_s { ovs_db_t *ovs_db; /* pointer to OVS DB instance */ ovs_events_config_t config; /* plugin config */ char *ovs_db_select_params; /* OVS DB select parameter request */ - _Bool is_db_available; /* specify whether OVS DB is available */ + bool is_db_available; /* specify whether OVS DB is available */ }; typedef struct ovs_events_ctx_s ovs_events_ctx_t; @@ -89,7 +89,7 @@ typedef struct ovs_events_ctx_s ovs_events_ctx_t; */ static ovs_events_ctx_t ovs_events_ctx = { .mutex = PTHREAD_MUTEX_INITIALIZER, - .config = {.send_notification = 1, /* send notification by default */ + .config = {.send_notification = true, /* send notification by default */ .ovs_db_node = "localhost", /* use default OVS DB node */ .ovs_db_serv = "6640"} /* use default OVS DB service */ }; @@ -231,7 +231,7 @@ static int ovs_events_config_get_interfaces(const oconfig_item_t *ci) { * in allocated memory. Returns negative value in case of error. */ static int ovs_events_plugin_config(oconfig_item_t *ci) { - _Bool dispatch_values = 0; + bool dispatch_values = false; for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; if (strcasecmp("SendNotification", child->key) == 0) { @@ -577,7 +577,7 @@ static void ovs_events_conn_initialize(ovs_db_t *pdb) { return; } } - OVS_EVENTS_CTX_LOCK { ovs_events_ctx.is_db_available = 1; } + OVS_EVENTS_CTX_LOCK { ovs_events_ctx.is_db_available = true; } DEBUG(OVS_EVENTS_PLUGIN ": OVS DB connection has been initialized"); } @@ -587,12 +587,12 @@ static void ovs_events_conn_terminate() { if (ovs_events_ctx.config.send_notification) ovs_events_dispatch_terminate_notification(msg); WARNING(OVS_EVENTS_PLUGIN ": %s", msg); - OVS_EVENTS_CTX_LOCK { ovs_events_ctx.is_db_available = 0; } + OVS_EVENTS_CTX_LOCK { ovs_events_ctx.is_db_available = false; } } /* Read OVS DB interface link status callback */ static int ovs_events_plugin_read(__attribute__((unused)) user_data_t *u) { - _Bool is_connected = 0; + bool is_connected = false; OVS_EVENTS_CTX_LOCK { is_connected = ovs_events_ctx.is_db_available; } if (is_connected) if (ovs_db_send_request(ovs_events_ctx.ovs_db, "transact", diff --git a/src/perl.c b/src/perl.c index 5ad99ee4..fffbc21d 100644 --- a/src/perl.c +++ b/src/perl.c @@ -33,21 +33,12 @@ /* do not automatically get the thread specific Perl interpreter */ #define PERL_NO_GET_CONTEXT -#define DONT_POISON_SPRINTF_YET 1 #include "collectd.h" - -#undef DONT_POISON_SPRINTF_YET - #include #include #include -#if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__ -#undef sprintf -#pragma GCC poison sprintf -#endif - #include /* Some versions of Perl define their own version of DEBUG... :-/ */ @@ -138,8 +129,8 @@ static int perl_flush(cdtime_t timeout, const char *identifier, typedef struct c_ithread_s { /* the thread's Perl interpreter */ PerlInterpreter *interp; - _Bool running; /* thread is inside Perl interpreter */ - _Bool shutdown; + bool running; /* thread is inside Perl interpreter */ + bool shutdown; pthread_t pthread; /* double linked list of threads */ @@ -183,17 +174,17 @@ extern char **environ; * private variables */ -static _Bool register_legacy_flush = 1; +static bool register_legacy_flush = true; /* if perl_threads != NULL perl_threads->head must * point to the "base" thread */ -static c_ithread_list_t *perl_threads = NULL; +static c_ithread_list_t *perl_threads; /* the key used to store each pthread's ithread */ static pthread_key_t perl_thr_key; -static int perl_argc = 0; -static char **perl_argv = NULL; +static int perl_argc; +static char **perl_argv; static char base_name[DATA_MAX_NAME_LEN] = ""; @@ -981,7 +972,7 @@ static int pplugin_dispatch_notification(pTHX_ HV *notif) { * Call perl sub with thread locking flags handled. */ static int call_pv_locked(pTHX_ const char *sub_name) { - _Bool old_running; + bool old_running; int ret; c_ithread_t *t = (c_ithread_t *)pthread_getspecific(perl_thr_key); @@ -989,7 +980,7 @@ static int call_pv_locked(pTHX_ const char *sub_name) { return 0; old_running = t->running; - t->running = 1; + t->running = true; if (t->shutdown) { t->running = old_running; @@ -1189,7 +1180,7 @@ static void c_ithread_destroy(c_ithread_t *ithread) { /* Mark as running to avoid deadlock: c_ithread_destroy -> log_debug -> perl_log() */ - ithread->running = 1; + ithread->running = true; log_debug("Shutting down Perl interpreter %p...", aTHX); #if COLLECT_DEBUG @@ -1275,8 +1266,8 @@ static c_ithread_t *c_ithread_create(PerlInterpreter *base) { } t->pthread = pthread_self(); - t->running = 0; - t->shutdown = 0; + t->running = false; + t->shutdown = false; perl_threads->tail = t; pthread_setspecific(perl_thr_key, (const void *)t); @@ -1642,23 +1633,23 @@ static void _plugin_register_generic_userdata(pTHX, int type, */ static XS(Collectd_plugin_register_read) { - return _plugin_register_generic_userdata(aTHX, PLUGIN_READ, "read"); + _plugin_register_generic_userdata(aTHX, PLUGIN_READ, "read"); } static XS(Collectd_plugin_register_write) { - return _plugin_register_generic_userdata(aTHX, PLUGIN_WRITE, "write"); + _plugin_register_generic_userdata(aTHX, PLUGIN_WRITE, "write"); } static XS(Collectd_plugin_register_log) { - return _plugin_register_generic_userdata(aTHX, PLUGIN_LOG, "log"); + _plugin_register_generic_userdata(aTHX, PLUGIN_LOG, "log"); } static XS(Collectd_plugin_register_notification) { - return _plugin_register_generic_userdata(aTHX, PLUGIN_NOTIF, "notification"); + _plugin_register_generic_userdata(aTHX, PLUGIN_NOTIF, "notification"); } static XS(Collectd_plugin_register_flush) { - return _plugin_register_generic_userdata(aTHX, PLUGIN_FLUSH, "flush"); + _plugin_register_generic_userdata(aTHX, PLUGIN_FLUSH, "flush"); } typedef int perl_unregister_function_t(const char *name); @@ -1685,8 +1676,6 @@ static void _plugin_unregister_generic(pTHX, perl_unregister_function_t *unreg, unreg(SvPV_nolen(ST(0))); XSRETURN_EMPTY; - - return; } /* static void _plugin_unregister_generic ( ... ) */ /* @@ -1700,24 +1689,24 @@ static void _plugin_unregister_generic(pTHX, perl_unregister_function_t *unreg, */ static XS(Collectd_plugin_unregister_read) { - return _plugin_unregister_generic(aTHX, plugin_unregister_read, "read"); + _plugin_unregister_generic(aTHX, plugin_unregister_read, "read"); } static XS(Collectd_plugin_unregister_write) { - return _plugin_unregister_generic(aTHX, plugin_unregister_write, "write"); + _plugin_unregister_generic(aTHX, plugin_unregister_write, "write"); } static XS(Collectd_plugin_unregister_log) { - return _plugin_unregister_generic(aTHX, plugin_unregister_log, "log"); + _plugin_unregister_generic(aTHX, plugin_unregister_log, "log"); } static XS(Collectd_plugin_unregister_notification) { - return _plugin_unregister_generic(aTHX, plugin_unregister_notification, - "notification"); + _plugin_unregister_generic(aTHX, plugin_unregister_notification, + "notification"); } static XS(Collectd_plugin_unregister_flush) { - return _plugin_unregister_generic(aTHX, plugin_unregister_flush, "flush"); + _plugin_unregister_generic(aTHX, plugin_unregister_flush, "flush"); } /* @@ -2276,7 +2265,7 @@ static int perl_shutdown(void) { * the thread as this will free the memory */ t = t->prev; - thr->shutdown = 1; + thr->shutdown = true; if (thr->running) { /* Give some time to thread to exit from Perl interpreter */ WARNING("perl shutdown: Thread is running inside Perl. Waiting."); diff --git a/src/pf.c b/src/pf.c index 1e4c465b..88a4c2d0 100644 --- a/src/pf.c +++ b/src/pf.c @@ -58,7 +58,7 @@ static char const *pf_scounters[SCNT_MAX + 1] = SCNT_NAMES; static char const *pf_device = "/dev/pf"; static void pf_submit(char const *type, char const *type_instance, uint64_t val, - _Bool is_gauge) { + bool is_gauge) { value_t values[1]; value_list_t vl = VALUE_LIST_INIT; @@ -103,19 +103,19 @@ static int pf_read(void) { for (int i = 0; i < PFRES_MAX; i++) pf_submit("pf_counters", pf_reasons[i], state.counters[i], - /* is gauge = */ 0); + /* is gauge = */ false); for (int i = 0; i < LCNT_MAX; i++) pf_submit("pf_limits", pf_lcounters[i], state.lcounters[i], - /* is gauge = */ 0); + /* is gauge = */ false); for (int i = 0; i < FCNT_MAX; i++) pf_submit("pf_state", pf_fcounters[i], state.fcounters[i], - /* is gauge = */ 0); + /* is gauge = */ false); for (int i = 0; i < SCNT_MAX; i++) pf_submit("pf_source", pf_scounters[i], state.scounters[i], - /* is gauge = */ 0); + /* is gauge = */ false); pf_submit("pf_states", "current", (uint32_t)state.states, - /* is gauge = */ 1); + /* is gauge = */ true); return 0; } /* int pf_read */ diff --git a/src/pinba.c b/src/pinba.c index 339988df..66b9cd1f 100644 --- a/src/pinba.c +++ b/src/pinba.c @@ -99,15 +99,15 @@ typedef struct pinba_statnode_s pinba_statnode_t; * Module global variables */ /* {{{ */ -static pinba_statnode_t *stat_nodes = NULL; -static unsigned int stat_nodes_num = 0; +static pinba_statnode_t *stat_nodes; +static unsigned int stat_nodes_num; static pthread_mutex_t stat_nodes_lock; -static char *conf_node = NULL; -static char *conf_service = NULL; +static char *conf_node; +static char *conf_service; -static _Bool collector_thread_running = 0; -static _Bool collector_thread_do_shutdown = 0; +static bool collector_thread_running; +static bool collector_thread_do_shutdown; static pthread_t collector_thread_id; /* }}} */ @@ -490,7 +490,7 @@ static void *collector_thread(void *arg) /* {{{ */ receive_loop(); memset(&collector_thread_id, 0, sizeof(collector_thread_id)); - collector_thread_running = 0; + collector_thread_running = false; pthread_exit(NULL); return NULL; } /* }}} void *collector_thread */ @@ -585,7 +585,7 @@ static int plugin_init(void) /* {{{ */ ERROR("pinba plugin: pthread_create(3) failed: %s", STRERRNO); return -1; } - collector_thread_running = 1; + collector_thread_running = true; return 0; } /* }}} */ @@ -596,15 +596,15 @@ static int plugin_shutdown(void) /* {{{ */ int status; DEBUG("pinba plugin: Shutting down collector thread."); - collector_thread_do_shutdown = 1; + collector_thread_do_shutdown = true; status = pthread_join(collector_thread_id, /* retval = */ NULL); if (status != 0) { ERROR("pinba plugin: pthread_join(3) failed: %s", STRERROR(status)); } - collector_thread_running = 0; - collector_thread_do_shutdown = 0; + collector_thread_running = false; + collector_thread_do_shutdown = false; } /* if (collector_thread_running) */ return 0; diff --git a/src/ping.c b/src/ping.c index 1ffd72b7..ffb16910 100644 --- a/src/ping.c +++ b/src/ping.c @@ -69,13 +69,14 @@ typedef struct hostlist_s hostlist_t; /* * Private variables */ -static hostlist_t *hostlist_head = NULL; +static hostlist_t *hostlist_head; -static char *ping_source = NULL; +static int ping_af = PING_DEF_AF; +static char *ping_source; #ifdef HAVE_OPING_1_3 -static char *ping_device = NULL; +static char *ping_device; #endif -static char *ping_data = NULL; +static char *ping_data; static int ping_ttl = PING_DEF_TTL; static double ping_interval = 1.0; static double ping_timeout = 0.9; @@ -83,11 +84,11 @@ static int ping_max_missed = -1; static pthread_mutex_t ping_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t ping_cond = PTHREAD_COND_INITIALIZER; -static int ping_thread_loop = 0; -static int ping_thread_error = 0; +static int ping_thread_loop; +static int ping_thread_error; static pthread_t ping_thread_id; -static const char *config_keys[] = {"Host", "SourceAddress", +static const char *config_keys[] = {"Host", "SourceAddress", "AddressFamily", #ifdef HAVE_OPING_1_3 "Device", #endif @@ -242,6 +243,12 @@ static void *ping_thread(void *arg) /* {{{ */ return (void *)-1; } + if (ping_af != PING_DEF_AF) { + if (ping_setopt(pingobj, PING_OPT_AF, &ping_af) != 0) + ERROR("ping plugin: Failed to set address family: %s", + ping_get_error(pingobj)); + } + if (ping_source != NULL) if (ping_setopt(pingobj, PING_OPT_SOURCE, (void *)ping_source) != 0) ERROR("ping plugin: Failed to set source address: %s", @@ -291,7 +298,7 @@ static void *ping_thread(void *arg) /* {{{ */ pthread_mutex_lock(&ping_lock); while (ping_thread_loop > 0) { - _Bool send_successful = 0; + bool send_successful = false; if (gettimeofday(&tv_begin, NULL) < 0) { ERROR("ping plugin: gettimeofday failed: %s", STRERRNO); @@ -307,7 +314,7 @@ static void *ping_thread(void *arg) /* {{{ */ ping_get_error(pingobj)); } else { c_release(LOG_NOTICE, &complaint, "ping plugin: ping_send succeeded."); - send_successful = 1; + send_successful = true; } pthread_mutex_lock(&ping_lock); @@ -468,6 +475,23 @@ static int ping_config(const char *key, const char *value) /* {{{ */ hl->latency_squared = 0.0; hl->next = hostlist_head; hostlist_head = hl; + } else if (strcasecmp(key, "AddressFamily") == 0) { + char *af = NULL; + int status = config_set_string(key, &af, value); + if (status != 0) + return status; + + if (strncmp(af, "any", 3) == 0) { + ping_af = AF_UNSPEC; + } else if (strncmp(af, "ipv4", 4) == 0) { + ping_af = AF_INET; + } else if (strncmp(af, "ipv6", 4) == 0) { + ping_af = AF_INET6; + } else { + WARNING("ping plugin: Ignoring invalid AddressFamily value %s", af); + } + free(af); + } else if (strcasecmp(key, "SourceAddress") == 0) { int status = config_set_string(key, &ping_source, value); if (status != 0) diff --git a/src/postgresql.c b/src/postgresql.c index 62b3d553..7c140e0a 100644 --- a/src/postgresql.c +++ b/src/postgresql.c @@ -102,7 +102,7 @@ typedef struct { typedef struct { char *name; char *statement; - _Bool store_rates; + bool store_rates; } c_psql_writer_t; typedef struct { @@ -155,14 +155,14 @@ static const char *const def_queries[] = { "table_states", "disk_io", "disk_usage"}; static int def_queries_num = STATIC_ARRAY_SIZE(def_queries); -static c_psql_database_t **databases = NULL; -static size_t databases_num = 0; +static c_psql_database_t **databases; +static size_t databases_num; -static udb_query_t **queries = NULL; -static size_t queries_num = 0; +static udb_query_t **queries; +static size_t queries_num; -static c_psql_writer_t *writers = NULL; -static size_t writers_num = 0; +static c_psql_writer_t *writers; +static size_t writers_num; static int c_psql_begin(c_psql_database_t *db) { PGresult *r = PQexec(db->conn, "BEGIN"); @@ -348,10 +348,10 @@ static int c_psql_connect(c_psql_database_t *db) { } /* c_psql_connect */ static int c_psql_check_connection(c_psql_database_t *db) { - _Bool init = 0; + bool init = false; if (!db->conn) { - init = 1; + init = true; /* trigger c_release() */ if (0 == db->conn_complaint.interval) @@ -664,7 +664,7 @@ static char *values_name_to_sqlarray(const data_set_t *ds, char *string, } /* values_name_to_sqlarray */ static char *values_type_to_sqlarray(const data_set_t *ds, char *string, - size_t string_len, _Bool store_rates) { + size_t string_len, bool store_rates) { char *str_ptr; size_t str_len; @@ -707,7 +707,7 @@ static char *values_type_to_sqlarray(const data_set_t *ds, char *string, static char *values_to_sqlarray(const data_set_t *ds, const value_list_t *vl, char *string, size_t string_len, - _Bool store_rates) { + bool store_rates) { char *str_ptr; size_t str_len; @@ -936,7 +936,7 @@ static int c_psql_flush(cdtime_t timeout, } /* c_psql_flush */ static int c_psql_shutdown(void) { - _Bool had_flush = 0; + bool had_flush = false; plugin_unregister_read_group("postgresql"); @@ -949,7 +949,7 @@ static int c_psql_shutdown(void) { if (!had_flush) { plugin_unregister_flush("postgresql"); - had_flush = 1; + had_flush = true; } plugin_unregister_flush(cb_name); @@ -1097,7 +1097,7 @@ static int c_psql_config_writer(oconfig_item_t *ci) { writer->name = sstrdup(ci->values[0].value.string); writer->statement = NULL; - writer->store_rates = 1; + writer->store_rates = true; for (int i = 0; i < ci->children_num; ++i) { oconfig_item_t *c = ci->children + i; @@ -1124,7 +1124,7 @@ static int c_psql_config_database(oconfig_item_t *ci) { c_psql_database_t *db; char cb_name[DATA_MAX_NAME_LEN]; - static _Bool have_flush = 0; + static bool have_flush; if ((1 != ci->values_num) || (OCONFIG_TYPE_STRING != ci->values[0].type)) { log_err(" expects a single string argument."); @@ -1221,7 +1221,7 @@ static int c_psql_config_database(oconfig_item_t *ci) { if (!have_flush) { /* flush all */ plugin_register_flush("postgresql", c_psql_flush, /* user data = */ NULL); - have_flush = 1; + have_flush = true; } /* flush this connection only */ @@ -1237,7 +1237,7 @@ static int c_psql_config_database(oconfig_item_t *ci) { } /* c_psql_config_database */ static int c_psql_config(oconfig_item_t *ci) { - static int have_def_config = 0; + static int have_def_config; if (0 == have_def_config) { oconfig_item_t *c; diff --git a/src/powerdns.c b/src/powerdns.c index 729a15b4..eb3ec537 100644 --- a/src/powerdns.c +++ b/src/powerdns.c @@ -304,10 +304,10 @@ static statname_lookup_t lookup_table[] = /* {{{ */ {"uptime", "uptime", NULL}}; /* }}} */ static int lookup_table_length = STATIC_ARRAY_SIZE(lookup_table); -static llist_t *list = NULL; +static llist_t *list; #define PDNS_LOCAL_SOCKPATH LOCALSTATEDIR "/run/" PACKAGE_NAME "-powerdns" -static char *local_sockpath = NULL; +static char *local_sockpath; /* TODO: Do this before 4.4: * - Update the collectd.conf(5) manpage. diff --git a/src/processes.c b/src/processes.c index d73d24a2..86e99c3a 100644 --- a/src/processes.c +++ b/src/processes.c @@ -198,20 +198,20 @@ typedef struct process_entry_s { derive_t io_syscw; derive_t io_diskr; derive_t io_diskw; - _Bool has_io; + bool has_io; derive_t cswitch_vol; derive_t cswitch_invol; - _Bool has_cswitch; + bool has_cswitch; #if HAVE_LIBTASKSTATS ts_delay_t delay; #endif - _Bool has_delay; + bool has_delay; - _Bool has_fd; + bool has_fd; - _Bool has_maps; + bool has_maps; } process_entry_t; typedef struct procstat_entry_s { @@ -284,22 +284,22 @@ typedef struct procstat { gauge_t delay_swapin; gauge_t delay_freepages; - _Bool report_fd_num; - _Bool report_maps_num; - _Bool report_ctx_switch; - _Bool report_delay; + bool report_fd_num; + bool report_maps_num; + bool report_ctx_switch; + bool report_delay; struct procstat *next; struct procstat_entry_s *instances; } procstat_t; -static procstat_t *list_head_g = NULL; +static procstat_t *list_head_g; -static _Bool want_init = 1; -static _Bool report_ctx_switch = 0; -static _Bool report_fd_num = 0; -static _Bool report_maps_num = 0; -static _Bool report_delay = 0; +static bool want_init = true; +static bool report_ctx_switch; +static bool report_fd_num; +static bool report_maps_num; +static bool report_delay; #if HAVE_THREAD_INFO static mach_port_t port_host_self; @@ -334,7 +334,7 @@ int getargs(void *processBuffer, int bufferLen, char *argsBuffer, int argsLen); #endif /* HAVE_PROCINFO_H */ #if HAVE_LIBTASKSTATS -static ts_t *taskstats_handle = NULL; +static ts_t *taskstats_handle; #endif /* put name of process from config to list_head_g tree @@ -909,7 +909,7 @@ static void ps_submit_proc_list(procstat_t *ps) { gauge_t const delay_factor = 1000000000.0; struct { - char *type_instance; + const char *type_instance; gauge_t rate_ns; } delay_metrics[] = { {"delay-cpu", ps->delay_cpu}, @@ -995,8 +995,9 @@ static int ps_read_tasks_status(process_entry_t *ps) { tpid = ent->d_name; - if (snprintf(filename, sizeof(filename), "/proc/%li/task/%s/status", ps->id, - tpid) >= sizeof(filename)) { + int r = snprintf(filename, sizeof(filename), "/proc/%li/task/%s/status", + ps->id, tpid); + if ((size_t)r >= sizeof(filename)) { DEBUG("Filename too long: `%s'", filename); continue; } @@ -1252,38 +1253,38 @@ static int ps_delay(process_entry_t *ps) { #endif static void ps_fill_details(const procstat_t *ps, process_entry_t *entry) { - if (entry->has_io == 0) { + if (entry->has_io == false) { ps_read_io(entry); - entry->has_io = 1; + entry->has_io = true; } if (ps->report_ctx_switch) { - if (entry->has_cswitch == 0) { + if (entry->has_cswitch == false) { ps_read_tasks_status(entry); - entry->has_cswitch = 1; + entry->has_cswitch = true; } } if (ps->report_maps_num) { int num_maps; - if (entry->has_maps == 0 && (num_maps = ps_count_maps(entry->id)) > 0) { + if (entry->has_maps == false && (num_maps = ps_count_maps(entry->id)) > 0) { entry->num_maps = num_maps; } - entry->has_maps = 1; + entry->has_maps = true; } if (ps->report_fd_num) { int num_fd; - if (entry->has_fd == 0 && (num_fd = ps_count_fd(entry->id)) > 0) { + if (entry->has_fd == false && (num_fd = ps_count_fd(entry->id)) > 0) { entry->num_fd = num_fd; } - entry->has_fd = 1; + entry->has_fd = true; } #if HAVE_LIBTASKSTATS if (ps->report_delay && !entry->has_delay) { if (ps_delay(entry) == 0) { - entry->has_delay = 1; + entry->has_delay = true; } } #endif @@ -1521,7 +1522,7 @@ static int read_fork_rate(void) { FILE *proc_stat; char buffer[1024]; value_t value; - _Bool value_valid = 0; + bool value_valid = 0; proc_stat = fopen("/proc/stat", "r"); if (proc_stat == NULL) { @@ -2137,7 +2138,7 @@ static int ps_read(void) { * filter out threads (duplicate PID entries). */ if ((proc_ptr == NULL) || (proc_ptr->ki_pid != procs[i].ki_pid)) { char cmdline[CMDLINE_BUFFER_SIZE] = ""; - _Bool have_cmdline = 0; + bool have_cmdline = 0; proc_ptr = &(procs[i]); /* Don't probe system processes and processes without arguments */ @@ -2292,7 +2293,7 @@ static int ps_read(void) { * filter out threads (duplicate PID entries). */ if ((proc_ptr == NULL) || (proc_ptr->p_pid != procs[i].p_pid)) { char cmdline[CMDLINE_BUFFER_SIZE] = ""; - _Bool have_cmdline = 0; + bool have_cmdline = 0; proc_ptr = &(procs[i]); /* Don't probe zombie processes */ @@ -2632,7 +2633,7 @@ static int ps_read(void) { read_fork_rate(); #endif /* KERNEL_SOLARIS */ - want_init = 0; + want_init = false; return 0; } /* int ps_read */ diff --git a/src/protocols.c b/src/protocols.c index a50539ef..59eb49a7 100644 --- a/src/protocols.c +++ b/src/protocols.c @@ -45,7 +45,7 @@ static const char *config_keys[] = { }; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static ignorelist_t *values_list = NULL; +static ignorelist_t *values_list; /* * Functions diff --git a/src/pyconfig.c b/src/pyconfig.c index c6e89306..4ba7e0d2 100644 --- a/src/pyconfig.c +++ b/src/pyconfig.c @@ -129,7 +129,7 @@ static int Config_init(PyObject *s, PyObject *args, PyObject *kwds) { static PyObject *Config_repr(PyObject *s) { Config *self = (Config *)s; PyObject *ret = NULL; - static PyObject *node_prefix = NULL, *root_prefix = NULL, *ending = NULL; + static PyObject *node_prefix, *root_prefix, *ending; /* This is ok because we have the GIL, so this is thread-save by default. */ if (node_prefix == NULL) diff --git a/src/python.c b/src/python.c index e60ba459..64db6985 100644 --- a/src/python.c +++ b/src/python.c @@ -241,7 +241,7 @@ static char CollectdError_doc[] = static pthread_t main_thread; static PyOS_sighandler_t python_sigint_handler; -static _Bool do_interactive = 0; +static bool do_interactive; /* This is our global thread state. Python saves some stuff in thread-local * storage. So if we allow the interpreter to run in the background @@ -257,8 +257,8 @@ static cpy_callback_t *cpy_init_callbacks; static cpy_callback_t *cpy_shutdown_callbacks; /* Make sure to hold the GIL while modifying these. */ -static int cpy_shutdown_triggered = 0; -static int cpy_num_callbacks = 0; +static int cpy_shutdown_triggered; +static int cpy_num_callbacks; static void cpy_destroy_user_data(void *data) { cpy_callback_t *c = data; @@ -448,7 +448,7 @@ static int cpy_write_callback(const data_set_t *ds, int64_t si; uint64_t ui; double d; - _Bool b; + bool b; type = meta_data_type(meta, table[i]); if (type == MD_TYPE_STRING) { @@ -703,9 +703,8 @@ static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) { for (size_t i = 0; i < ds->ds_num; ++i) { tuple = PyTuple_New(4); PyTuple_SET_ITEM(tuple, 0, cpy_string_to_unicode_or_bytes(ds->ds[i].name)); - PyTuple_SET_ITEM( - tuple, 1, - cpy_string_to_unicode_or_bytes(DS_TYPE_TO_STRING(ds->ds[i].type))); + PyTuple_SET_ITEM(tuple, 1, cpy_string_to_unicode_or_bytes( + DS_TYPE_TO_STRING(ds->ds[i].type))); PyTuple_SET_ITEM(tuple, 2, float_or_none(ds->ds[i].min)); PyTuple_SET_ITEM(tuple, 3, float_or_none(ds->ds[i].max)); PyList_SET_ITEM(list, i, tuple); @@ -775,8 +774,7 @@ static PyObject *cpy_register_generic_userdata(void *reg, void *handler, register_function(buf, handler, &(user_data_t){ - .data = c, - .free_func = cpy_destroy_user_data, + .data = c, .free_func = cpy_destroy_user_data, }); ++cpy_num_callbacks; @@ -819,8 +817,7 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args, /* group = */ "python", buf, cpy_read_callback, DOUBLE_TO_CDTIME_T(interval), &(user_data_t){ - .data = c, - .free_func = cpy_destroy_user_data, + .data = c, .free_func = cpy_destroy_user_data, }); ++cpy_num_callbacks; return cpy_string_to_unicode_or_bytes(buf); @@ -1200,9 +1197,8 @@ static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) { values = PyTuple_New(ci->values_num); /* New reference. */ for (int i = 0; i < ci->values_num; ++i) { if (ci->values[i].type == OCONFIG_TYPE_STRING) { - PyTuple_SET_ITEM( - values, i, - cpy_string_to_unicode_or_bytes(ci->values[i].value.string)); + PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes( + ci->values[i].value.string)); } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) { PyTuple_SET_ITEM(values, i, PyFloat_FromDouble(ci->values[i].value.number)); @@ -1366,7 +1362,7 @@ static int cpy_config(oconfig_item_t *ci) { #endif sfree(encoding); } else if (strcasecmp(item->key, "LogTraces") == 0) { - _Bool log_traces; + bool log_traces; if (cf_util_get_boolean(item, &log_traces) != 0) { status = 1; continue; diff --git a/src/pyvalues.c b/src/pyvalues.c index 7fe0a315..301df442 100644 --- a/src/pyvalues.c +++ b/src/pyvalues.c @@ -38,7 +38,7 @@ typedef struct { int (*add_signed_int)(void *, const char *, int64_t); int (*add_unsigned_int)(void *, const char *, uint64_t); int (*add_double)(void *, const char *, double); - int (*add_boolean)(void *, const char *, _Bool); + int (*add_boolean)(void *, const char *, bool); } cpy_build_meta_handler_t; #define FreeAll() \ @@ -52,9 +52,8 @@ typedef struct { static PyObject *cpy_common_repr(PyObject *s) { PyObject *ret, *tmp; - static PyObject *l_type = NULL, *l_type_instance = NULL, *l_plugin = NULL, - *l_plugin_instance = NULL; - static PyObject *l_host = NULL, *l_time = NULL; + static PyObject *l_type, *l_type_instance, *l_plugin, *l_plugin_instance; + static PyObject *l_host, *l_time; PluginData *self = (PluginData *)s; if (l_type == NULL) @@ -203,7 +202,7 @@ static int PluginData_init(PyObject *s, PyObject *args, PyObject *kwds) { static PyObject *PluginData_repr(PyObject *s) { PyObject *ret; - static PyObject *l_closing = NULL; + static PyObject *l_closing; if (l_closing == NULL) l_closing = cpy_string_to_unicode_or_bytes(")"); @@ -562,7 +561,7 @@ static int cpy_build_meta_generic(PyObject *meta, CPY_BUILD_META_FUNC(meta_type, func_prefix##_add_signed_int, int64_t) \ CPY_BUILD_META_FUNC(meta_type, func_prefix##_add_unsigned_int, uint64_t) \ CPY_BUILD_META_FUNC(meta_type, func_prefix##_add_double, double) \ - CPY_BUILD_META_FUNC(meta_type, func_prefix##_add_boolean, _Bool) \ + CPY_BUILD_META_FUNC(meta_type, func_prefix##_add_boolean, bool) \ \ static cpy_build_meta_handler_t cpy_##func_prefix = { \ .add_string = cpy_##func_prefix##_add_string, \ @@ -843,8 +842,7 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) { static PyObject *Values_repr(PyObject *s) { PyObject *ret, *tmp; - static PyObject *l_interval = NULL, *l_values = NULL, *l_meta = NULL, - *l_closing = NULL; + static PyObject *l_interval, *l_values, *l_meta, *l_closing; Values *self = (Values *)s; if (l_interval == NULL) @@ -1146,8 +1144,7 @@ static int Notification_setstring(PyObject *self, PyObject *value, void *data) { static PyObject *Notification_repr(PyObject *s) { PyObject *ret, *tmp; - static PyObject *l_severity = NULL, *l_message = NULL, *l_meta = NULL, - *l_closing = NULL; + static PyObject *l_severity, *l_message, *l_meta, *l_closing; Notification *self = (Notification *)s; if (l_severity == NULL) diff --git a/src/redis.c b/src/redis.c index 7c704ab5..36f57b09 100644 --- a/src/redis.c +++ b/src/redis.c @@ -28,17 +28,11 @@ #include #include -#ifndef HOST_NAME_MAX -#define HOST_NAME_MAX _POSIX_HOST_NAME_MAX -#endif - #define REDIS_DEF_HOST "localhost" #define REDIS_DEF_PASSWD "" #define REDIS_DEF_PORT 6379 -#define REDIS_DEF_TIMEOUT 2000 -#define REDIS_DEF_DB_COUNT 16 -#define MAX_REDIS_NODE_NAME 64 -#define MAX_REDIS_PASSWD_LENGTH 512 +#define REDIS_DEF_TIMEOUT_SEC 2 +#define REDIS_DEF_DB_COUNT 256 #define MAX_REDIS_VAL_SIZE 256 #define MAX_REDIS_QUERY 2048 @@ -60,60 +54,67 @@ struct redis_query_s { char query[MAX_REDIS_QUERY]; char type[DATA_MAX_NAME_LEN]; char instance[DATA_MAX_NAME_LEN]; + int database; + redis_query_t *next; }; struct redis_node_s; typedef struct redis_node_s redis_node_t; struct redis_node_s { - char name[MAX_REDIS_NODE_NAME]; - char host[HOST_NAME_MAX]; - char passwd[MAX_REDIS_PASSWD_LENGTH]; + char *name; + char *host; + char *passwd; int port; struct timeval timeout; + bool report_command_stats; + bool report_cpu_usage; + redisContext *redisContext; redis_query_t *queries; redis_node_t *next; }; -static redis_node_t *nodes_head = NULL; - -static int redis_node_add(const redis_node_t *rn) /* {{{ */ -{ - redis_node_t *rn_copy; - redis_node_t *rn_ptr; - - /* Check for duplicates first */ - for (rn_ptr = nodes_head; rn_ptr != NULL; rn_ptr = rn_ptr->next) - if (strcmp(rn->name, rn_ptr->name) == 0) - break; +static bool redis_have_instances; +static int redis_read(user_data_t *user_data); - if (rn_ptr != NULL) { - ERROR("redis plugin: A node with the name `%s' already exists.", rn->name); - return -1; - } +static void redis_node_free(void *arg) { + redis_node_t *rn = arg; + if (rn == NULL) + return; - rn_copy = malloc(sizeof(*rn_copy)); - if (rn_copy == NULL) { - ERROR("redis plugin: malloc failed adding redis_node to the tree."); - return -1; + redis_query_t *rq = rn->queries; + while (rq != NULL) { + redis_query_t *next = rq->next; + sfree(rq); + rq = next; } - memcpy(rn_copy, rn, sizeof(*rn_copy)); - rn_copy->next = NULL; + redisFree(rn->redisContext); + sfree(rn->name); + sfree(rn->host); + sfree(rn->passwd); + sfree(rn); +} /* void redis_node_free */ +static int redis_node_add(redis_node_t *rn) /* {{{ */ +{ DEBUG("redis plugin: Adding node \"%s\".", rn->name); - if (nodes_head == NULL) - nodes_head = rn_copy; - else { - rn_ptr = nodes_head; - while (rn_ptr->next != NULL) - rn_ptr = rn_ptr->next; - rn_ptr->next = rn_copy; - } + /* Disable automatic generation of default instance in the init callback. */ + redis_have_instances = true; - return 0; + char cb_name[sizeof("redis/") + DATA_MAX_NAME_LEN]; + snprintf(cb_name, sizeof(cb_name), "redis/%s", rn->name); + + return plugin_register_complex_read( + /* group = */ "redis", + /* name = */ cb_name, + /* callback = */ redis_read, + /* interval = */ 0, + &(user_data_t){ + .data = rn, .free_func = redis_node_free, + }); } /* }}} */ static redis_query_t *redis_config_query(oconfig_item_t *ci) /* {{{ */ @@ -137,6 +138,8 @@ static redis_query_t *redis_config_query(oconfig_item_t *ci) /* {{{ */ (void)sstrncpy(rq->instance, rq->query, sizeof(rq->instance)); replace_special(rq->instance, sizeof(rq->instance)); + rq->database = 0; + for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; @@ -145,6 +148,13 @@ static redis_query_t *redis_config_query(oconfig_item_t *ci) /* {{{ */ } else if (strcasecmp("Instance", option->key) == 0) { status = cf_util_get_string_buffer(option, rq->instance, sizeof(rq->instance)); + } else if (strcasecmp("Database", option->key) == 0) { + status = cf_util_get_int(option, &rq->database); + if (rq->database < 0) { + WARNING("redis plugin: The \"Database\" option must be positive " + "integer or zero"); + status = -1; + } } else { WARNING("redis plugin: unknown configuration option: %s", option->key); status = -1; @@ -160,44 +170,63 @@ err: static int redis_config_node(oconfig_item_t *ci) /* {{{ */ { - redis_query_t *rq; - int status; - int timeout; + redis_node_t *rn = calloc(1, sizeof(*rn)); + if (rn == NULL) { + ERROR("redis plugin: calloc failed adding node."); + return ENOMEM; + } - redis_node_t rn = {.port = REDIS_DEF_PORT, - .timeout.tv_usec = REDIS_DEF_TIMEOUT}; + rn->port = REDIS_DEF_PORT; + rn->timeout.tv_sec = REDIS_DEF_TIMEOUT_SEC; + rn->report_cpu_usage = true; - sstrncpy(rn.host, REDIS_DEF_HOST, sizeof(rn.host)); + rn->host = strdup(REDIS_DEF_HOST); + if (rn->host == NULL) { + ERROR("redis plugin: strdup failed adding node."); + sfree(rn); + return ENOMEM; + } - status = cf_util_get_string_buffer(ci, rn.name, sizeof(rn.name)); - if (status != 0) + int status = cf_util_get_string(ci, &rn->name); + if (status != 0) { + sfree(rn->host); + sfree(rn); return status; + } for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; if (strcasecmp("Host", option->key) == 0) - status = cf_util_get_string_buffer(option, rn.host, sizeof(rn.host)); + status = cf_util_get_string(option, &rn->host); else if (strcasecmp("Port", option->key) == 0) { status = cf_util_get_port_number(option); if (status > 0) { - rn.port = status; + rn->port = status; status = 0; } } else if (strcasecmp("Query", option->key) == 0) { - rq = redis_config_query(option); + redis_query_t *rq = redis_config_query(option); if (rq == NULL) { status = 1; } else { - rq->next = rn.queries; - rn.queries = rq; + rq->next = rn->queries; + rn->queries = rq; } } else if (strcasecmp("Timeout", option->key) == 0) { + int timeout; status = cf_util_get_int(option, &timeout); - if (status == 0) - rn.timeout.tv_usec = timeout; + if (status == 0) { + rn->timeout.tv_usec = timeout * 1000; + rn->timeout.tv_sec = rn->timeout.tv_usec / 1000000L; + rn->timeout.tv_usec %= 1000000L; + } } else if (strcasecmp("Password", option->key) == 0) - status = cf_util_get_string_buffer(option, rn.passwd, sizeof(rn.passwd)); + status = cf_util_get_string(option, &rn->passwd); + else if (strcasecmp("ReportCommandStats", option->key) == 0) + status = cf_util_get_boolean(option, &rn->report_command_stats); + else if (strcasecmp("ReportCpuUsage", option->key) == 0) + status = cf_util_get_boolean(option, &rn->report_cpu_usage); else WARNING("redis plugin: Option `%s' not allowed inside a `Node' " "block. I'll ignore this option.", @@ -207,10 +236,12 @@ static int redis_config_node(oconfig_item_t *ci) /* {{{ */ break; } - if (status != 0) + if (status != 0) { + redis_node_free(rn); return status; + } - return redis_node_add(&rn); + return redis_node_add(rn); } /* }}} int redis_config_node */ static int redis_config(oconfig_item_t *ci) /* {{{ */ @@ -226,17 +257,12 @@ static int redis_config(oconfig_item_t *ci) /* {{{ */ option->key); } - if (nodes_head == NULL) { - ERROR("redis plugin: No valid node configuration could be found."); - return ENOENT; - } - return 0; } /* }}} */ __attribute__((nonnull(2))) static void -redis_submit(char *plugin_instance, const char *type, const char *type_instance, - value_t value) /* {{{ */ +redis_submit(const char *plugin_instance, const char *type, + const char *type_instance, value_t value) /* {{{ */ { value_list_t vl = VALUE_LIST_INIT; @@ -252,28 +278,78 @@ redis_submit(char *plugin_instance, const char *type, const char *type_instance, plugin_dispatch_values(&vl); } /* }}} */ +__attribute__((nonnull(2))) static void +redis_submit2(const char *plugin_instance, const char *type, + const char *type_instance, value_t value0, + value_t value1) /* {{{ */ +{ + value_list_t vl = VALUE_LIST_INIT; + value_t values[] = {value0, value1}; + + vl.values = values; + vl.values_len = STATIC_ARRAY_SIZE(values); + + sstrncpy(vl.plugin, "redis", sizeof(vl.plugin)); + sstrncpy(vl.type, type, sizeof(vl.type)); + + if (plugin_instance != NULL) + sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance)); + + if (type_instance != NULL) + sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); + + plugin_dispatch_values(&vl); +} /* }}} */ + static int redis_init(void) /* {{{ */ { - redis_node_t rn = {.name = "default", - .host = REDIS_DEF_HOST, - .port = REDIS_DEF_PORT, - .timeout.tv_sec = 0, - .timeout.tv_usec = REDIS_DEF_TIMEOUT, - .next = NULL}; + if (redis_have_instances) + return 0; - if (nodes_head == NULL) - redis_node_add(&rn); + redis_node_t *rn = calloc(1, sizeof(*rn)); + if (rn == NULL) + return ENOMEM; - return 0; + rn->port = REDIS_DEF_PORT; + rn->timeout.tv_sec = REDIS_DEF_TIMEOUT_SEC; + + rn->name = strdup("default"); + rn->host = strdup(REDIS_DEF_HOST); + + if (rn->name == NULL || rn->host == NULL) { + sfree(rn->name); + sfree(rn->host); + sfree(rn); + return ENOMEM; + } + + return redis_node_add(rn); } /* }}} int redis_init */ -static int redis_handle_info(char *node, char const *info_line, - char const *type, char const *type_instance, - char const *field_name, int ds_type) /* {{{ */ -{ +static void *c_redisCommand(redis_node_t *rn, const char *format, ...) { + redisContext *c = rn->redisContext; + + if (c == NULL) + return NULL; + + va_list ap; + va_start(ap, format); + void *reply = redisvCommand(c, format, ap); + va_end(ap); + + if (reply == NULL) { + ERROR("redis plugin: Connection error: %s", c->errstr); + redisFree(rn->redisContext); + rn->redisContext = NULL; + } + + return reply; +} /* void c_redisCommand */ + +static int redis_get_info_value(char const *info_line, char const *field_name, + int ds_type, value_t *val) { char *str = strstr(info_line, field_name); static char buf[MAX_REDIS_VAL_SIZE]; - value_t val; if (str) { int i; @@ -283,20 +359,29 @@ static int redis_handle_info(char *node, char const *info_line, buf[i] = *str; buf[i] = '\0'; - if (parse_value(buf, &val, ds_type) == -1) { + if (parse_value(buf, val, ds_type) == -1) { WARNING("redis plugin: Unable to parse field `%s'.", field_name); return -1; } - redis_submit(node, type, type_instance, val); return 0; } return -1; +} /* int redis_get_info_value */ + +static int redis_handle_info(char *node, char const *info_line, + char const *type, char const *type_instance, + char const *field_name, int ds_type) /* {{{ */ +{ + value_t val; + if (redis_get_info_value(info_line, field_name, ds_type, &val) != 0) + return -1; + redis_submit(node, type, type_instance, val); + return 0; } /* }}} int redis_handle_info */ -static int redis_handle_query(redisContext *rh, redis_node_t *rn, - redis_query_t *rq) /* {{{ */ +static int redis_handle_query(redis_node_t *rn, redis_query_t *rq) /* {{{ */ { redisReply *rr; const data_set_t *ds; @@ -304,16 +389,24 @@ static int redis_handle_query(redisContext *rh, redis_node_t *rn, ds = plugin_get_ds(rq->type); if (!ds) { - ERROR("redis plugin: DataSet `%s' not defined.", rq->type); + ERROR("redis plugin: DS type `%s' not defined.", rq->type); return -1; } if (ds->ds_num != 1) { - ERROR("redis plugin: DS `%s' has too many types.", rq->type); + ERROR("redis plugin: DS type `%s' has too many datasources. This is not " + "supported currently.", + rq->type); return -1; } - if ((rr = redisCommand(rh, rq->query)) == NULL) { + if ((rr = c_redisCommand(rn, "SELECT %d", rq->database)) == NULL) { + WARNING("redis plugin: unable to switch to database `%d' on node `%s'.", + rq->database, rn->name); + return -1; + } + + if ((rr = c_redisCommand(rn, rq->query)) == NULL) { WARNING("redis plugin: unable to carry out query `%s'.", rq->query); return -1; } @@ -337,13 +430,24 @@ static int redis_handle_query(redisContext *rh, redis_node_t *rn, break; case REDIS_REPLY_STRING: if (parse_value(rr->str, &val, ds->ds[0].type) == -1) { - WARNING("redis plugin: Unable to parse field `%s'.", rq->type); + WARNING("redis plugin: Query `%s': Unable to parse value.", rq->query); freeReplyObject(rr); return -1; } break; + case REDIS_REPLY_ERROR: + WARNING("redis plugin: Query `%s' failed: %s.", rq->query, rr->str); + freeReplyObject(rr); + return -1; + case REDIS_REPLY_ARRAY: + WARNING("redis plugin: Query `%s' should return string or integer. Arrays " + "are not supported.", + rq->query); + freeReplyObject(rr); + return -1; default: - WARNING("redis plugin: Cannot coerce redis type."); + WARNING("redis plugin: Query `%s': Cannot coerce redis type (%i).", + rq->query, rr->type); freeReplyObject(rr); return -1; } @@ -354,7 +458,7 @@ static int redis_handle_query(redisContext *rh, redis_node_t *rn, return 0; } /* }}} int redis_handle_query */ -static int redis_db_stats(char *node, char const *info_line) /* {{{ */ +static int redis_db_stats(const char *node, char const *info_line) /* {{{ */ { /* redis_db_stats parses and dispatches Redis database statistics, * currently the number of keys for each database. @@ -364,8 +468,8 @@ static int redis_db_stats(char *node, char const *info_line) /* {{{ */ for (int db = 0; db < REDIS_DEF_DB_COUNT; db++) { static char buf[MAX_REDIS_VAL_SIZE]; - static char field_name[11]; - static char db_id[3]; + static char field_name[12]; + static char db_id[4]; value_t val; char *str; int i; @@ -393,91 +497,245 @@ static int redis_db_stats(char *node, char const *info_line) /* {{{ */ } /* }}} int redis_db_stats */ -static int redis_read(void) /* {{{ */ -{ - for (redis_node_t *rn = nodes_head; rn != NULL; rn = rn->next) { - redisContext *rh; +static void redis_cpu_usage(const char *node, char const *info_line) { + while (42) { + value_t rusage_user; + value_t rusage_syst; + + if (redis_get_info_value(info_line, "used_cpu_user", DS_TYPE_GAUGE, + &rusage_user) != 0) + break; + + if (redis_get_info_value(info_line, "used_cpu_sys", DS_TYPE_GAUGE, + &rusage_syst) != 0) + break; + + redis_submit2(node, "ps_cputime", "daemon", + (value_t){.derive = rusage_user.gauge * 1000000}, + (value_t){.derive = rusage_syst.gauge * 1000000}); + break; + } + + while (42) { + value_t rusage_user; + value_t rusage_syst; + + if (redis_get_info_value(info_line, "used_cpu_user_children", DS_TYPE_GAUGE, + &rusage_user) != 0) + break; + + if (redis_get_info_value(info_line, "used_cpu_sys_children", DS_TYPE_GAUGE, + &rusage_syst) != 0) + break; + + redis_submit2(node, "ps_cputime", "children", + (value_t){.derive = rusage_user.gauge * 1000000}, + (value_t){.derive = rusage_syst.gauge * 1000000}); + break; + } +} /* void redis_cpu_usage */ + +static void redis_check_connection(redis_node_t *rn) { + if (rn->redisContext) + return; + + redisContext *rh = redisConnectWithTimeout(rn->host, rn->port, rn->timeout); + + if (rh == NULL) { + ERROR("redis plugin: can't allocate redis context"); + return; + } + if (rh->err) { + ERROR("redis plugin: unable to connect to node `%s' (%s:%d): %s.", rn->name, + rn->host, rn->port, rh->errstr); + redisFree(rh); + return; + } + + rn->redisContext = rh; + + if (rn->passwd) { redisReply *rr; - DEBUG("redis plugin: querying info from node `%s' (%s:%d).", rn->name, - rn->host, rn->port); + DEBUG("redis plugin: authenticating node `%s' passwd(%s).", rn->name, + rn->passwd); - rh = redisConnectWithTimeout((char *)rn->host, rn->port, rn->timeout); - if (rh == NULL) { - ERROR("redis plugin: unable to connect to node `%s' (%s:%d).", rn->name, - rn->host, rn->port); - continue; + if ((rr = c_redisCommand(rn, "AUTH %s", rn->passwd)) == NULL) { + WARNING("redis plugin: unable to authenticate on node `%s'.", rn->name); + return; } - if (strlen(rn->passwd) > 0) { - DEBUG("redis plugin: authenticating node `%s' passwd(%s).", rn->name, - rn->passwd); + if (rr->type != REDIS_REPLY_STATUS) { + WARNING("redis plugin: invalid authentication on node `%s'.", rn->name); + freeReplyObject(rr); + redisFree(rn->redisContext); + rn->redisContext = NULL; + return; + } - if ((rr = redisCommand(rh, "AUTH %s", rn->passwd)) == NULL) { - WARNING("redis plugin: unable to authenticate on node `%s'.", rn->name); - goto redis_fail; - } + freeReplyObject(rr); + } + return; +} /* void redis_check_connection */ - if (rr->type != REDIS_REPLY_STATUS) { - WARNING("redis plugin: invalid authentication on node `%s'.", rn->name); - goto redis_fail; - } +static void redis_read_server_info(redis_node_t *rn) { + redisReply *rr; - freeReplyObject(rr); + if ((rr = c_redisCommand(rn, "INFO")) == NULL) { + WARNING("redis plugin: unable to get INFO from node `%s'.", rn->name); + return; + } + + redis_handle_info(rn->name, rr->str, "uptime", NULL, "uptime_in_seconds", + DS_TYPE_GAUGE); + redis_handle_info(rn->name, rr->str, "current_connections", "clients", + "connected_clients", DS_TYPE_GAUGE); + redis_handle_info(rn->name, rr->str, "blocked_clients", NULL, + "blocked_clients", DS_TYPE_GAUGE); + redis_handle_info(rn->name, rr->str, "memory", NULL, "used_memory", + DS_TYPE_GAUGE); + redis_handle_info(rn->name, rr->str, "memory_lua", NULL, "used_memory_lua", + DS_TYPE_GAUGE); + /* changes_since_last_save: Deprecated in redis version 2.6 and above */ + redis_handle_info(rn->name, rr->str, "volatile_changes", NULL, + "changes_since_last_save", DS_TYPE_GAUGE); + redis_handle_info(rn->name, rr->str, "total_connections", NULL, + "total_connections_received", DS_TYPE_DERIVE); + redis_handle_info(rn->name, rr->str, "total_operations", NULL, + "total_commands_processed", DS_TYPE_DERIVE); + redis_handle_info(rn->name, rr->str, "operations_per_second", NULL, + "instantaneous_ops_per_sec", DS_TYPE_GAUGE); + redis_handle_info(rn->name, rr->str, "expired_keys", NULL, "expired_keys", + DS_TYPE_DERIVE); + redis_handle_info(rn->name, rr->str, "evicted_keys", NULL, "evicted_keys", + DS_TYPE_DERIVE); + redis_handle_info(rn->name, rr->str, "pubsub", "channels", "pubsub_channels", + DS_TYPE_GAUGE); + redis_handle_info(rn->name, rr->str, "pubsub", "patterns", "pubsub_patterns", + DS_TYPE_GAUGE); + redis_handle_info(rn->name, rr->str, "current_connections", "slaves", + "connected_slaves", DS_TYPE_GAUGE); + redis_handle_info(rn->name, rr->str, "cache_result", "hits", "keyspace_hits", + DS_TYPE_DERIVE); + redis_handle_info(rn->name, rr->str, "cache_result", "misses", + "keyspace_misses", DS_TYPE_DERIVE); + redis_handle_info(rn->name, rr->str, "total_bytes", "input", + "total_net_input_bytes", DS_TYPE_DERIVE); + redis_handle_info(rn->name, rr->str, "total_bytes", "output", + "total_net_output_bytes", DS_TYPE_DERIVE); + + redis_db_stats(rn->name, rr->str); + + if (rn->report_cpu_usage) + redis_cpu_usage(rn->name, rr->str); + + freeReplyObject(rr); +} /* void redis_read_server_info */ + +static void redis_read_command_stats(redis_node_t *rn) { + redisReply *rr; + + if ((rr = c_redisCommand(rn, "INFO commandstats")) == NULL) { + WARNING("redis plugin: node `%s': unable to get `INFO commandstats'.", + rn->name); + return; + } + + if (rr->type != REDIS_REPLY_STRING) { + WARNING("redis plugin: node `%s' `INFO commandstats' returned unsupported " + "redis type %i.", + rn->name, rr->type); + freeReplyObject(rr); + return; + } + + char *command; + char *line; + char *ptr = rr->str; + char *saveptr = NULL; + while ((line = strtok_r(ptr, "\n\r", &saveptr)) != NULL) { + ptr = NULL; + + if (line[0] == '#') + continue; + + /* command name */ + if (strstr(line, "cmdstat_") != line) { + ERROR("redis plugin: not found 'cmdstat_' prefix in line '%s'", line); + continue; } - if ((rr = redisCommand(rh, "INFO")) == NULL) { - WARNING("redis plugin: unable to get info from node `%s'.", rn->name); - goto redis_fail; + char *values = strstr(line, ":"); + if (values == NULL) { + ERROR("redis plugin: not found ':' separator in line '%s'", line); + continue; } - redis_handle_info(rn->name, rr->str, "uptime", NULL, "uptime_in_seconds", - DS_TYPE_GAUGE); - redis_handle_info(rn->name, rr->str, "current_connections", "clients", - "connected_clients", DS_TYPE_GAUGE); - redis_handle_info(rn->name, rr->str, "blocked_clients", NULL, - "blocked_clients", DS_TYPE_GAUGE); - redis_handle_info(rn->name, rr->str, "memory", NULL, "used_memory", - DS_TYPE_GAUGE); - redis_handle_info(rn->name, rr->str, "memory_lua", NULL, "used_memory_lua", - DS_TYPE_GAUGE); - /* changes_since_last_save: Deprecated in redis version 2.6 and above */ - redis_handle_info(rn->name, rr->str, "volatile_changes", NULL, - "changes_since_last_save", DS_TYPE_GAUGE); - redis_handle_info(rn->name, rr->str, "total_connections", NULL, - "total_connections_received", DS_TYPE_DERIVE); - redis_handle_info(rn->name, rr->str, "total_operations", NULL, - "total_commands_processed", DS_TYPE_DERIVE); - redis_handle_info(rn->name, rr->str, "operations_per_second", NULL, - "instantaneous_ops_per_sec", DS_TYPE_GAUGE); - redis_handle_info(rn->name, rr->str, "expired_keys", NULL, "expired_keys", - DS_TYPE_DERIVE); - redis_handle_info(rn->name, rr->str, "evicted_keys", NULL, "evicted_keys", - DS_TYPE_DERIVE); - redis_handle_info(rn->name, rr->str, "pubsub", "channels", - "pubsub_channels", DS_TYPE_GAUGE); - redis_handle_info(rn->name, rr->str, "pubsub", "patterns", - "pubsub_patterns", DS_TYPE_GAUGE); - redis_handle_info(rn->name, rr->str, "current_connections", "slaves", - "connected_slaves", DS_TYPE_GAUGE); - redis_handle_info(rn->name, rr->str, "cache_result", "hits", - "keyspace_hits", DS_TYPE_DERIVE); - redis_handle_info(rn->name, rr->str, "cache_result", "misses", - "keyspace_misses", DS_TYPE_DERIVE); - redis_handle_info(rn->name, rr->str, "total_bytes", "input", - "total_net_input_bytes", DS_TYPE_DERIVE); - redis_handle_info(rn->name, rr->str, "total_bytes", "output", - "total_net_output_bytes", DS_TYPE_DERIVE); - - redis_db_stats(rn->name, rr->str); - - for (redis_query_t *rq = rn->queries; rq != NULL; rq = rq->next) - redis_handle_query(rh, rn, rq); - - redis_fail: - if (rr != NULL) - freeReplyObject(rr); - redisFree(rh); + /* Null-terminate command token */ + values[0] = '\0'; + command = line + strlen("cmdstat_"); + values++; + + /* parse values */ + /* cmdstat_publish:calls=20795774,usec=111039258,usec_per_call=5.34 */ + char *field; + char *saveptr_field = NULL; + while ((field = strtok_r(values, "=", &saveptr_field)) != NULL) { + values = NULL; + + const char *type; + /* only these are supported */ + if (strcmp(field, "calls") == 0) + type = "commands"; + else if (strcmp(field, "usec") == 0) + type = "redis_command_cputime"; + else + continue; + + if ((field = strtok_r(NULL, ",", &saveptr_field)) == NULL) + continue; + + char *endptr = NULL; + errno = 0; + derive_t value = strtoll(field, &endptr, 0); + + if ((endptr == field) || (errno != 0)) + continue; + + redis_submit(rn->name, type, command, (value_t){.derive = value}); + } + } + freeReplyObject(rr); +} /* void redis_read_command_stats */ + +static int redis_read(user_data_t *user_data) /* {{{ */ +{ + redis_node_t *rn = user_data->data; + + DEBUG("redis plugin: querying info from node `%s' (%s:%d).", rn->name, + rn->host, rn->port); + + redis_check_connection(rn); + + if (!rn->redisContext) /* no connection */ + return -1; + + redis_read_server_info(rn); + + if (!rn->redisContext) /* connection lost */ + return -1; + + if (rn->report_command_stats) { + redis_read_command_stats(rn); + + if (!rn->redisContext) /* connection lost */ + return -1; + } + + for (redis_query_t *rq = rn->queries; rq != NULL; rq = rq->next) { + redis_handle_query(rn, rq); + if (!rn->redisContext) /* connection lost */ + return -1; } return 0; @@ -488,8 +746,5 @@ void module_register(void) /* {{{ */ { plugin_register_complex_config("redis", redis_config); plugin_register_init("redis", redis_init); - plugin_register_read("redis", redis_read); - /* TODO: plugin_register_write: one redis list per value id with - * X elements */ } /* }}} */ diff --git a/src/routeros.c b/src/routeros.c index c502c3da..c0d5ef7f 100644 --- a/src/routeros.c +++ b/src/routeros.c @@ -39,12 +39,12 @@ struct cr_data_s { char *username; char *password; - _Bool collect_interface; - _Bool collect_regtable; - _Bool collect_cpu_load; - _Bool collect_memory; - _Bool collect_df; - _Bool collect_disk; + bool collect_interface; + bool collect_regtable; + bool collect_cpu_load; + bool collect_memory; + bool collect_df; + bool collect_disk; }; typedef struct cr_data_s cr_data_t; diff --git a/src/rrdcached.c b/src/rrdcached.c index 529d29c1..8b742bb5 100644 --- a/src/rrdcached.c +++ b/src/rrdcached.c @@ -37,10 +37,10 @@ /* * Private variables */ -static char *datadir = NULL; -static char *daemon_address = NULL; -static _Bool config_create_files = 1; -static _Bool config_collect_stats = 1; +static char *datadir; +static char *daemon_address; +static bool config_create_files = true; +static bool config_collect_stats = true; static rrdcreate_config_t rrdcreate_config = { /* stepsize = */ 0, /* heartbeat = */ 0, @@ -284,7 +284,7 @@ static int try_reconnect(void) { static int rc_read(void) { int status; rrdc_stats_t *head; - _Bool retried = 0; + bool retried = false; value_list_t vl = VALUE_LIST_INIT; vl.values = &(value_t){.gauge = NAN}; @@ -320,7 +320,7 @@ static int rc_read(void) { break; if (!retried) { - retried = 1; + retried = true; if (try_reconnect() == 0) continue; /* else: report the error and fail */ @@ -392,7 +392,7 @@ static int rc_write(const data_set_t *ds, const value_list_t *vl, char values[512]; char *values_array[2]; int status; - _Bool retried = 0; + bool retried = false; if (daemon_address == NULL) { ERROR("rrdcached plugin: daemon_address == NULL."); @@ -455,7 +455,7 @@ static int rc_write(const data_set_t *ds, const value_list_t *vl, break; if (!retried) { - retried = 1; + retried = true; if (try_reconnect() == 0) continue; /* else: report the error and fail */ @@ -474,7 +474,7 @@ static int rc_flush(__attribute__((unused)) cdtime_t timeout, /* {{{ */ __attribute__((unused)) user_data_t *ud) { char filename[PATH_MAX + 1]; int status; - _Bool retried = 0; + bool retried = false; if (identifier == NULL) return EINVAL; @@ -502,7 +502,7 @@ static int rc_flush(__attribute__((unused)) cdtime_t timeout, /* {{{ */ break; if (!retried) { - retried = 1; + retried = true; if (try_reconnect() == 0) continue; /* else: report the error and fail */ diff --git a/src/rrdtool.c b/src/rrdtool.c index e3ad07e2..f6290d73 100644 --- a/src/rrdtool.c +++ b/src/rrdtool.c @@ -66,8 +66,8 @@ static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); /* If datadir is zero, the daemon's basedir is used. If stepsize or heartbeat * is zero a default, depending on the `interval' member of the value list is * being used. */ -static char *datadir = NULL; -static double write_rate = 0.0; +static char *datadir; +static double write_rate; static rrdcreate_config_t rrdcreate_config = { /* stepsize = */ 0, /* heartbeat = */ 0, @@ -84,17 +84,17 @@ static rrdcreate_config_t rrdcreate_config = { /* XXX: If you need to lock both, cache_lock and queue_lock, at the same time, * ALWAYS lock `cache_lock' first! */ -static cdtime_t cache_timeout = 0; -static cdtime_t cache_flush_timeout = 0; -static cdtime_t random_timeout = 0; +static cdtime_t cache_timeout; +static cdtime_t cache_flush_timeout; +static cdtime_t random_timeout; static cdtime_t cache_flush_last; -static c_avl_tree_t *cache = NULL; +static c_avl_tree_t *cache; static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER; -static rrd_queue_t *queue_head = NULL; -static rrd_queue_t *queue_tail = NULL; -static rrd_queue_t *flushq_head = NULL; -static rrd_queue_t *flushq_tail = NULL; +static rrd_queue_t *queue_head; +static rrd_queue_t *queue_tail; +static rrd_queue_t *flushq_head; +static rrd_queue_t *flushq_tail; static pthread_t queue_thread; static int queue_thread_running = 1; static pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER; @@ -104,7 +104,7 @@ static pthread_cond_t queue_cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t librrd_lock = PTHREAD_MUTEX_INITIALIZER; #endif -static int do_shutdown = 0; +static int do_shutdown; #if HAVE_THREADSAFE_LIBRRD static int srrd_update(char *filename, char *template, int argc, @@ -624,6 +624,7 @@ static int rrd_cache_insert(const char *filename, const char *value, if ((status != 0) || (rc == NULL)) { rc = malloc(sizeof(*rc)); if (rc == NULL) { + ERROR("rrdtool plugin: malloc failed: %s", STRERRNO); pthread_mutex_unlock(&cache_lock); return -1; } @@ -790,17 +791,22 @@ static int rrd_write(const data_set_t *ds, const value_list_t *vl, } char filename[PATH_MAX]; - if (value_list_to_filename(filename, sizeof(filename), vl) != 0) + if (value_list_to_filename(filename, sizeof(filename), vl) != 0) { + ERROR("rrdtool plugin: failed to build filename"); return -1; + } char values[32 * (ds->ds_num + 1)]; - if (value_list_to_string(values, sizeof(values), ds, vl) != 0) + if (value_list_to_string(values, sizeof(values), ds, vl) != 0) { + ERROR("rrdtool plugin: failed to build values string"); return -1; + } struct stat statbuf = {0}; if (stat(filename, &statbuf) == -1) { if (errno == ENOENT) { if (cu_rrd_create_file(filename, ds, vl, &rrdcreate_config) != 0) { + ERROR("rrdtool plugin: cu_rrd_create_file (%s) failed.", filename); return -1; } else if (rrdcreate_config.async) { return 0; @@ -1010,7 +1016,7 @@ static int rrd_shutdown(void) { } /* int rrd_shutdown */ static int rrd_init(void) { - static int init_once = 0; + static int init_once; if (init_once != 0) return 0; diff --git a/src/sensors.c b/src/sensors.c index 572d41f1..41cccf1b 100644 --- a/src/sensors.c +++ b/src/sensors.c @@ -157,8 +157,8 @@ typedef struct featurelist { struct featurelist *next; } featurelist_t; -static char *conffile = NULL; -static _Bool use_labels = 0; +static char *conffile; +static bool use_labels; /* #endif (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500) */ #else /* if SENSORS_API_VERSION >= 0x500 */ @@ -166,7 +166,7 @@ static _Bool use_labels = 0; "as bug." #endif -static featurelist_t *first_feature = NULL; +static featurelist_t *first_feature; static ignorelist_t *sensor_list; #if SENSORS_API_VERSION < 0x400 @@ -225,7 +225,7 @@ static int sensors_config(const char *key, const char *value) { } #if (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500) else if (strcasecmp(key, "UseLabels") == 0) { - use_labels = IS_TRUE(value) ? 1 : 0; + use_labels = IS_TRUE(value); } #endif else { @@ -251,7 +251,7 @@ static void sensors_free_features(void) { } static int sensors_load_conf(void) { - static int call_once = 0; + static int call_once; FILE *fh = NULL; featurelist_t *last_feature = NULL; diff --git a/src/serial.c b/src/serial.c index 2b77db65..8bbd94c0 100644 --- a/src/serial.c +++ b/src/serial.c @@ -59,7 +59,8 @@ static int serial_read(void) { while (fgets(buffer, sizeof(buffer), fh) != NULL) { derive_t rx = 0; derive_t tx = 0; - _Bool have_rx = 0, have_tx = 0; + bool have_rx = false; + bool have_tx = false; size_t len; char *fields[16]; @@ -87,10 +88,10 @@ static int serial_read(void) { if (strncmp(fields[i], "tx:", 3) == 0) { if (strtoderive(fields[i] + 3, &tx) == 0) - have_tx = 1; + have_tx = true; } else if (strncmp(fields[i], "rx:", 3) == 0) { if (strtoderive(fields[i] + 3, &rx) == 0) - have_rx = 1; + have_rx = true; } } diff --git a/src/smart.c b/src/smart.c index 30680be6..62cbb4f1 100644 --- a/src/smart.c +++ b/src/smart.c @@ -42,9 +42,9 @@ static const char *config_keys[] = {"Disk", "IgnoreSelected", "IgnoreSleepMode", static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static ignorelist_t *ignorelist = NULL; -static int ignore_sleep_mode = 0; -static int use_serial = 0; +static ignorelist_t *ignorelist; +static int ignore_sleep_mode; +static int use_serial; static int smart_config(const char *key, const char *value) { if (ignorelist == NULL) diff --git a/src/snmp.c b/src/snmp.c index d0f9e846..6c018da7 100644 --- a/src/snmp.c +++ b/src/snmp.c @@ -29,6 +29,7 @@ #include "common.h" #include "plugin.h" #include "utils_complain.h" +#include "utils_ignorelist.h" #include #include @@ -44,18 +45,24 @@ struct oid_s { }; typedef struct oid_s oid_t; -union instance_u { - char string[DATA_MAX_NAME_LEN]; +struct instance_s { + bool configured; oid_t oid; + char *prefix; + char *value; }; -typedef union instance_u instance_t; +typedef struct instance_s instance_t; struct data_definition_s { char *name; /* used to reference this from the `Collect' option */ char *type; /* used to find the data_set */ - _Bool is_table; - instance_t instance; - char *instance_prefix; + bool is_table; + instance_t type_instance; + instance_t plugin_instance; + instance_t host; + oid_t filter_oid; + ignorelist_t *ignorelist; + char *plugin_name; oid_t *values; size_t values_len; double scale; @@ -63,7 +70,7 @@ struct data_definition_s { struct data_definition_s *next; char **ignores; size_t ignores_len; - _Bool invert_match; + bool invert_match; }; typedef struct data_definition_s data_definition_t; @@ -98,24 +105,33 @@ typedef struct host_definition_s host_definition_t; /* These two types are used to cache values in `csnmp_read_table' to handle * gaps in tables. */ -struct csnmp_list_instances_s { +struct csnmp_cell_char_s { oid_t suffix; - char instance[DATA_MAX_NAME_LEN]; - struct csnmp_list_instances_s *next; + char value[DATA_MAX_NAME_LEN]; + struct csnmp_cell_char_s *next; }; -typedef struct csnmp_list_instances_s csnmp_list_instances_t; +typedef struct csnmp_cell_char_s csnmp_cell_char_t; -struct csnmp_table_values_s { +struct csnmp_cell_value_s { oid_t suffix; value_t value; - struct csnmp_table_values_s *next; + struct csnmp_cell_value_s *next; }; -typedef struct csnmp_table_values_s csnmp_table_values_t; +typedef struct csnmp_cell_value_s csnmp_cell_value_t; + +typedef enum { + OID_TYPE_SKIP = 0, + OID_TYPE_VARIABLE, + OID_TYPE_TYPEINSTANCE, + OID_TYPE_PLUGININSTANCE, + OID_TYPE_HOST, + OID_TYPE_FILTER, +} csnmp_oid_type_t; /* * Private variables */ -static data_definition_t *data_head = NULL; +static data_definition_t *data_head; /* * Prototypes @@ -199,6 +215,22 @@ static void csnmp_host_definition_destroy(void *arg) /* {{{ */ sfree(hd); } /* }}} void csnmp_host_definition_destroy */ +static void csnmp_data_definition_destroy(data_definition_t *dd) { + sfree(dd->name); + sfree(dd->type); + sfree(dd->plugin_name); + sfree(dd->plugin_instance.prefix); + sfree(dd->plugin_instance.value); + sfree(dd->type_instance.prefix); + sfree(dd->type_instance.value); + sfree(dd->host.prefix); + sfree(dd->host.value); + sfree(dd->values); + sfree(dd->ignores); + ignorelist_free(dd->ignorelist); + sfree(dd); +} /* void csnmp_data_definition_destroy */ + /* Many functions to handle the configuration. {{{ */ /* First there are many functions which do configuration stuff. It's a big * bloated and messy, I'm afraid. */ @@ -208,8 +240,7 @@ static void csnmp_host_definition_destroy(void *arg) /* {{{ */ * csnmp_config * +-> call_snmp_init_once * +-> csnmp_config_add_data - * ! +-> csnmp_config_add_data_instance - * ! +-> csnmp_config_add_data_instance_prefix + * ! +-> csnmp_config_configure_data_instance * ! +-> csnmp_config_add_data_values * +-> csnmp_config_add_host * +-> csnmp_config_add_host_version @@ -219,52 +250,36 @@ static void csnmp_host_definition_destroy(void *arg) /* {{{ */ * +-> csnmp_config_add_host_security_level */ static void call_snmp_init_once(void) { - static int have_init = 0; + static int have_init; if (have_init == 0) init_snmp(PACKAGE_NAME); have_init = 1; } /* void call_snmp_init_once */ -static int csnmp_config_add_data_instance(data_definition_t *dd, - oconfig_item_t *ci) { +static int csnmp_config_configure_data_instance(instance_t *instance, + oconfig_item_t *ci) { char buffer[DATA_MAX_NAME_LEN]; - int status; - status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer)); + int status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer)); if (status != 0) return status; - if (dd->is_table) { - /* Instance is an OID */ - dd->instance.oid.oid_len = MAX_OID_LEN; + instance->configured = true; - if (!read_objid(buffer, dd->instance.oid.oid, &dd->instance.oid.oid_len)) { - ERROR("snmp plugin: read_objid (%s) failed.", buffer); - return -1; - } - } else { - /* Instance is a simple string */ - sstrncpy(dd->instance.string, buffer, sizeof(dd->instance.string)); + if (strlen(buffer) == 0) { + return 0; } - return 0; -} /* int csnmp_config_add_data_instance */ + instance->oid.oid_len = MAX_OID_LEN; -static int csnmp_config_add_data_instance_prefix(data_definition_t *dd, - oconfig_item_t *ci) { - int status; - - if (!dd->is_table) { - WARNING("snmp plugin: data %s: InstancePrefix is ignored when `Table' " - "is set to `false'.", - dd->name); + if (!read_objid(buffer, instance->oid.oid, &instance->oid.oid_len)) { + ERROR("snmp plugin: read_objid (%s) failed.", buffer); return -1; } - status = cf_util_get_string(ci, &dd->instance_prefix); - return status; -} /* int csnmp_config_add_data_instance_prefix */ + return 0; +} /* int csnmp_config_configure_data_instance */ static int csnmp_config_add_data_values(data_definition_t *dd, oconfig_item_t *ci) { @@ -301,7 +316,7 @@ static int csnmp_config_add_data_values(data_definition_t *dd, } return 0; -} /* int csnmp_config_add_data_instance */ +} /* int csnmp_config_configure_data_instance */ static int csnmp_config_add_data_blacklist(data_definition_t *dd, oconfig_item_t *ci) { @@ -315,9 +330,6 @@ static int csnmp_config_add_data_blacklist(data_definition_t *dd, } } - dd->ignores_len = 0; - dd->ignores = NULL; - for (int i = 0; i < ci->values_num; ++i) { if (strarray_add(&(dd->ignores), &(dd->ignores_len), ci->values[i].value.string) != 0) { @@ -329,6 +341,41 @@ static int csnmp_config_add_data_blacklist(data_definition_t *dd, return 0; } /* int csnmp_config_add_data_blacklist */ +static int csnmp_config_add_data_filter_values(data_definition_t *data, + oconfig_item_t *ci) { + if (ci->values_num < 1) { + WARNING("snmp plugin: `FilterValues' needs at least one argument."); + return -1; + } + + for (int i = 0; i < ci->values_num; i++) { + if (ci->values[i].type != OCONFIG_TYPE_STRING) { + WARNING("snmp plugin: All arguments to `FilterValues' must be strings."); + return -1; + } + ignorelist_add(data->ignorelist, ci->values[i].value.string); + } + + return 0; +} /* int csnmp_config_add_data_filter_values */ + +static int csnmp_config_add_data_filter_oid(data_definition_t *data, + oconfig_item_t *ci) { + + char buffer[DATA_MAX_NAME_LEN]; + int status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer)); + if (status != 0) + return status; + + data->filter_oid.oid_len = MAX_OID_LEN; + + if (!read_objid(buffer, data->filter_oid.oid, &data->filter_oid.oid_len)) { + ERROR("snmp plugin: read_objid (%s) failed.", buffer); + return -1; + } + return 0; +} /* int csnmp_config_add_data_filter_oid */ + static int csnmp_config_add_data(oconfig_item_t *ci) { data_definition_t *dd = calloc(1, sizeof(*dd)); if (dd == NULL) @@ -342,6 +389,22 @@ static int csnmp_config_add_data(oconfig_item_t *ci) { dd->scale = 1.0; dd->shift = 0.0; + dd->ignores_len = 0; + dd->ignores = NULL; + + dd->ignorelist = ignorelist_create(/* invert = */ 1); + if (dd->ignorelist == NULL) { + sfree(dd->name); + sfree(dd); + ERROR("snmp plugin: ignorelist_create() failed."); + return ENOMEM; + } + + dd->plugin_name = strdup("snmp"); + if (dd->plugin_name == NULL) { + ERROR("snmp plugin: Can't allocate memory"); + return ENOMEM; + } for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; @@ -350,10 +413,47 @@ static int csnmp_config_add_data(oconfig_item_t *ci) { status = cf_util_get_string(option, &dd->type); else if (strcasecmp("Table", option->key) == 0) status = cf_util_get_boolean(option, &dd->is_table); - else if (strcasecmp("Instance", option->key) == 0) - status = csnmp_config_add_data_instance(dd, option); - else if (strcasecmp("InstancePrefix", option->key) == 0) - status = csnmp_config_add_data_instance_prefix(dd, option); + else if (strcasecmp("Plugin", option->key) == 0) + status = cf_util_get_string(option, &dd->plugin_name); + else if (strcasecmp("Instance", option->key) == 0) { + if (dd->is_table) { + /* Instance is OID */ + WARNING( + "snmp plugin: data %s: Option `Instance' is deprecated, please use " + "option `TypeInstanceOID'.", + dd->name); + status = + csnmp_config_configure_data_instance(&dd->type_instance, option); + } else { + /* Instance is a simple string */ + WARNING( + "snmp plugin: data %s: Option `Instance' is deprecated, please use " + "option `TypeInstance'.", + dd->name); + status = cf_util_get_string(option, &dd->type_instance.value); + } + } else if (strcasecmp("InstancePrefix", option->key) == 0) { + WARNING("snmp plugin: data %s: Option `InstancePrefix' is deprecated, " + "please use option `TypeInstancePrefix'.", + dd->name); + status = cf_util_get_string(option, &dd->type_instance.prefix); + } else if (strcasecmp("PluginInstance", option->key) == 0) + status = cf_util_get_string(option, &dd->plugin_instance.value); + else if (strcasecmp("TypeInstance", option->key) == 0) + status = cf_util_get_string(option, &dd->type_instance.value); + else if (strcasecmp("PluginInstanceOID", option->key) == 0) + status = + csnmp_config_configure_data_instance(&dd->plugin_instance, option); + else if (strcasecmp("PluginInstancePrefix", option->key) == 0) + status = cf_util_get_string(option, &dd->plugin_instance.prefix); + else if (strcasecmp("TypeInstanceOID", option->key) == 0) + status = csnmp_config_configure_data_instance(&dd->type_instance, option); + else if (strcasecmp("TypeInstancePrefix", option->key) == 0) + status = cf_util_get_string(option, &dd->type_instance.prefix); + else if (strcasecmp("HostOID", option->key) == 0) + status = csnmp_config_configure_data_instance(&dd->host, option); + else if (strcasecmp("HostPrefix", option->key) == 0) + status = cf_util_get_string(option, &dd->host.prefix); else if (strcasecmp("Values", option->key) == 0) status = csnmp_config_add_data_values(dd, option); else if (strcasecmp("Shift", option->key) == 0) @@ -364,8 +464,18 @@ static int csnmp_config_add_data(oconfig_item_t *ci) { status = csnmp_config_add_data_blacklist(dd, option); else if (strcasecmp("InvertMatch", option->key) == 0) status = cf_util_get_boolean(option, &dd->invert_match); - else { - WARNING("snmp plugin: Option `%s' not allowed here.", option->key); + else if (strcasecmp("FilterOID", option->key) == 0) { + status = csnmp_config_add_data_filter_oid(dd, option); + } else if (strcasecmp("FilterValues", option->key) == 0) { + status = csnmp_config_add_data_filter_values(dd, option); + } else if (strcasecmp("FilterIgnoreSelected", option->key) == 0) { + bool t; + status = cf_util_get_boolean(option, &t); + if (status == 0) + ignorelist_set_invert(dd->ignorelist, /* invert = */ !t); + } else { + WARNING("snmp plugin: data %s: Option `%s' not allowed here.", dd->name, + option->key); status = -1; } @@ -374,6 +484,65 @@ static int csnmp_config_add_data(oconfig_item_t *ci) { } /* for (ci->children) */ while (status == 0) { + if (dd->is_table) { + /* Set type_instance to SUBID by default */ + if (!dd->plugin_instance.configured && !dd->host.configured) + dd->type_instance.configured = true; + + if (dd->plugin_instance.value && dd->plugin_instance.configured) { + WARNING( + "snmp plugin: data %s: Option `PluginInstance' will be ignored.", + dd->name); + } + if (dd->type_instance.value && dd->type_instance.configured) { + WARNING("snmp plugin: data %s: Option `TypeInstance' will be ignored.", + dd->name); + } + if (dd->type_instance.prefix && !dd->type_instance.configured) { + WARNING("snmp plugin: data %s: Option `TypeInstancePrefix' will be " + "ignored.", + dd->name); + } + if (dd->plugin_instance.prefix && !dd->plugin_instance.configured) { + WARNING("snmp plugin: data %s: Option `PluginInstancePrefix' will be " + "ignored.", + dd->name); + } + if (dd->host.prefix && !dd->host.configured) { + WARNING("snmp plugin: data %s: Option `HostPrefix' will be ignored.", + dd->name); + } + } else { + if (dd->plugin_instance.oid.oid_len > 0) { + WARNING("snmp plugin: data %s: Option `PluginInstanceOID' will be " + "ignored.", + dd->name); + } + if (dd->type_instance.oid.oid_len > 0) { + WARNING( + "snmp plugin: data %s: Option `TypeInstanceOID' will be ignored.", + dd->name); + } + if (dd->type_instance.prefix) { + WARNING("snmp plugin: data %s: Option `TypeInstancePrefix' is ignored " + "when `Table' " + "set to `false'.", + dd->name); + } + if (dd->plugin_instance.prefix) { + WARNING("snmp plugin: data %s: Option `PluginInstancePrefix' is " + "ignored when " + "`Table' set to `false'.", + dd->name); + } + if (dd->host.prefix) { + WARNING( + "snmp plugin: data %s: Option `HostPrefix' is ignored when `Table' " + "set to `false'.", + dd->name); + } + } + if (dd->type == NULL) { WARNING("snmp plugin: `Type' not given for data `%s'", dd->name); status = -1; @@ -389,18 +558,25 @@ static int csnmp_config_add_data(oconfig_item_t *ci) { } /* while (status == 0) */ if (status != 0) { - sfree(dd->name); - sfree(dd->instance_prefix); - sfree(dd->values); - sfree(dd->ignores); - sfree(dd); + csnmp_data_definition_destroy(dd); return -1; } DEBUG("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = " - "%" PRIsz " }", - dd->name, dd->type, (dd->is_table != 0) ? "true" : "false", - dd->values_len); + "%" PRIsz ",", + dd->name, dd->type, (dd->is_table) ? "true" : "false", dd->values_len); + + DEBUG("snmp plugin: plugin_instance = %s, type_instance = %s,", + dd->plugin_instance.value, dd->type_instance.value); + + DEBUG("snmp plugin: type_instance_by_oid = %s, plugin_instance_by_oid " + "= %s }", + (dd->type_instance.oid.oid_len > 0) + ? "true" + : ((dd->type_instance.configured) ? "SUBID" : "false"), + (dd->plugin_instance.oid.oid_len > 0) + ? "true" + : ((dd->plugin_instance.configured) ? "SUBID" : "false")); if (data_head == NULL) data_head = dd; @@ -434,7 +610,7 @@ static int csnmp_config_add_host_version(host_definition_t *hd, hd->version = version; return 0; -} /* int csnmp_config_add_host_address */ +} /* int csnmp_config_add_host_version */ static int csnmp_config_add_host_collect(host_definition_t *host, oconfig_item_t *ci) { @@ -590,7 +766,6 @@ static int csnmp_config_add_host(oconfig_item_t *ci) { for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; - status = 0; if (strcasecmp("Address", option->key) == 0) status = cf_util_get_string(option, &hd->address); @@ -599,13 +774,13 @@ static int csnmp_config_add_host(oconfig_item_t *ci) { else if (strcasecmp("Version", option->key) == 0) status = csnmp_config_add_host_version(hd, option); else if (strcasecmp("Timeout", option->key) == 0) - cf_util_get_cdtime(option, &hd->timeout); + status = cf_util_get_cdtime(option, &hd->timeout); else if (strcasecmp("Retries", option->key) == 0) - cf_util_get_int(option, &hd->retries); + status = cf_util_get_int(option, &hd->retries); else if (strcasecmp("Collect", option->key) == 0) - csnmp_config_add_host_collect(hd, option); + status = csnmp_config_add_host_collect(hd, option); else if (strcasecmp("Interval", option->key) == 0) - cf_util_get_cdtime(option, &hd->interval); + status = cf_util_get_cdtime(option, &hd->interval); else if (strcasecmp("Username", option->key) == 0) status = cf_util_get_string(option, &hd->username); else if (strcasecmp("AuthProtocol", option->key) == 0) @@ -823,16 +998,16 @@ static void csnmp_host_open_session(host_definition_t *host) { /* TODO: Check if negative values wrap around. Problem: negative temperatures. */ -static value_t csnmp_value_list_to_value(struct variable_list *vl, int type, - double scale, double shift, +static value_t csnmp_value_list_to_value(const struct variable_list *vl, + int type, double scale, double shift, const char *host_name, const char *data_name) { value_t ret; uint64_t tmp_unsigned = 0; int64_t tmp_signed = 0; - _Bool defined = 1; + bool defined = 1; /* Set to true when the original SNMP type appears to have been signed. */ - _Bool prefer_signed = 0; + bool prefer_signed = 0; if ((vl->type == ASN_INTEGER) || (vl->type == ASN_UINTEGER) || (vl->type == ASN_COUNTER) @@ -1027,99 +1202,102 @@ static int csnmp_strvbcopy(char *dst, /* {{{ */ return 0; } /* }}} int csnmp_strvbcopy */ -static int csnmp_instance_list_add(csnmp_list_instances_t **head, - csnmp_list_instances_t **tail, - const struct snmp_pdu *res, - const host_definition_t *hd, - const data_definition_t *dd) { - csnmp_list_instances_t *il; - struct variable_list *vb; - oid_t vb_name; - int status; +static csnmp_cell_char_t *csnmp_get_char_cell(const struct variable_list *vb, + const oid_t *root_oid, + const host_definition_t *hd, + const data_definition_t *dd) { - /* Set vb on the last variable */ - for (vb = res->variables; (vb != NULL) && (vb->next_variable != NULL); - vb = vb->next_variable) - /* do nothing */; if (vb == NULL) - return -1; + return NULL; - csnmp_oid_init(&vb_name, vb->name, vb->name_length); - - il = calloc(1, sizeof(*il)); + csnmp_cell_char_t *il = calloc(1, sizeof(*il)); if (il == NULL) { ERROR("snmp plugin: calloc failed."); - return -1; + return NULL; } il->next = NULL; - status = csnmp_oid_suffix(&il->suffix, &vb_name, &dd->instance.oid); - if (status != 0) { + oid_t vb_name; + csnmp_oid_init(&vb_name, vb->name, vb->name_length); + + if (csnmp_oid_suffix(&il->suffix, &vb_name, root_oid) != 0) { sfree(il); - return status; + return NULL; } - /* Get instance name */ + /* Get value */ if ((vb->type == ASN_OCTET_STR) || (vb->type == ASN_BIT_STR) || (vb->type == ASN_IPADDRESS)) { - char *ptr; - - csnmp_strvbcopy(il->instance, vb, sizeof(il->instance)); - _Bool is_matched = 0; - for (uint32_t i = 0; i < dd->ignores_len; i++) { - status = fnmatch(dd->ignores[i], il->instance, 0); - if (status == 0) { - if (!dd->invert_match) { - sfree(il); - return 0; - } else { - is_matched = 1; - break; - } - } - } - if (dd->invert_match && !is_matched) { - sfree(il); - return 0; - } - for (ptr = il->instance; *ptr != '\0'; ptr++) { - if ((*ptr > 0) && (*ptr < 32)) - *ptr = ' '; - else if (*ptr == '/') - *ptr = '_'; - } - DEBUG("snmp plugin: il->instance = `%s';", il->instance); + + csnmp_strvbcopy(il->value, vb, sizeof(il->value)); + } else { value_t val = csnmp_value_list_to_value( vb, DS_TYPE_COUNTER, /* scale = */ 1.0, /* shift = */ 0.0, hd->name, dd->name); - snprintf(il->instance, sizeof(il->instance), "%" PRIu64, - (uint64_t)val.counter); + snprintf(il->value, sizeof(il->value), "%" PRIu64, (uint64_t)val.counter); } - /* TODO: Debugging output */ + return il; +} /* csnmp_cell_char_t csnmp_get_char_cell */ +static void csnmp_cells_append(csnmp_cell_char_t **head, + csnmp_cell_char_t **tail, + csnmp_cell_char_t *il) { if (*head == NULL) *head = il; else (*tail)->next = il; *tail = il; - +} /* void csnmp_cells_append */ + +static bool csnmp_ignore_instance(csnmp_cell_char_t *cell, + const data_definition_t *dd) { + bool is_matched = 0; + for (uint32_t i = 0; i < dd->ignores_len; i++) { + int status = fnmatch(dd->ignores[i], cell->value, 0); + if (status == 0) { + if (!dd->invert_match) { + return 1; + } else { + is_matched = 1; + break; + } + } + } + if (dd->invert_match && !is_matched) { + return 1; + } return 0; -} /* int csnmp_instance_list_add */ +} /* bool csnmp_ignore_instance */ + +static void csnmp_cell_replace_reserved_chars(csnmp_cell_char_t *cell) { + for (char *ptr = cell->value; *ptr != '\0'; ptr++) { + if ((*ptr > 0) && (*ptr < 32)) + *ptr = ' '; + else if (*ptr == '/') + *ptr = '_'; + } +} /* void csnmp_cell_replace_reserved_chars */ static int csnmp_dispatch_table(host_definition_t *host, data_definition_t *data, - csnmp_list_instances_t *instance_list, - csnmp_table_values_t **value_table) { + csnmp_cell_char_t *type_instance_cells, + csnmp_cell_char_t *plugin_instance_cells, + csnmp_cell_char_t *hostname_cells, + csnmp_cell_char_t *filter_cells, + csnmp_cell_value_t **value_cells) { const data_set_t *ds; value_list_t vl = VALUE_LIST_INIT; - csnmp_list_instances_t *instance_list_ptr; - csnmp_table_values_t *value_table_ptr[data->values_len]; + csnmp_cell_char_t *type_instance_cell_ptr = type_instance_cells; + csnmp_cell_char_t *plugin_instance_cell_ptr = plugin_instance_cells; + csnmp_cell_char_t *hostname_cell_ptr = hostname_cells; + csnmp_cell_char_t *filter_cell_ptr = filter_cells; + csnmp_cell_value_t *value_cell_ptr[data->values_len]; size_t i; - _Bool have_more; + bool have_more; oid_t current_suffix; ds = plugin_get_ds(data->type); @@ -1130,32 +1308,30 @@ static int csnmp_dispatch_table(host_definition_t *host, assert(ds->ds_num == data->values_len); assert(data->values_len > 0); - instance_list_ptr = instance_list; - for (i = 0; i < data->values_len; i++) - value_table_ptr[i] = value_table[i]; + value_cell_ptr[i] = value_cells[i]; - sstrncpy(vl.host, host->name, sizeof(vl.host)); - sstrncpy(vl.plugin, "snmp", sizeof(vl.plugin)); + sstrncpy(vl.plugin, data->plugin_name, sizeof(vl.plugin)); + sstrncpy(vl.type, data->type, sizeof(vl.type)); vl.interval = host->interval; have_more = 1; while (have_more) { - _Bool suffix_skipped = 0; + bool suffix_skipped = 0; /* Determine next suffix to handle. */ - if (instance_list != NULL) { - if (instance_list_ptr == NULL) { + if (type_instance_cells != NULL) { + if (type_instance_cell_ptr == NULL) { have_more = 0; continue; } - memcpy(¤t_suffix, &instance_list_ptr->suffix, + memcpy(¤t_suffix, &type_instance_cell_ptr->suffix, sizeof(current_suffix)); } else { /* no instance configured */ - csnmp_table_values_t *ptr = value_table_ptr[0]; + csnmp_cell_value_t *ptr = value_cell_ptr[0]; if (ptr == NULL) { have_more = 0; continue; @@ -1164,18 +1340,82 @@ static int csnmp_dispatch_table(host_definition_t *host, memcpy(¤t_suffix, &ptr->suffix, sizeof(current_suffix)); } - /* Update all the value_table_ptr to point at the entry with the same + /* + char oid_buffer[1024] = {0}; + snprint_objid(oid_buffer, sizeof(oid_buffer) - 1, current_suffix.oid, + current_suffix.oid_len); + DEBUG("SNMP PLUGIN: SUFFIX %s", oid_buffer); + */ + + /* Update plugin_instance_cell_ptr to point expected suffix */ + if (plugin_instance_cells != NULL) { + while ((plugin_instance_cell_ptr != NULL) && + (csnmp_oid_compare(&plugin_instance_cell_ptr->suffix, + ¤t_suffix) < 0)) + plugin_instance_cell_ptr = plugin_instance_cell_ptr->next; + + if (plugin_instance_cell_ptr == NULL) { + have_more = 0; + continue; + } + + if (csnmp_oid_compare(&plugin_instance_cell_ptr->suffix, + ¤t_suffix) > 0) { + /* This suffix is missing in the subtree. Indicate this with the + * "suffix_skipped" flag and try the next instance / suffix. */ + suffix_skipped = 1; + } + } + + /* Update hostname_cell_ptr to point expected suffix */ + if (hostname_cells != NULL) { + while ( + (hostname_cell_ptr != NULL) && + (csnmp_oid_compare(&hostname_cell_ptr->suffix, ¤t_suffix) < 0)) + hostname_cell_ptr = hostname_cell_ptr->next; + + if (hostname_cell_ptr == NULL) { + have_more = 0; + continue; + } + + if (csnmp_oid_compare(&hostname_cell_ptr->suffix, ¤t_suffix) > 0) { + /* This suffix is missing in the subtree. Indicate this with the + * "suffix_skipped" flag and try the next instance / suffix. */ + suffix_skipped = 1; + } + } + + /* Update filter_cell_ptr to point expected suffix */ + if (filter_cells != NULL) { + while ((filter_cell_ptr != NULL) && + (csnmp_oid_compare(&filter_cell_ptr->suffix, ¤t_suffix) < 0)) + filter_cell_ptr = filter_cell_ptr->next; + + if (filter_cell_ptr == NULL) { + have_more = 0; + continue; + } + + if (csnmp_oid_compare(&filter_cell_ptr->suffix, ¤t_suffix) > 0) { + /* This suffix is missing in the subtree. Indicate this with the + * "suffix_skipped" flag and try the next instance / suffix. */ + suffix_skipped = 1; + } + } + + /* Update all the value_cell_ptr to point at the entry with the same * trailing partial OID */ for (i = 0; i < data->values_len; i++) { while ( - (value_table_ptr[i] != NULL) && - (csnmp_oid_compare(&value_table_ptr[i]->suffix, ¤t_suffix) < 0)) - value_table_ptr[i] = value_table_ptr[i]->next; + (value_cell_ptr[i] != NULL) && + (csnmp_oid_compare(&value_cell_ptr[i]->suffix, ¤t_suffix) < 0)) + value_cell_ptr[i] = value_cell_ptr[i]->next; - if (value_table_ptr[i] == NULL) { + if (value_cell_ptr[i] == NULL) { have_more = 0; break; - } else if (csnmp_oid_compare(&value_table_ptr[i]->suffix, + } else if (csnmp_oid_compare(&value_cell_ptr[i]->suffix, ¤t_suffix) > 0) { /* This suffix is missing in the subtree. Indicate this with the * "suffix_skipped" flag and try the next instance / suffix. */ @@ -1189,43 +1429,98 @@ static int csnmp_dispatch_table(host_definition_t *host, /* Matching the values failed. Start from the beginning again. */ if (suffix_skipped) { - if (instance_list != NULL) - instance_list_ptr = instance_list_ptr->next; + if (type_instance_cells != NULL) + type_instance_cell_ptr = type_instance_cell_ptr->next; else - value_table_ptr[0] = value_table_ptr[0]->next; + value_cell_ptr[0] = value_cell_ptr[0]->next; continue; } -/* if we reach this line, all value_table_ptr[i] are non-NULL and are set - * to the same subid. instance_list_ptr is either NULL or points to the +/* if we reach this line, all value_cell_ptr[i] are non-NULL and are set + * to the same subid. type_instance_cell_ptr is either NULL or points to the * same subid, too. */ #if COLLECT_DEBUG for (i = 1; i < data->values_len; i++) { - assert(value_table_ptr[i] != NULL); - assert(csnmp_oid_compare(&value_table_ptr[i - 1]->suffix, - &value_table_ptr[i]->suffix) == 0); + assert(value_cell_ptr[i] != NULL); + assert(csnmp_oid_compare(&value_cell_ptr[i - 1]->suffix, + &value_cell_ptr[i]->suffix) == 0); } - assert((instance_list_ptr == NULL) || - (csnmp_oid_compare(&instance_list_ptr->suffix, - &value_table_ptr[0]->suffix) == 0)); + assert((type_instance_cell_ptr == NULL) || + (csnmp_oid_compare(&type_instance_cell_ptr->suffix, + &value_cell_ptr[0]->suffix) == 0)); + assert((plugin_instance_cell_ptr == NULL) || + (csnmp_oid_compare(&plugin_instance_cell_ptr->suffix, + &value_cell_ptr[0]->suffix) == 0)); + assert((hostname_cell_ptr == NULL) || + (csnmp_oid_compare(&hostname_cell_ptr->suffix, + &value_cell_ptr[0]->suffix) == 0)); + assert((filter_cell_ptr == NULL) || + (csnmp_oid_compare(&filter_cell_ptr->suffix, + &value_cell_ptr[0]->suffix) == 0)); #endif - sstrncpy(vl.type, data->type, sizeof(vl.type)); + /* Check the value in filter column */ + if (filter_cell_ptr && + ignorelist_match(data->ignorelist, filter_cell_ptr->value) != 0) { + if (type_instance_cells != NULL) + type_instance_cell_ptr = type_instance_cell_ptr->next; + else + value_cell_ptr[0] = value_cell_ptr[0]->next; - { + continue; + } + + /* set vl.host */ + if (data->host.configured) { char temp[DATA_MAX_NAME_LEN]; + if (hostname_cell_ptr == NULL) + csnmp_oid_to_string(temp, sizeof(temp), ¤t_suffix); + else + sstrncpy(temp, hostname_cell_ptr->value, sizeof(temp)); - if (instance_list_ptr == NULL) + if (data->host.prefix == NULL) + sstrncpy(vl.host, temp, sizeof(vl.host)); + else + snprintf(vl.host, sizeof(vl.host), "%s%s", data->host.prefix, temp); + } else { + sstrncpy(vl.host, host->name, sizeof(vl.host)); + } + + /* set vl.type_instance */ + if (data->type_instance.configured) { + char temp[DATA_MAX_NAME_LEN]; + if (type_instance_cell_ptr == NULL) csnmp_oid_to_string(temp, sizeof(temp), ¤t_suffix); else - sstrncpy(temp, instance_list_ptr->instance, sizeof(temp)); + sstrncpy(temp, type_instance_cell_ptr->value, sizeof(temp)); - if (data->instance_prefix == NULL) + if (data->type_instance.prefix == NULL) sstrncpy(vl.type_instance, temp, sizeof(vl.type_instance)); else snprintf(vl.type_instance, sizeof(vl.type_instance), "%s%s", - data->instance_prefix, temp); + data->type_instance.prefix, temp); + } else if (data->type_instance.value) { + sstrncpy(vl.type_instance, data->type_instance.value, + sizeof(vl.type_instance)); + } + + /* set vl.plugin_instance */ + if (data->plugin_instance.configured) { + char temp[DATA_MAX_NAME_LEN]; + if (plugin_instance_cell_ptr == NULL) + csnmp_oid_to_string(temp, sizeof(temp), ¤t_suffix); + else + sstrncpy(temp, plugin_instance_cell_ptr->value, sizeof(temp)); + + if (data->plugin_instance.prefix == NULL) + sstrncpy(vl.plugin_instance, temp, sizeof(vl.plugin_instance)); + else + snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s%s", + data->plugin_instance.prefix, temp); + } else if (data->plugin_instance.value) { + sstrncpy(vl.plugin_instance, data->plugin_instance.value, + sizeof(vl.plugin_instance)); } vl.values_len = data->values_len; @@ -1233,23 +1528,18 @@ static int csnmp_dispatch_table(host_definition_t *host, vl.values = values; for (i = 0; i < data->values_len; i++) - vl.values[i] = value_table_ptr[i]->value; + vl.values[i] = value_cell_ptr[i]->value; - /* If we get here `vl.type_instance' and all `vl.values' have been set - * vl.type_instance can be empty, i.e. a blank port description on a - * switch if you're using IF-MIB::ifDescr as Instance. - */ - if (vl.type_instance[0] != '\0') - plugin_dispatch_values(&vl); + plugin_dispatch_values(&vl); /* prevent leakage of pointer to local variable. */ vl.values_len = 0; vl.values = NULL; - if (instance_list != NULL) - instance_list_ptr = instance_list_ptr->next; + if (type_instance_cells != NULL) + type_instance_cell_ptr = type_instance_cell_ptr->next; else - value_table_ptr[0] = value_table_ptr[0]->next; + value_cell_ptr[0] = value_cell_ptr[0]->next; } /* while (have_more) */ return (0); @@ -1262,25 +1552,43 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) { const data_set_t *ds; - size_t oid_list_len = data->values_len + 1; + size_t oid_list_len = data->values_len; + + if (data->type_instance.oid.oid_len > 0) + oid_list_len++; + + if (data->plugin_instance.oid.oid_len > 0) + oid_list_len++; + + if (data->host.oid.oid_len > 0) + oid_list_len++; + + if (data->filter_oid.oid_len > 0) + oid_list_len++; + /* Holds the last OID returned by the device. We use this in the GETNEXT * request to proceed. */ oid_t oid_list[oid_list_len]; /* Set to false when an OID has left its subtree so we don't re-request it * again. */ - _Bool oid_list_todo[oid_list_len]; + csnmp_oid_type_t oid_list_todo[oid_list_len]; int status; 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 - * instance names. This is used to jump gaps in the table. */ - csnmp_list_instances_t *instance_list_head; - csnmp_list_instances_t *instance_list_tail; - csnmp_table_values_t **value_list_head; - csnmp_table_values_t **value_list_tail; + /* `value_list_head' and `value_cells_tail' implement a linked list for each + * value. `instance_cells_head' and `instance_cells_tail' implement a linked + * list of instance names. This is used to jump gaps in the table. */ + csnmp_cell_char_t *type_instance_cells_head = NULL; + csnmp_cell_char_t *type_instance_cells_tail = NULL; + csnmp_cell_char_t *plugin_instance_cells_head = NULL; + csnmp_cell_char_t *plugin_instance_cells_tail = NULL; + csnmp_cell_char_t *hostname_cells_head = NULL; + csnmp_cell_char_t *hostname_cells_tail = NULL; + csnmp_cell_char_t *filter_cells_head = NULL; + csnmp_cell_char_t *filter_cells_tail = NULL; + csnmp_cell_value_t **value_cells_head; + csnmp_cell_value_t **value_cells_tail; DEBUG("snmp plugin: csnmp_read_table (host = %s, data = %s)", host->name, data->name); @@ -1305,31 +1613,48 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) { } assert(data->values_len > 0); + for (i = 0; i < data->values_len; i++) + oid_list_todo[i] = OID_TYPE_VARIABLE; + /* We need a copy of all the OIDs, because GETNEXT will destroy them. */ memcpy(oid_list, data->values, data->values_len * sizeof(oid_t)); - if (data->instance.oid.oid_len > 0) - memcpy(oid_list + data->values_len, &data->instance.oid, sizeof(oid_t)); - else /* no InstanceFrom option specified. */ - oid_list_len--; - for (i = 0; i < oid_list_len; i++) - oid_list_todo[i] = 1; + if (data->type_instance.oid.oid_len > 0) { + memcpy(oid_list + i, &data->type_instance.oid, sizeof(oid_t)); + oid_list_todo[i] = OID_TYPE_TYPEINSTANCE; + i++; + } + + if (data->plugin_instance.oid.oid_len > 0) { + memcpy(oid_list + i, &data->plugin_instance.oid, sizeof(oid_t)); + oid_list_todo[i] = OID_TYPE_PLUGININSTANCE; + i++; + } + + if (data->host.oid.oid_len > 0) { + memcpy(oid_list + i, &data->host.oid, sizeof(oid_t)); + oid_list_todo[i] = OID_TYPE_HOST; + i++; + } + + if (data->filter_oid.oid_len > 0) { + memcpy(oid_list + i, &data->filter_oid, sizeof(oid_t)); + oid_list_todo[i] = OID_TYPE_FILTER; + i++; + } /* 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, - * value_list_tail will contain pointers to the tail of the lists. */ - value_list_head = calloc(data->values_len, sizeof(*value_list_head)); - value_list_tail = calloc(data->values_len, sizeof(*value_list_tail)); - if ((value_list_head == NULL) || (value_list_tail == NULL)) { + * value_cells_head will contain pointers to the heads of these linked lists, + * value_cells_tail will contain pointers to the tail of the lists. */ + value_cells_head = calloc(data->values_len, sizeof(*value_cells_head)); + value_cells_tail = calloc(data->values_len, sizeof(*value_cells_tail)); + if ((value_cells_head == NULL) || (value_cells_tail == NULL)) { ERROR("snmp plugin: csnmp_read_table: calloc failed."); - sfree(value_list_head); - sfree(value_list_tail); + sfree(value_cells_head); + sfree(value_cells_tail); return -1; } - instance_list_head = NULL; - instance_list_tail = NULL; - status = 0; while (status == 0) { req = snmp_pdu_create(SNMP_MSG_GETNEXT); @@ -1442,30 +1767,126 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) { } /* An instance is configured and the res variable we process is the - * instance value (last index) */ - if ((data->instance.oid.oid_len > 0) && (i == data->values_len)) { + * instance value */ + if (oid_list_todo[i] == OID_TYPE_TYPEINSTANCE) { + if ((vb->type == SNMP_ENDOFMIBVIEW) || + (snmp_oid_ncompare(data->type_instance.oid.oid, + data->type_instance.oid.oid_len, vb->name, + vb->name_length, + data->type_instance.oid.oid_len) != 0)) { + DEBUG("snmp plugin: host = %s; data = %s; TypeInstance left its " + "subtree.", + host->name, data->name); + oid_list_todo[i] = 0; + continue; + } + + /* Allocate a new `csnmp_cell_char_t', insert the instance name and + * add it to the list */ + csnmp_cell_char_t *cell = + csnmp_get_char_cell(vb, &data->type_instance.oid, host, data); + if (cell == NULL) { + ERROR("snmp plugin: host %s: csnmp_get_char_cell() failed.", + host->name); + status = -1; + break; + } + + if (csnmp_ignore_instance(cell, data)) { + sfree(cell); + } else { + csnmp_cell_replace_reserved_chars(cell); + + DEBUG("snmp plugin: il->type_instance = `%s';", cell->value); + csnmp_cells_append(&type_instance_cells_head, + &type_instance_cells_tail, cell); + } + } else if (oid_list_todo[i] == OID_TYPE_PLUGININSTANCE) { + if ((vb->type == SNMP_ENDOFMIBVIEW) || + (snmp_oid_ncompare(data->plugin_instance.oid.oid, + data->plugin_instance.oid.oid_len, vb->name, + vb->name_length, + data->plugin_instance.oid.oid_len) != 0)) { + DEBUG("snmp plugin: host = %s; data = %s; TypeInstance left its " + "subtree.", + host->name, data->name); + oid_list_todo[i] = 0; + continue; + } + + /* Allocate a new `csnmp_cell_char_t', insert the instance name and + * add it to the list */ + csnmp_cell_char_t *cell = + csnmp_get_char_cell(vb, &data->plugin_instance.oid, host, data); + if (cell == NULL) { + ERROR("snmp plugin: host %s: csnmp_get_char_cell() failed.", + host->name); + status = -1; + break; + } + + csnmp_cell_replace_reserved_chars(cell); + + DEBUG("snmp plugin: il->plugin_instance = `%s';", cell->value); + csnmp_cells_append(&plugin_instance_cells_head, + &plugin_instance_cells_tail, cell); + } else if (oid_list_todo[i] == OID_TYPE_HOST) { + if ((vb->type == SNMP_ENDOFMIBVIEW) || + (snmp_oid_ncompare(data->host.oid.oid, data->host.oid.oid_len, + vb->name, vb->name_length, + data->host.oid.oid_len) != 0)) { + DEBUG("snmp plugin: host = %s; data = %s; Host left its subtree.", + host->name, data->name); + oid_list_todo[i] = 0; + continue; + } + + /* Allocate a new `csnmp_cell_char_t', insert the instance name and + * add it to the list */ + csnmp_cell_char_t *cell = + csnmp_get_char_cell(vb, &data->host.oid, host, data); + if (cell == NULL) { + ERROR("snmp plugin: host %s: csnmp_get_char_cell() failed.", + host->name); + status = -1; + break; + } + + csnmp_cell_replace_reserved_chars(cell); + + DEBUG("snmp plugin: il->hostname = `%s';", cell->value); + csnmp_cells_append(&hostname_cells_head, &hostname_cells_tail, cell); + } else if (oid_list_todo[i] == OID_TYPE_FILTER) { if ((vb->type == SNMP_ENDOFMIBVIEW) || - (snmp_oid_ncompare( - data->instance.oid.oid, data->instance.oid.oid_len, vb->name, - vb->name_length, data->instance.oid.oid_len) != 0)) { - DEBUG("snmp plugin: host = %s; data = %s; Instance left its subtree.", + (snmp_oid_ncompare(data->filter_oid.oid, data->filter_oid.oid_len, + vb->name, vb->name_length, + data->filter_oid.oid_len) != 0)) { + DEBUG("snmp plugin: host = %s; data = %s; Host left its subtree.", host->name, data->name); oid_list_todo[i] = 0; continue; } - /* Allocate a new `csnmp_list_instances_t', insert the instance name and + /* Allocate a new `csnmp_cell_char_t', insert the instance name and * add it to the list */ - if (csnmp_instance_list_add(&instance_list_head, &instance_list_tail, - res, host, data) != 0) { - ERROR("snmp plugin: host %s: csnmp_instance_list_add failed.", + csnmp_cell_char_t *cell = + csnmp_get_char_cell(vb, &data->filter_oid, host, data); + if (cell == NULL) { + ERROR("snmp plugin: host %s: csnmp_get_char_cell() failed.", host->name); status = -1; break; } + + csnmp_cell_replace_reserved_chars(cell); + + DEBUG("snmp plugin: il->filter = `%s';", cell->value); + csnmp_cells_append(&filter_cells_head, &filter_cells_tail, cell); } else /* The variable we are processing is a normal value */ { - csnmp_table_values_t *vt; + assert(oid_list_todo[i] == OID_TYPE_VARIABLE); + + csnmp_cell_value_t *vt; oid_t vb_name; oid_t suffix; int ret; @@ -1484,10 +1905,9 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) { } /* Make sure the OIDs returned by the agent are increasing. Otherwise - * our - * table matching algorithm will get confused. */ - if ((value_list_tail[i] != NULL) && - (csnmp_oid_compare(&suffix, &value_list_tail[i]->suffix) <= 0)) { + * our table matching algorithm will get confused. */ + if ((value_cells_tail[i] != NULL) && + (csnmp_oid_compare(&suffix, &value_cells_tail[i]->suffix) <= 0)) { DEBUG("snmp plugin: host = %s; data = %s; i = %" PRIsz "; " "Suffix is not increasing.", host->name, data->name, i); @@ -1508,11 +1928,11 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) { memcpy(&vt->suffix, &suffix, sizeof(vt->suffix)); vt->next = NULL; - if (value_list_tail[i] == NULL) - value_list_head[i] = vt; + if (value_cells_tail[i] == NULL) + value_cells_head[i] = vt; else - value_list_tail[i]->next = vt; - value_list_tail[i] = vt; + value_cells_tail[i]->next = vt; + value_cells_tail[i] = vt; } /* Copy OID to oid_list[i] */ @@ -1531,25 +1951,45 @@ static int csnmp_read_table(host_definition_t *host, data_definition_t *data) { res = NULL; if (status == 0) - csnmp_dispatch_table(host, data, instance_list_head, value_list_head); + csnmp_dispatch_table(host, data, type_instance_cells_head, + plugin_instance_cells_head, hostname_cells_head, + filter_cells_head, value_cells_head); /* Free all allocated variables here */ - while (instance_list_head != NULL) { - csnmp_list_instances_t *next = instance_list_head->next; - sfree(instance_list_head); - instance_list_head = next; + while (type_instance_cells_head != NULL) { + csnmp_cell_char_t *next = type_instance_cells_head->next; + sfree(type_instance_cells_head); + type_instance_cells_head = next; + } + + while (plugin_instance_cells_head != NULL) { + csnmp_cell_char_t *next = plugin_instance_cells_head->next; + sfree(plugin_instance_cells_head); + plugin_instance_cells_head = next; + } + + while (hostname_cells_head != NULL) { + csnmp_cell_char_t *next = hostname_cells_head->next; + sfree(hostname_cells_head); + hostname_cells_head = next; + } + + while (filter_cells_head != NULL) { + csnmp_cell_char_t *next = filter_cells_head->next; + sfree(filter_cells_head); + filter_cells_head = next; } for (i = 0; i < data->values_len; i++) { - while (value_list_head[i] != NULL) { - csnmp_table_values_t *next = value_list_head[i]->next; - sfree(value_list_head[i]); - value_list_head[i] = next; + while (value_cells_head[i] != NULL) { + csnmp_cell_value_t *next = value_cells_head[i]->next; + sfree(value_cells_head[i]); + value_cells_head[i] = next; } } - sfree(value_list_head); - sfree(value_list_tail); + sfree(value_cells_head); + sfree(value_cells_tail); return 0; } /* int csnmp_read_table */ @@ -1599,9 +2039,14 @@ static int csnmp_read_value(host_definition_t *host, data_definition_t *data) { } sstrncpy(vl.host, host->name, sizeof(vl.host)); - sstrncpy(vl.plugin, "snmp", sizeof(vl.plugin)); + sstrncpy(vl.plugin, data->plugin_name, sizeof(vl.plugin)); sstrncpy(vl.type, data->type, sizeof(vl.type)); - sstrncpy(vl.type_instance, data->instance.string, sizeof(vl.type_instance)); + if (data->type_instance.value) + sstrncpy(vl.type_instance, data->type_instance.value, + sizeof(vl.type_instance)); + if (data->plugin_instance.value) + sstrncpy(vl.plugin_instance, data->plugin_instance.value, + sizeof(vl.plugin_instance)); vl.interval = host->interval; @@ -1713,11 +2158,7 @@ static int csnmp_shutdown(void) { while (data_this != NULL) { data_next = data_this->next; - sfree(data_this->name); - sfree(data_this->type); - sfree(data_this->values); - sfree(data_this->ignores); - sfree(data_this); + csnmp_data_definition_destroy(data_this); data_this = data_next; } diff --git a/src/snmp_agent.c b/src/snmp_agent.c index b213adb1..d65af1f1 100644 --- a/src/snmp_agent.c +++ b/src/snmp_agent.c @@ -1,7 +1,7 @@ /** * collectd - src/snmp_agent.c * - * Copyright(c) 2017 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2018 Intel Corporation. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,6 +24,7 @@ * Authors: * Roman Korynkevych * Serhiy Pshyk + * Marcin Mozejko **/ #include "collectd.h" @@ -32,6 +33,7 @@ #include "utils_avltree.h" #include "utils_cache.h" #include "utils_llist.h" +#include #include @@ -40,12 +42,32 @@ #include #define PLUGIN_NAME "snmp_agent" -#define ERR_BUF_SIZE 1024 #define TYPE_STRING -1 +#define GROUP_UNUSED -1 +#define OID_EXISTS 1 +#define MAX_KEY_SOURCES 5 +#define MAX_INDEX_KEYS 5 +#define MAX_MATCHES 5 + +/* Identifies index key source */ +enum index_key_src_e { + INDEX_HOST = 0, + INDEX_PLUGIN, + INDEX_PLUGIN_INSTANCE, + INDEX_TYPE, + INDEX_TYPE_INSTANCE +}; +typedef enum index_key_src_e index_key_src_t; -#ifndef MIN -#define MIN(x, y) ((x) < (y) ? (x) : (y)) -#endif +struct index_key_s { + index_key_src_t source; + u_char type; + char *regex; /* Pattern used to parse index key source string */ + int group; /* If pattern gives more than one group we can specify which one + we want to take */ + regex_t regex_info; +}; +typedef struct index_key_s index_key_t; struct oid_s { oid oid[MAX_OID_LEN]; @@ -54,6 +76,12 @@ struct oid_s { }; typedef struct oid_s oid_t; +struct token_s { + char *str; + netsnmp_variable_list *key; /* Points to succeeding key */ +}; +typedef struct token_s token_t; + struct table_definition_s { char *name; oid_t index_oid; @@ -61,6 +89,19 @@ struct table_definition_s { llist_t *columns; c_avl_tree_t *instance_index; c_avl_tree_t *index_instance; + c_avl_tree_t *instance_oids; /* Tells us how many OIDs registered for every + instance; */ + index_key_t index_keys[MAX_INDEX_KEYS]; /* Stores information about what each + index key represents */ + int index_keys_len; + netsnmp_variable_list *index_list_cont; /* Index key container used for + generating as well as parsing + OIDs, not thread-safe */ + c_avl_tree_t *tokens[MAX_KEY_SOURCES]; /* Input string after regex execution + will be split into sepearate + tokens */ + + bool tokens_done; /* Set to true when all tokens are generated */ }; typedef struct table_definition_s table_definition_t; @@ -71,7 +112,8 @@ struct data_definition_s { char *type; char *type_instance; const table_definition_t *table; - _Bool is_instance; + bool is_index_key; /* indicates if table column is an index key */ + int index_key_pos; /* position in indexes list */ oid_t *oids; size_t oids_len; double scale; @@ -87,10 +129,13 @@ struct snmp_agent_ctx_s { llist_t *tables; llist_t *scalars; + c_avl_tree_t *registered_oids; /* AVL tree containing all registered OIDs */ }; typedef struct snmp_agent_ctx_s snmp_agent_ctx_t; -static snmp_agent_ctx_t *g_agent = NULL; +static snmp_agent_ctx_t *g_agent; +static const char *index_opts[MAX_KEY_SOURCES] = { + "Hostname", "Plugin", "PluginInstance", "Type", "TypeInstance"}; #define CHECK_DD_TYPE(_dd, _p, _pi, _t, _ti) \ (_dd->plugin ? !strcmp(_dd->plugin, _p) : 0) && \ @@ -105,6 +150,9 @@ static int snmp_agent_set_vardata(void *dst_buf, size_t *dst_buf_len, u_char asn_type, double scale, double shift, const void *value, size_t len, int type); static int snmp_agent_unregister_oid_index(oid_t *oid, int index); +static int snmp_agent_update_instance_oids(c_avl_tree_t *tree, oid_t *index_oid, + int value); +static int num_compare(const int *a, const int *b); static u_char snmp_agent_get_asn_type(oid *oid, size_t oid_len) { struct tree *node = get_tree(oid, oid_len, g_agent->tp); @@ -131,10 +179,55 @@ static int snmp_agent_oid_to_string(char *buf, size_t buf_size, return strjoin(buf, buf_size, oid_str_ptr, o->oid_len, "."); } -static void snmp_agent_dump_data(void) { +/* Prints a configuration storing list. It handles both table columns list + and scalars list */ #if COLLECT_DEBUG +static void snmp_agent_dump_data(llist_t *list) { char oid_str[DATA_MAX_NAME_LEN]; + for (llentry_t *de = llist_head(list); de != NULL; de = de->next) { + data_definition_t *dd = de->value; + table_definition_t const *td = dd->table; + if (dd->table != NULL) + DEBUG(PLUGIN_NAME ": Column:"); + else + DEBUG(PLUGIN_NAME ": Scalar:"); + + DEBUG(PLUGIN_NAME ": Name: %s", dd->name); + if (dd->plugin) + DEBUG(PLUGIN_NAME ": Plugin: %s", dd->plugin); + if (dd->plugin_instance) + DEBUG(PLUGIN_NAME ": PluginInstance: %s", dd->plugin_instance); + if (dd->is_index_key) { + index_key_t const *index_key = &td->index_keys[dd->index_key_pos]; + + DEBUG(PLUGIN_NAME ": IndexKey:"); + DEBUG(PLUGIN_NAME ": Source: %s", index_opts[index_key->source]); + DEBUG(PLUGIN_NAME ": Type: %s", + (index_key->type == ASN_INTEGER) ? "Integer" : "String"); + if (index_key->regex) + DEBUG(PLUGIN_NAME ": Regex: %s", index_key->regex); + if (index_key->group != GROUP_UNUSED) + DEBUG(PLUGIN_NAME ": Group: %d", index_key->group); + } + if (dd->type) + DEBUG(PLUGIN_NAME ": Type: %s", dd->type); + if (dd->type_instance) + DEBUG(PLUGIN_NAME ": TypeInstance: %s", dd->type_instance); + for (size_t i = 0; i < dd->oids_len; i++) { + snmp_agent_oid_to_string(oid_str, sizeof(oid_str), &dd->oids[i]); + DEBUG(PLUGIN_NAME ": OID[%" PRIsz "]: %s", i, oid_str); + } + DEBUG(PLUGIN_NAME ": Scale: %g", dd->scale); + DEBUG(PLUGIN_NAME ": Shift: %g", dd->shift); + } +} + +/* Prints parsed configuration */ +static void snmp_agent_dump_config(void) { + char oid_str[DATA_MAX_NAME_LEN]; + + /* Printing tables */ for (llentry_t *te = llist_head(g_agent->tables); te != NULL; te = te->next) { table_definition_t *td = te->value; @@ -149,62 +242,28 @@ static void snmp_agent_dump_data(void) { DEBUG(PLUGIN_NAME ": SizeOID: %s", oid_str); } - for (llentry_t *de = llist_head(td->columns); de != NULL; de = de->next) { - data_definition_t *dd = de->value; - - DEBUG(PLUGIN_NAME ": Column:"); - DEBUG(PLUGIN_NAME ": Name: %s", dd->name); - if (dd->plugin) - DEBUG(PLUGIN_NAME ": Plugin: %s", dd->plugin); - if (dd->plugin_instance) - DEBUG(PLUGIN_NAME ": PluginInstance: %s", dd->plugin_instance); - if (dd->is_instance) - DEBUG(PLUGIN_NAME ": Instance: true"); - if (dd->type) - DEBUG(PLUGIN_NAME ": Type: %s", dd->type); - if (dd->type_instance) - DEBUG(PLUGIN_NAME ": TypeInstance: %s", dd->type_instance); - for (size_t i = 0; i < dd->oids_len; i++) { - snmp_agent_oid_to_string(oid_str, sizeof(oid_str), &dd->oids[i]); - DEBUG(PLUGIN_NAME ": OID[%" PRIsz "]: %s", i, oid_str); - } - DEBUG(PLUGIN_NAME ": Scale: %g", dd->scale); - DEBUG(PLUGIN_NAME ": Shift: %g", dd->shift); - } + snmp_agent_dump_data(td->columns); } - for (llentry_t *e = llist_head(g_agent->scalars); e != NULL; e = e->next) { - data_definition_t *dd = e->value; - - DEBUG(PLUGIN_NAME ": Scalar:"); - DEBUG(PLUGIN_NAME ": Name: %s", dd->name); - if (dd->plugin) - DEBUG(PLUGIN_NAME ": Plugin: %s", dd->plugin); - if (dd->plugin_instance) - DEBUG(PLUGIN_NAME ": PluginInstance: %s", dd->plugin_instance); - if (dd->is_instance) - DEBUG(PLUGIN_NAME ": Instance: true"); - if (dd->type) - DEBUG(PLUGIN_NAME ": Type: %s", dd->type); - if (dd->type_instance) - DEBUG(PLUGIN_NAME ": TypeInstance: %s", dd->type_instance); - for (size_t i = 0; i < dd->oids_len; i++) { - snmp_agent_oid_to_string(oid_str, sizeof(oid_str), &dd->oids[i]); - DEBUG(PLUGIN_NAME ": OID[%" PRIsz "]: %s", i, oid_str); - } - DEBUG(PLUGIN_NAME ": Scale: %g", dd->scale); - DEBUG(PLUGIN_NAME ": Shift: %g", dd->shift); - } -#endif /* COLLECT_DEBUG */ + /* Printing scalars */ + snmp_agent_dump_data(g_agent->scalars); } +#endif /* COLLECT_DEBUG */ -static int snmp_agent_validate_data(void) { +static int snmp_agent_validate_config(void) { - snmp_agent_dump_data(); +#if COLLECT_DEBUG + snmp_agent_dump_config(); +#endif for (llentry_t *te = llist_head(g_agent->tables); te != NULL; te = te->next) { table_definition_t *td = te->value; + if (!td->index_keys_len) { + ERROR(PLUGIN_NAME ": Index keys not defined for '%s'", td->name); + return -EINVAL; + } + for (llentry_t *de = llist_head(td->columns); de != NULL; de = de->next) { data_definition_t *dd = de->value; @@ -227,11 +286,10 @@ static int snmp_agent_validate_data(void) { return -EINVAL; } - if (dd->is_instance) { - + if (dd->is_index_key) { if (dd->type || dd->type_instance) { ERROR(PLUGIN_NAME ": Type and TypeInstance are not valid for " - "instance data '%s'.'%s'", + "index data '%s'.'%s'", td->name, dd->name); return -EINVAL; } @@ -267,9 +325,8 @@ static int snmp_agent_validate_data(void) { return -EINVAL; } - if (dd->is_instance) { - ERROR(PLUGIN_NAME - ": Instance flag can't be specified for scalar data '%s'", + if (dd->is_index_key) { + ERROR(PLUGIN_NAME ": Index field can't be specified for scalar data '%s'", dd->name); return -EINVAL; } @@ -283,109 +340,429 @@ static int snmp_agent_validate_data(void) { return 0; } -static void snmp_agent_generate_oid2string(oid_t *oid, size_t offset, - char *key) { - int key_len = oid->oid[offset]; - int i; +static int snmp_agent_parse_index_key(const char *input, regex_t *regex_info, + int gi, regmatch_t *m) { + regmatch_t matches[MAX_MATCHES]; - for (i = 0; i < key_len && offset < oid->oid_len; i++) - key[i] = oid->oid[++offset]; + int ret = regexec(regex_info, input, MAX_MATCHES, matches, 0); + if (!ret) { + if (gi > regex_info->re_nsub) { + ERROR(PLUGIN_NAME ": Group index %d not found. Check regex config", gi); + return -1; + } + *m = matches[gi]; + } else if (ret == REG_NOMATCH) { + ERROR(PLUGIN_NAME ": No match found"); + return -1; + } else { + char msgbuf[100]; - key[i] = '\0'; + regerror(ret, regex_info, msgbuf, sizeof(msgbuf)); + ERROR(PLUGIN_NAME ": Regex match failed: %s", msgbuf); + return -1; + } + + return 0; } -static int snmp_agent_generate_string2oid(oid_t *oid, const char *key) { - int key_len = strlen(key); +static int snmp_agent_create_token(char const *input, int t_off, int n, + c_avl_tree_t *tree, + netsnmp_variable_list *index_key) { + assert(tree != NULL); + + token_t *token = malloc(sizeof(*token)); + + if (token == NULL) + goto error; + + int *offset = malloc(sizeof(*offset)); + + if (offset == NULL) + goto free_token_error; + + int ret = 0; + + token->key = index_key; + + /* copy at most n bytes from input with offset t_off into token->str */ + input += t_off; + size_t len = strlen(input); + if (n < len) + len = n; + + token->str = malloc(len + 1); + if (token->str == NULL) + goto free_offset_error; + + memcpy(token->str, input, len); + token->str[len] = '\0'; + + *offset = t_off; + ret = c_avl_insert(tree, (void *)offset, (void *)token); + + if (ret == 0) + return 0; + + sfree(token->str); + +free_offset_error: + sfree(offset); + +free_token_error: + sfree(token); + +error: + ERROR(PLUGIN_NAME ": Could not allocate memory to create token"); + + return -1; +} + +static int snmp_agent_delete_token(int t_off, c_avl_tree_t *tree) { + token_t *token = NULL; + int *offset = NULL; + + int ret = c_avl_remove(tree, &t_off, (void **)&offset, (void **)&token); + + if (ret != 0) { + ERROR(PLUGIN_NAME ": Could not delete token"); + return -1; + } + + sfree(token->str); + sfree(token); + sfree(offset); + return 0; +} + +static int snmp_agent_get_token(c_avl_tree_t *tree, int mpos) { + + int *pos; + char *token; + int prev_pos = 0; + + c_avl_iterator_t *it = c_avl_get_iterator(tree); + while (c_avl_iterator_next(it, (void **)&pos, (void **)&token) == 0) { + if (*pos >= mpos) + break; + else + prev_pos = *pos; + } + + c_avl_iterator_destroy(it); + return prev_pos; +} + +static int snmp_agent_tokenize(const char *input, c_avl_tree_t *tokens, + const regmatch_t *m, + netsnmp_variable_list *key) { + assert(tokens != NULL); + + int ret = 0; + int len = strlen(input); + + /* Creating first token that is going to be split later */ + if (c_avl_size(tokens) == 0) { + ret = snmp_agent_create_token(input, 0, len, tokens, NULL); + if (ret != 0) + return ret; + } + + /* Divide token that contains current match into two */ + int t_pos = snmp_agent_get_token(tokens, m->rm_so); + ret = snmp_agent_delete_token(t_pos, tokens); + + if (ret != 0) + return -1; + + ret = snmp_agent_create_token(input, t_pos, m->rm_so - t_pos, tokens, key); + + if (ret != 0) + return -1; + + if (len - m->rm_eo > 1) { + ret = snmp_agent_create_token(input, m->rm_eo, len - m->rm_eo + 1, tokens, + NULL); + if (ret != 0) { + snmp_agent_delete_token(t_pos, tokens); + return -1; + } + } - oid->oid[oid->oid_len++] = key_len; - for (int i = 0; i < key_len; i++) { - oid->oid[oid->oid_len++] = key[i]; - if (oid->oid_len >= MAX_OID_LEN) { - ERROR(PLUGIN_NAME ": Conversion key string %s to OID failed", key); + return 0; +} + +static int snmp_agent_fill_index_list(table_definition_t *td, + value_list_t const *vl) { + int ret; + int i; + netsnmp_variable_list *key = td->index_list_cont; + char const *ptr; + + for (i = 0; i < td->index_keys_len; i++) { + /* var should never be NULL */ + assert(key != NULL); + ptr = NULL; + ret = 0; + const index_key_src_t source = td->index_keys[i].source; + c_avl_tree_t *const tokens = td->tokens[source]; + /* Generating list filled with all data necessary to generate an OID */ + switch (source) { + case INDEX_HOST: + ptr = vl->host; + break; + case INDEX_PLUGIN: + ptr = vl->plugin; + break; + case INDEX_PLUGIN_INSTANCE: + ptr = vl->plugin_instance; + break; + case INDEX_TYPE: + ptr = vl->type; + break; + case INDEX_TYPE_INSTANCE: + ptr = vl->type_instance; + break; + default: + ERROR(PLUGIN_NAME ": Unknown index key source provided"); return -EINVAL; } + if (ret != 0) + return -EINVAL; + + /* Parsing input string if necessary */ + if (td->index_keys[i].regex) { + regmatch_t m; + + /* Parsing input string */ + ret = snmp_agent_parse_index_key(ptr, &td->index_keys[i].regex_info, + td->index_keys[i].group, &m); + if (ret != 0) { + ERROR(PLUGIN_NAME ": Error executing regex"); + return ret; + } + + /* Tokenizing input string if not done yet */ + if (td->tokens_done == false) + ret = snmp_agent_tokenize(ptr, tokens, &m, key); + + if (ret != 0) + return -1; + + if (td->index_keys[i].type == ASN_INTEGER) { + int val = strtol(ptr + m.rm_so, NULL, 0); + +#ifdef HAVE_NETSNMP_OLD_API + ret = snmp_set_var_value(key, (const u_char *)&val, sizeof(val)); +#else + ret = snmp_set_var_value(key, &val, sizeof(val)); +#endif + } else +#ifdef HAVE_NETSNMP_OLD_API + ret = snmp_set_var_value(key, (const u_char *)(ptr + m.rm_so), + m.rm_eo - m.rm_so); +#else + ret = snmp_set_var_value(key, ptr + m.rm_so, m.rm_eo - m.rm_so); +#endif + } else +#ifdef HAVE_NETSNMP_OLD_API + ret = snmp_set_var_value(key, (const u_char *)ptr, strlen(ptr)); +#else + ret = snmp_set_var_value(key, ptr, strlen(ptr)); +#endif + key = key->next_variable; } + /* Tokens for all source strings are generated */ + for (i = 0; i < MAX_KEY_SOURCES; i++) + td->tokens_done = true; + + return 0; +} + +static int snmp_agent_prep_index_list(table_definition_t const *td, + netsnmp_variable_list **index_list) { + /* Generating list having only the structure (with no values) letting us + * know how to parse an OID*/ + for (int i = 0; i < td->index_keys_len; i++) { + switch (td->index_keys[i].source) { + case INDEX_HOST: + case INDEX_PLUGIN: + case INDEX_PLUGIN_INSTANCE: + case INDEX_TYPE: + case INDEX_TYPE_INSTANCE: + snmp_varlist_add_variable(index_list, NULL, 0, td->index_keys[i].type, + NULL, 0); + break; + default: + ERROR(PLUGIN_NAME ": Unknown index key source provided"); + return -EINVAL; + } + } return 0; } -static int snmp_agent_register_oid_string(oid_t *oid, const char *key, +static int snmp_agent_generate_index(table_definition_t *td, + value_list_t const *vl, oid_t *index_oid) { + + /* According to given information by index_keys list + * index OID is going to be built + */ + int ret = snmp_agent_fill_index_list(td, vl); + if (ret != 0) + return -EINVAL; + + /* Building only index part OID (without table prefix OID) */ + ret = build_oid_noalloc(index_oid->oid, sizeof(index_oid->oid), + &index_oid->oid_len, NULL, 0, td->index_list_cont); + if (ret != SNMPERR_SUCCESS) { + ERROR(PLUGIN_NAME ": Error building index OID"); + return -EINVAL; + } + + return 0; +} + +/* It appends one OID to the end of another */ +static int snmp_agent_append_oid(oid_t *out, const oid_t *in) { + + if (out->oid_len + in->oid_len > MAX_OID_LEN) { + ERROR(PLUGIN_NAME ": Cannot create OID. Output length is too long!"); + return -EINVAL; + } + memcpy(&out->oid[out->oid_len], in->oid, in->oid_len * sizeof(oid)); + out->oid_len += in->oid_len; + + return 0; +} + +static int snmp_agent_register_oid_string(const oid_t *oid, + const oid_t *index_oid, Netsnmp_Node_Handler *handler) { oid_t new_oid; memcpy(&new_oid, oid, sizeof(*oid)); - int ret = snmp_agent_generate_string2oid(&new_oid, key); + /* Concatenating two string oids */ + int ret = snmp_agent_append_oid(&new_oid, index_oid); if (ret != 0) return ret; return snmp_agent_register_oid(&new_oid, handler); } -static int snmp_agent_unregister_oid_string(oid_t *oid, const char *key) { +static int snmp_agent_unregister_oid(oid_t *oid) { + int ret = c_avl_remove(g_agent->registered_oids, (void *)oid, NULL, NULL); + + if (ret != 0) + ERROR(PLUGIN_NAME ": Could not delete registration info"); + + return unregister_mib(oid->oid, oid->oid_len); +} + +static int snmp_agent_unregister_oid_string(oid_t *oid, + const oid_t *index_oid) { oid_t new_oid; + char oid_str[DATA_MAX_NAME_LEN]; memcpy(&new_oid, oid, sizeof(*oid)); - int ret = snmp_agent_generate_string2oid(&new_oid, key); + /* Concatenating two string oids */ + int ret = snmp_agent_append_oid(&new_oid, index_oid); if (ret != 0) return ret; - return unregister_mib(new_oid.oid, new_oid.oid_len); + snmp_agent_oid_to_string(oid_str, sizeof(oid_str), &new_oid); + DEBUG(PLUGIN_NAME ": Unregistered handler for OID (%s)", oid_str); + + return snmp_agent_unregister_oid(&new_oid); } -static int snmp_agent_table_row_remove(table_definition_t *td, - const char *instance) { +static void snmp_agent_table_data_remove(data_definition_t *dd, + table_definition_t *td, + oid_t *index_oid) { int *index = NULL; - char *ins = NULL; + oid_t *ind_oid = NULL; if (td->index_oid.oid_len) { - if ((c_avl_get(td->instance_index, instance, (void **)&index) != 0) || - (c_avl_get(td->index_instance, index, (void **)&ins) != 0)) - return 0; + if ((c_avl_get(td->instance_index, index_oid, (void **)&index) != 0) || + (c_avl_get(td->index_instance, index, NULL) != 0)) + return; } else { - if (c_avl_get(td->instance_index, instance, (void **)&ins) != 0) - return 0; + if (c_avl_get(td->instance_index, index_oid, NULL) != 0) + return; } pthread_mutex_lock(&g_agent->agentx_lock); - if (td->index_oid.oid_len) - snmp_agent_unregister_oid_index(&td->index_oid, *index); + int reg_oids = -1; /* Number of registered oids for given instance */ + + for (size_t i = 0; i < dd->oids_len; i++) { + if (td->index_oid.oid_len) + snmp_agent_unregister_oid_index(&dd->oids[i], *index); + else + snmp_agent_unregister_oid_string(&dd->oids[i], index_oid); + + reg_oids = + snmp_agent_update_instance_oids(td->instance_oids, index_oid, -1); + } + /* Checking if any metrics are left registered */ + if (reg_oids != 0) { + pthread_mutex_unlock(&g_agent->agentx_lock); + return; + } + + /* All metrics have been unregistered. Unregistering index key OIDs */ + int keys_processed = 0; for (llentry_t *de = llist_head(td->columns); de != NULL; de = de->next) { - data_definition_t *dd = de->value; + data_definition_t *idd = de->value; + + if (!idd->is_index_key) + continue; - for (size_t i = 0; i < dd->oids_len; i++) + for (size_t i = 0; i < idd->oids_len; i++) if (td->index_oid.oid_len) - snmp_agent_unregister_oid_index(&dd->oids[i], *index); + snmp_agent_unregister_oid_index(&idd->oids[i], *index); else - snmp_agent_unregister_oid_string(&dd->oids[i], ins); - } + snmp_agent_unregister_oid_string(&idd->oids[i], index_oid); + if (++keys_processed >= td->index_keys_len) + break; + } pthread_mutex_unlock(&g_agent->agentx_lock); - DEBUG(PLUGIN_NAME ": Removed row for '%s' table [%d, %s]", td->name, - (index != NULL) ? *index : -1, ins); + /* All OIDs have been unregistered so we dont need this instance registered + * as well */ + char index_str[DATA_MAX_NAME_LEN]; + + if (index == NULL) + snmp_agent_oid_to_string(index_str, sizeof(index_str), index_oid); + else + snprintf(index_str, sizeof(index_str), "%d", *index); notification_t n = { .severity = NOTIF_WARNING, .time = cdtime(), .plugin = PLUGIN_NAME}; sstrncpy(n.host, hostname_g, sizeof(n.host)); - sstrncpy(n.plugin_instance, ins, sizeof(n.plugin_instance)); snprintf(n.message, sizeof(n.message), - "Removed data row from table %s instance %s index %d", td->name, ins, - (index != NULL) ? *index : -1); + "Removed data row from table %s with index %s", td->name, index_str); + DEBUG(PLUGIN_NAME ": %s", n.message); plugin_dispatch_notification(&n); - if (td->index_oid.oid_len) { - c_avl_remove(td->index_instance, index, NULL, (void **)&ins); - c_avl_remove(td->instance_index, instance, NULL, (void **)&index); + int *val = NULL; + + c_avl_remove(td->instance_oids, index_oid, NULL, (void **)&val); + sfree(val); + + if (index != NULL) { + pthread_mutex_lock(&g_agent->agentx_lock); + snmp_agent_unregister_oid_index(&td->index_oid, *index); + pthread_mutex_unlock(&g_agent->agentx_lock); + + c_avl_remove(td->index_instance, index, NULL, (void **)&ind_oid); + c_avl_remove(td->instance_index, index_oid, NULL, (void **)&index); sfree(index); - sfree(ins); + sfree(ind_oid); } else { - c_avl_remove(td->instance_index, instance, NULL, (void **)&ins); - sfree(ins); + c_avl_remove(td->instance_index, index_oid, NULL, NULL); } - - return 0; } static int snmp_agent_clear_missing(const value_list_t *vl, @@ -399,11 +776,23 @@ static int snmp_agent_clear_missing(const value_list_t *vl, for (llentry_t *de = llist_head(td->columns); de != NULL; de = de->next) { data_definition_t *dd = de->value; - if (!dd->is_instance) { + if (!dd->is_index_key) { if (CHECK_DD_TYPE(dd, vl->plugin, vl->plugin_instance, vl->type, vl->type_instance)) { - snmp_agent_table_row_remove(td, vl->plugin_instance); - return 0; + oid_t *index_oid = calloc(1, sizeof(*index_oid)); + + if (index_oid == NULL) { + ERROR(PLUGIN_NAME ": Could not allocate memory for index_oid"); + return -ENOMEM; + } + + int ret = snmp_agent_generate_index(td, vl, index_oid); + + if (ret == 0) + snmp_agent_table_data_remove(dd, td, index_oid); + sfree(index_oid); + + return ret; } } } @@ -444,23 +833,22 @@ static void snmp_agent_free_table_columns(table_definition_t *td) { if (td->index_oid.oid_len) { int *index; - char *instance; + oid_t *index_oid; c_avl_iterator_t *iter = c_avl_get_iterator(td->index_instance); - while (c_avl_iterator_next(iter, (void *)&index, (void *)&instance) == + while (c_avl_iterator_next(iter, (void *)&index, (void *)&index_oid) == 0) { for (size_t i = 0; i < dd->oids_len; i++) snmp_agent_unregister_oid_index(&dd->oids[i], *index); } c_avl_iterator_destroy(iter); } else { - char *instance; + oid_t *index_oid; c_avl_iterator_t *iter = c_avl_get_iterator(dd->table->instance_index); - while (c_avl_iterator_next(iter, (void *)&instance, (void *)&instance) == - 0) { + while (c_avl_iterator_next(iter, (void *)&index_oid, NULL) == 0) { for (size_t i = 0; i < dd->oids_len; i++) - snmp_agent_unregister_oid_string(&dd->oids[i], instance); + snmp_agent_unregister_oid_string(&dd->oids[i], index_oid); } c_avl_iterator_destroy(iter); } @@ -480,13 +868,14 @@ static void snmp_agent_free_table(table_definition_t **td) { if ((*td)->size_oid.oid_len) unregister_mib((*td)->size_oid.oid, (*td)->size_oid.oid_len); + oid_t *index_oid; + /* Unregister Index OIDs */ if ((*td)->index_oid.oid_len) { int *index; - char *instance; c_avl_iterator_t *iter = c_avl_get_iterator((*td)->index_instance); - while (c_avl_iterator_next(iter, (void *)&index, (void *)&instance) == 0) + while (c_avl_iterator_next(iter, (void **)&index, (void **)&index_oid) == 0) snmp_agent_unregister_oid_index(&(*td)->index_oid, *index); c_avl_iterator_destroy(iter); @@ -497,6 +886,15 @@ static void snmp_agent_free_table(table_definition_t **td) { void *key = NULL; void *value = NULL; + int *num = NULL; + + /* Removing data from instance_oids, leaving key pointers since they are still + * used in other AVL trees */ + c_avl_iterator_t *iter = c_avl_get_iterator((*td)->instance_oids); + while (c_avl_iterator_next(iter, (void **)&index_oid, (void **)&num) == 0) + sfree(num); + c_avl_iterator_destroy(iter); + c_avl_destroy((*td)->instance_oids); /* index_instance and instance_index contain the same pointers */ c_avl_destroy((*td)->index_instance); @@ -511,20 +909,189 @@ static void snmp_agent_free_table(table_definition_t **td) { c_avl_destroy((*td)->instance_index); (*td)->instance_index = NULL; } + snmp_free_varbind((*td)->index_list_cont); + + int i; + token_t *tok = NULL; + for (i = 0; i < (*td)->index_keys_len; i++) { + sfree((*td)->index_keys[i].regex); + regfree(&(*td)->index_keys[i].regex_info); + } + for (i = 0; i < MAX_KEY_SOURCES; i++) + if ((*td)->tokens[i] != NULL) { + while (c_avl_pick((*td)->tokens[i], &key, (void **)&tok) == 0) { + sfree(key); + sfree(tok->str); + sfree(tok); + } + c_avl_destroy((*td)->tokens[i]); + (*td)->tokens[i] = NULL; + } sfree((*td)->name); sfree(*td); return; } +static int snmp_agent_parse_oid_index_keys(const table_definition_t *td, + oid_t *index_oid) { + int ret = parse_oid_indexes(index_oid->oid, index_oid->oid_len, + td->index_list_cont); + if (ret != SNMPERR_SUCCESS) + ERROR(PLUGIN_NAME ": index OID parse error!"); + return ret; +} + +static int snmp_agent_build_name(char **name, c_avl_tree_t *tokens) { + + int *pos; + token_t *tok; + char str[DATA_MAX_NAME_LEN]; + char out[DATA_MAX_NAME_LEN] = {0}; + c_avl_iterator_t *it = c_avl_get_iterator(tokens); + + if (it == NULL) { + ERROR(PLUGIN_NAME ": Error getting tokens list iterator"); + return -1; + } + + while (c_avl_iterator_next(it, (void **)&pos, (void **)&tok) == 0) { + strncat(out, tok->str, strlen(tok->str)); + if (tok->key != NULL) { + if (tok->key->type == ASN_INTEGER) { + snprintf(str, sizeof(str), "%ld", *tok->key->val.integer); + strncat(out, str, strlen(str)); + } else { /* OCTET_STR */ + strncat(out, (char *)tok->key->val.string, + strlen((char *)tok->key->val.string)); + } + } + } + *name = strdup(out); + c_avl_iterator_destroy(it); + + if (*name == NULL) { + ERROR(PLUGIN_NAME ": Could not allocate memory"); + return -ENOMEM; + } + + return 0; +} + +static int snmp_agent_format_name(char *name, int name_len, + data_definition_t *dd, oid_t *index_oid) { + + int ret = 0; + + if (index_oid == NULL) { + /* It's a scalar */ + format_name(name, name_len, hostname_g, dd->plugin, dd->plugin_instance, + dd->type, dd->type_instance); + } else { + /* Need to parse string index OID */ + const table_definition_t *td = dd->table; + ret = snmp_agent_parse_oid_index_keys(td, index_oid); + if (ret != 0) + return ret; + + int i = 0; + netsnmp_variable_list *key = td->index_list_cont; + char str[DATA_MAX_NAME_LEN]; + char *fields[MAX_KEY_SOURCES] = {hostname_g, dd->plugin, + dd->plugin_instance, dd->type, + dd->type_instance}; + + /* Looking for simple keys only */ + while (key != NULL) { + if (!td->index_keys[i].regex) { + index_key_src_t source = td->index_keys[i].source; + + if (source < INDEX_HOST || source > INDEX_TYPE_INSTANCE) { + ERROR(PLUGIN_NAME ": Unkown index key source!"); + return -EINVAL; + } + + if (td->index_keys[i].type == ASN_INTEGER) { + snprintf(str, sizeof(str), "%ld", *key->val.integer); + fields[source] = str; + } else /* OCTET_STR */ + fields[source] = (char *)key->val.string; + } + key = key->next_variable; + i++; + } + + /* Keys with regexes */ + for (i = 0; i < MAX_KEY_SOURCES; i++) { + if (td->tokens[i] == NULL) + continue; + ret = snmp_agent_build_name(&fields[i], td->tokens[i]); + if (ret != 0) + return ret; + } + format_name(name, name_len, fields[INDEX_HOST], fields[INDEX_PLUGIN], + fields[INDEX_PLUGIN_INSTANCE], fields[INDEX_TYPE], + fields[INDEX_TYPE_INSTANCE]); + for (i = 0; i < MAX_KEY_SOURCES; i++) { + if (td->tokens[i]) + sfree(fields[i]); + } + } + + return 0; +} + static int snmp_agent_form_reply(struct netsnmp_request_info_s *requests, - data_definition_t *dd, char *instance, + data_definition_t *dd, oid_t *index_oid, int oid_index) { + int ret; + + if (dd->is_index_key) { + const table_definition_t *td = dd->table; + int ret = snmp_agent_parse_oid_index_keys(td, index_oid); + + if (ret != 0) + return ret; + + netsnmp_variable_list *key = td->index_list_cont; + /* Searching index key */ + for (int pos = 0; pos < dd->index_key_pos; pos++) + key = key->next_variable; + + requests->requestvb->type = td->index_keys[dd->index_key_pos].type; + + if (requests->requestvb->type == ASN_INTEGER) +#ifdef HAVE_NETSNMP_OLD_API + snmp_set_var_typed_value(requests->requestvb, requests->requestvb->type, + (const u_char *)key->val.integer, + sizeof(*key->val.integer)); +#else + snmp_set_var_typed_value(requests->requestvb, requests->requestvb->type, + key->val.integer, sizeof(*key->val.integer)); +#endif + else /* OCTET_STR */ +#ifdef HAVE_NETSNMP_OLD_API + snmp_set_var_typed_value(requests->requestvb, requests->requestvb->type, + (const u_char *)key->val.string, + strlen((const char *)key->val.string)); +#else + snmp_set_var_typed_value(requests->requestvb, requests->requestvb->type, + key->val.string, + strlen((const char *)key->val.string)); +#endif + + pthread_mutex_unlock(&g_agent->lock); + + return SNMP_ERR_NOERROR; + } + char name[DATA_MAX_NAME_LEN]; - format_name(name, sizeof(name), hostname_g, dd->plugin, - instance ? instance : dd->plugin_instance, dd->type, - dd->type_instance); + + ret = snmp_agent_format_name(name, sizeof(name), dd, index_oid); + if (ret != 0) + return ret; + DEBUG(PLUGIN_NAME ": Identifier '%s'", name); value_t *values; @@ -535,7 +1102,7 @@ static int snmp_agent_form_reply(struct netsnmp_request_info_s *requests, return SNMP_NOSUCHINSTANCE; } - int ret = uc_get_value_by_name(name, &values, &values_num); + ret = uc_get_value_by_name(name, &values, &values_num); if (ret != 0) { ERROR(PLUGIN_NAME ": Failed to get value for '%s'", name); @@ -571,14 +1138,14 @@ snmp_agent_table_oid_handler(struct netsnmp_mib_handler_s *handler, struct netsnmp_agent_request_info_s *reqinfo, struct netsnmp_request_info_s *requests) { - if (reqinfo->mode != MODE_GET && reqinfo->mode != MODE_GETNEXT) { + if (reqinfo->mode != MODE_GET) { DEBUG(PLUGIN_NAME ": Not supported request mode (%d)", reqinfo->mode); return SNMP_ERR_NOERROR; } pthread_mutex_lock(&g_agent->lock); - oid_t oid; + oid_t oid; /* Requested OID */ memcpy(oid.oid, requests->requestvb->name, sizeof(oid.oid[0]) * requests->requestvb->name_length); oid.oid_len = requests->requestvb->name_length; @@ -588,6 +1155,7 @@ snmp_agent_table_oid_handler(struct netsnmp_mib_handler_s *handler, snmp_agent_oid_to_string(oid_str, sizeof(oid_str), &oid); DEBUG(PLUGIN_NAME ": Get request received for table OID '%s'", oid_str); #endif + oid_t index_oid; /* Index part of requested OID */ for (llentry_t *te = llist_head(g_agent->tables); te != NULL; te = te->next) { table_definition_t *td = te->value; @@ -598,49 +1166,37 @@ snmp_agent_table_oid_handler(struct netsnmp_mib_handler_s *handler, for (size_t i = 0; i < dd->oids_len; i++) { int ret = snmp_oid_ncompare(oid.oid, oid.oid_len, dd->oids[i].oid, dd->oids[i].oid_len, - MIN(oid.oid_len, dd->oids[i].oid_len)); + SNMP_MIN(oid.oid_len, dd->oids[i].oid_len)); if (ret != 0) continue; - char *instance; + /* Calculating OID length for index part */ + index_oid.oid_len = oid.oid_len - dd->oids[i].oid_len; + /* Fetching index part of the OID */ + memcpy(index_oid.oid, &oid.oid[dd->oids[i].oid_len], + index_oid.oid_len * sizeof(*oid.oid)); - if (!td->index_oid.oid_len) { - char key[MAX_OID_LEN]; - - memset(key, 0, sizeof(key)); - snmp_agent_generate_oid2string( - &oid, MIN(oid.oid_len, dd->oids[i].oid_len), key); + char index_str[DATA_MAX_NAME_LEN]; + snmp_agent_oid_to_string(index_str, sizeof(index_str), &index_oid); - ret = c_avl_get(td->instance_index, key, (void **)&instance); - if (ret != 0) { - DEBUG(PLUGIN_NAME ": Nonexisting index string '%s' requested", key); - pthread_mutex_unlock(&g_agent->lock); - return SNMP_NOSUCHINSTANCE; - } + if (!td->index_oid.oid_len) { + ret = c_avl_get(td->instance_index, &index_oid, NULL); } else { - int index = oid.oid[oid.oid_len - 1]; + oid_t *temp_oid; - ret = c_avl_get(td->index_instance, &index, (void **)&instance); - if (ret != 0) { - DEBUG(PLUGIN_NAME ": Nonexisting index '%d' requested", index); - pthread_mutex_unlock(&g_agent->lock); - return SNMP_NOSUCHINSTANCE; - } + assert(index_oid.oid_len == 1); + ret = c_avl_get(td->index_instance, (int *)&index_oid.oid[0], + (void **)&temp_oid); + memcpy(&index_oid, temp_oid, sizeof(index_oid)); } - if (dd->is_instance) { - requests->requestvb->type = ASN_OCTET_STR; - snmp_set_var_typed_value( - requests->requestvb, requests->requestvb->type, - (const u_char *)instance, strlen((instance))); - + if (ret != 0) { + INFO(PLUGIN_NAME ": Non-existing index (%s) requested", index_str); pthread_mutex_unlock(&g_agent->lock); - - return SNMP_ERR_NOERROR; + return SNMP_NOSUCHINSTANCE; } - ret = snmp_agent_form_reply(requests, dd, instance, i); - + ret = snmp_agent_form_reply(requests, dd, &index_oid, i); pthread_mutex_unlock(&g_agent->lock); return ret; @@ -659,7 +1215,7 @@ static int snmp_agent_table_index_oid_handler( struct netsnmp_agent_request_info_s *reqinfo, struct netsnmp_request_info_s *requests) { - if (reqinfo->mode != MODE_GET && reqinfo->mode != MODE_GETNEXT) { + if (reqinfo->mode != MODE_GET) { DEBUG(PLUGIN_NAME ": Not supported request mode (%d)", reqinfo->mode); return SNMP_ERR_NOERROR; } @@ -675,15 +1231,15 @@ static int snmp_agent_table_index_oid_handler( table_definition_t *td = te->value; if (td->index_oid.oid_len && - (snmp_oid_ncompare(oid.oid, oid.oid_len, td->index_oid.oid, - td->index_oid.oid_len, - MIN(oid.oid_len, td->index_oid.oid_len)) == 0)) { + (snmp_oid_ncompare( + oid.oid, oid.oid_len, td->index_oid.oid, td->index_oid.oid_len, + SNMP_MIN(oid.oid_len, td->index_oid.oid_len)) == 0)) { DEBUG(PLUGIN_NAME ": Handle '%s' table index OID", td->name); int index = oid.oid[oid.oid_len - 1]; - int ret = c_avl_get(td->index_instance, &index, &(void *){NULL}); + int ret = c_avl_get(td->index_instance, &index, NULL); if (ret != 0) { /* nonexisting index requested */ pthread_mutex_unlock(&g_agent->lock); @@ -711,7 +1267,7 @@ static int snmp_agent_table_size_oid_handler( struct netsnmp_agent_request_info_s *reqinfo, struct netsnmp_request_info_s *requests) { - if (reqinfo->mode != MODE_GET && reqinfo->mode != MODE_GETNEXT) { + if (reqinfo->mode != MODE_GET) { DEBUG(PLUGIN_NAME ": Not supported request mode (%d)", reqinfo->mode); return SNMP_ERR_NOERROR; } @@ -731,12 +1287,16 @@ static int snmp_agent_table_size_oid_handler( if (td->size_oid.oid_len && (snmp_oid_ncompare(oid.oid, oid.oid_len, td->size_oid.oid, td->size_oid.oid_len, - MIN(oid.oid_len, td->size_oid.oid_len)) == 0)) { + SNMP_MIN(oid.oid_len, td->size_oid.oid_len)) == 0)) { DEBUG(PLUGIN_NAME ": Handle '%s' table size OID", td->name); - long size = c_avl_size(td->index_instance); + long size; + if (td->index_oid.oid_len) + size = c_avl_size(td->index_instance); + else + size = c_avl_size(td->instance_index); - requests->requestvb->type = td->size_oid.type; + requests->requestvb->type = ASN_INTEGER; snmp_set_var_typed_value(requests->requestvb, requests->requestvb->type, (const u_char *)&size, sizeof(size)); @@ -757,7 +1317,7 @@ snmp_agent_scalar_oid_handler(struct netsnmp_mib_handler_s *handler, struct netsnmp_agent_request_info_s *reqinfo, struct netsnmp_request_info_s *requests) { - if (reqinfo->mode != MODE_GET && reqinfo->mode != MODE_GETNEXT) { + if (reqinfo->mode != MODE_GET) { DEBUG(PLUGIN_NAME ": Not supported request mode (%d)", reqinfo->mode); return SNMP_ERR_NOERROR; } @@ -860,10 +1420,14 @@ static int snmp_agent_config_data_oids(data_definition_t *dd, return -EINVAL; } - if (dd->oids != NULL) - sfree(dd->oids); + if (dd->oids != NULL) { + WARNING(PLUGIN_NAME ": OIDs can be configured only once for each data"); + return -EINVAL; + } + dd->oids_len = 0; dd->oids = calloc(ci->values_num, sizeof(*dd->oids)); + if (dd->oids == NULL) return -ENOMEM; dd->oids_len = (size_t)ci->values_num; @@ -935,98 +1499,125 @@ static int snmp_agent_config_table_index_oid(table_definition_t *td, return 0; } -static int snmp_agent_config_table_data(table_definition_t *td, - oconfig_item_t *ci) { - data_definition_t *dd; - int ret = 0; +/* Getting index key source that will represent table row */ +static int snmp_agent_config_index_key_source(table_definition_t *td, + data_definition_t *dd, + oconfig_item_t *ci) { + char *val = NULL; - assert(ci != NULL); + int ret = cf_util_get_string(ci, &val); + if (ret != 0) + return -1; - dd = calloc(1, sizeof(*dd)); - if (dd == NULL) { - ERROR(PLUGIN_NAME ": Failed to allocate memory for table data definition"); - return -ENOMEM; + bool match = false; + + for (int i = 0; i < MAX_KEY_SOURCES; i++) { + if (strcasecmp(index_opts[i], (const char *)val) == 0) { + td->index_keys[td->index_keys_len].source = i; + td->index_keys[td->index_keys_len].group = GROUP_UNUSED; + td->index_keys[td->index_keys_len].regex = NULL; + match = 1; + break; + } } - ret = cf_util_get_string(ci, &dd->name); - if (ret != 0) { - sfree(dd); - return -1; + if (!match) { + ERROR(PLUGIN_NAME ": Failed to parse index key source: '%s'", val); + sfree(val); + return -EINVAL; } - dd->scale = 1.0; - dd->shift = 0.0; + sfree(val); + dd->index_key_pos = td->index_keys_len++; + dd->is_index_key = true; - dd->table = td; + return 0; +} - for (int i = 0; i < ci->children_num; i++) { - oconfig_item_t *option = ci->children + i; +/* Getting format string used to parse values from index key source */ +static int snmp_agent_config_index_key_regex(table_definition_t *td, + data_definition_t *dd, + oconfig_item_t *ci) { + index_key_t *index_key = &td->index_keys[dd->index_key_pos]; - if (strcasecmp("Instance", option->key) == 0) - ret = cf_util_get_boolean(option, &dd->is_instance); - else if (strcasecmp("Plugin", option->key) == 0) - ret = cf_util_get_string(option, &dd->plugin); - else if (strcasecmp("PluginInstance", option->key) == 0) - ret = cf_util_get_string(option, &dd->plugin_instance); - else if (strcasecmp("Type", option->key) == 0) - ret = cf_util_get_string(option, &dd->type); - else if (strcasecmp("TypeInstance", option->key) == 0) - ret = cf_util_get_string(option, &dd->type_instance); - else if (strcasecmp("Shift", option->key) == 0) - ret = cf_util_get_double(option, &dd->shift); - else if (strcasecmp("Scale", option->key) == 0) - ret = cf_util_get_double(option, &dd->scale); - else if (strcasecmp("OIDs", option->key) == 0) - ret = snmp_agent_config_data_oids(dd, option); - else { - WARNING(PLUGIN_NAME ": Option `%s' not allowed here", option->key); - ret = -1; - } + int ret = cf_util_get_string(ci, &index_key->regex); + if (ret != 0) + return -1; - if (ret != 0) { - snmp_agent_free_data(&dd); - return -1; - } + ret = regcomp(&index_key->regex_info, index_key->regex, REG_EXTENDED); + if (ret) { + ERROR(PLUGIN_NAME ": Could not compile regex for %s", dd->name); + return -1; } - llentry_t *entry = llentry_create(dd->name, dd); - if (entry == NULL) { - snmp_agent_free_data(&dd); - return -ENOMEM; + index_key_src_t source = index_key->source; + if (td->tokens[source] == NULL) { + td->tokens[source] = + c_avl_create((int (*)(const void *, const void *))num_compare); + if (td->tokens[source] == NULL) { + ERROR(PLUGIN_NAME ": Could not allocate memory for AVL tree"); + return -ENOMEM; + } } - llist_append(td->columns, entry); - return 0; } -static int snmp_agent_config_data(oconfig_item_t *ci) { +static int snmp_agent_config_index_key(table_definition_t *td, + data_definition_t *dd, + oconfig_item_t *ci) { + int ret = 0; + + for (int i = 0; (i < ci->children_num && ret == 0); i++) { + oconfig_item_t *option = ci->children + i; + + if (strcasecmp("Source", option->key) == 0) + ret = snmp_agent_config_index_key_source(td, dd, option); + else if (strcasecmp("Regex", option->key) == 0) + ret = snmp_agent_config_index_key_regex(td, dd, option); + else if (strcasecmp("Group", option->key) == 0) + ret = cf_util_get_int(option, &td->index_keys[dd->index_key_pos].group); + } + + return ret; +} + +/* This function parses configuration of both scalar and table column + * because they have nearly the same structure */ +static int snmp_agent_config_table_column(table_definition_t *td, + oconfig_item_t *ci) { data_definition_t *dd; int ret = 0; + oconfig_item_t *option_tmp = NULL; assert(ci != NULL); dd = calloc(1, sizeof(*dd)); if (dd == NULL) { - ERROR(PLUGIN_NAME ": Failed to allocate memory for data definition"); + ERROR(PLUGIN_NAME ": Failed to allocate memory for table data definition"); return -ENOMEM; } ret = cf_util_get_string(ci, &dd->name); if (ret != 0) { - free(dd); + sfree(dd); return -1; } dd->scale = 1.0; dd->shift = 0.0; + /* NULL if it's a scalar */ + dd->table = td; + dd->is_index_key = false; for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; - if (strcasecmp("Instance", option->key) == 0) - ret = cf_util_get_boolean(option, &dd->is_instance); - else if (strcasecmp("Plugin", option->key) == 0) + /* First 3 options are reserved for table entry only */ + if (td != NULL && strcasecmp("IndexKey", option->key) == 0) { + dd->is_index_key = true; + option_tmp = option; + } else if (strcasecmp("Plugin", option->key) == 0) ret = cf_util_get_string(option, &dd->plugin); else if (strcasecmp("PluginInstance", option->key) == 0) ret = cf_util_get_string(option, &dd->plugin_instance); @@ -1051,17 +1642,37 @@ static int snmp_agent_config_data(oconfig_item_t *ci) { } } + if (dd->is_index_key) { + ret = snmp_agent_config_index_key(td, dd, option_tmp); + td->index_keys[dd->index_key_pos].type = + snmp_agent_get_asn_type(dd->oids[0].oid, dd->oids[0].oid_len); + + if (ret != 0) { + snmp_agent_free_data(&dd); + return -1; + } + } + llentry_t *entry = llentry_create(dd->name, dd); if (entry == NULL) { snmp_agent_free_data(&dd); return -ENOMEM; } - llist_append(g_agent->scalars, entry); + /* Append to column list in parent table */ + if (td != NULL) + llist_append(td->columns, entry); + else + llentry_destroy(entry); return 0; } +/* Parses scalar configuration entry */ +static int snmp_agent_config_scalar(oconfig_item_t *ci) { + return snmp_agent_config_table_column(NULL, ci); +} + static int num_compare(const int *a, const int *b) { assert((a != NULL) && (b != NULL)); if (*a < *b) @@ -1072,6 +1683,10 @@ static int num_compare(const int *a, const int *b) { return 0; } +static int oid_compare(const oid_t *a, const oid_t *b) { + return snmp_oid_compare(a->oid, a->oid_len, b->oid, b->oid_len); +} + static int snmp_agent_config_table(oconfig_item_t *ci) { table_definition_t *td; int ret = 0; @@ -1097,6 +1712,10 @@ static int snmp_agent_config_table(oconfig_item_t *ci) { return -ENOMEM; } + for (int i = 0; i < MAX_KEY_SOURCES; i++) + td->tokens[i] = NULL; + td->tokens_done = false; + for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; @@ -1105,7 +1724,7 @@ static int snmp_agent_config_table(oconfig_item_t *ci) { else if (strcasecmp("SizeOID", option->key) == 0) ret = snmp_agent_config_table_size_oid(td, option); else if (strcasecmp("Data", option->key) == 0) - ret = snmp_agent_config_table_data(td, option); + ret = snmp_agent_config_table_column(td, option); else { WARNING(PLUGIN_NAME ": Option `%s' not allowed here", option->key); ret = -1; @@ -1117,8 +1736,13 @@ static int snmp_agent_config_table(oconfig_item_t *ci) { } } + /* Preparing index list container */ + ret = snmp_agent_prep_index_list(td, &td->index_list_cont); + if (ret != 0) + return -EINVAL; + td->instance_index = - c_avl_create((int (*)(const void *, const void *))strcmp); + c_avl_create((int (*)(const void *, const void *))oid_compare); if (td->instance_index == NULL) { snmp_agent_free_table(&td); return -ENOMEM; @@ -1131,11 +1755,19 @@ static int snmp_agent_config_table(oconfig_item_t *ci) { return -ENOMEM; } + td->instance_oids = + c_avl_create((int (*)(const void *, const void *))oid_compare); + if (td->instance_oids == NULL) { + snmp_agent_free_table(&td); + return -ENOMEM; + } + llentry_t *entry = llentry_create(td->name, td); if (entry == NULL) { snmp_agent_free_table(&td); return -ENOMEM; } + llist_append(g_agent->tables, entry); return 0; @@ -1236,98 +1868,170 @@ static int snmp_agent_unregister_oid_index(oid_t *oid, int index) { oid_t new_oid; memcpy(&new_oid, oid, sizeof(*oid)); new_oid.oid[new_oid.oid_len++] = index; - return unregister_mib(new_oid.oid, new_oid.oid_len); + return snmp_agent_unregister_oid(&new_oid); } -static int snmp_agent_update_index(table_definition_t *td, - const char *instance) { +static int snmp_agent_update_instance_oids(c_avl_tree_t *tree, oid_t *index_oid, + int value) { + int *oids_num; /* number of oids registered for instance */ - if (c_avl_get(td->instance_index, instance, NULL) == 0) - return 0; + if (c_avl_get(tree, index_oid, (void **)&oids_num) == 0) { + *oids_num += value; + return *oids_num; + } else { + ERROR(PLUGIN_NAME ": Error updating index data"); + return -1; + } +} +static int snmp_agent_update_index(data_definition_t *dd, + table_definition_t *td, oid_t **index_oid) { int ret; int *index = NULL; - char *ins; + int *value = NULL; + bool do_free_index_oid = true; - ins = strdup(instance); - if (ins == NULL) - return -ENOMEM; + if (c_avl_get(td->instance_index, (void *)*index_oid, (void **)&index) != 0) { + /* Processing new instance */ + do_free_index_oid = false; - /* need to generate index for the table */ - if (td->index_oid.oid_len) { - index = calloc(1, sizeof(*index)); - if (index == NULL) { - sfree(ins); - return -ENOMEM; + /* need to generate index for the table */ + if (td->index_oid.oid_len) { + index = calloc(1, sizeof(*index)); + if (index == NULL) { + ret = -ENOMEM; + goto free_index_oid; + } + + *index = c_avl_size(td->instance_index) + 1; + + ret = c_avl_insert(td->instance_index, *index_oid, index); + if (ret != 0) + goto free_index; + + ret = c_avl_insert(td->index_instance, index, *index_oid); + if (ret < 0) { + DEBUG(PLUGIN_NAME ": Failed to update index_instance for '%s' table", + td->name); + goto remove_avl_index_oid; + } + + ret = snmp_agent_register_oid_index(&td->index_oid, *index, + snmp_agent_table_index_oid_handler); + if (ret != 0) + goto remove_avl_index; + } else { + /* instance as a key is required for any table */ + ret = c_avl_insert(td->instance_index, *index_oid, NULL); + if (ret != 0) + goto free_index_oid; } - *index = c_avl_size(td->instance_index) + 1; + value = calloc(1, sizeof(*value)); - ret = c_avl_insert(td->instance_index, ins, index); - if (ret != 0) { - sfree(ins); - sfree(index); - return ret; + if (value == NULL) { + ERROR(PLUGIN_NAME ": Failed to allocate memory"); + ret = -ENOMEM; + goto unregister_index; } - ret = c_avl_insert(td->index_instance, index, ins); + ret = c_avl_insert(td->instance_oids, *index_oid, value); + if (ret < 0) { - DEBUG(PLUGIN_NAME ": Failed to update index_instance for '%s' table", + DEBUG(PLUGIN_NAME ": Failed to update instance_oids for '%s' table", td->name); - c_avl_remove(td->instance_index, ins, NULL, (void **)&index); - sfree(ins); - sfree(index); - return ret; + goto free_value; } - ret = snmp_agent_register_oid_index(&td->index_oid, *index, - snmp_agent_table_index_oid_handler); - if (ret != 0) - return ret; - } else { - /* instance as a key is required for any table */ - ret = c_avl_insert(td->instance_index, ins, ins); - if (ret != 0) { - sfree(ins); - return ret; - } - } + int keys_processed = 0; - /* register new oids for all columns */ - for (llentry_t *de = llist_head(td->columns); de != NULL; de = de->next) { - data_definition_t *dd = de->value; + /* Registering index keys OIDs */ + for (llentry_t *de = llist_head(td->columns); de != NULL; de = de->next) { + data_definition_t *idd = de->value; + if (!idd->is_index_key) + continue; - for (size_t i = 0; i < dd->oids_len; i++) { - if (td->index_oid.oid_len) { - ret = snmp_agent_register_oid_index(&dd->oids[i], *index, - snmp_agent_table_oid_handler); - } else { - ret = snmp_agent_register_oid_string(&dd->oids[i], ins, - snmp_agent_table_oid_handler); + for (size_t i = 0; i < idd->oids_len; i++) { + if (td->index_oid.oid_len) + ret = snmp_agent_register_oid_index(&idd->oids[i], *index, + snmp_agent_table_oid_handler); + else + ret = snmp_agent_register_oid_string(&idd->oids[i], *index_oid, + snmp_agent_table_oid_handler); + + if (ret != 0) { + ERROR(PLUGIN_NAME ": Could not register OID"); + goto free_index; + } } - if (ret != 0) - return ret; + if (++keys_processed >= td->index_keys_len) + break; } } - DEBUG(PLUGIN_NAME ": Updated index for '%s' table [%d, %s]", td->name, - (index != NULL) ? *index : -1, ins); + ret = 0; - notification_t n = { - .severity = NOTIF_OKAY, .time = cdtime(), .plugin = PLUGIN_NAME}; - sstrncpy(n.host, hostname_g, sizeof(n.host)); - sstrncpy(n.plugin_instance, ins, sizeof(n.plugin_instance)); - snprintf(n.message, sizeof(n.message), - "Data row added to table %s instance %s index %d", td->name, ins, - (index != NULL) ? *index : -1); - plugin_dispatch_notification(&n); + for (size_t i = 0; i < dd->oids_len; i++) { + if (td->index_oid.oid_len) + ret = snmp_agent_register_oid_index(&dd->oids[i], *index, + snmp_agent_table_oid_handler); + else + ret = snmp_agent_register_oid_string(&dd->oids[i], *index_oid, + snmp_agent_table_oid_handler); + + if (ret < 0) + goto free_index; + else if (ret == OID_EXISTS) + break; + else if (snmp_agent_update_instance_oids(td->instance_oids, *index_oid, 1) < + 0) + goto free_index; + } + + if (ret != OID_EXISTS) { + char index_str[DATA_MAX_NAME_LEN]; + + if (index == NULL) + snmp_agent_oid_to_string(index_str, sizeof(index_str), *index_oid); + else + snprintf(index_str, sizeof(index_str), "%d", *index); + + notification_t n = { + .severity = NOTIF_OKAY, .time = cdtime(), .plugin = PLUGIN_NAME}; + sstrncpy(n.host, hostname_g, sizeof(n.host)); + snprintf(n.message, sizeof(n.message), + "Data added to table %s with index %s", td->name, index_str); + DEBUG(PLUGIN_NAME ": %s", n.message); + + plugin_dispatch_notification(&n); + } + + if (do_free_index_oid) + sfree(*index_oid); return 0; + +free_value: + sfree(value); +unregister_index: + if (td->index_oid.oid_len) + snmp_agent_unregister_oid_index(*index_oid, *index); +remove_avl_index: + if (td->index_oid.oid_len) + c_avl_remove(td->index_instance, index, NULL, NULL); +remove_avl_index_oid: + c_avl_remove(td->instance_index, *index_oid, NULL, NULL); +free_index: + if (index != NULL) + sfree(index); +free_index_oid: + sfree(*index_oid); + + return ret; } static int snmp_agent_write(value_list_t const *vl) { - if (vl == NULL) return -EINVAL; @@ -1337,11 +2041,22 @@ static int snmp_agent_write(value_list_t const *vl) { for (llentry_t *de = llist_head(td->columns); de != NULL; de = de->next) { data_definition_t *dd = de->value; - if (!dd->is_instance) { + if (!dd->is_index_key) { if (CHECK_DD_TYPE(dd, vl->plugin, vl->plugin_instance, vl->type, vl->type_instance)) { - snmp_agent_update_index(td, vl->plugin_instance); - return 0; + oid_t *index_oid = calloc(1, sizeof(*index_oid)); + + if (index_oid == NULL) { + ERROR(PLUGIN_NAME ": Could not allocate memory for index_oid"); + return -ENOMEM; + } + + int ret = snmp_agent_generate_index(td, vl, index_oid); + + if (ret == 0) + ret = snmp_agent_update_index(dd, td, &index_oid); + + return ret; } } } @@ -1363,10 +2078,6 @@ static int snmp_agent_collect(const data_set_t *ds, const value_list_t *vl, } static int snmp_agent_preinit(void) { - if (g_agent != NULL) { - /* already initialized if config callback was called before init callback */ - return 0; - } g_agent = calloc(1, sizeof(*g_agent)); if (g_agent == NULL) { @@ -1376,22 +2087,26 @@ static int snmp_agent_preinit(void) { g_agent->tables = llist_create(); g_agent->scalars = llist_create(); + g_agent->registered_oids = + c_avl_create((int (*)(const void *, const void *))oid_compare); if (g_agent->tables == NULL || g_agent->scalars == NULL) { ERROR(PLUGIN_NAME ": llist_create() failed"); llist_destroy(g_agent->scalars); llist_destroy(g_agent->tables); + c_avl_destroy(g_agent->registered_oids); return -ENOMEM; } int err; - /* make us a agentx client. */ + /* make us an agentx client. */ err = netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1); if (err != 0) { ERROR(PLUGIN_NAME ": Failed to set agent role (%d)", err); llist_destroy(g_agent->scalars); llist_destroy(g_agent->tables); + c_avl_destroy(g_agent->registered_oids); return -1; } @@ -1405,6 +2120,7 @@ static int snmp_agent_preinit(void) { ERROR(PLUGIN_NAME ": Failed to initialize the agent library (%d)", err); llist_destroy(g_agent->scalars); llist_destroy(g_agent->tables); + c_avl_destroy(g_agent->registered_oids); return -1; } @@ -1480,6 +2196,27 @@ static void *snmp_agent_thread_run(void __attribute__((unused)) * arg) { static int snmp_agent_register_oid(oid_t *oid, Netsnmp_Node_Handler *handler) { netsnmp_handler_registration *reg; + + if (c_avl_get(g_agent->registered_oids, (void *)oid, NULL) == 0) + return OID_EXISTS; + else { + oid_t *new_oid = calloc(1, sizeof(*oid)); + + if (new_oid == NULL) { + ERROR(PLUGIN_NAME ": Could not allocate memory to register new OID"); + return -ENOMEM; + } + + memcpy(new_oid, oid, sizeof(*oid)); + + int ret = c_avl_insert(g_agent->registered_oids, (void *)new_oid, NULL); + if (ret != 0) { + ERROR(PLUGIN_NAME ": Could not allocate memory to register new OID"); + sfree(new_oid); + return -ENOMEM; + } + } + char *oid_name = snmp_agent_get_oid_name(oid->oid, oid->oid_len - 1); char oid_str[DATA_MAX_NAME_LEN]; @@ -1554,13 +2291,22 @@ static int snmp_agent_shutdown(void) { pthread_mutex_destroy(&g_agent->lock); pthread_mutex_destroy(&g_agent->agentx_lock); + /* Freeing registered OIDs list */ + void *oid; + + if (g_agent->registered_oids != NULL) { + while (c_avl_pick(g_agent->registered_oids, &oid, NULL) == 0) { + sfree(oid); + } + c_avl_destroy(g_agent->registered_oids); + } + sfree(g_agent); return ret; } static int snmp_agent_config(oconfig_item_t *ci) { - int ret = snmp_agent_preinit(); if (ret != 0) { @@ -1571,7 +2317,7 @@ static int snmp_agent_config(oconfig_item_t *ci) { for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; if (strcasecmp("Data", child->key) == 0) { - ret = snmp_agent_config_data(child); + ret = snmp_agent_config_scalar(child); } else if (strcasecmp("Table", child->key) == 0) { ret = snmp_agent_config_table(child); } else { @@ -1588,7 +2334,7 @@ static int snmp_agent_config(oconfig_item_t *ci) { } } - ret = snmp_agent_validate_data(); + ret = snmp_agent_validate_config(); if (ret != 0) { ERROR(PLUGIN_NAME ": Invalid configuration provided"); snmp_agent_free_config(); diff --git a/src/snmp_agent_test.c b/src/snmp_agent_test.c new file mode 100644 index 00000000..581f33d3 --- /dev/null +++ b/src/snmp_agent_test.c @@ -0,0 +1,831 @@ +/** + * collectd - src/snmp_agent_test.c + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * 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: + * Marcin Mozejko + **/ + +#include "snmp_agent.c" +#include "testing.h" + +#define TEST_HOSTNAME "test_hostname" +#define TEST_PLUGIN "test_plugin" +#define TEST_PLUGIN_INST "test_plugin_inst" +#define TEST_TYPE "test_type" +#define TEST_TYPE_INST "test_type_inst" + +DEF_TEST(oid_to_string) { + oid_t o = {.oid = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .oid_len = 9}; + char oid_str[DATA_MAX_NAME_LEN]; + + int ret = snmp_agent_oid_to_string(oid_str, DATA_MAX_NAME_LEN, &o); + EXPECT_EQ_INT(o.oid_len * 2 - 1, ret); + EXPECT_EQ_STR("1.2.3.4.5.6.7.8.9", oid_str); + + return 0; +} + +/* Testing formatting metric name for simple scalar */ +DEF_TEST(format_name_scalar) { + data_definition_t *dd = calloc(1, sizeof(*dd)); + + dd->plugin = TEST_PLUGIN; + dd->plugin_instance = TEST_PLUGIN_INST; + dd->type = TEST_TYPE; + dd->type_instance = TEST_TYPE_INST; + + char name[DATA_MAX_NAME_LEN]; + int ret = snmp_agent_format_name(name, sizeof(name), dd, NULL); + + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_STR( + "example.com/test_plugin-test_plugin_inst/test_type-test_type_inst", + name); + + sfree(dd); + + return 0; +} + +DEF_TEST(format_name_simple_index) { + netsnmp_variable_list *index_list_tmp = NULL; + oid_t index_oid; + data_definition_t *dd = calloc(1, sizeof(*dd)); + table_definition_t *td = calloc(1, sizeof(*td)); + + td->index_list_cont = NULL; + td->index_keys[0].source = INDEX_PLUGIN_INSTANCE; + td->index_keys[0].type = ASN_OCTET_STR; + td->index_keys[1].source = INDEX_TYPE_INSTANCE; + td->index_keys[1].type = ASN_OCTET_STR; + dd->table = td; + dd->plugin = TEST_PLUGIN; + dd->type = TEST_TYPE; + + const char plugin_inst[] = TEST_PLUGIN_INST; + const char type_inst[] = TEST_TYPE_INST; + + snmp_varlist_add_variable(&index_list_tmp, NULL, 0, ASN_OCTET_STR, + (const u_char *)plugin_inst, strlen(plugin_inst)); + snmp_varlist_add_variable(&index_list_tmp, NULL, 0, ASN_OCTET_STR, + (const u_char *)type_inst, strlen(type_inst)); + + build_oid_noalloc(index_oid.oid, sizeof(index_oid.oid), &index_oid.oid_len, + NULL, 0, index_list_tmp); + + snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, ASN_OCTET_STR, NULL, + 0); + snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, ASN_OCTET_STR, NULL, + 0); + + char name[DATA_MAX_NAME_LEN]; + + int ret = snmp_agent_format_name(name, DATA_MAX_NAME_LEN, dd, &index_oid); + + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_STR( + "example.com/test_plugin-test_plugin_inst/test_type-test_type_inst", + name); + + snmp_free_varbind(index_list_tmp); + snmp_free_varbind(td->index_list_cont); + sfree(dd); + sfree(td); + + return 0; +} + +DEF_TEST(format_name_regex_index) { + netsnmp_variable_list *index_list_tmp = NULL; + oid_t index_oid; + data_definition_t *dd = calloc(1, sizeof(*dd)); + table_definition_t *td = calloc(1, sizeof(*td)); + + td->index_keys_len = 3; + td->index_list_cont = NULL; + td->index_keys[0].source = INDEX_PLUGIN_INSTANCE; + td->index_keys[0].type = ASN_OCTET_STR; + td->index_keys[1].source = INDEX_TYPE_INSTANCE; + td->index_keys[1].type = ASN_INTEGER; + td->index_keys[1].regex = "^vcpu_([0-9]{1,3})-cpu_[0-9]{1,3}$"; + td->index_keys[1].group = 1; + td->index_keys[2].source = INDEX_TYPE_INSTANCE; + td->index_keys[2].type = ASN_INTEGER; + td->index_keys[2].regex = "^vcpu_[0-9]{1,3}-cpu_([0-9]{1,3})$"; + td->index_keys[2].group = 1; + + dd->table = td; + dd->plugin = TEST_PLUGIN; + dd->type = TEST_TYPE; + + const char plugin_inst[] = TEST_PLUGIN_INST; + int vcpu = 1; + int cpu = 10; + + snmp_varlist_add_variable(&index_list_tmp, NULL, 0, ASN_OCTET_STR, + (const u_char *)plugin_inst, strlen(plugin_inst)); + snmp_varlist_add_variable(&index_list_tmp, NULL, 0, ASN_INTEGER, + (const u_char *)&vcpu, sizeof(vcpu)); + snmp_varlist_add_variable(&index_list_tmp, NULL, 0, ASN_INTEGER, + (const u_char *)&cpu, sizeof(cpu)); + + build_oid_noalloc(index_oid.oid, sizeof(index_oid.oid), &index_oid.oid_len, + NULL, 0, index_list_tmp); + + token_t *token; + int *offset; + + td->tokens[INDEX_TYPE_INSTANCE] = + c_avl_create((int (*)(const void *, const void *))num_compare); + snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, ASN_OCTET_STR, NULL, + 0); + + token = malloc(sizeof(*token)); + offset = malloc(sizeof(*offset)); + token->key = snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, + ASN_INTEGER, NULL, 0); + token->str = strdup("vcpu_"); + *offset = 0; + int ret = c_avl_insert(td->tokens[INDEX_TYPE_INSTANCE], (void *)offset, + (void *)token); + + token = malloc(sizeof(*token)); + offset = malloc(sizeof(*offset)); + token->key = snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, + ASN_INTEGER, NULL, 0); + token->str = strdup("-cpu_"); + *offset = 6; + ret += c_avl_insert(td->tokens[INDEX_TYPE_INSTANCE], (void *)offset, + (void *)token); + char name[DATA_MAX_NAME_LEN]; + + ret += snmp_agent_format_name(name, DATA_MAX_NAME_LEN, dd, &index_oid); + + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_STR( + "example.com/test_plugin-test_plugin_inst/test_type-vcpu_1-cpu_10", name); + while (c_avl_pick(td->tokens[INDEX_TYPE_INSTANCE], (void **)&offset, + (void **)&token) == 0) { + sfree(offset); + sfree(token->str); + sfree(token); + } + c_avl_destroy(td->tokens[INDEX_TYPE_INSTANCE]); + snmp_free_varbind(index_list_tmp); + snmp_free_varbind(td->index_list_cont); + sfree(dd); + sfree(td); + + return 0; +} + +DEF_TEST(prep_index_list) { + table_definition_t *td = calloc(1, sizeof(*td)); + + assert(td != NULL); + td->index_keys_len = 5; + td->index_keys[0].source = INDEX_HOST; + td->index_keys[0].type = ASN_OCTET_STR; + td->index_keys[1].source = INDEX_PLUGIN; + td->index_keys[1].type = ASN_OCTET_STR; + td->index_keys[2].source = INDEX_PLUGIN_INSTANCE; + td->index_keys[2].type = ASN_INTEGER; + td->index_keys[3].source = INDEX_TYPE; + td->index_keys[3].type = ASN_INTEGER; + td->index_keys[4].source = INDEX_TYPE_INSTANCE; + td->index_keys[4].type = ASN_OCTET_STR; + td->index_list_cont = NULL; + + int ret = snmp_agent_prep_index_list(td, &td->index_list_cont); + EXPECT_EQ_INT(0, ret); + + netsnmp_variable_list *key = td->index_list_cont; + + OK(key != NULL); + EXPECT_EQ_INT(ASN_OCTET_STR, key->type); + key = key->next_variable; + OK(key != NULL); + EXPECT_EQ_INT(ASN_OCTET_STR, key->type); + key = key->next_variable; + OK(key != NULL); + EXPECT_EQ_INT(ASN_INTEGER, key->type); + key = key->next_variable; + OK(key != NULL); + EXPECT_EQ_INT(ASN_INTEGER, key->type); + key = key->next_variable; + OK(key != NULL); + EXPECT_EQ_INT(ASN_OCTET_STR, key->type); + key = key->next_variable; + OK(key == NULL); + + snmp_free_varbind(td->index_list_cont); + sfree(td); + + return 0; +} + +DEF_TEST(fill_index_list_simple) { + table_definition_t *td = calloc(1, sizeof(*td)); + assert(td != NULL); + + /* Preparing value list */ + value_list_t *vl = calloc(1, sizeof(*vl)); + assert(vl != NULL); + strncpy(vl->host, TEST_HOSTNAME, DATA_MAX_NAME_LEN); + strncpy(vl->plugin, TEST_PLUGIN, DATA_MAX_NAME_LEN); + strncpy(vl->plugin_instance, TEST_PLUGIN_INST, DATA_MAX_NAME_LEN); + strncpy(vl->type, TEST_TYPE, DATA_MAX_NAME_LEN); + strncpy(vl->type_instance, TEST_TYPE_INST, DATA_MAX_NAME_LEN); + + td->index_keys_len = 5; + td->index_keys[0].source = INDEX_HOST; + td->index_keys[0].type = ASN_OCTET_STR; + td->index_keys[1].source = INDEX_PLUGIN; + td->index_keys[1].type = ASN_OCTET_STR; + td->index_keys[2].source = INDEX_PLUGIN_INSTANCE; + td->index_keys[2].type = ASN_OCTET_STR; + td->index_keys[3].source = INDEX_TYPE; + td->index_keys[3].type = ASN_OCTET_STR; + td->index_keys[4].source = INDEX_TYPE_INSTANCE; + td->index_keys[4].type = ASN_OCTET_STR; + + td->index_list_cont = NULL; + for (int i = 0; i < td->index_keys_len; i++) + snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, ASN_OCTET_STR, + NULL, 0); + + int ret = snmp_agent_fill_index_list(td, vl); + EXPECT_EQ_INT(0, ret); + + netsnmp_variable_list *key = td->index_list_cont; + + ret = 0; + + OK(key != NULL); + EXPECT_EQ_STR(vl->host, (char *)key->val.string); + key = key->next_variable; + OK(key != NULL); + EXPECT_EQ_STR(vl->plugin, (char *)key->val.string); + key = key->next_variable; + OK(key != NULL); + EXPECT_EQ_STR(vl->plugin_instance, (char *)key->val.string); + key = key->next_variable; + OK(key != NULL); + EXPECT_EQ_STR(vl->type, (char *)key->val.string); + key = key->next_variable; + OK(key != NULL); + EXPECT_EQ_STR(vl->type_instance, (char *)key->val.string); + key = key->next_variable; + OK(key == NULL); + + snmp_free_varbind(td->index_list_cont); + sfree(vl); + sfree(td); + + return 0; +} + +DEF_TEST(fill_index_list_regex) { + table_definition_t *td = calloc(1, sizeof(*td)); + int ret = 0; + + assert(td != NULL); + + /* Preparing value list */ + value_list_t *vl = calloc(1, sizeof(*vl)); + strncpy(vl->plugin_instance, TEST_PLUGIN_INST, DATA_MAX_NAME_LEN); + strncpy(vl->type_instance, "1test2test3", DATA_MAX_NAME_LEN); + + td->index_keys_len = 4; + td->index_keys[0].source = INDEX_PLUGIN_INSTANCE; + td->index_keys[0].type = ASN_OCTET_STR; + td->index_keys[1].source = INDEX_TYPE_INSTANCE; + td->index_keys[1].type = ASN_INTEGER; + td->index_keys[1].regex = "^([0-9])test[0-9]test[0-9]$"; + td->index_keys[1].group = 1; + td->index_keys[2].source = INDEX_TYPE_INSTANCE; + td->index_keys[2].type = ASN_INTEGER; + td->index_keys[2].regex = "^[0-9]test([0-9])test[0-9]$"; + td->index_keys[2].group = 1; + td->index_keys[3].source = INDEX_TYPE_INSTANCE; + td->index_keys[3].type = ASN_INTEGER; + td->index_keys[3].regex = "^[0-9]test[0-9]test([0-9])$"; + td->index_keys[3].group = 1; + + td->index_list_cont = NULL; + snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, ASN_OCTET_STR, NULL, + 0); + for (int i = 1; i < td->index_keys_len; i++) { + snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, ASN_INTEGER, NULL, + 0); + ret = regcomp(&td->index_keys[i].regex_info, td->index_keys[i].regex, + REG_EXTENDED); + EXPECT_EQ_INT(0, ret); + } + td->tokens[INDEX_TYPE_INSTANCE] = + c_avl_create((int (*)(const void *, const void *))num_compare); + assert(td->tokens[INDEX_TYPE_INSTANCE] != NULL); + + ret = snmp_agent_fill_index_list(td, vl); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(1, td->tokens_done); + + netsnmp_variable_list *key = td->index_list_cont; + + OK(key != NULL); + EXPECT_EQ_STR(vl->plugin_instance, (char *)key->val.string); + key = key->next_variable; + OK(key != NULL); + EXPECT_EQ_INT(1, *key->val.integer); + key = key->next_variable; + OK(key != NULL); + EXPECT_EQ_INT(2, *key->val.integer); + key = key->next_variable; + OK(key != NULL); + EXPECT_EQ_INT(3, *key->val.integer); + key = key->next_variable; + OK(key == NULL); + + token_t *token; + int *offset; + + while (c_avl_pick(td->tokens[INDEX_TYPE_INSTANCE], (void **)&offset, + (void **)&token) == 0) { + sfree(offset); + sfree(token->str); + sfree(token); + } + + c_avl_destroy(td->tokens[INDEX_TYPE_INSTANCE]); + snmp_free_varbind(td->index_list_cont); + sfree(vl); + + for (int i = 0; i < td->index_keys_len; i++) { + regfree(&td->index_keys[i].regex_info); + } + sfree(td); + + return 0; +} + +DEF_TEST(config_index_key_source) { + oconfig_item_t *ci = calloc(1, sizeof(*ci)); + table_definition_t *td = calloc(1, sizeof(*td)); + data_definition_t *dd = calloc(1, sizeof(*dd)); + + assert(ci != NULL); + assert(td != NULL); + assert(dd != NULL); + + ci->values = calloc(1, sizeof(*ci->values)); + assert(ci->values != NULL); + ci->values_num = 1; + ci->values->value.string = "PluginInstance"; + ci->values->type = OCONFIG_TYPE_STRING; + + int ret = snmp_agent_config_index_key_source(td, dd, ci); + + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(1, td->index_keys_len); + EXPECT_EQ_INT(0, dd->index_key_pos); + EXPECT_EQ_INT(INDEX_PLUGIN_INSTANCE, td->index_keys[0].source); + EXPECT_EQ_INT(GROUP_UNUSED, td->index_keys[0].group); + OK(td->index_keys[0].regex == NULL); + + sfree(ci->values); + sfree(ci); + sfree(td); + sfree(dd); + + return 0; +} + +DEF_TEST(config_index_key_regex) { + oconfig_item_t *ci = calloc(1, sizeof(*ci)); + table_definition_t *td = calloc(1, sizeof(*td)); + data_definition_t *dd = calloc(1, sizeof(*dd)); + + assert(ci != NULL); + assert(td != NULL); + assert(dd != NULL); + + dd->index_key_pos = 0; + td->index_keys_len = 1; + td->index_keys[0].source = INDEX_PLUGIN_INSTANCE; + td->index_keys[0].group = 1; + ci->values = calloc(1, sizeof(*ci->values)); + assert(ci->values != NULL); + ci->values_num = 1; + ci->values->value.string = "^([0-9])test[0-9]test[0-9]$"; + ci->values->type = OCONFIG_TYPE_STRING; + + int ret = snmp_agent_config_index_key_regex(td, dd, ci); + + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_STR(td->index_keys[0].regex, "^([0-9])test[0-9]test[0-9]$"); + OK(td->tokens[INDEX_PLUGIN_INSTANCE] != NULL); + + c_avl_destroy(td->tokens[INDEX_PLUGIN_INSTANCE]); + sfree(ci->values); + sfree(ci); + sfree(td->index_keys[0].regex); + regfree(&td->index_keys[0].regex_info); + sfree(td); + sfree(dd); + + return 0; +} + +DEF_TEST(config_index_key) { + oconfig_item_t *ci = calloc(1, sizeof(*ci)); + table_definition_t *td = calloc(1, sizeof(*td)); + data_definition_t *dd = calloc(1, sizeof(*dd)); + + assert(ci != NULL); + assert(td != NULL); + assert(dd != NULL); + + ci->children_num = 3; + ci->children = calloc(1, sizeof(*ci->children) * ci->children_num); + + ci->children[0].key = "Source"; + ci->children[0].parent = ci; + ci->children[0].values_num = 1; + ci->children[0].values = calloc(1, sizeof(*ci->children[0].values)); + assert(ci->children[0].values != NULL); + ci->children[0].values->value.string = "PluginInstance"; + ci->children[0].values->type = OCONFIG_TYPE_STRING; + + ci->children[1].key = "Regex"; + ci->children[1].parent = ci; + ci->children[1].values_num = 1; + ci->children[1].values = calloc(1, sizeof(*ci->children[0].values)); + assert(ci->children[1].values != NULL); + ci->children[1].values->value.string = "^([0-9])test[0-9]test[0-9]$"; + ci->children[1].values->type = OCONFIG_TYPE_STRING; + + ci->children[2].key = "Group"; + ci->children[2].parent = ci; + ci->children[2].values_num = 1; + ci->children[2].values = calloc(1, sizeof(*ci->children[0].values)); + assert(ci->children[2].values != NULL); + ci->children[2].values->value.number = 1; + ci->children[2].values->type = OCONFIG_TYPE_NUMBER; + + int ret = snmp_agent_config_index_key(td, dd, ci); + + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(1, td->index_keys_len); + EXPECT_EQ_INT(0, dd->index_key_pos); + EXPECT_EQ_INT(INDEX_PLUGIN_INSTANCE, td->index_keys[0].source); + EXPECT_EQ_INT(1, td->index_keys[0].group); + EXPECT_EQ_STR("^([0-9])test[0-9]test[0-9]$", td->index_keys[0].regex); + OK(td->tokens[INDEX_PLUGIN_INSTANCE] != NULL); + + sfree(ci->children[0].values); + sfree(ci->children[1].values); + sfree(ci->children[2].values); + + sfree(ci->children); + sfree(ci); + + c_avl_destroy(td->tokens[INDEX_PLUGIN_INSTANCE]); + sfree(dd); + sfree(td->index_keys[0].regex); + regfree(&td->index_keys[0].regex_info); + sfree(td); + + return 0; +} + +DEF_TEST(parse_index_key) { + const char regex[] = "test-([0-9])-([0-9])"; + const char input[] = "snmp-test-5-6"; + regex_t regex_info; + regmatch_t match; + + int ret = regcomp(®ex_info, regex, REG_EXTENDED); + EXPECT_EQ_INT(0, ret); + + ret = snmp_agent_parse_index_key(input, ®ex_info, 0, &match); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(5, match.rm_so); + EXPECT_EQ_INT(13, match.rm_eo); + + ret = snmp_agent_parse_index_key(input, ®ex_info, 1, &match); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(10, match.rm_so); + EXPECT_EQ_INT(11, match.rm_eo); + + ret = snmp_agent_parse_index_key(input, ®ex_info, 2, &match); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(12, match.rm_so); + EXPECT_EQ_INT(13, match.rm_eo); + + regfree(®ex_info); + + return 0; +} + +DEF_TEST(create_token) { + c_avl_tree_t *tokens = + c_avl_create((int (*)(const void *, const void *))num_compare); + const char input[] = "testA1-testB2"; + + assert(tokens != NULL); + + int ret = snmp_agent_create_token(input, 0, 5, tokens, NULL); + EXPECT_EQ_INT(0, ret); + ret = snmp_agent_create_token(input, 6, 6, tokens, NULL); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(2, c_avl_size(tokens)); + + token_t *token; + int *offset; + + ret = c_avl_pick(tokens, (void **)&offset, (void **)&token); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(6, *offset); + EXPECT_EQ_STR("-testB", token->str); + sfree(offset); + sfree(token->str); + sfree(token); + + ret = c_avl_pick(tokens, (void **)&offset, (void **)&token); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(0, *offset); + EXPECT_EQ_STR("testA", token->str); + sfree(offset); + sfree(token->str); + sfree(token); + + ret = c_avl_pick(tokens, (void **)&offset, (void **)&token); + OK(ret != 0); + + c_avl_destroy(tokens); + + return 0; +} + +DEF_TEST(delete_token) { + c_avl_tree_t *tokens = + c_avl_create((int (*)(const void *, const void *))num_compare); + const char input[] = "testA1-testB2-testC3"; + + assert(tokens != NULL); + + int ret = snmp_agent_create_token(input, 0, 5, tokens, NULL); + EXPECT_EQ_INT(0, ret); + ret = snmp_agent_create_token(input, 6, 6, tokens, NULL); + EXPECT_EQ_INT(0, ret); + ret = snmp_agent_create_token(input, 13, 6, tokens, NULL); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(3, c_avl_size(tokens)); + ret = snmp_agent_delete_token(6, tokens); + EXPECT_EQ_INT(0, ret); + + token_t *token; + int *offset; + + ret = c_avl_pick(tokens, (void **)&offset, (void **)&token); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(0, *offset); + EXPECT_EQ_STR("testA", token->str); + sfree(offset); + sfree(token->str); + sfree(token); + + ret = c_avl_pick(tokens, (void **)&offset, (void **)&token); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(13, *offset); + EXPECT_EQ_STR("-testC", token->str); + sfree(offset); + sfree(token->str); + sfree(token); + + ret = c_avl_pick(tokens, (void **)&offset, (void **)&token); + OK(ret != 0); + + c_avl_destroy(tokens); + + return 0; +} + +DEF_TEST(get_token) { + c_avl_tree_t *tokens = + c_avl_create((int (*)(const void *, const void *))num_compare); + const char input[] = "testA1-testB2-testC3"; + + assert(tokens != NULL); + + int ret = snmp_agent_create_token(input, 0, 5, tokens, NULL); + EXPECT_EQ_INT(0, ret); + ret = snmp_agent_create_token(input, 6, 6, tokens, NULL); + EXPECT_EQ_INT(0, ret); + ret = snmp_agent_create_token(input, 13, 6, tokens, NULL); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(3, c_avl_size(tokens)); + ret = snmp_agent_get_token(tokens, 12); + EXPECT_EQ_INT(6, ret); + + token_t *token; + int *offset; + + while (c_avl_pick(tokens, (void **)&offset, (void **)&token) == 0) { + sfree(offset); + sfree(token->str); + sfree(token); + } + + c_avl_destroy(tokens); + + return 0; +} + +DEF_TEST(tokenize) { + regmatch_t m[3]; + + m[0].rm_so = 5; + m[0].rm_eo = 6; + m[1].rm_so = 12; + m[1].rm_eo = 13; + m[2].rm_so = 19; + m[2].rm_eo = 20; + + c_avl_tree_t *tokens = + c_avl_create((int (*)(const void *, const void *))num_compare); + const char input[] = "testA1-testB2-testC3"; + token_t *token; + int *offset; + c_avl_iterator_t *it; + int ret; + + assert(tokens != NULL); + + /* First pass */ + ret = snmp_agent_tokenize(input, tokens, &m[0], NULL); + EXPECT_EQ_INT(0, ret); + it = c_avl_get_iterator(tokens); + ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_STR("testA", token->str); + ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_STR("-testB2-testC3", token->str); + ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token); + OK(ret != 0); + c_avl_iterator_destroy(it); + + /* Second pass */ + ret = snmp_agent_tokenize(input, tokens, &m[1], NULL); + EXPECT_EQ_INT(0, ret); + it = c_avl_get_iterator(tokens); + ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_STR("testA", token->str); + ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_STR("-testB", token->str); + ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_STR("-testC3", token->str); + ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token); + OK(ret != 0); + c_avl_iterator_destroy(it); + + /* Third pass */ + ret = snmp_agent_tokenize(input, tokens, &m[2], NULL); + EXPECT_EQ_INT(0, ret); + it = c_avl_get_iterator(tokens); + ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_STR("testA", token->str); + ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_STR("-testB", token->str); + ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_STR("-testC", token->str); + ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token); + OK(ret != 0); + c_avl_iterator_destroy(it); + + while (c_avl_pick(tokens, (void **)&offset, (void **)&token) == 0) { + sfree(offset); + sfree(token->str); + sfree(token); + } + + c_avl_destroy(tokens); + + return 0; +} + +DEF_TEST(build_name) { + table_definition_t *td = calloc(1, sizeof(*td)); + c_avl_tree_t *tokens = + c_avl_create((int (*)(const void *, const void *))num_compare); + + assert(tokens != NULL); + assert(td != NULL); + + int n[3] = {1, 2, 3}; + char *t[3] = {"testA", "-testB", "-testC"}; + int off[3] = {0, 6, 13}; + token_t *token; + int *offset; + int ret = 0; + char *name = NULL; + + td->index_list_cont = NULL; + for (int i = 0; i < 3; i++) { + token = malloc(sizeof(*token)); + token->str = t[i]; + token->key = + snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, ASN_INTEGER, + (const u_char *)&n[i], sizeof(n[i])); + assert(token->key != NULL); + offset = &off[i]; + ret = c_avl_insert(tokens, (void *)offset, (void *)token); + assert(ret == 0); + } + + ret = snmp_agent_build_name(&name, tokens); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_STR("testA1-testB2-testC3", name); + + while (c_avl_pick(tokens, (void **)&offset, (void **)&token) == 0) + sfree(token); + + c_avl_destroy(tokens); + snmp_free_varbind(td->index_list_cont); + sfree(td); + sfree(name); + return 0; +} + +int main(void) { + /* snmp_agent_oid_to_string */ + RUN_TEST(oid_to_string); + + /* snmp_agent_prep_index_list */ + RUN_TEST(prep_index_list); + + /* snmp_agent_fill_index_list */ + RUN_TEST(fill_index_list_simple); + RUN_TEST(fill_index_list_regex); + + /* snmp_agent_format_name */ + RUN_TEST(format_name_scalar); + RUN_TEST(format_name_simple_index); + RUN_TEST(format_name_regex_index); + + /* snmp_agent_config_index_key_source */ + RUN_TEST(config_index_key_source); + + /* snmp_agent_config_index_key_regex */ + RUN_TEST(config_index_key_regex); + + /* snmp_agent_config_index_key */ + RUN_TEST(config_index_key); + + /*snmp_agent_parse_index_key */ + RUN_TEST(parse_index_key); + + /* snmp_agent_create_token */ + RUN_TEST(create_token); + + /* snmp_agent_delete_token */ + RUN_TEST(delete_token); + + /* snmp_agent_get_token */ + RUN_TEST(get_token); + + /* snmp_agent_tokenize */ + RUN_TEST(tokenize); + + /* snmp_agent_build_name */ + RUN_TEST(build_name); + + END_TEST; +} diff --git a/src/statsd.c b/src/statsd.c index ccd15ebe..444e8ea1 100644 --- a/src/statsd.c +++ b/src/statsd.c @@ -61,29 +61,29 @@ struct statsd_metric_s { }; typedef struct statsd_metric_s statsd_metric_t; -static c_avl_tree_t *metrics_tree = NULL; +static c_avl_tree_t *metrics_tree; static pthread_mutex_t metrics_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_t network_thread; -static _Bool network_thread_running = 0; -static _Bool network_thread_shutdown = 0; +static bool network_thread_running; +static bool network_thread_shutdown; -static char *conf_node = NULL; -static char *conf_service = NULL; +static char *conf_node; +static char *conf_service; -static _Bool conf_delete_counters = 0; -static _Bool conf_delete_timers = 0; -static _Bool conf_delete_gauges = 0; -static _Bool conf_delete_sets = 0; +static bool conf_delete_counters; +static bool conf_delete_timers; +static bool conf_delete_gauges; +static bool conf_delete_sets; -static double *conf_timer_percentile = NULL; -static size_t conf_timer_percentile_num = 0; +static double *conf_timer_percentile; +static size_t conf_timer_percentile_num; -static _Bool conf_counter_sum = 0; -static _Bool conf_timer_lower = 0; -static _Bool conf_timer_upper = 0; -static _Bool conf_timer_sum = 0; -static _Bool conf_timer_count = 0; +static bool conf_counter_sum; +static bool conf_timer_lower; +static bool conf_timer_upper; +static bool conf_timer_sum; +static bool conf_timer_count; /* Must hold metrics_lock when calling this function. */ static statsd_metric_t *statsd_metric_lookup_unsafe(char const *name, /* {{{ */ @@ -352,9 +352,8 @@ static int statsd_handle_set(char const *name, /* {{{ */ status = c_avl_insert(metric->set, set_key, /* value = */ NULL); if (status < 0) { pthread_mutex_unlock(&metrics_lock); - if (status < 0) - ERROR("statsd plugin: c_avl_insert (\"%s\") failed with status %i.", - set_key, status); + ERROR("statsd plugin: c_avl_insert (\"%s\") failed with status %i.", + set_key, status); sfree(set_key); return -1; } else if (status > 0) /* key already exists */ @@ -666,7 +665,7 @@ static int statsd_init(void) /* {{{ */ return status; } } - network_thread_running = 1; + network_thread_running = true; pthread_mutex_unlock(&metrics_lock); @@ -717,7 +716,7 @@ static int statsd_metric_submit_unsafe(char const *name, if (metric->type == STATSD_GAUGE) vl.values[0].gauge = (gauge_t)metric->value; else if (metric->type == STATSD_TIMER) { - _Bool have_events = (metric->updates_num > 0); + bool have_events = (metric->updates_num > 0); /* Make sure all timer metrics share the *same* timestamp. */ vl.time = cdtime(); @@ -876,11 +875,11 @@ static int statsd_shutdown(void) /* {{{ */ void *value; if (network_thread_running) { - network_thread_shutdown = 1; + network_thread_shutdown = true; pthread_kill(network_thread, SIGTERM); pthread_join(network_thread, /* retval = */ NULL); } - network_thread_running = 0; + network_thread_running = false; pthread_mutex_lock(&metrics_lock); diff --git a/src/stdendian.h b/src/stdendian.h deleted file mode 100644 index 2fc569ce..00000000 --- a/src/stdendian.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * stdendian.h - * - * This header defines the following endian macros as defined here: - * http://austingroupbugs.net/view.php?id=162 - * - * BYTE_ORDER this macro shall have a value equal to one - * of the *_ENDIAN macros in this header. - * LITTLE_ENDIAN if BYTE_ORDER == LITTLE_ENDIAN, the host - * byte order is from least significant to - * most significant. - * BIG_ENDIAN if BYTE_ORDER == BIG_ENDIAN, the host byte - * order is from most significant to least - * significant. - * - * The following are defined as macros: - * - * uint16_t bswap16(uint16_t x); - * uint32_t bswap32(uint32_t x); - * uint64_t bswap64(uint64_t x); - - * uint16_t htobe16(uint16_t x); - * uint16_t htole16(uint16_t x); - * uint16_t be16toh(uint16_t x); - * uint16_t le16toh(uint16_t x); - * - * uint32_t htobe32(uint32_t x); - * uint32_t htole32(uint32_t x); - * uint32_t be32toh(uint32_t x); - * uint32_t le32toh(uint32_t x); - * - * uint64_t htobe64(uint64_t x); - * uint64_t htole64(uint64_t x); - * uint64_t be64toh(uint64_t x); - * uint64_t le64toh(uint64_t x); - * - * The header defines the following macro for OpenCL compatibility - * - https://www.khronos.org/registry/cl/sdk/2.0/docs/man/xhtml/preprocessorDirectives.html - * - * __ENDIAN_LITTLE__ if BYTE_ORDER == LITTLE_ENDIAN then this - * macro is present for OpenCL compatibility - * - * The implementation provides a uniform interface to endian macros using only - * system headers on recent Linux, Darwin, FreeBSD, Solaris and Windows - systems. - * - * This approach is intended to avoid the need for preflight configure - scripts. - * An alternative approach would be to test compiler CPU architecture marcros. - * - * This header has had *limited* testing on recent C11/C++11 compilers and is - * based on the austin bug tracker interface, manpages, and headers present in - * Linux, FreeBSD, Windows, Solaris and Darwin. - * - * The header uses __builtin_bswapXX intrinsic with GCC/Clang (__GNUC__) on - * platforms that do not provide bswap16, bswap32, bswap64 (Darwin) - * - * Public Domain. - */ - -#if HAVE_STDINT_H -#include -#endif - -/* Linux / GLIBC */ -#if defined(__linux__) || defined(__GLIBC__) -#include -#include -#define __ENDIAN_DEFINED 1 -#define __BSWAP_DEFINED 1 -#define __HOSTSWAP_DEFINED 1 -#define _BYTE_ORDER __BYTE_ORDER -#define _LITTLE_ENDIAN __LITTLE_ENDIAN -#define _BIG_ENDIAN __BIG_ENDIAN -#define bswap16(x) bswap_16(x) -#define bswap32(x) bswap_32(x) -#define bswap64(x) bswap_64(x) -#endif /* __linux__ || __GLIBC__ */ - -/* BSD */ -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \ - defined(__OpenBSD__) -#include -#define __ENDIAN_DEFINED 1 -#define __BSWAP_DEFINED 1 -#define __HOSTSWAP_DEFINED 1 -#endif /* BSD */ - -/* Solaris */ -#if defined(sun) -#include -#include -#define bswap16(x) BSWAP_16(x) -#define bswap32(x) BSWAP_32(x) -#define bswap64(x) BSWAP_64(x) -/* sun headers don't set a value for _LITTLE_ENDIAN or _BIG_ENDIAN */ -#if defined(_LITTLE_ENDIAN) -#undef _LITTLE_ENDIAN -#define _LITTLE_ENDIAN 1234 -#define _BIG_ENDIAN 4321 -#define _BYTE_ORDER _LITTLE_ENDIAN -#elif defined(_BIG_ENDIAN) -#undef _BIG_ENDIAN -#define _LITTLE_ENDIAN 1234 -#define _BIG_ENDIAN 4321 -#define _BYTE_ORDER _BIG_ENDIAN -#endif -#define __ENDIAN_DEFINED 1 -#endif /* sun */ - -/* Windows */ -#if defined(_WIN32) || defined(_MSC_VER) -/* assumes all Microsoft targets are little endian */ -#define _LITTLE_ENDIAN 1234 -#define _BIG_ENDIAN 4321 -#define _BYTE_ORDER _LITTLE_ENDIAN -#define __ENDIAN_DEFINED 1 -#endif /* _MSC_VER */ - -/* OS X */ -#if defined(__APPLE__) -#include -#define _BYTE_ORDER BYTE_ORDER -#define _LITTLE_ENDIAN LITTLE_ENDIAN -#define _BIG_ENDIAN BIG_ENDIAN -#define __ENDIAN_DEFINED 1 -#endif /* __APPLE__ */ - -/* OpenCL */ -#if defined(__OPENCL_VERSION__) -#define _LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#if defined(__ENDIAN_LITTLE__) -#define _BYTE_ORDER _LITTLE_ENDIAN -#else -#define _BYTE_ORDER _BIG_ENDIAN -#endif -#define bswap16(x) as_ushort(as_uchar2(ushort(x)).s1s0) -#define bswap32(x) as_uint(as_uchar4(uint(x)).s3s2s1s0) -#define bswap64(x) as_ulong(as_uchar8(ulong(x)).s7s6s5s4s3s2s1s0) -#define __ENDIAN_DEFINED 1 -#define __BSWAP_DEFINED 1 -#endif - -/* Unknown */ -#if !__ENDIAN_DEFINED -#error Could not determine CPU byte order -#endif - -/* POSIX - http://austingroupbugs.net/view.php?id=162 */ -#ifndef BYTE_ORDER -#define BYTE_ORDER _BYTE_ORDER -#endif -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN _LITTLE_ENDIAN -#endif -#ifndef BIG_ENDIAN -#define BIG_ENDIAN _BIG_ENDIAN -#endif - -/* OpenCL compatibility - define __ENDIAN_LITTLE__ on little endian systems */ -#if _BYTE_ORDER == _LITTLE_ENDIAN -#if !defined(__ENDIAN_LITTLE__) -#define __ENDIAN_LITTLE__ 1 -#endif -#endif - -/* Byte swap macros */ -#if !__BSWAP_DEFINED - -#ifndef bswap16 -/* handle missing __builtin_bswap16 - * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52624 */ -#if defined __GNUC__ -#define bswap16(x) __builtin_bswap16(x) -#else -#define bswap16(x) \ - ((uint16_t)((((uint16_t)(x)&0xff00) >> 8) | (((uint16_t)(x)&0x00ff) << 8))) -#endif -#endif - -#ifndef bswap32 -#if defined __GNUC__ -#define bswap32(x) __builtin_bswap32(x) -#else -#define bswap32(x) \ - ((uint32_t)( \ - (((uint32_t)(x)&0xff000000) >> 24) | (((uint32_t)(x)&0x00ff0000) >> 8) | \ - (((uint32_t)(x)&0x0000ff00) << 8) | (((uint32_t)(x)&0x000000ff) << 24))) -#endif -#endif - -#ifndef bswap64 -#if defined __GNUC__ -#define bswap64(x) __builtin_bswap64(x) -#else -#define bswap64(x) \ - ((uint64_t)((((uint64_t)(x)&0xff00000000000000ull) >> 56) | \ - (((uint64_t)(x)&0x00ff000000000000ull) >> 40) | \ - (((uint64_t)(x)&0x0000ff0000000000ull) >> 24) | \ - (((uint64_t)(x)&0x000000ff00000000ull) >> 8) | \ - (((uint64_t)(x)&0x00000000ff000000ull) << 8) | \ - (((uint64_t)(x)&0x0000000000ff0000ull) << 24) | \ - (((uint64_t)(x)&0x000000000000ff00ull) << 40) | \ - (((uint64_t)(x)&0x00000000000000ffull) << 56))) -#endif -#endif - -#endif - -/* Host swap macros */ -#ifndef __HOSTSWAP_DEFINED -#if _BYTE_ORDER == _LITTLE_ENDIAN -#define htobe16(x) bswap16((x)) -#define htole16(x) ((uint16_t)(x)) -#define be16toh(x) bswap16((x)) -#define le16toh(x) ((uint16_t)(x)) - -#define htobe32(x) bswap32((x)) -#define htole32(x) ((uint32_t)(x)) -#define be32toh(x) bswap32((x)) -#define le32toh(x) ((uint32_t)(x)) - -#define htobe64(x) bswap64((x)) -#define htole64(x) ((uint64_t)(x)) -#define be64toh(x) bswap64((x)) -#define le64toh(x) ((uint64_t)(x)) -#elif _BYTE_ORDER == _BIG_ENDIAN -#define htobe16(x) ((uint16_t)(x)) -#define htole16(x) bswap16((x)) -#define be16toh(x) ((uint16_t)(x)) -#define le16toh(x) bswap16((x)) - -#define htobe32(x) ((uint32_t)(x)) -#define htole32(x) bswap32((x)) -#define be32toh(x) ((uint32_t)(x)) -#define le64toh(x) bswap64((x)) - -#define htobe64(x) ((uint64_t)(x)) -#define htole64(x) bswap64((x)) -#define be64toh(x) ((uint64_t)(x)) -#define le32toh(x) bswap32((x)) -#endif -#endif diff --git a/src/swap.c b/src/swap.c index dfca67b4..db0b987c 100644 --- a/src/swap.c +++ b/src/swap.c @@ -74,14 +74,14 @@ #if KERNEL_LINUX #define SWAP_HAVE_REPORT_BY_DEVICE 1 static derive_t pagesize; -static _Bool report_bytes = 0; -static _Bool report_by_device = 0; +static bool report_bytes; +static bool report_by_device; /* #endif KERNEL_LINUX */ #elif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS #define SWAP_HAVE_REPORT_BY_DEVICE 1 static derive_t pagesize; -static _Bool report_by_device = 0; +static bool report_by_device; /* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS */ #elif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS @@ -93,7 +93,7 @@ static _Bool report_by_device = 0; /* #endif defined(VM_SWAPUSAGE) */ #elif HAVE_LIBKVM_GETSWAPINFO -static kvm_t *kvm_obj = NULL; +static kvm_t *kvm_obj; int kvm_pagesize; /* #endif HAVE_LIBKVM_GETSWAPINFO */ @@ -109,9 +109,9 @@ static int pagesize; #error "No applicable input method." #endif /* HAVE_LIBSTATGRAB */ -static _Bool values_absolute = 1; -static _Bool values_percentage = 0; -static _Bool report_io = 1; +static bool values_absolute = true; +static bool values_percentage; +static bool report_io = true; static int swap_config(oconfig_item_t *ci) /* {{{ */ { @@ -203,10 +203,10 @@ static void swap_submit_usage(char const *plugin_instance, /* {{{ */ sstrncpy(vl.type, "swap", sizeof(vl.type)); if (values_absolute) - plugin_dispatch_multivalue(&vl, 0, DS_TYPE_GAUGE, "used", used, "free", + plugin_dispatch_multivalue(&vl, false, DS_TYPE_GAUGE, "used", used, "free", free, other_name, other_value, NULL); if (values_percentage) - plugin_dispatch_multivalue(&vl, 1, DS_TYPE_GAUGE, "used", used, "free", + plugin_dispatch_multivalue(&vl, true, DS_TYPE_GAUGE, "used", used, "free", free, other_name, other_value, NULL); } /* }}} void swap_submit_usage */ @@ -335,7 +335,7 @@ static int swap_read_io(void) /* {{{ */ FILE *fh; char buffer[1024]; - _Bool old_kernel = 0; + bool old_kernel = false; uint8_t have_data = 0; derive_t swap_in = 0; @@ -349,7 +349,7 @@ static int swap_read_io(void) /* {{{ */ WARNING("swap: fopen: %s", STRERRNO); return -1; } else - old_kernel = 1; + old_kernel = true; } while (fgets(buffer, sizeof(buffer), fh) != NULL) { @@ -556,7 +556,7 @@ static int swap_read(void) /* {{{ */ return -1; } - /* If the "separate" option was specified (report_by_device == 1), all + /* If the "separate" option was specified (report_by_device == true) all * values have already been dispatched from within the loop. */ if (!report_by_device) swap_submit_usage(NULL, total - avail, avail, NULL, NAN); diff --git a/src/syslog.c b/src/syslog.c index 90a97fb5..beb82456 100644 --- a/src/syslog.c +++ b/src/syslog.c @@ -38,7 +38,7 @@ static int log_level = LOG_DEBUG; #else static int log_level = LOG_INFO; #endif /* COLLECT_DEBUG */ -static int notif_severity = 0; +static int notif_severity; static const char *config_keys[] = { "LogLevel", "NotifyLevel", diff --git a/src/table.c b/src/table.c index 20f02756..492bea61 100644 --- a/src/table.c +++ b/src/table.c @@ -132,29 +132,14 @@ static size_t tables_num; /* * configuration handling */ - -static int tbl_config_set_s(char *name, char **var, oconfig_item_t *ci) { - if ((1 != ci->values_num) || (OCONFIG_TYPE_STRING != ci->values[0].type)) { - log_err("\"%s\" expects a single string argument.", name); - return 1; - } - - sfree(*var); - *var = sstrdup(ci->values[0].value.string); - return 0; -} /* tbl_config_set_separator */ - static int tbl_config_append_array_i(char *name, size_t **var, size_t *len, oconfig_item_t *ci) { - size_t *tmp; - size_t num; - - if (1 > ci->values_num) { + if (ci->values_num < 1) { log_err("\"%s\" expects at least one argument.", name); return 1; } - num = (size_t)ci->values_num; + size_t num = ci->values_num; for (size_t i = 0; i < num; ++i) { if (OCONFIG_TYPE_NUMBER != ci->values[i].type) { log_err("\"%s\" expects numerical arguments only.", name); @@ -162,8 +147,8 @@ static int tbl_config_append_array_i(char *name, size_t **var, size_t *len, } } - tmp = realloc(*var, ((*len) + num) * sizeof(**var)); - if (NULL == tmp) { + size_t *tmp = realloc(*var, ((*len) + num) * sizeof(**var)); + if (tmp == NULL) { log_err("realloc failed: %s.", STRERRNO); return -1; } @@ -178,7 +163,7 @@ static int tbl_config_append_array_i(char *name, size_t **var, size_t *len, } /* tbl_config_append_array_s */ static int tbl_config_result(tbl_t *tbl, oconfig_item_t *ci) { - if (0 != ci->values_num) { + if (ci->values_num != 0) { log_err(" does not expect any arguments."); return 1; } @@ -198,14 +183,14 @@ static int tbl_config_result(tbl_t *tbl, oconfig_item_t *ci) { for (int i = 0; i < ci->children_num; ++i) { oconfig_item_t *c = ci->children + i; - if (0 == strcasecmp(c->key, "Type")) - tbl_config_set_s(c->key, &res->type, c); - else if (0 == strcasecmp(c->key, "InstancePrefix")) - tbl_config_set_s(c->key, &res->instance_prefix, c); - else if (0 == strcasecmp(c->key, "InstancesFrom")) + if (strcasecmp(c->key, "Type") == 0) + cf_util_get_string(c, &res->type); + else if (strcasecmp(c->key, "InstancePrefix") == 0) + cf_util_get_string(c, &res->instance_prefix); + else if (strcasecmp(c->key, "InstancesFrom") == 0) tbl_config_append_array_i(c->key, &res->instances, &res->instances_num, c); - else if (0 == strcasecmp(c->key, "ValuesFrom")) + else if (strcasecmp(c->key, "ValuesFrom") == 0) tbl_config_append_array_i(c->key, &res->values, &res->values_num, c); else log_warn("Ignoring unknown config key \"%s\" " @@ -214,19 +199,19 @@ static int tbl_config_result(tbl_t *tbl, oconfig_item_t *ci) { } int status = 0; - if (NULL == res->type) { + if (res->type == NULL) { log_err("No \"Type\" option specified for in table \"%s\".", tbl->file); status = 1; } - if (NULL == res->values) { + if (res->values == NULL) { log_err("No \"ValuesFrom\" option specified for in table \"%s\".", tbl->file); status = 1; } - if (0 != status) { + if (status != 0) { tbl_result_clear(res); return status; } @@ -236,13 +221,13 @@ static int tbl_config_result(tbl_t *tbl, oconfig_item_t *ci) { } /* tbl_config_result */ static int tbl_config_table(oconfig_item_t *ci) { - if ((1 != ci->values_num) || (OCONFIG_TYPE_STRING != ci->values[0].type)) { + if (ci->values_num != 1 || ci->values[0].type != OCONFIG_TYPE_STRING) { log_err("
expects a single string argument."); return 1; } tbl_t *tbl = realloc(tables, (tables_num + 1) * sizeof(*tables)); - if (NULL == tbl) { + if (tbl == NULL) { log_err("realloc failed: %s.", STRERRNO); return -1; } @@ -252,16 +237,16 @@ static int tbl_config_table(oconfig_item_t *ci) { tbl = tables + tables_num; tbl_setup(tbl, ci->values[0].value.string); - for (size_t i = 0; i < ((size_t)ci->children_num); ++i) { + for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *c = ci->children + i; - if (0 == strcasecmp(c->key, "Separator")) - tbl_config_set_s(c->key, &tbl->sep, c); - else if (0 == strcasecmp(c->key, "Plugin")) - tbl_config_set_s(c->key, &tbl->plugin_name, c); - else if (0 == strcasecmp(c->key, "Instance")) - tbl_config_set_s(c->key, &tbl->instance, c); - else if (0 == strcasecmp(c->key, "Result")) + if (strcasecmp(c->key, "Separator") == 0) + cf_util_get_string(c, &tbl->sep); + else if (strcasecmp(c->key, "Plugin") == 0) + cf_util_get_string(c, &tbl->plugin_name); + else if (strcasecmp(c->key, "Instance") == 0) + cf_util_get_string(c, &tbl->instance); + else if (strcasecmp(c->key, "Result") == 0) tbl_config_result(tbl, c); else log_warn("Ignoring unknown config key \"%s\" " @@ -270,25 +255,25 @@ static int tbl_config_table(oconfig_item_t *ci) { } int status = 0; - if (NULL == tbl->sep) { + if (tbl->sep == NULL) { log_err("Table \"%s\" does not specify any separator.", tbl->file); status = 1; } else { strunescape(tbl->sep, strlen(tbl->sep) + 1); } - if (NULL == tbl->instance) { + if (tbl->instance == NULL) { tbl->instance = sstrdup(tbl->file); replace_special(tbl->instance, strlen(tbl->instance)); } - if (NULL == tbl->results) { + if (tbl->results == NULL) { assert(tbl->results_num == 0); log_err("Table \"%s\" does not specify any (valid) results.", tbl->file); status = 1; } - if (0 != status) { + if (status != 0) { tbl_clear(tbl); return status; } @@ -313,7 +298,7 @@ static int tbl_config(oconfig_item_t *ci) { for (int i = 0; i < ci->children_num; ++i) { oconfig_item_t *c = ci->children + i; - if (0 == strcasecmp(c->key, "Table")) + if (strcasecmp(c->key, "Table") == 0) tbl_config_table(c); else log_warn("Ignoring unknown config key \"%s\".", c->key); @@ -330,7 +315,7 @@ static int tbl_prepare(tbl_t *tbl) { tbl_result_t *res = tbl->results + i; res->ds = plugin_get_ds(res->type); - if (NULL == res->ds) { + if (res->ds == NULL) { log_err("Unknown type \"%s\". See types.db(5) for details.", res->type); return -1; } @@ -357,16 +342,13 @@ static int tbl_result_dispatch(tbl_t *tbl, tbl_result_t *res, char **fields, value_list_t vl = VALUE_LIST_INIT; value_t values[res->values_num]; - assert(NULL != res->ds); + assert(res->ds); assert(res->values_num == res->ds->ds_num); for (size_t i = 0; i < res->values_num; ++i) { - char *value; - assert(res->values[i] < fields_num); - value = fields[res->values[i]]; - - if (0 != parse_value(value, &values[i], res->ds->ds[i].type)) + char *value = fields[res->values[i]]; + if (parse_value(value, &values[i], res->ds->ds[i].type) != 0) return -1; } @@ -378,8 +360,8 @@ static int tbl_result_dispatch(tbl_t *tbl, tbl_result_t *res, char **fields, sstrncpy(vl.plugin_instance, tbl->instance, sizeof(vl.plugin_instance)); sstrncpy(vl.type, res->type, sizeof(vl.type)); - if (0 == res->instances_num) { - if (NULL != res->instance_prefix) + if (res->instances_num == 0) { + if (res->instance_prefix) sstrncpy(vl.type_instance, res->instance_prefix, sizeof(vl.type_instance)); } else { @@ -395,17 +377,15 @@ static int tbl_result_dispatch(tbl_t *tbl, tbl_result_t *res, char **fields, STATIC_ARRAY_SIZE(instances), "-"); instances_str[sizeof(instances_str) - 1] = '\0'; - vl.type_instance[sizeof(vl.type_instance) - 1] = '\0'; - if (NULL == res->instance_prefix) - strncpy(vl.type_instance, instances_str, sizeof(vl.type_instance)); + int r; + if (res->instance_prefix == NULL) + r = snprintf(vl.type_instance, sizeof(vl.type_instance), "%s", + instances_str); else - snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%s", - res->instance_prefix, instances_str); - - if ('\0' != vl.type_instance[sizeof(vl.type_instance) - 1]) { - vl.type_instance[sizeof(vl.type_instance) - 1] = '\0'; + r = snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%s", + res->instance_prefix, instances_str); + if ((size_t)r >= sizeof(vl.type_instance)) log_warn("Truncated type instance: %s.", vl.type_instance); - } } plugin_dispatch_values(&vl); @@ -414,15 +394,13 @@ static int tbl_result_dispatch(tbl_t *tbl, tbl_result_t *res, char **fields, static int tbl_parse_line(tbl_t *tbl, char *line, size_t len) { char *fields[tbl->max_colnum + 1]; - char *ptr, *saveptr; - size_t i = 0; - ptr = line; - saveptr = NULL; - while (NULL != (fields[i] = strtok_r(ptr, tbl->sep, &saveptr))) { + char *ptr = line; + char *saveptr = NULL; + while ((fields[i] = strtok_r(ptr, tbl->sep, &saveptr)) != NULL) { ptr = NULL; - ++i; + i++; if (i > tbl->max_colnum) break; @@ -436,8 +414,8 @@ static int tbl_parse_line(tbl_t *tbl, char *line, size_t len) { } for (i = 0; i < tbl->results_num; ++i) - if (0 != tbl_result_dispatch(tbl, tbl->results + i, fields, - STATIC_ARRAY_SIZE(fields))) { + if (tbl_result_dispatch(tbl, tbl->results + i, fields, + STATIC_ARRAY_SIZE(fields)) != 0) { log_err("Failed to dispatch result."); continue; } @@ -445,29 +423,28 @@ static int tbl_parse_line(tbl_t *tbl, char *line, size_t len) { } /* tbl_parse_line */ static int tbl_read_table(tbl_t *tbl) { - FILE *fh; char buf[4096]; - fh = fopen(tbl->file, "r"); - if (NULL == fh) { + FILE *fh = fopen(tbl->file, "r"); + if (fh == NULL) { log_err("Failed to open file \"%s\": %s.", tbl->file, STRERRNO); return -1; } buf[sizeof(buf) - 1] = '\0'; - while (NULL != fgets(buf, sizeof(buf), fh)) { - if ('\0' != buf[sizeof(buf) - 1]) { + while (fgets(buf, sizeof(buf), fh) != NULL) { + if (buf[sizeof(buf) - 1] != '\0') { buf[sizeof(buf) - 1] = '\0'; log_warn("Table %s: Truncated line: %s", tbl->file, buf); } - if (0 != tbl_parse_line(tbl, buf, sizeof(buf))) { + if (tbl_parse_line(tbl, buf, sizeof(buf)) != 0) { log_warn("Table %s: Failed to parse line: %s", tbl->file, buf); continue; } } - if (0 != ferror(fh)) { + if (ferror(fh) != 0) { log_err("Failed to read from file \"%s\": %s.", tbl->file, STRERRNO); fclose(fh); return -1; @@ -484,18 +461,18 @@ static int tbl_read_table(tbl_t *tbl) { static int tbl_read(void) { int status = -1; - if (0 == tables_num) + if (tables_num == 0) return 0; for (size_t i = 0; i < tables_num; ++i) { tbl_t *tbl = tables + i; - if (0 != tbl_prepare(tbl)) { + if (tbl_prepare(tbl) != 0) { log_err("Failed to prepare and parse table \"%s\".", tbl->file); continue; } - if (0 == tbl_read_table(tbl)) + if (tbl_read_table(tbl) == 0) status = 0; tbl_finish(tbl); @@ -511,7 +488,7 @@ static int tbl_shutdown(void) { } /* tbl_shutdown */ static int tbl_init(void) { - if (0 == tables_num) + if (tables_num == 0) return 0; plugin_register_read("table", tbl_read); diff --git a/src/tail.c b/src/tail.c index fbba4788..a6471d83 100644 --- a/src/tail.c +++ b/src/tail.c @@ -59,8 +59,8 @@ struct ctail_config_match_s { }; typedef struct ctail_config_match_s ctail_config_match_t; -static cu_tail_match_t **tail_match_list = NULL; -static size_t tail_match_list_num = 0; +static cu_tail_match_t **tail_match_list; +static size_t tail_match_list_num; static cdtime_t tail_match_list_intervals[255]; static int ctail_config_add_match_dstype(ctail_config_match_t *cm, @@ -134,8 +134,7 @@ static int ctail_config_add_match_dstype(ctail_config_match_t *cm, return 0; } /* int ctail_config_add_match_dstype */ -static int ctail_config_add_match(cu_tail_match_t *tm, - const char *plugin_name, +static int ctail_config_add_match(cu_tail_match_t *tm, const char *plugin_name, const char *plugin_instance, oconfig_item_t *ci, cdtime_t interval) { ctail_config_match_t cm = {0}; @@ -194,8 +193,8 @@ static int ctail_config_add_match(cu_tail_match_t *tm, // TODO(octo): there's nothing "simple" about the latency stuff … status = tail_match_add_match_simple( tm, cm.regex, cm.excluderegex, cm.flags, - (plugin_name != NULL) ? plugin_name : "tail", plugin_instance, - cm.type, cm.type_instance, cm.latency, interval); + (plugin_name != NULL) ? plugin_name : "tail", plugin_instance, cm.type, + cm.type_instance, cm.latency, interval); if (status != 0) ERROR("tail plugin: tail_match_add_match_simple failed."); @@ -234,7 +233,7 @@ static int ctail_config_add_file(oconfig_item_t *ci) { int status = 0; if (strcasecmp("Plugin", option->key) == 0) - status = cf_util_get_string (option, &plugin_name); + status = cf_util_get_string(option, &plugin_name); else if (strcasecmp("Instance", option->key) == 0) status = cf_util_get_string(option, &plugin_instance); else if (strcasecmp("Interval", option->key) == 0) diff --git a/src/tail_csv.c b/src/tail_csv.c index f963528b..be7cd40f 100644 --- a/src/tail_csv.c +++ b/src/tail_csv.c @@ -57,7 +57,7 @@ struct instance_definition_s { typedef struct instance_definition_s instance_definition_t; /* Private */ -static metric_definition_t *metric_head = NULL; +static metric_definition_t *metric_head; static int tcsv_submit(instance_definition_t *id, metric_definition_t *md, value_t v, cdtime_t t) { @@ -120,17 +120,17 @@ static int tcsv_read_metric(instance_definition_t *id, metric_definition_t *md, return tcsv_submit(id, md, v, t); } -static _Bool tcsv_check_index(ssize_t 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; + return true; else if (((size_t)index) < fields_num) - return 1; + return true; ERROR("tail_csv plugin: Metric \"%s\": Request for index %zd when " "only %" PRIsz " fields are available.", name, index, fields_num); - return 0; + return false; } static int tcsv_read_buffer(instance_definition_t *id, char *buffer, @@ -513,7 +513,7 @@ static int tcsv_config(oconfig_item_t *ci) { } /* int tcsv_config */ static int tcsv_init(void) { /* {{{ */ - static _Bool have_init = 0; + static bool have_init; metric_definition_t *md; if (have_init) diff --git a/src/tape.c b/src/tape.c index f59b7ea6..26bd969a 100644 --- a/src/tape.c +++ b/src/tape.c @@ -36,7 +36,7 @@ #define MAX_NUMTAPE 256 extern kstat_ctl_t *kc; static kstat_t *ksp[MAX_NUMTAPE]; -static int numtape = 0; +static int numtape; static int tape_init(void) { kstat_t *ksp_chain; diff --git a/src/target_replace.c b/src/target_replace.c index 54d41647..887507e1 100644 --- a/src/target_replace.c +++ b/src/target_replace.c @@ -37,7 +37,7 @@ typedef struct tr_action_s tr_action_t; struct tr_action_s { regex_t re; char *replacement; - _Bool may_be_empty; + bool may_be_empty; tr_action_t *next; }; @@ -110,7 +110,7 @@ static void tr_meta_data_action_destroy(tr_meta_data_action_t *act) /* {{{ */ } /* }}} void tr_meta_data_action_destroy */ static int tr_config_add_action(tr_action_t **dest, /* {{{ */ - const oconfig_item_t *ci, _Bool may_be_empty) { + const oconfig_item_t *ci, bool may_be_empty) { tr_action_t *act; int status; @@ -172,7 +172,7 @@ static int tr_config_add_action(tr_action_t **dest, /* {{{ */ static int tr_config_add_meta_action(tr_meta_data_action_t **dest, /* {{{ */ const oconfig_item_t *ci, - _Bool should_delete) { + bool should_delete) { tr_meta_data_action_t *act; int status; @@ -262,7 +262,7 @@ static int tr_config_add_meta_action(tr_meta_data_action_t **dest, /* {{{ */ static int tr_action_invoke(tr_action_t *act_head, /* {{{ */ char *buffer_in, size_t buffer_in_size, - _Bool may_be_empty) { + bool may_be_empty) { int status; char buffer[DATA_MAX_NAME_LEN]; regmatch_t matches[8] = {[0] = {0}}; @@ -306,7 +306,7 @@ static int tr_action_invoke(tr_action_t *act_head, /* {{{ */ DEBUG("target_replace plugin: tr_action_invoke: -- buffer = %s;", buffer); } /* for (act = act_head; act != NULL; act = act->next) */ - if ((may_be_empty == 0) && (buffer[0] == 0)) { + if ((may_be_empty == false) && (buffer[0] == 0)) { WARNING("Target `replace': Replacement resulted in an empty string, " "which is not allowed for this buffer (`host' or `plugin')."); return 0; @@ -470,13 +470,13 @@ static int tr_create(const oconfig_item_t *ci, void **user_data) /* {{{ */ if ((strcasecmp("Host", child->key) == 0) || (strcasecmp("Hostname", child->key) == 0)) status = tr_config_add_action(&data->host, child, - /* may be empty = */ 0); + /* may be empty = */ false); else if (strcasecmp("Plugin", child->key) == 0) status = tr_config_add_action(&data->plugin, child, - /* may be empty = */ 0); + /* may be empty = */ false); else if (strcasecmp("PluginInstance", child->key) == 0) status = tr_config_add_action(&data->plugin_instance, child, - /* may be empty = */ 1); + /* may be empty = */ true); #if 0 else if (strcasecmp ("Type", child->key) == 0) status = tr_config_add_action (&data->type, child, @@ -484,13 +484,13 @@ static int tr_create(const oconfig_item_t *ci, void **user_data) /* {{{ */ #endif else if (strcasecmp("TypeInstance", child->key) == 0) status = tr_config_add_action(&data->type_instance, child, - /* may be empty = */ 1); + /* may be empty = */ true); else if (strcasecmp("MetaData", child->key) == 0) status = tr_config_add_meta_action(&data->meta, child, - /* should delete = */ 0); + /* should delete = */ false); else if (strcasecmp("DeleteMetaData", child->key) == 0) status = tr_config_add_meta_action(&data->meta, child, - /* should delete = */ 1); + /* should delete = */ true); else { ERROR("Target `replace': The `%s' configuration option is not understood " "and will be ignored.", @@ -546,11 +546,11 @@ static int tr_invoke(const data_set_t *ds, value_list_t *vl, /* {{{ */ #define HANDLE_FIELD(f, e) \ if (data->f != NULL) \ tr_action_invoke(data->f, vl->f, sizeof(vl->f), e) - HANDLE_FIELD(host, 0); - HANDLE_FIELD(plugin, 0); - HANDLE_FIELD(plugin_instance, 1); - /* HANDLE_FIELD (type, 0); */ - HANDLE_FIELD(type_instance, 1); + HANDLE_FIELD(host, false); + HANDLE_FIELD(plugin, false); + HANDLE_FIELD(plugin_instance, true); + /* HANDLE_FIELD (type, false); */ + HANDLE_FIELD(type_instance, true); return FC_TARGET_CONTINUE; } /* }}} int tr_invoke */ diff --git a/src/target_v5upgrade.c b/src/target_v5upgrade.c index 49f09f08..650f9a5e 100644 --- a/src/target_v5upgrade.c +++ b/src/target_v5upgrade.c @@ -213,15 +213,15 @@ static int v5_mysql_threads(const data_set_t *ds, value_list_t *vl) /* {{{ */ static int v5_zfs_arc_counts(const data_set_t *ds, value_list_t *vl) /* {{{ */ { value_list_t new_vl; - _Bool is_hits; + bool is_hits; if (vl->values_len != 4) return FC_TARGET_STOP; if (strcmp("hits", vl->type_instance) == 0) - is_hits = 1; + is_hits = true; else if (strcmp("misses", vl->type_instance) == 0) - is_hits = 0; + is_hits = false; else return FC_TARGET_STOP; diff --git a/src/tcpconns.c b/src/tcpconns.c index 3889d0ff..5a3fd4ef 100644 --- a/src/tcpconns.c +++ b/src/tcpconns.c @@ -76,7 +76,6 @@ #endif #if KERNEL_LINUX -#include #include #if HAVE_LINUX_INET_DIAG_H #include @@ -206,7 +205,7 @@ static const char *tcp_state[] = {"CLOSED", "LISTEN", "SYN_SENT", "FIN_WAIT2", "TIME_WAIT"}; static kvm_t *kvmd; -static u_long inpcbtable_off = 0; +static u_long inpcbtable_off; struct inpcbtable *inpcbtable_ptr = NULL; #define TCP_STATE_LISTEN 1 @@ -262,9 +261,9 @@ static const char *config_keys[] = {"ListeningPorts", "LocalPort", "RemotePort", "AllPortsSummary"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static int port_collect_listening = 0; -static int port_collect_total = 0; -static port_entry_t *port_list_head = NULL; +static int port_collect_listening; +static int port_collect_total; +static port_entry_t *port_list_head; static uint32_t count_total[TCP_STATE_MAX + 1]; #if KERNEL_LINUX @@ -272,7 +271,7 @@ static uint32_t count_total[TCP_STATE_MAX + 1]; /* This depends on linux inet_diag_req because if this structure is missing, * sequence_number is useless and we get a compilation warning. */ -static uint32_t sequence_number = 0; +static uint32_t sequence_number; #endif static enum { SRC_DUNNO, SRC_NETLINK, SRC_PROC } linux_source = SRC_DUNNO; @@ -499,7 +498,6 @@ static int conn_read_netlink(void) { iov.iov_len = sizeof(buf); while (1) { - int status; struct nlmsghdr *h; memset(&msg, 0, sizeof(msg)); @@ -508,7 +506,7 @@ static int conn_read_netlink(void) { msg.msg_iov = &iov; msg.msg_iovlen = 1; - status = recvmsg(fd, (void *)&msg, /* flags = */ 0); + ssize_t status = recvmsg(fd, (void *)&msg, /* flags = */ 0); if (status < 0) { if ((errno == EINTR) || (errno == EAGAIN)) continue; @@ -575,11 +573,11 @@ static int conn_handle_line(char *buffer) { uint8_t state; - int buffer_len = strlen(buffer); + size_t buffer_len = strlen(buffer); while ((buffer_len > 0) && (buffer[buffer_len - 1] < 32)) buffer[--buffer_len] = '\0'; - if (buffer_len <= 0) + if (buffer_len == 0) return -1; fields_len = strsplit(buffer, fields, STATIC_ARRAY_SIZE(fields)); diff --git a/src/teamspeak2.c b/src/teamspeak2.c index ae9200c1..6d0cdbb8 100644 --- a/src/teamspeak2.c +++ b/src/teamspeak2.c @@ -46,14 +46,14 @@ typedef struct vserver_list_s { int port; struct vserver_list_s *next; } vserver_list_t; -static vserver_list_t *server_list = NULL; +static vserver_list_t *server_list; /* Host data */ -static char *config_host = NULL; -static char *config_port = NULL; +static char *config_host; +static char *config_port; -static FILE *global_read_fh = NULL; -static FILE *global_write_fh = NULL; +static FILE *global_read_fh; +static FILE *global_write_fh; /* Config data */ static const char *config_keys[] = {"Host", "Port", "Server"}; diff --git a/src/ted.c b/src/ted.c index b8036810..b5fa4c1e 100644 --- a/src/ted.c +++ b/src/ted.c @@ -53,8 +53,8 @@ #define DEFAULT_DEVICE "/dev/ttyUSB0" -static char *conf_device = NULL; -static int conf_retries = 0; +static char *conf_device; +static int conf_retries; static int fd = -1; diff --git a/src/testing.h b/src/testing.h index d3da9db4..5cf69559 100644 --- a/src/testing.h +++ b/src/testing.h @@ -29,8 +29,8 @@ #include -static int fail_count__ = 0; -static int check_count__ = 0; +static int fail_count__; +static int check_count__; #ifndef DBL_PRECISION #define DBL_PRECISION 1e-12 @@ -56,7 +56,7 @@ static int check_count__ = 0; #define OK1(cond, text) \ do { \ - _Bool result = (cond); \ + bool result = (cond); \ LOG(result, text); \ if (!result) { \ return -1; \ diff --git a/src/thermal.c b/src/thermal.c index 9da8fa5f..959fec64 100644 --- a/src/thermal.c +++ b/src/thermal.c @@ -35,7 +35,7 @@ static const char *config_keys[] = {"Device", "IgnoreSelected", static const char *const dirname_sysfs = "/sys/class/thermal"; static const char *const dirname_procfs = "/proc/acpi/thermal_zone"; -static _Bool force_procfs = 0; +static bool force_procfs; static ignorelist_t *device_list; enum dev_type { TEMP = 0, COOLING_DEV }; @@ -59,7 +59,7 @@ static int thermal_sysfs_device_read(const char __attribute__((unused)) * dir, const char *name, void __attribute__((unused)) * user_data) { char filename[PATH_MAX]; - _Bool success = 0; + bool success = false; value_t value; if (device_list && ignorelist_match(device_list, name)) @@ -69,13 +69,13 @@ static int thermal_sysfs_device_read(const char __attribute__((unused)) * dir, if (parse_value_file(filename, &value, DS_TYPE_GAUGE) == 0) { value.gauge /= 1000.0; thermal_submit(name, TEMP, value); - success = 1; + success = true; } snprintf(filename, sizeof(filename), "%s/%s/cur_state", dirname_sysfs, name); if (parse_value_file(filename, &value, DS_TYPE_GAUGE) == 0) { thermal_submit(name, COOLING_DEV, value); - success = 1; + success = true; } return success ? 0 : -1; @@ -157,9 +157,9 @@ static int thermal_config(const char *key, const char *value) { if (IS_TRUE(value)) ignorelist_set_invert(device_list, 0); } else if (strcasecmp(key, "ForceUseProcfs") == 0) { - force_procfs = 0; + force_procfs = false; if (IS_TRUE(value)) - force_procfs = 1; + force_procfs = true; } else { return -1; } diff --git a/src/threshold.c b/src/threshold.c index 79001334..79300f14 100644 --- a/src/threshold.c +++ b/src/threshold.c @@ -109,90 +109,6 @@ static int ut_threshold_add(const threshold_t *th) { /* {{{ */ * The following approximately two hundred functions are used to handle the * configuration and fill the threshold list. * {{{ */ -static int ut_config_type_datasource(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - WARNING("threshold values: The `DataSource' option needs exactly one " - "string argument."); - return -1; - } - - sstrncpy(th->data_source, ci->values[0].value.string, - sizeof(th->data_source)); - - return 0; -} /* int ut_config_type_datasource */ - -static int ut_config_type_instance(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - WARNING("threshold values: The `Instance' option needs exactly one " - "string argument."); - return -1; - } - - sstrncpy(th->type_instance, ci->values[0].value.string, - sizeof(th->type_instance)); - - return 0; -} /* int ut_config_type_instance */ - -static int ut_config_type_max(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) { - WARNING("threshold values: The `%s' option needs exactly one " - "number argument.", - ci->key); - return -1; - } - - if (strcasecmp(ci->key, "WarningMax") == 0) - th->warning_max = ci->values[0].value.number; - else - th->failure_max = ci->values[0].value.number; - - return 0; -} /* int ut_config_type_max */ - -static int ut_config_type_min(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) { - WARNING("threshold values: The `%s' option needs exactly one " - "number argument.", - ci->key); - return -1; - } - - if (strcasecmp(ci->key, "WarningMin") == 0) - th->warning_min = ci->values[0].value.number; - else - th->failure_min = ci->values[0].value.number; - - return 0; -} /* int ut_config_type_min */ - -static int ut_config_type_hits(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) { - WARNING("threshold values: The `%s' option needs exactly one " - "number argument.", - ci->key); - return -1; - } - - th->hits = ci->values[0].value.number; - - return 0; -} /* int ut_config_type_hits */ - -static int ut_config_type_hysteresis(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) { - WARNING("threshold values: The `%s' option needs exactly one " - "number argument.", - ci->key); - return -1; - } - - th->hysteresis = ci->values[0].value.number; - - return 0; -} /* int ut_config_type_hysteresis */ - static int ut_config_type(const threshold_t *th_orig, oconfig_item_t *ci) { threshold_t th; int status = 0; @@ -223,15 +139,19 @@ static int ut_config_type(const threshold_t *th_orig, oconfig_item_t *ci) { oconfig_item_t *option = ci->children + i; if (strcasecmp("Instance", option->key) == 0) - status = ut_config_type_instance(&th, option); + status = cf_util_get_string_buffer(option, th.type_instance, + sizeof(th.type_instance)); else if (strcasecmp("DataSource", option->key) == 0) - status = ut_config_type_datasource(&th, option); - else if ((strcasecmp("WarningMax", option->key) == 0) || - (strcasecmp("FailureMax", option->key) == 0)) - status = ut_config_type_max(&th, option); - else if ((strcasecmp("WarningMin", option->key) == 0) || - (strcasecmp("FailureMin", option->key) == 0)) - status = ut_config_type_min(&th, option); + status = cf_util_get_string_buffer(option, th.data_source, + sizeof(th.data_source)); + else if (strcasecmp("WarningMax", option->key) == 0) + status = cf_util_get_double(option, &th.warning_max); + else if (strcasecmp("FailureMax", option->key) == 0) + status = cf_util_get_double(option, &th.failure_max); + else if (strcasecmp("WarningMin", option->key) == 0) + status = cf_util_get_double(option, &th.warning_min); + else if (strcasecmp("FailureMin", option->key) == 0) + status = cf_util_get_double(option, &th.failure_min); else if (strcasecmp("Interesting", option->key) == 0) status = cf_util_get_flag(option, &th.flags, UT_FLAG_INTERESTING); else if (strcasecmp("Invert", option->key) == 0) @@ -243,9 +163,9 @@ static int ut_config_type(const threshold_t *th_orig, oconfig_item_t *ci) { else if (strcasecmp("Percentage", option->key) == 0) status = cf_util_get_flag(option, &th.flags, UT_FLAG_PERCENTAGE); else if (strcasecmp("Hits", option->key) == 0) - status = ut_config_type_hits(&th, option); + status = cf_util_get_int(option, &th.hits); else if (strcasecmp("Hysteresis", option->key) == 0) - status = ut_config_type_hysteresis(&th, option); + status = cf_util_get_double(option, &th.hysteresis); else { WARNING("threshold values: Option `%s' not allowed inside a `Type' " "block.", @@ -264,19 +184,6 @@ static int ut_config_type(const threshold_t *th_orig, oconfig_item_t *ci) { return status; } /* int ut_config_type */ -static int ut_config_plugin_instance(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - WARNING("threshold values: The `Instance' option needs exactly one " - "string argument."); - return -1; - } - - sstrncpy(th->plugin_instance, ci->values[0].value.string, - sizeof(th->plugin_instance)); - - return 0; -} /* int ut_config_plugin_instance */ - static int ut_config_plugin(const threshold_t *th_orig, oconfig_item_t *ci) { threshold_t th; int status = 0; @@ -302,7 +209,8 @@ static int ut_config_plugin(const threshold_t *th_orig, oconfig_item_t *ci) { if (strcasecmp("Type", option->key) == 0) status = ut_config_type(&th, option); else if (strcasecmp("Instance", option->key) == 0) - status = ut_config_plugin_instance(&th, option); + status = cf_util_get_string_buffer(option, th.plugin_instance, + sizeof(th.plugin_instance)); else { WARNING("threshold values: Option `%s' not allowed inside a `Plugin' " "block.", diff --git a/src/tokyotyrant.c b/src/tokyotyrant.c index 1534f51e..aca0a4e3 100644 --- a/src/tokyotyrant.c +++ b/src/tokyotyrant.c @@ -33,10 +33,10 @@ static const char *config_keys[] = {"Host", "Port"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static char *config_host = NULL; -static char *config_port = NULL; +static char *config_host; +static char *config_port; -static TCRDB *rdb = NULL; +static TCRDB *rdb; static int tt_config(const char *key, const char *value) { if (strcasecmp("Host", key) == 0) { diff --git a/src/turbostat.c b/src/turbostat.c index 85f7d87f..68cf4120 100644 --- a/src/turbostat.c +++ b/src/turbostat.c @@ -65,12 +65,12 @@ * * This value is automatically set if mperf or aperf go backward */ -static _Bool aperf_mperf_unstable; +static bool aperf_mperf_unstable; /* * If set, use kernel logical core numbering for all "per core" metrics. */ -static _Bool config_lcn; +static bool config_lcn; /* * Bitmask of the list of core C states supported by the processor. @@ -78,7 +78,7 @@ static _Bool config_lcn; */ static unsigned int do_core_cstate; static unsigned int config_core_cstate; -static _Bool apply_config_core_cstate; +static bool apply_config_core_cstate; /* * Bitmask of the list of pacages C states supported by the processor. @@ -86,15 +86,15 @@ static _Bool apply_config_core_cstate; */ static unsigned int do_pkg_cstate; static unsigned int config_pkg_cstate; -static _Bool apply_config_pkg_cstate; +static bool apply_config_pkg_cstate; /* * Boolean indicating if the processor supports 'I/O System-Management Interrupt * counter' */ -static _Bool do_smi; -static _Bool config_smi; -static _Bool apply_config_smi; +static bool do_smi; +static bool config_smi; +static bool apply_config_smi; /* * Boolean indicating if the processor supports 'Digital temperature sensor' @@ -105,9 +105,9 @@ static _Bool apply_config_smi; * might be wrong * - Temperatures above the tcc_activation_temp are not recorded */ -static _Bool do_dts; -static _Bool config_dts; -static _Bool apply_config_dts; +static bool do_dts; +static bool config_dts; +static bool apply_config_dts; /* * Boolean indicating if the processor supports 'Package thermal management' @@ -118,9 +118,9 @@ static _Bool apply_config_dts; * might be wrong * - Temperatures above the tcc_activation_temp are not recorded */ -static _Bool do_ptm; -static _Bool config_ptm; -static _Bool apply_config_ptm; +static bool do_ptm; +static bool config_ptm; +static bool apply_config_ptm; /* * Thermal Control Circuit Activation Temperature as configured by the user. @@ -131,7 +131,7 @@ static unsigned int tcc_activation_temp; static unsigned int do_rapl; static unsigned int config_rapl; -static _Bool apply_config_rapl; +static bool apply_config_rapl; static double rapl_energy_units; #define RAPL_PKG (1 << 0) @@ -195,10 +195,10 @@ static struct pkg_data { #define DELTA_COUNTERS thread_delta, core_delta, package_delta #define ODD_COUNTERS thread_odd, core_odd, package_odd #define EVEN_COUNTERS thread_even, core_even, package_even -static _Bool is_even = 1; +static bool is_even = true; -static _Bool allocated = 0; -static _Bool initialized = 0; +static bool allocated; +static bool initialized; #define GET_THREAD(thread_base, thread_no, core_no, pkg_no) \ (thread_base + (pkg_no)*topology.num_cores * topology.num_threads + \ @@ -210,8 +210,8 @@ static _Bool initialized = 0; struct cpu_topology { unsigned int package_id; unsigned int core_id; - _Bool first_core_in_package; - _Bool first_thread_in_core; + bool first_core_in_package; + bool first_thread_in_core; }; static struct topology { @@ -243,10 +243,10 @@ static const int config_keys_num = STATIC_ARRAY_SIZE(config_keys); /* * Open a MSR device for reading * Can change the scheduling affinity of the current process if multiple_read is - * 1 + * true */ static int __attribute__((warn_unused_result)) -open_msr(unsigned int cpu, _Bool multiple_read) { +open_msr(unsigned int cpu, bool multiple_read) { char pathname[32]; int fd; @@ -487,7 +487,7 @@ delta_thread(struct thread_data *delta, const struct thread_data *new, "the entire interval. Fix this by running " "Linux-2.6.30 or later."); - aperf_mperf_unstable = 1; + aperf_mperf_unstable = true; } } @@ -895,14 +895,14 @@ static int __attribute__((warn_unused_result)) probe_cpu(void) { switch (model) { /* Atom (partial) */ case 0x27: - do_smi = 0; + do_smi = false; do_core_cstate = 0; do_pkg_cstate = (1 << 2) | (1 << 4) | (1 << 6); break; /* Silvermont */ case 0x37: /* BYT */ case 0x4D: /* AVN */ - do_smi = 1; + do_smi = true; do_core_cstate = (1 << 1) | (1 << 6); do_pkg_cstate = (1 << 6); break; @@ -912,7 +912,7 @@ static int __attribute__((warn_unused_result)) probe_cpu(void) { Forest */ case 0x1F: /* Core i7 and i5 Processor - Nehalem */ case 0x2E: /* Nehalem-EX Xeon - Beckton */ - do_smi = 1; + do_smi = true; do_core_cstate = (1 << 3) | (1 << 6); do_pkg_cstate = (1 << 3) | (1 << 6) | (1 << 7); break; @@ -920,21 +920,21 @@ static int __attribute__((warn_unused_result)) probe_cpu(void) { case 0x25: /* Westmere Client - Clarkdale, Arrandale */ case 0x2C: /* Westmere EP - Gulftown */ case 0x2F: /* Westmere-EX Xeon - Eagleton */ - do_smi = 1; + do_smi = true; do_core_cstate = (1 << 3) | (1 << 6); do_pkg_cstate = (1 << 3) | (1 << 6) | (1 << 7); break; /* Sandy Bridge */ case 0x2A: /* SNB */ case 0x2D: /* SNB Xeon */ - do_smi = 1; + do_smi = true; do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7); do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7); break; /* Ivy Bridge */ case 0x3A: /* IVB */ case 0x3E: /* IVB Xeon */ - do_smi = 1; + do_smi = true; do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7); do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7); break; @@ -942,31 +942,31 @@ static int __attribute__((warn_unused_result)) probe_cpu(void) { case 0x3C: /* HSW */ case 0x3F: /* HSW */ case 0x46: /* HSW */ - do_smi = 1; + do_smi = true; do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7); do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7); break; case 0x45: /* HSW */ - do_smi = 1; + do_smi = true; do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7); do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10); break; - /* Broadwel */ + /* Broadwell */ case 0x4F: /* BDW */ case 0x56: /* BDX-DE */ - do_smi = 1; + do_smi = true; do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7); do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7); break; case 0x3D: /* BDW */ - do_smi = 1; + do_smi = true; do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7); do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10); break; default: - do_smi = 0; + do_smi = false; do_core_cstate = 0; do_pkg_cstate = 0; break; @@ -1227,7 +1227,7 @@ static int __attribute__((warn_unused_result)) topology_probe(void) { if (ret < 0) goto err; else if ((unsigned int)ret == i) - cpu->first_core_in_package = 1; + cpu->first_core_in_package = true; ret = get_threads_on_core(i); if (ret < 0) @@ -1241,7 +1241,7 @@ static int __attribute__((warn_unused_result)) topology_probe(void) { if (ret < 0) goto err; else if ((unsigned int)ret == i) - cpu->first_thread_in_core = 1; + cpu->first_thread_in_core = true; DEBUG("turbostat plugin: cpu %d pkg %d core %d\n", i, cpu->package_id, cpu->core_id); @@ -1289,15 +1289,15 @@ static int allocate_counters(struct thread_data **threads, *cores = calloc(total_cores, sizeof(struct core_data)); if (*cores == NULL) { ERROR("turbostat plugin: calloc failed"); - sfree(threads); + sfree(*threads); return -1; } *packages = calloc(topology.num_packages, sizeof(struct pkg_data)); if (*packages == NULL) { ERROR("turbostat plugin: calloc failed"); - sfree(cores); - sfree(threads); + sfree(*cores); + sfree(*threads); return -1; } @@ -1338,8 +1338,8 @@ static void initialize_counters(void) { } static void free_all_buffers(void) { - allocated = 0; - initialized = 0; + allocated = false; + initialized = false; CPU_FREE(cpu_present_set); cpu_present_set = NULL; @@ -1400,7 +1400,7 @@ static int setup_all_buffers(void) { DO_OR_GOTO_ERR(for_all_cpus(set_temperature_target, EVEN_COUNTERS)); DO_OR_GOTO_ERR(for_all_cpus(set_temperature_target, ODD_COUNTERS)); - allocated = 1; + allocated = true; return 0; err: free_all_buffers(); @@ -1437,8 +1437,8 @@ static int turbostat_read(void) { if ((ret = for_all_cpus(get_counters, EVEN_COUNTERS)) < 0) goto out; time_even = cdtime(); - is_even = 1; - initialized = 1; + is_even = true; + initialized = true; ret = 0; goto out; } @@ -1447,7 +1447,7 @@ static int turbostat_read(void) { if ((ret = for_all_cpus(get_counters, ODD_COUNTERS)) < 0) goto out; time_odd = cdtime(); - is_even = 0; + is_even = false; time_delta = time_odd - time_even; if ((ret = for_all_cpus_delta(ODD_COUNTERS, EVEN_COUNTERS)) < 0) goto out; @@ -1457,7 +1457,7 @@ static int turbostat_read(void) { if ((ret = for_all_cpus(get_counters, EVEN_COUNTERS)) < 0) goto out; time_even = cdtime(); - is_even = 1; + is_even = true; time_delta = time_even - time_odd; if ((ret = for_all_cpus_delta(EVEN_COUNTERS, ODD_COUNTERS)) < 0) goto out; @@ -1554,7 +1554,7 @@ static int turbostat_config(const char *key, const char *value) { return -1; } config_core_cstate = (unsigned int)tmp_val; - apply_config_core_cstate = 1; + apply_config_core_cstate = true; } else if (strcasecmp("PackageCstates", key) == 0) { tmp_val = strtoul(value, &end, 0); if (*end != '\0' || tmp_val > UINT_MAX) { @@ -1562,16 +1562,16 @@ static int turbostat_config(const char *key, const char *value) { return -1; } config_pkg_cstate = (unsigned int)tmp_val; - apply_config_pkg_cstate = 1; + apply_config_pkg_cstate = true; } else if (strcasecmp("SystemManagementInterrupt", key) == 0) { config_smi = IS_TRUE(value); - apply_config_smi = 1; + apply_config_smi = true; } else if (strcasecmp("DigitalTemperatureSensor", key) == 0) { config_dts = IS_TRUE(value); - apply_config_dts = 1; + apply_config_dts = true; } else if (strcasecmp("PackageThermalManagement", key) == 0) { config_ptm = IS_TRUE(value); - apply_config_ptm = 1; + apply_config_ptm = true; } else if (strcasecmp("LogicalCoreNames", key) == 0) { config_lcn = IS_TRUE(value); } else if (strcasecmp("RunningAveragePowerLimit", key) == 0) { @@ -1581,7 +1581,7 @@ static int turbostat_config(const char *key, const char *value) { return -1; } config_rapl = (unsigned int)tmp_val; - apply_config_rapl = 1; + apply_config_rapl = true; } else if (strcasecmp("TCCActivationTemp", key) == 0) { tmp_val = strtoul(value, &end, 0); if (*end != '\0' || tmp_val > UINT_MAX) { diff --git a/src/types.db b/src/types.db index f27ba465..f4933ee3 100644 --- a/src/types.db +++ b/src/types.db @@ -31,6 +31,7 @@ clock_state value:GAUGE:0:U clock_stratum value:GAUGE:0:U compression uncompressed:DERIVE:0:U, compressed:DERIVE:0:U compression_ratio value:GAUGE:0:2 +commands value:DERIVE:0:U connections value:DERIVE:0:U conntrack value:GAUGE:0:4294967295 contextswitch value:DERIVE:0:U @@ -111,6 +112,7 @@ if_octets rx:DERIVE:0:U, tx:DERIVE:0:U if_packets rx:DERIVE:0:U, tx:DERIVE:0:U if_rx_dropped value:DERIVE:0:U if_rx_errors value:DERIVE:0:U +if_rx_nohandler value:DERIVE:0:U if_rx_octets value:DERIVE:0:U if_rx_packets value:DERIVE:0:U if_tx_dropped value:DERIVE:0:U @@ -210,6 +212,7 @@ ps_vm value:GAUGE:0:9223372036854775807 pubsub value:GAUGE:0:U queue_length value:GAUGE:0:U records value:GAUGE:0:U +redis_command_cputime value:DERIVE:0:U requests value:GAUGE:0:U response_code value:GAUGE:0:U response_time value:GAUGE:0:U diff --git a/src/unixsock.c b/src/unixsock.c index bceafe6d..8c08e18a 100644 --- a/src/unixsock.c +++ b/src/unixsock.c @@ -55,14 +55,14 @@ static const char *config_keys[] = {"SocketFile", "SocketGroup", "SocketPerms", "DeleteSocket"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static int loop = 0; +static int loop; /* socket configuration */ static int sock_fd = -1; -static char *sock_file = NULL; -static char *sock_group = NULL; +static char *sock_file; +static char *sock_group; static int sock_perms = S_IRWXU | S_IRWXG; -static _Bool delete_socket = 0; +static bool delete_socket; static pthread_t listen_thread = (pthread_t)0; @@ -208,7 +208,6 @@ static void *us_handle_client(void *arg) { char buffer_copy[1024]; char *fields[128]; int fields_num; - int len; errno = 0; if (fgets(buffer, sizeof(buffer), fhin) == NULL) { @@ -222,7 +221,7 @@ static void *us_handle_client(void *arg) { break; } - len = strlen(buffer); + size_t len = strlen(buffer); while ((len > 0) && ((buffer[len - 1] == '\n') || (buffer[len - 1] == '\r'))) buffer[--len] = '\0'; @@ -350,9 +349,9 @@ static int us_config(const char *key, const char *val) { sock_perms = (int)strtol(val, NULL, 8); } else if (strcasecmp(key, "DeleteSocket") == 0) { if (IS_TRUE(val)) - delete_socket = 1; + delete_socket = true; else - delete_socket = 0; + delete_socket = false; } else { return -1; } @@ -361,7 +360,7 @@ static int us_config(const char *key, const char *val) { } /* int us_config */ static int us_init(void) { - static int have_init = 0; + static int have_init; int status; diff --git a/src/utils_cmd_listval.c b/src/utils_cmd_listval.c index df23a954..24ec9421 100644 --- a/src/utils_cmd_listval.c +++ b/src/utils_cmd_listval.c @@ -34,8 +34,6 @@ #include "utils_parse_option.h" cmd_status_t cmd_parse_listval(size_t argc, char **argv, - cmd_listval_t *ret_listval - __attribute__((unused)), const cmd_options_t *opts __attribute__((unused)), cmd_error_handler_t *err) { @@ -103,7 +101,3 @@ cmd_status_t cmd_handle_listval(FILE *fh, char *buffer) { free_everything_and_return(CMD_OK); } /* cmd_status_t cmd_handle_listval */ - -void cmd_destroy_listval(cmd_listval_t *listval __attribute__((unused))) { - /* nothing to do */ -} /* void cmd_destroy_listval */ diff --git a/src/utils_cmd_listval.h b/src/utils_cmd_listval.h index 6abdeee3..6dbaabcb 100644 --- a/src/utils_cmd_listval.h +++ b/src/utils_cmd_listval.h @@ -32,12 +32,9 @@ #include "utils_cmds.h" cmd_status_t cmd_parse_listval(size_t argc, char **argv, - cmd_listval_t *ret_listval, const cmd_options_t *opts, cmd_error_handler_t *err); cmd_status_t cmd_handle_listval(FILE *fh, char *buffer); -void cmd_destroy_listval(cmd_listval_t *listval); - #endif /* UTILS_CMD_LISTVAL_H */ diff --git a/src/utils_cmd_putval.c b/src/utils_cmd_putval.c index 6f1bc39e..b5b9065b 100644 --- a/src/utils_cmd_putval.c +++ b/src/utils_cmd_putval.c @@ -271,7 +271,7 @@ int cmd_create_putval(char *ret, size_t ret_len, /* {{{ */ escape_string(buffer_ident, sizeof(buffer_ident)); status = format_values(buffer_values, sizeof(buffer_values), ds, vl, - /* store rates = */ 0); + /* store rates = */ false); if (status != 0) return status; escape_string(buffer_values, sizeof(buffer_values)); diff --git a/src/utils_cmds.c b/src/utils_cmds.c index fe57d5a2..88fdfc7f 100644 --- a/src/utils_cmds.c +++ b/src/utils_cmds.c @@ -206,8 +206,7 @@ cmd_status_t cmd_parsev(size_t argc, char **argv, cmd_t *ret_cmd, cmd_parse_getval(argc - 1, argv + 1, &ret_cmd->cmd.getval, opts, err); } else if (strcasecmp("LISTVAL", command) == 0) { ret_cmd->type = CMD_LISTVAL; - status = - cmd_parse_listval(argc - 1, argv + 1, &ret_cmd->cmd.listval, opts, err); + status = cmd_parse_listval(argc - 1, argv + 1, opts, err); } else if (strcasecmp("PUTVAL", command) == 0) { ret_cmd->type = CMD_PUTVAL; status = @@ -252,7 +251,6 @@ void cmd_destroy(cmd_t *cmd) { cmd_destroy_getval(&cmd->cmd.getval); break; case CMD_LISTVAL: - cmd_destroy_listval(&cmd->cmd.listval); break; case CMD_PUTVAL: cmd_destroy_putval(&cmd->cmd.putval); diff --git a/src/utils_cmds.h b/src/utils_cmds.h index 26d5338d..f3882f54 100644 --- a/src/utils_cmds.h +++ b/src/utils_cmds.h @@ -39,13 +39,13 @@ typedef enum { CMD_PUTVAL = 4, } cmd_type_t; #define CMD_TO_STRING(type) \ - ((type) == CMD_FLUSH) ? "FLUSH" : ((type) == CMD_GETVAL) \ - ? "GETVAL" \ - : ((type) == CMD_LISTVAL) \ - ? "LISTVAL" \ - : ((type) == CMD_PUTVAL) \ - ? "PUTVAL" \ - : "UNKNOWN" + ((type) == CMD_FLUSH) \ + ? "FLUSH" \ + : ((type) == CMD_GETVAL) \ + ? "GETVAL" \ + : ((type) == CMD_LISTVAL) \ + ? "LISTVAL" \ + : ((type) == CMD_PUTVAL) ? "PUTVAL" : "UNKNOWN" typedef struct { double timeout; @@ -62,9 +62,6 @@ typedef struct { } cmd_getval_t; typedef struct { -} cmd_listval_t; - -typedef struct { /* The raw identifier as provided by the user. */ char *raw_identifier; @@ -86,7 +83,6 @@ typedef struct { union { cmd_flush_t flush; cmd_getval_t getval; - cmd_listval_t listval; cmd_putval_t putval; } cmd; } cmd_t; diff --git a/src/utils_cmds_test.c b/src/utils_cmds_test.c index bb35ce8c..93bf5129 100644 --- a/src/utils_cmds_test.c +++ b/src/utils_cmds_test.c @@ -191,7 +191,7 @@ DEF_TEST(parse) { cmd_status_t status; cmd_t cmd; - _Bool result; + bool result; memset(&cmd, 0, sizeof(cmd)); diff --git a/src/utils_config_cores.c b/src/utils_config_cores.c new file mode 100644 index 00000000..94657459 --- /dev/null +++ b/src/utils_config_cores.c @@ -0,0 +1,372 @@ +/** + * collectd - src/utils_config_cores.c + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * 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: + * Kamil Wiatrowski + **/ + +#include "collectd.h" + +#include "common.h" + +#include "utils_config_cores.h" + +#define UTIL_NAME "utils_config_cores" + +#define MAX_SOCKETS 8 +#define MAX_SOCKET_CORES 64 +#define MAX_CORES (MAX_SOCKET_CORES * MAX_SOCKETS) + +static inline _Bool is_in_list(unsigned val, const unsigned *list, size_t len) { + for (size_t i = 0; i < len; i++) + if (list[i] == val) + return 1; + return 0; +} + +static int str_to_uint(const char *s, unsigned *n) { + if (s == NULL || n == NULL) + return -EINVAL; + char *endptr = NULL; + + *n = (unsigned)strtoul(s, &endptr, 0); + if (*s == '\0' || *endptr != '\0') { + ERROR(UTIL_NAME ": Failed to parse '%s' into unsigned number", s); + return -EINVAL; + } + + return 0; +} + +/* + * NAME + * str_list_to_nums + * + * DESCRIPTION + * Converts string of characters representing list of numbers into array of + * numbers. Allowed formats are: + * 0,1,2,3 + * 0-10,20-18 + * 1,3,5-8,10,0x10-12 + * + * Numbers can be in decimal or hexadecimal format. + * + * PARAMETERS + * `s' String representing list of unsigned numbers. + * `nums' Array to put converted numeric values into. + * `nums_len' Maximum number of elements that nums can accommodate. + * + * RETURN VALUE + * Number of elements placed into nums. + */ +static size_t str_list_to_nums(char *s, unsigned *nums, size_t nums_len) { + char *saveptr = NULL; + char *token; + size_t idx = 0; + + while ((token = strtok_r(s, ",", &saveptr))) { + char *pos; + unsigned start, end = 0; + s = NULL; + + while (isspace(*token)) + token++; + if (*token == '\0') + continue; + + pos = strchr(token, '-'); + if (pos) { + *pos = '\0'; + } + + if (str_to_uint(token, &start)) + return 0; + + if (pos) { + if (str_to_uint(pos + 1, &end)) + return 0; + } else { + end = start; + } + + if (start > end) { + unsigned swap = start; + start = end; + end = swap; + } + + for (unsigned i = start; i <= end; i++) { + if (is_in_list(i, nums, idx)) + continue; + if (idx >= nums_len) { + WARNING(UTIL_NAME ": exceeded the cores number limit: %" PRIsz, + nums_len); + return idx; + } + nums[idx] = i; + idx++; + } + } + return idx; +} + +/* + * NAME + * check_core_grouping + * + * DESCRIPTION + * Look for [...] brackets in *in string and if found copy the + * part between brackets into *out string and set grouped to 0. + * Otherwise grouped is set to 1 and input is copied without leading + * whitespaces. + * + * PARAMETERS + * `out' Output string to store result. + * `in' Input string to be parsed and copied. + * `out_size' Maximum number of elements that out can accommodate. + * `grouped' Set by function depending if cores should be grouped or not. + * + * RETURN VALUE + * Zero upon success or non-zero if an error occurred. + */ +static int check_core_grouping(char *out, const char *in, size_t out_size, + _Bool *grouped) { + const char *start = in; + char *end; + while (isspace(*start)) + ++start; + if (start[0] == '[') { + *grouped = 0; + ++start; + end = strchr(start, ']'); + if (end == NULL) { + ERROR(UTIL_NAME ": Missing closing bracket ] in option %s.", in); + return -EINVAL; + } + if ((size_t)(end - start) >= out_size) { + ERROR(UTIL_NAME ": Out buffer is too small."); + return -EINVAL; + } + sstrncpy(out, start, end - start + 1); + DEBUG(UTIL_NAME ": Mask for individual (not aggregated) cores: %s", out); + } else { + *grouped = 1; + sstrncpy(out, start, out_size); + } + return 0; +} + +int config_cores_parse(const oconfig_item_t *ci, core_groups_list_t *cgl) { + if (ci == NULL || cgl == NULL) + return -EINVAL; + if (ci->values_num == 0 || ci->values_num > MAX_CORES) + return -EINVAL; + core_group_t cgroups[MAX_CORES] = {{0}}; + size_t cg_idx = 0; /* index for cgroups array */ + int ret = 0; + + for (int i = 0; i < ci->values_num; i++) { + if (ci->values[i].type != OCONFIG_TYPE_STRING) { + WARNING(UTIL_NAME ": The %s option requires string arguments.", ci->key); + return -EINVAL; + } + } + + if (ci->values_num == 1 && ci->values[0].value.string && + strlen(ci->values[0].value.string) == 0) + return 0; + + for (int i = 0; i < ci->values_num; i++) { + size_t n; + _Bool grouped = 1; + char str[DATA_MAX_NAME_LEN]; + unsigned cores[MAX_CORES] = {0}; + + if (cg_idx >= STATIC_ARRAY_SIZE(cgroups)) { + ERROR(UTIL_NAME + ": Configuration exceeds maximum number of cores: %" PRIsz, + STATIC_ARRAY_SIZE(cgroups)); + ret = -EINVAL; + goto parse_error; + } + if ((ci->values[i].value.string == NULL) || + (strlen(ci->values[i].value.string) == 0)) { + ERROR(UTIL_NAME ": Failed to parse parameters for %s option.", ci->key); + ret = -EINVAL; + goto parse_error; + } + + ret = check_core_grouping(str, ci->values[i].value.string, sizeof(str), + &grouped); + if (ret != 0) { + ERROR(UTIL_NAME ": Failed to parse config option [%d] %s.", i, + ci->values[i].value.string); + goto parse_error; + } + n = str_list_to_nums(str, cores, STATIC_ARRAY_SIZE(cores)); + if (n == 0) { + ERROR(UTIL_NAME ": Failed to parse config option [%d] %s.", i, + ci->values[i].value.string); + ret = -EINVAL; + goto parse_error; + } + + if (grouped) { + cgroups[cg_idx].desc = strdup(ci->values[i].value.string); + if (cgroups[cg_idx].desc == NULL) { + ERROR(UTIL_NAME ": Failed to allocate description."); + ret = -ENOMEM; + goto parse_error; + } + + cgroups[cg_idx].cores = calloc(n, sizeof(*cgroups[cg_idx].cores)); + if (cgroups[cg_idx].cores == NULL) { + ERROR(UTIL_NAME ": Failed to allocate cores for cgroup."); + ret = -ENOMEM; + goto parse_error; + } + + for (size_t j = 0; j < n; j++) + cgroups[cg_idx].cores[j] = cores[j]; + + cgroups[cg_idx].num_cores = n; + cg_idx++; + } else { + for (size_t j = 0; j < n && cg_idx < STATIC_ARRAY_SIZE(cgroups); j++) { + char desc[DATA_MAX_NAME_LEN]; + snprintf(desc, sizeof(desc), "%u", cores[j]); + + cgroups[cg_idx].desc = strdup(desc); + if (cgroups[cg_idx].desc == NULL) { + ERROR(UTIL_NAME ": Failed to allocate desc for core %u.", cores[j]); + ret = -ENOMEM; + goto parse_error; + } + + cgroups[cg_idx].cores = calloc(1, sizeof(*(cgroups[cg_idx].cores))); + if (cgroups[cg_idx].cores == NULL) { + ERROR(UTIL_NAME ": Failed to allocate cgroup for core %u.", cores[j]); + ret = -ENOMEM; + goto parse_error; + } + cgroups[cg_idx].num_cores = 1; + cgroups[cg_idx].cores[0] = cores[j]; + cg_idx++; + } + } + } + + cgl->cgroups = calloc(cg_idx, sizeof(*cgl->cgroups)); + if (cgl->cgroups == NULL) { + ERROR(UTIL_NAME ": Failed to allocate core groups."); + ret = -ENOMEM; + goto parse_error; + } + + cgl->num_cgroups = cg_idx; + for (size_t i = 0; i < cg_idx; i++) + cgl->cgroups[i] = cgroups[i]; + + return 0; + +parse_error: + + cg_idx = 0; + while (cg_idx < STATIC_ARRAY_SIZE(cgroups) && cgroups[cg_idx].desc != NULL) { + sfree(cgroups[cg_idx].desc); + sfree(cgroups[cg_idx].cores); + cg_idx++; + } + return ret; +} + +int config_cores_default(int num_cores, core_groups_list_t *cgl) { + if (cgl == NULL || num_cores < 0 || num_cores > MAX_CORES) + return -EINVAL; + + cgl->cgroups = calloc(num_cores, sizeof(*(cgl->cgroups))); + if (cgl->cgroups == NULL) { + ERROR(UTIL_NAME ": Failed to allocate memory for core groups."); + return -ENOMEM; + } + cgl->num_cgroups = num_cores; + + for (int i = 0; i < num_cores; i++) { + char desc[DATA_MAX_NAME_LEN]; + snprintf(desc, sizeof(desc), "%d", i); + + cgl->cgroups[i].cores = calloc(1, sizeof(*(cgl->cgroups[i].cores))); + if (cgl->cgroups[i].cores == NULL) { + ERROR(UTIL_NAME ": Failed to allocate default cores for cgroup %d.", i); + config_cores_cleanup(cgl); + return -ENOMEM; + } + cgl->cgroups[i].num_cores = 1; + cgl->cgroups[i].cores[0] = i; + + cgl->cgroups[i].desc = strdup(desc); + if (cgl->cgroups[i].desc == NULL) { + ERROR(UTIL_NAME ": Failed to allocate description for cgroup %d.", i); + config_cores_cleanup(cgl); + return -ENOMEM; + } + } + return 0; +} + +void config_cores_cleanup(core_groups_list_t *cgl) { + if (cgl == NULL) + return; + for (size_t i = 0; i < cgl->num_cgroups; i++) { + sfree(cgl->cgroups[i].desc); + sfree(cgl->cgroups[i].cores); + } + sfree(cgl->cgroups); + cgl->num_cgroups = 0; +} + +int config_cores_cmp_cgroups(const core_group_t *cg_a, + const core_group_t *cg_b) { + size_t found = 0; + + assert(cg_a != NULL); + assert(cg_b != NULL); + + const size_t sz_a = cg_a->num_cores; + const size_t sz_b = cg_b->num_cores; + const unsigned *tab_a = cg_a->cores; + const unsigned *tab_b = cg_b->cores; + + for (size_t i = 0; i < sz_a; i++) + if (is_in_list(tab_a[i], tab_b, sz_b)) + found++; + + /* if no cores are the same */ + if (!found) + return 0; + /* if group contains same cores */ + if (sz_a == sz_b && sz_b == found) + return 1; + /* if not all cores are the same */ + return -1; +} diff --git a/src/utils_config_cores.h b/src/utils_config_cores.h new file mode 100644 index 00000000..d45f8480 --- /dev/null +++ b/src/utils_config_cores.h @@ -0,0 +1,136 @@ +/** + * collectd - src/utils_config_cores.h + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * 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: + * Kamil Wiatrowski + **/ + +#ifndef UTILS_CONFIG_CORES_H +#define UTILS_CONFIG_CORES_H 1 + +#include "configfile.h" + +#ifndef PRIsz +#define PRIsz "zu" +#endif /* PRIsz */ + +struct core_group_s { + char *desc; + unsigned int *cores; + size_t num_cores; +}; +typedef struct core_group_s core_group_t; + +struct core_groups_list_s { + core_group_t *cgroups; + size_t num_cgroups; +}; +typedef struct core_groups_list_s core_groups_list_t; + +/* + * NAME + * config_cores_parse + * + * DESCRIPTION + * Convert strings from config item into list of core groups. + * + * PARAMETERS + * `ci' Pointer to config item. + * `cgl' Pointer to core groups list to be filled. + * + * RETURN VALUE + * Zero upon success or non-zero if an error occurred. + * + * NOTES + * In case of an error, *cgl is not modified. + * Numbers can be in decimal or hexadecimal format. + * The memory allocated for *cgroups in list needs to be freed + * with config_cores_cleanup. + * + * EXAMPLES + * If config is "0-3" "[4-15]" it means that cores 0-3 are aggregated + * into one group and cores 4 to 15 are stored individualily in + * separate groups. Examples of allowed formats: + * "0,3,4" "10-15" - cores collected into two groups + * "0" "0x3" "7" - 3 cores, each in individual group + * "[32-63]" - 32 cores, each in individual group + * + * For empty string "" *cgl is not modified and zero is returned. + */ +int config_cores_parse(const oconfig_item_t *ci, core_groups_list_t *cgl); + +/* + * NAME + * config_cores_default + * + * DESCRIPTION + * Set number of cores starting from zero into individual + * core groups in *cgl list. + * + * PARAMETERS + * `num_cores' Number of cores to be configured. + * `cgl' Pointer to core groups list. + * + * RETURN VALUE + * Zero upon success or non-zero if an error occurred. + * + * NOTES + * The memory allocated for *cgroups in list needs to be freed + * with config_cores_cleanup. In case of error the memory is + * freed by the function itself. + */ +int config_cores_default(int num_cores, core_groups_list_t *cgl); + +/* + * NAME + * config_cores_cleanup + * + * DESCRIPTION + * Free the memory allocated for cgroups and set + * num_cgroups to zero. + * + * PARAMETERS + * `cgl' Pointer to core groups list. + */ +void config_cores_cleanup(core_groups_list_t *cgl); + +/* + * NAME + * config_cores_cmp_cgroups + * + * DESCRIPTION + * Function to compare cores in 2 core groups. + * + * PARAMETERS + * `cg_a' Pointer to core group a. + * `cg_b' Pointer to core group b. + * + * RETURN VALUE + * 1 if both groups contain the same cores + * 0 if none of their cores match + * -1 if some but not all cores match + */ +int config_cores_cmp_cgroups(const core_group_t *cg_a, + const core_group_t *cg_b); + +#endif /* UTILS_CONFIG_CORES_H */ diff --git a/src/utils_config_cores_test.c b/src/utils_config_cores_test.c new file mode 100644 index 00000000..2c6f5b60 --- /dev/null +++ b/src/utils_config_cores_test.c @@ -0,0 +1,249 @@ +/** + * collectd - src/utils_config_cores_test.c + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * 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: + * Kamil Wiatrowski + **/ + +#include "collectd.h" + +#include "testing.h" +#include "utils_config_cores.c" /* sic */ + +oconfig_value_t test_cfg_values[] = {{{"0"}, OCONFIG_TYPE_STRING}, + {{"1-2"}, OCONFIG_TYPE_STRING}, + {{"[3-4]"}, OCONFIG_TYPE_STRING}}; + +oconfig_item_t test_cfg = { + "Cores", test_cfg_values, STATIC_ARRAY_SIZE(test_cfg_values), NULL, NULL, + 0}; + +static int compare_with_test_config(core_groups_list_t *cgl) { + if (cgl->num_cgroups == 4 && cgl->cgroups[0].num_cores == 1 && + strcmp("0", cgl->cgroups[0].desc) == 0 && cgl->cgroups[0].cores[0] == 0 && + cgl->cgroups[1].num_cores == 2 && + strcmp("1-2", cgl->cgroups[1].desc) == 0 && + cgl->cgroups[1].cores[0] == 1 && cgl->cgroups[1].cores[1] == 2 && + cgl->cgroups[2].num_cores == 1 && + strcmp("3", cgl->cgroups[2].desc) == 0 && cgl->cgroups[2].cores[0] == 3 && + cgl->cgroups[3].num_cores == 1 && + strcmp("4", cgl->cgroups[3].desc) == 0 && cgl->cgroups[3].cores[0] == 4) + return 0; + + return -1; +} + +DEF_TEST(string_to_uint) { + int ret = 0; + char *s = "13", *s1 = "0xd", *s2 = "g"; + unsigned n = 0; + + ret = str_to_uint(s, &n); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(13, n); + + ret = str_to_uint(s1, &n); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(13, n); + + ret = str_to_uint(s2, &n); + OK(ret < 0); + + ret = str_to_uint(NULL, &n); + OK(ret < 0); + return 0; +} + +DEF_TEST(cores_list_to_numbers) { + size_t n = 0; + unsigned nums[MAX_CORES]; + char str[64] = ""; + + n = str_list_to_nums(str, nums, STATIC_ARRAY_SIZE(nums)); + EXPECT_EQ_INT(0, n); + + strncpy(str, "1", STATIC_ARRAY_SIZE(str)); + n = str_list_to_nums(str, nums, STATIC_ARRAY_SIZE(nums)); + EXPECT_EQ_INT(1, n); + EXPECT_EQ_INT(1, nums[0]); + + strncpy(str, "0,2-3", STATIC_ARRAY_SIZE(str)); + n = str_list_to_nums(str, nums, STATIC_ARRAY_SIZE(nums)); + EXPECT_EQ_INT(3, n); + EXPECT_EQ_INT(0, nums[0]); + EXPECT_EQ_INT(2, nums[1]); + EXPECT_EQ_INT(3, nums[2]); + + strncpy(str, "11-0xa", STATIC_ARRAY_SIZE(str)); + n = str_list_to_nums(str, nums, STATIC_ARRAY_SIZE(nums)); + EXPECT_EQ_INT(2, n); + EXPECT_EQ_INT(10, nums[0]); + EXPECT_EQ_INT(11, nums[1]); + + snprintf(str, sizeof(str), "0-%d", (MAX_CORES - 1)); + n = str_list_to_nums(str, nums, STATIC_ARRAY_SIZE(nums)); + EXPECT_EQ_INT(MAX_CORES, n); + EXPECT_EQ_INT(0, nums[0]); + EXPECT_EQ_INT(MAX_CORES - 1, nums[MAX_CORES - 1]); + + /* Should return 0 for incorrect syntax. */ + strncpy(str, "5g", STATIC_ARRAY_SIZE(str)); + n = str_list_to_nums(str, nums, STATIC_ARRAY_SIZE(nums)); + EXPECT_EQ_INT(0, n); + return 0; +} + +DEF_TEST(check_grouped_cores) { + int ret = 0; + _Bool grouped; + char src[64] = "[5-15]"; + char dest[64]; + + ret = check_core_grouping(dest, src, sizeof(dest), &grouped); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(0, grouped); + EXPECT_EQ_STR("5-15", dest); + + strncpy(src, " 5-15", STATIC_ARRAY_SIZE(src)); + ret = check_core_grouping(dest, src, sizeof(dest), &grouped); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(1, grouped); + EXPECT_EQ_STR("5-15", dest); + return 0; +} + +DEF_TEST(cores_option_parse) { + int ret = 0; + core_groups_list_t cgl = {0}; + + ret = config_cores_parse(&test_cfg, &cgl); + EXPECT_EQ_INT(0, ret); + CHECK_NOT_NULL(cgl.cgroups); + EXPECT_EQ_INT(0, compare_with_test_config(&cgl)); + + config_cores_cleanup(&cgl); + return 0; +} + +DEF_TEST(cores_option_parse_fail) { + int ret = 0; + core_groups_list_t cgl = {0}; + /* Wrong value, missing closing bracket ] */ + oconfig_value_t values = {{"[0-15"}, OCONFIG_TYPE_STRING}; + oconfig_item_t cfg = {"Cores", &values, 1, NULL, NULL, 0}; + + ret = config_cores_parse(&cfg, &cgl); + EXPECT_EQ_INT(-EINVAL, ret); + EXPECT_EQ_INT(0, cgl.num_cgroups); + OK(NULL == cgl.cgroups); + return 0; +} + +DEF_TEST(cores_default_list) { + int ret = 0; + core_groups_list_t cgl = {0}; + + ret = config_cores_default(2, &cgl); + EXPECT_EQ_INT(0, ret); + EXPECT_EQ_INT(2, cgl.num_cgroups); + CHECK_NOT_NULL(cgl.cgroups); + + CHECK_NOT_NULL(cgl.cgroups[0].cores); + CHECK_NOT_NULL(cgl.cgroups[0].desc); + EXPECT_EQ_STR("0", cgl.cgroups[0].desc); + EXPECT_EQ_INT(1, cgl.cgroups[0].num_cores); + EXPECT_EQ_INT(0, cgl.cgroups[0].cores[0]); + + CHECK_NOT_NULL(cgl.cgroups[1].cores); + CHECK_NOT_NULL(cgl.cgroups[1].desc); + EXPECT_EQ_STR("1", cgl.cgroups[1].desc); + EXPECT_EQ_INT(1, cgl.cgroups[1].num_cores); + EXPECT_EQ_INT(1, cgl.cgroups[1].cores[0]); + + config_cores_cleanup(&cgl); + return 0; +} + +DEF_TEST(cores_default_list_fail) { + int ret = 0; + core_groups_list_t cgl = {0}; + + ret = config_cores_default(-1, &cgl); + OK(ret < 0); + ret = config_cores_default(MAX_CORES + 1, &cgl); + OK(ret < 0); + ret = config_cores_default(1, NULL); + OK(ret < 0); + return 0; +} + +DEF_TEST(cores_group_cleanup) { + core_groups_list_t cgl; + cgl.cgroups = calloc(1, sizeof(*cgl.cgroups)); + CHECK_NOT_NULL(cgl.cgroups); + cgl.num_cgroups = 1; + cgl.cgroups[0].desc = strdup("1"); + cgl.cgroups[0].cores = calloc(1, sizeof(*cgl.cgroups[0].cores)); + CHECK_NOT_NULL(cgl.cgroups[0].cores); + cgl.cgroups[0].cores[0] = 1; + cgl.cgroups[0].num_cores = 1; + + config_cores_cleanup(&cgl); + OK(NULL == cgl.cgroups); + EXPECT_EQ_INT(0, cgl.num_cgroups); + return 0; +} + +DEF_TEST(cores_group_cmp) { + unsigned cores_mock[] = {0, 1, 2}; + core_group_t group_mock = {"0,1,2", cores_mock, 3}; + unsigned cores_mock_2[] = {2, 3}; + core_group_t group_mock_2 = {"2,3", cores_mock_2, 2}; + + int ret = config_cores_cmp_cgroups(&group_mock, &group_mock); + EXPECT_EQ_INT(1, ret); + + ret = config_cores_cmp_cgroups(&group_mock, &group_mock_2); + EXPECT_EQ_INT(-1, ret); + + cores_mock_2[0] = 4; + ret = config_cores_cmp_cgroups(&group_mock, &group_mock_2); + EXPECT_EQ_INT(0, ret); + return 0; +} + +int main(void) { + RUN_TEST(string_to_uint); + RUN_TEST(cores_list_to_numbers); + RUN_TEST(check_grouped_cores); + + RUN_TEST(cores_group_cleanup); + RUN_TEST(cores_option_parse); + RUN_TEST(cores_option_parse_fail); + RUN_TEST(cores_default_list); + RUN_TEST(cores_default_list_fail); + + RUN_TEST(cores_group_cmp); + + END_TEST; +} diff --git a/src/utils_curl_stats.c b/src/utils_curl_stats.c index 2a1d9de3..09856599 100644 --- a/src/utils_curl_stats.c +++ b/src/utils_curl_stats.c @@ -182,7 +182,7 @@ curl_stats_t *curl_stats_from_config(oconfig_item_t *ci) { oconfig_item_t *c = ci->children + i; size_t field; - _Bool enabled = 0; + bool enabled = 0; for (field = 0; field < STATIC_ARRAY_SIZE(field_specs); ++field) { if (!strcasecmp(c->key, field_specs[field].config_key)) diff --git a/src/utils_db_query.c b/src/utils_db_query.c index a58bc065..54ddb046 100644 --- a/src/utils_db_query.c +++ b/src/utils_db_query.c @@ -92,47 +92,23 @@ struct udb_query_preparation_area_s /* {{{ */ /* * Config Private functions */ -static int udb_config_set_string(char **ret_string, /* {{{ */ - oconfig_item_t *ci) { - char *string; - - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - WARNING("db query utils: The `%s' config option " - "needs exactly one string argument.", - ci->key); - return -1; - } - - string = strdup(ci->values[0].value.string); - if (string == NULL) { - ERROR("db query utils: strdup failed."); - return -1; - } - - if (*ret_string != NULL) - free(*ret_string); - *ret_string = string; - - return 0; -} /* }}} int udb_config_set_string */ - static int udb_config_add_string(char ***ret_array, /* {{{ */ size_t *ret_array_len, oconfig_item_t *ci) { char **array; size_t array_len; if (ci->values_num < 1) { - WARNING("db query utils: The `%s' config option " - "needs at least one argument.", - ci->key); + P_WARNING("The `%s' config option " + "needs at least one argument.", + ci->key); return -1; } for (int i = 0; i < ci->values_num; i++) { if (ci->values[i].type != OCONFIG_TYPE_STRING) { - WARNING("db query utils: Argument %i to the `%s' option " - "is not a string.", - i + 1, ci->key); + P_WARNING("Argument %i to the `%s' option " + "is not a string.", + i + 1, ci->key); return -1; } } @@ -140,7 +116,7 @@ static int udb_config_add_string(char ***ret_array, /* {{{ */ array_len = *ret_array_len; array = realloc(*ret_array, sizeof(char *) * (array_len + ci->values_num)); if (array == NULL) { - ERROR("db query utils: realloc failed."); + P_ERROR("udb_config_add_string: realloc failed."); return -1; } *ret_array = array; @@ -148,7 +124,7 @@ static int udb_config_add_string(char ***ret_array, /* {{{ */ for (int i = 0; i < ci->values_num; i++) { array[array_len] = strdup(ci->values[i].value.string); if (array[array_len] == NULL) { - ERROR("db query utils: strdup failed."); + P_ERROR("udb_config_add_string: strdup failed."); *ret_array_len = array_len; return -1; } @@ -161,18 +137,19 @@ static int udb_config_add_string(char ***ret_array, /* {{{ */ static int udb_config_set_uint(unsigned int *ret_value, /* {{{ */ oconfig_item_t *ci) { - double tmp; if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) { - WARNING("db query utils: The `%s' config option " - "needs exactly one numeric argument.", - ci->key); + P_WARNING("The `%s' config option " + "needs exactly one numeric argument.", + ci->key); return -1; } - tmp = ci->values[0].value.number; - if ((tmp < 0.0) || (tmp > ((double)UINT_MAX))) + double tmp = ci->values[0].value.number; + if ((tmp < 0.0) || (tmp > ((double)UINT_MAX))) { + P_WARNING("The value given for the `%s` option is out of range.", ci->key); return -ERANGE; + } *ret_value = (unsigned int)(tmp + .5); return 0; @@ -194,7 +171,7 @@ static int udb_result_submit(udb_result_t *r, /* {{{ */ vl.values = calloc(r->values_num, sizeof(*vl.values)); if (vl.values == NULL) { - ERROR("db query utils: calloc failed."); + P_ERROR("udb_result_submit: calloc failed."); return -1; } vl.values_len = r_area->ds->ds_num; @@ -203,8 +180,8 @@ static int udb_result_submit(udb_result_t *r, /* {{{ */ char *value_str = r_area->values_buffer[i]; if (0 != parse_value(value_str, &vl.values[i], r_area->ds->ds[i].type)) { - ERROR("db query utils: udb_result_submit: Parsing `%s' as %s failed.", - value_str, DS_TYPE_TO_STRING(r_area->ds->ds[i].type)); + P_ERROR("udb_result_submit: Parsing `%s' as %s failed.", value_str, + DS_TYPE_TO_STRING(r_area->ds->ds[i].type)); errno = EINVAL; free(vl.values); return -1; @@ -238,7 +215,7 @@ static int udb_result_submit(udb_result_t *r, /* {{{ */ int status = strjoin(vl.type_instance, sizeof(vl.type_instance), r_area->instances_buffer, r->instances_num, "-"); if (status < 0) { - ERROR( + P_ERROR( "udb_result_submit: creating type_instance failed with status %d.", status); return status; @@ -249,7 +226,7 @@ static int udb_result_submit(udb_result_t *r, /* {{{ */ int status = strjoin(tmp, sizeof(tmp), r_area->instances_buffer, r->instances_num, "-"); if (status < 0) { - ERROR( + P_ERROR( "udb_result_submit: creating type_instance failed with status %d.", status); return status; @@ -267,7 +244,8 @@ static int udb_result_submit(udb_result_t *r, /* {{{ */ if (r->metadata_num > 0) { vl.meta = meta_data_create(); if (vl.meta == NULL) { - ERROR("db query utils:: meta_data_create failed."); + P_ERROR("udb_result_submit: meta_data_create failed."); + free(vl.values); return -ENOMEM; } @@ -275,9 +253,10 @@ static int udb_result_submit(udb_result_t *r, /* {{{ */ int status = meta_data_add_string(vl.meta, r->metadata[i], r_area->metadata_buffer[i]); if (status != 0) { - ERROR("db query utils:: meta_data_add_string failed."); + P_ERROR("udb_result_submit: meta_data_add_string failed."); meta_data_destroy(vl.meta); vl.meta = NULL; + free(vl.values); return status; } } @@ -336,37 +315,35 @@ static int udb_result_prepare_result(udb_result_t const *r, /* {{{ */ if ((r == NULL) || (prep_area == NULL)) return -EINVAL; +#if COLLECT_DEBUG + assert(prep_area->ds == NULL); + assert(prep_area->instances_pos == NULL); + assert(prep_area->values_pos == NULL); + assert(prep_area->metadata_pos == NULL); + assert(prep_area->instances_buffer == NULL); + assert(prep_area->values_buffer == NULL); + assert(prep_area->metadata_buffer == NULL); +#endif + #define BAIL_OUT(status) \ - prep_area->ds = NULL; \ - sfree(prep_area->instances_pos); \ - sfree(prep_area->values_pos); \ - sfree(prep_area->metadata_pos); \ - sfree(prep_area->instances_buffer); \ - sfree(prep_area->values_buffer); \ - sfree(prep_area->metadata_buffer); \ + udb_result_finish_result(r, prep_area); \ return (status) - /* Make sure previous preparations are cleaned up. */ - udb_result_finish_result(r, prep_area); - prep_area->instances_pos = NULL; - prep_area->values_pos = NULL; - prep_area->metadata_pos = NULL; - /* Read `ds' and check number of values {{{ */ prep_area->ds = plugin_get_ds(r->type); if (prep_area->ds == NULL) { - ERROR("db query utils: udb_result_prepare_result: Type `%s' is not " - "known by the daemon. See types.db(5) for details.", - r->type); + P_ERROR("udb_result_prepare_result: Type `%s' is not " + "known by the daemon. See types.db(5) for details.", + r->type); BAIL_OUT(-1); } if (prep_area->ds->ds_num != r->values_num) { - ERROR("db query utils: udb_result_prepare_result: The type `%s' " - "requires exactly %" PRIsz - " value%s, but the configuration specifies %" PRIsz ".", - r->type, prep_area->ds->ds_num, - (prep_area->ds->ds_num == 1) ? "" : "s", r->values_num); + P_ERROR("udb_result_prepare_result: The type `%s' " + "requires exactly %" PRIsz + " value%s, but the configuration specifies %" PRIsz ".", + r->type, prep_area->ds->ds_num, + (prep_area->ds->ds_num == 1) ? "" : "s", r->values_num); BAIL_OUT(-1); } /* }}} */ @@ -377,39 +354,39 @@ static int udb_result_prepare_result(udb_result_t const *r, /* {{{ */ prep_area->instances_pos = (size_t *)calloc(r->instances_num, sizeof(size_t)); if (prep_area->instances_pos == NULL) { - ERROR("db query utils: udb_result_prepare_result: calloc failed."); + P_ERROR("udb_result_prepare_result: calloc failed."); BAIL_OUT(-ENOMEM); } prep_area->instances_buffer = (char **)calloc(r->instances_num, sizeof(char *)); if (prep_area->instances_buffer == NULL) { - ERROR("db query utils: udb_result_prepare_result: calloc failed."); + P_ERROR("udb_result_prepare_result: calloc failed."); BAIL_OUT(-ENOMEM); } } /* if (r->instances_num > 0) */ prep_area->values_pos = (size_t *)calloc(r->values_num, sizeof(size_t)); if (prep_area->values_pos == NULL) { - ERROR("db query utils: udb_result_prepare_result: calloc failed."); + P_ERROR("udb_result_prepare_result: calloc failed."); BAIL_OUT(-ENOMEM); } prep_area->values_buffer = (char **)calloc(r->values_num, sizeof(char *)); if (prep_area->values_buffer == NULL) { - ERROR("db query utils: udb_result_prepare_result: calloc failed."); + P_ERROR("udb_result_prepare_result: calloc failed."); BAIL_OUT(-ENOMEM); } prep_area->metadata_pos = (size_t *)calloc(r->metadata_num, sizeof(size_t)); if (prep_area->metadata_pos == NULL) { - ERROR("db query utils: udb_result_prepare_result: calloc failed."); + P_ERROR("udb_result_prepare_result: calloc failed."); BAIL_OUT(-ENOMEM); } prep_area->metadata_buffer = (char **)calloc(r->metadata_num, sizeof(char *)); if (prep_area->metadata_buffer == NULL) { - ERROR("db query utils: udb_result_prepare_result: calloc failed."); + P_ERROR("udb_result_prepare_result: calloc failed."); BAIL_OUT(-ENOMEM); } @@ -427,9 +404,9 @@ static int udb_result_prepare_result(udb_result_t const *r, /* {{{ */ } if (j >= column_num) { - ERROR("db query utils: udb_result_prepare_result: " - "Column `%s' could not be found.", - r->instances[i]); + P_ERROR("udb_result_prepare_result: " + "Column `%s' could not be found.", + r->instances[i]); BAIL_OUT(-ENOENT); } } /* }}} for (i = 0; i < r->instances_num; i++) */ @@ -446,9 +423,9 @@ static int udb_result_prepare_result(udb_result_t const *r, /* {{{ */ } if (j >= column_num) { - ERROR("db query utils: udb_result_prepare_result: " - "Column `%s' could not be found.", - r->values[i]); + P_ERROR("udb_result_prepare_result: " + "Column `%s' could not be found.", + r->values[i]); BAIL_OUT(-ENOENT); } } /* }}} for (i = 0; i < r->values_num; i++) */ @@ -465,9 +442,9 @@ static int udb_result_prepare_result(udb_result_t const *r, /* {{{ */ } if (j >= column_num) { - ERROR("db query utils: udb_result_prepare_result: " - "Metadata column `%s' could not be found.", - r->values[i]); + P_ERROR("udb_result_prepare_result: " + "Metadata column `%s' could not be found.", + r->values[i]); BAIL_OUT(-ENOENT); } } /* }}} for (i = 0; i < r->metadata_num; i++) */ @@ -507,14 +484,14 @@ static int udb_result_create(const char *query_name, /* {{{ */ int status; if (ci->values_num != 0) { - WARNING("db query utils: The `Result' block doesn't accept " - "any arguments. Ignoring %i argument%s.", - ci->values_num, (ci->values_num == 1) ? "" : "s"); + P_WARNING("The `Result' block doesn't accept " + "any arguments. Ignoring %i argument%s.", + ci->values_num, (ci->values_num == 1) ? "" : "s"); } r = calloc(1, sizeof(*r)); if (r == NULL) { - ERROR("db query utils: calloc failed."); + P_ERROR("udb_result_create: calloc failed."); return -1; } r->type = NULL; @@ -530,9 +507,9 @@ static int udb_result_create(const char *query_name, /* {{{ */ oconfig_item_t *child = ci->children + i; if (strcasecmp("Type", child->key) == 0) - status = udb_config_set_string(&r->type, child); + status = cf_util_get_string(child, &r->type); else if (strcasecmp("InstancePrefix", child->key) == 0) - status = udb_config_set_string(&r->instance_prefix, child); + status = cf_util_get_string(child, &r->instance_prefix); else if (strcasecmp("InstancesFrom", child->key) == 0) status = udb_config_add_string(&r->instances, &r->instances_num, child); else if (strcasecmp("ValuesFrom", child->key) == 0) @@ -540,8 +517,8 @@ static int udb_result_create(const char *query_name, /* {{{ */ else if (strcasecmp("MetadataFrom", child->key) == 0) status = udb_config_add_string(&r->metadata, &r->metadata_num, child); else { - WARNING("db query utils: Query `%s': Option `%s' not allowed here.", - query_name, child->key); + P_WARNING("Query `%s': Option `%s' not allowed here.", query_name, + child->key); status = -1; } @@ -552,15 +529,15 @@ static int udb_result_create(const char *query_name, /* {{{ */ /* Check that all necessary options have been given. */ while (status == 0) { if (r->type == NULL) { - WARNING("db query utils: `Type' not given for " - "result in query `%s'", - query_name); + P_WARNING("udb_result_create: `Type' not given for " + "result in query `%s'", + query_name); status = -1; } if (r->values == NULL) { - WARNING("db query utils: `ValuesFrom' not given for " - "result in query `%s'", - query_name); + P_WARNING("udb_result_create: `ValuesFrom' not given for " + "result in query `%s'", + query_name); status = -1; } @@ -623,14 +600,14 @@ int udb_query_create(udb_query_t ***ret_query_list, /* {{{ */ query_list_len = *ret_query_list_len; if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - WARNING("db query utils: The `Query' block " - "needs exactly one string argument."); + P_WARNING("udb_result_create: The `Query' block " + "needs exactly one string argument."); return -1; } q = calloc(1, sizeof(*q)); if (q == NULL) { - ERROR("db query utils: calloc failed."); + P_ERROR("udb_query_create: calloc failed."); return -1; } q->min_version = 0; @@ -639,7 +616,7 @@ int udb_query_create(udb_query_t ***ret_query_list, /* {{{ */ q->results = NULL; q->plugin_instance_from = NULL; - status = udb_config_set_string(&q->name, ci); + status = cf_util_get_string(ci, &q->name); if (status != 0) { sfree(q); return status; @@ -650,7 +627,7 @@ int udb_query_create(udb_query_t ***ret_query_list, /* {{{ */ oconfig_item_t *child = ci->children + i; if (strcasecmp("Statement", child->key) == 0) - status = udb_config_set_string(&q->statement, child); + status = cf_util_get_string(child, &q->statement); else if (strcasecmp("Result", child->key) == 0) status = udb_result_create(q->name, &q->results, child); else if (strcasecmp("MinVersion", child->key) == 0) @@ -658,19 +635,19 @@ int udb_query_create(udb_query_t ***ret_query_list, /* {{{ */ else if (strcasecmp("MaxVersion", child->key) == 0) status = udb_config_set_uint(&q->max_version, child); else if (strcasecmp("PluginInstanceFrom", child->key) == 0) - status = udb_config_set_string(&q->plugin_instance_from, child); + status = cf_util_get_string(child, &q->plugin_instance_from); /* Call custom callbacks */ else if (cb != NULL) { status = (*cb)(q, child); if (status != 0) { - WARNING("db query utils: The configuration callback failed " - "to handle `%s'.", - child->key); + P_WARNING("The configuration callback failed " + "to handle `%s'.", + child->key); } } else { - WARNING("db query utils: Query `%s': Option `%s' not allowed here.", - q->name, child->key); + P_WARNING("Query `%s': Option `%s' not allowed here.", q->name, + child->key); status = -1; } @@ -681,12 +658,11 @@ int udb_query_create(udb_query_t ***ret_query_list, /* {{{ */ /* Check that all necessary options have been given. */ if (status == 0) { if (q->statement == NULL) { - WARNING("db query utils: Query `%s': No `Statement' given.", q->name); + P_WARNING("Query `%s': No `Statement' given.", q->name); status = -1; } if (q->results == NULL) { - WARNING("db query utils: Query `%s': No (valid) `Result' block given.", - q->name); + P_WARNING("Query `%s': No (valid) `Result' block given.", q->name); status = -1; } } /* if (status == 0) */ @@ -698,7 +674,7 @@ int udb_query_create(udb_query_t ***ret_query_list, /* {{{ */ temp = realloc(query_list, sizeof(*query_list) * (query_list_len + 1)); if (temp == NULL) { - ERROR("db query utils: realloc failed"); + P_ERROR("udb_query_create: realloc failed"); status = -1; } else { query_list = temp; @@ -738,8 +714,8 @@ int udb_query_pick_from_list_by_name(const char *name, /* {{{ */ if ((name == NULL) || (src_list == NULL) || (dst_list == NULL) || (dst_list_len == NULL)) { - ERROR("db query utils: udb_query_pick_from_list_by_name: " - "Invalid argument."); + P_ERROR("udb_query_pick_from_list_by_name: " + "Invalid argument."); return -EINVAL; } @@ -754,7 +730,7 @@ int udb_query_pick_from_list_by_name(const char *name, /* {{{ */ tmp_list_len = *dst_list_len; tmp_list = realloc(*dst_list, (tmp_list_len + 1) * sizeof(udb_query_t *)); if (tmp_list == NULL) { - ERROR("db query utils: realloc failed."); + P_ERROR("udb_query_pick_from_list_by_name: realloc failed."); return -ENOMEM; } @@ -768,12 +744,12 @@ int udb_query_pick_from_list_by_name(const char *name, /* {{{ */ } /* for (i = 0; i < src_list_len; i++) */ if (num_added <= 0) { - ERROR("db query utils: Cannot find query `%s'. Make sure the " - "block is above the database definition!", - name); + P_ERROR("Cannot find query `%s'. Make sure the " + "block is above the database definition!", + name); return -ENOENT; } else { - DEBUG("db query utils: Added %i versions of query `%s'.", num_added, name); + DEBUG("Added %i versions of query `%s'.", num_added, name); } return 0; @@ -786,15 +762,15 @@ int udb_query_pick_from_list(oconfig_item_t *ci, /* {{{ */ if ((ci == NULL) || (src_list == NULL) || (dst_list == NULL) || (dst_list_len == NULL)) { - ERROR("db query utils: udb_query_pick_from_list: " - "Invalid argument."); + P_ERROR("udb_query_pick_from_list: " + "Invalid argument."); return -EINVAL; } if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - ERROR("db query utils: The `%s' config option " - "needs exactly one string argument.", - ci->key); + P_ERROR("The `%s' config option " + "needs exactly one string argument.", + ci->key); return -1; } name = ci->values[0].value.string; @@ -883,16 +859,16 @@ int udb_query_handle_result(udb_query_t const *q, /* {{{ */ if ((prep_area->column_num < 1) || (prep_area->host == NULL) || (prep_area->plugin == NULL) || (prep_area->db_name == NULL)) { - ERROR("db query utils: Query `%s': Query is not prepared; " - "can't handle result.", - q->name); + P_ERROR("Query `%s': Query is not prepared; " + "can't handle result.", + q->name); return -EINVAL; } #if defined(COLLECT_DEBUG) && COLLECT_DEBUG /* {{{ */ do { for (size_t i = 0; i < prep_area->column_num; i++) { - DEBUG("db query utils: udb_query_handle_result (%s, %s): " + DEBUG("udb_query_handle_result (%s, %s): " "column[%" PRIsz "] = %s;", prep_area->db_name, q->name, i, column_values[i]); } @@ -908,9 +884,9 @@ int udb_query_handle_result(udb_query_t const *q, /* {{{ */ } if (success == 0) { - ERROR("db query utils: udb_query_handle_result (%s, %s): " - "All results failed.", - prep_area->db_name, q->name); + P_ERROR("udb_query_handle_result (%s, %s): " + "All results failed.", + prep_area->db_name, q->name); return -1; } @@ -929,7 +905,13 @@ int udb_query_prepare_result(udb_query_t const *q, /* {{{ */ if ((q == NULL) || (prep_area == NULL)) return -EINVAL; - udb_query_finish_result(q, prep_area); +#if COLLECT_DEBUG + assert(prep_area->column_num == 0); + assert(prep_area->host == NULL); + assert(prep_area->plugin == NULL); + assert(prep_area->db_name == NULL); + assert(prep_area->interval == 0); +#endif prep_area->column_num = column_num; prep_area->host = strdup(host); @@ -940,8 +922,7 @@ int udb_query_prepare_result(udb_query_t const *q, /* {{{ */ if ((prep_area->host == NULL) || (prep_area->plugin == NULL) || (prep_area->db_name == NULL)) { - ERROR("db query utils: Query `%s': Prepare failed: Out of memory.", - q->name); + P_ERROR("Query `%s': Prepare failed: Out of memory.", q->name); udb_query_finish_result(q, prep_area); return -ENOMEM; } @@ -949,7 +930,7 @@ int udb_query_prepare_result(udb_query_t const *q, /* {{{ */ #if defined(COLLECT_DEBUG) && COLLECT_DEBUG do { for (size_t i = 0; i < column_num; i++) { - DEBUG("db query utils: udb_query_prepare_result: " + DEBUG("udb_query_prepare_result: " "query = %s; column[%" PRIsz "] = %s;", q->name, i, column_names[i]); } @@ -968,9 +949,9 @@ int udb_query_prepare_result(udb_query_t const *q, /* {{{ */ } if (i >= column_num) { - ERROR("db query utils: udb_query_prepare_result: " - "Column `%s' from `PluginInstanceFrom' could not be found.", - q->plugin_instance_from); + P_ERROR("udb_query_prepare_result: " + "Column `%s' from `PluginInstanceFrom' could not be found.", + q->plugin_instance_from); udb_query_finish_result(q, prep_area); return -ENOENT; } @@ -980,9 +961,9 @@ int udb_query_prepare_result(udb_query_t const *q, /* {{{ */ for (r = q->results, r_area = prep_area->result_prep_areas; r != NULL; r = r->next, r_area = r_area->next) { if (!r_area) { - ERROR("db query utils: Query `%s': Invalid number of result " - "preparation areas.", - q->name); + P_ERROR("Query `%s': Invalid number of result " + "preparation areas.", + q->name); udb_query_finish_result(q, prep_area); return -EINVAL; } diff --git a/src/utils_deq.h b/src/utils_deq.h new file mode 100644 index 00000000..3182baae --- /dev/null +++ b/src/utils_deq.h @@ -0,0 +1,214 @@ +/** + * collectd - src/utils_deq.h + * Copyright(c) 2017 Red Hat Inc. + * + * 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: + * Andy Smith + */ + +#ifndef utils_deq_h +#define utils_deq_h 1 + +#include +#include +#include + +#define CT_ASSERT(exp) \ + { assert(exp); } + +#define NEW(t) (t *)malloc(sizeof(t)) +#define NEW_ARRAY(t, n) (t *)malloc(sizeof(t) * (n)) +#define NEW_PTR_ARRAY(t, n) (t **)malloc(sizeof(t *) * (n)) + +#define ZERO(p) memset(p, 0, sizeof(*p)) + +#define DEQ_DECLARE(i, d) \ + typedef struct { \ + i *head; \ + i *tail; \ + i *scratch; \ + size_t size; \ + } d + +#define DEQ_LINKS_N(n, t) \ + t *prev##n; \ + t *next##n +#define DEQ_LINKS(t) DEQ_LINKS_N(, t) +#define DEQ_EMPTY \ + { 0, 0, 0, 0 } + +#define DEQ_INIT(d) \ + do { \ + (d).head = 0; \ + (d).tail = 0; \ + (d).scratch = 0; \ + (d).size = 0; \ + } while (0) +#define DEQ_IS_EMPTY(d) ((d).head == 0) +#define DEQ_ITEM_INIT_N(n, i) \ + do { \ + (i)->next##n = 0; \ + (i)->prev##n = 0; \ + } while (0) +#define DEQ_ITEM_INIT(i) DEQ_ITEM_INIT_N(, i) +#define DEQ_HEAD(d) ((d).head) +#define DEQ_TAIL(d) ((d).tail) +#define DEQ_SIZE(d) ((d).size) +#define DEQ_NEXT_N(n, i) (i)->next##n +#define DEQ_NEXT(i) DEQ_NEXT_N(, i) +#define DEQ_PREV_N(n, i) (i)->prev##n +#define DEQ_PREV(i) DEQ_PREV_N(, i) +#define DEQ_MOVE(d1, d2) \ + do { \ + d2 = d1; \ + DEQ_INIT(d1); \ + } while (0) +/** + *@pre ptr points to first element of deq + *@post ptr points to first element of deq that passes test, or 0. Test should + *involve ptr. + */ +#define DEQ_FIND_N(n, ptr, test) \ + while ((ptr) && !(test)) \ + ptr = DEQ_NEXT_N(n, ptr); +#define DEQ_FIND(ptr, test) DEQ_FIND_N(, ptr, test) + +#define DEQ_INSERT_HEAD_N(n, d, i) \ + do { \ + CT_ASSERT((i)->next##n == 0); \ + CT_ASSERT((i)->prev##n == 0); \ + if ((d).head) { \ + (i)->next##n = (d).head; \ + (d).head->prev##n = i; \ + } else { \ + (d).tail = i; \ + (i)->next##n = 0; \ + CT_ASSERT((d).size == 0); \ + } \ + (i)->prev##n = 0; \ + (d).head = i; \ + (d).size++; \ + } while (0) +#define DEQ_INSERT_HEAD(d, i) DEQ_INSERT_HEAD_N(, d, i) + +#define DEQ_INSERT_TAIL_N(n, d, i) \ + do { \ + CT_ASSERT((i)->next##n == 0); \ + CT_ASSERT((i)->prev##n == 0); \ + if ((d).tail) { \ + (i)->prev##n = (d).tail; \ + (d).tail->next##n = i; \ + } else { \ + (d).head = i; \ + (i)->prev##n = 0; \ + CT_ASSERT((d).size == 0); \ + } \ + (i)->next##n = 0; \ + (d).tail = i; \ + (d).size++; \ + } while (0) +#define DEQ_INSERT_TAIL(d, i) DEQ_INSERT_TAIL_N(, d, i) + +#define DEQ_REMOVE_HEAD_N(n, d) \ + do { \ + CT_ASSERT((d).head); \ + if ((d).head) { \ + (d).scratch = (d).head; \ + (d).head = (d).head->next##n; \ + if ((d).head == 0) { \ + (d).tail = 0; \ + CT_ASSERT((d).size == 1); \ + } else \ + (d).head->prev##n = 0; \ + (d).size--; \ + (d).scratch->next##n = 0; \ + (d).scratch->prev##n = 0; \ + } \ + } while (0) +#define DEQ_REMOVE_HEAD(d) DEQ_REMOVE_HEAD_N(, d) + +#define DEQ_REMOVE_TAIL_N(n, d) \ + do { \ + CT_ASSERT((d).tail); \ + if ((d).tail) { \ + (d).scratch = (d).tail; \ + (d).tail = (d).tail->prev##n; \ + if ((d).tail == 0) { \ + (d).head = 0; \ + CT_ASSERT((d).size == 1); \ + } else \ + (d).tail->next##n = 0; \ + (d).size--; \ + (d).scratch->next##n = 0; \ + (d).scratch->prev##n = 0; \ + } \ + } while (0) +#define DEQ_REMOVE_TAIL(d) DEQ_REMOVE_TAIL_N(, d) + +#define DEQ_INSERT_AFTER_N(n, d, i, a) \ + do { \ + CT_ASSERT((i)->next##n == 0); \ + CT_ASSERT((i)->prev##n == 0); \ + CT_ASSERT(a); \ + if ((a)->next##n) \ + (a)->next##n->prev##n = (i); \ + else \ + (d).tail = (i); \ + (i)->next##n = (a)->next##n; \ + (i)->prev##n = (a); \ + (a)->next##n = (i); \ + (d).size++; \ + } while (0) +#define DEQ_INSERT_AFTER(d, i, a) DEQ_INSERT_AFTER_N(, d, i, a) + +#define DEQ_REMOVE_N(n, d, i) \ + do { \ + if ((i)->next##n) \ + (i)->next##n->prev##n = (i)->prev##n; \ + else \ + (d).tail = (i)->prev##n; \ + if ((i)->prev##n) \ + (i)->prev##n->next##n = (i)->next##n; \ + else \ + (d).head = (i)->next##n; \ + CT_ASSERT((d).size > 0); \ + (d).size--; \ + (i)->next##n = 0; \ + (i)->prev##n = 0; \ + CT_ASSERT((d).size || (!(d).head && !(d).tail)); \ + } while (0) +#define DEQ_REMOVE(d, i) DEQ_REMOVE_N(, d, i) + +#define DEQ_APPEND_N(n, d1, d2) \ + do { \ + if (!(d1).head) \ + (d1) = (d2); \ + else if ((d2).head) { \ + (d1).tail->next##n = (d2).head; \ + (d2).head->prev##n = (d1).tail; \ + (d1).tail = (d2).tail; \ + (d1).size += (d2).size; \ + } \ + DEQ_INIT(d2); \ + } while (0) +#define DEQ_APPEND(d1, d2) DEQ_APPEND_N(, d1, d2) + +#endif diff --git a/src/utils_dns.c b/src/utils_dns.c index e7e04f7c..7b20e139 100644 --- a/src/utils_dns.c +++ b/src/utils_dns.c @@ -158,16 +158,16 @@ typedef int(printer)(const char *, ...); */ #if HAVE_PCAP_H -static pcap_t *pcap_obj = NULL; +static pcap_t *pcap_obj; #endif -static ip_list_t *IgnoreList = NULL; +static ip_list_t *IgnoreList; #if HAVE_PCAP_H -static void (*Callback)(const rfc1035_header_t *) = NULL; +static void (*Callback)(const rfc1035_header_t *); -static int query_count_intvl = 0; -static int query_count_total = 0; +static int query_count_intvl; +static int query_count_total; #ifdef __OpenBSD__ static struct bpf_timeval last_ts; #else @@ -267,7 +267,7 @@ static int rfc1035NameUnpack(const char *buf, size_t sz, off_t *off, char *name, off_t no = 0; unsigned char c; size_t len; - static int loop_detect = 0; + static int loop_detect; if (loop_detect > 2) return 4; /* compression loop */ if (ns == 0) diff --git a/src/utils_dpdk.c b/src/utils_dpdk.c index adc55306..1d4668f3 100644 --- a/src/utils_dpdk.c +++ b/src/utils_dpdk.c @@ -852,7 +852,7 @@ uint128_t str_to_uint128(const char *str, int len) { return lcore_mask; } -uint8_t dpdk_helper_eth_dev_count() { +uint8_t dpdk_helper_eth_dev_count(void) { uint8_t ports = rte_eth_dev_count(); if (ports == 0) { ERROR( diff --git a/src/utils_dpdk.h b/src/utils_dpdk.h index f3b7e7f7..d4551d86 100644 --- a/src/utils_dpdk.h +++ b/src/utils_dpdk.h @@ -74,7 +74,7 @@ int dpdk_helper_command(dpdk_helper_ctx_t *phc, enum DPDK_CMD cmd, int *result, cdtime_t cmd_wait_time); void *dpdk_helper_priv_get(dpdk_helper_ctx_t *phc); int dpdk_helper_data_size_get(dpdk_helper_ctx_t *phc); -uint8_t dpdk_helper_eth_dev_count(); +uint8_t dpdk_helper_eth_dev_count(void); /* forward declaration of handler function that is called by helper from * child process. not implemented in helper. must be provided by client. */ diff --git a/src/utils_format_graphite.c b/src/utils_format_graphite.c index fbeff4f0..44700b54 100644 --- a/src/utils_format_graphite.c +++ b/src/utils_format_graphite.c @@ -66,8 +66,8 @@ static int gr_format_values(char *ret, size_t ret_len, int ds_num, else if (ds->ds[ds_num].type == DS_TYPE_ABSOLUTE) BUFFER_ADD("%" PRIu64, vl->values[ds_num].absolute); else { - ERROR("gr_format_values plugin: Unknown data source type: %i", - ds->ds[ds_num].type); + P_ERROR("gr_format_values: Unknown data source type: %i", + ds->ds[ds_num].type); return -1; } @@ -77,7 +77,7 @@ static int gr_format_values(char *ret, size_t ret_len, int ds_num, } static void gr_copy_escape_part(char *dst, const char *src, size_t dst_len, - char escape_char, _Bool preserve_separator) { + char escape_char, bool preserve_separator) { memset(dst, 0, dst_len); if (src == NULL) @@ -116,7 +116,7 @@ static int gr_format_name(char *ret, int ret_len, value_list_t const *vl, if (postfix == NULL) postfix = ""; - _Bool preserve_separator = (flags & GRAPHITE_PRESERVE_SEPARATOR) ? 1 : 0; + bool preserve_separator = (flags & GRAPHITE_PRESERVE_SEPARATOR); gr_copy_escape_part(n_host, vl->host, sizeof(n_host), escape_char, preserve_separator); @@ -183,7 +183,7 @@ int format_graphite(char *buffer, size_t buffer_size, data_set_t const *ds, if (flags & GRAPHITE_STORE_RATES) { rates = uc_get_rate(ds, vl); if (rates == NULL) { - ERROR("format_graphite: error with uc_get_rate"); + P_ERROR("format_graphite: error with uc_get_rate"); return -1; } } @@ -202,7 +202,7 @@ int format_graphite(char *buffer, size_t buffer_size, data_set_t const *ds, status = gr_format_name(key, sizeof(key), vl, ds_name, prefix, postfix, escape_char, flags); if (status != 0) { - ERROR("format_graphite: error with gr_format_name"); + P_ERROR("format_graphite: error with gr_format_name"); sfree(rates); return status; } @@ -212,7 +212,7 @@ int format_graphite(char *buffer, size_t buffer_size, data_set_t const *ds, * `values'. */ status = gr_format_values(values, sizeof(values), i, ds, vl, rates); if (status != 0) { - ERROR("format_graphite: error with gr_format_values"); + P_ERROR("format_graphite: error with gr_format_values"); sfree(rates); return status; } @@ -222,16 +222,16 @@ int format_graphite(char *buffer, size_t buffer_size, data_set_t const *ds, (size_t)snprintf(message, sizeof(message), "%s %s %u\r\n", key, values, (unsigned int)CDTIME_T_TO_TIME_T(vl->time)); if (message_len >= sizeof(message)) { - ERROR("format_graphite: message buffer too small: " - "Need %" PRIsz " bytes.", - message_len + 1); + P_ERROR("format_graphite: message buffer too small: " + "Need %" PRIsz " bytes.", + message_len + 1); sfree(rates); return -ENOMEM; } /* Append it in case we got multiple data set */ if ((buffer_pos + message_len) >= buffer_size) { - ERROR("format_graphite: target buffer too small"); + P_ERROR("format_graphite: target buffer too small"); sfree(rates); return -ENOMEM; } diff --git a/src/utils_format_json.c b/src/utils_format_json.c index 6a0c6642..eae0b18f 100644 --- a/src/utils_format_json.c +++ b/src/utils_format_json.c @@ -267,7 +267,7 @@ static int meta_data_keys_to_json(char *buffer, size_t buffer_size, /* {{{ */ if (meta_data_get_double(meta, key, &value) == 0) BUFFER_ADD(",\"%s\":%f", key, value); } else if (type == MD_TYPE_BOOLEAN) { - _Bool value = 0; + bool value = false; if (meta_data_get_boolean(meta, key, &value) == 0) BUFFER_ADD(",\"%s\":%s", key, value ? "true" : "false"); } diff --git a/src/utils_format_json_test.c b/src/utils_format_json_test.c index 389004d3..b230ef35 100644 --- a/src/utils_format_json_test.c +++ b/src/utils_format_json_test.c @@ -87,7 +87,7 @@ static int test_map_key(void *ctx, unsigned char const *key, } static int expect_label(char const *name, char const *got, char const *want) { - _Bool ok = (strcmp(got, want) == 0); + bool ok = (strcmp(got, want) == 0); char msg[1024]; if (ok) diff --git a/src/utils_latency_config.h b/src/utils_latency_config.h index 7008fd00..2572fa0d 100644 --- a/src/utils_latency_config.h +++ b/src/utils_latency_config.h @@ -47,9 +47,9 @@ typedef struct { char *bucket_type; /* - _Bool lower; - _Bool upper; - _Bool avg; + bool lower; + bool upper; + bool avg; */ } latency_config_t; diff --git a/src/utils_lua.c b/src/utils_lua.c index 1f060f84..11ac0010 100644 --- a/src/utils_lua.c +++ b/src/utils_lua.c @@ -24,10 +24,6 @@ * Florian Forster **/ -/* defines a macro using "sprintf". Although not used here, - * GCC will complain about the macro definition. */ -#define DONT_POISON_SPRINTF_YET - #include "common.h" #include "utils_lua.h" diff --git a/src/utils_lua.h b/src/utils_lua.h index 61d9070e..e5a3d746 100644 --- a/src/utils_lua.h +++ b/src/utils_lua.h @@ -27,12 +27,9 @@ #ifndef UTILS_LUA_H #define UTILS_LUA_H 1 -#include "plugin.h" #include "collectd.h" +#include "plugin.h" -#ifndef DONT_POISON_SPRINTF_YET -#error "Files including utils_lua.h need to define DONT_POISON_SPRINTF_YET." -#endif #include /* diff --git a/src/utils_mount.c b/src/utils_mount.c index b8af367e..e430cc9c 100644 --- a/src/utils_mount.c +++ b/src/utils_mount.c @@ -688,7 +688,7 @@ void cu_mount_freelist(cu_mount_t *list) { char *cu_mount_checkoption(char *line, const char *keyword, int full) { char *line2, *l2, *p1, *p2; - int l; + size_t l; if (line == NULL || keyword == NULL) { return NULL; diff --git a/src/utils_ovs.c b/src/utils_ovs.c index ca631812..4ca86aeb 100644 --- a/src/utils_ovs.c +++ b/src/utils_ovs.c @@ -191,7 +191,7 @@ struct ovs_db_s { }; /* Global variables */ -static uint64_t ovs_uid = 0; +static uint64_t ovs_uid; static pthread_mutex_t ovs_uid_mutex = PTHREAD_MUTEX_INITIALIZER; /* Post an event to event thread. @@ -209,7 +209,7 @@ static void ovs_db_event_post(ovs_db_t *pdb, int event) { /* Check if POLL thread is still running. Returns * 1 if running otherwise 0 is returned */ -static _Bool ovs_db_poll_is_running(ovs_db_t *pdb) { +static bool ovs_db_poll_is_running(ovs_db_t *pdb) { int state = 0; pthread_mutex_lock(&pdb->poll_thread.mutex); state = pdb->poll_thread.state; @@ -1051,6 +1051,8 @@ ovs_db_t *ovs_db_init(const char *node, const char *service, ret = ovs_db_destroy(pdb); if (ret > 0) goto failure; + else + return NULL; } /* init polling thread */ @@ -1059,6 +1061,8 @@ ovs_db_t *ovs_db_init(const char *node, const char *service, if (ret > 0) { ovs_db_event_thread_data_destroy(pdb); goto failure; + } else { + return NULL; } } return pdb; diff --git a/src/utils_rrdcreate.c b/src/utils_rrdcreate.c index ef126012..8f92cfd3 100644 --- a/src/utils_rrdcreate.c +++ b/src/utils_rrdcreate.c @@ -61,7 +61,7 @@ static int rra_types_num = STATIC_ARRAY_SIZE(rra_types); static pthread_mutex_t librrd_lock = PTHREAD_MUTEX_INITIALIZER; #endif -static async_create_file_t *async_creation_list = NULL; +static async_create_file_t *async_creation_list; static pthread_mutex_t async_creation_lock = PTHREAD_MUTEX_INITIALIZER; /* @@ -96,7 +96,7 @@ static srrd_create_args_t *srrd_create_args_create(const char *filename, args = calloc(1, sizeof(*args)); if (args == NULL) { - ERROR("srrd_create_args_create: calloc failed."); + P_ERROR("srrd_create_args_create: calloc failed."); return NULL; } args->filename = NULL; @@ -106,14 +106,14 @@ static srrd_create_args_t *srrd_create_args_create(const char *filename, args->filename = strdup(filename); if (args->filename == NULL) { - ERROR("srrd_create_args_create: strdup failed."); + P_ERROR("srrd_create_args_create: strdup failed."); srrd_create_args_destroy(args); return NULL; } args->argv = calloc((size_t)(argc + 1), sizeof(*args->argv)); if (args->argv == NULL) { - ERROR("srrd_create_args_create: calloc failed."); + P_ERROR("srrd_create_args_create: calloc failed."); srrd_create_args_destroy(args); return NULL; } @@ -121,7 +121,7 @@ static srrd_create_args_t *srrd_create_args_create(const char *filename, for (args->argc = 0; args->argc < argc; args->argc++) { args->argv[args->argc] = strdup(argv[args->argc]); if (args->argv[args->argc] == NULL) { - ERROR("srrd_create_args_create: strdup failed."); + P_ERROR("srrd_create_args_create: strdup failed."); srrd_create_args_destroy(args); return NULL; } @@ -212,7 +212,7 @@ static int rra_get(char ***ret, const value_list_t *vl, /* {{{ */ rra_types[j], cfg->xff, cdp_len, cdp_num); if ((status < 0) || ((size_t)status >= sizeof(buffer))) { - ERROR("rra_get: Buffer would have been truncated."); + P_ERROR("rra_get: Buffer would have been truncated."); continue; } @@ -251,7 +251,7 @@ static int ds_get(char ***ret, /* {{{ */ ds_def = calloc(ds->ds_num, sizeof(*ds_def)); if (ds_def == NULL) { - ERROR("rrdtool plugin: calloc failed: %s", STRERRNO); + P_ERROR("ds_get: calloc failed: %s", STRERRNO); return -1; } @@ -271,7 +271,7 @@ static int ds_get(char ***ret, /* {{{ */ else if (d->type == DS_TYPE_ABSOLUTE) type = "ABSOLUTE"; else { - ERROR("rrdtool plugin: Unknown DS type: %i", d->type); + P_ERROR("ds_get: Unknown DS type: %i", d->type); break; } @@ -335,8 +335,8 @@ static int srrd_create(const char *filename, /* {{{ */ status = rrd_create_r(filename_copy, pdp_step, last_up, argc, (void *)argv); if (status != 0) { - WARNING("rrdtool plugin: rrd_create_r (%s) failed: %s", filename, - rrd_get_error()); + P_WARNING("srrd_create: rrd_create_r (%s) failed: %s", filename, + rrd_get_error()); } sfree(filename_copy); @@ -360,7 +360,7 @@ static int srrd_create(const char *filename, /* {{{ */ new_argc = 6 + argc; new_argv = malloc((new_argc + 1) * sizeof(*new_argv)); if (new_argv == NULL) { - ERROR("rrdtool plugin: malloc failed."); + P_ERROR("srrd_create: malloc failed."); return -1; } @@ -388,8 +388,8 @@ static int srrd_create(const char *filename, /* {{{ */ pthread_mutex_unlock(&librrd_lock); if (status != 0) { - WARNING("rrdtool plugin: rrd_create (%s) failed: %s", filename, - rrd_get_error()); + P_WARNING("srrd_create: rrd_create (%s) failed: %s", filename, + rrd_get_error()); } sfree(new_argv); @@ -487,10 +487,11 @@ static void *srrd_create_thread(void *targs) /* {{{ */ status = lock_file(args->filename); if (status != 0) { if (status == EEXIST) - NOTICE("srrd_create_thread: File \"%s\" is already being created.", - args->filename); + P_NOTICE("srrd_create_thread: File \"%s\" is already being created.", + args->filename); else - ERROR("srrd_create_thread: Unable to lock file \"%s\".", args->filename); + P_ERROR("srrd_create_thread: Unable to lock file \"%s\".", + args->filename); srrd_create_args_destroy(args); return 0; } @@ -500,8 +501,8 @@ static void *srrd_create_thread(void *targs) /* {{{ */ status = srrd_create(tmpfile, args->pdp_step, args->last_up, args->argc, (void *)args->argv); if (status != 0) { - WARNING("srrd_create_thread: srrd_create (%s) returned status %i.", - args->filename, status); + P_WARNING("srrd_create_thread: srrd_create (%s) returned status %i.", + args->filename, status); unlink(tmpfile); unlock_file(args->filename); srrd_create_args_destroy(args); @@ -510,8 +511,8 @@ static void *srrd_create_thread(void *targs) /* {{{ */ status = rename(tmpfile, args->filename); if (status != 0) { - ERROR("srrd_create_thread: rename (\"%s\", \"%s\") failed: %s", tmpfile, - args->filename, STRERRNO); + P_ERROR("srrd_create_thread: rename (\"%s\", \"%s\") failed: %s", tmpfile, + args->filename, STRERRNO); unlink(tmpfile); unlock_file(args->filename); srrd_create_args_destroy(args); @@ -556,7 +557,7 @@ static int srrd_create_async(const char *filename, /* {{{ */ status = pthread_create(&thread, &attr, srrd_create_thread, args); if (status != 0) { - ERROR("srrd_create_async: pthread_create failed: %s", STRERROR(status)); + P_ERROR("srrd_create_async: pthread_create failed: %s", STRERROR(status)); pthread_attr_destroy(&attr); srrd_create_args_destroy(args); return status; @@ -587,12 +588,12 @@ int cu_rrd_create_file(const char *filename, /* {{{ */ return -1; if ((rra_num = rra_get(&rra_def, vl, cfg)) < 1) { - ERROR("cu_rrd_create_file failed: Could not calculate RRAs"); + P_ERROR("cu_rrd_create_file failed: Could not calculate RRAs"); return -1; } if ((ds_num = ds_get(&ds_def, ds, vl, cfg)) < 1) { - ERROR("cu_rrd_create_file failed: Could not calculate DSes"); + P_ERROR("cu_rrd_create_file failed: Could not calculate DSes"); rra_free(rra_num, rra_def); return -1; } @@ -600,7 +601,7 @@ int cu_rrd_create_file(const char *filename, /* {{{ */ argc = ds_num + rra_num; if ((argv = malloc(sizeof(*argv) * (argc + 1))) == NULL) { - ERROR("cu_rrd_create_file failed: %s", STRERRNO); + P_ERROR("cu_rrd_create_file failed: %s", STRERRNO); rra_free(rra_num, rra_def); ds_free(ds_num, ds_def); return -1; @@ -624,25 +625,25 @@ int cu_rrd_create_file(const char *filename, /* {{{ */ status = srrd_create_async(filename, stepsize, last_up, argc, (const char **)argv); if (status != 0) - WARNING("cu_rrd_create_file: srrd_create_async (%s) " - "returned status %i.", - filename, status); + P_WARNING("cu_rrd_create_file: srrd_create_async (%s) " + "returned status %i.", + filename, status); } else /* synchronous */ { status = lock_file(filename); if (status != 0) { if (status == EEXIST) - NOTICE("cu_rrd_create_file: File \"%s\" is already being created.", - filename); + P_NOTICE("cu_rrd_create_file: File \"%s\" is already being created.", + filename); else - ERROR("cu_rrd_create_file: Unable to lock file \"%s\".", filename); + P_ERROR("cu_rrd_create_file: Unable to lock file \"%s\".", filename); } else { 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); + P_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); diff --git a/src/utils_rrdcreate.h b/src/utils_rrdcreate.h index d5f9a12a..b2277e75 100644 --- a/src/utils_rrdcreate.h +++ b/src/utils_rrdcreate.h @@ -43,7 +43,7 @@ struct rrdcreate_config_s { char **consolidation_functions; size_t consolidation_functions_num; - _Bool async; + bool async; }; typedef struct rrdcreate_config_s rrdcreate_config_t; diff --git a/src/utils_vl_lookup.c b/src/utils_vl_lookup.c index 052c4c0f..03e61f80 100644 --- a/src/utils_vl_lookup.c +++ b/src/utils_vl_lookup.c @@ -57,7 +57,7 @@ kstat_ctl_t *kc; struct part_match_s { char str[DATA_MAX_NAME_LEN]; regex_t regex; - _Bool is_regex; + bool is_regex; }; typedef struct part_match_s part_match_t; @@ -114,25 +114,25 @@ typedef struct by_type_entry_s by_type_entry_t; /* * Private functions */ -static _Bool lu_part_matches(part_match_t const *match, /* {{{ */ - char const *str) { +static bool lu_part_matches(part_match_t const *match, /* {{{ */ + char const *str) { if (match->is_regex) { /* Short cut popular catch-all regex. */ if (strcmp(".*", match->str) == 0) - return 1; + return true; int status = regexec(&match->regex, str, /* nmatch = */ 0, /* pmatch = */ NULL, /* flags = */ 0); if (status == 0) - return 1; + return true; else - return 0; + return false; } else if (strcmp(match->str, str) == 0) - return 1; + return true; else - return 0; -} /* }}} _Bool lu_part_matches */ + return false; +} /* }}} bool lu_part_matches */ static int lu_copy_ident_to_match_part(part_match_t *match_part, /* {{{ */ char const *ident_part) { @@ -141,7 +141,7 @@ static int lu_copy_ident_to_match_part(part_match_t *match_part, /* {{{ */ if ((len < 3) || (ident_part[0] != '/') || (ident_part[len - 1] != '/')) { sstrncpy(match_part->str, ident_part, sizeof(match_part->str)); - match_part->is_regex = 0; + match_part->is_regex = false; return 0; } @@ -160,7 +160,7 @@ static int lu_copy_ident_to_match_part(part_match_t *match_part, /* {{{ */ match_part->str, errbuf); return EINVAL; } - match_part->is_regex = 1; + match_part->is_regex = true; return 0; } /* }}} int lu_copy_ident_to_match_part */ @@ -335,7 +335,7 @@ static int lu_handle_user_class_list(lookup_t *obj, /* {{{ */ static by_type_entry_t *lu_search_by_type(lookup_t *obj, /* {{{ */ char const *type, - _Bool allocate_if_missing) { + bool allocate_if_missing) { by_type_entry_t *by_type; char *type_copy; int status; @@ -467,7 +467,7 @@ static void lu_destroy_user_class_list(lookup_t *obj, /* {{{ */ do { \ if (user_class_list->entry.match.field.is_regex) { \ regfree(&user_class_list->entry.match.field.regex); \ - user_class_list->entry.match.field.is_regex = 0; \ + user_class_list->entry.match.field.is_regex = false; \ } \ } while (0) @@ -576,7 +576,7 @@ int lookup_add(lookup_t *obj, /* {{{ */ by_type_entry_t *by_type = NULL; user_class_list_t *user_class_obj; - by_type = lu_search_by_type(obj, ident->type, /* allocate = */ 1); + by_type = lu_search_by_type(obj, ident->type, /* allocate = */ true); if (by_type == NULL) return -1; @@ -605,7 +605,7 @@ int lookup_search(lookup_t *obj, /* {{{ */ if ((obj == NULL) || (ds == NULL) || (vl == NULL)) return -EINVAL; - by_type = lu_search_by_type(obj, vl->type, /* allocate = */ 0); + by_type = lu_search_by_type(obj, vl->type, /* allocate = */ false); if (by_type == NULL) return 0; diff --git a/src/utils_vl_lookup_test.c b/src/utils_vl_lookup_test.c index 058015ed..27bfddf0 100644 --- a/src/utils_vl_lookup_test.c +++ b/src/utils_vl_lookup_test.c @@ -29,8 +29,8 @@ #include "testing.h" #include "utils_vl_lookup.h" -static _Bool expect_new_obj = 0; -static _Bool have_new_obj = 0; +static bool expect_new_obj; +static bool have_new_obj; static lookup_identifier_t last_class_ident; static lookup_identifier_t last_obj_ident; @@ -75,7 +75,7 @@ static void *lookup_class_callback(data_set_t const *ds, value_list_t const *vl, strncpy(obj->type, vl->type, sizeof(obj->type)); strncpy(obj->type_instance, vl->type_instance, sizeof(obj->type_instance)); - have_new_obj = 1; + have_new_obj = true; return (void *)obj; } @@ -105,7 +105,7 @@ static int checked_lookup_add(lookup_t *obj, /* {{{ */ 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) { + char const *type_instance, bool expect_new) { int status; value_list_t vl = VALUE_LIST_INIT; data_set_t const *ds = &ds_unknown; @@ -120,7 +120,7 @@ static int checked_lookup_search(lookup_t *obj, char const *host, ds = &ds_test; expect_new_obj = expect_new; - have_new_obj = 0; + have_new_obj = false; status = lookup_search(obj, ds, &vl); return status; diff --git a/src/uuid.c b/src/uuid.c index 1cb90270..c7878c74 100644 --- a/src/uuid.c +++ b/src/uuid.c @@ -37,18 +37,15 @@ #define UUID_PRINTABLE_COMPACT_LENGTH (UUID_RAW_LENGTH * 2) #define UUID_PRINTABLE_NORMAL_LENGTH (UUID_PRINTABLE_COMPACT_LENGTH + 4) -static char *uuidfile = NULL; +static char *uuidfile; static const char *config_keys[] = {"UUIDFile"}; static int looks_like_a_uuid(const char *uuid) { - int len; - if (!uuid) return 0; - len = strlen(uuid); - + size_t len = strlen(uuid); if (len < UUID_PRINTABLE_COMPACT_LENGTH) return 0; diff --git a/src/valgrind.suppress b/src/valgrind.suppress new file mode 100644 index 00000000..f4c3f343 --- /dev/null +++ b/src/valgrind.suppress @@ -0,0 +1,7 @@ +{ + libnl1_virt_initialization_unpreventable_leak + Memcheck:Leak + ... + obj:*libnl.so.1.* + ... +} \ No newline at end of file diff --git a/src/varnish.c b/src/varnish.c index 08260dc2..b515be89 100644 --- a/src/varnish.c +++ b/src/varnish.c @@ -50,50 +50,50 @@ typedef struct varnish_stats c_varnish_stats_t; struct user_config_s { char *instance; - _Bool collect_cache; - _Bool collect_connections; - _Bool collect_esi; - _Bool collect_backend; + bool collect_cache; + bool collect_connections; + bool collect_esi; + bool collect_backend; #ifdef HAVE_VARNISH_V3 - _Bool collect_dirdns; + bool collect_dirdns; #endif - _Bool collect_fetch; - _Bool collect_hcb; - _Bool collect_objects; + bool collect_fetch; + bool collect_hcb; + bool collect_objects; #if HAVE_VARNISH_V2 - _Bool collect_purge; + bool collect_purge; #else - _Bool collect_ban; + bool collect_ban; #endif - _Bool collect_session; - _Bool collect_shm; - _Bool collect_sms; + bool collect_session; + bool collect_shm; + bool collect_sms; #if HAVE_VARNISH_V2 - _Bool collect_sm; + bool collect_sm; #endif #if HAVE_VARNISH_V2 || HAVE_VARNISH_V4 || HAVE_VARNISH_V5 - _Bool collect_sma; + bool collect_sma; #endif - _Bool collect_struct; - _Bool collect_totals; + bool collect_struct; + bool collect_totals; #if HAVE_VARNISH_V3 || HAVE_VARNISH_V4 || HAVE_VARNISH_V5 - _Bool collect_uptime; + bool collect_uptime; #endif - _Bool collect_vcl; - _Bool collect_workers; + bool collect_vcl; + bool collect_workers; #if HAVE_VARNISH_V4 || HAVE_VARNISH_V5 - _Bool collect_vsm; - _Bool collect_lck; - _Bool collect_mempool; - _Bool collect_mgt; - _Bool collect_smf; - _Bool collect_vbe; - _Bool collect_mse; + bool collect_vsm; + bool collect_lck; + bool collect_mempool; + bool collect_mgt; + bool collect_smf; + bool collect_vbe; + bool collect_mse; #endif }; typedef struct user_config_s user_config_t; /* }}} */ -static _Bool have_instance = 0; +static bool have_instance; static int varnish_submit(const char *plugin_instance, /* {{{ */ const char *category, const char *type, @@ -1331,7 +1331,7 @@ static int varnish_read(user_data_t *ud) /* {{{ */ { #if HAVE_VARNISH_V3 || HAVE_VARNISH_V4 struct VSM_data *vd; - _Bool ok; + bool ok; const c_varnish_stats_t *stats; #elif HAVE_VARNISH_V5 struct vsm *vd; @@ -1480,45 +1480,45 @@ static int varnish_config_apply_default(user_config_t *conf) /* {{{ */ if (conf == NULL) return EINVAL; - conf->collect_backend = 1; - conf->collect_cache = 1; - conf->collect_connections = 1; + conf->collect_backend = true; + conf->collect_cache = true; + conf->collect_connections = true; #ifdef HAVE_VARNISH_V3 - conf->collect_dirdns = 0; + conf->collect_dirdns = false; #endif - conf->collect_esi = 0; - conf->collect_fetch = 0; - conf->collect_hcb = 0; - conf->collect_objects = 0; + conf->collect_esi = false; + conf->collect_fetch = false; + conf->collect_hcb = false; + conf->collect_objects = false; #if HAVE_VARNISH_V2 - conf->collect_purge = 0; + conf->collect_purge = false; #else - conf->collect_ban = 0; + conf->collect_ban = false; #endif - conf->collect_session = 0; - conf->collect_shm = 1; + conf->collect_session = false; + conf->collect_shm = true; #if HAVE_VARNISH_V2 - conf->collect_sm = 0; + conf->collect_sm = false; #endif #if HAVE_VARNISH_V2 || HAVE_VARNISH_V4 || HAVE_VARNISH_V5 - conf->collect_sma = 0; + conf->collect_sma = false; #endif - conf->collect_sms = 0; - conf->collect_struct = 0; - conf->collect_totals = 0; + conf->collect_sms = false; + conf->collect_struct = false; + conf->collect_totals = false; #if HAVE_VARNISH_V3 || HAVE_VARNISH_V4 || HAVE_VARNISH_V5 - conf->collect_uptime = 0; + conf->collect_uptime = false; #endif - conf->collect_vcl = 0; - conf->collect_workers = 0; + conf->collect_vcl = false; + conf->collect_workers = false; #if HAVE_VARNISH_V4 || HAVE_VARNISH_V5 - conf->collect_vsm = 0; - conf->collect_lck = 0; - conf->collect_mempool = 0; - conf->collect_mgt = 0; - conf->collect_smf = 0; - conf->collect_vbe = 0; - conf->collect_mse = 0; + conf->collect_vsm = false; + conf->collect_lck = false; + conf->collect_mempool = false; + conf->collect_mgt = false; + conf->collect_smf = false; + conf->collect_vbe = false; + conf->collect_mse = false; #endif return 0; @@ -1771,7 +1771,7 @@ static int varnish_config_instance(const oconfig_item_t *ci) /* {{{ */ .data = conf, .free_func = varnish_config_free, }); - have_instance = 1; + have_instance = true; return 0; } /* }}} int varnish_config_instance */ diff --git a/src/virt.c b/src/virt.c index 06e2408f..87ab8fdc 100644 --- a/src/virt.c +++ b/src/virt.c @@ -34,10 +34,19 @@ #include #include #include +#include /* Plugin name */ #define PLUGIN_NAME "virt" +/* Secure strcat macro assuring null termination. Parameter (n) is the size of + buffer (d), allowing this macro to be safe for static and dynamic buffers */ +#define SSTRNCAT(d, s, n) \ + do { \ + size_t _l = strlen(d); \ + sstrncpy((d) + _l, (s), (n)-_l); \ + } while (0) + #ifdef LIBVIR_CHECK_VERSION #if LIBVIR_CHECK_VERSION(0, 9, 2) @@ -59,6 +68,16 @@ #define HAVE_DOM_REASON_RUNNING_WAKEUP 1 #endif +/* + virConnectListAllDomains() appeared in 0.10.2 + Note that LIBVIR_CHECK_VERSION appeared a year later, so + in some systems which actually have virConnectListAllDomains() + we can't detect this. + */ +#if LIBVIR_CHECK_VERSION(0, 10, 2) +#define HAVE_LIST_ALL_DOMAINS 1 +#endif + #if LIBVIR_CHECK_VERSION(1, 0, 1) #define HAVE_DOM_REASON_PAUSED_SNAPSHOT 1 #endif @@ -90,6 +109,14 @@ #endif /* LIBVIR_CHECK_VERSION */ +/* structure used for aggregating notification-thread data*/ +typedef struct virt_notif_thread_s { + pthread_t event_loop_tid; + int domain_event_cb_id; + pthread_mutex_t active_mutex; /* protects 'is_active' member access*/ + bool is_active; +} virt_notif_thread_t; + static const char *config_keys[] = {"Connection", "RefreshInterval", @@ -108,8 +135,15 @@ static const char *config_keys[] = {"Connection", "Instances", "ExtraStats", + "PersistentNotification", NULL}; +/* PersistentNotification is false by default */ +static bool persistent_notification = false; + +/* Thread used for handling libvirt notifications events */ +static virt_notif_thread_t notif_thread; + const char *domain_states[] = { [VIR_DOMAIN_NOSTATE] = "no state", [VIR_DOMAIN_RUNNING] = "the domain is running", @@ -124,7 +158,202 @@ const char *domain_states[] = { #endif }; +static int map_domain_event_to_state(int event) { + int ret; + switch (event) { + case VIR_DOMAIN_EVENT_STARTED: + ret = VIR_DOMAIN_RUNNING; + break; + case VIR_DOMAIN_EVENT_SUSPENDED: + ret = VIR_DOMAIN_PAUSED; + break; + case VIR_DOMAIN_EVENT_RESUMED: + ret = VIR_DOMAIN_RUNNING; + break; + case VIR_DOMAIN_EVENT_STOPPED: + ret = VIR_DOMAIN_SHUTOFF; + break; + case VIR_DOMAIN_EVENT_SHUTDOWN: + ret = VIR_DOMAIN_SHUTDOWN; + break; +#ifdef HAVE_DOM_STATE_PMSUSPENDED + case VIR_DOMAIN_EVENT_PMSUSPENDED: + ret = VIR_DOMAIN_PMSUSPENDED; + break; +#endif +#ifdef HAVE_DOM_REASON_CRASHED + case VIR_DOMAIN_EVENT_CRASHED: + ret = VIR_DOMAIN_CRASHED; + break; +#endif + default: + ret = VIR_DOMAIN_NOSTATE; + } + return ret; +} + #ifdef HAVE_DOM_REASON +static int map_domain_event_detail_to_reason(int event, int detail) { + int ret; + switch (event) { + case VIR_DOMAIN_EVENT_STARTED: + switch (detail) { + case VIR_DOMAIN_EVENT_STARTED_BOOTED: /* Normal startup from boot */ + ret = VIR_DOMAIN_RUNNING_BOOTED; + break; + case VIR_DOMAIN_EVENT_STARTED_MIGRATED: /* Incoming migration from another + host */ + ret = VIR_DOMAIN_RUNNING_MIGRATED; + break; + case VIR_DOMAIN_EVENT_STARTED_RESTORED: /* Restored from a state file */ + ret = VIR_DOMAIN_RUNNING_RESTORED; + break; + case VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT: /* Restored from snapshot */ + ret = VIR_DOMAIN_RUNNING_FROM_SNAPSHOT; + break; +#ifdef HAVE_DOM_REASON_RUNNING_WAKEUP + case VIR_DOMAIN_EVENT_STARTED_WAKEUP: /* Started due to wakeup event */ + ret = VIR_DOMAIN_RUNNING_WAKEUP; + break; +#endif + default: + ret = VIR_DOMAIN_RUNNING_UNKNOWN; + } + break; + case VIR_DOMAIN_EVENT_SUSPENDED: + switch (detail) { + case VIR_DOMAIN_EVENT_SUSPENDED_PAUSED: /* Normal suspend due to admin + pause */ + ret = VIR_DOMAIN_PAUSED_USER; + break; + case VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED: /* Suspended for offline + migration */ + ret = VIR_DOMAIN_PAUSED_MIGRATION; + break; + case VIR_DOMAIN_EVENT_SUSPENDED_IOERROR: /* Suspended due to a disk I/O + error */ + ret = VIR_DOMAIN_PAUSED_IOERROR; + break; + case VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG: /* Suspended due to a watchdog + firing */ + ret = VIR_DOMAIN_PAUSED_WATCHDOG; + break; + case VIR_DOMAIN_EVENT_SUSPENDED_RESTORED: /* Restored from paused state + file */ + ret = VIR_DOMAIN_PAUSED_UNKNOWN; + break; + case VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT: /* Restored from paused + snapshot */ + ret = VIR_DOMAIN_PAUSED_FROM_SNAPSHOT; + break; + case VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR: /* Suspended after failure during + libvirt API call */ + ret = VIR_DOMAIN_PAUSED_UNKNOWN; + break; +#ifdef HAVE_DOM_REASON_POSTCOPY + case VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY: /* Suspended for post-copy + migration */ + ret = VIR_DOMAIN_PAUSED_POSTCOPY; + break; + case VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY_FAILED: /* Suspended after failed + post-copy */ + ret = VIR_DOMAIN_PAUSED_POSTCOPY_FAILED; + break; +#endif + default: + ret = VIR_DOMAIN_PAUSED_UNKNOWN; + } + break; + case VIR_DOMAIN_EVENT_RESUMED: + switch (detail) { + case VIR_DOMAIN_EVENT_RESUMED_UNPAUSED: /* Normal resume due to admin + unpause */ + ret = VIR_DOMAIN_RUNNING_UNPAUSED; + break; + case VIR_DOMAIN_EVENT_RESUMED_MIGRATED: /* Resumed for completion of + migration */ + ret = VIR_DOMAIN_RUNNING_MIGRATED; + break; + case VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT: /* Resumed from snapshot */ + ret = VIR_DOMAIN_RUNNING_FROM_SNAPSHOT; + break; +#ifdef HAVE_DOM_REASON_POSTCOPY + case VIR_DOMAIN_EVENT_RESUMED_POSTCOPY: /* Resumed, but migration is still + running in post-copy mode */ + ret = VIR_DOMAIN_RUNNING_POSTCOPY; + break; +#endif + default: + ret = VIR_DOMAIN_RUNNING_UNKNOWN; + } + break; + case VIR_DOMAIN_EVENT_STOPPED: + switch (detail) { + case VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN: /* Normal shutdown */ + ret = VIR_DOMAIN_SHUTOFF_SHUTDOWN; + break; + case VIR_DOMAIN_EVENT_STOPPED_DESTROYED: /* Forced poweroff from host */ + ret = VIR_DOMAIN_SHUTOFF_DESTROYED; + break; + case VIR_DOMAIN_EVENT_STOPPED_CRASHED: /* Guest crashed */ + ret = VIR_DOMAIN_SHUTOFF_CRASHED; + break; + case VIR_DOMAIN_EVENT_STOPPED_MIGRATED: /* Migrated off to another host */ + ret = VIR_DOMAIN_SHUTOFF_MIGRATED; + break; + case VIR_DOMAIN_EVENT_STOPPED_SAVED: /* Saved to a state file */ + ret = VIR_DOMAIN_SHUTOFF_SAVED; + break; + case VIR_DOMAIN_EVENT_STOPPED_FAILED: /* Host emulator/mgmt failed */ + ret = VIR_DOMAIN_SHUTOFF_FAILED; + break; + case VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT: /* Offline snapshot loaded */ + ret = VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT; + break; + default: + ret = VIR_DOMAIN_SHUTOFF_UNKNOWN; + } + break; + case VIR_DOMAIN_EVENT_SHUTDOWN: + switch (detail) { + case VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED: /* Guest finished shutdown + sequence */ + ret = VIR_DOMAIN_SHUTDOWN_USER; + break; + default: + ret = VIR_DOMAIN_SHUTDOWN_UNKNOWN; + } + break; +#ifdef HAVE_DOM_STATE_PMSUSPENDED + case VIR_DOMAIN_EVENT_PMSUSPENDED: + switch (detail) { + case VIR_DOMAIN_EVENT_PMSUSPENDED_MEMORY: /* Guest was PM suspended to + memory */ + ret = VIR_DOMAIN_PMSUSPENDED_UNKNOWN; + break; + case VIR_DOMAIN_EVENT_PMSUSPENDED_DISK: /* Guest was PM suspended to disk */ + ret = VIR_DOMAIN_PMSUSPENDED_DISK_UNKNOWN; + break; + default: + ret = VIR_DOMAIN_PMSUSPENDED_UNKNOWN; + } + break; +#endif + case VIR_DOMAIN_EVENT_CRASHED: + switch (detail) { + case VIR_DOMAIN_EVENT_CRASHED_PANICKED: /* Guest was panicked */ + ret = VIR_DOMAIN_CRASHED_PANICKED; + break; + default: + ret = VIR_DOMAIN_CRASHED_UNKNOWN; + } + break; + default: + ret = VIR_DOMAIN_NOSTATE_UNKNOWN; + } + return ret; +} + #define DOMAIN_STATE_REASON_MAX_SIZE 20 const char *domain_reasons[][DOMAIN_STATE_REASON_MAX_SIZE] = { [VIR_DOMAIN_NOSTATE][VIR_DOMAIN_NOSTATE_UNKNOWN] = @@ -158,7 +387,6 @@ const char *domain_reasons[][DOMAIN_STATE_REASON_MAX_SIZE] = { [VIR_DOMAIN_RUNNING][VIR_DOMAIN_RUNNING_POSTCOPY] = "running in post-copy migration mode", #endif - [VIR_DOMAIN_BLOCKED][VIR_DOMAIN_BLOCKED_UNKNOWN] = "the reason is unknown", @@ -198,7 +426,6 @@ const char *domain_reasons[][DOMAIN_STATE_REASON_MAX_SIZE] = { [VIR_DOMAIN_PAUSED][VIR_DOMAIN_PAUSED_POSTCOPY_FAILED] = "paused after failed post-copy", #endif - [VIR_DOMAIN_SHUTDOWN][VIR_DOMAIN_SHUTDOWN_UNKNOWN] = "the reason is unknown", [VIR_DOMAIN_SHUTDOWN][VIR_DOMAIN_SHUTDOWN_USER] = @@ -241,8 +468,8 @@ const char *domain_reasons[][DOMAIN_STATE_REASON_MAX_SIZE] = { } while (0) /* Connection. */ -static virConnectPtr conn = 0; -static char *conn_string = NULL; +static virConnectPtr conn; +static char *conn_string; static c_complain_t conn_complain = C_COMPLAIN_INIT_STATIC; /* Node information required for %CPU */ @@ -252,11 +479,11 @@ static virNodeInfo nodeinfo; static int interval = 60; /* List of domains, if specified. */ -static ignorelist_t *il_domains = NULL; +static ignorelist_t *il_domains; /* List of block devices, if specified. */ -static ignorelist_t *il_block_devices = NULL; +static ignorelist_t *il_block_devices; /* List of network interface devices, if specified. */ -static ignorelist_t *il_interface_devices = NULL; +static ignorelist_t *il_interface_devices; static int ignore_device_match(ignorelist_t *, const char *domname, const char *devpath); @@ -278,6 +505,7 @@ struct interface_device { typedef struct domain_s { virDomainPtr ptr; virDomainInfo info; + bool active; } domain_t; struct lv_read_state { @@ -293,7 +521,8 @@ struct lv_read_state { }; static void free_domains(struct lv_read_state *state); -static int add_domain(struct lv_read_state *state, virDomainPtr dom); +static int add_domain(struct lv_read_state *state, virDomainPtr dom, + bool active); static void free_block_devices(struct lv_read_state *state); static int add_block_device(struct lv_read_state *state, virDomainPtr dom, @@ -401,7 +630,7 @@ static const struct ex_stats_item ex_stats_table[] = { }; /* BlockDeviceFormatBasename */ -_Bool blockdevice_format_basename = 0; +static bool blockdevice_format_basename; static enum bd_field blockdevice_format = target; static enum if_field interface_format = if_name; @@ -533,7 +762,6 @@ static int lv_domain_info(virDomainPtr dom, struct lv_info *info) { } static void init_value_list(value_list_t *vl, virDomainPtr dom) { - int n; const char *name; char uuid[VIR_UUID_STRING_BUFLEN]; @@ -546,44 +774,34 @@ static void init_value_list(value_list_t *vl, virDomainPtr dom) { if (hostname_format[i] == hf_none) continue; - n = DATA_MAX_NAME_LEN - strlen(vl->host) - 2; - - if (i > 0 && n >= 1) { - strncat(vl->host, ":", 1); - n--; - } + if (i > 0) + SSTRNCAT(vl->host, ":", sizeof(vl->host)); switch (hostname_format[i]) { case hf_none: break; case hf_hostname: - strncat(vl->host, hostname_g, n); + SSTRNCAT(vl->host, hostname_g, sizeof(vl->host)); break; case hf_name: name = virDomainGetName(dom); if (name) - strncat(vl->host, name, n); + SSTRNCAT(vl->host, name, sizeof(vl->host)); break; case hf_uuid: if (virDomainGetUUIDString(dom, uuid) == 0) - strncat(vl->host, uuid, n); + SSTRNCAT(vl->host, uuid, sizeof(vl->host)); break; } } - vl->host[sizeof(vl->host) - 1] = '\0'; - /* Construct the plugin instance field according to PluginInstanceFormat. */ for (int i = 0; i < PLGINST_MAX_FIELDS; ++i) { if (plugin_instance_format[i] == plginst_none) continue; - n = sizeof(vl->plugin_instance) - strlen(vl->plugin_instance) - 2; - - if (i > 0 && n >= 1) { - strncat(vl->plugin_instance, ":", 1); - n--; - } + if (i > 0) + SSTRNCAT(vl->plugin_instance, ":", sizeof(vl->plugin_instance)); switch (plugin_instance_format[i]) { case plginst_none: @@ -591,17 +809,15 @@ static void init_value_list(value_list_t *vl, virDomainPtr dom) { case plginst_name: name = virDomainGetName(dom); if (name) - strncat(vl->plugin_instance, name, n); + SSTRNCAT(vl->plugin_instance, name, sizeof(vl->plugin_instance)); break; case plginst_uuid: if (virDomainGetUUIDString(dom, uuid) == 0) - strncat(vl->plugin_instance, uuid, n); + SSTRNCAT(vl->plugin_instance, uuid, sizeof(vl->plugin_instance)); break; } } - vl->plugin_instance[sizeof(vl->plugin_instance) - 1] = '\0'; - } /* void init_value_list */ static int init_notif(notification_t *notif, const virDomainPtr domain, @@ -799,9 +1015,8 @@ static unsigned int parse_ex_stats_flags(char **exstats, int numexstats) { return ex_stats_flags; } -static void domain_state_submit(virDomainPtr dom, int state, int reason) { - - if ((state < 0) || (state >= STATIC_ARRAY_SIZE(domain_states))) { +static void domain_state_submit_notif(virDomainPtr dom, int state, int reason) { + if ((state < 0) || ((size_t)state >= STATIC_ARRAY_SIZE(domain_states))) { ERROR(PLUGIN_NAME ": Array index out of bounds: state=%d", state); return; } @@ -809,7 +1024,8 @@ static void domain_state_submit(virDomainPtr dom, int state, int reason) { char msg[DATA_MAX_NAME_LEN]; const char *state_str = domain_states[state]; #ifdef HAVE_DOM_REASON - if ((reason < 0) || (reason >= STATIC_ARRAY_SIZE(domain_reasons[0]))) { + if ((reason < 0) || + ((size_t)reason >= STATIC_ARRAY_SIZE(domain_reasons[0]))) { ERROR(PLUGIN_NAME ": Array index out of bounds: reason=%d", reason); return; } @@ -908,7 +1124,7 @@ static int lv_config(const char *key, const char *value) { return 0; } if (strcasecmp(key, "BlockDeviceFormatBasename") == 0) { - blockdevice_format_basename = IS_TRUE(value); + blockdevice_format_basename = IS_TRUE(value) ? true : false; return 0; } if (strcasecmp(key, "InterfaceDevice") == 0) { @@ -1070,6 +1286,11 @@ static int lv_config(const char *key, const char *value) { } } + if (strcasecmp(key, "PersistentNotification") == 0) { + persistent_notification = IS_TRUE(value); + return 0; + } + /* Unrecognised option. */ return -1; } @@ -1177,7 +1398,7 @@ static void vcpu_pin_submit(virDomainPtr dom, int max_cpus, int vcpu, unsigned char *cpu_maps, int cpu_map_len) { for (int cpu = 0; cpu < max_cpus; ++cpu) { char type_instance[DATA_MAX_NAME_LEN]; - _Bool is_set = VIR_CPU_USABLE(cpu_maps, cpu_map_len, vcpu, cpu) ? 1 : 0; + bool is_set = VIR_CPU_USABLE(cpu_maps, cpu_map_len, vcpu, cpu); snprintf(type_instance, sizeof(type_instance), "vcpu_%d-cpu_%d", vcpu, cpu); submit(dom, "cpu_affinity", type_instance, &(value_t){.gauge = is_set}, 1); @@ -1223,6 +1444,15 @@ static int get_vcpu_stats(virDomainPtr domain, unsigned short nr_virt_cpu) { } #ifdef HAVE_DOM_REASON + +static void domain_state_submit(virDomainPtr dom, int state, int reason) { + value_t values[] = { + {.gauge = (gauge_t)state}, {.gauge = (gauge_t)reason}, + }; + + submit(dom, "domain_state", NULL, values, STATIC_ARRAY_SIZE(values)); +} + static int get_domain_state(virDomainPtr domain) { int domain_state = 0; int domain_reason = 0; @@ -1235,8 +1465,28 @@ static int get_domain_state(virDomainPtr domain) { } domain_state_submit(domain, domain_state, domain_reason); + return status; } + +#ifdef HAVE_LIST_ALL_DOMAINS +static int get_domain_state_notify(virDomainPtr domain) { + int domain_state = 0; + int domain_reason = 0; + + int status = virDomainGetState(domain, &domain_state, &domain_reason, 0); + if (status != 0) { + ERROR(PLUGIN_NAME " plugin: virDomainGetState failed with status %i.", + status); + return status; + } + + if (persistent_notification) + domain_state_submit_notif(domain, domain_state, domain_reason); + + return status; +} +#endif /* HAVE_LIST_ALL_DOMAINS */ #endif /* HAVE_DOM_REASON */ static int get_memory_stats(virDomainPtr domain) { @@ -1335,7 +1585,7 @@ static int get_block_stats(struct block_device *block_dev) { #define NM_ADD_STR_ITEMS(_items, _size) \ do { \ - for (int _i = 0; _i < _size; ++_i) { \ + for (size_t _i = 0; _i < _size; ++_i) { \ DEBUG(PLUGIN_NAME \ " plugin: Adding notification metadata name=%s value=%s", \ _items[_i].name, _items[_i].value); \ @@ -1360,7 +1610,7 @@ static int fs_info_notify(virDomainPtr domain, virDomainFSInfoPtr fs_info) { {.name = "name", .value = fs_info->name}, {.name = "fstype", .value = fs_info->fstype}}; - for (int i = 0; i < fs_info->ndevAlias; ++i) { + for (size_t i = 0; i < fs_info->ndevAlias; ++i) { fs_dev_alias[i].name = "devAlias"; fs_dev_alias[i].value = fs_info->devAlias[i]; } @@ -1488,10 +1738,6 @@ static int get_domain_metrics(domain_t *domain) { * We need to get it from virDomainGetState. */ GET_STATS(get_domain_state, "domain reason", domain->ptr); -#else - /* virDomainGetState is not available. Submit 0, which corresponds to - * unknown reason. */ - domain_state_submit(domain->ptr, info.di.state, 0); #endif } @@ -1530,6 +1776,7 @@ static int get_domain_metrics(domain_t *domain) { /* Update cached virDomainInfo. It has to be done after cpu_submit */ memcpy(&domain->info, &info.di, sizeof(domain->info)); + return 0; } @@ -1578,6 +1825,192 @@ static int get_if_dev_stats(struct interface_device *if_dev) { return 0; } +static int domain_lifecycle_event_cb(__attribute__((unused)) virConnectPtr con_, + virDomainPtr dom, int event, int detail, + __attribute__((unused)) void *opaque) { + int domain_state = map_domain_event_to_state(event); + int domain_reason = 0; /* 0 means UNKNOWN reason for any state */ +#ifdef HAVE_DOM_REASON + domain_reason = map_domain_event_detail_to_reason(event, detail); +#endif + domain_state_submit_notif(dom, domain_state, domain_reason); + + return 0; +} + +static int register_event_impl(void) { + if (virEventRegisterDefaultImpl() < 0) { + virErrorPtr err = virGetLastError(); + ERROR(PLUGIN_NAME + " plugin: error while event implementation registering: %s", + err && err->message ? err->message : "Unknown error"); + return -1; + } + + return 0; +} + +static void virt_notif_thread_set_active(virt_notif_thread_t *thread_data, + const bool active) { + assert(thread_data != NULL); + pthread_mutex_lock(&thread_data->active_mutex); + thread_data->is_active = active; + pthread_mutex_unlock(&thread_data->active_mutex); +} + +static bool virt_notif_thread_is_active(virt_notif_thread_t *thread_data) { + bool active = false; + + assert(thread_data != NULL); + pthread_mutex_lock(&thread_data->active_mutex); + active = thread_data->is_active; + pthread_mutex_unlock(&thread_data->active_mutex); + + return active; +} + +/* worker function running default event implementation */ +static void *event_loop_worker(void *arg) { + virt_notif_thread_t *thread_data = (virt_notif_thread_t *)arg; + + while (virt_notif_thread_is_active(thread_data)) { + if (virEventRunDefaultImpl() < 0) { + virErrorPtr err = virGetLastError(); + ERROR(PLUGIN_NAME " plugin: failed to run event loop: %s\n", + err && err->message ? err->message : "Unknown error"); + } + } + + return NULL; +} + +static int virt_notif_thread_init(virt_notif_thread_t *thread_data) { + int ret; + + assert(thread_data != NULL); + ret = pthread_mutex_init(&thread_data->active_mutex, NULL); + if (ret != 0) { + ERROR(PLUGIN_NAME ": Failed to initialize mutex, err %u", ret); + return ret; + } + + /** + * '0' and positive integers are meaningful ID's, therefore setting + * domain_event_cb_id to '-1' + */ + thread_data->domain_event_cb_id = -1; + pthread_mutex_lock(&thread_data->active_mutex); + thread_data->is_active = false; + pthread_mutex_unlock(&thread_data->active_mutex); + + return 0; +} + +/* register domain event callback and start event loop thread */ +static int start_event_loop(virt_notif_thread_t *thread_data) { + assert(thread_data != NULL); + thread_data->domain_event_cb_id = virConnectDomainEventRegisterAny( + conn, NULL, VIR_DOMAIN_EVENT_ID_LIFECYCLE, + VIR_DOMAIN_EVENT_CALLBACK(domain_lifecycle_event_cb), NULL, NULL); + if (thread_data->domain_event_cb_id == -1) { + ERROR(PLUGIN_NAME " plugin: error while callback registering"); + return -1; + } + + virt_notif_thread_set_active(thread_data, 1); + if (pthread_create(&thread_data->event_loop_tid, NULL, event_loop_worker, + thread_data)) { + ERROR(PLUGIN_NAME " plugin: failed event loop thread creation"); + virConnectDomainEventDeregisterAny(conn, thread_data->domain_event_cb_id); + return -1; + } + + return 0; +} + +/* stop event loop thread and deregister callback */ +static void stop_event_loop(virt_notif_thread_t *thread_data) { + /* stopping loop and de-registering event handler*/ + virt_notif_thread_set_active(thread_data, 0); + if (conn != NULL && thread_data->domain_event_cb_id != -1) + virConnectDomainEventDeregisterAny(conn, thread_data->domain_event_cb_id); + + if (pthread_join(notif_thread.event_loop_tid, NULL) != 0) + ERROR(PLUGIN_NAME " plugin: stopping notification thread failed"); +} + +static int persistent_domains_state_notification(void) { + int status = 0; + int n; +#ifdef HAVE_LIST_ALL_DOMAINS + virDomainPtr *domains = NULL; + n = virConnectListAllDomains(conn, &domains, + VIR_CONNECT_LIST_DOMAINS_PERSISTENT); + if (n < 0) { + VIRT_ERROR(conn, "reading list of persistent domains"); + status = -1; + } else { + DEBUG(PLUGIN_NAME " plugin: getting state of %i persistent domains", n); + /* Fetch each persistent domain's state and notify it */ + int n_notified = n; + for (int i = 0; i < n; ++i) { + status = get_domain_state_notify(domains[i]); + if (status != 0) { + n_notified--; + ERROR(PLUGIN_NAME " plugin: could not notify state of domain %s", + virDomainGetName(domains[i])); + } + virDomainFree(domains[i]); + } + + sfree(domains); + DEBUG(PLUGIN_NAME " plugin: notified state of %i persistent domains", + n_notified); + } +#else + n = virConnectNumOfDomains(conn); + if (n > 0) { + int *domids; + /* Get list of domains. */ + domids = calloc(n, sizeof(*domids)); + if (domids == NULL) { + ERROR(PLUGIN_NAME " plugin: calloc failed."); + return -1; + } + n = virConnectListDomains(conn, domids, n); + if (n < 0) { + VIRT_ERROR(conn, "reading list of domains"); + sfree(domids); + return -1; + } + /* Fetch info of each active domain and notify it */ + for (int i = 0; i < n; ++i) { + virDomainInfo info; + virDomainPtr dom = NULL; + dom = virDomainLookupByID(conn, domids[i]); + if (dom == NULL) { + VIRT_ERROR(conn, "virDomainLookupByID"); + /* Could be that the domain went away -- ignore it anyway. */ + continue; + } + status = virDomainGetInfo(dom, &info); + if (status == 0) + /* virDomainGetState is not available. Submit 0, which corresponds to + * unknown reason. */ + domain_state_submit_notif(dom, info.state, 0); + else + ERROR(PLUGIN_NAME " plugin: virDomainGetInfo failed with status %i.", + status); + + virDomainFree(dom); + } + sfree(domids); + } +#endif + + return status; +} + static int lv_read(user_data_t *ud) { time_t t; struct lv_read_instance *inst = NULL; @@ -1591,9 +2024,19 @@ static int lv_read(user_data_t *ud) { inst = ud->data; state = &inst->read_state; + bool reconnect = conn == NULL ? true : false; + /* event implementation must be registered before connection is opened */ if (inst->id == 0) { + if (!persistent_notification && reconnect) + if (register_event_impl() != 0) + return -1; + if (lv_connect() < 0) return -1; + + if (!persistent_notification && reconnect && conn != NULL) + if (start_event_loop(¬if_thread) != 0) + return -1; } time(&t); @@ -1602,32 +2045,53 @@ static int lv_read(user_data_t *ud) { if ((last_refresh == (time_t)0) || ((interval > 0) && ((last_refresh + interval) <= t))) { if (refresh_lists(inst) != 0) { - if (inst->id == 0) + if (inst->id == 0) { + if (!persistent_notification) + stop_event_loop(¬if_thread); lv_disconnect(); + } return -1; } last_refresh = t; } -#if 0 - for (int i = 0; i < nr_domains; ++i) - fprintf (stderr, "domain %s\n", virDomainGetName (state->domains[i].ptr)); - for (int i = 0; i < nr_block_devices; ++i) - fprintf (stderr, "block device %d %s:%s\n", - i, virDomainGetName (block_devices[i].dom), - block_devices[i].path); - for (int i = 0; i < nr_interface_devices; ++i) - fprintf (stderr, "interface device %d %s:%s\n", - i, virDomainGetName (interface_devices[i].dom), - interface_devices[i].path); + /* persistent domains state notifications are handled by instance 0 */ + if (inst->id == 0 && persistent_notification) { + int status = persistent_domains_state_notification(); + if (status != 0) + DEBUG(PLUGIN_NAME " plugin: persistent_domains_state_notifications " + "returned with status %i", + status); + } + +#if COLLECT_DEBUG + for (int i = 0; i < state->nr_domains; ++i) + DEBUG(PLUGIN_NAME " plugin: domain %s", + virDomainGetName(state->domains[i].ptr)); + for (int i = 0; i < state->nr_block_devices; ++i) + DEBUG(PLUGIN_NAME " plugin: block device %d %s:%s", i, + virDomainGetName(state->block_devices[i].dom), + state->block_devices[i].path); + for (int i = 0; i < state->nr_interface_devices; ++i) + DEBUG(PLUGIN_NAME " plugin: interface device %d %s:%s", i, + virDomainGetName(state->interface_devices[i].dom), + state->interface_devices[i].path); #endif /* Get domains' metrics */ for (int i = 0; i < state->nr_domains; ++i) { - int status = get_domain_metrics(&state->domains[i]); + domain_t *dom = &state->domains[i]; + int status = 0; + if (dom->active) + status = get_domain_metrics(dom); +#ifdef HAVE_DOM_REASON + else + status = get_domain_state(dom->ptr); +#endif + if (status != 0) ERROR(PLUGIN_NAME " failed to get metrics for domain=%s", - virDomainGetName(state->domains[i].ptr)); + virDomainGetName(dom->ptr)); } /* Get block device stats for each domain. */ @@ -1667,6 +2131,7 @@ static int lv_init_instance(size_t i, plugin_read_cb callback) { ud->free_func = NULL; INFO(PLUGIN_NAME " plugin: reader %s initialized", inst->tag); + return plugin_register_complex_read(NULL, inst->tag, callback, 0, ud); } @@ -1681,6 +2146,7 @@ static void lv_fini_instance(size_t i) { struct lv_read_state *state = &(inst->read_state); lv_clean_read_state(state); + INFO(PLUGIN_NAME " plugin: reader %s finalized", inst->tag); } @@ -1688,13 +2154,27 @@ static int lv_init(void) { if (virInitialize() != 0) return -1; + /* event implementation must be registered before connection is opened */ + if (!persistent_notification) + if (register_event_impl() != 0) + return -1; + if (lv_connect() != 0) return -1; + DEBUG(PLUGIN_NAME " plugin: starting event loop"); + + if (!persistent_notification) { + virt_notif_thread_init(¬if_thread); + if (start_event_loop(¬if_thread) != 0) + return -1; + } + DEBUG(PLUGIN_NAME " plugin: starting %i instances", nr_instances); for (int i = 0; i < nr_instances; ++i) - lv_init_instance(i, lv_read); + if (lv_init_instance(i, lv_read) != 0) + return -1; return 0; } @@ -1793,224 +2273,247 @@ static int lv_instance_include_domain(struct lv_read_instance *inst, return 0; } -/* - virConnectListAllDomains() appeared in 0.10.2 - Note that LIBVIR_CHECK_VERSION appeared a year later, so - in some systems which actually have virConnectListAllDomains() - we can't detect this. - */ -#ifdef LIBVIR_CHECK_VERSION -#if LIBVIR_CHECK_VERSION(0, 10, 2) -#define HAVE_LIST_ALL_DOMAINS 1 -#endif -#endif - static int refresh_lists(struct lv_read_instance *inst) { struct lv_read_state *state = &inst->read_state; int n; +#ifndef HAVE_LIST_ALL_DOMAINS n = virConnectNumOfDomains(conn); if (n < 0) { VIRT_ERROR(conn, "reading number of domains"); return -1; } +#endif lv_clean_read_state(state); - if (n > 0) { +#ifndef HAVE_LIST_ALL_DOMAINS + if (n == 0) + goto end; +#endif + #ifdef HAVE_LIST_ALL_DOMAINS - virDomainPtr *domains; - n = virConnectListAllDomains(conn, &domains, - VIR_CONNECT_LIST_DOMAINS_ACTIVE); + virDomainPtr *domains, *domains_inactive; + int m = virConnectListAllDomains(conn, &domains_inactive, + VIR_CONNECT_LIST_DOMAINS_INACTIVE); + n = virConnectListAllDomains(conn, &domains, VIR_CONNECT_LIST_DOMAINS_ACTIVE); #else - int *domids; + int *domids; - /* Get list of domains. */ - domids = malloc(sizeof(*domids) * n); - if (domids == NULL) { - ERROR(PLUGIN_NAME " plugin: malloc failed."); - return -1; - } + /* Get list of domains. */ + domids = calloc(n, sizeof(*domids)); + if (domids == NULL) { + ERROR(PLUGIN_NAME " plugin: calloc failed."); + return -1; + } - n = virConnectListDomains(conn, domids, n); + n = virConnectListDomains(conn, domids, n); #endif - if (n < 0) { - VIRT_ERROR(conn, "reading list of domains"); + if (n < 0) { + VIRT_ERROR(conn, "reading list of domains"); #ifndef HAVE_LIST_ALL_DOMAINS - sfree(domids); + sfree(domids); +#else + for (int i = 0; i < m; ++i) + virDomainFree(domains_inactive[i]); + sfree(domains_inactive); #endif - return -1; + return -1; + } + +#ifdef HAVE_LIST_ALL_DOMAINS + for (int i = 0; i < m; ++i) + if (add_domain(state, domains_inactive[i], 0) < 0) { + ERROR(PLUGIN_NAME " plugin: malloc failed."); + virDomainFree(domains_inactive[i]); + domains_inactive[i] = NULL; + continue; } +#endif - /* Fetch each domain and add it to the list, unless ignore. */ - for (int i = 0; i < n; ++i) { - const char *name; - char *xml = NULL; - xmlDocPtr xml_doc = NULL; - xmlXPathContextPtr xpath_ctx = NULL; - xmlXPathObjectPtr xpath_obj = NULL; - char tag[PARTITION_TAG_MAX_LEN] = {'\0'}; - virDomainInfo info; - int status; + /* Fetch each domain and add it to the list, unless ignore. */ + for (int i = 0; i < n; ++i) { + const char *name; + char *xml = NULL; + xmlDocPtr xml_doc = NULL; + xmlXPathContextPtr xpath_ctx = NULL; + xmlXPathObjectPtr xpath_obj = NULL; + char tag[PARTITION_TAG_MAX_LEN] = {'\0'}; + virDomainInfo info; + int status; #ifdef HAVE_LIST_ALL_DOMAINS - virDomainPtr dom = domains[i]; + virDomainPtr dom = domains[i]; #else - virDomainPtr dom = NULL; - dom = virDomainLookupByID(conn, domids[i]); - if (dom == NULL) { - VIRT_ERROR(conn, "virDomainLookupByID"); - /* Could be that the domain went away -- ignore it anyway. */ - continue; - } + virDomainPtr dom = NULL; + dom = virDomainLookupByID(conn, domids[i]); + if (dom == NULL) { + VIRT_ERROR(conn, "virDomainLookupByID"); + /* Could be that the domain went away -- ignore it anyway. */ + continue; + } #endif - name = virDomainGetName(dom); - if (name == NULL) { - VIRT_ERROR(conn, "virDomainGetName"); - goto cont; - } + if (add_domain(state, dom, 1) < 0) { + /* + * When domain is already tracked, then there is + * no problem with memory handling (will be freed + * with the rest of domains cached data) + * But in case of error like this (error occurred + * before adding domain to track) we have to take + * care it ourselves and call virDomainFree + */ + ERROR(PLUGIN_NAME " plugin: malloc failed."); + virDomainFree(dom); + goto cont; + } - status = virDomainGetInfo(dom, &info); - if (status != 0) { - ERROR(PLUGIN_NAME " plugin: virDomainGetInfo failed with status %i.", - status); - continue; - } + name = virDomainGetName(dom); + if (name == NULL) { + VIRT_ERROR(conn, "virDomainGetName"); + goto cont; + } - if (info.state != VIR_DOMAIN_RUNNING) { - DEBUG(PLUGIN_NAME " plugin: skipping inactive domain %s", name); - continue; - } + status = virDomainGetInfo(dom, &info); + if (status != 0) { + ERROR(PLUGIN_NAME " plugin: virDomainGetInfo failed with status %i.", + status); + continue; + } - if (il_domains && ignorelist_match(il_domains, name) != 0) - goto cont; + if (info.state != VIR_DOMAIN_RUNNING) { + DEBUG(PLUGIN_NAME " plugin: skipping inactive domain %s", name); + continue; + } - /* Get a list of devices for this domain. */ - xml = virDomainGetXMLDesc(dom, 0); - if (!xml) { - VIRT_ERROR(conn, "virDomainGetXMLDesc"); - goto cont; - } + if (il_domains && ignorelist_match(il_domains, name) != 0) + goto cont; - /* Yuck, XML. Parse out the devices. */ - xml_doc = xmlReadDoc((xmlChar *)xml, NULL, NULL, XML_PARSE_NONET); - if (xml_doc == NULL) { - VIRT_ERROR(conn, "xmlReadDoc"); - goto cont; - } + /* Get a list of devices for this domain. */ + xml = virDomainGetXMLDesc(dom, 0); + if (!xml) { + VIRT_ERROR(conn, "virDomainGetXMLDesc"); + goto cont; + } - xpath_ctx = xmlXPathNewContext(xml_doc); + /* Yuck, XML. Parse out the devices. */ + xml_doc = xmlReadDoc((xmlChar *)xml, NULL, NULL, XML_PARSE_NONET); + if (xml_doc == NULL) { + VIRT_ERROR(conn, "xmlReadDoc"); + goto cont; + } - if (lv_domain_get_tag(xpath_ctx, name, tag) < 0) { - ERROR(PLUGIN_NAME " plugin: lv_domain_get_tag failed."); - goto cont; - } + xpath_ctx = xmlXPathNewContext(xml_doc); - if (!lv_instance_include_domain(inst, name, tag)) - goto cont; + if (lv_domain_get_tag(xpath_ctx, name, tag) < 0) { + ERROR(PLUGIN_NAME " plugin: lv_domain_get_tag failed."); + goto cont; + } - if (add_domain(state, dom) < 0) { - ERROR(PLUGIN_NAME " plugin: malloc failed."); - goto cont; - } + if (!lv_instance_include_domain(inst, name, tag)) + goto cont; - /* Block devices. */ - const char *bd_xmlpath = "/domain/devices/disk/target[@dev]"; - if (blockdevice_format == source) - bd_xmlpath = "/domain/devices/disk/source[@dev]"; - xpath_obj = xmlXPathEval((const xmlChar *)bd_xmlpath, xpath_ctx); + /* Block devices. */ + const char *bd_xmlpath = "/domain/devices/disk/target[@dev]"; + if (blockdevice_format == source) + bd_xmlpath = "/domain/devices/disk/source[@dev]"; + xpath_obj = xmlXPathEval((const xmlChar *)bd_xmlpath, xpath_ctx); - if (xpath_obj == NULL || xpath_obj->type != XPATH_NODESET || - xpath_obj->nodesetval == NULL) - goto cont; + if (xpath_obj == NULL || xpath_obj->type != XPATH_NODESET || + xpath_obj->nodesetval == NULL) + goto cont; - for (int j = 0; j < xpath_obj->nodesetval->nodeNr; ++j) { - xmlNodePtr node; - char *path = NULL; + for (int j = 0; j < xpath_obj->nodesetval->nodeNr; ++j) { + xmlNodePtr node; + char *path = NULL; - node = xpath_obj->nodesetval->nodeTab[j]; - if (!node) - continue; - path = (char *)xmlGetProp(node, (xmlChar *)"dev"); - if (!path) - continue; + node = xpath_obj->nodesetval->nodeTab[j]; + if (!node) + continue; + path = (char *)xmlGetProp(node, (xmlChar *)"dev"); + if (!path) + continue; - if (il_block_devices && - ignore_device_match(il_block_devices, name, path) != 0) - goto cont2; + if (il_block_devices && + ignore_device_match(il_block_devices, name, path) != 0) + goto cont2; - add_block_device(state, dom, path); - cont2: - if (path) - xmlFree(path); - } - xmlXPathFreeObject(xpath_obj); + add_block_device(state, dom, path); + cont2: + if (path) + xmlFree(path); + } + xmlXPathFreeObject(xpath_obj); + + /* Network interfaces. */ + xpath_obj = xmlXPathEval( + (xmlChar *)"/domain/devices/interface[target[@dev]]", xpath_ctx); + if (xpath_obj == NULL || xpath_obj->type != XPATH_NODESET || + xpath_obj->nodesetval == NULL) + goto cont; - /* Network interfaces. */ - xpath_obj = xmlXPathEval( - (xmlChar *)"/domain/devices/interface[target[@dev]]", xpath_ctx); - if (xpath_obj == NULL || xpath_obj->type != XPATH_NODESET || - xpath_obj->nodesetval == NULL) - goto cont; + xmlNodeSetPtr xml_interfaces = xpath_obj->nodesetval; - xmlNodeSetPtr xml_interfaces = xpath_obj->nodesetval; + for (int j = 0; j < xml_interfaces->nodeNr; ++j) { + char *path = NULL; + char *address = NULL; + xmlNodePtr xml_interface; - for (int j = 0; j < xml_interfaces->nodeNr; ++j) { - char *path = NULL; - char *address = NULL; - xmlNodePtr xml_interface; + xml_interface = xml_interfaces->nodeTab[j]; + if (!xml_interface) + continue; - xml_interface = xml_interfaces->nodeTab[j]; - if (!xml_interface) + for (xmlNodePtr child = xml_interface->children; child; + child = child->next) { + if (child->type != XML_ELEMENT_NODE) continue; - for (xmlNodePtr child = xml_interface->children; child; - child = child->next) { - if (child->type != XML_ELEMENT_NODE) + if (xmlStrEqual(child->name, (const xmlChar *)"target")) { + path = (char *)xmlGetProp(child, (const xmlChar *)"dev"); + if (!path) + continue; + } else if (xmlStrEqual(child->name, (const xmlChar *)"mac")) { + address = (char *)xmlGetProp(child, (const xmlChar *)"address"); + if (!address) continue; - - if (xmlStrEqual(child->name, (const xmlChar *)"target")) { - path = (char *)xmlGetProp(child, (const xmlChar *)"dev"); - if (!path) - continue; - } else if (xmlStrEqual(child->name, (const xmlChar *)"mac")) { - address = (char *)xmlGetProp(child, (const xmlChar *)"address"); - if (!address) - continue; - } } - - if (il_interface_devices && - (ignore_device_match(il_interface_devices, name, path) != 0 || - ignore_device_match(il_interface_devices, name, address) != 0)) - goto cont3; - - add_interface_device(state, dom, path, address, j + 1); - cont3: - if (path) - xmlFree(path); - if (address) - xmlFree(address); } - cont: - if (xpath_obj) - xmlXPathFreeObject(xpath_obj); - if (xpath_ctx) - xmlXPathFreeContext(xpath_ctx); - if (xml_doc) - xmlFreeDoc(xml_doc); - sfree(xml); + if (il_interface_devices && + (ignore_device_match(il_interface_devices, name, path) != 0 || + ignore_device_match(il_interface_devices, name, address) != 0)) + goto cont3; + + add_interface_device(state, dom, path, address, j + 1); + cont3: + if (path) + xmlFree(path); + if (address) + xmlFree(address); } + cont: + if (xpath_obj) + xmlXPathFreeObject(xpath_obj); + if (xpath_ctx) + xmlXPathFreeContext(xpath_ctx); + if (xml_doc) + xmlFreeDoc(xml_doc); + sfree(xml); + } + #ifdef HAVE_LIST_ALL_DOMAINS - sfree(domains); + /* NOTE: domains_active and domains_inactive data will be cleared during + refresh of all domains (inside lv_clean_read_state function) so we need + to free here only allocated arrays */ + sfree(domains); + sfree(domains_inactive); #else - sfree(domids); + sfree(domids); + +end: #endif - } DEBUG(PLUGIN_NAME " plugin#%s: refreshing" " domains=%i block_devices=%i iface_devices=%i", @@ -2030,7 +2533,8 @@ static void free_domains(struct lv_read_state *state) { state->nr_domains = 0; } -static int add_domain(struct lv_read_state *state, virDomainPtr dom) { +static int add_domain(struct lv_read_state *state, virDomainPtr dom, + bool active) { domain_t *new_ptr; int new_size = sizeof(state->domains[0]) * (state->nr_domains + 1); @@ -2044,6 +2548,7 @@ static int add_domain(struct lv_read_state *state, virDomainPtr dom) { state->domains = new_ptr; state->domains[state->nr_domains].ptr = dom; + state->domains[state->nr_domains].active = active; memset(&state->domains[state->nr_domains].info, 0, sizeof(state->domains[state->nr_domains].info)); @@ -2105,7 +2610,7 @@ static int add_interface_device(struct lv_read_state *state, virDomainPtr dom, struct interface_device *new_ptr; int new_size = sizeof(state->interface_devices[0]) * (state->nr_interface_devices + 1); - char *path_copy, *address_copy, number_string[15]; + char *path_copy, *address_copy, number_string[21]; if ((path == NULL) || (address == NULL)) return EINVAL; @@ -2144,12 +2649,12 @@ static int add_interface_device(struct lv_read_state *state, virDomainPtr dom, static int ignore_device_match(ignorelist_t *il, const char *domname, const char *devpath) { char *name; - int n, r; + int r; if ((domname == NULL) || (devpath == NULL)) return 0; - n = strlen(domname) + strlen(devpath) + 2; + size_t n = strlen(domname) + strlen(devpath) + 2; name = malloc(n); if (name == NULL) { ERROR(PLUGIN_NAME " plugin: malloc failed."); @@ -2166,6 +2671,11 @@ static int lv_shutdown(void) { lv_fini_instance(i); } + DEBUG(PLUGIN_NAME " plugin: stopping event loop"); + + if (!persistent_notification) + stop_event_loop(¬if_thread); + lv_disconnect(); ignorelist_free(il_domains); diff --git a/src/virt_test.c b/src/virt_test.c index 489a367d..458facaf 100644 --- a/src/virt_test.c +++ b/src/virt_test.c @@ -25,183 +25,71 @@ #include "testing.h" #include "virt.c" /* sic */ -#include +static virDomainPtr *domains; +static int nr_domains; -static const char minimal_xml[] = - "" - "" - "" - " " - ""; - -static const char minimal_metadata_xml[] = - "" - "" - "" - " " - " virt-0" - " " - ""; - -struct xml_state { - xmlDocPtr xml_doc; - xmlXPathContextPtr xpath_ctx; - xmlXPathObjectPtr xpath_obj; - char tag[PARTITION_TAG_MAX_LEN]; -}; - -static int init_state(struct xml_state *st, const char *xml) { - memset(st, 0, sizeof(*st)); - - st->xml_doc = xmlReadDoc((const xmlChar *)xml, NULL, NULL, XML_PARSE_NONET); - if (st->xml_doc == NULL) { - return -1; - } - st->xpath_ctx = xmlXPathNewContext(st->xml_doc); - if (st->xpath_ctx == NULL) { +static int setup(void) { + if (virInitialize() != 0) { + printf("ERROR: virInitialize() != 0\n"); return -1; } - return 0; -} -static void fini_state(struct xml_state *st) { - if (st->xpath_ctx) { - xmlXPathFreeContext(st->xpath_ctx); - st->xpath_ctx = NULL; - } - if (st->xml_doc) { - xmlFreeDoc(st->xml_doc); - st->xml_doc = NULL; + conn = virConnectOpen("test:///default"); + if (conn == NULL) { + printf("ERROR: virConnectOpen == NULL\n"); + return -1; } -} - -#define TAG "virt-0" - -DEF_TEST(lv_domain_get_tag_no_metadata_xml) { - int err; - struct xml_state st; - err = init_state(&st, minimal_xml); - EXPECT_EQ_INT(0, err); - - err = lv_domain_get_tag(st.xpath_ctx, "test", st.tag); - - EXPECT_EQ_INT(0, err); - EXPECT_EQ_STR("", st.tag); - - fini_state(&st); - return 0; -} - -DEF_TEST(lv_domain_get_tag_valid_xml) { - int err; - struct xml_state st; - err = init_state(&st, minimal_metadata_xml); - EXPECT_EQ_INT(0, err); - - err = lv_domain_get_tag(st.xpath_ctx, "test", st.tag); - - EXPECT_EQ_INT(0, err); - EXPECT_EQ_STR(TAG, st.tag); - - return 0; -} - -DEF_TEST(lv_default_instance_include_domain_without_tag) { - struct lv_read_instance *inst = NULL; - int ret; - - ret = lv_init_instance(0, lv_read); - inst = &(lv_read_user_data[0].inst); - EXPECT_EQ_STR("virt-0", inst->tag); - - ret = lv_instance_include_domain(inst, "testing", ""); - EXPECT_EQ_INT(1, ret); - - lv_fini_instance(0); - return 0; -} - -DEF_TEST(lv_regular_instance_skip_domain_without_tag) { - struct lv_read_instance *inst = NULL; - int ret; - - ret = lv_init_instance(1, lv_read); - inst = &(lv_read_user_data[1].inst); - EXPECT_EQ_STR("virt-1", inst->tag); - ret = lv_instance_include_domain(inst, "testing", ""); - EXPECT_EQ_INT(0, ret); - - lv_fini_instance(0); return 0; } -DEF_TEST(lv_include_domain_matching_tags) { - struct lv_read_instance *inst = NULL; - int ret; - - ret = lv_init_instance(0, lv_read); - inst = &(lv_read_user_data[0].inst); - EXPECT_EQ_STR("virt-0", inst->tag); - - ret = lv_instance_include_domain(inst, "testing", "virt-0"); - EXPECT_EQ_INT(1, ret); - - ret = lv_init_instance(1, lv_read); - inst = &(lv_read_user_data[1].inst); - EXPECT_EQ_STR("virt-1", inst->tag); - - ret = lv_instance_include_domain(inst, "testing", "virt-1"); - EXPECT_EQ_INT(1, ret); +static int teardown(void) { + if (domains) { + for (int i = 0; i < nr_domains; ++i) + virDomainFree(domains[i]); + sfree(domains); + } + nr_domains = 0; + if (conn != NULL) + virConnectClose(conn); - lv_fini_instance(0); - lv_fini_instance(1); return 0; } -DEF_TEST(lv_default_instance_include_domain_with_unknown_tag) { - struct lv_read_instance *inst = NULL; - int ret; - - ret = lv_init_instance(0, lv_read); - inst = &(lv_read_user_data[0].inst); - EXPECT_EQ_STR("virt-0", inst->tag); - - ret = lv_instance_include_domain(inst, "testing", "unknownFormat-tag"); - EXPECT_EQ_INT(1, ret); +#ifdef HAVE_LIST_ALL_DOMAINS +DEF_TEST(get_domain_state_notify) { + if (setup() == 0) { + nr_domains = virConnectListAllDomains(conn, &domains, + VIR_CONNECT_LIST_DOMAINS_PERSISTENT); + if (nr_domains <= 0) { + printf("ERROR: virConnectListAllDomains: nr_domains <= 0\n"); + return -1; + } + + int ret = get_domain_state_notify(domains[0]); + EXPECT_EQ_INT(0, ret); + } + teardown(); - lv_fini_instance(0); return 0; } +#endif -DEF_TEST(lv_regular_instance_skip_domain_with_unknown_tag) { - struct lv_read_instance *inst = NULL; - int ret; - - ret = lv_init_instance(1, lv_read); - inst = &(lv_read_user_data[1].inst); - EXPECT_EQ_STR("virt-1", inst->tag); - - ret = lv_instance_include_domain(inst, "testing", "unknownFormat-tag"); - EXPECT_EQ_INT(0, ret); +DEF_TEST(persistent_domains_state_notification) { + if (setup() == 0) { + int ret = persistent_domains_state_notification(); + EXPECT_EQ_INT(0, ret); + } + teardown(); - lv_fini_instance(0); return 0; } -#undef TAG int main(void) { - RUN_TEST(lv_domain_get_tag_no_metadata_xml); - RUN_TEST(lv_domain_get_tag_valid_xml); - - RUN_TEST(lv_default_instance_include_domain_without_tag); - RUN_TEST(lv_regular_instance_skip_domain_without_tag); - RUN_TEST(lv_include_domain_matching_tags); - RUN_TEST(lv_default_instance_include_domain_with_unknown_tag); - RUN_TEST(lv_regular_instance_skip_domain_with_unknown_tag); +#ifdef HAVE_LIST_ALL_DOMAINS + RUN_TEST(get_domain_state_notify); +#endif + RUN_TEST(persistent_domains_state_notification); END_TEST; } - -/* vim: set sw=2 sts=2 et : */ diff --git a/src/vmem.c b/src/vmem.c index 95cfbaf1..c7229756 100644 --- a/src/vmem.c +++ b/src/vmem.c @@ -33,7 +33,7 @@ static const char *config_keys[] = {"Verbose"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); -static int verbose_output = 0; +static int verbose_output; /* #endif KERNEL_LINUX */ #else diff --git a/src/vserver.c b/src/vserver.c index f15bb3b5..3c6d58cd 100644 --- a/src/vserver.c +++ b/src/vserver.c @@ -42,7 +42,7 @@ #error "No applicable input method." #endif -static int pagesize = 0; +static int pagesize; static int vserver_init(void) { /* XXX Should we check for getpagesize () in configure? diff --git a/src/wireless.c b/src/wireless.c index 31aba0a5..2e597f37 100644 --- a/src/wireless.c +++ b/src/wireless.c @@ -86,7 +86,7 @@ static int wireless_read(void) { int numfields; int devices_found; - int len; + size_t len; /* there are a variety of names for the wireless device */ if ((fh = fopen(WIRELESS_PROC_FILE, "r")) == NULL) { diff --git a/src/write_graphite.c b/src/write_graphite.c index b39448ff..099c62bb 100644 --- a/src/write_graphite.c +++ b/src/write_graphite.c @@ -65,7 +65,7 @@ #endif #ifndef WG_DEFAULT_LOG_SEND_ERRORS -#define WG_DEFAULT_LOG_SEND_ERRORS 1 +#define WG_DEFAULT_LOG_SEND_ERRORS true #endif #ifndef WG_DEFAULT_ESCAPE @@ -92,7 +92,7 @@ struct wg_callback { char *node; char *service; char *protocol; - _Bool log_send_errors; + bool log_send_errors; char *prefix; char *postfix; char escape_char; @@ -111,7 +111,7 @@ struct wg_callback { /* Force reconnect useful for load balanced environments */ cdtime_t last_reconnect_time; cdtime_t reconnect_interval; - _Bool reconnect_interval_reached; + bool reconnect_interval_reached; }; /* wg_force_reconnect_check closes cb->sock_fd when it was open for longer @@ -131,7 +131,7 @@ static void wg_force_reconnect_check(struct wg_callback *cb) { close(cb->sock_fd); cb->sock_fd = -1; cb->last_reconnect_time = now; - cb->reconnect_interval_reached = 1; + cb->reconnect_interval_reached = true; INFO("write_graphite plugin: Connection closed after %.3f seconds.", CDTIME_T_TO_DOUBLE(now - cb->last_reconnect_time)); @@ -274,7 +274,7 @@ static int wg_callback_init(struct wg_callback *cb) { if (!cb->reconnect_interval_reached || (cb->send_buf_free == 0)) wg_reset_buffer(cb); else - cb->reconnect_interval_reached = 0; + cb->reconnect_interval_reached = false; return 0; } @@ -466,7 +466,7 @@ static int wg_config_node(oconfig_item_t *ci) { cb->protocol = strdup(WG_DEFAULT_PROTOCOL); cb->last_reconnect_time = cdtime(); cb->reconnect_interval = 0; - cb->reconnect_interval_reached = 0; + cb->reconnect_interval_reached = false; cb->log_send_errors = WG_DEFAULT_LOG_SEND_ERRORS; cb->prefix = NULL; cb->postfix = NULL; diff --git a/src/write_http.c b/src/write_http.c index 024dccc1..ad0cb5e4 100644 --- a/src/write_http.c +++ b/src/write_http.c @@ -50,16 +50,16 @@ struct wh_callback_s { char *user; char *pass; char *credentials; - _Bool verify_peer; - _Bool verify_host; + bool verify_peer; + bool verify_host; char *cacert; char *capath; char *clientkey; char *clientcert; char *clientkeypass; long sslversion; - _Bool store_rates; - _Bool log_http_error; + bool store_rates; + bool log_http_error; int low_speed_limit; time_t low_speed_time; int timeout; @@ -68,8 +68,8 @@ struct wh_callback_s { #define WH_FORMAT_JSON 1 #define WH_FORMAT_KAIROSDB 2 int format; - _Bool send_metrics; - _Bool send_notifications; + bool send_metrics; + bool send_notifications; CURL *curl; struct curl_slist *headers; @@ -624,16 +624,16 @@ static int wh_config_node(oconfig_item_t *ci) /* {{{ */ ERROR("write_http plugin: calloc failed."); return -1; } - cb->verify_peer = 1; - cb->verify_host = 1; + cb->verify_peer = true; + cb->verify_host = true; cb->format = WH_FORMAT_COMMAND; cb->sslversion = CURL_SSLVERSION_DEFAULT; cb->low_speed_limit = 0; cb->timeout = 0; - cb->log_http_error = 0; + cb->log_http_error = false; cb->headers = NULL; - cb->send_metrics = 1; - cb->send_notifications = 0; + cb->send_metrics = true; + cb->send_notifications = false; cb->data_ttl = 0; cb->metrics_prefix = strdup(WRITE_HTTP_DEFAULT_PREFIX); diff --git a/src/write_kafka.c b/src/write_kafka.c index 2baaf0e5..c120d15d 100644 --- a/src/write_kafka.c +++ b/src/write_kafka.c @@ -43,7 +43,7 @@ struct kafka_topic_context { #define KAFKA_FORMAT_GRAPHITE 2 uint8_t format; unsigned int graphite_flags; - _Bool store_rates; + bool store_rates; rd_kafka_topic_conf_t *conf; rd_kafka_topic_t *topic; rd_kafka_conf_t *kafka_conf; @@ -273,7 +273,7 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, } tctx->escape_char = '.'; - tctx->store_rates = 1; + tctx->store_rates = true; tctx->format = KAFKA_FORMAT_JSON; tctx->key = NULL; diff --git a/src/write_log.c b/src/write_log.c index fdc99ef3..52ad6104 100644 --- a/src/write_log.c +++ b/src/write_log.c @@ -96,7 +96,7 @@ static int wl_write(const data_set_t *ds, const value_list_t *vl, static int wl_config(oconfig_item_t *ci) /* {{{ */ { - _Bool format_seen = 0; + bool format_seen = false; for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; @@ -110,7 +110,7 @@ static int wl_config(oconfig_item_t *ci) /* {{{ */ if (format_seen) { WARNING("write_log plugin: Redefining option `%s'.", child->key); } - format_seen = 1; + format_seen = true; if (strcasecmp("Graphite", str) == 0) wl_format = WL_FORMAT_GRAPHITE; diff --git a/src/write_mongodb.c b/src/write_mongodb.c index a6b39d30..9cddc916 100644 --- a/src/write_mongodb.c +++ b/src/write_mongodb.c @@ -50,8 +50,8 @@ struct wm_node_s { char *user; char *passwd; - _Bool store_rates; - _Bool connected; + bool store_rates; + bool connected; mongoc_client_t *client; mongoc_database_t *database; @@ -63,7 +63,7 @@ typedef struct wm_node_s wm_node_t; * Functions */ static bson_t *wm_create_bson(const data_set_t *ds, /* {{{ */ - const value_list_t *vl, _Bool store_rates) { + const value_list_t *vl, bool store_rates) { bson_t *ret; bson_t subarray; gauge_t *rates; @@ -170,7 +170,7 @@ static int wm_initialize(wm_node_t *node) /* {{{ */ "authentication string."); mongoc_client_destroy(node->client); node->client = NULL; - node->connected = 0; + node->connected = false; return -1; } @@ -179,7 +179,7 @@ static int wm_initialize(wm_node_t *node) /* {{{ */ ERROR("write_mongodb plugin: Authenticating to [%s]:%d for database " "\"%s\" as user \"%s\" failed.", node->host, node->port, node->db, node->user); - node->connected = 0; + node->connected = false; sfree(uri); return -1; } @@ -190,7 +190,7 @@ static int wm_initialize(wm_node_t *node) /* {{{ */ "authentication string."); mongoc_client_destroy(node->client); node->client = NULL; - node->connected = 0; + node->connected = false; return -1; } @@ -198,7 +198,7 @@ static int wm_initialize(wm_node_t *node) /* {{{ */ if (!node->client) { ERROR("write_mongodb plugin: Connecting to [%s]:%d failed.", node->host, node->port); - node->connected = 0; + node->connected = false; sfree(uri); return -1; } @@ -210,11 +210,11 @@ static int wm_initialize(wm_node_t *node) /* {{{ */ ERROR("write_mongodb plugin: error creating/getting database"); mongoc_client_destroy(node->client); node->client = NULL; - node->connected = 0; + node->connected = false; return -1; } - node->connected = 1; + node->connected = true; return 0; } /* }}} int wm_initialize */ @@ -248,7 +248,7 @@ static int wm_write(const data_set_t *ds, /* {{{ */ mongoc_client_destroy(node->client); node->database = NULL; node->client = NULL; - node->connected = 0; + node->connected = false; pthread_mutex_unlock(&node->lock); bson_destroy(bson_record); return -1; @@ -263,7 +263,7 @@ static int wm_write(const data_set_t *ds, /* {{{ */ mongoc_client_destroy(node->client); node->database = NULL; node->client = NULL; - node->connected = 0; + node->connected = false; pthread_mutex_unlock(&node->lock); bson_destroy(bson_record); mongoc_collection_destroy(collection); @@ -291,7 +291,7 @@ static void wm_config_free(void *ptr) /* {{{ */ mongoc_client_destroy(node->client); node->database = NULL; node->client = NULL; - node->connected = 0; + node->connected = false; sfree(node->host); sfree(node); @@ -312,7 +312,7 @@ static int wm_config_node(oconfig_item_t *ci) /* {{{ */ return ENOMEM; } node->port = MONGOC_DEFAULT_PORT; - node->store_rates = 1; + node->store_rates = true; pthread_mutex_init(&node->lock, /* attr = */ NULL); status = cf_util_get_string_buffer(ci, node->name, sizeof(node->name)); diff --git a/src/write_prometheus.c b/src/write_prometheus.c index 26b0b4d4..3b22922a 100644 --- a/src/write_prometheus.c +++ b/src/write_prometheus.c @@ -244,9 +244,8 @@ static int http_handler(void *cls, struct MHD_Connection *connection, char const *accept = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_ACCEPT); - _Bool want_proto = - (accept != NULL) && - (strstr(accept, "application/vnd.google.protobuf") != NULL); + bool want_proto = (accept != NULL) && + (strstr(accept, "application/vnd.google.protobuf") != NULL); uint8_t scratch[4096] = {0}; ProtobufCBufferSimple simple = PROTOBUF_C_BUFFER_SIMPLE_INIT(scratch); @@ -689,7 +688,7 @@ static char *metric_family_name(data_set_t const *ds, value_list_t const *vl, * necessary. */ static Io__Prometheus__Client__MetricFamily * metric_family_get(data_set_t const *ds, value_list_t const *vl, size_t ds_index, - _Bool allocate) { + bool allocate) { char *name = metric_family_name(ds, vl, ds_index); if (name == NULL) { ERROR("write_prometheus plugin: Allocating metric family name failed."); @@ -885,7 +884,7 @@ static int prom_write(data_set_t const *ds, value_list_t const *vl, for (size_t i = 0; i < ds->ds_num; i++) { Io__Prometheus__Client__MetricFamily *fam = - metric_family_get(ds, vl, i, /* allocate = */ 1); + metric_family_get(ds, vl, i, /* allocate = */ true); if (fam == NULL) continue; @@ -912,7 +911,7 @@ static int prom_missing(value_list_t const *vl, for (size_t i = 0; i < ds->ds_num; i++) { Io__Prometheus__Client__MetricFamily *fam = - metric_family_get(ds, vl, i, /* allocate = */ 0); + metric_family_get(ds, vl, i, /* allocate = */ false); if (fam == NULL) continue; diff --git a/src/write_redis.c b/src/write_redis.c index 7dd5029c..72cb5946 100644 --- a/src/write_redis.c +++ b/src/write_redis.c @@ -46,7 +46,7 @@ struct wr_node_s { int database; int max_set_size; int max_set_duration; - _Bool store_rates; + bool store_rates; redisContext *conn; pthread_mutex_t lock; @@ -129,10 +129,10 @@ static int wr_write(const data_set_t *ds, /* {{{ */ if (node->max_set_duration > 0) { /* * remove element, scored less than 'current-max_set_duration' - * '(%d' indicates 'less than' in redis CLI. + * '(...' indicates 'less than' in redis CLI. */ - rr = redisCommand(node->conn, "ZREMRANGEBYSCORE %s -1 (%d", key, - (time - node->max_set_duration) + 1); + rr = redisCommand(node->conn, "ZREMRANGEBYSCORE %s -1 (%.9f", key, + (CDTIME_T_TO_DOUBLE(vl->time) - node->max_set_duration)); if (rr == NULL) WARNING("ZREMRANGEBYSCORE command error. key:%s message:%s", key, node->conn->errstr); @@ -184,14 +184,14 @@ static int wr_config_node(oconfig_item_t *ci) /* {{{ */ return ENOMEM; node->host = NULL; node->port = 0; - node->timeout.tv_sec = 0; - node->timeout.tv_usec = 1000; + node->timeout.tv_sec = 1; + node->timeout.tv_usec = 0; node->conn = NULL; node->prefix = NULL; node->database = 0; node->max_set_size = -1; node->max_set_duration = -1; - node->store_rates = 1; + node->store_rates = true; pthread_mutex_init(&node->lock, /* attr = */ NULL); status = cf_util_get_string_buffer(ci, node->name, sizeof(node->name)); @@ -213,8 +213,11 @@ static int wr_config_node(oconfig_item_t *ci) /* {{{ */ } } else if (strcasecmp("Timeout", child->key) == 0) { status = cf_util_get_int(child, &timeout); - if (status == 0) - node->timeout.tv_usec = timeout; + if (status == 0) { + node->timeout.tv_usec = timeout * 1000; + node->timeout.tv_sec = node->timeout.tv_usec / 1000000L; + node->timeout.tv_usec %= 1000000L; + } } else if (strcasecmp("Prefix", child->key) == 0) { status = cf_util_get_string(child, &node->prefix); } else if (strcasecmp("Database", child->key) == 0) { diff --git a/src/write_riemann.c b/src/write_riemann.c index 55699d5d..b35d10ee 100644 --- a/src/write_riemann.c +++ b/src/write_riemann.c @@ -48,11 +48,11 @@ struct riemann_host { char *name; char *event_service_prefix; pthread_mutex_t lock; - _Bool batch_mode; - _Bool notifications; - _Bool check_thresholds; - _Bool store_rates; - _Bool always_append_ds; + bool batch_mode; + bool notifications; + bool check_thresholds; + bool store_rates; + bool always_append_ds; char *node; int port; riemann_client_type_t client_type; @@ -181,9 +181,7 @@ static int wrr_send(struct riemann_host *host, riemann_message_t *msg) { return status; } -static riemann_message_t * -wrr_notification_to_message(struct riemann_host *host, /* {{{ */ - notification_t const *n) { +static riemann_message_t *wrr_notification_to_message(notification_t const *n) { riemann_message_t *msg; riemann_event_t *event; char service_buffer[6 * DATA_MAX_NAME_LEN]; @@ -271,7 +269,7 @@ wrr_notification_to_message(struct riemann_host *host, /* {{{ */ "host = \"%s\", service = \"%s\", state = \"%s\"", event->host, event->service, event->state); return msg; -} /* }}} riemann_message_t *wrr_notification_to_message */ +} static riemann_event_t * wrr_value_to_event(struct riemann_host const *host, /* {{{ */ @@ -546,7 +544,7 @@ static int wrr_notification(const notification_t *n, user_data_t *ud) /* {{{ */ /* * Never batch for notifications, send them ASAP */ - msg = wrr_notification_to_message(host, n); + msg = wrr_notification_to_message(n); if (msg == NULL) return -1; @@ -632,11 +630,11 @@ static int wrr_config_node(oconfig_item_t *ci) /* {{{ */ host->reference_count = 1; host->node = NULL; host->port = 0; - host->notifications = 1; - host->check_thresholds = 0; - host->store_rates = 1; - host->always_append_ds = 0; - host->batch_mode = 1; + host->notifications = true; + host->check_thresholds = false; + host->store_rates = true; + host->always_append_ds = false; + host->batch_mode = true; host->batch_max = RIEMANN_BATCH_MAX; /* typical MSS */ host->batch_init = cdtime(); host->batch_timeout = 0; @@ -701,21 +699,13 @@ static int wrr_config_node(oconfig_item_t *ci) /* {{{ */ } else if (strcasecmp("Port", child->key) == 0) { host->port = cf_util_get_port_number(child); if (host->port == -1) { - ERROR("write_riemann plugin: Invalid argument " - "configured for the \"Port\" " - "option."); break; } } else if (strcasecmp("Protocol", child->key) == 0) { char tmp[16]; status = cf_util_get_string_buffer(child, tmp, sizeof(tmp)); - if (status != 0) { - ERROR("write_riemann plugin: cf_util_get_" - "string_buffer failed with " - "status %i.", - status); + if (status != 0) break; - } if (strcasecmp("UDP", tmp) == 0) host->client_type = RIEMANN_CLIENT_UDP; @@ -731,31 +721,16 @@ static int wrr_config_node(oconfig_item_t *ci) /* {{{ */ tmp); } else if (strcasecmp("TLSCAFile", child->key) == 0) { status = cf_util_get_string(child, &host->tls_ca_file); - if (status != 0) { - ERROR("write_riemann plugin: cf_util_get_" - "string_buffer failed with " - "status %i.", - status); + if (status != 0) break; - } } else if (strcasecmp("TLSCertFile", child->key) == 0) { status = cf_util_get_string(child, &host->tls_cert_file); - if (status != 0) { - ERROR("write_riemann plugin: cf_util_get_" - "string_buffer failed with " - "status %i.", - status); + if (status != 0) break; - } } else if (strcasecmp("TLSKeyFile", child->key) == 0) { status = cf_util_get_string(child, &host->tls_key_file); - if (status != 0) { - ERROR("write_riemann plugin: cf_util_get_" - "string_buffer failed with " - "status %i.", - status); + if (status != 0) break; - } } else if (strcasecmp("StoreRates", child->key) == 0) { status = cf_util_get_boolean(child, &host->store_rates); if (status != 0) diff --git a/src/write_sensu.c b/src/write_sensu.c index 71dd5854..6ea8106c 100644 --- a/src/write_sensu.c +++ b/src/write_sensu.c @@ -107,10 +107,10 @@ struct sensu_host { #define F_READY 0x01 uint8_t flags; pthread_mutex_t lock; - _Bool notifications; - _Bool metrics; - _Bool store_rates; - _Bool always_append_ds; + bool notifications; + bool metrics; + bool store_rates; + bool always_append_ds; char *separator; char *node; char *service; @@ -119,8 +119,8 @@ struct sensu_host { int reference_count; }; -static char *sensu_tags = NULL; -static char **sensu_attrs = NULL; +static char *sensu_tags; +static char **sensu_attrs; static size_t sensu_attrs_num; static int add_str_to_list(struct str_list *strs, @@ -309,8 +309,8 @@ static int sensu_format_name2(char *ret, int ret_len, const char *hostname, static void in_place_replace_sensu_name_reserved(char *orig_name) /* {{{ */ { - int len = strlen(orig_name); - for (int i = 0; i < len; i++) { + size_t len = strlen(orig_name); + for (size_t i = 0; i < len; i++) { // some plugins like ipmi generate special characters in metric name switch (orig_name[i]) { case '(': @@ -337,8 +337,7 @@ static void in_place_replace_sensu_name_reserved(char *orig_name) /* {{{ */ static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */ data_set_t const *ds, value_list_t const *vl, - size_t index, gauge_t const *rates, - int status) { + size_t index, gauge_t const *rates) { char name_buffer[5 * DATA_MAX_NAME_LEN]; char service_buffer[6 * DATA_MAX_NAME_LEN]; char *ret_str; @@ -627,7 +626,7 @@ static char *replace_str(const char *str, const char *old, /* {{{ */ r += newlen; p = q + oldlen; } - strncpy(r, p, strlen(p)); + sstrncpy(r, p, retlen + 1); return ret; } /* }}} char *replace_str */ @@ -926,7 +925,7 @@ static int sensu_write(const data_set_t *ds, /* {{{ */ } } for (size_t i = 0; i < vl->values_len; i++) { - msg = sensu_value_to_json(host, ds, vl, (int)i, rates, statuses[i]); + msg = sensu_value_to_json(host, ds, vl, (int)i, rates); if (msg == NULL) { sfree(rates); pthread_mutex_unlock(&host->lock); @@ -1019,10 +1018,10 @@ static int sensu_config_node(oconfig_item_t *ci) /* {{{ */ host->reference_count = 1; host->node = NULL; host->service = NULL; - host->notifications = 0; - host->metrics = 0; - host->store_rates = 1; - host->always_append_ds = 0; + host->notifications = false; + host->metrics = false; + host->store_rates = true; + host->always_append_ds = false; host->metric_handlers.nb_strs = 0; host->metric_handlers.strs = NULL; host->notification_handlers.nb_strs = 0; @@ -1085,12 +1084,8 @@ static int sensu_config_node(oconfig_item_t *ci) /* {{{ */ break; } else if (strcasecmp("Port", child->key) == 0) { status = cf_util_get_service(child, &host->service); - if (status != 0) { - ERROR("write_sensu plugin: Invalid argument " - "configured for the \"Port\" " - "option."); + if (status != 0) break; - } } else if (strcasecmp("StoreRates", child->key) == 0) { status = cf_util_get_boolean(child, &host->store_rates); if (status != 0) @@ -1124,16 +1119,17 @@ static int sensu_config_node(oconfig_item_t *ci) /* {{{ */ return -1; } - if ((host->notification_handlers.nb_strs > 0) && (host->notifications == 0)) { + if ((host->notification_handlers.nb_strs > 0) && + (host->notifications == false)) { WARNING("write_sensu plugin: NotificationHandler given so forcing " "notifications to be enabled"); host->notifications = 1; } - if ((host->metric_handlers.nb_strs > 0) && (host->metrics == 0)) { + if ((host->metric_handlers.nb_strs > 0) && (host->metrics == false)) { WARNING("write_sensu plugin: MetricHandler given so forcing metrics to be " "enabled"); - host->metrics = 1; + host->metrics = true; } if (!(host->notifications || host->metrics)) { diff --git a/src/write_tsdb.c b/src/write_tsdb.c index 349b0d0c..42f5d65b 100644 --- a/src/write_tsdb.c +++ b/src/write_tsdb.c @@ -79,8 +79,8 @@ struct wt_callback { char *service; char *host_tags; - _Bool store_rates; - _Bool always_append_ds; + bool store_rates; + bool always_append_ds; char send_buf[WT_SEND_BUF_SIZE]; size_t send_buf_free; @@ -89,13 +89,13 @@ struct wt_callback { pthread_mutex_t send_lock; - _Bool connect_failed_log_enabled; + bool connect_failed_log_enabled; int connect_dns_failed_attempts_remaining; cdtime_t next_random_ttl; }; -static cdtime_t resolve_interval = 0; -static cdtime_t resolve_jitter = 0; +static cdtime_t resolve_interval; +static cdtime_t resolve_jitter; /* * Functions @@ -152,7 +152,7 @@ static int wt_flush_nolock(cdtime_t timeout, struct wt_callback *cb) { return status; } -static cdtime_t new_random_ttl() { +static cdtime_t new_random_ttl(void) { if (resolve_jitter == 0) return 0; @@ -313,7 +313,7 @@ static int wt_flush(cdtime_t timeout, static int wt_format_values(char *ret, size_t ret_len, int ds_num, const data_set_t *ds, const value_list_t *vl, - _Bool store_rates) { + bool store_rates) { size_t offset = 0; int status; gauge_t *rates = NULL; diff --git a/src/zookeeper.c b/src/zookeeper.c index 1de01d00..a99bbc01 100644 --- a/src/zookeeper.c +++ b/src/zookeeper.c @@ -37,8 +37,8 @@ #define ZOOKEEPER_DEF_HOST "127.0.0.1" #define ZOOKEEPER_DEF_PORT "2181" -static char *zk_host = NULL; -static char *zk_port = NULL; +static char *zk_host; +static char *zk_port; static const char *config_keys[] = {"Host", "Port"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);