author | Ruben Kerkhof <ruben@rubenkerkhof.com> | |
Sat, 26 Mar 2016 18:12:20 +0000 (19:12 +0100) | ||
committer | Ruben Kerkhof <ruben@rubenkerkhof.com> | |
Sat, 26 Mar 2016 18:12:20 +0000 (19:12 +0100) |
163 files changed:
diff --git a/.gitignore b/.gitignore
index 54eaa9748ef6240a0e8cd12650275d6536892f53..b14cc7abd3678d58100952abac32260624e1fef8 100644 (file)
--- a/.gitignore
+++ b/.gitignore
config.log
config.status
libtool
-src/.deps
src/collectd.conf
src/config.h
src/libcollectdclient/libcollectdclient.pc
*.lo
*.o
.libs/
-src/collectd
+.deps/
src/collectd-nagios
src/collectd-tg
src/collectdctl
# python stuff
*.pyc
-# tag stuff
-src/tags
-
# backup stuff
*~
-# tests stuff
-src/tests/.deps/
-src/tests/mock/.deps/
-src/tests/.dirstamp
-src/tests/mock/.dirstamp
-test*.log
+# Unit tests
+src/tests/
+test_*
-# new daemon repo
-src/daemon/.deps/
-src/daemon/.dirstamp
+# src/daemon/...
src/daemon/collectd
diff --git a/.travis.yml b/.travis.yml
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,56 @@
+sudo: required
+dist: trusty
+compiler:
+ - gcc
+ - clang
+language: c
+before_install:
+ - sudo apt-get update -qq
+ - sudo apt-get install -qq --no-install-recommends
+ iptables-dev
+ libatasmart-dev
+ libcap-dev
+ libcurl4-gnutls-dev
+ libdbi0-dev
+ libesmtp-dev
+ libganglia1-dev
+ libgcrypt11-dev
+ libglib2.0-dev
+ libhiredis-dev
+ libi2c-dev
+ libldap2-dev
+ libltdl-dev
+ liblvm2-dev
+ libmemcached-dev
+ libmnl-dev
+ libmodbus-dev
+ libmosquitto0-dev
+ libmysqlclient-dev
+ libnotify-dev
+ libopenipmi-dev
+ liboping-dev
+ libow-dev
+ libpcap-dev
+ libperl-dev
+ libpq-dev
+ libprotobuf-c0-dev
+ librabbitmq-dev
+ librdkafka-dev
+ librrd-dev
+ libsensors4-dev
+ libsigrok-dev
+ libsnmp-dev
+ libstatgrab-dev
+ libtokyocabinet-dev
+ libtokyotyrant-dev
+ libudev-dev
+ libupsclient-dev
+ libvarnish-dev
+ libvirt-dev
+ libxml2-dev
+ libyajl-dev
+ linux-libc-dev
+ perl
+ protobuf-c-compiler
+ python-dev
+script: sh build.sh && ./configure --with-python=/usr/bin/python && make distcheck DISTCHECK_CONFIGURE_FLAGS="--with-python=/usr/bin/python"
index 3f63c3dcd5591c72131b4bfa3dc579d9bc5e36cc..02b125688ee778587d14992e449d28bb2142515f 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
Cyril Feraudet <cyril at feraudet.com>
- ethstat plugin.
+Dagobert Michelsen <dam at opencsw.org>
+ - zone plugin.
+
Dan Berrange <berrange at redhat.com>
- uuid plugin.
- ip6tables support in the iptables plugin.
- openvpn plugin (support for more status file formats)
+Mathijs Möhlmann <collectd at mmrc.nl>
+ - zone plugin.
+
Michael Hanselmann <public at hansmi.ch>
- md plugin.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,38 @@
+# Thanks !
+
+Thanks for your feedback & contributions to the
+[collectd project](https://collectd.org/) !
+
+## Need help using collectd ?
+
+Please use the
+[collectd mailing list](http://mailman.verplant.org/listinfo/collectd) or the
+[#collectd IRC channel](https://webchat.freenode.net/?channels=#collectd).
+We'd like to keep the github issue tracker for bugreports and patch reviews.
+
+## Found a bug ?
+
+Please mention the exact collectd version you're using, how it was installed
+(built from source, or installed from packages. Where was it downloaded
+from). Which operating system/architecture, distribution and version are you
+running collectd on.
+
+If collectd crashes, try to get a
+[stack trace](https://collectd.org/wiki/index.php/Core_file).
+
+## Fixed a bug ? Want to add a feature ?
+
+Using git/github to submit changes is not mandatory. Sending patches to the
+[mailing-list](http://mailman.verplant.org/listinfo/collectd) is also fine.
+In both cases, take a quick look at the
+[submission guidelines](https://collectd.org/wiki/index.php/Submitting_patches)
+and the [coding style recommendations](https://collectd.org/wiki/index.php/Coding_style).
+
+Please try to submit **bugfixes** to the
+[oldest release branch](https://github.com/collectd/collectd/milestones) on
+which the bug is found, so that it gets included in every future **bugfix
+release**.
+
+Please try to submit **new features** to the master branch (which will become
+the next **feature release**).
+
index 3e2c0233adc3ea9ccfbcbbf072c107a0f6dcbd5b..f2371cbe9d543b1d1cc37701d8f07e167e5c4139 100644 (file)
--- a/README
+++ b/README
Reads values from Modbus/TCP enabled devices. Supports reading values
from multiple "slaves" so gateway devices can be used.
+ - mqtt
+ Publishes and subscribes to MQTT topics.
+
- multimeter
Information provided by serial multimeters, such as the `Metex
M-4650CR'.
- zfs_arc
Statistics for ZFS' “Adaptive Replacement Cache” (ARC).
+ - zone
+ Measures the percentage of cpu load per container (zone) under Solaris 10
+ and higher
+
- zookeeper
Read data from Zookeeper's MNTR command.
library checks succeed.
If this doesn't work for you, you have the possibility to specify CPP-flags,
- C-flags and LD-flags for the ‘Java’ plugin by hand, using the following three
- (environment) variables:
+ C-flags, LD-flags and LIBS for the ‘Java’ plugin by hand, using the
+ following environment variables:
- JAVA_CPPFLAGS
- JAVA_CFLAGS
- JAVA_LDFLAGS
+ - JAVA_LIBS
For example (shortened for demonstration purposes):
./configure JAVA_CPPFLAGS="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
- Adding "-ljvm" to the JAVA_LDFLAGS is done automatically, you don't have to
+ Adding "-ljvm" to JAVA_LIBS is done automatically, you don't have to
do that.
Generating the configure script
diff --git a/bindings/java/org/collectd/java/GenericJMXConfConnection.java b/bindings/java/org/collectd/java/GenericJMXConfConnection.java
index ea0f2fa2e54a1a3eabe7ca65517ac336c60ca40d..aced54b4f2278955fc69ecb506c0036892027195 100644 (file)
private String _host = null;
private String _instance_prefix = null;
private String _service_url = null;
- private MBeanServerConnection _jmx_connection = null;
+ private JMXConnector _jmx_connector = null;
+ private MBeanServerConnection _mbean_connection = null;
private List<GenericJMXConfMBean> _mbeans = null;
/*
return Collectd.getHostname();
} /* }}} String getHost */
-private void connect () /* {{{ */
-{
- JMXServiceURL service_url;
- JMXConnector connector;
- Map environment;
+ private void connect () /* {{{ */
+ {
+ JMXServiceURL service_url;
+ Map<String,Object> environment;
- if (_jmx_connection != null)
- return;
+ // already connected
+ if (this._jmx_connector != null) {
+ return;
+ }
- environment = null;
- if (this._password != null)
- {
- String[] credentials;
+ environment = null;
+ if (this._password != null)
+ {
+ String[] credentials;
- if (this._username == null)
- this._username = new String ("monitorRole");
+ if (this._username == null)
+ this._username = new String ("monitorRole");
- credentials = new String[] { this._username, this._password };
+ credentials = new String[] { this._username, this._password };
- environment = new HashMap ();
- environment.put (JMXConnector.CREDENTIALS, credentials);
- environment.put(JMXConnectorFactory.PROTOCOL_PROVIDER_CLASS_LOADER, this.getClass().getClassLoader());
- }
+ environment = new HashMap<String,Object> ();
+ environment.put (JMXConnector.CREDENTIALS, credentials);
+ environment.put (JMXConnectorFactory.PROTOCOL_PROVIDER_CLASS_LOADER, this.getClass().getClassLoader());
+ }
- try
- {
- service_url = new JMXServiceURL (this._service_url);
- connector = JMXConnectorFactory.connect (service_url, environment);
- _jmx_connection = connector.getMBeanServerConnection ();
- }
- catch (Exception e)
+ try
+ {
+ service_url = new JMXServiceURL (this._service_url);
+ this._jmx_connector = JMXConnectorFactory.connect (service_url, environment);
+ this._mbean_connection = _jmx_connector.getMBeanServerConnection ();
+ }
+ catch (Exception e)
+ {
+ Collectd.logError ("GenericJMXConfConnection: "
+ + "Creating MBean server connection failed: " + e);
+ disconnect ();
+ return;
+ }
+ } /* }}} void connect */
+
+ private void disconnect () /* {{{ */
{
- Collectd.logError ("GenericJMXConfConnection: "
- + "Creating MBean server connection failed: " + e);
- return;
- }
-} /* }}} void connect */
+ try
+ {
+ this._jmx_connector.close();
+ }
+ catch (Exception e)
+ {
+ // It's fine if close throws an exception
+ }
-/*
- * public methods
- *
- * <Connection>
- * Host "tomcat0.mycompany"
- * ServiceURL "service:jmx:rmi:///jndi/rmi://localhost:17264/jmxrmi"
- * Collect "java.lang:type=GarbageCollector,name=Copy"
- * Collect "java.lang:type=Memory"
- * </Connection>
- *
- */
+ this._jmx_connector = null;
+ this._mbean_connection = null;
+ } /* }}} void disconnect */
+
+ /*
+ * public methods
+ *
+ * <Connection>
+ * Host "tomcat0.mycompany"
+ * ServiceURL "service:jmx:rmi:///jndi/rmi://localhost:17264/jmxrmi"
+ * Collect "java.lang:type=GarbageCollector,name=Copy"
+ * Collect "java.lang:type=Memory"
+ * </Connection>
+ *
+ */
public GenericJMXConfConnection (OConfigItem ci) /* {{{ */
throws IllegalArgumentException
{
{
PluginData pd;
+ // try to connect
connect ();
- if (this._jmx_connection == null)
+ if (this._mbean_connection == null)
return;
Collectd.logDebug ("GenericJMXConfConnection.query: "
{
int status;
- status = this._mbeans.get (i).query (this._jmx_connection, pd,
+ status = this._mbeans.get (i).query (this._mbean_connection, pd,
this._instance_prefix);
if (status != 0)
{
- this._jmx_connection = null;
+ disconnect ();
return;
}
} /* for */
diff --git a/bindings/java/org/collectd/java/GenericJMXConfValue.java b/bindings/java/org/collectd/java/GenericJMXConfValue.java
index 4b42c91171036ca70d213d0f1131373f79b7f572..25b70d4ad7166dfda421f8b29fb37a757a837673 100644 (file)
import java.util.Arrays;
import java.util.List;
+import java.util.Collection;
import java.util.Set;
import java.util.Iterator;
import java.util.ArrayList;
import javax.management.ObjectName;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
import javax.management.openmbean.InvalidKeyException;
import org.collectd.api.Collectd;
private List<String> _attributes;
private String _instance_prefix;
private List<String> _instance_from;
+ private String _plugin_name;
private boolean _is_table;
/**
{
if (value instanceof CompositeData)
return (queryAttributeRecursive ((CompositeData) value, attrName));
+ else if (value instanceof TabularData)
+ return (queryAttributeRecursive ((TabularData) value, attrName));
+ else
+ return (null);
+ }
+ } /* }}} queryAttributeRecursive */
+
+ private Object queryAttributeRecursive (TabularData parent, /* {{{ */
+ List<String> attrName)
+ {
+ String key;
+ Object value = null;
+
+ key = attrName.remove (0);
+
+ TabularData tabularData = (TabularData) parent;
+ Collection<CompositeData> table =
+ (Collection<CompositeData>)tabularData.values();
+ for (CompositeData compositeData : table)
+ {
+ if (key.equals(compositeData.get("key")))
+ {
+ value = compositeData.get("value");
+ }
+ }
+ if (null == value)
+ {
+ return (null);
+ }
+
+ if (attrName.size () == 0)
+ {
+ return (value);
+ }
+ else
+ {
+ if (value instanceof CompositeData)
+ return (queryAttributeRecursive ((CompositeData) value, attrName));
+ else if (value instanceof TabularData)
+ return (queryAttributeRecursive ((TabularData) value, attrName));
else
return (null);
}
{
if (value instanceof CompositeData)
return (queryAttributeRecursive((CompositeData) value, attrNameList));
+ else if (value instanceof TabularData)
+ return (queryAttributeRecursive((TabularData) value, attrNameList));
else if (value instanceof OpenType)
{
OpenType ot = (OpenType) value;
else
{
Collectd.logError ("GenericJMXConfValue: Received object of "
- + "unknown class.");
+ + "unknown class. " + attrName + " " + ((value == null)?"null":value.getClass().getName()));
return (null);
}
}
this._attributes = new ArrayList<String> ();
this._instance_prefix = null;
this._instance_from = new ArrayList<String> ();
+ this._plugin_name = null;
this._is_table = false;
/*
if (tmp != null)
this._instance_from.add (tmp);
}
+ else if (child.getKey ().equalsIgnoreCase ("PluginName"))
+ {
+ String tmp = getConfigString (child);
+ if (tmp != null)
+ this._plugin_name = tmp;
+ }
else
throw (new IllegalArgumentException ("Unknown option: "
+ child.getKey ()));
vl = new ValueList (pd);
vl.setType (this._ds_name);
+ if (this._plugin_name != null)
+ {
+ vl.setPlugin (this._plugin_name);
+ }
/*
* Build the instnace prefix from the fixed string prefix and the
index 5e79d2682ecbb723ff094f1d12add49b15b72a76..d927d13e4bc486b48110c5d786ad537d763f8de8 100644 (file)
sub _escape_argument
{
- local $_ = shift;
+ my $arg = shift;
- return $_ if /^\w+$/;
+ return $arg if $arg =~ /^\w+$/;
- s#\\#\\\\#g;
- s#"#\\"#g;
- return "\"$_\"";
+ $arg =~ s#\\#\\\\#g;
+ $arg =~ s#"#\\"#g;
+ return "\"$arg\"";
}
# Send a command on a socket, including any required argument escaping.
index 2f7818b15799cb650e6d2288072286f4426ac583..4e94f8e8d235f53fa742bd716a1b738b6aade28f 100644 (file)
my ($nresults, $resultdata) = @$results;
my $r = $s->getval(%{Collectd::Unixsock::_parse_identifier($attr)});
is(ref $r, 'HASH', "Got a result for $attr");
- is(scalar keys $r, $nresults, "$nresults result result for $attr");
+ is(scalar keys %$r, $nresults, "$nresults result result for $attr");
is_deeply($r, $resultdata, "Data or $attr matches");
}
diff --git a/build.sh b/build.sh
index 20854b13b7d88cf6aa90f5ce990fd07370fff56c..57f3d4449a99bef83b75b50f425dc548bc9ead60 100755 (executable)
--- a/build.sh
+++ b/build.sh
done
}
-check_for_application lex yacc autoheader aclocal automake autoconf
+check_for_application lex bison autoheader aclocal automake autoconf
# Actually we don't need the pkg-config executable, but we need the M4 macros.
# We check for `pkg-config' here and hope that M4 macros will then be
diff --git a/configure.ac b/configure.ac
index dc9d324ffa9a231863dbc3eadcff47bfdd8240da..1ed690d867c707196dd65024806d7c4163e7a1ca 100644 (file)
--- a/configure.ac
+++ b/configure.ac
AC_DEFINE([KERNEL_OPENBSD], 1, [True if program is to be compiled for an OpenBSD kernel])
ac_system="OpenBSD"
;;
+ *netbsd*)
+ AC_DEFINE([KERNEL_NETBSD], 1, [True if program is to be compiled for a NetBSD kernel])
+ ac_system="NetBSD"
+ ;;
*aix*)
AC_DEFINE([KERNEL_AIX], 1, [True if program is to be compiled for a AIX kernel])
ac_system="AIX"
AC_CHECK_HEADERS(stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h sys/isa_defs.h fnmatch.h libgen.h)
+# For entropy plugin on newer NetBSD
+AC_CHECK_HEADERS(sys/rndio.h, [], [],
+[#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+])
+
# For ping library
AC_CHECK_HEADERS(netinet/in_systm.h, [], [],
[#if HAVE_STDINT_H
AC_MSG_CHECKING([for sysctl kern.cp_times])
if test -x /sbin/sysctl
then
- /sbin/sysctl kern.cp_times 2>/dev/null
+ /sbin/sysctl kern.cp_times >/dev/null 2>&1
if test $? -eq 0
then
AC_MSG_RESULT([yes])
AC_MSG_RESULT([no])
fi
+AC_MSG_CHECKING([for sysctl kern.cp_time])
+if test -x /sbin/sysctl
+then
+ /sbin/sysctl kern.cp_time >/dev/null 2>&1
+ if test $? -eq 0
+ then
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_SYSCTL_KERN_CP_TIME, 1,
+ [Define if sysctl supports kern.cp_time])
+ else
+ AC_MSG_RESULT([no])
+ fi
+else
+ AC_MSG_RESULT([no])
+fi
+
# For hddtemp module
AC_CHECK_HEADERS(linux/major.h)
have_linux_raid_md_u_h="no"
fi
-# For the swap module
+# For the wireless module
have_linux_wireless_h="no"
if test "x$ac_system" = "xLinux"
then
#endif
])
-AC_CHECK_HEADERS(netinet/ip_compat.h)
-
have_net_pfvar_h="no"
AC_CHECK_HEADERS(net/pfvar.h,
[have_net_pfvar_h="yes"],
# Checks for typedefs, structures, and compiler characteristics.
#
AC_C_CONST
-AC_C_INLINE
-AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
-AC_TYPE_SSIZE_T
AC_TYPE_UID_T
-AC_TYPE_UINT32_T
AC_HEADER_TIME
#
if test "x$have_clock_gettime" = "xyes"
then
AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if the clock_gettime(2) function is available.])
-else
- AC_MSG_WARN(cannot find clock_gettime)
fi
nanosleep_needs_rt="no"
#include <kvm.h>
])
+
+AC_CHECK_MEMBERS([struct kinfo_proc2.p_pid, struct kinfo_proc2.p_uru_maxrss],
+ [
+ AC_DEFINE(HAVE_STRUCT_KINFO_PROC2_NETBSD, 1,
+ [Define if struct kinfo_proc2 exists in the NetBSD variant.])
+ have_struct_kinfo_proc2_netbsd="yes"
+ ],
+ [
+ have_struct_kinfo_proc2_netbsd="no"
+ ],
+ [
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <kvm.h>
+ ])
+
+
+
AC_CHECK_MEMBERS([struct udphdr.uh_dport, struct udphdr.uh_sport], [], [],
[#define _BSD_SOURCE
#define _DEFAULT_SOURCE
fi
fi
+# --with-libpthread {{{
+AC_ARG_WITH(libpthread, [AS_HELP_STRING([--with-libpthread=@<:@=PREFIX@:>@], [Path to libpthread.])],
+[ if test "x$withval" != "xno" \
+ && test "x$withval" != "xyes"
+ then
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ with_libpthread="yes"
+ else
+ if test "x$withval" = "xno"
+ then
+ with_libpthread="no (disabled)"
+ fi
+ fi
+], [with_libpthread="yes"])
+
+AC_SUBST([PTHREAD_LIBS])
+if test "x$with_libpthread" = "xyes"
+then
+ SAVE_LIBS="$LIBS"
+ AC_CHECK_LIB(pthread, pthread_create, [], [with_libpthread="no (Symbol 'pthread_create' not found)"], [])
+ PTHREAD_LIBS="$LIBS"
+ LIBS="$SAVE_LIBS"
+fi
+
+if test "x$with_libpthread" = "xyes"
+then
+ AC_CHECK_HEADERS(pthread.h,, [with_libpthread="no (pthread.h not found)"])
+fi
+if test "x$with_libpthread" = "xyes"
+then
+ collect_pthread=1
+else
+ collect_pthread=0
+fi
+AC_DEFINE_UNQUOTED(HAVE_LIBPTHREAD, [$collect_pthread],
+ [Wether or not to use pthread (POSIX threads) library])
+AM_CONDITIONAL(BUILD_WITH_LIBPTHREAD, test "x$with_libpthread" = "xyes")
+# }}}
+
m4_divert_once([HELP_WITH], [
collectd additional packages:])
AC_CHECK_LIB(gcrypt, gcry_md_hash_buffer,
[with_libgcrypt="yes"],
[with_libgcrypt="no (symbol gcry_md_hash_buffer not found)"])
-
- if test "$with_libgcrypt" != "no"; then
- m4_ifdef([AM_PATH_LIBGCRYPT],[AM_PATH_LIBGCRYPT(1:1.2.0,,with_libgcrypt="no (version 1.2.0+ required)")])
- GCRYPT_CPPFLAGS="$LIBGCRYPT_CPPFLAGS $LIBGCRYPT_CFLAGS"
- GCRYPT_LIBS="$LIBGCRYPT_LIBS"
- fi
fi
CPPFLAGS="$SAVE_CPPFLAGS"
then
with_java_home="/usr/lib/jvm"
fi
-with_java_vmtype="client"
-with_java_cflags=""
-with_java_libs=""
JAVAC="$JAVAC"
JAR="$JAR"
AC_ARG_WITH(java, [AS_HELP_STRING([--with-java@<:@=PREFIX@:>@], [Path to Java home.])],
then
AC_MSG_NOTICE([Building with JAVA_LDFLAGS set to: $JAVA_LDFLAGS])
fi
+if test "x$JAVA_LIBS" != "x"
+then
+ AC_MSG_NOTICE([Building with JAVA_LIBS set to: $JAVA_LIBS])
+fi
if test "x$JAVAC" = "x"
then
with_javac_path="$PATH"
SAVE_CPPFLAGS="$CPPFLAGS"
SAVE_CFLAGS="$CFLAGS"
SAVE_LDFLAGS="$LDFLAGS"
+SAVE_LIBS="$LIBS"
CPPFLAGS="$CPPFLAGS $JAVA_CPPFLAGS"
CFLAGS="$CFLAGS $JAVA_CFLAGS"
LDFLAGS="$LDFLAGS $JAVA_LDFLAGS"
+LIBS="$LIBS $JAVA_LIBS"
if test "x$with_java" = "xyes"
then
then
AC_CHECK_LIB(jvm, JNI_CreateJavaVM,
[with_java="yes"],
- [with_java="no (libjvm not found)"],
- [$JAVA_LIBS])
+ [with_java="no (Symbol 'JNI_CreateJavaVM' not found)"],
+ [$JAVA_LIBS $PTHREAD_LIBS])
fi
if test "x$with_java" = "xyes"
then
CPPFLAGS="$SAVE_CPPFLAGS"
CFLAGS="$SAVE_CFLAGS"
LDFLAGS="$SAVE_LDFLAGS"
+LIBS="$SAVE_LIBS"
AC_SUBST(JAVA_CPPFLAGS)
AC_SUBST(JAVA_CFLAGS)
with_liblvm2app_ldflags=""
AC_ARG_WITH(liblvm2app, [AS_HELP_STRING([--with-liblvm2app@<:@=PREFIX@:>@], [Path to liblvm2app.])],
[
- if test "x$withval" != "xno" && test "x$withval" != "xyes"
- then
- with_liblvm2app_cppflags="-I$withval/include"
- with_liblvm2app_ldflags="-L$withval/lib"
- with_liblvm2app="yes"
- else
- with_liblvm2app="$withval"
+ if test "x$withval" = "xno"
+ then
+ with_liblvm2app="no"
+ else
+ with_liblvm2app="yes"
+ if test "x$withval" != "xyes"
+ then
+ with_liblvm2app_cppflags="-I$withval/include"
+ with_liblvm2app_ldflags="-L$withval/lib"
+ fi
fi
],
[
- with_liblvm2app="yes"
+ if test "x$ac_system" = "xLinux"
+ then
+ with_liblvm2app="yes"
+ else
+ with_liblvm2app="no (Linux only library)"
+ fi
])
if test "x$with_liblvm2app" = "xyes"
then
AM_CONDITIONAL(BUILD_WITH_LIBMONGOC, test "x$with_libmongoc" = "xyes")
# }}}
+# --with-libmosquitto {{{
+with_libmosquitto_cppflags=""
+with_libmosquitto_ldflags=""
+AC_ARG_WITH(libmosquitto, [AS_HELP_STRING([--with-libmosquitto@<:@=PREFIX@:>@], [Path to libmosquitto.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ with_libmosquitto_cppflags="-I$withval/include"
+ with_libmosquitto_ldflags="-L$withval/lib"
+ with_libmosquitto="yes"
+ else
+ with_libmosquitto="$withval"
+ fi
+],
+[
+ with_libmosquitto="yes"
+])
+if test "x$with_libmosquitto" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libmosquitto_cppflags"
+
+ AC_CHECK_HEADERS(mosquitto.h, [with_libmosquitto="yes"], [with_libmosquitto="no (mosquitto.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libmosquitto" = "xyes"
+then
+ SAVE_LDFLAGS="$LDFLAGS"
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ LDFLAGS="$LDFLAGS $with_libmosquitto_ldflags"
+ CPPFLAGS="$CPPFLAGS $with_libmosquitto_cppflags"
+
+ AC_CHECK_LIB(mosquitto, mosquitto_connect, [with_libmosquitto="yes"], [with_libmosquitto="no (libmosquitto not found)"])
+
+ LDFLAGS="$SAVE_LDFLAGS"
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libmosquitto" = "xyes"
+then
+ BUILD_WITH_LIBMOSQUITTO_CPPFLAGS="$with_libmosquitto_cppflags"
+ BUILD_WITH_LIBMOSQUITTO_LDFLAGS="$with_libmosquitto_ldflags"
+ BUILD_WITH_LIBMOSQUITTO_LIBS="-lmosquitto"
+ AC_SUBST(BUILD_WITH_LIBMOSQUITTO_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBMOSQUITTO_LDFLAGS)
+ AC_SUBST(BUILD_WITH_LIBMOSQUITTO_LIBS)
+fi
+# }}}
+
# --with-libmysql {{{
with_mysql_config="mysql_config"
with_mysql_cflags=""
if test "x$LIBNETAPP_LIBS" = "x"
then
- LIBNETAPP_LIBS="-lpthread -lxml -ladt -lssl -lm -lcrypto -lz"
+ LIBNETAPP_LIBS="$PTHREAD_LIBS -lxml -ladt -lssl -lm -lcrypto -lz"
fi
AC_MSG_NOTICE([netapp LIBS: $LIBNETAPP_LIBS])
# --with-libowcapi {{{
with_libowcapi_cppflags=""
-with_libowcapi_libs="-lowcapi"
+with_libowcapi_ldflags=""
AC_ARG_WITH(libowcapi, [AS_HELP_STRING([--with-libowcapi@<:@=PREFIX@:>@], [Path to libowcapi.])],
[
if test "x$withval" != "xno" && test "x$withval" != "xyes"
then
with_libowcapi_cppflags="-I$withval/include"
- with_libowcapi_libs="-L$withval/lib -lowcapi"
+ with_libowcapi_ldflags="-L$withval/lib"
with_libowcapi="yes"
else
with_libowcapi="$withval"
@@ -3232,7 +3370,7 @@ AC_ARG_WITH(libowcapi, [AS_HELP_STRING([--with-libowcapi@<:@=PREFIX@:>@], [Path
if test "x$with_libowcapi" = "xyes"
then
SAVE_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$with_libowcapi_cppflags"
+ CPPFLAGS="$CPPFLAGS $with_libowcapi_cppflags"
AC_CHECK_HEADERS(owcapi.h, [with_libowcapi="yes"], [with_libowcapi="no (owcapi.h not found)"])
then
SAVE_LDFLAGS="$LDFLAGS"
SAVE_CPPFLAGS="$CPPFLAGS"
- LDFLAGS="$with_libowcapi_libs"
+ LDFLAGS="$LDFLAGS $with_libowcapi_ldflags"
CPPFLAGS="$with_libowcapi_cppflags"
AC_CHECK_LIB(owcapi, OW_get, [with_libowcapi="yes"], [with_libowcapi="no (libowcapi not found)"])
if test "x$with_libowcapi" = "xyes"
then
BUILD_WITH_LIBOWCAPI_CPPFLAGS="$with_libowcapi_cppflags"
- BUILD_WITH_LIBOWCAPI_LIBS="$with_libowcapi_libs"
+ BUILD_WITH_LIBOWCAPI_LDFLAGS="$with_libowcapi_ldflags"
+ BUILD_WITH_LIBOWCAPI_LIBS="-lowcapi"
AC_SUBST(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBOWCAPI_LDFLAGS)
AC_SUBST(BUILD_WITH_LIBOWCAPI_LIBS)
fi
# }}}
AM_CONDITIONAL(BUILD_WITH_LIBPQ, test "x$with_libpq" = "xyes")
# }}}
-# --with-libpthread {{{
-AC_ARG_WITH(libpthread, [AS_HELP_STRING([--with-libpthread=@<:@=PREFIX@:>@], [Path to libpthread.])],
-[ if test "x$withval" != "xno" \
- && test "x$withval" != "xyes"
- then
- LDFLAGS="$LDFLAGS -L$withval/lib"
- CPPFLAGS="$CPPFLAGS -I$withval/include"
- with_libpthread="yes"
- else
- if test "x$withval" = "xno"
- then
- with_libpthread="no (disabled)"
- fi
- fi
-], [with_libpthread="yes"])
-if test "x$with_libpthread" = "xyes"
-then
- AC_CHECK_LIB(pthread, pthread_create, [with_libpthread="yes"], [with_libpthread="no (libpthread not found)"], [])
-fi
-
-if test "x$with_libpthread" = "xyes"
-then
- AC_CHECK_HEADERS(pthread.h,, [with_libpthread="no (pthread.h not found)"])
-fi
-if test "x$with_libpthread" = "xyes"
-then
- collect_pthread=1
-else
- collect_pthread=0
-fi
-AC_DEFINE_UNQUOTED(HAVE_LIBPTHREAD, [$collect_pthread],
- [Wether or not to use pthread (POSIX threads) library])
-AM_CONDITIONAL(BUILD_WITH_LIBPTHREAD, test "x$with_libpthread" = "xyes")
-# }}}
-
# --with-python {{{
with_python_prog=""
with_python_path="$PATH"
SAVE_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $with_sensors_cflags"
-# AC_CHECK_HEADERS(sensors/sensors.h,
-# [
-# AC_DEFINE(HAVE_SENSORS_SENSORS_H, 1, [Define to 1 if you have the <sensors/sensors.h> header file.])
-# ],
-# [with_libsensors="no (sensors/sensors.h not found)"])
AC_CHECK_HEADERS(sensors/sensors.h, [], [with_libsensors="no (sensors/sensors.h not found)"])
CPPFLAGS="$SAVE_CPPFLAGS"
if test "x$with_libstatgrab" = "xyes"
then
SAVE_CFLAGS="$CFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
SAVE_LIBS="$LIBS"
CFLAGS="$CFLAGS $with_libstatgrab_cflags"
@@ -4724,7 +4825,7 @@ AC_ARG_WITH(mic,[AS_HELP_STRING([--with-mic@<:@=PREFIX@:>@], [Path to Intel MIC
AC_MSG_NOTICE([Not checking for Intel Mic: Manually configured])
with_mic_cflags="-I$withval/include"
with_mic_ldpath="-L$withval/lib/Linux"
- with_mic_libs="-lMicAccessSDK -lscif -lpthread"
+ with_mic_libs="$PTHREAD_LIBS -lMicAccessSDK -lscif"
with_mic="yes"
fi; fi; fi
],
AC_CHECK_LIB(MicAccessSDK, MicInitAPI,
[with_mic_ldpath="$with_mic_ldpath"
- with_mic_libs="-lMicAccessSDK -lscif -lpthread"],
- [with_mic="no (symbol MicInitAPI not found)"],[-lscif -lpthread])
+ with_mic_libs="$PTHREAD_LIBS -lMicAccessSDK -lscif"],
+ [with_mic="no (symbol MicInitAPI not found)"],[$PTHREAD_LIBS -lscif])
CPPFLAGS="$SAVE_CPPFLAGS"
LDFLAGS="$SAVE_LDFLAGS"
PKG_CHECK_MODULES([LIBNOTIFY], [libnotify],
[with_libnotify="yes"],
- [if test "x$LIBNOTIFY_PKG_ERRORS" = "x"; then
- with_libnotify="no"
- else
- with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"
- fi])
+ [with_libnotify="no (pkg-config doesn't know libnotify)"]
+)
# Check for enabled/disabled features
#
AC_COLLECTD([debug], [enable], [feature], [debugging])
AC_COLLECTD([daemon], [disable], [feature], [daemon mode])
AC_COLLECTD([getifaddrs],[enable], [feature], [getifaddrs under Linux])
+AC_COLLECTD([werror], [disable], [feature], [building with -Werror])
dependency_warning="no"
dependency_error="no"
plugin_vserver="no"
plugin_wireless="no"
plugin_zfs_arc="no"
+plugin_zone="no"
plugin_zookeeper="no"
# Linux
plugin_tcpconns="yes"
fi
+if test "x$ac_system" = "xNetBSD"
+then
+ plugin_entropy="yes"
+ plugin_irq="yes"
+ plugin_processes="yes"
+ plugin_disk="yes"
+fi
+
# Mac OS X devices
if test "x$with_libiokit" = "xyes"
then
if test "x$ac_system" = "xFreeBSD"
then
+ plugin_disk="yes"
plugin_zfs_arc="yes"
fi
plugin_processes="yes"
plugin_uptime="yes"
plugin_zfs_arc="yes"
+ plugin_zone="yes"
fi
if test "x$with_devinfo$with_kstat" = "xyesyes"
fi
# libi2c-dev
-with_libi2c="no"
if test "x$ac_system" = "xLinux"
then
AC_CHECK_DECL(i2c_smbus_read_i2c_block_data,
[with_libi2c="no (symbol i2c_smbus_read_i2c_block_data not found - have you installed libi2c-dev ?)"],
[[#include <stdlib.h>
#include <linux/i2c-dev.h>]])
+else
+ with_libi2c="no (Linux only)"
fi
if test "x$with_libi2c" = "xyes"
plugin_swap="yes"
fi
+if test "x$have_swapctl" = "xyes" && test "x$c_cv_have_swapctl_three_args" = "xyes"
+then
+ plugin_swap="yes"
+fi
+
if test "x$with_kvm_openfiles$with_kvm_nlist" = "xyesyes"
then
plugin_tcpconns="yes"
AC_PLUGIN([memory], [$plugin_memory], [Memory usage])
AC_PLUGIN([mic], [$with_mic], [Intel Many Integrated Core stats])
AC_PLUGIN([modbus], [$with_libmodbus], [Modbus plugin])
+AC_PLUGIN([mqtt], [$with_libmosquitto], [MQTT output plugin])
AC_PLUGIN([multimeter], [$plugin_multimeter], [Read multimeter values])
AC_PLUGIN([mysql], [$with_libmysql], [MySQL statistics])
AC_PLUGIN([netapp], [$with_libnetapp], [NetApp plugin])
AC_PLUGIN([nginx], [$with_libcurl], [nginx statistics])
AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications])
AC_PLUGIN([notify_email], [$with_libesmtp], [Email notifier])
+AC_PLUGIN([notify_nagios], [yes], [Nagios notification plugin])
AC_PLUGIN([ntpd], [yes], [NTPd statistics])
AC_PLUGIN([numa], [$plugin_numa], [NUMA virtual memory statistics])
AC_PLUGIN([nut], [$with_libupsclient], [Network UPS tools statistics])
AC_PLUGIN([write_tsdb], [yes], [TSDB output plugin])
AC_PLUGIN([xmms], [$with_libxmms], [XMMS statistics])
AC_PLUGIN([zfs_arc], [$plugin_zfs_arc], [ZFS ARC statistics])
+AC_PLUGIN([zone], [$plugin_zone], [Solaris container statistics])
AC_PLUGIN([zookeeper], [yes], [Zookeeper statistics])
dnl Default configuration file
AC_CONFIG_FILES(src/libcollectdclient/collectd/lcc_features.h)
+AM_CFLAGS="-Wall"
+if test "x$enable_werror" != "xno"
+then
+ AM_CFLAGS="$AM_CFLAGS -Werror"
+fi
+AC_SUBST([AM_CFLAGS])
+
AC_CONFIG_FILES([Makefile src/Makefile src/daemon/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile])
AC_OUTPUT
cat <<EOF;
Configuration:
+ Build:
+ Platform . . . . . . $ac_system
+ CC . . . . . . . . . $CC
+ CFLAGS . . . . . . . $AM_CFLAGS $CFLAGS
+ CPP . . . . . . . . . $CPP
+ CPPFLAGS . . . . . . $CPPFLAGS
+ LD . . . . . . . . . $LD
+ LDFLAGS . . . . . . . $LDFLAGS
+ YACC . . . . . . . . $YACC
+ YFLAGS . . . . . . . $YFLAGS
+
Libraries:
intel mic . . . . . . $with_mic
libaquaero5 . . . . . $with_libaquaero5
libmnl . . . . . . . $with_libmnl
libmodbus . . . . . . $with_libmodbus
libmongoc . . . . . . $with_libmongoc
+ libmosquitto . . . . $with_libmosquitto
libmysql . . . . . . $with_libmysql
libnetapp . . . . . . $with_libnetapp
libnetsnmp . . . . . $with_libnetsnmp
memory . . . . . . . $enable_memory
mic . . . . . . . . . $enable_mic
modbus . . . . . . . $enable_modbus
+ mqtt . . . . . . . . $enable_mqtt
multimeter . . . . . $enable_multimeter
mysql . . . . . . . . $enable_mysql
netapp . . . . . . . $enable_netapp
nginx . . . . . . . . $enable_nginx
notify_desktop . . . $enable_notify_desktop
notify_email . . . . $enable_notify_email
+ notify_nagios . . . . $enable_notify_nagios
ntpd . . . . . . . . $enable_ntpd
numa . . . . . . . . $enable_numa
nut . . . . . . . . . $enable_nut
write_tsdb . . . . . $enable_write_tsdb
xmms . . . . . . . . $enable_xmms
zfs_arc . . . . . . . $enable_zfs_arc
+ zone . . . . . . . . $enable_zone
zookeeper . . . . . . $enable_zookeeper
EOF
diff --git a/contrib/README b/contrib/README
index 1ebf1f146e6332ce88f90b894ec233bbbc196946..897d61978c32532c535d635cf96c1bdac781007e 100644 (file)
--- a/contrib/README
+++ b/contrib/README
RRD-file that should have been in multiple RRD-files instead. Is is used by
`migrate-3-4.px' to split up the cpu-, nfs-, swap-files and possibly others.
-fedora/
--------
- Init-script and Spec-file that can be used when creating RPM-packages for
-Fedora.
-
GenericJMX.conf
---------------
Example configuration file for the ‘GenericJMX’ Java plugin. Please read the
diff --git a/contrib/collectd.service b/contrib/collectd.service
--- a/contrib/collectd.service
+++ /dev/null
@@ -1,15 +0,0 @@
-[Unit]
-Description=statistics collection daemon
-Documentation=man:collectd(1)
-After=local-fs.target network.target
-Requires=local-fs.target network.target
-
-[Service]
-ExecStart=/usr/sbin/collectd -C /etc/collectd/collectd.conf -f
-Restart=always
-RestartSec=10
-StandardOutput=syslog
-StandardError=syslog
-
-[Install]
-WantedBy=multi-user.target
diff --git a/contrib/fedora/collectd.spec b/contrib/fedora/collectd.spec
+++ /dev/null
@@ -1,376 +0,0 @@
-Summary: Statistics collection daemon for filling RRD files.
-Name: collectd
-Version: 4.2.0
-Release: 1.fc6
-Source: http://collectd.org/files/%{name}-%{version}.tar.gz
-License: GPL
-Group: System Environment/Daemons
-BuildRoot: %{_tmppath}/%{name}-%{version}-root
-BuildPrereq: lm_sensors-devel
-BuildPrereq: mysql-devel
-BuildPrereq: rrdtool-devel
-BuildPrereq: net-snmp-devel
-Requires: rrdtool
-Requires: perl-Regexp-Common
-Packager: Florian octo Forster <octo@verplant.org>
-Vendor: Florian octo Forster <octo@verplant.org>
-
-%description
-collectd is a small daemon written in C for performance. It reads various
-system statistics and updates RRD files, creating them if neccessary.
-Since the daemon doesn't need to startup every time it wants to update the
-files it's very fast and easy on the system. Also, the statistics are very
-fine grained since the files are updated every 10 seconds.
-
-%package apache
-Summary: apache-plugin for collectd.
-Group: System Environment/Daemons
-Requires: collectd = %{version}, curl
-%description apache
-This plugin collectd data provided by Apache's `mod_status'.
-
-%package email
-Summary: email-plugin for collectd.
-Group: System Environment/Daemons
-Requires: collectd = %{version}, spamassassin
-%description email
-This plugin collectd data provided by spamassassin.
-
-%package mysql
-Summary: mysql-module for collectd.
-Group: System Environment/Daemons
-Requires: collectd = %{version}, mysql
-%description mysql
-MySQL querying plugin. This plugins provides data of issued commands,
-called handlers and database traffic.
-
-%package sensors
-Summary: libsensors-module for collectd.
-Group: System Environment/Daemons
-Requires: collectd = %{version}, lm_sensors
-%description sensors
-This plugin for collectd provides querying of sensors supported by
-lm_sensors.
-
-%prep
-rm -rf $RPM_BUILD_ROOT
-%setup
-
-%build
-./configure --prefix=%{_prefix} --sbindir=%{_sbindir} --mandir=%{_mandir} --libdir=%{_libdir} --sysconfdir=%{_sysconfdir}
-make
-
-%install
-make install DESTDIR=$RPM_BUILD_ROOT
-mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
-mkdir -p $RPM_BUILD_ROOT/var/www/cgi-bin
-cp src/collectd.conf $RPM_BUILD_ROOT/etc/collectd.conf
-cp contrib/fedora/init.d-collectd $RPM_BUILD_ROOT/etc/rc.d/init.d/collectd
-cp contrib/collection.cgi $RPM_BUILD_ROOT/var/www/cgi-bin
-cp contrib/collection.conf $RPM_BUILD_ROOT/etc/collection.conf
-mkdir -p $RPM_BUILD_ROOT/var/lib/collectd
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%post
-/sbin/chkconfig --add collectd
-/sbin/chkconfig collectd on
-
-%preun
-if [ "$1" = 0 ]; then
- /sbin/chkconfig collectd off
- /etc/init.d/collectd stop
- /sbin/chkconfig --del collectd
-fi
-exit 0
-
-%postun
-if [ "$1" -ge 1 ]; then
- /etc/init.d/collectd restart
-fi
-exit 0
-
-%files
-%defattr(-,root,root)
-%doc AUTHORS COPYING ChangeLog INSTALL NEWS README
-%attr(0644,root,root) %config(noreplace) /etc/collectd.conf
-%attr(0644,root,root) %config(noreplace) /etc/collection.conf
-%attr(0755,root,root) /etc/rc.d/init.d/collectd
-%attr(0755,root,root) /var/www/cgi-bin/collection.cgi
-%attr(0755,root,root) %{_sbindir}/collectd
-%attr(0755,root,root) %{_bindir}/collectd-nagios
-%attr(0644,root,root) %{_mandir}/man1/*
-%attr(0644,root,root) %{_mandir}/man5/*
-
-%attr(0644,root,root) /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod
-%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/Collectd.pm
-%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/Collectd/Unixsock.pm
-%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/Collectd/.packlist
-%attr(0644,root,root) %{_mandir}/man3/Collectd::Unixsock.3pm.gz
-
-%attr(0644,root,root) %{_libdir}/%{name}/apcups.so*
-%attr(0644,root,root) %{_libdir}/%{name}/apcups.la
-
-# FIXME!!!
-#%attr(0644,root,root) %{_libdir}/%{name}/apple_sensors.so*
-#%attr(0644,root,root) %{_libdir}/%{name}/apple_sensors.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/battery.so*
-%attr(0644,root,root) %{_libdir}/%{name}/battery.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/conntrack.so*
-%attr(0644,root,root) %{_libdir}/%{name}/conntrack.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/cpufreq.so*
-%attr(0644,root,root) %{_libdir}/%{name}/cpufreq.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/cpu.so*
-%attr(0644,root,root) %{_libdir}/%{name}/cpu.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/csv.so*
-%attr(0644,root,root) %{_libdir}/%{name}/csv.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/df.so*
-%attr(0644,root,root) %{_libdir}/%{name}/df.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/disk.so*
-%attr(0644,root,root) %{_libdir}/%{name}/disk.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/dns.so*
-%attr(0644,root,root) %{_libdir}/%{name}/dns.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/entropy.so*
-%attr(0644,root,root) %{_libdir}/%{name}/entropy.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/exec.so*
-%attr(0644,root,root) %{_libdir}/%{name}/exec.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/hddtemp.so*
-%attr(0644,root,root) %{_libdir}/%{name}/hddtemp.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/interface.so*
-%attr(0644,root,root) %{_libdir}/%{name}/interface.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/iptables.so*
-%attr(0644,root,root) %{_libdir}/%{name}/iptables.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/irq.so*
-%attr(0644,root,root) %{_libdir}/%{name}/irq.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/load.so*
-%attr(0644,root,root) %{_libdir}/%{name}/load.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/logfile.so*
-%attr(0644,root,root) %{_libdir}/%{name}/logfile.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/mbmon.so*
-%attr(0644,root,root) %{_libdir}/%{name}/mbmon.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/memcached.so*
-%attr(0644,root,root) %{_libdir}/%{name}/memcached.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/memory.so*
-%attr(0644,root,root) %{_libdir}/%{name}/memory.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/multimeter.so*
-%attr(0644,root,root) %{_libdir}/%{name}/multimeter.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/network.so*
-%attr(0644,root,root) %{_libdir}/%{name}/network.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/nfs.so*
-%attr(0644,root,root) %{_libdir}/%{name}/nfs.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/nginx.so*
-%attr(0644,root,root) %{_libdir}/%{name}/nginx.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/ntpd.so*
-%attr(0644,root,root) %{_libdir}/%{name}/ntpd.la
-
-# FIXME!!!
-#%attr(0644,root,root) %{_libdir}/%{name}/nut.so*
-#%attr(0644,root,root) %{_libdir}/%{name}/nut.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/perl.so*
-%attr(0644,root,root) %{_libdir}/%{name}/perl.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/ping.so*
-%attr(0644,root,root) %{_libdir}/%{name}/ping.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/processes.so*
-%attr(0644,root,root) %{_libdir}/%{name}/processes.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/rrdtool.so*
-%attr(0644,root,root) %{_libdir}/%{name}/rrdtool.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/serial.so*
-%attr(0644,root,root) %{_libdir}/%{name}/serial.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/swap.so*
-%attr(0644,root,root) %{_libdir}/%{name}/swap.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/snmp.so*
-%attr(0644,root,root) %{_libdir}/%{name}/snmp.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/syslog.so*
-%attr(0644,root,root) %{_libdir}/%{name}/syslog.la
-
-# FIXME!!!
-#%attr(0644,root,root) %{_libdir}/%{name}/tape.so*
-#%attr(0644,root,root) %{_libdir}/%{name}/tape.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/tcpconns.so*
-%attr(0644,root,root) %{_libdir}/%{name}/tcpconns.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/unixsock.so*
-%attr(0644,root,root) %{_libdir}/%{name}/unixsock.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/users.so*
-%attr(0644,root,root) %{_libdir}/%{name}/users.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/vserver.so*
-%attr(0644,root,root) %{_libdir}/%{name}/vserver.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/wireless.so*
-%attr(0644,root,root) %{_libdir}/%{name}/wireless.la
-
-%attr(0644,root,root) %{_datadir}/%{name}/types.db
-
-%dir /var/lib/collectd
-
-%files apache
-%attr(0644,root,root) %{_libdir}/%{name}/apache.so*
-%attr(0644,root,root) %{_libdir}/%{name}/apache.la
-
-%files email
-%attr(0644,root,root) %{_libdir}/%{name}/email.so*
-%attr(0644,root,root) %{_libdir}/%{name}/email.la
-
-%files mysql
-%attr(0644,root,root) %{_libdir}/%{name}/mysql.so*
-%attr(0644,root,root) %{_libdir}/%{name}/mysql.la
-
-%files sensors
-%attr(0644,root,root) %{_libdir}/%{name}/sensors.so*
-%attr(0644,root,root) %{_libdir}/%{name}/sensors.la
-
-%changelog
-* Wed Oct 31 2007 Iain Lea <iain@bricbrac.de> 4.2.0
-- New major release
-- Changes to support 4.2.0 (ie. contrib/collection.conf)
-
-* Mon Aug 06 2007 Kjell Randa <Kjell.Randa@broadpark.no> 4.0.6
-- New upstream version
-
-* Wed Jul 25 2007 Kjell Randa <Kjell.Randa@broadpark.no> 4.0.5
-- New major release
-- Changes to support 4.0.5
-
-* Wed Jan 11 2007 Iain Lea <iain@bricbrac.de> 3.11.0-0
-- fixed spec file to build correctly on fedora core
-- added improved init.d script to work with chkconfig
-- added %post and %postun to call chkconfig automatically
-
-* Sun Jul 09 2006 Florian octo Forster <octo@verplant.org> 3.10.0-1
-- New upstream version
-
-* Tue Jun 25 2006 Florian octo Forster <octo@verplant.org> 3.9.4-1
-- New upstream version
-
-* Tue Jun 01 2006 Florian octo Forster <octo@verplant.org> 3.9.3-1
-- New upstream version
-
-* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.9.2-1
-- New upstream version
-
-* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.8.5-1
-- New upstream version
-
-* Fri Apr 21 2006 Florian octo Forster <octo@verplant.org> 3.9.1-1
-- New upstream version
-
-* Fri Apr 14 2006 Florian octo Forster <octo@verplant.org> 3.9.0-1
-- New upstream version
-- Added the `apache' package.
-
-* Thu Mar 14 2006 Florian octo Forster <octo@verplant.org> 3.8.2-1
-- New upstream version
-
-* Thu Mar 13 2006 Florian octo Forster <octo@verplant.org> 3.8.1-1
-- New upstream version
-
-* Thu Mar 09 2006 Florian octo Forster <octo@verplant.org> 3.8.0-1
-- New upstream version
-
-* Sat Feb 18 2006 Florian octo Forster <octo@verplant.org> 3.7.2-1
-- Include `tape.so' so the build doesn't terminate because of missing files..
-- New upstream version
-
-* Sat Feb 04 2006 Florian octo Forster <octo@verplant.org> 3.7.1-1
-- New upstream version
-
-* Mon Jan 30 2006 Florian octo Forster <octo@verplant.org> 3.7.0-1
-- New upstream version
-- Removed the extra `hddtemp' package
-
-* Tue Jan 24 2006 Florian octo Forster <octo@verplant.org> 3.6.2-1
-- New upstream version
-
-* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.1-1
-- New upstream version
-
-* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.0-1
-- New upstream version
-- Added config file, `collectd.conf(5)', `df.so'
-- Added package `collectd-mysql', dependency on `mysqlclient10 | mysql'
-
-* Wed Dec 07 2005 Florian octo Forster <octo@verplant.org> 3.5.0-1
-- New upstream version
-
-* Sat Nov 26 2005 Florian octo Forster <octo@verplant.org> 3.4.0-1
-- New upstream version
-
-* Sat Nov 05 2005 Florian octo Forster <octo@verplant.org> 3.3.0-1
-- New upstream version
-
-* Tue Oct 26 2005 Florian octo Forster <octo@verplant.org> 3.2.0-1
-- New upstream version
-- Added statement to remove the `*.la' files. This fixes a problem when
- `Unpackaged files terminate build' is in effect.
-- Added `processes.so*' to the main package
-
-* Fri Oct 14 2005 Florian octo Forster <octo@verplant.org> 3.1.0-1
-- New upstream version
-- Added package `collectd-hddtemp'
-
-* Fri Sep 30 2005 Florian octo Forster <octo@verplant.org> 3.0.0-1
-- New upstream version
-- Split the package into `collectd' and `collectd-sensors'
-
-* Fri Sep 16 2005 Florian octo Forster <octo@verplant.org> 2.1.0-1
-- New upstream version
-
-* Mon Sep 10 2005 Florian octo Forster <octo@verplant.org> 2.0.0-1
-- New upstream version
-
-* Mon Aug 29 2005 Florian octo Forster <octo@verplant.org> 1.8.0-1
-- New upstream version
-
-* Sun Aug 25 2005 Florian octo Forster <octo@verplant.org> 1.7.0-1
-- New upstream version
-
-* Sun Aug 21 2005 Florian octo Forster <octo@verplant.org> 1.6.0-1
-- New upstream version
-
-* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5.1-1
-- New upstream version
-
-* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5-1
-- New upstream version
-
-* Mon Jul 11 2005 Florian octo Forster <octo@verplant.org> 1.4.2-1
-- New upstream version
-
-* Sat Jul 09 2005 Florian octo Forster <octo@verplant.org> 1.4-1
-- Built on RedHat 7.3
diff --git a/contrib/fedora/init.d-collectd b/contrib/fedora/init.d-collectd
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/bash
-#
-# collectd Startup script for the Collectd statistics gathering daemon
-# chkconfig: - 86 15
-# description: Collectd is a statistics gathering daemon used to collect \
-# system information ie. cpu, memory, disk, network
-# processname: collectd
-# config: /etc/collectd.conf
-# config: /etc/sysconfig/collectd
-# pidfile: /var/run/collectd.pid
-
-# Source function library.
-. /etc/init.d/functions
-
-RETVAL=0
-ARGS=""
-prog="collectd"
-CONFIG=/etc/collectd.conf
-
-if [ -r /etc/default/$prog ]; then
- . /etc/default/$prog
-fi
-
-start () {
- echo -n $"Starting $prog: "
- if [ -r "$CONFIG" ]
- then
- daemon /usr/sbin/collectd -C "$CONFIG"
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
- fi
-}
-stop () {
- echo -n $"Stopping $prog: "
- killproc $prog
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
-}
-# See how we were called.
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status $prog
- ;;
- restart|reload)
- stop
- start
- ;;
- condrestart)
- [ -f /var/lock/subsys/$prog ] && stop && start || :
- ;;
- *)
- echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
- exit 1
-esac
-
-exit $?
-
-# vim:syntax=sh
index 1a8eb0e3594dacefbd045fa2798b96270edc6766..4d4e0aa21a254289efddd9a29166599cd485e6a2 100644 (file)
%{?el7:%global _has_atasmart 1}
%{?el7:%global _has_hiredis 1}
%{?el7:%global _has_asm_msr_index 1}
+%{?el7:%global _has_libmosquitto 1}
%{?el7:%global _has_libmodbus 1}
%{?el7:%global _has_xmms 1}
%define with_memory 0%{!?_without_memory:1}
%define with_multimeter 0%{!?_without_multimeter:1}
%define with_modbus 0%{!?_without_modbus:0%{?_has_libmodbus}}
+%define with_mqtt 0%{!?_without_mqtt:0%{?_has_libmosquitto}}
%define with_mysql 0%{!?_without_mysql:1}
%define with_netlink 0%{!?_without_netlink:0%{?_has_iproute}}
%define with_network 0%{!?_without_network:1}
%define with_nginx 0%{!?_without_nginx:1}
%define with_notify_desktop 0%{!?_without_notify_desktop:1}
%define with_notify_email 0%{!?_without_notify_email:1}
+%define with_notify_nagios 0%{!?_without_notify_nagios:1}
%define with_ntpd 0%{!?_without_ntpd:1}
%define with_numa 0%{!?_without_numa:1}
%define with_nut 0%{!?_without_nut:1}
%define with_write_kafka 0%{!?_without_write_kafka:0}
# plugin write_mongodb disabled, requires libmongoc
%define with_write_mongodb 0%{!?_without_write_mongodb:0}
+# plugin zone disabled, requires Solaris
+%define with_zone 0%{!?_without_zone:0}
Summary: statistics collection and monitoring daemon
Name: collectd
handlers and database traffic.
%endif
+%if %{with_mqtt}
+%package mqtt
+Summary: mqtt plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: mosquitto-devel
+%description mqtt
+The MQTT plugin publishes and subscribes to MQTT topics.
+%endif
+
%if %{with_netlink}
%package netlink
Summary: netlink plugin for collectd
%define _with_multimeter --disable-multimeter
%endif
+%if %{with_mqtt}
+%define _with_mqtt --enable-mqtt
+%else
+%define _with_mqtt --disable-mqtt
+%endif
+
%if %{with_mysql}
%define _with_mysql --enable-mysql
%else
%define _with_notify_email --disable-notify_email
%endif
+%if %{with_notify_nagios}
+%define _with_notify_nagios --enable-notify_nagios
+%else
+%define _with_notify_nagios --disable-notify_nagios
+%endif
+
%if %{with_ntpd}
%define _with_ntpd --enable-ntpd
%else
%define _with_zfs_arc --disable-zfs_arc
%endif
+%if %{with_zone}
+%define _with_zone --enable-zone
+%else
+%define _with_zone --disable-zone
+%endif
+
%if %{with_zookeeper}
%define _with_zookeeper --enable-zookeeper
%else
%{?_with_mic} \
%{?_with_modbus} \
%{?_with_multimeter} \
+ %{?_with_mqtt} \
%{?_with_mysql} \
%{?_with_netapp} \
%{?_with_netlink} \
%{?_with_write_redis} \
%{?_with_xmms} \
%{?_with_zfs_arc} \
+ %{?_with_zone} \
%{?_with_zookeeper} \
%{?_with_irq} \
%{?_with_load} \
%{?_with_memory} \
%{?_with_network} \
%{?_with_nfs} \
+ %{?_with_notify_nagios} \
%{?_with_ntpd} \
%{?_with_numa} \
%{?_with_olsrd} \
%if %{with_nfs}
%{_libdir}/%{name}/nfs.so
%endif
+%if %{with_notify_nagios}
+%{_libdir}/%{name}/notify_nagios.so
+%endif
%if %{with_ntpd}
%{_libdir}/%{name}/ntpd.so
%endif
%{_libdir}/%{name}/modbus.so
%endif
+%if %{with_mqtt}
+%files mqtt
+%{_libdir}/%{name}/mqtt.so
+%endif
+
%if %{with_mysql}
%files mysql
%{_libdir}/%{name}/mysql.so
%doc contrib/
%changelog
+#* TODO: next feature release changelog
+#- New upstream version
+#- New plugins enabled by default: mqtt, notify_nagios
+#- New plugins disabled by default: zone
+#
* Wed May 27 2015 Marc Fournier <marc.fournier@camptocamp.com> 5.5.0-1
- New upstream version
- New plugins enabled by default: ceph, drbd, log_logstash, write_tsdb, smart,
diff --git a/src/Makefile.am b/src/Makefile.am
index 9b845cae6046dbef8774df2142061370a5d8a1af..3832bd241dea8ddcc8542fe743238e822a9b290f 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
PLUGIN_LDFLAGS = -module -avoid-version -export-symbols-regex '\<module_register\>'
-if COMPILER_IS_GCC
-AM_CFLAGS = -Wall -Werror
-endif
-
AM_CPPFLAGS = -I$(srcdir)/daemon
AM_CPPFLAGS += -DPREFIX='"${prefix}"'
AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
AUTOMAKE_OPTIONS = subdir-objects
-noinst_LTLIBRARIES = libmount.la liblookup.la
+noinst_LTLIBRARIES =
+check_PROGRAMS =
+TESTS =
-libmount_la_SOURCES = utils_mount.c utils_mount.h
-libmount_la_LIBADD = daemon/libcommon.la
+noinst_LTLIBRARIES += liblatency.la
+liblatency_la_SOURCES = utils_latency.c utils_latency.h
+check_PROGRAMS += test_utils_latency
+TESTS += test_utils_latency
+test_utils_latency_SOURCES = utils_latency_test.c testing.h
+test_utils_latency_LDADD = liblatency.la daemon/libplugin_mock.la -lm
+noinst_LTLIBRARIES += liblookup.la
liblookup_la_SOURCES = utils_vl_lookup.c utils_vl_lookup.h
-liblookup_la_LIBADD = daemon/libavltree.la daemon/libcommon.la
+liblookup_la_LIBADD = daemon/libavltree.la
+check_PROGRAMS += test_utils_vl_lookup
+TESTS += test_utils_vl_lookup
+test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h
+test_utils_vl_lookup_LDADD = liblookup.la daemon/libplugin_mock.la
+if BUILD_WITH_LIBKSTAT
+test_utils_vl_lookup_LDADD += -lkstat
+endif
+
+noinst_LTLIBRARIES += libmount.la
+libmount_la_SOURCES = utils_mount.c utils_mount.h
+check_PROGRAMS += test_utils_mount
+TESTS += test_utils_mount
+test_utils_mount_SOURCES = utils_mount_test.c testing.h
+test_utils_mount_LDADD = libmount.la daemon/libplugin_mock.la
+if BUILD_WITH_LIBKSTAT
+test_utils_mount_LDADD += -lkstat
+endif
sbin_PROGRAMS = collectdmon
bin_PROGRAMS = collectd-nagios collectdctl collectd-tg
collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la
collectd_tg_SOURCES = collectd-tg.c
-collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
collectd_tg_LDADD = daemon/libheap.la
if BUILD_WITH_LIBSOCKET
collectd_tg_LDADD += -lsocket
collectd_tg_LDADD += -lm
endif
if BUILD_WITH_LIBPTHREAD
-collectd_tg_LDADD += -lpthread
+collectd_tg_LDADD += $(PTHREAD_LIBS)
endif
collectd_tg_LDADD += libcollectdclient/libcollectdclient.la
collectd_tg_DEPENDENCIES = libcollectdclient/libcollectdclient.la
if BUILD_WITH_LIBUDEV
disk_la_LIBADD += -ludev
endif
+if BUILD_FREEBSD
+disk_la_LIBADD += -ldevstat -lgeom
+endif
if BUILD_WITH_PERFSTAT
disk_la_LIBADD += -lperfstat
endif
pkglib_LTLIBRARIES += dns.la
dns_la_SOURCES = dns.c utils_dns.c utils_dns.h
dns_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-dns_la_LIBADD = -lpcap -lpthread
+dns_la_LIBADD = $(PTHREAD_LIBS) -lpcap
endif
if BUILD_PLUGIN_DRBD
pkglib_LTLIBRARIES += drbd.la
drbd_la_SOURCES = drbd.c
drbd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-drbd_la_LIBADD = -lpthread
endif
if BUILD_PLUGIN_EMAIL
pkglib_LTLIBRARIES += email.la
email_la_SOURCES = email.c
email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-email_la_LIBADD = -lpthread
+email_la_LIBADD = $(PTHREAD_LIBS)
endif
if BUILD_PLUGIN_ENTROPY
utils_cmd_putval.c utils_cmd_putval.h \
utils_parse_option.h utils_parse_option.c
exec_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-exec_la_LIBADD = -lpthread
+exec_la_LIBADD = $(PTHREAD_LIBS)
endif
if BUILD_PLUGIN_ETHSTAT
ipvs_la_SOURCES = ipvs.c
if IP_VS_H_NEEDS_KERNEL_CFLAGS
ipvs_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
+else
+ipvs_la_CFLAGS = $(AM_CFLAGS)
endif
ipvs_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
java_la_CPPFLAGS = $(AM_CPPFLAGS) $(JAVA_CPPFLAGS)
java_la_CFLAGS = $(AM_CFLAGS) $(JAVA_CFLAGS)
java_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(JAVA_LDFLAGS)
-java_la_LIBADD = $(JAVA_LIBS)
+java_la_LIBADD = $(PTHREAD_LIBS) $(JAVA_LIBS)
endif
if BUILD_PLUGIN_LOAD
modbus_la_LIBADD = $(BUILD_WITH_LIBMODBUS_LIBS)
endif
+if BUILD_PLUGIN_MQTT
+pkglib_LTLIBRARIES += mqtt.la
+mqtt_la_SOURCES = mqtt.c
+mqtt_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMOSQUITTO_CPPFLAGS)
+mqtt_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBMOSQUITTO_LDFLAGS)
+mqtt_la_LIBADD = $(BUILD_WITH_LIBMOSQUITTO_LIBS)
+endif
+
if BUILD_PLUGIN_MULTIMETER
pkglib_LTLIBRARIES += multimeter.la
multimeter_la_SOURCES = multimeter.c
utils_fbhash.c utils_fbhash.h
network_la_CPPFLAGS = $(AM_CPPFLAGS)
network_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-network_la_LIBADD = -lpthread
+network_la_LIBADD = $(PTHREAD_LIBS)
if BUILD_WITH_LIBSOCKET
network_la_LIBADD += -lsocket
endif
pkglib_LTLIBRARIES += notify_email.la
notify_email_la_SOURCES = notify_email.c
notify_email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-notify_email_la_LIBADD = -lesmtp -lssl -lcrypto -lpthread
+notify_email_la_LIBADD = $(PTHREAD_LIBS) -lesmtp -lssl -lcrypto
+endif
+
+if BUILD_PLUGIN_NOTIFY_NAGIOS
+pkglib_LTLIBRARIES += notify_nagios.la
+notify_nagios_la_SOURCES = notify_nagios.c
+notify_nagios_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
if BUILD_PLUGIN_NTPD
nut_la_SOURCES = nut.c
nut_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBUPSCLIENT_CFLAGS)
nut_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-nut_la_LIBADD = -lpthread $(BUILD_WITH_LIBUPSCLIENT_LIBS)
+nut_la_LIBADD = $(PTHREAD_LIBS) $(BUILD_WITH_LIBUPSCLIENT_LIBS)
endif
if BUILD_PLUGIN_OLSRD
onewire_la_CFLAGS = $(AM_CFLAGS)
onewire_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS)
-onewire_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+onewire_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBOWCAPI_LDFLAGS)
endif
if BUILD_PLUGIN_OPENLDAP
snmp_la_LIBADD += $(BUILD_WITH_LIBSNMP_LIBS)
endif
if BUILD_WITH_LIBPTHREAD
-snmp_la_LIBADD += -lpthread
+snmp_la_LIBADD += $(PTHREAD_LIBS)
endif
endif
if BUILD_PLUGIN_STATSD
pkglib_LTLIBRARIES += statsd.la
-statsd_la_SOURCES = statsd.c \
- utils_latency.h utils_latency.c
+statsd_la_SOURCES = statsd.c
statsd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-statsd_la_LIBADD = -lpthread -lm
+statsd_la_LIBADD = $(PTHREAD_LIBS) liblatency.la -lm
endif
if BUILD_PLUGIN_SWAP
utils_cmd_putnotif.h utils_cmd_putnotif.c \
utils_parse_option.h utils_parse_option.c
unixsock_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-unixsock_la_LIBADD = -lpthread
+unixsock_la_LIBADD = $(PTHREAD_LIBS)
endif
if BUILD_PLUGIN_UPTIME
BUILT_SOURCES += $(dist_man_MANS)
+if BUILD_PLUGIN_ZONE
+pkglib_LTLIBRARIES += zone.la
+zone_la_SOURCES = zone.c
+zone_la_CFLAGS = $(AM_CFLAGS)
+zone_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
dist_man_MANS = collectd.1 \
collectd.conf.5 \
collectd-email.5 \
rm -f $(DESTDIR)$(sysconfdir)/collectd.conf
rm -f $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
-check_PROGRAMS = test_utils_mount test_utils_vl_lookup
-
-test_utils_mount_SOURCES = utils_mount_test.c testing.h
-test_utils_mount_LDADD = libmount.la daemon/libplugin_mock.la
-
-test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h
-test_utils_vl_lookup_LDADD = liblookup.la daemon/libplugin_mock.la
-
-TESTS = test_utils_mount test_utils_vl_lookup
-
if BUILD_PLUGIN_CEPH
test_plugin_ceph_SOURCES = ceph_test.c
test_plugin_ceph_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
diff --git a/src/apache.c b/src/apache.c
index c515e3c5db57a45bc04e706db387d02b5a27ba24..38035caa22e94cfdeeaac8ef1047ddf443a40fdd 100644 (file)
--- a/src/apache.c
+++ b/src/apache.c
status = plugin_register_complex_read (/* group = */ NULL,
/* name = */ callback_name,
/* callback = */ apache_read_host,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user_data = */ &ud);
}
if (st->timeout >= 0)
curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS, (long) st->timeout);
else
- curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
diff --git a/src/apcups.c b/src/apcups.c
index 281bf9803bdd6e6a84086b152f14b623961337b7..b4bc0997e6c3e7d309d13e23225edef31ca7f465 100644 (file)
--- a/src/apcups.c
+++ b/src/apcups.c
/*
* collectd - src/apcups.c
- * Copyright (C) 2006-2012 Florian octo Forster
+ * Copyright (C) 2006-2015 Florian octo Forster
* Copyright (C) 2006 Anthony Gialluca <tonyabg at charter.net>
* Copyright (C) 2000-2004 Kern Sibbald
* Copyright (C) 1996-1999 Andre M. Hedrick <andre at suse.com>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NETDB_H
# include <netdb.h>
#endif
# include <netinet/in.h>
#endif
-#define NISPORT 3551
-#define MAXSTRING 256
-#define MODULE_NAME "apcups"
+#ifndef APCUPS_DEFAULT_NODE
+# define APCUPS_DEFAULT_NODE "localhost"
+#endif
-#define APCUPS_DEFAULT_HOST "localhost"
+#ifndef APCUPS_DEFAULT_SERVICE
+# define APCUPS_DEFAULT_SERVICE "3551"
+#endif
/*
* Private data types
* Private variables
*/
/* Default values for contacting daemon */
-static char *conf_host = NULL;
-static int conf_port = NISPORT;
+static char *conf_node = NULL;
+static char *conf_service = NULL;
/* Defaults to false for backwards compatibility. */
static _Bool conf_report_seconds = 0;
+static _Bool conf_persistent_conn = 1;
static int global_sockfd = -1;
static int count_retries = 0;
static int count_iterations = 0;
-static _Bool close_socket = 0;
-
-static const char *config_keys[] =
-{
- "Host",
- "Port",
- "ReportSeconds"
-};
-static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
static int net_shutdown (int *fd)
{
* Returns -1 on error
* Returns socket file descriptor otherwise
*/
-static int net_open (char *host, int port)
+static int net_open (char const *node, char const *service)
{
int sd;
int status;
- char port_str[8];
struct addrinfo ai_hints;
struct addrinfo *ai_return;
struct addrinfo *ai_list;
- assert ((port > 0x00000000) && (port <= 0x0000FFFF));
-
- /* Convert the port to a string */
- ssnprintf (port_str, sizeof (port_str), "%i", port);
-
/* Resolve name */
- memset ((void *) &ai_hints, '\0', sizeof (ai_hints));
- ai_hints.ai_family = AF_INET; /* XXX: Change this to `AF_UNSPEC' if apcupsd can handle IPv6 */
+ memset (&ai_hints, 0, sizeof (ai_hints));
+ /* TODO: Change this to `AF_UNSPEC' if apcupsd can handle IPv6 */
+ ai_hints.ai_family = AF_INET;
ai_hints.ai_socktype = SOCK_STREAM;
- status = getaddrinfo (host, port_str, &ai_hints, &ai_return);
+ status = getaddrinfo (node, service, &ai_hints, &ai_return);
if (status != 0)
{
char errbuf[1024];
DEBUG ("apcups plugin: Done opening a socket %i", sd);
return (sd);
-} /* int net_open (char *host, char *service, int port) */
+} /* int net_open */
/*
* Receive a message from the other end. Each message consists of
* Returns zero on success
* Returns non-zero on error
*/
-static int net_send (int *sockfd, char *buff, int len)
+static int net_send (int *sockfd, const char *buff, int len)
{
uint16_t packet_size;
}
/* Get and print status from apcupsd NIS server */
-static int apc_query_server (char *host, int port,
+static int apc_query_server (char const *node, char const *service,
struct apc_detail_s *apcups_detail)
{
int n;
{
if (global_sockfd < 0)
{
- global_sockfd = net_open (host, port);
+ global_sockfd = net_open (node, service);
if (global_sockfd < 0)
{
ERROR ("apcups plugin: Connecting to the "
"first %i iterations. Will close the socket "
"in future iterations.",
count_retries, count_iterations);
- close_socket = 1;
+ conf_persistent_conn = 0;
}
while ((n = net_recv (&global_sockfd, recvline, sizeof (recvline) - 1)) > 0)
{
- assert ((unsigned int)n < sizeof (recvline));
- recvline[n] = '\0';
+ assert ((size_t)n < sizeof (recvline));
+ recvline[n] = 0;
#if APCMAIN
printf ("net_recv = `%s';\n", recvline);
#endif /* if APCMAIN */
+ if (strncmp ("END APC", recvline, strlen ("END APC")) == 0)
+ break;
+
toksaveptr = NULL;
tokptr = strtok_r (recvline, " :\t", &toksaveptr);
while (tokptr != NULL)
}
status = errno; /* save errno, net_shutdown() may re-set it. */
- if (close_socket)
+ if (!conf_persistent_conn)
net_shutdown (&global_sockfd);
if (n < 0)
return (0);
}
-static int apcups_config (const char *key, const char *value)
+static int apcups_config (oconfig_item_t *ci)
{
- if (strcasecmp (key, "host") == 0)
- {
- if (conf_host != NULL)
- {
- free (conf_host);
- conf_host = NULL;
- }
- if ((conf_host = strdup (value)) == NULL)
- return (1);
- }
- else if (strcasecmp (key, "Port") == 0)
- {
- int port_tmp = atoi (value);
- if (port_tmp < 1 || port_tmp > 65535)
- {
- WARNING ("apcups plugin: Invalid port: %i", port_tmp);
- return (1);
- }
- conf_port = port_tmp;
- }
- else if (strcasecmp (key, "ReportSeconds") == 0)
+ int i;
+
+ for (i = 0; i < ci->children_num; i++)
{
- if (IS_TRUE (value))
- conf_report_seconds = 1;
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp (child->key, "Host") == 0)
+ cf_util_get_string (child, &conf_node);
+ else if (strcasecmp (child->key, "Port") == 0)
+ cf_util_get_service (child, &conf_service);
+ else if (strcasecmp (child->key, "ReportSeconds") == 0)
+ cf_util_get_boolean (child, &conf_report_seconds);
+ else if (strcasecmp (child->key, "PersistentConnection") == 0)
+ cf_util_get_boolean (child, &conf_persistent_conn);
else
- conf_report_seconds = 0;
- }
- else
- {
- return (-1);
+ ERROR ("apcups plugin: Unknown config option \"%s\".", child->key);
}
+
return (0);
-}
+} /* int apcups_config */
-static void apc_submit_generic (char *type, char *type_inst, double value)
+static void apc_submit_generic (const char *type, const char *type_inst, double value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
apcups_detail.itemp = -300.0;
apcups_detail.linefreq = -1.0;
- status = apc_query_server (conf_host == NULL
- ? APCUPS_DEFAULT_HOST
- : conf_host,
- conf_port, &apcups_detail);
+ status = apc_query_server ((conf_node == NULL) ? APCUPS_DEFAULT_NODE : conf_node,
+ (conf_service == NULL) ? APCUPS_DEFAULT_SERVICE : conf_service,
+ &apcups_detail);
/*
* if we did not connect then do not bother submitting
*/
if (status != 0)
{
- DEBUG ("apcups plugin: apc_query_server (%s, %i) = %i",
- conf_host == NULL
- ? APCUPS_DEFAULT_HOST
- : conf_host,
- conf_port, status);
+ DEBUG ("apcups plugin: apc_query_server (%s, %s) = %i",
+ (conf_node == NULL) ? APCUPS_DEFAULT_NODE : conf_node,
+ (conf_service == NULL) ? APCUPS_DEFAULT_SERVICE : conf_service,
+ status);
return (-1);
}
void module_register (void)
{
- plugin_register_config ("apcups", apcups_config, config_keys,
- config_keys_num);
+ plugin_register_complex_config ("apcups", apcups_config);
plugin_register_read ("apcups", apcups_read);
plugin_register_shutdown ("apcups", apcups_shutdown);
} /* void module_register */
diff --git a/src/ascent.c b/src/ascent.c
index 11175af5e6104afa7b39291fd77fd45441a0cb64..d38e85916e937468c13dfb1d33e6706991fd261b 100644 (file)
--- a/src/ascent.c
+++ b/src/ascent.c
#include <curl/curl.h>
#include <libxml/parser.h>
-static char *races_list[] = /* {{{ */
+static const char *races_list[] = /* {{{ */
{
NULL,
"Human", /* 1 */
}; /* }}} */
#define RACES_LIST_LENGTH STATIC_ARRAY_SIZE (races_list)
-static char *classes_list[] = /* {{{ */
+static const char *classes_list[] = /* {{{ */
{
NULL,
"Warrior", /* 1 */
}; /* }}} */
#define CLASSES_LIST_LENGTH STATIC_ARRAY_SIZE (classes_list)
-static char *genders_list[] = /* {{{ */
+static const char *genders_list[] = /* {{{ */
{
"Male",
"Female"
if (timeout != NULL)
curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, atol(timeout));
else
- curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
diff --git a/src/barometer.c b/src/barometer.c
index aaedd70afd075a51293b354c7a792a5f3e81d7ec..0e8deaf82fca1685c8f368850b9eb0b2cea0759b 100644 (file)
--- a/src/barometer.c
+++ b/src/barometer.c
gauge_t * values = NULL; /**< rate values */
size_t values_num = 0; /**< number of rate values */
- int i;
+ size_t i;
gauge_t values_history[REF_TEMP_AVG_NUM];
for(i=0; i<values_num; ++i)
{
- DEBUG ("barometer: get_reference_temperature - rate %d: %lf **",
- i,
- values[i]);
+ DEBUG ("barometer: get_reference_temperature - rate %zu: %lf **",
+ i, values[i]);
if(!isnan(values[i]))
{
avg_sum += values[i];
for(i=0; i<REF_TEMP_AVG_NUM*list->num_values; ++i)
{
- DEBUG ("barometer: get_reference_temperature - history %d: %lf",
- i,
- values_history[i]);
+ DEBUG ("barometer: get_reference_temperature - history %zu: %lf",
+ i, values_history[i]);
if(!isnan(values_history[i]))
{
avg_sum += values_history[i];
for(i=0; i<values_num; ++i)
{
- DEBUG ("barometer: get_reference_temperature - rate last %d: %lf **",
- i,
- values[i]);
+ DEBUG ("barometer: get_reference_temperature - rate last %zu: %lf **",
+ i, values[i]);
if(!isnan(values[i]))
{
avg_sum += values[i];
diff --git a/src/battery.c b/src/battery.c
index c4c050d7ff1cd11cc70cd2d17323f90da747e542..b87739ac7d03affe2f20047d161f77b2b2d85001 100644 (file)
--- a/src/battery.c
+++ b/src/battery.c
} /* }}} void submit_capacity */
#if HAVE_IOKIT_PS_IOPOWERSOURCES_H || HAVE_IOKIT_IOKITLIB_H
-static double dict_get_double (CFDictionaryRef dict, char *key_string) /* {{{ */
+static double dict_get_double (CFDictionaryRef dict, const char *key_string) /* {{{ */
{
double val_double;
long long val_int;
diff --git a/src/bind.c b/src/bind.c
index 6eac159cbcf78b1f36651aa7468f389a9baf74a8..b9731eeee0d89522cd3375239f07e0a4c1c50a96 100644 (file)
--- a/src/bind.c
+++ b/src/bind.c
curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 50L);
#ifdef HAVE_CURLOPT_TIMEOUT_MS
curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (timeout >= 0) ?
- (long) timeout : CDTIME_T_TO_MS(plugin_get_interval()));
+ (long) timeout : (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
diff --git a/src/ceph.c b/src/ceph.c
index 9c53a3e76590e1ba490c83e24c26551815c935cf..b1ca3b66649dce4d6e086910b89ef13f534a7d2c 100644 (file)
--- a/src/ceph.c
+++ b/src/ceph.c
#include <stdlib.h>
#include <string.h>
#include <strings.h>
-#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/un.h>
};
/** Valid types for ceph defined in types.db */
-const char * ceph_dset_types [CEPH_DSET_TYPES_NUM] =
+static const char * const ceph_dset_types [CEPH_DSET_TYPES_NUM] =
{"ceph_latency", "ceph_bytes", "ceph_rate"};
/******* ceph_daemon *******/
diff --git a/src/ceph_test.c b/src/ceph_test.c
index ae67125fc881fe1f63c2e34a0317930b03564bb5..114114068621097b04ebd5992b039fcaf12a91b9 100644 (file)
--- a/src/ceph_test.c
+++ b/src/ceph_test.c
struct case_s
{
- char *key;
- char *value;
+ const char *key;
+ const char *value;
};
typedef struct case_s case_t;
yajl_handle hndl;
#if HAVE_YAJL_V2
hndl = yajl_alloc (&callbacks, NULL, &ctx);
- CHECK_ZERO (traverse_json ((unsigned char *) json, (uint32_t) strlen (json), hndl));
+ CHECK_ZERO (traverse_json ((const unsigned char *) json, (uint32_t) strlen (json), hndl));
CHECK_ZERO (yajl_complete_parse (hndl));
#else
hndl = yajl_alloc (&callbacks, NULL, NULL, &ctx);
- CHECK_ZERO (traverse_json ((unsigned char *) json, (uint32_t) strlen (json), hndl));
+ CHECK_ZERO (traverse_json ((const unsigned char *) json, (uint32_t) strlen (json), hndl));
CHECK_ZERO (yajl_parse_complete (hndl));
#endif
DEF_TEST(parse_keys)
{
struct {
- char *str;
- char *want;
+ const char *str;
+ const char *want;
} cases[] = {
{"WBThrottle.bytes_dirtied.description.bytes_wb.description.ios_dirtied.description.ios_wb.type", "WBThrottle.bytesDirtied.description.bytesWb.description.iosDirt"},
{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
{
char got[DATA_MAX_NAME_LEN];
- memset (got, 0, sizeof (got));
-
CHECK_ZERO (parse_keys (got, sizeof (got), cases[i].str));
-
- CHECK_ZERO (strcmp (got, cases[i].want));
+ EXPECT_EQ_STR (cases[i].want, got);
}
return 0;
diff --git a/src/collectd-java.pod b/src/collectd-java.pod
index aade08a456b701aff4fdc94f70f1907617de1127..afa7e48a6516c1bd82aef5358d3301cbb5827be6 100644 (file)
--- a/src/collectd-java.pod
+++ b/src/collectd-java.pod
Works like the option of the same name directly beneath the I<MBean> block, but
sets the type instance instead. I<(optional)>
+=item B<PluginName> I<name>
+
+When set, overrides the default setting for the I<plugin> field
+(C<GenericJMX>).
+
=item B<Table> B<true>|B<false>
Set this to true if the returned attribute is a I<composite type>. If set to
diff --git a/src/collectd-nagios.c b/src/collectd-nagios.c
index 8b0f867949e1f09c1b8f015598c8dd08e8d8925c..49e84f35f8d2d1d54dcf77a54d130b9b91425275 100644 (file)
--- a/src/collectd-nagios.c
+++ b/src/collectd-nagios.c
static _Bool nan_is_error_g = 0;
static char **match_ds_g = NULL;
-static int match_ds_num_g = 0;
+static size_t match_ds_num_g = 0;
/* `strdup' is an XSI extension. I don't want to pull in all of XSI just for
* that, so here's an own implementation.. It's easy enough. The GCC attributes
return (RET_UNKNOWN);
}
- for (i = 0; i < (size_t) match_ds_num_g; i++)
+ for (i = 0; i < match_ds_num_g; i++)
{
size_t j;
return (((ret - range->invert) == 0) ? 0 : 1);
} /* int match_range */
+__attribute__((noreturn))
static void usage (const char *name)
{
fprintf (stderr, "Usage: %s <-s socket> <-n value_spec> <-H hostname> [options]\n"
diff --git a/src/collectd-tg.c b/src/collectd-tg.c
index 08bb74877de4ad9b375585fbc2175adf501d3e95..53fd3a17362287de70c2849dff0b207e5649d990 100644 (file)
--- a/src/collectd-tg.c
+++ b/src/collectd-tg.c
# include "config.h"
#endif
-#ifndef _ISOC99_SOURCE
-# define _ISOC99_SOURCE
-#endif
-
-#ifndef _POSIX_C_SOURCE
-# define _POSIX_C_SOURCE 200809L
-#endif
-
-#ifndef _XOPEN_SOURCE
-# define _XOPEN_SOURCE 700
-#endif
-
#if !__GNUC__
# define __attribute__(x) /**/
#endif
#include <time.h>
#include <signal.h>
#include <errno.h>
+#include <math.h>
+#include <sys/time.h>
#include "utils_heap.h"
loop = 0;
} /* }}} void signal_handler */
+#if HAVE_CLOCK_GETTIME
+static double dtime (void) /* {{{ */
+{
+ struct timespec ts = { 0 };
+
+ if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0)
+ perror ("clock_gettime");
+
+ return ((double) ts.tv_sec) + (((double) ts.tv_nsec) / 1e9);
+} /* }}} double dtime */
+#else
+/* Work around for Mac OS X which doesn't have clock_gettime(2). *sigh* */
+static double dtime (void) /* {{{ */
+{
+ struct timeval tv = { 0 };
+
+ if (gettimeofday (&tv, /* timezone = */ NULL) != 0)
+ perror ("gettimeofday");
+
+ return ((double) tv.tv_sec) + (((double) tv.tv_usec) / 1e6);
+} /* }}} double dtime */
+#endif
+
static int compare_time (const void *v0, const void *v1) /* {{{ */
{
const lcc_value_list_t *vl0 = v0;
host_num = get_boundet_random (0, conf_num_hosts);
vl->interval = conf_interval;
- vl->time = 1.0 + time (NULL)
+ vl->time = 1.0 + dtime ()
+ (host_num % (1 + (int) vl->interval));
if (get_boundet_random (0, 2) == 0)
if (vl->values_types[0] == LCC_TYPE_GAUGE)
vl->values[0].gauge = 100.0 * ((gauge_t) random ()) / (((gauge_t) RAND_MAX) + 1.0);
else
- vl->values[0].derive += get_boundet_random (0, 100);
+ vl->values[0].derive += (derive_t) get_boundet_random (0, 100);
status = lcc_network_values_send (net, vl);
if (status != 0)
int main (int argc, char **argv) /* {{{ */
{
int i;
- time_t last_time;
+ double last_time;
int values_sent = 0;
read_options (argc, argv);
printf ("%i values have been sent.\n", values_sent);
/* Check if we need to sleep */
- time_t now = time (NULL);
+ double now = dtime ();
while (now < vl->time)
{
/* 1 / 100 second */
struct timespec ts = { 0, 10000000 };
+
+ ts.tv_sec = (time_t) now;
+ ts.tv_nsec = (long) ((now - ((double) ts.tv_sec)) * 1e9);
+
nanosleep (&ts, /* remaining = */ NULL);
- now = time (NULL);
+ now = dtime ();
if (!loop)
break;
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
index 36eca9c143105d5a0a97fbe0006a9957582b5b03..20b17b2db170062f5562560abe303750d9f68995 100644 (file)
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
@BUILD_PLUGIN_MEMORY_TRUE@@BUILD_PLUGIN_MEMORY_TRUE@LoadPlugin memory
#@BUILD_PLUGIN_MIC_TRUE@LoadPlugin mic
#@BUILD_PLUGIN_MODBUS_TRUE@LoadPlugin modbus
+#@BUILD_PLUGIN_MQTT_TRUE@LoadPlugin mqtt
#@BUILD_PLUGIN_MULTIMETER_TRUE@LoadPlugin multimeter
#@BUILD_PLUGIN_MYSQL_TRUE@LoadPlugin mysql
#@BUILD_PLUGIN_NETAPP_TRUE@LoadPlugin netapp
#@BUILD_PLUGIN_NGINX_TRUE@LoadPlugin nginx
#@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@LoadPlugin notify_desktop
#@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@LoadPlugin notify_email
+#@BUILD_PLUGIN_NOTIFY_NAGIOS_TRUE@LoadPlugin notify_nagios
#@BUILD_PLUGIN_NTPD_TRUE@LoadPlugin ntpd
#@BUILD_PLUGIN_NUMA_TRUE@LoadPlugin numa
#@BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut
#@BUILD_PLUGIN_WRITE_TSDB_TRUE@LoadPlugin write_tsdb
#@BUILD_PLUGIN_XMMS_TRUE@LoadPlugin xmms
#@BUILD_PLUGIN_ZFS_ARC_TRUE@LoadPlugin zfs_arc
+#@BUILD_PLUGIN_ZONE_TRUE@LoadPlugin zone
#@BUILD_PLUGIN_ZOOKEEPER_TRUE@LoadPlugin zookeeper
##############################################################################
# Host "localhost"
# Port "3551"
# ReportSeconds true
+# PersistentConnection true
#</Plugin>
#<Plugin aquaero>
#<Plugin interface>
# Interface "eth0"
# IgnoreSelected false
+# UniqueName false
#</Plugin>
#<Plugin ipmi>
# </Host>
#</Plugin>
+#<Plugin mqtt>
+# <Publish "name">
+# Host "localhost"
+# Port 1883
+# ClientId "localhost"
+# User "user"
+# Password "secret"
+# QoS 0
+# Prefix "collectd"
+# StoreRates true
+# Retain false
+# CACert "/etc/ssl/ca.crt"
+# CertificateFile "/etc/ssl/client.crt"
+# CertificateKeyFile "/etc/ssl/client.pem"
+# TLSProtocol "tlsv1.2"
+# CipherSuite "ciphers"
+# </Publish>
+# <Subscribe "name">
+# Host "localhost"
+# Port 1883
+# ClientId "localhost"
+# User "user"
+# Password "secret"
+# QoS 2
+# Topic "collectd/#"
+# CleanSession true
+# </Subscribe>
+#</Plugin>
+
#<Plugin mysql>
# <Database db_name>
# Host "database.serv.er"
# Recipient "email2@domain2.com"
#</Plugin>
+#<Plugin notify_nagios>
+# CommandFile "/usr/local/nagios/var/rw/nagios.cmd"
+#</Plugin>
+
#<Plugin ntpd>
# Host "localhost"
# Port 123
# DeleteTimers false
# DeleteGauges false
# DeleteSets false
+# CounterSum false
# TimerPercentile 90.0
# TimerPercentile 95.0
# TimerPercentile 99.0
## None of the following option should be set manually
## This plugin automatically detect most optimal options
## Only set values here if:
-## - The module ask you to
+## - The module asks you to
## - You want to disable the collection of some data
-## - Your (intel) CPU is not supported (yet) by the module
-## - The module generate a lot of errors 'MSR offset 0x... read failed'
+## - Your (Intel) CPU is not supported (yet) by the module
+## - The module generates a lot of errors 'MSR offset 0x... read failed'
## In the last two cases, please open a bug request
#
# TCCActivationTemp "100"
# Host "localhost"
# Port "2003"
# Protocol "tcp"
+# ReconnectInterval 0
# LogSendErrors true
# Prefix "collectd"
# Postfix "collectd"
# Host "localhost"
# Port "6379"
# Timeout 1000
+# Prefix "collectd/"
# </Node>
#</Plugin>
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 56bab99ab808001875127d039af3f7dd806a1d92..cf7ccd0190e32fa81a2f55ad892bc7a96ee36299 100644 (file)
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
The syntax of this config file is similar to the config file of the famous
I<Apache> webserver. Each line contains either an option (a key and a list of
one or more values) or a section-start or -end. Empty lines and everything
-after a non-quoted hash-symbol (C<#>) is ignored. I<Keys> are unquoted
+after a non-quoted hash-symbol (C<#>) are ignored. I<Keys> are unquoted
strings, consisting only of alphanumeric characters and the underscore (C<_>)
character. Keys are handled case insensitive by I<collectd> itself and all
plugins included with it. I<Values> can either be an I<unquoted string>, a
=item B<BaseDir> I<Directory>
-Sets the base directory. This is the directory beneath all RRD-files are
+Sets the base directory. This is the directory beneath which all RRD-files are
created. Possibly more subdirectories are created. This is also the working
directory for the daemon.
Only the first B<LoadPlugin> statement or block for a given plugin name has any
effect. This is useful when you want to split up the configuration into smaller
files and want each file to be "self contained", i.e. it contains a B<Plugin>
-block I<and> then appropriate B<LoadPlugin> statement. The downside is that if
+block I<and> the appropriate B<LoadPlugin> statement. The downside is that if
you have multiple conflicting B<LoadPlugin> blocks, e.g. when they specify
different intervals, only one of them (the first one encountered) will take
effect and all others will be silently ignored.
=item B<Interval> I<Seconds>
Sets a plugin-specific interval for collecting metrics. This overrides the
-global B<Interval> setting. If a plugin provides own support for specifying an
-interval, that setting will take precedence.
+global B<Interval> setting. If a plugin provides its own support for specifying
+an interval, that setting will take precedence.
+
+=item B<FlushInterval> I<Seconds>
+
+Specifies the interval, in seconds, to call the flush callback if it's
+defined in this plugin. By default, this is disabled.
+
+=item B<FlushTimeout> I<Seconds>
+
+Specifies the value of the timeout argument of the flush callback.
=back
=back
-If more than one files are included by a single B<Include> option, the files
+If more than one file is included by a single B<Include> option, the files
will be included in lexicographical order (as defined by the C<strcmp>
function). Thus, you can e.E<nbsp>g. use numbered prefixes to specify the
order in which the files are loaded.
=item B<MaxReadInterval> I<Seconds>
-Read plugin doubles interval between queries after each failed attempt
+A read plugin doubles the interval between queries after each failed attempt
to get data.
This options limits the maximum value of the interval. The default value is
The I<AMQP plugin> can be used to communicate with other instances of
I<collectd> or third party applications using an AMQP message broker. Values
are sent to or received from the broker, which handles routing, queueing and
-possibly filtering or messages.
+possibly filtering out messages.
+
+B<Synopsis:>
<Plugin "amqp">
# Send values to an AMQP broker
TCP-Port to connect to. Defaults to B<3551>.
-=item B<ReportSeconds> B<true|false>
+=item B<ReportSeconds> B<true>|B<false>
If set to B<true>, the time reported in the C<timeleft> metric will be
converted to seconds. This is the recommended setting. If set to B<false>, the
default for backwards compatibility, the time will be reported in minutes.
+=item B<PersistentConnection> B<true>|B<false>
+
+By default, the plugin will try to keep the connection to UPS open between
+reads. Since this appears to be somewhat brittle (I<apcupsd> appears to close
+the connection due to inactivity quite quickly), the plugin will try to detect
+this problem and switch to an open-read-close mode in such cases.
+
+You can instruct the plugin to close the connection after each read by setting
+this option to B<false>.
+
=back
=head2 Plugin C<aquaero>
</Query>
<Database "product_information">
Driver "mysql"
+ Interval 120
DriverOption "host" "localhost"
DriverOption "username" "collectd"
DriverOption "password" "aZo6daiw"
=over 4
+=item B<Interval> I<Interval>
+
+Sets the interval (in seconds) in which the values will be collected from this
+database. By default the global B<Interval> setting will be used.
+
=item B<Driver> I<Driver>
Specifies the driver to use to connect to the database. In many cases those
at least one digit.
+=item B<UniqueName> I<true>|I<false>
+
+Interface name is not unique on Solaris (KSTAT), interface name is unique
+only within a module/instance. Following tuple is considered unique:
+ (ks_module, ks_instance, ks_name)
+If this option is set to true, interface name contains above three fields
+separated by an underscore. For more info on KSTAT, visit
+L<http://docs.oracle.com/cd/E23824_01/html/821-1468/kstat-3kstat.html#REFMAN3Ekstat-3kstat>
+
+This option is only available on Solaris.
+
=back
=head2 Plugin C<ipmi>
=back
+=back
+
+=head2 Plugin C<mqtt>
+
+The I<MQTT plugin> can send metrics to MQTT (B<Publish> blocks) and receive
+values from MQTT (B<Subscribe> blocks).
+
+B<Synopsis:>
+
+ <Plugin mqtt>
+ <Publish "name">
+ Host "mqtt.example.com"
+ Prefix "collectd"
+ </Publish>
+ <Subscribe "name">
+ Host "mqtt.example.com"
+ Topic "collectd/#"
+ </Subscribe>
+ </Plugin>
+
+The plugin's configuration is in B<Publish> and/or B<Subscribe> blocks,
+configuring the sending and receiving direction respectively. The plugin will
+register a write callback named C<mqtt/I<name>> where I<name> is the string
+argument given to the B<Publish> block. Both types of blocks share many but not
+all of the following options. If an option is valid in only one of the blocks,
+it will be mentioned explicitly.
+
+B<Options:>
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname of the MQTT broker to connect to.
+
+=item B<Port> I<Service>
+
+Port number or service name of the MQTT broker to connect to.
+
+=item B<User> I<UserName>
+
+Username used when authenticating to the MQTT broker.
+
+=item B<Password> I<Password>
+
+Password used when authenticating to the MQTT broker.
+
+=item B<ClientId> I<ClientId>
+
+MQTT client ID to use. Defaults to the hostname used by I<collectd>.
+
+=item B<QoS> [B<0>-B<2>]
+
+Sets the I<Quality of Service>, with the values C<0>, C<1> and C<2> meaning:
+
+=over 4
+
+=item B<0>
+
+At most once
+
+=item B<1>
+
+At least once
+
+=item B<2>
+
+Exactly once
+
+=back
+
+In B<Publish> blocks, this option determines the QoS flag set on outgoing
+messages and defaults to B<0>. In B<Subscribe> blocks, determines the maximum
+QoS setting the client is going to accept and defaults to B<2>. If the QoS flag
+on a message is larger than the maximum accepted QoS of a subscriber, the
+message's QoS will be downgraded.
+
+=item B<Prefix> I<Prefix> (Publish only)
+
+This plugin will use one topic per I<value list> which will looks like a path.
+I<Prefix> is used as the first path element and defaults to B<collectd>.
+
+An example topic name would be:
+
+ collectd/cpu-0/cpu-user
+
+=item B<Retain> B<false>|B<true> (Publish only)
+
+Controls whether the MQTT broker will retain (keep a copy of) the last message
+sent to each topic and deliver it to new subscribers. Defaults to B<false>.
+
+=item B<StoreRates> B<true>|B<false> (Publish only)
+
+Controls whether C<DERIVE> and C<COUNTER> metrics are converted to a I<rate>
+before sending. Defaults to B<true>.
+
+=item B<CleanSession> B<true>|B<false> (Subscribe only)
+
+Controls whether the MQTT "cleans" the session up after the subscriber
+disconnects or if it maintains the subscriber's subscriptions and all messages
+that arrive while the subscriber is disconnected. Defaults to B<true>.
+
+=item B<Topic> I<TopicName> (Subscribe only)
+
+Configures the topic(s) to subscribe to. You can use the single level C<+> and
+multi level C<#> wildcards. Defaults to B<collectd/#>, i.e. all topics beneath
+the B<collectd> branch.
+
+=item B<CACert> I<file>
+
+Path to the PEM-encoded CA certificate file. Setting this option enables TLS
+communication with the MQTT broker, and as such, B<Port> should be the TLS-enabled
+port of the MQTT broker.
+A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+
+=item B<CertificateFile> I<file>
+
+Path to the PEM-encoded certificate file to use as client certificate when
+connecting to the MQTT broker.
+A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+
+=item B<CertificateKeyFile> I<file>
+
+Path to the unencrypted PEM-encoded key file corresponding to B<CertificateFile>.
+A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+
+=item B<TLSProtocol> I<protocol>
+
+If configured, this specifies the string protocol version (e.g. C<tlsv1>,
+C<tlsv1.2>) to use for the TLS connection to the broker. If not set a default
+version is used which depends on the version of OpenSSL the Mosquitto library
+was linked against.
+
+=item B<CipherSuite> I<ciphersuite>
+
+A string describing the ciphers available for use. See L<ciphers(1)> and the
+C<openssl ciphers> utility for more information. If unset, the default ciphers
+will be used.
+
+
=back
=head2 Plugin C<mysql>
=back
+=head2 Plugin C<notify_nagios>
+
+The I<notify_nagios> plugin writes notifications to Nagios' I<command file> as
+a I<passive service check result>.
+
+Available configuration options:
+
+=over 4
+
+=item B<CommandFile> I<Path>
+
+Sets the I<command file> to write to. Defaults to F</usr/local/nagios/var/rw/nagios.cmd>.
+
+=back
+
=head2 Plugin C<ntpd>
The C<ntpd> plugin collects per-peer ntpd data such as time offset and time
Sets the URL to use to connect to the I<OpenLDAP> server. This option is
I<mandatory>.
+=item B<BindDN> I<BindDN>
+
+Name in the form of an LDAP distinguished name intended to be used for
+authentication. Defaults to empty string to establish an anonymous authorization.
+
+=item B<Password> I<Password>
+
+Password for simple bind authentication. If this option is not set,
+unauthenticated bind operation is used.
+
=item B<StartTLS> B<true|false>
Defines whether TLS must be used when connecting to the I<OpenLDAP> server.
Sets the Time-To-Live of generated ICMP packets.
+=item B<Size> I<size>
+
+Sets the size of the data payload in ICMP packet to specified I<size> (it
+will be filled with regular ASCII pattern). If not set, default 56 byte
+long string is used so that the packet size of an ICMPv4 packet is exactly
+64 bytes, similar to the behaviour of normal ping(1) command.
+
=item B<SourceAddress> I<host>
Sets the source address to use. I<host> may either be a numerical network
allows to "group" several processes together. I<name> must not contain
slashes.
+=item B<CollectContextSwitch> I<Boolean>
+
+Collect context switch of the process.
+
=back
=head2 Plugin C<protocols>
@@ -6084,6 +6298,12 @@ rate of counters and size of sets will be zero, timers report C<NaN> and gauges
are unchanged. If set to B<True>, the such metrics are not dispatched and
removed from the internal cache.
+=item B<CounterSum> B<false>|B<true>
+
+When enabled, creates a C<count> metric which reports the change since the last
+read. This option primarily exists for compatibility with the I<statsd>
+implementation by Etsy.
+
=item B<TimerPercentile> I<Percent>
Calculate and dispatch the configured percentile, i.e. compute the latency, so
B<address> means use the interface's mac address. This is useful since the
interface path might change between reboots of a guest or across migrations.
-=item B<PluginInstanceFormat> B<name|uuid>
+=item B<PluginInstanceFormat> B<name|uuid|none>
When the virt plugin logs data, it sets the plugin_instance of the collected
-data according to this setting. The default is to use the guest name as provided
-by the hypervisor, which is equal to setting B<name>.
+data according to this setting. The default is to not set the plugin_instance.
+B<name> means use the guest's name as provided by the hypervisor.
B<uuid> means use the guest's UUID.
-You can also specify combinations of these fields. For example B<name uuid>
-means to concatenate the guest name and UUID (with a literal colon character
-between, thus I<"foo:1234-1234-1234-1234">).
+You can also specify combinations of the B<name> and B<uuid> fields.
+For example B<name uuid> means to concatenate the guest name and UUID
+(with a literal colon character between, thus I<"foo:1234-1234-1234-1234">).
=back
Protocol to use when connecting to I<Graphite>. Defaults to C<tcp>.
+=item B<ReconnectInterval> I<Seconds>
+
+When set to non-zero, forces the connection to the Graphite backend to be
+closed and re-opend periodically. This behavior is desirable in environments
+where the connection to the Graphite backend is done through load balancers,
+for example. When set to zero, the default, the connetion is kept open for as
+long as possible.
+
=item B<LogSendErrors> B<false>|B<true>
If set to B<true> (the default), logs errors when sending data to I<Graphite>.
@@ -7391,6 +7619,10 @@ complete. When this limit is reached, the POST operation will be aborted, and
all the data in the current send buffer will probably be lost. Defaults to 0,
which means the connection never times out.
+=item B<LogHttpError> B<false>|B<true>
+
+Enables printing of HTTP error code to log. Turned off by default.
+
The C<write_http> plugin regularly submits the collected values to the HTTP
server. How frequently this happens depends on how much data you are collecting
and the size of B<BufferSize>. The optimal value to set B<Timeout> to is
Host "localhost"
Port "6379"
Timeout 1000
+ Prefix "collectd/"
+ Database 1
+ MaxSetSize -1
+ StoreRates true
</Node>
</Plugin>
Values are submitted to I<Sorted Sets>, using the metric name as the key, and
the timestamp as the score. Retrieving a date range can then be done using the
C<ZRANGEBYSCORE> I<Redis> command. Additionally, all the identifiers of these
-I<Sorted Sets> are kept in a I<Set> called C<collectd/values> and can be
-retrieved using the C<SMEMBERS> I<Redis> command. See
+I<Sorted Sets> are kept in a I<Set> called C<collectd/values> (or
+C<${prefix}/values> if the B<Prefix> option was specified) and can be retrieved
+using the C<SMEMBERS> I<Redis> command. You can specify the database to use
+with the B<Database> parameter (default is C<0>). See
L<http://redis.io/commands#sorted_set> and L<http://redis.io/commands#set> for
details.
The B<Timeout> option sets the socket connection timeout, in milliseconds.
+=item B<Prefix> I<Prefix>
+
+Prefix used when constructing the name of the I<Sorted Sets> and the I<Set>
+containing all metrics. Defaults to C<collectd/>, so metrics will have names
+like C<collectd/cpu-0/cpu-user>. When setting this to something different, it
+is recommended but not required to include a trailing slash in I<Prefix>.
+
+=item B<Database> I<Index>
+
+This index selects the redis database to use for writing operations. Defaults
+to C<0>.
+
+=item B<MaxSetSize> I<Items>
+
+The B<MaxSetSize> option limits the number of items that the I<Sorted Sets> can
+hold. Negative values for I<Items> sets no limit, which is the default behavior.
+
+=item B<StoreRates> B<true>|B<false>
+
+If set to B<true> (the default), convert counter values to rates. If set to
+B<false> counter values are stored as is, i.e. as an increasing integer number.
+
=back
=head2 Plugin C<write_riemann>
diff --git a/src/collectdctl.c b/src/collectdctl.c
index d019d2742f3db6bef5d98f653ed144cdf4a42895..7d3cbce8c1551ca062c199882fb87b576e8e97e8 100644 (file)
--- a/src/collectdctl.c
+++ b/src/collectdctl.c
extern char *optarg;
extern int optind;
+__attribute__((noreturn))
static void exit_usage (const char *name, int status) {
fprintf ((status == 0) ? stdout : stderr,
"Usage: %s [options] <command> [cmd options]\n\n"
return count;
} /* count_chars */
-static int array_grow (void **array, int *array_len, size_t elem_size)
+static int array_grow (void **array, size_t *array_len, size_t elem_size)
{
void *tmp;
int timeout = -1;
lcc_identifier_t *identifiers = NULL;
- int identifiers_num = 0;
+ size_t identifiers_num = 0;
char **plugins = NULL;
- int plugins_num = 0;
+ size_t plugins_num = 0;
int status;
int i;
values_types[values_len] = LCC_TYPE_GAUGE;
}
else { /* integer */
- values[values_len].counter = strtol (value, &endptr, 0);
+ values[values_len].counter = (counter_t) strtoull (value, &endptr, 0);
values_types[values_len] = LCC_TYPE_COUNTER;
}
++values_len;
int status;
while (42) {
- int n;
+ int opt;
- n = getopt (argc, argv, "s:h");
+ opt = getopt (argc, argv, "s:h");
- if (n == -1)
+ if (opt == -1)
break;
- switch (n) {
+ switch (opt) {
case 's':
snprintf (address, sizeof (address), "unix:%s", optarg);
address[sizeof (address) - 1] = '\0';
diff --git a/src/collectdmon.c b/src/collectdmon.c
index 33f02b45694d889d07613a05110230c1b32d7442..2c1d58978bc175221bf3fd71448b2930c0a4aaab 100644 (file)
--- a/src/collectdmon.c
+++ b/src/collectdmon.c
static int loop = 0;
static int restart = 0;
-static char *pidfile = NULL;
-static pid_t collectd_pid = 0;
+static const char *pidfile = NULL;
+static pid_t collectd_pid = 0;
-static void exit_usage (char *name)
+__attribute__((noreturn))
+static void exit_usage (const char *name)
{
printf ("Usage: %s <options> [-- <collectd options>]\n"
static int daemonize (void)
{
struct rlimit rl;
+ int dev_null;
pid_t pid = 0;
int i = 0;
for (i = 0; i < (int)rl.rlim_max; ++i)
close (i);
- errno = 0;
- if (open ("/dev/null", O_RDWR) != 0) {
- syslog (LOG_ERR, "Error: couldn't connect STDIN to /dev/null: %s",
- strerror (errno));
+ dev_null = open ("/dev/null", O_RDWR);
+ if (dev_null == -1) {
+ syslog (LOG_ERR, "Error: couldn't failed to open /dev/null: %s", strerror (errno));
return -1;
}
- errno = 0;
- if (dup (0) != 1) {
- syslog (LOG_ERR, "Error: couldn't connect STDOUT to /dev/null: %s",
- strerror (errno));
+ if (dup2 (dev_null, STDIN_FILENO) == -1) {
+ syslog (LOG_ERR, "Error: couldn't connect STDIN to /dev/null: %s", strerror (errno));
return -1;
}
- errno = 0;
- if (dup (0) != 2) {
- syslog (LOG_ERR, "Error: couldn't connect STDERR to /dev/null: %s",
- strerror (errno));
+ if (dup2 (dev_null, STDOUT_FILENO) == -1) {
+ syslog (LOG_ERR, "Error: couldn't connect STDOUT to /dev/null: %s", strerror (errno));
return -1;
}
+
+ if (dup2 (dev_null, STDERR_FILENO) == -1) {
+ syslog (LOG_ERR, "Error: couldn't connect STDERR to /dev/null: %s", strerror (errno));
+ return -1;
+ }
+
+ if ((dev_null != STDIN_FILENO) && (dev_null != STDOUT_FILENO) && (dev_null != STDERR_FILENO))
+ close (dev_null);
+
return 0;
} /* daemonize */
diff --git a/src/cpu.c b/src/cpu.c
index c9462506dca025a633ccf3f591de8c23f2671c1a..7f8c9858995c7d11f3d853905e4d3e574d660822 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
/* Adds a derive value to the internal state. This should be used by each read
* function for each state. At the end of the iteration, the read function
* should call cpu_commit(). */
-static int cpu_stage (size_t cpu_num, size_t state, derive_t value, cdtime_t now) /* {{{ */
+static int cpu_stage (size_t cpu_num, size_t state, derive_t d, cdtime_t now) /* {{{ */
{
int status;
cpu_state_t *s;
- value_t v;
+ gauge_t rate = NAN;
+ value_t val = {.derive = d};
if (state >= COLLECTD_CPU_STATE_ACTIVE)
return (EINVAL);
@@ -554,12 +555,11 @@ static int cpu_stage (size_t cpu_num, size_t state, derive_t value, cdtime_t now
s = get_cpu_state (cpu_num, state);
- v.gauge = NAN;
- status = value_to_rate (&v, value, &s->conv, DS_TYPE_DERIVE, now);
+ status = value_to_rate (&rate, val, DS_TYPE_DERIVE, now, &s->conv);
if (status != 0)
return (status);
- s->rate = v.gauge;
+ s->rate = rate;
s->has_value = 1;
return (0);
} /* }}} int cpu_stage */
diff --git a/src/csv.c b/src/csv.c
index 07728734cc727ab0f8991480fd27c65298aabed1..7b513e7345199a508fc53531187aac959784c74b 100644 (file)
--- a/src/csv.c
+++ b/src/csv.c
{
int offset;
int status;
- int i;
+ size_t i;
gauge_t *rates = NULL;
assert (0 == strcmp (ds->type, vl->type));
static int csv_create_file (const char *filename, const data_set_t *ds)
{
FILE *csv;
- int i;
+ size_t i;
if (check_create_dir (filename))
return (-1);
diff --git a/src/curl.c b/src/curl.c
index ac4cc512c63fd51dcdd9190814aca5e0eaf1cc7d..16ae3ababc1d48c421c85c814b2eb0499edd699e 100644 (file)
--- a/src/curl.c
+++ b/src/curl.c
if (wp->timeout >= 0)
curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS, (long) wp->timeout);
else
- curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
diff --git a/src/curl_json.c b/src/curl_json.c
index 448db15eed78d91f34028b39d6577ea3048b914e..45898c3ec1115ed9c7b6c8fd0f0c463b1370ff66 100644 (file)
--- a/src/curl_json.c
+++ b/src/curl_json.c
#include "utils_avltree.h"
#include "utils_complain.h"
-#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
if (db->timeout >= 0)
curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) db->timeout);
else if (db->interval > 0)
- curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(db->timeout));
+ curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(db->timeout));
else
- curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
{
user_data_t ud;
char *cb_name;
- struct timespec interval = { 0, 0 };
-
- CDTIME_T_TO_TIMESPEC (db->interval, &interval);
if (db->instance == NULL)
db->instance = strdup("default");
db->instance, db->url ? db->url : db->sock);
plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read,
- /* interval = */ (db->interval > 0) ? &interval : NULL,
+ /* interval = */ db->interval,
&ud);
sfree (cb_name);
}
static int cj_sock_perform (cj_t *db) /* {{{ */
{
char errbuf[1024];
- struct sockaddr_un sa_unix = {};
+ struct sockaddr_un sa_unix = { 0 };
sa_unix.sun_family = AF_UNIX;
sstrncpy (sa_unix.sun_path, db->sock, sizeof (sa_unix.sun_path));
diff --git a/src/curl_xml.c b/src/curl_xml.c
index 3ffb71c559c77d3f00d5f8027880646be0f7c2be..39d6fd04b3c93f5ac9bec31df153f8093203e626 100644 (file)
--- a/src/curl_xml.c
+++ b/src/curl_xml.c
char *path;
char *type;
cx_values_t *values;
- int values_len;
+ size_t values_len;
char *instance_prefix;
char *instance;
int is_table;
if (ds->ds_num != xpath->values_len)
{
- WARNING ("curl_xml plugin: DataSet `%s' requires %i values, but config talks about %i",
+ WARNING ("curl_xml plugin: DataSet `%s' requires %zu values, but config talks about %zu",
xpath->type, ds->ds_num, xpath->values_len);
return (-1);
}
{
value_t values[xpath->values_len];
int status;
- int i;
+ size_t i;
assert (xpath->values_len > 0);
assert (xpath->values_len == vl->values_len);
xpath->values = (cx_values_t *) malloc (sizeof (cx_values_t) * ci->values_num);
if (xpath->values == NULL)
return (-1);
- xpath->values_len = ci->values_num;
+ xpath->values_len = (size_t) ci->values_num;
/* populate cx_values_t structure */
for (i = 0; i < ci->values_num; i++)
if (db->timeout >= 0)
curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) db->timeout);
else
- curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
cb_name = ssnprintf_alloc ("curl_xml-%s-%s", db->instance, db->url);
plugin_register_complex_read (/* group = */ "curl_xml", cb_name, cx_read,
- /* interval = */ NULL, &ud);
+ /* interval = */ 0, &ud);
sfree (cb_name);
}
else
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index 95fb947aa361ba545519073f6225a4510ae14b70..cdd927bc7b859e037aeb5e1abf2c9596e4a5fae4 100644 (file)
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
-if COMPILER_IS_GCC
-AM_CFLAGS = -Wall -Werror
-endif
-
AM_CPPFLAGS = -I$(top_srcdir)/src
AM_CPPFLAGS += -DPREFIX='"${prefix}"'
AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
sbin_PROGRAMS = collectd
-noinst_LTLIBRARIES = libavltree.la libcommon.la libheap.la libplugin_mock.la
+noinst_LTLIBRARIES = libavltree.la libcommon.la libheap.la libmetadata.la libplugin_mock.la
libavltree_la_SOURCES = utils_avltree.c utils_avltree.h
libcommon_la_SOURCES = common.c common.h
+libcommon_la_LIBADD = $(COMMON_LIBS)
libheap_la_SOURCES = utils_heap.c utils_heap.h
-libplugin_mock_la_SOURCES = plugin_mock.c utils_cache_mock.c utils_time_mock.c
+libmetadata_la_SOURCES = meta_data.c meta_data.h
+
+libplugin_mock_la_SOURCES = plugin_mock.c utils_cache_mock.c \
+ utils_time.c utils_time.h
+libplugin_mock_la_CPPFLAGS = $(AM_CPPFLAGS) -DMOCK_TIME
+libplugin_mock_la_LIBADD = $(COMMON_LIBS) libcommon.la
collectd_SOURCES = collectd.c collectd.h \
configfile.c configfile.h \
collectd_CFLAGS = $(AM_CFLAGS)
collectd_LDFLAGS = -export-dynamic
collectd_LDADD = libavltree.la libcommon.la libheap.la -lm $(COMMON_LIBS)
-collectd_DEPENDENCIES = libavltree.la libcommon.la libheap.la
+collectd_DEPENDENCIES = libavltree.la libcommon.la libheap.la libmetadata.la
# The daemon needs to call sg_init, so we need to link it against libstatgrab,
# too. -octo
collectd_LDADD += -loconfig
endif
-check_PROGRAMS = test_common test_utils_avltree test_utils_heap
-TESTS = test_common test_utils_avltree test_utils_heap
+check_PROGRAMS = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_time test_utils_subst
+TESTS = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_time test_utils_subst
test_common_SOURCES = common_test.c ../testing.h
-test_common_LDADD = libcommon.la libplugin_mock.la $(COMMON_LIBS)
+test_common_LDADD = libplugin_mock.la
+
+test_meta_data_SOURCES = meta_data_test.c ../testing.h
+test_meta_data_LDADD = libmetadata.la libplugin_mock.la
test_utils_avltree_SOURCES = utils_avltree_test.c ../testing.h
test_utils_avltree_LDADD = libavltree.la $(COMMON_LIBS)
test_utils_heap_SOURCES = utils_heap_test.c ../testing.h
test_utils_heap_LDADD = libheap.la $(COMMON_LIBS)
+
+test_utils_time_SOURCES = utils_time_test.c ../testing.h
+
+test_utils_subst_SOURCES = utils_subst_test.c ../testing.h \
+ utils_subst.c utils_subst.h
+test_utils_subst_LDADD = libplugin_mock.la
diff --git a/src/daemon/collectd.c b/src/daemon/collectd.c
index 6e625bbb04cdc062f87335a45153523a6cf75c57..6f299174ad8ea38af32fc630d47f208905864dea 100644 (file)
--- a/src/daemon/collectd.c
+++ b/src/daemon/collectd.c
#include "configfile.h"
#include <sys/types.h>
-#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
/* TODO
* Remove all settings but `-f' and `-C'
*/
+__attribute__((noreturn))
static void exit_usage (int status)
{
printf ("Usage: "PACKAGE_NAME" [OPTIONS]\n\n"
#ifdef KERNEL_LINUX
static int notify_upstart (void)
{
- const char *upstart_job = getenv("UPSTART_JOB");
+ char const *upstart_job = getenv("UPSTART_JOB");
if (upstart_job == NULL)
return 0;
if (strcmp(upstart_job, "collectd") != 0)
+ {
+ WARNING ("Environment specifies unexpected UPSTART_JOB=\"%s\", expected \"collectd\". Ignoring the variable.", upstart_job);
return 0;
+ }
- WARNING ("supervised by upstart, will stop to signal readyness");
+ NOTICE("Upstart detected, stopping now to signal readyness.");
raise(SIGSTOP);
unsetenv("UPSTART_JOB");
static int notify_systemd (void)
{
- int fd = -1;
- const char *notifysocket = getenv("NOTIFY_SOCKET");
+ int fd;
+ const char *notifysocket;
struct sockaddr_un su;
- struct iovec iov;
- struct msghdr hdr;
+ size_t su_size;
+ char buffer[] = "READY=1\n";
+ notifysocket = getenv ("NOTIFY_SOCKET");
if (notifysocket == NULL)
return 0;
- if ((strchr("@/", notifysocket[0])) == NULL ||
- strlen(notifysocket) < 2)
+ if ((strlen (notifysocket) < 2)
+ || ((notifysocket[0] != '@') && (notifysocket[0] != '/')))
+ {
+ ERROR ("invalid notification socket NOTIFY_SOCKET=\"%s\": path must be absolute", notifysocket);
return 0;
+ }
+ NOTICE ("Systemd detected, trying to signal readyness.");
- WARNING ("supervised by systemd, will signal readyness");
- if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
- WARNING ("cannot contact systemd socket %s", notifysocket);
+ 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) {
+ char errbuf[1024];
+ ERROR ("creating UNIX socket failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
return 0;
}
- bzero(&su, sizeof(su));
+ memset (&su, 0, sizeof (su));
su.sun_family = AF_UNIX;
- sstrncpy (su.sun_path, notifysocket, sizeof(su.sun_path));
-
- if (notifysocket[0] == '@')
+ if (notifysocket[0] != '@')
+ {
+ /* regular UNIX socket */
+ sstrncpy (su.sun_path, notifysocket, sizeof (su.sun_path));
+ su_size = sizeof (su);
+ }
+ else
+ {
+ /* Linux abstract namespace socket: specify address as "\0foo", i.e.
+ * start with a null byte. Since null bytes have no special meaning in
+ * that case, we have to set su_size correctly to cover only the bytes
+ * that are part of the address. */
+ sstrncpy (su.sun_path, notifysocket, sizeof (su.sun_path));
su.sun_path[0] = 0;
+ su_size = sizeof (sa_family_t) + strlen (notifysocket);
+ if (su_size > sizeof (su))
+ su_size = sizeof (su);
+ }
- bzero(&iov, sizeof(iov));
- iov.iov_base = "READY=1";
- iov.iov_len = strlen("READY=1");
-
- bzero(&hdr, sizeof(hdr));
- hdr.msg_name = &su;
- hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) +
- strlen(notifysocket);
- hdr.msg_iov = &iov;
- hdr.msg_iovlen = 1;
-
- unsetenv("NOTIFY_SOCKET");
- if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) {
- WARNING ("cannot send notification to systemd");
+ if (sendto (fd, buffer, strlen (buffer), MSG_NOSIGNAL, (void *) &su, (socklen_t) su_size) < 0)
+ {
+ char errbuf[1024];
+ ERROR ("sendto(\"%s\") failed: %s", notifysocket,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
close(fd);
return 0;
}
+
+ unsetenv ("NOTIFY_SOCKET");
close(fd);
return 1;
}
struct sigaction sig_term_action;
struct sigaction sig_usr1_action;
struct sigaction sig_pipe_action;
- char *configfile = CONFIGFILE;
+ const char *configfile = CONFIGFILE;
int test_config = 0;
int test_readall = 0;
const char *basedir;
#endif
)
{
+ int status;
+
if ((pid = fork ()) == -1)
{
/* error */
close (1);
close (0);
- if (open ("/dev/null", O_RDWR) != 0)
+ status = open ("/dev/null", O_RDWR);
+ if (status != 0)
{
- ERROR ("Error: Could not connect `STDIN' to `/dev/null'");
+ ERROR ("Error: Could not connect `STDIN' to `/dev/null' (status %d)", status);
return (1);
}
- if (dup (0) != 1)
+
+ status = dup (0);
+ if (status != 1)
{
- ERROR ("Error: Could not connect `STDOUT' to `/dev/null'");
+ ERROR ("Error: Could not connect `STDOUT' to `/dev/null' (status %d)", status);
return (1);
}
- if (dup (0) != 2)
+
+ status = dup (0);
+ if (status != 2)
{
- ERROR ("Error: Could not connect `STDERR' to `/dev/null'");
+ ERROR ("Error: Could not connect `STDERR' to `/dev/null', (status %d)", status);
return (1);
}
} /* if (daemonize) */
diff --git a/src/daemon/collectd.h b/src/daemon/collectd.h
index 80b753c8a83442b3e278858a8cb54528bf9868d1..66b485681b223c97c7fda9cc595a16d9616e0494 100644 (file)
--- a/src/daemon/collectd.h
+++ b/src/daemon/collectd.h
# include <time.h>
# endif
#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
#if HAVE_ASSERT_H
# include <assert.h>
diff --git a/src/daemon/common.c b/src/daemon/common.c
index fba51ef8f73be8f8bbb174e55525e59e6e397eb0..dd4f9b15ae39a5036cbb0b40f0b8c21624ee473a 100644 (file)
--- a/src/daemon/common.c
+++ b/src/daemon/common.c
/* for getaddrinfo */
#include <sys/types.h>
-#include <sys/socket.h>
#include <netdb.h>
#include <poll.h>
assert ((0 > status) || (nleft >= (size_t)status));
- nleft = nleft - status;
- ptr = ptr + status;
+ nleft = nleft - ((size_t) status);
+ ptr = ptr + ((size_t) status);
}
return (0);
if (status < 0)
return (status);
- nleft = nleft - status;
- ptr = ptr + status;
+ nleft = nleft - ((size_t) status);
+ ptr = ptr + ((size_t) status);
}
return (0);
}
assert (buffer[buffer_size - 1] == 0);
- return (strlen (buffer));
+ return ((int) strlen (buffer));
}
int strsubstitute (char *str, char c_from, char c_to)
int escape_slashes (char *buffer, size_t buffer_size)
{
- int i;
size_t buffer_len;
+ size_t i;
buffer_len = strlen (buffer);
* Join the components together again
*/
dir[0] = '/';
- if (strjoin (dir + path_is_absolute, dir_len - path_is_absolute,
- fields, i + 1, "/") < 0)
+ if (strjoin (dir + path_is_absolute, (size_t) (dir_len - path_is_absolute),
+ fields, (size_t) (i + 1), "/") < 0)
{
ERROR ("strjoin failed: `%s', component #%i", file_orig, i);
return (-1);
{
size_t offset = 0;
int status;
- int i;
+ size_t i;
gauge_t *rates = NULL;
assert (0 == strcmp (ds->type, vl->type));
int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
{
- int i;
+ size_t i;
char *dummy;
char *ptr;
char *saveptr;
if ((buffer == NULL) || (vl == NULL) || (ds == NULL))
return EINVAL;
- i = -1;
+ i = 0;
dummy = buffer;
saveptr = NULL;
+ vl->time = 0;
while ((ptr = strtok_r (dummy, ":", &saveptr)) != NULL)
{
dummy = NULL;
if (i >= vl->values_len)
{
/* Make sure i is invalid. */
- i = vl->values_len + 1;
+ i = 0;
break;
}
- if (i == -1)
+ if (vl->time == 0)
{
if (strcmp ("N", ptr) == 0)
vl->time = cdtime ();
vl->time = DOUBLE_TO_CDTIME_T (tmp);
}
+
+ continue;
}
- else
- {
- if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
- vl->values[i].gauge = NAN;
- else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
- return -1;
- }
+
+ if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
+ vl->values[i].gauge = NAN;
+ else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
+ return -1;
i++;
} /* while (strtok_r) */
- if ((ptr != NULL) || (i != vl->values_len))
+ if ((ptr != NULL) || (i == 0))
return (-1);
return (0);
} /* int parse_values */
if (old_value > new_value)
{
if (old_value <= 4294967295U)
- diff = (4294967295U - old_value) + new_value;
+ diff = (4294967295U - old_value) + new_value + 1;
else
- diff = (18446744073709551615ULL - old_value)
- + new_value;
+ diff = (18446744073709551615ULL - old_value) + new_value + 1;
}
else
{
return (0);
} /* }}} value_t rate_to_value */
-int value_to_rate (value_t *ret_rate, derive_t value, /* {{{ */
- value_to_rate_state_t *state,
- int ds_type, cdtime_t t)
+int value_to_rate (gauge_t *ret_rate, /* {{{ */
+ value_t value, int ds_type, cdtime_t t, value_to_rate_state_t *state)
{
- double interval;
+ gauge_t interval;
/* Another invalid state: The time is not increasing. */
if (t <= state->last_time)
interval = CDTIME_T_TO_DOUBLE(t - state->last_time);
/* Previous value is invalid. */
- if (state->last_time == 0) /* {{{ */
+ if (state->last_time == 0)
{
- if (ds_type == DS_TYPE_DERIVE)
- {
- state->last_value.derive = value;
- }
- else if (ds_type == DS_TYPE_COUNTER)
- {
- state->last_value.counter = (counter_t) value;
- }
- else if (ds_type == DS_TYPE_ABSOLUTE)
- {
- state->last_value.absolute = (absolute_t) value;
- }
- else
- {
- assert (23 == 42);
- }
-
+ state->last_value = value;
state->last_time = t;
return (EAGAIN);
- } /* }}} */
+ }
- if (ds_type == DS_TYPE_DERIVE)
- {
- ret_rate->gauge = (value - state->last_value.derive) / interval;
- state->last_value.derive = value;
+ switch (ds_type) {
+ case DS_TYPE_DERIVE: {
+ derive_t diff = value.derive - state->last_value.derive;
+ *ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
+ break;
}
- else if (ds_type == DS_TYPE_COUNTER)
- {
- ret_rate->gauge = (((counter_t)value) - state->last_value.counter) / interval;
- state->last_value.counter = (counter_t) value;
+ case DS_TYPE_GAUGE: {
+ *ret_rate = value.gauge;
+ break;
}
- else if (ds_type == DS_TYPE_ABSOLUTE)
- {
- ret_rate->gauge = (((absolute_t)value) - state->last_value.absolute) / interval;
- state->last_value.absolute = (absolute_t) value;
+ case DS_TYPE_COUNTER: {
+ counter_t diff = counter_diff (state->last_value.counter, value.counter);
+ *ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
+ break;
}
- else
- {
- assert (23 == 42);
+ case DS_TYPE_ABSOLUTE: {
+ absolute_t diff = value.absolute;
+ *ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
+ break;
+ }
+ default:
+ return EINVAL;
}
- state->last_time = t;
+ state->last_value = value;
+ state->last_time = t;
return (0);
} /* }}} value_t rate_to_value */
diff --git a/src/daemon/common.h b/src/daemon/common.h
index da21cad9a6f3a81f1120b466740a669ec009c231..c3f7f5485cb5888ed7a95634e538ff9c35b82d46 100644 (file)
--- a/src/daemon/common.h
+++ b/src/daemon/common.h
int rate_to_value (value_t *ret_value, gauge_t rate,
rate_to_value_state_t *state, int ds_type, cdtime_t t);
-int value_to_rate (value_t *ret_rate, derive_t value,
- value_to_rate_state_t *state, int ds_type, cdtime_t t);
+int value_to_rate (gauge_t *ret_rate, value_t value, int ds_type, cdtime_t t,
+ value_to_rate_state_t *state);
/* Converts a service name (a string) to a port number
* (in the range [1-65535]). Returns less than zero on error. */
index 1fa8f324461293c201b30440a8bb3e857062a993..ca8f15a35fd793d9799016ae594d2544ad5b67d7 100644 (file)
--- a/src/daemon/common_test.c
+++ b/src/daemon/common_test.c
* Florian octo Forster <octo at collectd.org>
*/
-#include "testing.h"
#include "common.h"
+#include "testing.h"
+
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc;
+#endif /* HAVE_LIBKSTAT */
DEF_TEST(sstrncpy)
{
ret = sstrncpy (ptr, "foobar", 8);
OK(ret == ptr);
- STREQ ("foobar", ptr);
+ EXPECT_EQ_STR ("foobar", ptr);
OK(buffer[3] == buffer[12]);
ret = sstrncpy (ptr, "abc", 8);
OK(ret == ptr);
- STREQ ("abc", ptr);
+ EXPECT_EQ_STR ("abc", ptr);
OK(buffer[3] == buffer[12]);
ret = sstrncpy (ptr, "collectd", 8);
OK(ret == ptr);
OK(ptr[7] == 0);
- STREQ ("collect", ptr);
+ EXPECT_EQ_STR ("collect", ptr);
OK(buffer[3] == buffer[12]);
return (0);
status = ssnprintf (ptr, 8, "%i", 1337);
OK(status == 4);
- STREQ ("1337", ptr);
+ EXPECT_EQ_STR ("1337", ptr);
status = ssnprintf (ptr, 8, "%s", "collectd");
OK(status == 8);
OK(ptr[7] == 0);
- STREQ ("collect", ptr);
+ EXPECT_EQ_STR ("collect", ptr);
OK(buffer[3] == buffer[12]);
return (0);
ptr = sstrdup ("collectd");
OK(ptr != NULL);
- STREQ ("collectd", ptr);
+ EXPECT_EQ_STR ("collectd", ptr);
sfree(ptr);
OK(ptr == NULL);
strncpy (buffer, "foo bar", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 2);
- STREQ ("foo", fields[0]);
- STREQ ("bar", fields[1]);
+ EXPECT_EQ_STR ("foo", fields[0]);
+ EXPECT_EQ_STR ("bar", fields[1]);
strncpy (buffer, "foo \t bar", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 2);
- STREQ ("foo", fields[0]);
- STREQ ("bar", fields[1]);
+ EXPECT_EQ_STR ("foo", fields[0]);
+ EXPECT_EQ_STR ("bar", fields[1]);
strncpy (buffer, "one two\tthree\rfour\nfive", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 5);
- STREQ ("one", fields[0]);
- STREQ ("two", fields[1]);
- STREQ ("three", fields[2]);
- STREQ ("four", fields[3]);
- STREQ ("five", fields[4]);
+ EXPECT_EQ_STR ("one", fields[0]);
+ EXPECT_EQ_STR ("two", fields[1]);
+ EXPECT_EQ_STR ("three", fields[2]);
+ EXPECT_EQ_STR ("four", fields[3]);
+ EXPECT_EQ_STR ("five", fields[4]);
strncpy (buffer, "\twith trailing\n", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 2);
- STREQ ("with", fields[0]);
- STREQ ("trailing", fields[1]);
+ EXPECT_EQ_STR ("with", fields[0]);
+ EXPECT_EQ_STR ("trailing", fields[1]);
strncpy (buffer, "1 2 3 4 5 6 7 8 9 10 11 12 13", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 8);
- STREQ ("7", fields[6]);
- STREQ ("8", fields[7]);
+ EXPECT_EQ_STR ("7", fields[6]);
+ EXPECT_EQ_STR ("8", fields[7]);
strncpy (buffer, "single", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 1);
- STREQ ("single", fields[0]);
+ EXPECT_EQ_STR ("single", fields[0]);
strncpy (buffer, "", sizeof (buffer));
status = strsplit (buffer, fields, 8);
status = strjoin (buffer, sizeof (buffer), fields, 2, "!");
OK(status == 7);
- STREQ ("foo!bar", buffer);
+ EXPECT_EQ_STR ("foo!bar", buffer);
status = strjoin (buffer, sizeof (buffer), fields, 1, "!");
OK(status == 3);
- STREQ ("foo", buffer);
+ EXPECT_EQ_STR ("foo", buffer);
status = strjoin (buffer, sizeof (buffer), fields, 0, "!");
OK(status < 0);
status = strjoin (buffer, sizeof (buffer), fields, 2, "rcht");
OK(status == 10);
- STREQ ("foorchtbar", buffer);
+ EXPECT_EQ_STR ("foorchtbar", buffer);
status = strjoin (buffer, sizeof (buffer), fields, 4, "");
OK(status == 12);
- STREQ ("foobarbazqux", buffer);
+ EXPECT_EQ_STR ("foobarbazqux", buffer);
status = strjoin (buffer, sizeof (buffer), fields, 4, "!");
OK(status == 15);
- STREQ ("foo!bar!baz!qux", buffer);
+ EXPECT_EQ_STR ("foo!bar!baz!qux", buffer);
fields[0] = "0123";
fields[1] = "4567";
return (0);
}
+DEF_TEST(escape_slashes)
+{
+ struct {
+ char *str;
+ char *want;
+ } cases[] = {
+ {"foo/bar/baz", "foo_bar_baz"},
+ {"/like/a/path", "like_a_path"},
+ {"trailing/slash/", "trailing_slash_"},
+ {"foo//bar", "foo__bar"},
+ };
+ size_t i;
+
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ char buffer[32];
+
+ strncpy (buffer, cases[i].str, sizeof (buffer));
+ OK(escape_slashes (buffer, sizeof (buffer)) == 0);
+ EXPECT_EQ_STR(cases[i].want, buffer);
+ }
+
+ return 0;
+}
+
+DEF_TEST(escape_string)
+{
+ struct {
+ char *str;
+ char *want;
+ } cases[] = {
+ {"foobar", "foobar"},
+ {"f00bar", "f00bar"},
+ {"foo bar", "\"foo bar\""},
+ {"foo \"bar\"", "\"foo \\\"bar\\\"\""},
+ {"012345678901234", "012345678901234"},
+ {"012345 78901234", "\"012345 789012\""},
+ {"012345 78901\"34", "\"012345 78901\""},
+ };
+ size_t i;
+
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ char buffer[16];
+
+ strncpy (buffer, cases[i].str, sizeof (buffer));
+ OK(escape_string (buffer, sizeof (buffer)) == 0);
+ EXPECT_EQ_STR(cases[i].want, buffer);
+ }
+
+ return 0;
+}
+
DEF_TEST(strunescape)
{
char buffer[16];
strncpy (buffer, "foo\\tbar", sizeof (buffer));
status = strunescape (buffer, sizeof (buffer));
OK(status == 0);
- STREQ ("foo\tbar", buffer);
+ EXPECT_EQ_STR ("foo\tbar", buffer);
strncpy (buffer, "\\tfoo\\r\\n", sizeof (buffer));
status = strunescape (buffer, sizeof (buffer));
OK(status == 0);
- STREQ ("\tfoo\r\n", buffer);
+ EXPECT_EQ_STR ("\tfoo\r\n", buffer);
strncpy (buffer, "With \\\"quotes\\\"", sizeof (buffer));
status = strunescape (buffer, sizeof (buffer));
OK(status == 0);
- STREQ ("With \"quotes\"", buffer);
+ EXPECT_EQ_STR ("With \"quotes\"", buffer);
/* Backslash before null byte */
strncpy (buffer, "\\tbackslash end\\", sizeof (buffer));
status = strunescape (buffer, sizeof (buffer));
OK(status != 0);
- STREQ ("\tbackslash end", buffer);
+ EXPECT_EQ_STR ("\tbackslash end", buffer);
return (0);
/* Backslash at buffer end */
return (0);
}
+DEF_TEST(parse_values)
+{
+ struct {
+ char buffer[64];
+ int status;
+ gauge_t value;
+ } cases[] = {
+ {"1435044576:42", 0, 42.0},
+ {"1435044576:42:23", -1, NAN},
+ {"1435044576:U", 0, NAN},
+ {"N:12.3", 0, 12.3},
+ {"N:42.0:23", -1, NAN},
+ {"N:U", 0, NAN},
+ {"T:42.0", -1, NAN},
+ };
+
+ size_t i;
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+ {
+ data_source_t dsrc = {
+ .name = "value",
+ .type = DS_TYPE_GAUGE,
+ .min = 0.0,
+ .max = NAN,
+ };
+ data_set_t ds = {
+ .type = "example",
+ .ds_num = 1,
+ .ds = &dsrc,
+ };
+
+ value_t v = {
+ .gauge = NAN,
+ };
+ value_list_t vl = {
+ .values = &v,
+ .values_len = 1,
+ .time = 0,
+ .interval = 0,
+ .host = "example.com",
+ .plugin = "common_test",
+ .type = "example",
+ .meta = NULL,
+ };
+
+ int status = parse_values (cases[i].buffer, &vl, &ds);
+ EXPECT_EQ_INT (cases[i].status, status);
+ if (status != 0)
+ continue;
+
+ EXPECT_EQ_DOUBLE (cases[i].value, vl.values[0].gauge);
+ }
+
+ return (0);
+}
+
+DEF_TEST(value_to_rate)
+{
+ struct {
+ time_t t0;
+ time_t t1;
+ int ds_type;
+ value_t v0;
+ value_t v1;
+ gauge_t want;
+ } cases[] = {
+ { 0, 10, DS_TYPE_DERIVE, {.derive = 0}, {.derive = 1000}, NAN},
+ {10, 20, DS_TYPE_DERIVE, {.derive = 1000}, {.derive = 2000}, 100.0},
+ {20, 30, DS_TYPE_DERIVE, {.derive = 2000}, {.derive = 1800}, -20.0},
+ { 0, 10, DS_TYPE_COUNTER, {.counter = 0}, {.counter = 1000}, NAN},
+ {10, 20, DS_TYPE_COUNTER, {.counter = 1000}, {.counter = 5000}, 400.0},
+ /* 32bit wrap-around. */
+ {20, 30, DS_TYPE_COUNTER, {.counter = 4294967238ULL}, {.counter = 42}, 10.0},
+ /* 64bit wrap-around. */
+ {30, 40, DS_TYPE_COUNTER, {.counter = 18446744073709551558ULL}, {.counter = 42}, 10.0},
+ };
+ size_t i;
+
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ value_to_rate_state_t state = { cases[i].v0, TIME_T_TO_CDTIME_T (cases[i].t0) };
+ gauge_t got;
+
+ if (cases[i].t0 == 0) {
+ OK(value_to_rate (&got, cases[i].v1, cases[i].ds_type, TIME_T_TO_CDTIME_T(cases[i].t1), &state) == EAGAIN);
+ continue;
+ }
+
+ OK(value_to_rate (&got, cases[i].v1, cases[i].ds_type, TIME_T_TO_CDTIME_T(cases[i].t1), &state) == 0);
+ EXPECT_EQ_DOUBLE(cases[i].want, got);
+ }
+
+ return 0;
+}
+
int main (void)
{
RUN_TEST(sstrncpy);
RUN_TEST(sstrdup);
RUN_TEST(strsplit);
RUN_TEST(strjoin);
+ RUN_TEST(escape_slashes);
+ RUN_TEST(escape_string);
RUN_TEST(strunescape);
+ RUN_TEST(parse_values);
+ RUN_TEST(value_to_rate);
END_TEST;
}
index 16e07247b3cf56d07937d677c1eddf861c5c2655..8a7621d2b5fb912b02d64c8c9f86456d42dbea08 100644 (file)
--- a/src/daemon/configfile.c
+++ b/src/daemon/configfile.c
typedef struct cf_value_map_s
{
- char *key;
+ const char *key;
int (*func) (oconfig_item_t *);
} cf_value_map_t;
typedef struct cf_global_option_s
{
- char *key;
+ const char *key;
char *value;
- char *def;
+ const char *def;
} cf_global_option_t;
/*
/* default to the global interval set before loading this plugin */
memset (&ctx, 0, sizeof (ctx));
ctx.interval = cf_get_default_interval ();
+ ctx.flush_interval = 0;
+ ctx.flush_timeout = 0;
- for (i = 0; i < ci->children_num; ++i) {
- if (strcasecmp("Globals", ci->children[i].key) == 0)
- cf_util_get_flag (ci->children + i, &flags, PLUGIN_FLAGS_GLOBAL);
- else if (strcasecmp ("Interval", ci->children[i].key) == 0) {
- if (cf_util_get_cdtime (ci->children + i, &ctx.interval) != 0) {
- /* cf_util_get_cdtime will log an error */
- continue;
- }
- }
+ for (i = 0; i < ci->children_num; ++i)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp("Globals", child->key) == 0)
+ cf_util_get_flag (child, &flags, PLUGIN_FLAGS_GLOBAL);
+ else if (strcasecmp ("Interval", child->key) == 0)
+ cf_util_get_cdtime (child, &ctx.interval);
+ else if (strcasecmp ("FlushInterval", child->key) == 0)
+ cf_util_get_cdtime (child, &ctx.flush_interval);
+ else if (strcasecmp ("FlushTimeout", child->key) == 0)
+ cf_util_get_cdtime (child, &ctx.flush_timeout);
else {
WARNING("Ignoring unknown LoadPlugin option \"%s\" "
"for plugin \"%s\"",
- ci->children[i].key, ci->values[0].value.string);
+ child->key, ci->values[0].value.string);
}
}
static int dispatch_block_plugin (oconfig_item_t *ci)
{
int i;
- char *name;
+ const char *name;
cf_complex_callback_t *cb;
@@ -1110,7 +1115,7 @@ int cf_register_complex (const char *type, int (*callback) (oconfig_item_t *))
return (0);
} /* int cf_register_complex */
-int cf_read (char *filename)
+int cf_read (const char *filename)
{
oconfig_item_t *conf;
int i;
index 5bc9b305615ee3404d8d373dd5544de7e88e433d..648246bd2d22076178afb4f64df2bbadd97c74cc 100644 (file)
--- a/src/daemon/configfile.h
+++ b/src/daemon/configfile.h
* Returns zero upon success and non-zero otherwise. A error-message will have
* been printed in this case.
*/
-int cf_read (char *filename);
+int cf_read (const char *filename);
int global_option_set (const char *option, const char *value);
const char *global_option_get (const char *option);
diff --git a/src/daemon/meta_data_test.c b/src/daemon/meta_data_test.c
--- /dev/null
@@ -0,0 +1,119 @@
+/**
+ * collectd - src/daemon/meta_data_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "collectd.h"
+#include "testing.h"
+#include "meta_data.h"
+
+DEF_TEST(base)
+{
+ meta_data_t *m;
+
+ char *s;
+ int64_t si;
+ uint64_t ui;
+ double d;
+ _Bool b;
+
+ CHECK_NOT_NULL (m = meta_data_create ());
+
+ /* all of these are absent */
+ OK(meta_data_get_string (m, "string", &s) != 0);
+ OK(meta_data_get_signed_int (m, "signed_int", &si) != 0);
+ OK(meta_data_get_unsigned_int (m, "unsigned_int", &ui) != 0);
+ OK(meta_data_get_double (m, "double", &d) != 0);
+ OK(meta_data_get_boolean (m, "boolean", &b) != 0);
+
+ /* populate structure */
+ CHECK_ZERO (meta_data_add_string (m, "string", "foobar"));
+ OK(meta_data_exists (m, "string"));
+ OK(meta_data_type (m, "string") == MD_TYPE_STRING);
+
+ CHECK_ZERO (meta_data_add_signed_int (m, "signed_int", -1));
+ OK(meta_data_exists (m, "signed_int"));
+ OK(meta_data_type (m, "signed_int") == MD_TYPE_SIGNED_INT);
+
+ CHECK_ZERO (meta_data_add_unsigned_int (m, "unsigned_int", 1));
+ OK(meta_data_exists (m, "unsigned_int"));
+ OK(meta_data_type (m, "unsigned_int") == MD_TYPE_UNSIGNED_INT);
+
+ CHECK_ZERO (meta_data_add_double (m, "double", 47.11));
+ OK(meta_data_exists (m, "double"));
+ OK(meta_data_type (m, "double") == MD_TYPE_DOUBLE);
+
+ CHECK_ZERO (meta_data_add_boolean (m, "boolean", 1));
+ OK(meta_data_exists (m, "boolean"));
+ OK(meta_data_type (m, "boolean") == MD_TYPE_BOOLEAN);
+
+ /* retrieve and check all values */
+ CHECK_ZERO (meta_data_get_string (m, "string", &s));
+ EXPECT_EQ_STR ("foobar", s);
+ sfree (s);
+
+ CHECK_ZERO (meta_data_get_signed_int (m, "signed_int", &si));
+ EXPECT_EQ_INT (-1, (int) si);
+
+ CHECK_ZERO (meta_data_get_unsigned_int (m, "unsigned_int", &ui));
+ EXPECT_EQ_INT (1, (int) ui);
+
+ CHECK_ZERO (meta_data_get_double (m, "double", &d));
+ EXPECT_EQ_DOUBLE (47.11, d);
+
+ CHECK_ZERO (meta_data_get_boolean (m, "boolean", &b));
+ OK1 (b, "b evaluates to true");
+
+ /* retrieving the wrong type always fails */
+ EXPECT_EQ_INT (-2, meta_data_get_boolean (m, "string", &b));
+ EXPECT_EQ_INT (-2, meta_data_get_string (m, "signed_int", &s));
+ EXPECT_EQ_INT (-2, meta_data_get_string (m, "unsigned_int", &s));
+ EXPECT_EQ_INT (-2, meta_data_get_string (m, "double", &s));
+ EXPECT_EQ_INT (-2, meta_data_get_string (m, "boolean", &s));
+
+ /* replace existing keys */
+ CHECK_ZERO (meta_data_add_signed_int (m, "string", 666));
+ OK(meta_data_type (m, "string") == MD_TYPE_SIGNED_INT);
+
+ CHECK_ZERO (meta_data_add_signed_int (m, "signed_int", 666));
+ CHECK_ZERO (meta_data_get_signed_int (m, "signed_int", &si));
+ EXPECT_EQ_INT (666, (int) si);
+
+ /* deleting keys */
+ CHECK_ZERO (meta_data_delete (m, "signed_int"));
+ EXPECT_EQ_INT (-2, meta_data_delete (m, "doesnt exist"));
+
+ meta_data_destroy (m);
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(base);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/plugin.c b/src/daemon/plugin.c
index e723af075d112363ac9db07d4cdab99546bfad85..e7993f1e8686b4adce2670754f9f24f82f3e9dc4 100644 (file)
--- a/src/daemon/plugin.c
+++ b/src/daemon/plugin.c
write_queue_t *next;
};
+struct flush_callback_s {
+ char *name;
+ cdtime_t timeout;
+};
+typedef struct flush_callback_s flush_callback_t;
+
/*
* Private variables
*/
{
ERROR ("plugin: register_callback: "
"llentry_create failed.");
- free (key);
+ sfree (key);
destroy_callback (cf);
return (-1);
}
*str = '\0';
strjoin(str, len, keys, n, "', '");
INFO("%s ['%s']", comment, str);
- free(str);
+ sfree (str);
}
- free(keys);
+ sfree (keys);
} /* }}} void log_list_callbacks */
static int create_register_callback (llist_t **list, /* {{{ */
{
read_func_t *rf;
plugin_ctx_t old_ctx;
+ cdtime_t start;
cdtime_t now;
+ cdtime_t elapsed;
int status;
int rf_type;
int rc;
DEBUG ("plugin_read_thread: Handling `%s'.", rf->rf_name);
+ start = cdtime ();
+
old_ctx = plugin_set_ctx (rf->rf_ctx);
if (rf_type == RF_SIMPLE)
/* update the ``next read due'' field */
now = cdtime ();
+ /* calculate the time spent in the read function */
+ elapsed = (now - start);
+
+ if (elapsed > rf->rf_effective_interval)
+ WARNING ("plugin_read_thread: read-function of the `%s' plugin took %.3f "
+ "seconds, which is above its read interval (%.3f seconds). You might "
+ "want to adjust the `Interval' or `ReadThreads' settings.",
+ rf->rf_name, CDTIME_T_TO_DOUBLE(elapsed),
+ CDTIME_T_TO_DOUBLE(rf->rf_effective_interval));
+
+ DEBUG ("plugin_read_thread: read-function of the `%s' plugin took "
+ "%.6f seconds.",
+ rf->rf_name, CDTIME_T_TO_DOUBLE(elapsed));
+
DEBUG ("plugin_read_thread: Effective interval of the "
- "%s plugin is %.3f seconds.",
+ "`%s' plugin is %.3f seconds.",
rf->rf_name,
CDTIME_T_TO_DOUBLE (rf->rf_effective_interval));
rf->rf_next_read = now;
}
- DEBUG ("plugin_read_thread: Next read of the %s plugin at %.3f.",
+ DEBUG ("plugin_read_thread: Next read of the `%s' plugin at %.3f.",
rf->rf_name,
CDTIME_T_TO_DOUBLE (rf->rf_next_read));
static void stop_write_threads (void) /* {{{ */
{
write_queue_t *q;
- int i;
+ size_t i;
if (write_threads == NULL)
return;
if (i > 0)
{
- WARNING ("plugin: %i value list%s left after shutting down "
+ WARNING ("plugin: %zu value list%s left after shutting down "
"the write threads.",
i, (i == 1) ? " was" : "s were");
}
*/
void plugin_set_dir (const char *dir)
{
- if (plugindir != NULL)
- free (plugindir);
+ sfree (plugindir);
if (dir == NULL)
- plugindir = NULL;
- else if ((plugindir = strdup (dir)) == NULL)
{
- char errbuf[1024];
- ERROR ("strdup failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
+ plugindir = NULL;
+ return;
}
+
+ plugindir = strdup (dir);
+ if (plugindir == NULL)
+ ERROR ("plugin_set_dir: strdup(\"%s\") failed", dir);
}
static _Bool plugin_is_loaded (char const *name)
/* success */
plugin_mark_loaded (plugin_name);
ret = 0;
+ INFO ("plugin_load: plugin \"%s\" successfully loaded.", plugin_name);
break;
}
else
int plugin_register_complex_read (const char *group, const char *name,
plugin_read_cb callback,
- const struct timespec *interval,
+ cdtime_t interval,
user_data_t *user_data)
{
read_func_t *rf;
rf->rf_group[0] = '\0';
rf->rf_name = strdup (name);
rf->rf_type = RF_COMPLEX;
- if (interval != NULL)
- rf->rf_interval = TIMESPEC_TO_CDTIME_T (interval);
- else
- rf->rf_interval = plugin_get_interval ();
+ rf->rf_interval = (interval != 0) ? interval : plugin_get_interval ();
/* Set user data */
if (user_data == NULL)
(void *) callback, ud));
} /* int plugin_register_write */
+static int plugin_flush_timeout_callback (user_data_t *ud)
+{
+ flush_callback_t *cb = ud->data;
+
+ return plugin_flush (cb->name, cb->timeout, /* identifier = */ NULL);
+} /* static int plugin_flush_callback */
+
+static void plugin_flush_timeout_callback_free (void *data)
+{
+ flush_callback_t *cb = data;
+
+ if (cb == NULL) return;
+
+ sfree (cb->name);
+ sfree (cb);
+} /* static void plugin_flush_callback_free */
+
+static char *plugin_flush_callback_name (const char *name)
+{
+ const char *flush_prefix = "flush/";
+ size_t prefix_size;
+ char *flush_name;
+ size_t name_size;
+
+ prefix_size = strlen(flush_prefix);
+ name_size = strlen(name);
+
+ flush_name = malloc (sizeof(char) * (name_size + prefix_size + 1));
+ if (flush_name == NULL)
+ {
+ ERROR ("plugin_flush_callback_name: malloc failed.");
+ return (NULL);
+ }
+
+ sstrncpy (flush_name, flush_prefix, prefix_size + 1);
+ sstrncpy (flush_name + prefix_size, name, name_size + 1);
+
+ return flush_name;
+} /* static char *plugin_flush_callback_name */
+
int plugin_register_flush (const char *name,
plugin_flush_cb callback, user_data_t *ud)
{
- return (create_register_callback (&list_flush, name,
- (void *) callback, ud));
+ int status;
+ plugin_ctx_t ctx = plugin_get_ctx ();
+
+ status = create_register_callback (&list_flush, name,
+ (void *) callback, ud);
+ if (status != 0)
+ return status;
+
+ if (ctx.flush_interval != 0)
+ {
+ char *flush_name;
+ flush_callback_t *cb;
+
+ flush_name = plugin_flush_callback_name (name);
+ if (flush_name == NULL)
+ return (-1);
+
+ cb = malloc(sizeof(flush_callback_t));
+ if (cb == NULL)
+ {
+ ERROR ("plugin_register_flush: malloc failed.");
+ sfree (flush_name);
+ return (-1);
+ }
+
+ cb->name = strdup (name);
+ if (cb->name == NULL)
+ {
+ ERROR ("plugin_register_flush: strdup failed.");
+ sfree (cb);
+ sfree (flush_name);
+ return (-1);
+ }
+ cb->timeout = ctx.flush_timeout;
+
+ ud->data = cb;
+ ud->free_func = plugin_flush_timeout_callback_free;
+
+ status = plugin_register_complex_read (
+ /* group = */ "flush",
+ /* name = */ flush_name,
+ /* callback = */ plugin_flush_timeout_callback,
+ /* interval = */ ctx.flush_interval,
+ /* user data = */ ud);
+
+ sfree (flush_name);
+ if (status != 0)
+ {
+ sfree (cb->name);
+ sfree (cb);
+ return status;
+ }
+ }
+
+ return 0;
} /* int plugin_register_flush */
int plugin_register_missing (const char *name,
int plugin_register_data_set (const data_set_t *ds)
{
data_set_t *ds_copy;
- int i;
+ size_t i;
if ((data_sets != NULL)
&& (c_avl_get (data_sets, ds->type, NULL) == 0))
* ds->ds_num);
if (ds_copy->ds == NULL)
{
- free (ds_copy);
+ sfree (ds_copy);
return (-1);
}
int plugin_unregister_flush (const char *name)
{
- return (plugin_unregister (list_flush, name));
+ plugin_ctx_t ctx = plugin_get_ctx ();
+
+ if (ctx.flush_interval != 0)
+ {
+ char *flush_name;
+
+ flush_name = plugin_flush_callback_name (name);
+ if (flush_name != NULL)
+ {
+ plugin_unregister_read(flush_name);
+ sfree (flush_name);
+ }
+ }
+
+ return plugin_unregister (list_flush, name);
}
int plugin_unregister_missing (const char *name)
if (ds->ds_num != vl->values_len)
{
ERROR ("plugin_dispatch_values: ds->type = %s: "
- "(ds->ds_num = %i) != "
- "(vl->values_len = %i)",
+ "(ds->ds_num = %zu) != "
+ "(vl->values_len = %zu)",
ds->type, ds->ds_num, vl->values_len);
return (-1);
}
* don't get confused.. */
if (saved_values != NULL)
{
- free (vl->values);
+ sfree (vl->values);
vl->values = saved_values;
vl->values_len = saved_values_len;
}
* confused.. */
if (saved_values != NULL)
{
- free (vl->values);
+ sfree (vl->values);
vl->values = saved_values;
vl->values_len = saved_values_len;
}
if (this->type == NM_TYPE_STRING)
{
- free ((char *)this->nm_value.nm_string);
+ /* Assign to a temporary variable to work around nm_string's const
+ * modifier. */
+ void *tmp = (void *) this->nm_value.nm_string;
+
+ sfree (tmp);
this->nm_value.nm_string = NULL;
}
sfree (this);
plugin_set_ctx (plugin_thread->ctx);
- free (plugin_thread);
+ sfree (plugin_thread);
return start_routine (plugin_arg);
} /* void *plugin_thread_start */
diff --git a/src/daemon/plugin.h b/src/daemon/plugin.h
index cba298cfc4355a3783ac918b9589c8bb94ee6f52..a63f5cdc6e5e189e0461cf982f117e6d48b55a0f 100644 (file)
--- a/src/daemon/plugin.h
+++ b/src/daemon/plugin.h
struct value_list_s
{
value_t *values;
- int values_len;
+ size_t values_len;
cdtime_t time;
cdtime_t interval;
char host[DATA_MAX_NAME_LEN];
struct data_set_s
{
char type[DATA_MAX_NAME_LEN];
- int ds_num;
+ size_t ds_num;
data_source_t *ds;
};
typedef struct data_set_s data_set_t;
struct plugin_ctx_s
{
cdtime_t interval;
+ cdtime_t flush_interval;
+ cdtime_t flush_timeout;
};
typedef struct plugin_ctx_s plugin_ctx_t;
* "plugin_register_complex_read" returns an error (non-zero). */
int plugin_register_complex_read (const char *group, const char *name,
plugin_read_cb callback,
- const struct timespec *interval,
+ cdtime_t interval,
user_data_t *user_data);
int plugin_register_write (const char *name,
plugin_write_cb callback, user_data_t *user_data);
index f3eefd5a6ebc5ebededb1af1206f4f997a330941..b6efa3ad788387528074efc38b258b6ef309b6dd 100644 (file)
--- a/src/daemon/plugin_mock.c
+++ b/src/daemon/plugin_mock.c
#include "plugin.h"
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc = NULL;
+#endif /* HAVE_LIBKSTAT */
+
char hostname_g[] = "example.com";
int plugin_register_complex_config (const char *type, int (*callback) (oconfig_item_t *))
index 4023a8f609759920d18bcdb4503c295a7f70be57..eb50bb8a390969fcf580419b944e05b7fec537b8 100644 (file)
--- a/src/daemon/types_list.c
+++ b/src/daemon/types_list.c
char *fields[64];
size_t fields_num;
data_set_t *ds;
- int i;
+ size_t i;
fields_num = strsplit (buf, fields, 64);
if (fields_num < 2)
ds->ds_num = fields_num - 1;
ds->ds = (data_source_t *) calloc (ds->ds_num, sizeof (data_source_t));
if (ds->ds == NULL)
+ {
+ sfree (ds);
return;
+ }
for (i = 0; i < ds->ds_num; i++)
if (parse_ds (ds->ds + i, fields[i + 1], strlen (fields[i + 1])) != 0)
{
- sfree (ds->ds);
- ERROR ("types_list: parse_line: Cannot parse data source #%i "
+ ERROR ("types_list: parse_line: Cannot parse data source #%zu "
"of data set %s", i, ds->type);
+ sfree (ds->ds);
+ sfree (ds);
return;
}
index 2a8244c9f3e6cd1008649091de98b595ebf386f6..489d60faa2b0cd3602857d8d2b543c4c61bf7b07 100644 (file)
* Florian octo Forster <octo at collectd.org>
*/
-#include "testing.h"
+#include "common.h" /* STATIC_ARRAY_SIZE */
#include "collectd.h"
+#include "testing.h"
#include "utils_avltree.h"
static int compare_total_count = 0;
DEF_TEST(success)
{
+ struct {
+ char *key;
+ char *value;
+ } cases[] = {
+ {"Eeph7chu", "vai1reiV"},
+ {"igh3Paiz", "teegh1Ee"},
+ {"caip6Uu8", "ooteQu8n"},
+ {"Aech6vah", "AijeeT0l"},
+ {"Xah0et2L", "gah8Taep"},
+ {"BocaeB8n", "oGaig8io"},
+ {"thai8AhM", "ohjeFo3f"},
+ {"ohth6ieC", "hoo8ieWo"},
+ {"aej7Woow", "phahuC2s"},
+ {"Hai8ier2", "Yie6eimi"},
+ {"phuXi3Li", "JaiF7ieb"},
+ {"Shaig5ef", "aihi5Zai"},
+ {"voh6Aith", "Oozaeto0"},
+ {"zaiP5kie", "seep5veM"},
+ {"pae7ba7D", "chie8Ojo"},
+ {"Gou2ril3", "ouVoo0ha"},
+ {"lo3Thee3", "ahDu4Zuj"},
+ {"Rah8kohv", "ieShoc7E"},
+ {"ieN5engi", "Aevou1ah"},
+ {"ooTe4OhP", "aingai5Y"},
+ };
+
c_avl_tree_t *t;
- char key_orig[] = "foo";
- char value_orig[] = "bar";
- char *key_ret = NULL;
- char *value_ret = NULL;
+ size_t i;
RESET_COUNTS ();
- t = c_avl_create (compare_callback);
- OK (t != NULL);
+ CHECK_NOT_NULL (t = c_avl_create (compare_callback));
+
+ /* insert */
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+ {
+ char *key;
+ char *value;
- OK (c_avl_insert (t, key_orig, value_orig) == 0);
- OK (c_avl_size (t) == 1);
+ CHECK_NOT_NULL (key = strdup (cases[i].key));
+ CHECK_NOT_NULL (value = strdup (cases[i].value));
+
+ CHECK_ZERO (c_avl_insert (t, key, value));
+ EXPECT_EQ_INT ((int) (i + 1), c_avl_size (t));
+ }
/* Key already exists. */
- OK (c_avl_insert (t, "foo", "qux") > 0);
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+ EXPECT_EQ_INT (1, c_avl_insert (t, cases[i].key, cases[i].value));
+
+ /* get */
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+ {
+ char *value_ret = NULL;
+
+ CHECK_ZERO (c_avl_get (t, cases[i].key, (void *) &value_ret));
+ EXPECT_EQ_STR (cases[i].value, value_ret);
+ }
+
+ /* remove half */
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases) / 2; i++)
+ {
+ char *key = NULL;
+ char *value = NULL;
+
+ int expected_size = (int) (STATIC_ARRAY_SIZE (cases) - (i + 1));
+
+ CHECK_ZERO (c_avl_remove (t, cases[i].key, (void *) &key, (void *) &value));
+
+ EXPECT_EQ_STR (cases[i].key, key);
+ EXPECT_EQ_STR (cases[i].value, value);
+
+ free (key);
+ free (value);
+
+ EXPECT_EQ_INT (expected_size, c_avl_size (t));
+ }
+
+ /* pick the other half */
+ for (i = STATIC_ARRAY_SIZE (cases) / 2; i < STATIC_ARRAY_SIZE (cases); i++)
+ {
+ char *key = NULL;
+ char *value = NULL;
+
+ int expected_size = (int) (STATIC_ARRAY_SIZE (cases) - (i + 1));
+
+ EXPECT_EQ_INT (expected_size + 1, c_avl_size (t));
+ EXPECT_EQ_INT (0, c_avl_pick (t, (void *) &key, (void *) &value));
- OK (c_avl_get (t, "foo", (void *) &value_ret) == 0);
- OK (value_ret == &value_orig[0]);
+ free (key);
+ free (value);
- key_ret = value_ret = NULL;
- OK (c_avl_remove (t, "foo", (void *) &key_ret, (void *) &value_ret) == 0);
- OK (key_ret == &key_orig[0]);
- OK (value_ret == &value_orig[0]);
- OK (c_avl_size (t) == 0);
+ EXPECT_EQ_INT (expected_size, c_avl_size (t));
+ }
c_avl_destroy (t);
index 45444c7f912b4575984ca1937240beb3ce04ba12..0756807334b7b4eba7bf05bb3757c3917de63878 100644 (file)
--- a/src/daemon/utils_cache.c
+++ b/src/daemon/utils_cache.c
typedef struct cache_entry_s
{
char name[6 * DATA_MAX_NAME_LEN];
- int values_num;
+ size_t values_num;
gauge_t *values_gauge;
value_t *values_raw;
/* Time contained in the package
return (strcmp (a->name, b->name));
} /* int cache_compare */
-static cache_entry_t *cache_alloc (int values_num)
+static cache_entry_t *cache_alloc (size_t values_num)
{
cache_entry_t *ce;
static void uc_check_range (const data_set_t *ds, cache_entry_t *ce)
{
- int i;
+ size_t i;
for (i = 0; i < ds->ds_num; i++)
{
static int uc_insert (const data_set_t *ds, const value_list_t *vl,
const char *key)
{
- int i;
char *key_copy;
cache_entry_t *ce;
+ size_t i;
/* `cache_lock' has been locked by `uc_update' */
if (ce == NULL)
{
sfree (key_copy);
- ERROR ("uc_insert: cache_alloc (%i) failed.", ds->ds_num);
+ ERROR ("uc_insert: cache_alloc (%zu) failed.", ds->ds_num);
return (-1);
}
char name[6 * DATA_MAX_NAME_LEN];
cache_entry_t *ce = NULL;
int status;
- int i;
+ size_t i;
if (FORMAT_VL (name, sizeof (name), vl) != 0)
{
{
case DS_TYPE_COUNTER:
{
- counter_t diff;
-
- /* check if the counter has wrapped around */
- if (vl->values[i].counter < ce->values_raw[i].counter)
- {
- if (ce->values_raw[i].counter <= 4294967295U)
- diff = (4294967295U - ce->values_raw[i].counter)
- + vl->values[i].counter;
- else
- diff = (18446744073709551615ULL - ce->values_raw[i].counter)
- + vl->values[i].counter;
- }
- else /* counter has NOT wrapped around */
- {
- diff = vl->values[i].counter - ce->values_raw[i].counter;
- }
-
+ counter_t diff = counter_diff (ce->values_raw[i].counter, vl->values[i].counter);
ce->values_gauge[i] = ((double) diff)
/ (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
ce->values_raw[i].counter = vl->values[i].counter;
case DS_TYPE_DERIVE:
{
- derive_t diff;
-
- diff = vl->values[i].derive - ce->values_raw[i].derive;
+ derive_t diff = vl->values[i].derive - ce->values_raw[i].derive;
ce->values_gauge[i] = ((double) diff)
/ (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
return (-1);
} /* switch (ds->ds[i].type) */
- DEBUG ("uc_update: %s: ds[%i] = %lf", name, i, ce->values_gauge[i]);
+ DEBUG ("uc_update: %s: ds[%zu] = %lf", name, i, ce->values_gauge[i]);
} /* for (i) */
/* Update the history if it exists. */
* values are returned. */
if (ret_num != (size_t) ds->ds_num)
{
- ERROR ("utils_cache: uc_get_rate: ds[%s] has %i values, "
+ ERROR ("utils_cache: uc_get_rate: ds[%s] has %zu values, "
"but uc_get_rate_by_name returned %zu.",
ds->type, ds->ds_num, ret_num);
sfree (ret);
index 6c78d64dc86c01bc731ff5a09ed6688fd94a5587..37f21edb0f9023d1e3132999b75953e6e6cbec17 100644 (file)
#include "utils_cache.h"
-gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl)
+gauge_t *uc_get_rate (__attribute((unused)) data_set_t const *ds,
+ __attribute((unused)) value_list_t const *vl)
{
return (NULL);
}
index 53d0fba863f3b7cb6a117e5224107d9dc98cfb8c..6ef80475c0bde77931173b0d50231561a84934af 100644 (file)
* Florian octo Forster <octo at collectd.org>
*/
-#include "testing.h"
#include "collectd.h"
+#include "testing.h"
#include "utils_heap.h"
static int compare (void const *v0, void const *v1)
index 692a1e51bc12c9698025674c8f034d4cd05ba851..12688380e89739f9afd03e6440521580cf5fe74d 100644 (file)
@@ -88,50 +88,45 @@ static inline void ignorelist_append (ignorelist_t *il, ignorelist_item_t *item)
}
#if HAVE_REGEX_H
-static int ignorelist_append_regex(ignorelist_t *il, const char *entry)
+static int ignorelist_append_regex(ignorelist_t *il, const char *re_str)
{
regex_t *re;
- ignorelist_item_t *item;
+ ignorelist_item_t *entry;
int status;
- /* create buffer */
re = malloc (sizeof (*re));
if (re == NULL)
{
ERROR ("ignorelist_append_regex: malloc failed.");
- return ENOMEM;
+ return (ENOMEM);
}
memset (re, 0, sizeof (*re));
- /* compile regex */
- status = regcomp (re, entry, REG_EXTENDED);
+ status = regcomp (re, re_str, REG_EXTENDED);
if (status != 0)
{
char errbuf[1024];
-
(void) regerror (status, re, errbuf, sizeof (errbuf));
- ERROR ("ignorelist_append_regex: Compiling regular expression \"%s\" failed: %s", entry, errbuf);
+ ERROR ("utils_ignorelist: regcomp failed: %s", errbuf);
+ ERROR ("ignorelist_append_regex: Compiling regular expression \"%s\" failed: %s", re_str, errbuf);
sfree (re);
- return status;
+ return (status);
}
- /* create new entry */
- item = malloc (sizeof (*item));
- if (item == NULL)
+ entry = malloc (sizeof (*entry));
+ if (entry == NULL)
{
ERROR ("ignorelist_append_regex: malloc failed.");
regfree (re);
sfree (re);
- return ENOMEM;
+ return (ENOMEM);
}
- memset (item, 0, sizeof (*item));
- item->rmatch = re;
-
- /* append new entry */
- ignorelist_append (il, item);
+ memset (entry, 0, sizeof (*entry));
+ entry->rmatch = re;
+ ignorelist_append (il, entry);
return (0);
-} /* int ignorelist_append_regex(ignorelist_t *il, const char *entry) */
+} /* int ignorelist_append_regex */
#endif
static int ignorelist_append_string(ignorelist_t *il, const char *entry)
/*
* append entry into ignorelist_t
- * return 1 for success
+ * return 0 for success
*/
int ignorelist_add (ignorelist_t *il, const char *entry)
{
index 3e554973c7698dc54bd6d32c0d612e11270a1223..cfa1c7642f0d01b5b5bbdfb2be78dbf38bcb6968 100644 (file)
--- a/src/daemon/utils_subst.c
+++ b/src/daemon/utils_subst.c
#include "common.h"
#include "utils_subst.h"
-char *subst (char *buf, size_t buflen, const char *string, int off1, int off2,
+char *subst (char *buf, size_t buflen, const char *string, size_t off1, size_t off2,
const char *replacement)
{
- char *buf_ptr = buf;
- size_t len = buflen;
+ char *out = buf;
- if ((NULL == buf) || (0 >= buflen) || (NULL == string)
- || (0 > off1) || (0 > off2) || (off1 > off2)
- || (NULL == replacement))
+ char const *front;
+ char const *back;
+ size_t front_len;
+ size_t replacement_len;
+ size_t back_len;
+
+ if ((NULL == buf) || (0 == buflen) || (NULL == string) || (NULL == replacement))
return NULL;
- sstrncpy (buf_ptr, string,
- ((size_t)off1 + 1 > buflen) ? buflen : (size_t)off1 + 1);
- buf_ptr += off1;
- len -= off1;
+ size_t string_len = strlen (string);
+ if ((off1 > string_len) || (off2 > string_len) || (off1 > off2))
+ return NULL;
- if (0 >= len)
- return buf;
+ front = string;
+ back = string + off2;
+ front_len = off1;
+ replacement_len = strlen (replacement);
+ back_len = strlen (back);
+
+ if (front_len >= buflen) {
+ front_len = buflen - 1;
+ replacement_len = 0;
+ back_len = 0;
+ } else if ((front_len + replacement_len) >= buflen) {
+ replacement_len = buflen - (front_len + 1);
+ back_len = 0;
+ } else if ((front_len + replacement_len + back_len) >= buflen) {
+ back_len = buflen - (front_len + replacement_len + 1);
+ } else {
+ buflen = front_len + replacement_len + back_len + 1;
+ }
+ assert ((front_len + replacement_len + back_len) == (buflen - 1));
- sstrncpy (buf_ptr, replacement, len);
- buf_ptr += strlen (replacement);
- len -= strlen (replacement);
+ if (front_len != 0) {
+ sstrncpy (out, front, front_len + 1);
+ out += front_len;
+ }
- if (0 >= len)
- return buf;
+ if (replacement_len != 0) {
+ sstrncpy (out, replacement, replacement_len + 1);
+ out += replacement_len;
+ }
- sstrncpy (buf_ptr, string + off2, len);
+ if (back_len != 0) {
+ sstrncpy (out, back, back_len + 1);
+ out += back_len;
+ }
+
+ out[0] = 0;
return buf;
} /* subst */
char *subst_string (char *buf, size_t buflen, const char *string,
const char *needle, const char *replacement)
{
- char *temp;
size_t needle_len;
size_t i;
|| (needle == NULL) || (replacement == NULL))
return (NULL);
- temp = (char *) malloc (buflen);
- if (temp == NULL)
- {
- ERROR ("subst_string: malloc failed.");
- return (NULL);
- }
-
needle_len = strlen (needle);
- strncpy (buf, string, buflen);
+ sstrncpy (buf, string, buflen);
/* Limit the loop to prevent endless loops. */
for (i = 0; i < buflen; i++)
{
+ char temp[buflen];
char *begin_ptr;
size_t begin;
i, string, needle, replacement);
}
- sfree (temp);
return (buf);
} /* char *subst_string */
index 9085286a474c79da17428467e0865ae02bcb07f6..50df9c7ba0404a377e2b3a0967f58adfe931b039 100644 (file)
--- a/src/daemon/utils_subst.h
+++ b/src/daemon/utils_subst.h
*
* The function returns 'buf' on success, NULL else.
*/
-char *subst (char *buf, size_t buflen, const char *string, int off1, int off2,
+char *subst (char *buf, size_t buflen, const char *string, size_t off1, size_t off2,
const char *replacement);
/*
diff --git a/src/daemon/utils_subst_test.c b/src/daemon/utils_subst_test.c
--- /dev/null
@@ -0,0 +1,136 @@
+/**
+ * collectd - src/daemon/utils_subst_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "collectd.h"
+#include "testing.h"
+#include "utils_subst.h"
+
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc;
+#endif /* HAVE_LIBKSTAT */
+
+DEF_TEST(subst)
+{
+ struct {
+ const char *str;
+ int off1;
+ int off2;
+ const char *rplmt;
+ const char *want;
+ } cases[] = {
+ {"foo_____bar", 3, 8, " - ", "foo - bar"}, /* documentation example */
+ {"foo bar", 0, 2, "m", "mo bar"}, /* beginning, shorten */
+ {"foo bar", 0, 1, "m", "moo bar"}, /* beginning, same length */
+ {"foo bar", 0, 3, "milk", "milk bar"}, /* beginning, extend */
+ {"foo bar", 3, 6, "de", "fooder"}, /* center, shorten */
+ {"foo bar", 2, 6, "rste", "forster"}, /* center, same length */
+ {"foo bar", 1, 3, "ish", "fish bar"}, /* center, extend */
+ {"foo bar", 2, 7, "ul", "foul"}, /* end, shorten */
+ {"foo bar", 3, 7, "lish", "foolish"}, /* end, same length */
+ {"foo bar", 3, 7, "dwear", "foodwear"}, /* end, extend */
+ /* truncation (buffer is 16 chars) */
+ {"01234567890123", 8, 8, "", "01234567890123"},
+ {"01234567890123", 8, 8, "*", "01234567*890123"},
+ {"01234567890123", 8, 8, "**", "01234567**89012"},
+ /* input > buffer */
+ {"012345678901234----", 0, 0, "", "012345678901234"},
+ {"012345678901234----", 17, 18, "", "012345678901234"},
+ {"012345678901234----", 0, 3, "", "345678901234---"},
+ {"012345678901234----", 0, 4, "", "45678901234----"},
+ {"012345678901234----", 0, 5, "", "5678901234----"},
+ {"012345678901234----", 8, 8, "#", "01234567#890123"},
+ {"012345678901234----", 12, 12, "##", "012345678901##2"},
+ {"012345678901234----", 13, 13, "##", "0123456789012##"},
+ {"012345678901234----", 14, 14, "##", "01234567890123#"},
+ {"012345678901234----", 15, 15, "##", "012345678901234"},
+ {"012345678901234----", 16, 16, "##", "012345678901234"},
+ /* error cases */
+ {NULL, 3, 4, "_", NULL}, /* no input */
+ {"foo bar", 3, 10, "_", NULL}, /* offset exceeds input */
+ {"foo bar", 10, 13, "_", NULL}, /* offset exceeds input */
+ {"foo bar", 4, 3, "_", NULL}, /* off1 > off2 */
+ {"foo bar", 3, 4, NULL, NULL}, /* no replacement */
+ };
+ size_t i;
+
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ char buffer[16] = "!!!!!!!!!!!!!!!";
+
+ if (cases[i].want == NULL) {
+ OK(subst (buffer, sizeof (buffer), cases[i].str, cases[i].off1, cases[i].off2, cases[i].rplmt) == NULL);
+ continue;
+ }
+
+ OK(subst (buffer, sizeof (buffer), cases[i].str, cases[i].off1, cases[i].off2, cases[i].rplmt) == &buffer[0]);
+ EXPECT_EQ_STR(cases[i].want, buffer);
+ }
+
+ return 0;
+}
+
+DEF_TEST(subst_string)
+{
+ struct {
+ const char *str;
+ const char *srch;
+ const char *rplmt;
+ const char *want;
+ } cases[] = {
+ {"Hello %{name}", "%{name}", "world", "Hello world"},
+ {"abcccccc", "abc", "cab", "ccccccab"},
+ {"(((()(())))())", "()", "", ""},
+ {"food booth", "oo", "ee", "feed beeth"},
+ {"foo bar", "baz", "qux", "foo bar"},
+ {"foo bar", "oo", "oo", "foo bar"},
+ {"sixteen chars", "chars", "characters", "sixteen charact"},
+ };
+ size_t i;
+
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ char buffer[16];
+
+ if (cases[i].want == NULL) {
+ OK(subst_string (buffer, sizeof (buffer), cases[i].str, cases[i].srch, cases[i].rplmt) == NULL);
+ continue;
+ }
+
+ OK(subst_string (buffer, sizeof (buffer), cases[i].str, cases[i].srch, cases[i].rplmt) == buffer);
+ EXPECT_EQ_STR(cases[i].want, buffer);
+ }
+
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(subst);
+ RUN_TEST(subst_string);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
index 6603c15e89f161afc832a5e2cd8ef08b335564ea..56c250cdbb6479b2a1f07297dc2e5f9800243675 100644 (file)
--- a/src/daemon/utils_time.c
+++ b/src/daemon/utils_time.c
/**
* collectd - src/utils_time.c
- * Copyright (C) 2010 Florian octo Forster
+ * Copyright (C) 2010-2015 Florian octo Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* DEALINGS IN THE SOFTWARE.
*
* Authors:
- * Florian octo Forster <ff at octo.it>
+ * Florian octo Forster <octo at collectd.org>
**/
#include "collectd.h"
#include "plugin.h"
#include "common.h"
-#if HAVE_CLOCK_GETTIME
+#ifndef DEFAULT_MOCK_TIME
+# define DEFAULT_MOCK_TIME 1542455354518929408ULL
+#endif
+
+#ifdef MOCK_TIME
+cdtime_t cdtime_mock = (cdtime_t) MOCK_TIME;
+
+cdtime_t cdtime (void)
+{
+ return cdtime_mock;
+}
+#else /* !MOCK_TIME */
+# if HAVE_CLOCK_GETTIME
cdtime_t cdtime (void) /* {{{ */
{
int status;
return (TIMESPEC_TO_CDTIME_T (&ts));
} /* }}} cdtime_t cdtime */
-#else
+# else /* !HAVE_CLOCK_GETTIME */
/* Work around for Mac OS X which doesn't have clock_gettime(2). *sigh* */
cdtime_t cdtime (void) /* {{{ */
{
return (TIMEVAL_TO_CDTIME_T (&tv));
} /* }}} cdtime_t cdtime */
+# endif
#endif
-size_t cdtime_to_iso8601 (char *s, size_t max, cdtime_t t) /* {{{ */
+/* format_zone reads time zone information from "extern long timezone", exported
+ * by <time.h>, and formats it according to RFC 3339. This differs from
+ * strftime()'s "%z" format by including a colon between hour and minute. */
+static int format_zone (char *buffer, size_t buffer_size, struct tm const *tm) /* {{{ */
+{
+ char tmp[7];
+ size_t sz;
+
+ if ((buffer == NULL) || (buffer_size < 7))
+ return EINVAL;
+
+ sz = strftime (tmp, sizeof (tmp), "%z", tm);
+ if (sz == 0)
+ return ENOMEM;
+ if (sz != 5)
+ {
+ DEBUG ("format_zone: strftime(\"%%z\") = \"%s\", want \"+hhmm\"", tmp);
+ sstrncpy (buffer, tmp, buffer_size);
+ return 0;
+ }
+
+ buffer[0] = tmp[0];
+ buffer[1] = tmp[1];
+ buffer[2] = tmp[2];
+ buffer[3] = ':';
+ buffer[4] = tmp[3];
+ buffer[5] = tmp[4];
+ buffer[6] = 0;
+
+ return 0;
+} /* }}} int format_zone */
+
+static int format_rfc3339 (char *buffer, size_t buffer_size, cdtime_t t, _Bool print_nano) /* {{{ */
{
struct timespec t_spec;
struct tm t_tm;
-
+ char base[20]; /* 2006-01-02T15:04:05 */
+ char nano[11]; /* .999999999 */
+ char zone[7]; /* +00:00 */
+ char *fields[] = {base, nano, zone};
size_t len;
+ int status;
CDTIME_T_TO_TIMESPEC (t, &t_spec);
NORMALIZE_TIMESPEC (t_spec);
- if (localtime_r ((time_t *)&t_spec.tv_sec, &t_tm) == NULL) {
+ if (localtime_r (&t_spec.tv_sec, &t_tm) == NULL) {
char errbuf[1024];
- ERROR ("cdtime_to_iso8601: localtime_r failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (0);
+ status = errno;
+ ERROR ("format_rfc3339: localtime_r failed: %s",
+ sstrerror (status, errbuf, sizeof (errbuf)));
+ return (status);
}
- len = strftime (s, max, "%Y-%m-%dT%H:%M:%S", &t_tm);
+ len = strftime (base, sizeof (base), "%Y-%m-%dT%H:%M:%S", &t_tm);
if (len == 0)
- return 0;
+ return ENOMEM;
- if (max - len > 2) {
- int n = snprintf (s + len, max - len, ".%09i", (int)t_spec.tv_nsec);
- len += (n < max - len) ? n : max - len;
- }
+ if (print_nano)
+ ssnprintf (nano, sizeof (nano), ".%09ld", (long) t_spec.tv_nsec);
+ else
+ sstrncpy (nano, "", sizeof (nano));
- if (max - len > 3) {
- int n = strftime (s + len, max - len, "%z", &t_tm);
- len += (n < max - len) ? n : max - len;
- }
+ status = format_zone (zone, sizeof (zone), &t_tm);
+ if (status != 0)
+ return status;
+
+ if (strjoin (buffer, buffer_size, fields, STATIC_ARRAY_SIZE (fields), "") < 0)
+ return ENOMEM;
+ return 0;
+} /* }}} int format_rfc3339 */
+
+int rfc3339 (char *buffer, size_t buffer_size, cdtime_t t) /* {{{ */
+{
+ if (buffer_size < RFC3339_SIZE)
+ return ENOMEM;
+
+ return format_rfc3339 (buffer, buffer_size, t, 0);
+} /* }}} size_t cdtime_to_rfc3339 */
+
+int rfc3339nano (char *buffer, size_t buffer_size, cdtime_t t) /* {{{ */
+{
+ if (buffer_size < RFC3339NANO_SIZE)
+ return ENOMEM;
- s[max - 1] = '\0';
- return len;
-} /* }}} size_t cdtime_to_iso8601 */
+ return format_rfc3339 (buffer, buffer_size, t, 1);
+} /* }}} size_t cdtime_to_rfc3339nano */
/* vim: set sw=2 sts=2 et fdm=marker : */
index 9b08e8e4de68f011d24b4dc947c9d23922506544..46faa9ce44dbd89e8dcc85e7411fc259d6138c4d 100644 (file)
--- a/src/daemon/utils_time.h
+++ b/src/daemon/utils_time.h
/**
- * collectd - src/utils_time.h
- * Copyright (C) 2010 Florian octo Forster
+ * collectd - src/daemon/utils_time.h
+ * Copyright (C) 2010-2015 Florian octo Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* DEALINGS IN THE SOFTWARE.
*
* Authors:
- * Florian octo Forster <ff at octo.it>
+ * Florian octo Forster <octo at collectd.org>
**/
#ifndef UTILS_TIME_H
#include "collectd.h"
+#ifdef TESTING_H
+/* cdtime_mock is the time returned by cdtime() when build with
+ * -DMOCK_TIME */
+extern cdtime_t cdtime_mock;
+#endif
+
/*
* "cdtime_t" is a 64bit unsigned integer. The time is stored at a 2^-30 second
* resolution, i.e. the most significant 34 bit are used to store the time in
/* typedef uint64_t cdtime_t; */
/* 2^30 = 1073741824 */
-#define TIME_T_TO_CDTIME_T(t) (((cdtime_t) (t)) * 1073741824)
-#define CDTIME_T_TO_TIME_T(t) ((time_t) ((t) / 1073741824))
+#define TIME_T_TO_CDTIME_T(t) (((cdtime_t) (t)) << 30)
+
+#define MS_TO_CDTIME_T(ms) (((((cdtime_t) (ms)) / 1000) << 30) | \
+ ((((((cdtime_t) (ms)) % 1000) << 30) + 500) / 1000))
+#define US_TO_CDTIME_T(us) (((((cdtime_t) (us)) / 1000000) << 30) | \
+ ((((((cdtime_t) (us)) % 1000000) << 30) + 500000) / 1000000))
+#define NS_TO_CDTIME_T(ns) (((((cdtime_t) (ns)) / 1000000000) << 30) | \
+ ((((((cdtime_t) (ns)) % 1000000000) << 30) + 500000000) / 1000000000))
+
+#define CDTIME_T_TO_TIME_T(t) ((time_t) (((t) + (1 << 29)) >> 30))
+#define CDTIME_T_TO_MS(t) ((uint64_t) ((((t) >> 30) * 1000) + \
+ ((((t) & 0x3fffffff) * 1000 + (1 << 29)) >> 30)))
+#define CDTIME_T_TO_US(t) ((uint64_t) ((((t) >> 30) * 1000000) + \
+ ((((t) & 0x3fffffff) * 1000000 + (1 << 29)) >> 30)))
+#define CDTIME_T_TO_NS(t) ((uint64_t) ((((t) >> 30) * 1000000000) + \
+ ((((t) & 0x3fffffff) * 1000000000 + (1 << 29)) >> 30)))
#define CDTIME_T_TO_DOUBLE(t) (((double) (t)) / 1073741824.0)
#define DOUBLE_TO_CDTIME_T(d) ((cdtime_t) ((d) * 1073741824.0))
-#define MS_TO_CDTIME_T(ms) ((cdtime_t) (((double) (ms)) * 1073741.824))
-#define CDTIME_T_TO_MS(t) ((long) (((double) (t)) / 1073741.824))
-#define US_TO_CDTIME_T(us) ((cdtime_t) (((double) (us)) * 1073.741824))
-#define CDTIME_T_TO_US(t) ((suseconds_t) (((double) (t)) / 1073.741824))
-#define NS_TO_CDTIME_T(ns) ((cdtime_t) (((double) (ns)) * 1.073741824))
-#define CDTIME_T_TO_NS(t) ((long) (((double) (t)) / 1.073741824))
-
-#define CDTIME_T_TO_TIMEVAL(cdt,tvp) do { \
- (tvp)->tv_sec = CDTIME_T_TO_TIME_T (cdt); \
- (tvp)->tv_usec = CDTIME_T_TO_US ((cdt) % 1073741824); \
+#define CDTIME_T_TO_TIMEVAL(cdt,tvp) do { \
+ (tvp)->tv_sec = (time_t) ((cdt) >> 30); \
+ (tvp)->tv_usec = (suseconds_t) ((((cdt) & 0x3fffffff) * 1000000 + (1 << 29)) >> 30); \
} while (0)
-#define TIMEVAL_TO_CDTIME_T(tv) (TIME_T_TO_CDTIME_T ((tv)->tv_sec) \
- + US_TO_CDTIME_T ((tv)->tv_usec))
+#define TIMEVAL_TO_CDTIME_T(tv) US_TO_CDTIME_T(1000000 * (tv)->tv_sec + (tv)->tv_usec)
-#define CDTIME_T_TO_TIMESPEC(cdt,tsp) do { \
- (tsp)->tv_sec = CDTIME_T_TO_TIME_T (cdt); \
- (tsp)->tv_nsec = CDTIME_T_TO_NS ((cdt) % 1073741824); \
+#define CDTIME_T_TO_TIMESPEC(cdt,tsp) do { \
+ (tsp)->tv_sec = (time_t) ((cdt) >> 30); \
+ (tsp)->tv_nsec = (long) ((((cdt) & 0x3fffffff) * 1000000000 + (1 << 29)) >> 30); \
} while (0)
-#define TIMESPEC_TO_CDTIME_T(ts) (TIME_T_TO_CDTIME_T ((ts)->tv_sec) \
- + NS_TO_CDTIME_T ((ts)->tv_nsec))
+#define TIMESPEC_TO_CDTIME_T(ts) NS_TO_CDTIME_T(1000000000ULL * (ts)->tv_sec + (ts)->tv_nsec)
cdtime_t cdtime (void);
-/* format a cdtime_t value in ISO 8601 format:
- * returns the number of characters written to the string (not including the
- * terminating null byte or 0 on error; the function ensures that the string
- * is null terminated */
-size_t cdtime_to_iso8601 (char *s, size_t max, cdtime_t t);
+#define RFC3339_SIZE 26
+#define RFC3339NANO_SIZE 36
+
+/* rfc3339 formats a cdtime_t time in RFC 3339 format with second precision. */
+int rfc3339 (char *buffer, size_t buffer_size, cdtime_t t);
+
+/* rfc3339nano formats a cdtime_t time in RFC 3339 format with nanosecond
+ * precision. */
+int rfc3339nano (char *buffer, size_t buffer_size, cdtime_t t);
#endif /* UTILS_TIME_H */
/* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/utils_time_mock.c b/src/daemon/utils_time_mock.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * collectd - src/tests/mock/utils_time.c
- * Copyright (C) 2013 Florian octo Forster
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Florian octo Forster <octo at collectd.org>
- */
-
-#include "utils_time.h"
-
-cdtime_t cdtime (void)
-{
- return (0);
-}
-
diff --git a/src/daemon/utils_time_test.c b/src/daemon/utils_time_test.c
--- /dev/null
@@ -0,0 +1,127 @@
+/**
+ * collectd - src/daemon/utils_time_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#define DBL_PRECISION 1e-3
+
+#include "collectd.h"
+#include "testing.h"
+#include "utils_time.h"
+
+DEF_TEST(conversion)
+{
+ struct {
+ cdtime_t t;
+ double d;
+ time_t tt;
+ uint64_t ms;
+ struct timeval tv;
+ struct timespec ts;
+ } cases[] = {
+ /* cdtime double time_t milliseconds timeval timespec */
+ { 0, 0.0 , 0, 0, { 0, 0}, { 0, 0}},
+ { 10737418240ULL, 10.0 , 10, 10000, { 10, 0}, { 10, 0}},
+ {1542908534771941376ULL, 1436945549.0 , 1436945549, 1436945549000ULL, {1436945549, 0}, {1436945549, 0}},
+ {1542908535540740522ULL, 1436945549.716, 1436945550, 1436945549716ULL, {1436945549, 716000}, {1436945549, 716000000}},
+ // 1426076671.123 * 2^30 = 1531238166015458148.352
+ {1531238166015458148ULL, 1426076671.123, 1426076671, 1426076671123ULL, {1426076671, 123000}, {1426076671, 123000000}},
+ // 1426076681.234 * 2^30 = 1531238176872061730.816
+ {1531238176872061731ULL, 1426076681.234, 1426076681, 1426076681234ULL, {1426076681, 234000}, {1426076681, 234000000}},
+ // 1426083986.314 * 2^30 = 1531246020641985396.736
+ {1531246020641985397ULL, 1426083986.314, 1426083986, 1426083986314ULL, {1426083986, 314000}, {1426083986, 314000000}},
+ // 1426083986.494142531 * 2^30 = 1531246020835411966.5
+ {1531246020835411967ULL, 1426083986.494, 1426083986, 1426083986494ULL, {1426083986, 494143}, {1426083986, 494142531}},
+ // 1426083986.987410814 * 2^30 = 1531246021365054752.4
+ {1531246021365054752ULL, 1426083986.987, 1426083987, 1426083986987ULL, {1426083986, 987411}, {1426083986, 987410814}},
+
+ /* These cases test the cdtime_t -> ns conversion rounds correctly. */
+ // 1546167635576736987 / 2^30 = 1439980823.1524536265...
+ {1546167635576736987ULL, 1439980823.152, 1439980823, 1439980823152ULL, {1439980823, 152454}, {1439980823, 152453627}},
+ // 1546167831554815222 / 2^30 = 1439981005.6712620165...
+ {1546167831554815222ULL, 1439981005.671, 1439981006, 1439981005671ULL, {1439981005, 671262}, {1439981005, 671262017}},
+ // 1546167986577716567 / 2^30 = 1439981150.0475896215...
+ {1546167986577716567ULL, 1439981150.048, 1439981150, 1439981150048ULL, {1439981150, 47590}, {1439981150, 47589622}},
+ };
+ size_t i;
+
+ for (i = 0; i < (sizeof (cases) / sizeof (cases[0])); i++) {
+ struct timeval tv;
+ struct timespec ts;
+
+ // cdtime -> s
+ EXPECT_EQ_UINT64 (cases[i].tt, CDTIME_T_TO_TIME_T (cases[i].t));
+
+ // cdtime -> ms
+ EXPECT_EQ_UINT64(cases[i].ms, CDTIME_T_TO_MS (cases[i].t));
+
+ // cdtime -> us
+ CDTIME_T_TO_TIMEVAL (cases[i].t, &tv);
+ EXPECT_EQ_UINT64 (cases[i].tv.tv_sec, tv.tv_sec);
+ EXPECT_EQ_UINT64 (cases[i].tv.tv_usec, tv.tv_usec);
+
+ // cdtime -> ns
+ CDTIME_T_TO_TIMESPEC (cases[i].t, &ts);
+ EXPECT_EQ_UINT64 (cases[i].ts.tv_sec, ts.tv_sec);
+ EXPECT_EQ_UINT64 (cases[i].ts.tv_nsec, ts.tv_nsec);
+
+ // cdtime -> double
+ EXPECT_EQ_DOUBLE (cases[i].d, CDTIME_T_TO_DOUBLE (cases[i].t));
+ }
+
+ return 0;
+}
+
+/* These cases test the ns -> cdtime_t conversion rounds correctly. */
+DEF_TEST(ns_to_cdtime)
+{
+ struct {
+ uint64_t ns;
+ cdtime_t want;
+ } cases[] = {
+ // 1439981652801860766 * 2^30 / 10^9 = 1546168526406004689.4
+ {1439981652801860766ULL, 1546168526406004689ULL},
+ // 1439981836985281914 * 2^30 / 10^9 = 1546168724171447263.4
+ {1439981836985281914ULL, 1546168724171447263ULL},
+ // 1439981880053705608 * 2^30 / 10^9 = 1546168770415815077.4
+ {1439981880053705608ULL, 1546168770415815077ULL},
+ };
+ size_t i;
+
+ for (i = 0; i < (sizeof (cases) / sizeof (cases[0])); i++) {
+ EXPECT_EQ_UINT64 (cases[i].want, NS_TO_CDTIME_T (cases[i].ns));
+ }
+
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(conversion);
+ RUN_TEST(ns_to_cdtime);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/dbi.c b/src/dbi.c
index a7963ea223371f5d70a4ef63f2d0a3a6263db22a..94d0762d261fada2a4ebda04278f43947dc0b006 100644 (file)
--- a/src/dbi.c
+++ b/src/dbi.c
char *name;
char *select_db;
+ cdtime_t interval;
+
char *driver;
char *host;
cdbi_driver_option_t *driver_options;
*
* <Database "plugin_instance1">
* Driver "mysql"
+ * Interval 120
* DriverOption "hostname" "localhost"
* ...
* Query "plugin_instance0"
&db->queries, &db->queries_num);
else if (strcasecmp ("Host", child->key) == 0)
status = cf_util_get_string (child, &db->host);
+ else if (strcasecmp ("Interval", child->key) == 0)
+ status = cf_util_get_cdtime(child, &db->interval);
else
{
WARNING ("dbi plugin: Option `%s' not allowed here.", child->key);
while ((status == 0) && (db->queries_num > 0))
{
+ size_t j;
db->q_prep_areas = (udb_query_preparation_area_t **) calloc (
db->queries_num, sizeof (*db->q_prep_areas));
break;
}
- for (i = 0; i < db->queries_num; ++i)
+ for (j = 0; j < db->queries_num; ++j)
{
- db->q_prep_areas[i]
- = udb_query_allocate_preparation_area (db->queries[i]);
+ db->q_prep_areas[j]
+ = udb_query_allocate_preparation_area (db->queries[j]);
- if (db->q_prep_areas[i] == NULL)
+ if (db->q_prep_areas[j] == NULL)
{
WARNING ("dbi plugin: udb_query_allocate_preparation_area failed");
status = -1;
plugin_register_complex_read (/* group = */ NULL,
/* name = */ name ? name : db->name,
/* callback = */ cdbi_read_database,
- /* interval = */ NULL,
+ /* interval = */ (db->interval > 0) ? db->interval : 0,
/* user_data = */ &ud);
free (name);
}
udb_query_prepare_result (q, prep_area, (db->host ? db->host : hostname_g),
/* plugin = */ "dbi", db->name,
- column_names, column_num, /* interval = */ 0);
+ column_names, column_num, /* interval = */ (db->interval > 0) ? db->interval : 0);
/* 0 = error; 1 = success; */
status = dbi_result_first_row (res); /* {{{ */
diff --git a/src/disk.c b/src/disk.c
index 1c3dd98d7d2a93318e8ce0318fbd8acbbd15e016..b60fefa03bd1186aede7264bbc2d6e640ecd38e0 100644 (file)
--- a/src/disk.c
+++ b/src/disk.c
#if HAVE_IOKIT_IOBSD_H
# include <IOKit/IOBSD.h>
#endif
+#if KERNEL_FREEBSD
+#include <devstat.h>
+#include <libgeom.h>
+#endif
#if HAVE_LIMITS_H
# include <limits.h>
static diskstats_t *disklist;
/* #endif KERNEL_LINUX */
+#elif KERNEL_FREEBSD
+static struct gmesh geom_tree;
+/* #endif KERNEL_FREEBSD */
#elif HAVE_LIBKSTAT
#define MAX_NUMDISK 1024
/* do nothing */
/* #endif KERNEL_LINUX */
+#elif KERNEL_FREEBSD
+ int rv;
+
+ rv = geom_gettree(&geom_tree);
+ if (rv != 0) {
+ ERROR ("geom_gettree() failed, returned %d", rv);
+ return (-1);
+ }
+ rv = geom_stats_open();
+ if (rv != 0) {
+ ERROR ("geom_stats_open() failed, returned %d", rv);
+ return (-1);
+ }
+/* #endif KERNEL_FREEBSD */
+
#elif HAVE_LIBKSTAT
kstat_t *ksp_chain;
IOObjectRelease (disk_list);
/* #endif HAVE_IOKIT_IOKITLIB_H */
+#elif KERNEL_FREEBSD
+ int retry, dirty;
+
+ void *snap = NULL;
+ struct devstat *snap_iter;
+
+ struct gident *geom_id;
+
+ const char *disk_name;
+ long double read_time, write_time;
+
+ for (retry = 0, dirty = 1; retry < 5 && dirty == 1; retry++) {
+ if (snap != NULL)
+ geom_stats_snapshot_free(snap);
+
+ /* Get a fresh copy of stats snapshot */
+ snap = geom_stats_snapshot_get();
+ if (snap == NULL) {
+ ERROR("disk plugin: geom_stats_snapshot_get() failed.");
+ return (-1);
+ }
+
+ /* Check if we have dirty read from this snapshot */
+ dirty = 0;
+ geom_stats_snapshot_reset(snap);
+ while ((snap_iter = geom_stats_snapshot_next(snap)) != NULL) {
+ if (snap_iter->id == NULL)
+ continue;
+ geom_id = geom_lookupid(&geom_tree, snap_iter->id);
+
+ /* New device? refresh GEOM tree */
+ if (geom_id == NULL) {
+ geom_deletetree(&geom_tree);
+ if (geom_gettree(&geom_tree) != 0) {
+ ERROR("disk plugin: geom_gettree() failed");
+ geom_stats_snapshot_free(snap);
+ return (-1);
+ }
+ geom_id = geom_lookupid(&geom_tree, snap_iter->id);
+ }
+ /*
+ * This should be rare: the device come right before we take the
+ * snapshot and went away right after it. We will handle this
+ * case later, so don't mark dirty but silently ignore it.
+ */
+ if (geom_id == NULL)
+ continue;
+
+ /* Only collect PROVIDER data */
+ if (geom_id->lg_what != ISPROVIDER)
+ continue;
+
+ /* Only collect data when rank is 1 (physical devices) */
+ if (((struct gprovider *)(geom_id->lg_ptr))->lg_geom->lg_rank != 1)
+ continue;
+
+ /* Check if this is a dirty read quit for another try */
+ if (snap_iter->sequence0 != snap_iter->sequence1) {
+ dirty = 1;
+ break;
+ }
+ }
+ }
+
+ /* Reset iterator */
+ geom_stats_snapshot_reset(snap);
+ for (;;) {
+ snap_iter = geom_stats_snapshot_next(snap);
+ if (snap_iter == NULL)
+ break;
+
+ if (snap_iter->id == NULL)
+ continue;
+ geom_id = geom_lookupid(&geom_tree, snap_iter->id);
+ if (geom_id == NULL)
+ continue;
+ if (geom_id->lg_what != ISPROVIDER)
+ continue;
+ if (((struct gprovider *)(geom_id->lg_ptr))->lg_geom->lg_rank != 1)
+ continue;
+ /* Skip dirty reads, if present */
+ if (dirty && (snap_iter->sequence0 != snap_iter->sequence1))
+ continue;
+
+ disk_name = ((struct gprovider *)geom_id->lg_ptr)->lg_name;
+
+ if ((snap_iter->bytes[DEVSTAT_READ] != 0) || (snap_iter->bytes[DEVSTAT_WRITE] != 0)) {
+ disk_submit(disk_name, "disk_octets",
+ (derive_t)snap_iter->bytes[DEVSTAT_READ],
+ (derive_t)snap_iter->bytes[DEVSTAT_WRITE]);
+ }
+
+ if ((snap_iter->operations[DEVSTAT_READ] != 0) || (snap_iter->operations[DEVSTAT_WRITE] != 0)) {
+ disk_submit(disk_name, "disk_ops",
+ (derive_t)snap_iter->operations[DEVSTAT_READ],
+ (derive_t)snap_iter->operations[DEVSTAT_WRITE]);
+ }
+
+ read_time = devstat_compute_etime(&snap_iter->duration[DEVSTAT_READ], NULL);
+ write_time = devstat_compute_etime(&snap_iter->duration[DEVSTAT_WRITE], NULL);
+ if ((read_time != 0) || (write_time != 0)) {
+ disk_submit (disk_name, "disk_time",
+ (derive_t)(read_time*1000), (derive_t)(write_time*1000));
+ }
+ }
+ geom_stats_snapshot_free(snap);
+
#elif KERNEL_LINUX
FILE *fh;
char buffer[1024];
{
char *disk_name;
char *output_name;
- char *alt_name;
numfields = strsplit (buffer, fields, 32);
output_name = disk_name;
#if HAVE_LIBUDEV
- alt_name = disk_udev_attr_name (handle_udev, disk_name,
- conf_udev_name_attr);
-#else
- alt_name = NULL;
-#endif
+ char *alt_name = disk_udev_attr_name (handle_udev, disk_name, conf_udev_name_attr);
if (alt_name != NULL)
output_name = alt_name;
+#endif
if ((ds->read_bytes != 0) || (ds->write_bytes != 0))
disk_submit (output_name, "disk_octets",
submit_io_time (output_name, io_time, weighted_time);
} /* if (is_disk) */
+#if HAVE_LIBUDEV
/* release udev-based alternate name, if allocated */
- free(alt_name);
+ sfree (alt_name);
+#endif
} /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
#if HAVE_LIBUDEV
diff --git a/src/email.c b/src/email.c
index 6a0c0a45718e7b167a5e179f028b40a6eb1cce06..81ae29c3035269513105e87a1193bdc205b9808a 100644 (file)
--- a/src/email.c
+++ b/src/email.c
# include <pthread.h>
#endif
-#include <sys/socket.h>
#include <sys/un.h>
#include <sys/select.h>
{
struct sockaddr_un addr;
- char *path = (NULL == sock_file) ? SOCK_PATH : sock_file;
- char *group = (NULL == sock_group) ? COLLECTD_GRP_NAME : sock_group;
+ const char *path = (NULL == sock_file) ? SOCK_PATH : sock_file;
+ const char *group = (NULL == sock_group) ? COLLECTD_GRP_NAME : sock_group;
/* create UNIX socket */
errno = 0;
diff --git a/src/gmond.c b/src/gmond.c
index 2ac9f2501c390e09b3a0f9783fb3078ec0c2fae4..f86d8f7add6df91563d6c8cb1f0d692c9ef7e803 100644 (file)
--- a/src/gmond.c
+++ b/src/gmond.c
#if HAVE_PTHREAD_H
# include <pthread.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NETDB_H
# include <netdb.h>
#endif
struct metric_map_s
{
- char *ganglia_name;
- char *type;
- char *type_instance;
- char *ds_name;
- int ds_type;
- int ds_index;
+ char *ganglia_name;
+ char *type;
+ char *type_instance;
+ char *ds_name;
+ int ds_type;
+ size_t ds_index;
};
typedef struct metric_map_s metric_map_t;
return (NULL);
/* Look up the DS type and ds_index. */
- if ((map[i].ds_type < 0) || (map[i].ds_index < 0)) /* {{{ */
+ if (map[i].ds_type < 0) /* {{{ */
{
const data_set_t *ds;
}
else
{
- int j;
+ size_t j;
for (j = 0; j < ds->ds_num; j++)
if (strcasecmp (ds->ds[j].name, map[i].ds_name) == 0)
static int staging_entry_update (const char *host, const char *name, /* {{{ */
const char *type, const char *type_instance,
- int ds_index, int ds_type, value_t value)
+ size_t ds_index, int ds_type, value_t value)
{
const data_set_t *ds;
staging_entry_t *se;
if (ds->ds_num <= ds_index)
{
- ERROR ("gmond plugin: Invalid index %i: %s has only %i data source(s).",
+ ERROR ("gmond plugin: Invalid index %zu: %s has only %zu data source(s).",
ds_index, ds->type, ds->ds_num);
return (-1);
}
diff --git a/src/hddtemp.c b/src/hddtemp.c
index 82c158cab17180dc18a4d5e878d1704b60e081ce..3de18fd91354d166a58beff919d4b38e65e0fe33 100644 (file)
--- a/src/hddtemp.c
+++ b/src/hddtemp.c
#include "configfile.h"
# include <netdb.h>
-# include <sys/socket.h>
# include <netinet/in.h>
# include <netinet/tcp.h>
# include <libgen.h> /* for basename */
diff --git a/src/interface.c b/src/interface.c
index df8ffb46c34522ee5696b22a3409a687c37161e4..90dc139dccc0131ff7b83a8921b8333beb615c84 100644 (file)
--- a/src/interface.c
+++ b/src/interface.c
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
/* One cannot include both. This sucks. */
#if HAVE_LINUX_IF_H
extern kstat_ctl_t *kc;
static kstat_t *ksp[MAX_NUMIF];
static int numif = 0;
+static _Bool unique_name = 0;
#endif /* HAVE_LIBKSTAT */
static int interface_config (const char *key, const char *value)
invert = 0;
ignorelist_set_invert (ignorelist, invert);
}
+ else if (strcasecmp (key, "UniqueName") == 0)
+ {
+ #ifdef HAVE_LIBKSTAT
+ if (IS_TRUE (value))
+ unique_name = 1;
+ #else
+ WARNING ("interface plugin: the \"UniqueName\" option is only valid on Solaris.");
+ #endif /* HAVE_LIBKSTAT */
+ }
else
{
return (-1);
struct ifaddrs *if_list;
struct ifaddrs *if_ptr;
-/* Darin/Mac OS X and possible other *BSDs */
+/* Darwin/Mac OS X and possible other *BSDs */
#if HAVE_STRUCT_IF_DATA
# define IFA_DATA if_data
# define IFA_RX_BYTES ifi_ibytes
incoming = atoll (fields[2]);
outgoing = atoll (fields[10]);
if_submit (device, "if_errors", incoming, outgoing);
+
+ incoming = atoll (fields[3]);
+ outgoing = atoll (fields[11]);
+ if_submit (device, "if_dropped", incoming, outgoing);
}
fclose (fh);
int i;
derive_t rx;
derive_t tx;
+ char iname[DATA_MAX_NAME_LEN];
if (kc == NULL)
return (-1);
if (kstat_read (kc, ksp[i], NULL) == -1)
continue;
+ if (unique_name)
+ ssnprintf(iname, sizeof(iname), "%s_%d_%s", ksp[i]->ks_module, ksp[i]->ks_instance, ksp[i]->ks_name);
+ else
+ sstrncpy(iname, ksp[i]->ks_name, sizeof(iname));
+
/* try to get 64bit counters */
rx = get_kstat_value (ksp[i], "rbytes64");
tx = get_kstat_value (ksp[i], "obytes64");
if (tx == -1LL)
tx = get_kstat_value (ksp[i], "obytes");
if ((rx != -1LL) || (tx != -1LL))
- if_submit (ksp[i]->ks_name, "if_octets", rx, tx);
+ if_submit (iname, "if_octets", rx, tx);
/* try to get 64bit counters */
rx = get_kstat_value (ksp[i], "ipackets64");
if (tx == -1LL)
tx = get_kstat_value (ksp[i], "opackets");
if ((rx != -1LL) || (tx != -1LL))
- if_submit (ksp[i]->ks_name, "if_packets", rx, tx);
+ if_submit (iname, "if_packets", rx, tx);
/* no 64bit error counters yet */
rx = get_kstat_value (ksp[i], "ierrors");
tx = get_kstat_value (ksp[i], "oerrors");
if ((rx != -1LL) || (tx != -1LL))
- if_submit (ksp[i]->ks_name, "if_errors", rx, tx);
+ if_submit (iname, "if_errors", rx, tx);
}
/* #endif HAVE_LIBKSTAT */
diff --git a/src/ipc.c b/src/ipc.c
index b4038472efb76e4ff48df62e95b91307a8ff2dfc..645d4b087e735ce06d8db51fd8fa731e6345bac4 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
msg_alloc_queues++;
msg_used_space += ipcinfo_msg[i].msg_cbytes;
msg_qnum += ipcinfo_msg[i].msg_qnum;
-
+ }
free(ipcinfo_msg);
ipc_submit_g("msg", "count", "queues", msg_alloc_queues);
diff --git a/src/iptables.c b/src/iptables.c
index 590b693110a637dd36e4529b2cb4a854ca51c27b..05e3e24b92b9716612b13748d8027521c289bd54 100644 (file)
--- a/src/iptables.c
+++ b/src/iptables.c
#include "plugin.h"
#include "configfile.h"
-#include <sys/socket.h>
-
#include <libiptc/libiptc.h>
#include <libiptc/libip6tc.h>
*/
static const char *config_keys[] =
{
- "Chain",
- "Chain6"
+ "Chain",
+ "Chain6"
};
static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
-/*
- Each table/chain combo that will be queried goes into this list
-*/
-
enum protocol_version_e
{
IPV4,
};
typedef enum protocol_version_e protocol_version_t;
+/*
+ * Each table/chain combo that will be queried goes into this list
+ */
#ifndef XT_TABLE_MAXNAMELEN
# define XT_TABLE_MAXNAMELEN 32
#endif
char chain[XT_TABLE_MAXNAMELEN];
union
{
- int num;
- char *comment;
+ int num;
+ char *comment;
} rule;
enum
{
- RTYPE_NUM,
- RTYPE_COMMENT,
- RTYPE_COMMENT_ALL
+ RTYPE_NUM,
+ RTYPE_COMMENT,
+ RTYPE_COMMENT_ALL
} rule_type;
char name[64];
} ip_chain_t;
static int iptables_config (const char *key, const char *value)
{
- /* int ip_value; */
- protocol_version_t ip_version = 0;
-
- if (strcasecmp (key, "Chain") == 0)
- ip_version = IPV4;
- else if (strcasecmp (key, "Chain6") == 0)
- ip_version = IPV6;
- else
- return (1);
-
- ip_chain_t temp, *final, **list;
- char *table;
- int table_len;
- char *chain;
- int chain_len;
-
- char *value_copy;
- char *fields[4];
- int fields_num;
-
- memset (&temp, 0, sizeof (temp));
-
- value_copy = strdup (value);
- if (value_copy == NULL)
- {
- char errbuf[1024];
- ERROR ("strdup failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (1);
- }
-
- /*
- * Time to fill the temp element
- * Examine value string, it should look like:
- * Chain[6] <table> <chain> [<comment|num> [name]]
- */
-
- /* set IPv4 or IPv6 */
- temp.ip_version = ip_version;
-
- /* Chain <table> <chain> [<comment|num> [name]] */
- fields_num = strsplit (value_copy, fields, 4);
- if (fields_num < 2)
- {
- free (value_copy);
- return (1);
- }
-
- table = fields[0];
- chain = fields[1];
-
- table_len = strlen (table) + 1;
- if ((unsigned int)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))
- {
- ERROR ("Chain `%s' too long.", chain);
- free (value_copy);
- return (1);
- }
- sstrncpy (temp.chain, chain, chain_len);
-
- if (fields_num >= 3)
- {
- char *comment = fields[2];
- int rule = atoi (comment);
-
- if (rule)
- {
- temp.rule.num = rule;
- temp.rule_type = RTYPE_NUM;
- }
- else
- {
- temp.rule.comment = strdup (comment);
- if (temp.rule.comment == NULL)
- {
- free (value_copy);
- return (1);
- }
- temp.rule_type = RTYPE_COMMENT;
- }
- }
- else
- {
- temp.rule_type = RTYPE_COMMENT_ALL;
- }
-
- if (fields_num >= 4)
- sstrncpy (temp.name, fields[3], sizeof (temp.name));
-
- free (value_copy);
- value_copy = NULL;
- table = NULL;
- chain = NULL;
-
- list = (ip_chain_t **) realloc (chain_list, (chain_num + 1) * sizeof (ip_chain_t *));
- if (list == NULL)
- {
- char errbuf[1024];
- ERROR ("realloc failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- sfree (temp.rule.comment);
- return (1);
- }
-
- chain_list = list;
- final = (ip_chain_t *) malloc( sizeof(temp) );
- if (final == NULL)
- {
- char errbuf[1024];
- ERROR ("malloc failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- sfree (temp.rule.comment);
- return (1);
- }
- memcpy (final, &temp, sizeof (temp));
- chain_list[chain_num] = final;
- chain_num++;
-
- DEBUG ("Chain #%i: table = %s; chain = %s;", chain_num, final->table, final->chain);
-
- return (0);
+ /* int ip_value; */
+ protocol_version_t ip_version = 0;
+
+ if (strcasecmp (key, "Chain") == 0)
+ ip_version = IPV4;
+ else if (strcasecmp (key, "Chain6") == 0)
+ ip_version = IPV6;
+ else
+ return (1);
+
+ ip_chain_t temp, *final, **list;
+ char *table;
+ int table_len;
+ char *chain;
+ int chain_len;
+
+ char *value_copy;
+ char *fields[4];
+ int fields_num;
+
+ memset (&temp, 0, sizeof (temp));
+
+ value_copy = strdup (value);
+ if (value_copy == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("strdup failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (1);
+ }
+
+ /*
+ * Time to fill the temp element
+ * Examine value string, it should look like:
+ * Chain[6] <table> <chain> [<comment|num> [name]]
+ */
+
+ /* set IPv4 or IPv6 */
+ temp.ip_version = ip_version;
+
+ /* Chain <table> <chain> [<comment|num> [name]] */
+ fields_num = strsplit (value_copy, fields, 4);
+ if (fields_num < 2)
+ {
+ free (value_copy);
+ return (1);
+ }
+
+ table = fields[0];
+ chain = fields[1];
+
+ table_len = strlen (table) + 1;
+ if ((unsigned int)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))
+ {
+ ERROR ("Chain `%s' too long.", chain);
+ free (value_copy);
+ return (1);
+ }
+ sstrncpy (temp.chain, chain, chain_len);
+
+ if (fields_num >= 3)
+ {
+ char *comment = fields[2];
+ int rule = atoi (comment);
+
+ if (rule)
+ {
+ temp.rule.num = rule;
+ temp.rule_type = RTYPE_NUM;
+ }
+ else
+ {
+ temp.rule.comment = strdup (comment);
+ if (temp.rule.comment == NULL)
+ {
+ free (value_copy);
+ return (1);
+ }
+ temp.rule_type = RTYPE_COMMENT;
+ }
+ }
+ else
+ {
+ temp.rule_type = RTYPE_COMMENT_ALL;
+ }
+
+ if (fields_num >= 4)
+ sstrncpy (temp.name, fields[3], sizeof (temp.name));
+
+ free (value_copy);
+ value_copy = NULL;
+ table = NULL;
+ chain = NULL;
+
+ list = (ip_chain_t **) realloc (chain_list, (chain_num + 1) * sizeof (ip_chain_t *));
+ if (list == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("realloc failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ sfree (temp.rule.comment);
+ return (1);
+ }
+
+ chain_list = list;
+ final = (ip_chain_t *) malloc( sizeof(temp) );
+ if (final == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("malloc failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ sfree (temp.rule.comment);
+ return (1);
+ }
+ memcpy (final, &temp, sizeof (temp));
+ chain_list[chain_num] = final;
+ chain_num++;
+
+ DEBUG ("Chain #%i: table = %s; chain = %s;", chain_num, final->table, final->chain);
+
+ return (0);
} /* int iptables_config */
static int submit6_match (const struct ip6t_entry_match *match,
- const struct ip6t_entry *entry,
- const ip_chain_t *chain,
- int rule_num)
+ const struct ip6t_entry *entry,
+ const ip_chain_t *chain,
+ int rule_num)
{
int status;
value_t values[1];
if (strcmp (match->u.user.name, "comment") != 0)
return (0);
if ((chain->rule_type == RTYPE_COMMENT)
- && (strcmp (chain->rule.comment, (char *) match->data) != 0))
+ && (strcmp (chain->rule.comment, (char *) match->data) != 0))
return (0);
}
sstrncpy (vl.plugin, "ip6tables", sizeof (vl.plugin));
status = ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
- "%s-%s", chain->table, chain->chain);
+ "%s-%s", chain->table, chain->chain);
if ((status < 1) || ((unsigned int)status >= sizeof (vl.plugin_instance)))
return (0);
{
if (chain->rule_type == RTYPE_NUM)
ssnprintf (vl.type_instance, sizeof (vl.type_instance),
- "%i", chain->rule.num);
+ "%i", chain->rule.num);
else
sstrncpy (vl.type_instance, (char *) match->data,
- sizeof (vl.type_instance));
+ sizeof (vl.type_instance));
}
sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
/* This needs to return `int' for IPT_MATCH_ITERATE to work. */
static int submit_match (const struct ipt_entry_match *match,
- const struct ipt_entry *entry,
- const ip_chain_t *chain,
- int rule_num)
+ const struct ipt_entry *entry,
+ const ip_chain_t *chain,
+ int rule_num)
{
int status;
value_t values[1];
/* Select the rules to collect */
if (chain->rule_type == RTYPE_NUM)
{
- if (chain->rule.num != rule_num)
- return (0);
+ if (chain->rule.num != rule_num)
+ return (0);
}
else
{
- if (strcmp (match->u.user.name, "comment") != 0)
- return (0);
- if ((chain->rule_type == RTYPE_COMMENT)
- && (strcmp (chain->rule.comment, (char *) match->data) != 0))
- return (0);
+ if (strcmp (match->u.user.name, "comment") != 0)
+ return (0);
+ if ((chain->rule_type == RTYPE_COMMENT)
+ && (strcmp (chain->rule.comment, (char *) match->data) != 0))
+ return (0);
}
vl.values = values;
sstrncpy (vl.plugin, "iptables", sizeof (vl.plugin));
status = ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
- "%s-%s", chain->table, chain->chain);
+ "%s-%s", chain->table, chain->chain);
if ((status < 1) || ((unsigned int)status >= sizeof (vl.plugin_instance)))
- return (0);
+ return (0);
if (chain->name[0] != '\0')
{
- sstrncpy (vl.type_instance, chain->name, sizeof (vl.type_instance));
+ sstrncpy (vl.type_instance, chain->name, sizeof (vl.type_instance));
}
else
{
- if (chain->rule_type == RTYPE_NUM)
- ssnprintf (vl.type_instance, sizeof (vl.type_instance),
- "%i", chain->rule.num);
- else
- sstrncpy (vl.type_instance, (char *) match->data,
- sizeof (vl.type_instance));
+ if (chain->rule_type == RTYPE_NUM)
+ ssnprintf (vl.type_instance, sizeof (vl.type_instance),
+ "%i", chain->rule.num);
+ else
+ sstrncpy (vl.type_instance, (char *) match->data,
+ sizeof (vl.type_instance));
}
sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
/* ipv6 submit_chain */
-static void submit6_chain( ip6tc_handle_t *handle, ip_chain_t *chain )
+static void submit6_chain (ip6tc_handle_t *handle, ip_chain_t *chain)
{
const struct ip6t_entry *entry;
int rule_num;
/* ipv4 submit_chain */
-static void submit_chain( iptc_handle_t *handle, ip_chain_t *chain )
+static void submit_chain (iptc_handle_t *handle, ip_chain_t *chain)
{
const struct ipt_entry *entry;
int rule_num;
- /* Find first rule for chain and use the iterate macro */
+ /* Find first rule for chain and use the iterate macro */
entry = iptc_first_rule( chain->chain, handle );
if (entry == NULL)
{
- DEBUG ("iptc_first_rule failed: %s", iptc_strerror (errno));
- return;
+ DEBUG ("iptc_first_rule failed: %s", iptc_strerror (errno));
+ return;
}
rule_num = 1;
while (entry)
{
- if (chain->rule_type == RTYPE_NUM)
- {
- submit_match (NULL, entry, chain, rule_num);
- }
- else
- {
- IPT_MATCH_ITERATE( entry, submit_match, entry, chain, rule_num );
- }
-
- entry = iptc_next_rule( entry, handle );
- rule_num++;
+ if (chain->rule_type == RTYPE_NUM)
+ {
+ submit_match (NULL, entry, chain, rule_num);
+ }
+ else
+ {
+ IPT_MATCH_ITERATE( entry, submit_match, entry, chain, rule_num );
+ }
+
+ entry = iptc_next_rule( entry, handle );
+ rule_num++;
} /* while (entry) */
}
int num_failures = 0;
ip_chain_t *chain;
- /* Init the iptc handle structure and query the correct table */
+ /* Init the iptc handle structure and query the correct table */
for (i = 0; i < chain_num; i++)
{
- chain = chain_list[i];
-
- if (!chain)
- {
- DEBUG ("iptables plugin: chain == NULL");
- continue;
- }
-
- if ( chain->ip_version == IPV4 )
+ chain = chain_list[i];
+
+ if (!chain)
+ {
+ DEBUG ("iptables plugin: chain == NULL");
+ continue;
+ }
+
+ if ( chain->ip_version == IPV4 )
{
#ifdef HAVE_IPTC_HANDLE_T
- iptc_handle_t _handle;
- iptc_handle_t *handle = &_handle;
+ iptc_handle_t _handle;
+ iptc_handle_t *handle = &_handle;
- *handle = iptc_init (chain->table);
+ *handle = iptc_init (chain->table);
#else
- iptc_handle_t *handle;
- handle = iptc_init (chain->table);
+ iptc_handle_t *handle;
+ handle = iptc_init (chain->table);
#endif
- if (!handle)
- {
- ERROR ("iptables plugin: iptc_init (%s) failed: %s",
- chain->table, iptc_strerror (errno));
- num_failures++;
- continue;
- }
+ if (!handle)
+ {
+ ERROR ("iptables plugin: iptc_init (%s) failed: %s",
+ chain->table, iptc_strerror (errno));
+ num_failures++;
+ continue;
+ }
- submit_chain (handle, chain);
- iptc_free (handle);
+ submit_chain (handle, chain);
+ iptc_free (handle);
}
else if ( chain->ip_version == IPV6 )
{
#ifdef HAVE_IP6TC_HANDLE_T
- ip6tc_handle_t _handle;
- ip6tc_handle_t *handle = &_handle;
+ ip6tc_handle_t _handle;
+ ip6tc_handle_t *handle = &_handle;
- *handle = ip6tc_init (chain->table);
+ *handle = ip6tc_init (chain->table);
#else
- ip6tc_handle_t *handle;
- handle = ip6tc_init (chain->table);
+ ip6tc_handle_t *handle;
+ handle = ip6tc_init (chain->table);
#endif
-
- if (!handle)
- {
- ERROR ("iptables plugin: ip6tc_init (%s) failed: %s",
- chain->table, ip6tc_strerror (errno));
- num_failures++;
- continue;
- }
-
- submit6_chain (handle, chain);
- ip6tc_free (handle);
+ if (!handle)
+ {
+ ERROR ("iptables plugin: ip6tc_init (%s) failed: %s",
+ chain->table, ip6tc_strerror (errno));
+ num_failures++;
+ continue;
+ }
+
+ submit6_chain (handle, chain);
+ ip6tc_free (handle);
}
- else num_failures++;
-
+ else
+ num_failures++;
} /* for (i = 0 .. chain_num) */
return ((num_failures < chain_num) ? 0 : -1);
for (i = 0; i < chain_num; i++)
{
- if ((chain_list[i] != NULL) && (chain_list[i]->rule_type == RTYPE_COMMENT))
- {
- sfree (chain_list[i]->rule.comment);
- }
- sfree (chain_list[i]);
+ if ((chain_list[i] != NULL) && (chain_list[i]->rule_type == RTYPE_COMMENT))
+ sfree (chain_list[i]->rule.comment);
+ sfree (chain_list[i]);
}
sfree (chain_list);
void module_register (void)
{
plugin_register_config ("iptables", iptables_config,
- config_keys, config_keys_num);
+ config_keys, config_keys_num);
plugin_register_read ("iptables", iptables_read);
plugin_register_shutdown ("iptables", iptables_shutdown);
} /* void module_register */
-/*
- * vim:shiftwidth=4:softtabstop=4:tabstop=8
- */
diff --git a/src/ipvs.c b/src/ipvs.c
index cbb554286bd08f292219ff91b8a81a601925638d..760aa3c5598af6a8a96785ec5a83137ae7e484e2 100644 (file)
--- a/src/ipvs.c
+++ b/src/ipvs.c
#if HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif /* HAVE_ARPA_INET_H */
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif /* HAVE_SYS_SOCKET_H */
#if HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
(se->protocol == IPPROTO_TCP) ? "TCP" : "UDP",
ntohs (se->port));
- if ((0 > len) || (size <= len)) {
+ if ((0 > len) || (size <= ((size_t) len))) {
log_err ("plugin instance truncated: %s", pi);
return -1;
}
len = ssnprintf (ti, size, "%s_%u", inet_ntoa (addr),
ntohs (de->port));
- if ((0 > len) || (size <= len)) {
+ if ((0 > len) || (size <= ((size_t) len))) {
log_err ("type instance truncated: %s", ti);
return -1;
}
return 0;
} /* get_ti */
-static void cipvs_submit_connections (char *pi, char *ti, derive_t value)
+static void cipvs_submit_connections (const char *pi, const char *ti,
+ derive_t value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
return;
} /* cipvs_submit_connections */
-static void cipvs_submit_if (char *pi, char *t, char *ti,
+static void cipvs_submit_if (const char *pi, const char *t, const char *ti,
derive_t rx, derive_t tx)
{
value_t values[2];
return;
} /* cipvs_submit_if */
-static void cipvs_submit_dest (char *pi, struct ip_vs_dest_entry *de) {
+static void cipvs_submit_dest (const char *pi, struct ip_vs_dest_entry *de)
+{
struct ip_vs_stats_user stats = de->stats;
char ti[DATA_MAX_NAME_LEN];
char pi[DATA_MAX_NAME_LEN];
- int i = 0;
+ size_t i;
if (0 != get_pi (se, pi, sizeof (pi)))
{
static int cipvs_read (void)
{
struct ip_vs_get_services *services = NULL;
- int i = 0;
+ size_t i;
if (sockfd < 0)
return (-1);
diff --git a/src/java.c b/src/java.c
index c74fe6c79de8fee4a3e80cd3a6fd7f15ea7dcb62..6b92f54e966f313e907514d17569aed104312f1c 100644 (file)
--- a/src/java.c
+++ b/src/java.c
jmethodID m_add;
jobject o_type;
jobject o_dataset;
- int i;
+ size_t i;
/* Look up the org/collectd/api/DataSet class */
c_dataset = (*jvm_env)->FindClass (jvm_env, "org/collectd/api/DataSet");
jmethodID m_valuelist_constructor;
jobject o_valuelist;
int status;
- int i;
+ size_t i;
/* First, create a new ValueList instance..
* Look up the class.. */
ud.free_func = cjni_callback_info_destroy;
plugin_register_complex_read (/* group = */ NULL, cbi->name, cjni_read,
- /* interval = */ NULL, &ud);
+ /* interval = */ 0, &ud);
(*jvm_env)->DeleteLocalRef (jvm_env, o_read);
index 5abee2f1a44f1fd0abdce185c1cb390ffd00aeab..e81a59438394960ab8cb6b4b0c0e40a30ca6befa 100644 (file)
AUTOMAKE_OPTIONS = foreign no-dependencies
-if COMPILER_IS_GCC
-AM_CFLAGS = -Wall -Werror
-endif
-
pkginclude_HEADERS = collectd/client.h collectd/network.h collectd/network_buffer.h collectd/lcc_features.h
lib_LTLIBRARIES = libcollectdclient.la
nodist_pkgconfig_DATA = libcollectdclient.pc
index 0f56bd239891fc3e35b4ddd76461074994356c22..77819c217b6e8ae1272415974f88480ab17710b0 100644 (file)
* beginning of the message. */
ptr = NULL;
errno = 0;
- res.status = strtol (buffer, &ptr, 0);
+ res.status = (int) strtol (buffer, &ptr, 0);
if ((errno != 0) || (ptr == &buffer[0]))
{
lcc_set_errno (c, errno);
index 420471df577eb28aece3cc3770fca73ffce2faec..7a866ee78c377408ff7187766eaf1061a9c2bdf5 100644 (file)
int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ */
{
- int if_index;
+ unsigned int if_index;
int status;
if ((srv == NULL) || (interface == NULL))
@@ -420,7 +420,7 @@ int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ *
memset (&mreq, 0, sizeof (mreq));
mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
mreq.imr_address.s_addr = ntohl (INADDR_ANY);
- mreq.imr_ifindex = if_index;
+ mreq.imr_ifindex = (int) if_index;
#else
struct ip_mreq mreq;
@@ -456,8 +456,8 @@ int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ *
/* else: Not a multicast interface. */
#if defined(SO_BINDTODEVICE)
- status = setsockopt (srv->fd, SOL_SOCKET, SO_BINDTODEVICE,
- interface, strlen (interface) + 1);
+ status = setsockopt (srv->fd, SOL_SOCKET, SO_BINDTODEVICE, interface,
+ (socklen_t) (strlen (interface) + 1));
if (status != 0)
return (-1);
#endif
index 5d2c5b2afa7a7907b6a2e3139fcf7357f563f0ae..89ccdecb9e6e935be7eb840b8ac4a135d687de28 100644 (file)
--- a/src/liboconfig/oconfig.c
+++ b/src/liboconfig/oconfig.c
if (NULL == c_file) {
status = snprintf (file, sizeof (file), "<fd#%d>", fileno (fh));
- if ((status < 0) || (status >= sizeof (file))) {
+ if ((status < 0) || (((size_t) status) >= sizeof (file))) {
c_file = "<unknown>";
}
else {
{
int i;
- ci_copy->values = (oconfig_value_t *) calloc (ci_orig->values_num,
- sizeof (*ci_copy->values));
+ ci_copy->values = (oconfig_value_t *) calloc ((size_t) ci_orig->values_num,
+ sizeof (*ci_copy->values));
if (ci_copy->values == NULL)
{
fprintf (stderr, "calloc failed.\n");
ci_copy->values[i].type = ci_orig->values[i].type;
if (ci_copy->values[i].type == OCONFIG_TYPE_STRING)
{
- ci_copy->values[i].value.string
- = strdup (ci_orig->values[i].value.string);
- if (ci_copy->values[i].value.string == NULL)
- {
- fprintf (stderr, "strdup failed.\n");
- oconfig_free (ci_copy);
- return (NULL);
- }
+ ci_copy->values[i].value.string = strdup (ci_orig->values[i].value.string);
+ if (ci_copy->values[i].value.string == NULL)
+ {
+ fprintf (stderr, "strdup failed.\n");
+ oconfig_free (ci_copy);
+ return (NULL);
+ }
}
else /* ci_copy->values[i].type != OCONFIG_TYPE_STRING) */
{
- ci_copy->values[i].value = ci_orig->values[i].value;
+ ci_copy->values[i].value = ci_orig->values[i].value;
}
}
} /* }}} if (ci_orig->values_num > 0) */
{
int i;
- ci_copy->children = (oconfig_item_t *) calloc (ci_orig->children_num,
- sizeof (*ci_copy->children));
+ ci_copy->children = (oconfig_item_t *) calloc ((size_t) ci_orig->children_num,
+ sizeof (*ci_copy->children));
if (ci_copy->children == NULL)
{
fprintf (stderr, "calloc failed.\n");
index f0e886cc1a1e28ab5f1c277eb830c54896410d59..803eec26205317b30c21425c9c2821a4f75321fe 100644 (file)
--- a/src/liboconfig/parser.y
+++ b/src/liboconfig/parser.y
%%
static int yyerror (const char *s)
{
- char *text;
+ const char *text;
if (*yytext == '\n')
text = "<newline>";
diff --git a/src/madwifi.c b/src/madwifi.c
index 7987378ed4a857e5674080b2d540bfdfbc11b6f6..d0b2f83ea1afa0e429f3fe2646ddbfa2739b7d5d 100644 (file)
--- a/src/madwifi.c
+++ b/src/madwifi.c
#include <dirent.h>
#include <sys/ioctl.h>
-#include <sys/socket.h>
#if !KERNEL_LINUX
# error "No applicable input method."
static inline int item_watched(int i)
{
assert (i >= 0);
- assert (i < ((STATIC_ARRAY_SIZE (watch_items) + 1) * 32));
+ assert (((size_t) i) < ((STATIC_ARRAY_SIZE (watch_items) + 1) * 32));
return watch_items[i / 32] & FLAG (i);
}
static inline int item_summed(int i)
{
assert (i >= 0);
- assert (i < ((STATIC_ARRAY_SIZE (misc_items) + 1) * 32));
+ assert (((size_t) i) < ((STATIC_ARRAY_SIZE (misc_items) + 1) * 32));
return misc_items[i / 32] & FLAG (i);
}
static int madwifi_real_init (void)
{
- int max = STATIC_ARRAY_SIZE (specs);
- int i;
+ size_t max = STATIC_ARRAY_SIZE (specs);
+ size_t i;
for (i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
bounds[i] = 0;
@@ -618,7 +617,7 @@ process_stat_struct (int which, const void *ptr, const char *dev, const char *ma
int i;
assert (which >= 1);
- assert (which < STATIC_ARRAY_SIZE (bounds));
+ assert (((size_t) which) < STATIC_ARRAY_SIZE (bounds));
for (i = bounds[which - 1]; i < bounds[which]; i++)
{
uint8_t buf[24*1024];
struct iwreq iwr;
uint8_t *cp;
- int len, nodes;
+ int nodes;
+ size_t len;
int status;
memset (&iwr, 0, sizeof (iwr));
index abde2b3495f818bf25b3188b4dadfd090210d6c9..e30ff91bc7f17e6a9983a9215e53497ea8c78794 100644 (file)
{
int num_counters;
int num_empty;
- int i;
+ size_t i;
if ((user_data == NULL) || (*user_data == NULL))
return (-1);
diff --git a/src/match_value.c b/src/match_value.c
index 4d49984f618173b48323634a3ed34a1b85cde048..9ffcecaae473b9bc24b49d721e5b2914ae4bcfbe 100644 (file)
--- a/src/match_value.c
+++ b/src/match_value.c
*/
static void mv_free_match (mv_match_t *m) /* {{{ */
{
- int i;
+ size_t i;
if (m == NULL)
return;
mv_match_t *m;
gauge_t *values;
int status;
- int i;
+ size_t i;
if ((user_data == NULL) || (*user_data == NULL))
return (-1);
diff --git a/src/mbmon.c b/src/mbmon.c
index d23062db2d54734551789c76cac837c9915c43f2..2d6d77e21474c274af56c7c9e2cdcd7e41575af2 100644 (file)
--- a/src/mbmon.c
+++ b/src/mbmon.c
#include "configfile.h"
#include <netdb.h>
-#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
double value;
char *nextc;
- char *type;
- char *inst;
+ const char *type;
+ const char *inst;
*t++ = '\0';
trim_spaces (s);
diff --git a/src/memcached.c b/src/memcached.c
index d650f02f1d3fd866030ca2914fccaefd82a9175b..2c01a576566579e32b3d8b092bebb4f1fdc5bc5f 100644 (file)
--- a/src/memcached.c
+++ b/src/memcached.c
#include "configfile.h"
#include <netdb.h>
-#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
static int memcached_connect_inet (memcached_t *st)
{
- char *host;
- char *port;
+ const char *host;
+ const char *port;
struct addrinfo ai_hints;
struct addrinfo *ai_list, *ai_ptr;
status = plugin_register_complex_read (/* group = */ "memcached",
/* name = */ callback_name,
/* callback = */ memcached_read,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user_data = */ &ud);
return (status);
} /* int memcached_add_read_callback */
diff --git a/src/memory.c b/src/memory.c
index fb2f3d38a4045fd8790160a1155ed04cda33ab23..3d8a867a7463c9eab4329d8af34caa1764b8dac5 100644 (file)
--- a/src/memory.c
+++ b/src/memory.c
#elif HAVE_LIBKSTAT
static int pagesize;
static kstat_t *ksp;
+static kstat_t *ksz;
/* #endif HAVE_LIBKSTAT */
#elif HAVE_SYSCTL
ksp = NULL;
return (-1);
}
+ if (get_kstat (&ksz, "zfs", 0, "arcstats") != 0)
+ {
+ ksz = NULL;
+ return (-1);
+ }
+
/* #endif HAVE_LIBKSTAT */
#elif HAVE_SYSCTL
* vm.stats.vm.v_inactive_count: 113730
* vm.stats.vm.v_cache_count: 10809
*/
- char *sysctl_keys[8] =
+ const char *sysctl_keys[8] =
{
"vm.stats.vm.v_page_size",
"vm.stats.vm.v_page_count",
long long mem_lock;
long long mem_kern;
long long mem_unus;
+ long long arcsize;
+
long long pp_kernel;
long long physmem;
if (ksp == NULL)
return (-1);
+ if (ksz == NULL)
+ return (-1);
mem_used = get_kstat_value (ksp, "pagestotal");
mem_free = get_kstat_value (ksp, "pagesfree");
mem_lock = get_kstat_value (ksp, "pageslocked");
- mem_kern = 0;
- mem_unus = 0;
-
+ arcsize = get_kstat_value (ksz, "size");
pp_kernel = get_kstat_value (ksp, "pp_kernel");
physmem = get_kstat_value (ksp, "physmem");
availrmem = get_kstat_value (ksp, "availrmem");
+ mem_kern = 0;
+ mem_unus = 0;
+
if ((mem_used < 0LL) || (mem_free < 0LL) || (mem_lock < 0LL))
{
WARNING ("memory plugin: one of used, free or locked is negative.");
mem_lock *= pagesize; /* some? ;) */
mem_kern *= pagesize; /* it's 2011 RAM is cheap */
mem_unus *= pagesize;
+ mem_kern -= arcsize;
+
MEMORY_SUBMIT ("used", (gauge_t) mem_used,
"free", (gauge_t) mem_free,
"locked", (gauge_t) mem_lock,
"kernel", (gauge_t) mem_kern,
+ "arc", (gauge_t) arcsize,
"unusable", (gauge_t) mem_unus);
/* #endif HAVE_LIBKSTAT */
diff --git a/src/modbus.c b/src/modbus.c
index c04b308d81728e74f4621737b64fb394eb47430d..d538fb3f717774bbc36b6c2eb7b7e1ff0919bc85 100644 (file)
--- a/src/modbus.c
+++ b/src/modbus.c
if (ds->ds_num != 1)
{
- ERROR ("Modbus plugin: The type \"%s\" has %i data sources. "
+ ERROR ("Modbus plugin: The type \"%s\" has %zu data sources. "
"I can only handle data sets with only one data source.",
data->type, ds->ds_num);
return (-1);
{
user_data_t ud;
char name[1024];
- struct timespec interval = { 0, 0 };
ud.data = host;
ud.free_func = host_free;
ssnprintf (name, sizeof (name), "modbus-%s", host->host);
- CDTIME_T_TO_TIMESPEC (host->interval, &interval);
-
plugin_register_complex_read (/* group = */ NULL, name,
/* callback = */ mb_read,
- /* interval = */ (host->interval > 0) ? &interval : NULL,
+ /* interval = */ host->interval,
&ud);
}
else
diff --git a/src/mqtt.c b/src/mqtt.c
--- /dev/null
+++ b/src/mqtt.c
@@ -0,0 +1,810 @@
+/**
+ * collectd - src/mqtt.c
+ * Copyright (C) 2014 Marc Falzon
+ * Copyright (C) 2014,2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Marc Falzon <marc at baha dot mu>
+ * Florian octo Forster <octo at collectd.org>
+ * Jan-Piet Mens <jpmens at gmail.com>
+ **/
+
+// Reference: http://mosquitto.org/api/files/mosquitto-h.html
+
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_cache.h"
+#include "utils_complain.h"
+
+#include <pthread.h>
+
+#include <mosquitto.h>
+
+#define MQTT_MAX_TOPIC_SIZE 1024
+#define MQTT_MAX_MESSAGE_SIZE MQTT_MAX_TOPIC_SIZE + 1024
+#define MQTT_DEFAULT_HOST "localhost"
+#define MQTT_DEFAULT_PORT 1883
+#define MQTT_DEFAULT_TOPIC_PREFIX "collectd"
+#define MQTT_DEFAULT_TOPIC "collectd/#"
+#ifndef MQTT_KEEPALIVE
+# define MQTT_KEEPALIVE 60
+#endif
+#ifndef SSL_VERIFY_PEER
+# define SSL_VERIFY_PEER 1
+#endif
+
+
+/*
+ * Data types
+ */
+struct mqtt_client_conf
+{
+ _Bool publish;
+ char *name;
+
+ struct mosquitto *mosq;
+ _Bool connected;
+
+ char *host;
+ int port;
+ char *client_id;
+ char *username;
+ char *password;
+ int qos;
+ char *cacertificatefile;
+ char *certificatefile;
+ char *certificatekeyfile;
+ char *tlsprotocol;
+ char *ciphersuite;
+
+ /* For publishing */
+ char *topic_prefix;
+ _Bool store_rates;
+ _Bool retain;
+
+ /* For subscribing */
+ pthread_t thread;
+ _Bool loop;
+ char *topic;
+ _Bool clean_session;
+
+ c_complain_t complaint_cantpublish;
+ pthread_mutex_t lock;
+};
+typedef struct mqtt_client_conf mqtt_client_conf_t;
+
+static mqtt_client_conf_t **subscribers = NULL;
+static size_t subscribers_num = 0;
+
+/*
+ * Functions
+ */
+#if LIBMOSQUITTO_MAJOR == 0
+static char const *mosquitto_strerror (int code)
+{
+ switch (code)
+ {
+ case MOSQ_ERR_SUCCESS: return "MOSQ_ERR_SUCCESS";
+ case MOSQ_ERR_NOMEM: return "MOSQ_ERR_NOMEM";
+ case MOSQ_ERR_PROTOCOL: return "MOSQ_ERR_PROTOCOL";
+ case MOSQ_ERR_INVAL: return "MOSQ_ERR_INVAL";
+ case MOSQ_ERR_NO_CONN: return "MOSQ_ERR_NO_CONN";
+ case MOSQ_ERR_CONN_REFUSED: return "MOSQ_ERR_CONN_REFUSED";
+ case MOSQ_ERR_NOT_FOUND: return "MOSQ_ERR_NOT_FOUND";
+ case MOSQ_ERR_CONN_LOST: return "MOSQ_ERR_CONN_LOST";
+ case MOSQ_ERR_SSL: return "MOSQ_ERR_SSL";
+ case MOSQ_ERR_PAYLOAD_SIZE: return "MOSQ_ERR_PAYLOAD_SIZE";
+ case MOSQ_ERR_NOT_SUPPORTED: return "MOSQ_ERR_NOT_SUPPORTED";
+ case MOSQ_ERR_AUTH: return "MOSQ_ERR_AUTH";
+ case MOSQ_ERR_ACL_DENIED: return "MOSQ_ERR_ACL_DENIED";
+ case MOSQ_ERR_UNKNOWN: return "MOSQ_ERR_UNKNOWN";
+ case MOSQ_ERR_ERRNO: return "MOSQ_ERR_ERRNO";
+ }
+
+ return "UNKNOWN ERROR CODE";
+}
+#else
+/* provided by libmosquitto */
+#endif
+
+static void mqtt_free (mqtt_client_conf_t *conf)
+{
+ if (conf == NULL)
+ return;
+
+ if (conf->connected)
+ (void) mosquitto_disconnect (conf->mosq);
+ conf->connected = 0;
+ (void) mosquitto_destroy (conf->mosq);
+
+ sfree (conf->host);
+ sfree (conf->username);
+ sfree (conf->password);
+ sfree (conf->client_id);
+ sfree (conf->topic_prefix);
+ sfree (conf);
+}
+
+static char *strip_prefix (char *topic)
+{
+ size_t num;
+ size_t i;
+
+ num = 0;
+ for (i = 0; topic[i] != 0; i++)
+ if (topic[i] == '/')
+ num++;
+
+ if (num < 2)
+ return (NULL);
+
+ while (num > 2)
+ {
+ char *tmp = strchr (topic, '/');
+ if (tmp == NULL)
+ return (NULL);
+ topic = tmp + 1;
+ num--;
+ }
+
+ return (topic);
+}
+
+static void on_message (
+#if LIBMOSQUITTO_MAJOR == 0
+#else
+ __attribute__((unused)) struct mosquitto *m,
+#endif
+ __attribute__((unused)) void *arg,
+ const struct mosquitto_message *msg)
+{
+ value_list_t vl = VALUE_LIST_INIT;
+ data_set_t const *ds;
+ char *topic;
+ char *name;
+ char *payload;
+ int status;
+
+ if (msg->payloadlen <= 0) {
+ DEBUG ("mqtt plugin: message has empty payload");
+ return;
+ }
+
+ topic = strdup (msg->topic);
+ name = strip_prefix (topic);
+
+ status = parse_identifier_vl (name, &vl);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: Unable to parse topic \"%s\".", topic);
+ sfree (topic);
+ return;
+ }
+ sfree (topic);
+
+ ds = plugin_get_ds (vl.type);
+ if (ds == NULL)
+ {
+ ERROR ("mqtt plugin: Unknown type: \"%s\".", vl.type);
+ return;
+ }
+
+ vl.values = calloc (ds->ds_num, sizeof (*vl.values));
+ if (vl.values == NULL)
+ {
+ ERROR ("mqtt plugin: calloc failed.");
+ return;
+ }
+ vl.values_len = ds->ds_num;
+
+ payload = malloc (msg->payloadlen+1);
+ if (payload == NULL)
+ {
+ ERROR ("mqtt plugin: malloc for payload buffer failed.");
+ sfree (vl.values);
+ return;
+ }
+ memmove (payload, msg->payload, msg->payloadlen);
+ payload[msg->payloadlen] = 0;
+
+ DEBUG ("mqtt plugin: payload = \"%s\"", payload);
+ status = parse_values (payload, &vl, ds);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: Unable to parse payload \"%s\".", payload);
+ sfree (payload);
+ sfree (vl.values);
+ return;
+ }
+ sfree (payload);
+
+ plugin_dispatch_values (&vl);
+ sfree (vl.values);
+} /* void on_message */
+
+/* must hold conf->lock when calling. */
+static int mqtt_reconnect (mqtt_client_conf_t *conf)
+{
+ int status;
+
+ if (conf->connected)
+ return (0);
+
+ status = mosquitto_reconnect (conf->mosq);
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ char errbuf[1024];
+ ERROR ("mqtt_connect_broker: mosquitto_connect failed: %s",
+ (status == MOSQ_ERR_ERRNO)
+ ? sstrerror(errno, errbuf, sizeof (errbuf))
+ : mosquitto_strerror (status));
+ return (-1);
+ }
+
+ conf->connected = 1;
+
+ c_release (LOG_INFO,
+ &conf->complaint_cantpublish,
+ "mqtt plugin: successfully reconnected to broker \"%s:%d\"",
+ conf->host, conf->port);
+
+ return (0);
+} /* mqtt_reconnect */
+
+/* must hold conf->lock when calling. */
+static int mqtt_connect (mqtt_client_conf_t *conf)
+{
+ char const *client_id;
+ int status;
+
+ if (conf->mosq != NULL)
+ return mqtt_reconnect (conf);
+
+ if (conf->client_id)
+ client_id = conf->client_id;
+ else
+ client_id = hostname_g;
+
+#if LIBMOSQUITTO_MAJOR == 0
+ conf->mosq = mosquitto_new (client_id, /* user data = */ conf);
+#else
+ conf->mosq = mosquitto_new (client_id, conf->clean_session, /* user data = */ conf);
+#endif
+ if (conf->mosq == NULL)
+ {
+ ERROR ("mqtt plugin: mosquitto_new failed");
+ return (-1);
+ }
+
+#if LIBMOSQUITTO_MAJOR != 0
+ if (conf->cacertificatefile) {
+ status = mosquitto_tls_set(conf->mosq, conf->cacertificatefile, NULL,
+ conf->certificatefile, conf->certificatekeyfile, /* pw_callback */NULL);
+ if (status != MOSQ_ERR_SUCCESS) {
+ ERROR ("mqtt plugin: cannot mosquitto_tls_set: %s", mosquitto_strerror(status));
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+
+ status = mosquitto_tls_opts_set(conf->mosq, SSL_VERIFY_PEER, conf->tlsprotocol, conf->ciphersuite);
+ if (status != MOSQ_ERR_SUCCESS) {
+ ERROR ("mqtt plugin: cannot mosquitto_tls_opts_set: %s", mosquitto_strerror(status));
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+
+ status = mosquitto_tls_insecure_set(conf->mosq, false);
+ if (status != MOSQ_ERR_SUCCESS) {
+ ERROR ("mqtt plugin: cannot mosquitto_tls_insecure_set: %s", mosquitto_strerror(status));
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+ }
+#endif
+
+ if (conf->username && conf->password)
+ {
+ status = mosquitto_username_pw_set (conf->mosq, conf->username, conf->password);
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ char errbuf[1024];
+ ERROR ("mqtt plugin: mosquitto_username_pw_set failed: %s",
+ (status == MOSQ_ERR_ERRNO)
+ ? sstrerror (errno, errbuf, sizeof (errbuf))
+ : mosquitto_strerror (status));
+
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+ }
+
+#if LIBMOSQUITTO_MAJOR == 0
+ status = mosquitto_connect (conf->mosq, conf->host, conf->port,
+ /* keepalive = */ MQTT_KEEPALIVE, /* clean session = */ conf->clean_session);
+#else
+ status = mosquitto_connect (conf->mosq, conf->host, conf->port, MQTT_KEEPALIVE);
+#endif
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ char errbuf[1024];
+ ERROR ("mqtt plugin: mosquitto_connect failed: %s",
+ (status == MOSQ_ERR_ERRNO)
+ ? sstrerror (errno, errbuf, sizeof (errbuf))
+ : mosquitto_strerror (status));
+
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+
+ if (!conf->publish)
+ {
+ mosquitto_message_callback_set (conf->mosq, on_message);
+
+ status = mosquitto_subscribe (conf->mosq,
+ /* message_id = */ NULL,
+ conf->topic, conf->qos);
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ ERROR ("mqtt plugin: Subscribing to \"%s\" failed: %s",
+ conf->topic, mosquitto_strerror (status));
+
+ mosquitto_disconnect (conf->mosq);
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+ }
+
+ conf->connected = 1;
+ return (0);
+} /* mqtt_connect */
+
+static void *subscribers_thread (void *arg)
+{
+ mqtt_client_conf_t *conf = arg;
+ int status;
+
+ conf->loop = 1;
+
+ while (conf->loop)
+ {
+ status = mqtt_connect (conf);
+ if (status != 0)
+ {
+ sleep (1);
+ continue;
+ }
+
+ /* The documentation says "0" would map to the default (1000ms), but
+ * that does not work on some versions. */
+#if LIBMOSQUITTO_MAJOR == 0
+ status = mosquitto_loop (conf->mosq, /* timeout = */ 1000 /* ms */);
+#else
+ status = mosquitto_loop (conf->mosq,
+ /* timeout[ms] = */ 1000,
+ /* max_packets = */ 100);
+#endif
+ if (status == MOSQ_ERR_CONN_LOST)
+ {
+ conf->connected = 0;
+ continue;
+ }
+ else if (status != MOSQ_ERR_SUCCESS)
+ {
+ ERROR ("mqtt plugin: mosquitto_loop failed: %s",
+ mosquitto_strerror (status));
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ conf->connected = 0;
+ continue;
+ }
+
+ DEBUG ("mqtt plugin: mosquitto_loop succeeded.");
+ } /* while (conf->loop) */
+
+ pthread_exit (0);
+} /* void *subscribers_thread */
+
+static int publish (mqtt_client_conf_t *conf, char const *topic,
+ void const *payload, size_t payload_len)
+{
+ int status;
+
+ pthread_mutex_lock (&conf->lock);
+
+ status = mqtt_connect (conf);
+ if (status != 0) {
+ pthread_mutex_unlock (&conf->lock);
+ ERROR ("mqtt plugin: unable to reconnect to broker");
+ return (status);
+ }
+
+ status = mosquitto_publish(conf->mosq, /* message_id */ NULL, topic,
+#if LIBMOSQUITTO_MAJOR == 0
+ (uint32_t) payload_len, payload,
+#else
+ (int) payload_len, payload,
+#endif
+ conf->qos, conf->retain);
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ char errbuf[1024];
+ c_complain (LOG_ERR,
+ &conf->complaint_cantpublish,
+ "mqtt plugin: mosquitto_publish failed: %s",
+ (status == MOSQ_ERR_ERRNO)
+ ? sstrerror(errno, errbuf, sizeof (errbuf))
+ : mosquitto_strerror(status));
+ /* Mark our connection "down" regardless of the error as a safety
+ * measure; we will try to reconnect the next time we have to publish a
+ * message */
+ conf->connected = 0;
+
+ pthread_mutex_unlock (&conf->lock);
+ return (-1);
+ }
+
+ pthread_mutex_unlock (&conf->lock);
+ return (0);
+} /* int publish */
+
+static int format_topic (char *buf, size_t buf_len,
+ data_set_t const *ds, value_list_t const *vl,
+ mqtt_client_conf_t *conf)
+{
+ char name[MQTT_MAX_TOPIC_SIZE];
+ int status;
+
+ if ((conf->topic_prefix == NULL) || (conf->topic_prefix[0] == 0))
+ return (FORMAT_VL (buf, buf_len, vl));
+
+ status = FORMAT_VL (name, sizeof (name), vl);
+ if (status != 0)
+ return (status);
+
+ status = ssnprintf (buf, buf_len, "%s/%s", conf->topic_prefix, name);
+ if ((status < 0) || (((size_t) status) >= buf_len))
+ return (ENOMEM);
+
+ return (0);
+} /* int format_topic */
+
+static int mqtt_write (const data_set_t *ds, const value_list_t *vl,
+ user_data_t *user_data)
+{
+ mqtt_client_conf_t *conf;
+ char topic[MQTT_MAX_TOPIC_SIZE];
+ char payload[MQTT_MAX_MESSAGE_SIZE];
+ int status = 0;
+
+ if ((user_data == NULL) || (user_data->data == NULL))
+ return (EINVAL);
+ conf = user_data->data;
+
+ status = format_topic (topic, sizeof (topic), ds, vl, conf);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: format_topic failed with status %d.", status);
+ return (status);
+ }
+
+ status = format_values (payload, sizeof (payload),
+ ds, vl, conf->store_rates);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: format_values failed with status %d.", status);
+ return (status);
+ }
+
+ status = publish (conf, topic, payload, strlen (payload) + 1);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: publish failed: %s", mosquitto_strerror (status));
+ return (status);
+ }
+
+ return (status);
+} /* mqtt_write */
+
+/*
+ * <Publish "name">
+ * Host "example.com"
+ * Port 1883
+ * ClientId "collectd"
+ * User "guest"
+ * Password "secret"
+ * Prefix "collectd"
+ * StoreRates true
+ * Retain false
+ * QoS 0
+ * CACert "ca.pem" Enables TLS if set
+ * CertificateFile "client-cert.pem" optional
+ * CertificateKeyFile "client-key.pem" optional
+ * TLSProtocol "tlsv1.2" optional
+ * </Publish>
+ */
+static int mqtt_config_publisher (oconfig_item_t *ci)
+{
+ mqtt_client_conf_t *conf;
+ char cb_name[1024];
+ user_data_t user_data;
+ int status;
+ int i;
+
+ conf = calloc (1, sizeof (*conf));
+ if (conf == NULL)
+ {
+ ERROR ("mqtt plugin: malloc failed.");
+ return (-1);
+ }
+ conf->publish = 1;
+
+ conf->name = NULL;
+ status = cf_util_get_string (ci, &conf->name);
+ if (status != 0)
+ {
+ mqtt_free (conf);
+ return (status);
+ }
+
+ conf->host = strdup (MQTT_DEFAULT_HOST);
+ conf->port = MQTT_DEFAULT_PORT;
+ conf->client_id = NULL;
+ conf->qos = 0;
+ conf->topic_prefix = strdup (MQTT_DEFAULT_TOPIC_PREFIX);
+ conf->store_rates = 1;
+
+ status = pthread_mutex_init (&conf->lock, NULL);
+ if (status != 0)
+ {
+ mqtt_free (conf);
+ return (status);
+ }
+
+ C_COMPLAIN_INIT (&conf->complaint_cantpublish);
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+ if (strcasecmp ("Host", child->key) == 0)
+ cf_util_get_string (child, &conf->host);
+ else if (strcasecmp ("Port", child->key) == 0)
+ {
+ int tmp = cf_util_get_port_number (child);
+ if (tmp < 0)
+ ERROR ("mqtt plugin: Invalid port number.");
+ else
+ conf->port = tmp;
+ }
+ else if (strcasecmp ("ClientId", child->key) == 0)
+ cf_util_get_string (child, &conf->client_id);
+ else if (strcasecmp ("User", child->key) == 0)
+ cf_util_get_string (child, &conf->username);
+ else if (strcasecmp ("Password", child->key) == 0)
+ cf_util_get_string (child, &conf->password);
+ else if (strcasecmp ("QoS", child->key) == 0)
+ {
+ int tmp = -1;
+ status = cf_util_get_int (child, &tmp);
+ if ((status != 0) || (tmp < 0) || (tmp > 2))
+ ERROR ("mqtt plugin: Not a valid QoS setting.");
+ else
+ conf->qos = tmp;
+ }
+ else if (strcasecmp ("Prefix", child->key) == 0)
+ cf_util_get_string (child, &conf->topic_prefix);
+ else if (strcasecmp ("StoreRates", child->key) == 0)
+ cf_util_get_boolean (child, &conf->store_rates);
+ else if (strcasecmp ("Retain", child->key) == 0)
+ cf_util_get_boolean (child, &conf->retain);
+ else if (strcasecmp ("CACert", child->key) == 0)
+ cf_util_get_string (child, &conf->cacertificatefile);
+ else if (strcasecmp ("CertificateFile", child->key) == 0)
+ cf_util_get_string (child, &conf->certificatefile);
+ else if (strcasecmp ("CertificateKeyFile", child->key) == 0)
+ cf_util_get_string (child, &conf->certificatekeyfile);
+ else if (strcasecmp ("TLSProtocol", child->key) == 0)
+ cf_util_get_string (child, &conf->tlsprotocol);
+ else if (strcasecmp ("CipherSuite", child->key) == 0)
+ cf_util_get_string (child, &conf->ciphersuite);
+ else
+ ERROR ("mqtt plugin: Unknown config option: %s", child->key);
+ }
+
+ ssnprintf (cb_name, sizeof (cb_name), "mqtt/%s", conf->name);
+ memset (&user_data, 0, sizeof (user_data));
+ user_data.data = conf;
+
+ plugin_register_write (cb_name, mqtt_write, &user_data);
+ return (0);
+} /* mqtt_config_publisher */
+
+/*
+ * <Subscribe "name">
+ * Host "example.com"
+ * Port 1883
+ * ClientId "collectd"
+ * User "guest"
+ * Password "secret"
+ * Topic "collectd/#"
+ * </Subscribe>
+ */
+static int mqtt_config_subscriber (oconfig_item_t *ci)
+{
+ mqtt_client_conf_t **tmp;
+ mqtt_client_conf_t *conf;
+ int status;
+ int i;
+
+ conf = calloc (1, sizeof (*conf));
+ if (conf == NULL)
+ {
+ ERROR ("mqtt plugin: malloc failed.");
+ return (-1);
+ }
+ conf->publish = 0;
+
+ conf->name = NULL;
+ status = cf_util_get_string (ci, &conf->name);
+ if (status != 0)
+ {
+ mqtt_free (conf);
+ return (status);
+ }
+
+ conf->host = strdup (MQTT_DEFAULT_HOST);
+ conf->port = MQTT_DEFAULT_PORT;
+ conf->client_id = NULL;
+ conf->qos = 2;
+ conf->topic = strdup (MQTT_DEFAULT_TOPIC);
+ conf->clean_session = 1;
+
+ status = pthread_mutex_init (&conf->lock, NULL);
+ if (status != 0)
+ {
+ mqtt_free (conf);
+ return (status);
+ }
+
+ C_COMPLAIN_INIT (&conf->complaint_cantpublish);
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+ if (strcasecmp ("Host", child->key) == 0)
+ cf_util_get_string (child, &conf->host);
+ else if (strcasecmp ("Port", child->key) == 0)
+ {
+ status = cf_util_get_port_number (child);
+ if (status < 0)
+ ERROR ("mqtt plugin: Invalid port number.");
+ else
+ conf->port = status;
+ }
+ else if (strcasecmp ("ClientId", child->key) == 0)
+ cf_util_get_string (child, &conf->client_id);
+ else if (strcasecmp ("User", child->key) == 0)
+ cf_util_get_string (child, &conf->username);
+ else if (strcasecmp ("Password", child->key) == 0)
+ cf_util_get_string (child, &conf->password);
+ else if (strcasecmp ("QoS", child->key) == 0)
+ {
+ int qos = -1;
+ status = cf_util_get_int (child, &qos);
+ if ((status != 0) || (qos < 0) || (qos > 2))
+ ERROR ("mqtt plugin: Not a valid QoS setting.");
+ else
+ conf->qos = qos;
+ }
+ else if (strcasecmp ("Topic", child->key) == 0)
+ cf_util_get_string (child, &conf->topic);
+ else if (strcasecmp ("CleanSession", child->key) == 0)
+ cf_util_get_boolean (child, &conf->clean_session);
+ else
+ ERROR ("mqtt plugin: Unknown config option: %s", child->key);
+ }
+
+ tmp = realloc (subscribers, sizeof (*subscribers) * (subscribers_num + 1) );
+ if (tmp == NULL)
+ {
+ ERROR ("mqtt plugin: realloc failed.");
+ mqtt_free (conf);
+ return (-1);
+ }
+ subscribers = tmp;
+ subscribers[subscribers_num] = conf;
+ subscribers_num++;
+
+ return (0);
+} /* mqtt_config_subscriber */
+
+/*
+ * <Plugin mqtt>
+ * <Publish "name">
+ * # ...
+ * </Publish>
+ * <Subscribe "name">
+ * # ...
+ * </Subscribe>
+ * </Plugin>
+ */
+static int mqtt_config (oconfig_item_t *ci)
+{
+ int i;
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp ("Publish", child->key) == 0)
+ mqtt_config_publisher (child);
+ else if (strcasecmp ("Subscribe", child->key) == 0)
+ mqtt_config_subscriber (child);
+ else
+ ERROR ("mqtt plugin: Unknown config option: %s", child->key);
+ }
+
+ return (0);
+} /* int mqtt_config */
+
+static int mqtt_init (void)
+{
+ size_t i;
+
+ mosquitto_lib_init ();
+
+ for (i = 0; i < subscribers_num; i++)
+ {
+ int status;
+
+ if (subscribers[i]->loop)
+ continue;
+
+ status = plugin_thread_create (&subscribers[i]->thread,
+ /* attrs = */ NULL,
+ /* func = */ subscribers_thread,
+ /* args = */ subscribers[i]);
+ if (status != 0)
+ {
+ char errbuf[1024];
+ ERROR ("mqtt plugin: pthread_create failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ continue;
+ }
+ }
+
+ return (0);
+} /* mqtt_init */
+
+void module_register (void)
+{
+ plugin_register_complex_config ("mqtt", mqtt_config);
+ plugin_register_init ("mqtt", mqtt_init);
+} /* void module_register */
+
+/* vim: set sw=4 sts=4 et fdm=marker : */
diff --git a/src/mysql.c b/src/mysql.c
index f6c710c0376e5fa85638f4675d46e635320c2313..8a1692064b534dda25db368fdb77830cbebdcf15 100644 (file)
--- a/src/mysql.c
+++ b/src/mysql.c
plugin_register_complex_read (/* group = */ NULL, cb_name,
mysql_read,
- /* interval = */ NULL, &ud);
+ /* interval = */ 0, &ud);
}
else
{
MYSQL_RES *res;
MYSQL_ROW row;
- char *query;
- int field_num;
+ const char *query;
+ int field_num;
unsigned long long position;
query = "SHOW MASTER STATUS";
MYSQL_RES *res;
MYSQL_ROW row;
- char *query;
- int field_num;
+ const char *query;
+ int field_num;
/* WTF? libmysqlclient does not seem to provide any means to
* translate a column name to a column index ... :-/ */
MYSQL_RES *res;
MYSQL_ROW row;
- char *query;
- struct {
- char *key;
- char *type;
- int ds_type;
- } metrics[] = {
- { "metadata_mem_pool_size", "bytes", DS_TYPE_GAUGE },
- { "lock_deadlocks", "mysql_locks", DS_TYPE_DERIVE },
- { "lock_timeouts", "mysql_locks", DS_TYPE_DERIVE },
- { "lock_row_lock_current_waits", "mysql_locks", DS_TYPE_DERIVE },
- { "buffer_pool_size", "bytes", DS_TYPE_GAUGE },
-
- { "buffer_pool_reads", "operations", DS_TYPE_DERIVE },
- { "buffer_pool_read_requests", "operations", DS_TYPE_DERIVE },
- { "buffer_pool_write_requests", "operations", DS_TYPE_DERIVE },
- { "buffer_pool_wait_free", "operations", DS_TYPE_DERIVE },
- { "buffer_pool_read_ahead", "operations", DS_TYPE_DERIVE },
- { "buffer_pool_read_ahead_evicted", "operations", DS_TYPE_DERIVE },
-
- { "buffer_pool_pages_total", "gauge", DS_TYPE_GAUGE },
- { "buffer_pool_pages_misc", "gauge", DS_TYPE_GAUGE },
- { "buffer_pool_pages_data", "gauge", DS_TYPE_GAUGE },
- { "buffer_pool_bytes_data", "gauge", DS_TYPE_GAUGE },
- { "buffer_pool_pages_dirty", "gauge", DS_TYPE_GAUGE },
- { "buffer_pool_bytes_dirty", "gauge", DS_TYPE_GAUGE },
- { "buffer_pool_pages_free", "gauge", DS_TYPE_GAUGE },
-
- { "buffer_pages_created", "operations", DS_TYPE_DERIVE },
- { "buffer_pages_written", "operations", DS_TYPE_DERIVE },
- { "buffer_pages_read", "operations", DS_TYPE_DERIVE },
- { "buffer_data_reads", "operations", DS_TYPE_DERIVE },
- { "buffer_data_written", "operations", DS_TYPE_DERIVE },
-
- { "os_data_reads", "operations", DS_TYPE_DERIVE },
- { "os_data_writes", "operations", DS_TYPE_DERIVE },
- { "os_data_fsyncs", "operations", DS_TYPE_DERIVE },
- { "os_log_bytes_written", "operations", DS_TYPE_DERIVE },
- { "os_log_fsyncs", "operations", DS_TYPE_DERIVE },
- { "os_log_pending_fsyncs", "operations", DS_TYPE_DERIVE },
- { "os_log_pending_writes", "operations", DS_TYPE_DERIVE },
-
- { "trx_rseg_history_len", "gauge", DS_TYPE_GAUGE },
-
- { "log_waits", "operations", DS_TYPE_DERIVE },
- { "log_write_requests", "operations", DS_TYPE_DERIVE },
- { "log_writes", "operations", DS_TYPE_DERIVE },
- { "adaptive_hash_searches", "operations", DS_TYPE_DERIVE },
-
- { "file_num_open_files", "gauge", DS_TYPE_GAUGE },
-
- { "ibuf_merges_insert", "operations", DS_TYPE_DERIVE },
- { "ibuf_merges_delete_mark", "operations", DS_TYPE_DERIVE },
- { "ibuf_merges_delete", "operations", DS_TYPE_DERIVE },
- { "ibuf_merges_discard_insert", "operations", DS_TYPE_DERIVE },
- { "ibuf_merges_discard_delete_mark","operations", DS_TYPE_DERIVE },
- { "ibuf_merges_discard_delete", "operations", DS_TYPE_DERIVE },
- { "ibuf_merges_discard_merges", "operations", DS_TYPE_DERIVE },
- { "ibuf_size", "bytes", DS_TYPE_GAUGE },
-
- { "innodb_activity_count", "gauge", DS_TYPE_GAUGE },
- { "innodb_dblwr_writes", "operations", DS_TYPE_DERIVE },
- { "innodb_dblwr_pages_written", "operations", DS_TYPE_DERIVE },
- { "innodb_dblwr_page_size", "gauge", DS_TYPE_GAUGE },
-
- { "innodb_rwlock_s_spin_waits", "operations", DS_TYPE_DERIVE },
- { "innodb_rwlock_x_spin_waits", "operations", DS_TYPE_DERIVE },
- { "innodb_rwlock_s_spin_rounds", "operations", DS_TYPE_DERIVE },
- { "innodb_rwlock_x_spin_rounds", "operations", DS_TYPE_DERIVE },
- { "innodb_rwlock_s_os_waits", "operations", DS_TYPE_DERIVE },
- { "innodb_rwlock_x_os_waits", "operations", DS_TYPE_DERIVE },
-
- { "dml_reads", "operations", DS_TYPE_DERIVE },
- { "dml_inserts", "operations", DS_TYPE_DERIVE },
- { "dml_deletes", "operations", DS_TYPE_DERIVE },
- { "dml_updates", "operations", DS_TYPE_DERIVE },
-
- { NULL, NULL, 0}
- };
+ const char *query;
+ struct {
+ const char *key;
+ const char *type;
+ int ds_type;
+ } metrics[] = {
+ { "metadata_mem_pool_size", "bytes", DS_TYPE_GAUGE },
+ { "lock_deadlocks", "mysql_locks", DS_TYPE_DERIVE },
+ { "lock_timeouts", "mysql_locks", DS_TYPE_DERIVE },
+ { "lock_row_lock_current_waits", "mysql_locks", DS_TYPE_DERIVE },
+ { "buffer_pool_size", "bytes", DS_TYPE_GAUGE },
+
+ { "buffer_pool_reads", "operations", DS_TYPE_DERIVE },
+ { "buffer_pool_read_requests", "operations", DS_TYPE_DERIVE },
+ { "buffer_pool_write_requests", "operations", DS_TYPE_DERIVE },
+ { "buffer_pool_wait_free", "operations", DS_TYPE_DERIVE },
+ { "buffer_pool_read_ahead", "operations", DS_TYPE_DERIVE },
+ { "buffer_pool_read_ahead_evicted", "operations", DS_TYPE_DERIVE },
+
+ { "buffer_pool_pages_total", "gauge", DS_TYPE_GAUGE },
+ { "buffer_pool_pages_misc", "gauge", DS_TYPE_GAUGE },
+ { "buffer_pool_pages_data", "gauge", DS_TYPE_GAUGE },
+ { "buffer_pool_bytes_data", "gauge", DS_TYPE_GAUGE },
+ { "buffer_pool_pages_dirty", "gauge", DS_TYPE_GAUGE },
+ { "buffer_pool_bytes_dirty", "gauge", DS_TYPE_GAUGE },
+ { "buffer_pool_pages_free", "gauge", DS_TYPE_GAUGE },
+
+ { "buffer_pages_created", "operations", DS_TYPE_DERIVE },
+ { "buffer_pages_written", "operations", DS_TYPE_DERIVE },
+ { "buffer_pages_read", "operations", DS_TYPE_DERIVE },
+ { "buffer_data_reads", "operations", DS_TYPE_DERIVE },
+ { "buffer_data_written", "operations", DS_TYPE_DERIVE },
+
+ { "os_data_reads", "operations", DS_TYPE_DERIVE },
+ { "os_data_writes", "operations", DS_TYPE_DERIVE },
+ { "os_data_fsyncs", "operations", DS_TYPE_DERIVE },
+ { "os_log_bytes_written", "operations", DS_TYPE_DERIVE },
+ { "os_log_fsyncs", "operations", DS_TYPE_DERIVE },
+ { "os_log_pending_fsyncs", "operations", DS_TYPE_DERIVE },
+ { "os_log_pending_writes", "operations", DS_TYPE_DERIVE },
+
+ { "trx_rseg_history_len", "gauge", DS_TYPE_GAUGE },
+
+ { "log_waits", "operations", DS_TYPE_DERIVE },
+ { "log_write_requests", "operations", DS_TYPE_DERIVE },
+ { "log_writes", "operations", DS_TYPE_DERIVE },
+ { "adaptive_hash_searches", "operations", DS_TYPE_DERIVE },
+
+ { "file_num_open_files", "gauge", DS_TYPE_GAUGE },
+
+ { "ibuf_merges_insert", "operations", DS_TYPE_DERIVE },
+ { "ibuf_merges_delete_mark", "operations", DS_TYPE_DERIVE },
+ { "ibuf_merges_delete", "operations", DS_TYPE_DERIVE },
+ { "ibuf_merges_discard_insert", "operations", DS_TYPE_DERIVE },
+ { "ibuf_merges_discard_delete_mark", "operations", DS_TYPE_DERIVE },
+ { "ibuf_merges_discard_delete", "operations", DS_TYPE_DERIVE },
+ { "ibuf_merges_discard_merges", "operations", DS_TYPE_DERIVE },
+ { "ibuf_size", "bytes", DS_TYPE_GAUGE },
+
+ { "innodb_activity_count", "gauge", DS_TYPE_GAUGE },
+ { "innodb_dblwr_writes", "operations", DS_TYPE_DERIVE },
+ { "innodb_dblwr_pages_written", "operations", DS_TYPE_DERIVE },
+ { "innodb_dblwr_page_size", "gauge", DS_TYPE_GAUGE },
+
+ { "innodb_rwlock_s_spin_waits", "operations", DS_TYPE_DERIVE },
+ { "innodb_rwlock_x_spin_waits", "operations", DS_TYPE_DERIVE },
+ { "innodb_rwlock_s_spin_rounds", "operations", DS_TYPE_DERIVE },
+ { "innodb_rwlock_x_spin_rounds", "operations", DS_TYPE_DERIVE },
+ { "innodb_rwlock_s_os_waits", "operations", DS_TYPE_DERIVE },
+ { "innodb_rwlock_x_os_waits", "operations", DS_TYPE_DERIVE },
+
+ { "dml_reads", "operations", DS_TYPE_DERIVE },
+ { "dml_inserts", "operations", DS_TYPE_DERIVE },
+ { "dml_deletes", "operations", DS_TYPE_DERIVE },
+ { "dml_updates", "operations", DS_TYPE_DERIVE },
+
+ { NULL, NULL, 0}
+ };
query = "SELECT name, count, type FROM information_schema.innodb_metrics WHERE status = 'enabled'";
while ((row = mysql_fetch_row (res)))
{
- int i;
+ int i;
char *key;
unsigned long long val;
key = row[0];
val = atoll (row[1]);
- for (i = 0;
- metrics[i].key != NULL && strcmp(metrics[i].key, key) != 0;
- i++)
- ;
-
- if (metrics[i].key == NULL)
- continue;
-
- switch (metrics[i].ds_type) {
- case DS_TYPE_COUNTER:
- counter_submit(metrics[i].type, key, (counter_t)val, db);
- break;
- case DS_TYPE_GAUGE:
- gauge_submit(metrics[i].type, key, (gauge_t)val, db);
- break;
- case DS_TYPE_DERIVE:
- derive_submit(metrics[i].type, key, (derive_t)val, db);
- break;
- }
- }
-
- mysql_free_result(res);
- return (0);
+ for (i = 0; metrics[i].key != NULL && strcmp(metrics[i].key, key) != 0; i++)
+ ;
+
+ if (metrics[i].key == NULL)
+ continue;
+
+ switch (metrics[i].ds_type) {
+ case DS_TYPE_COUNTER:
+ counter_submit(metrics[i].type, key, (counter_t)val, db);
+ break;
+ case DS_TYPE_GAUGE:
+ gauge_submit(metrics[i].type, key, (gauge_t)val, db);
+ break;
+ case DS_TYPE_DERIVE:
+ derive_submit(metrics[i].type, key, (derive_t)val, db);
+ break;
+ }
+ }
+
+ mysql_free_result(res);
+ return (0);
}
static int mysql_read (user_data_t *ud)
{
mysql_database_t *db;
- MYSQL *con;
- MYSQL_RES *res;
- MYSQL_ROW row;
- char *query;
+ MYSQL *con;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ const char *query;
derive_t qcache_hits = 0;
derive_t qcache_inserts = 0;
unsigned long long traffic_incoming = 0ULL;
unsigned long long traffic_outgoing = 0ULL;
- unsigned long mysql_version = 0ULL;
+ unsigned long mysql_version = 0ULL;
if ((ud == NULL) || (ud->data == NULL))
{
if ((con = getconnection (db)) == NULL)
return (-1);
- mysql_version = mysql_get_server_version(con);
+ mysql_version = mysql_get_server_version(con);
query = "SHOW STATUS";
if (mysql_version >= 50002)
traffic_submit (traffic_incoming, traffic_outgoing, db);
if (mysql_version >= 50600 && db->innodb_stats)
- mysql_read_innodb_stats (db, con);
+ mysql_read_innodb_stats (db, con);
if (db->master_stats)
mysql_read_master_stats (db, con);
diff --git a/src/netapp.c b/src/netapp.c
index f761e290dfb509432f24fa6a2b5f6e517c2e5963..8a8a7fe4ea0863e3aed4f18052abd11e03c5de96 100644 (file)
--- a/src/netapp.c
+++ b/src/netapp.c
static int cna_register_host (host_config_t *host) /* {{{ */
{
char cb_name[256];
- struct timespec interval;
user_data_t ud;
if (host->vfiler)
else
ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name);
- CDTIME_T_TO_TIMESPEC (host->interval, &interval);
-
memset (&ud, 0, sizeof (ud));
ud.data = host;
ud.free_func = (void (*) (void *)) free_host_config;
plugin_register_complex_read (/* group = */ NULL, cb_name,
/* callback = */ cna_read,
- /* interval = */ (host->interval > 0) ? &interval : NULL,
+ /* interval = */ host->interval,
/* user data = */ &ud);
return (0);
diff --git a/src/netlink.c b/src/netlink.c
index aa9760f9328b78eb87e14f70501bc1622a57f12d..d4661ce8423091b72f5276a3a2f4fa9d3f15561c 100644 (file)
--- a/src/netlink.c
+++ b/src/netlink.c
#include "common.h"
#include <asm/types.h>
-#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
const char *kind = NULL;
/* char *type_instance; */
- char *tc_type;
+ const char *tc_type;
char tc_inst[DATA_MAX_NAME_LEN];
_Bool stats_submitted = 0;
diff --git a/src/network.c b/src/network.c
index af24911ee365b1ae512000cce93103ffdaf86a94..439b0cef704d7d22404f73561faf4d2b3241729c 100644 (file)
--- a/src/network.c
+++ b/src/network.c
#if HAVE_PTHREAD_H
# include <pthread.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NETDB_H
# include <netdb.h>
#endif
static int network_config_ttl = 0;
/* Ethernet - (IPv6 + UDP) = 1500 - (40 + 8) = 1452 */
static size_t network_config_packet_size = 1452;
-static int network_config_forward = 0;
-static int network_config_stats = 0;
+static _Bool network_config_forward = 0;
+static _Bool network_config_stats = 0;
static sockent_t *sending_sockets = NULL;
static char *send_buffer;
static char *send_buffer_ptr;
static int send_buffer_fill;
+static cdtime_t send_buffer_last_update;
static value_list_t send_buffer_vl = VALUE_LIST_STATIC;
static pthread_mutex_t send_buffer_lock = PTHREAD_MUTEX_INITIALIZER;
_Bool received = 0;
int status;
- if (network_config_forward != 0)
+ if (network_config_forward)
return (1);
if (vl->meta == NULL)
} /* int write_part_string */
static int parse_part_values (void **ret_buffer, size_t *ret_buffer_len,
- value_t **ret_values, int *ret_num_values)
+ value_t **ret_values, size_t *ret_num_values)
{
char *buffer = *ret_buffer;
size_t buffer_len = *ret_buffer_len;
uint16_t tmp16;
size_t exp_size;
- int i;
+ size_t i;
uint16_t pkg_length;
uint16_t pkg_type;
- uint16_t pkg_numval;
+ size_t pkg_numval;
uint8_t *pkg_types;
value_t *pkg_values;
memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
buffer += sizeof (tmp16);
- pkg_numval = ntohs (tmp16);
+ pkg_numval = (size_t) ntohs (tmp16);
assert (pkg_type == TYPE_VALUES);
exp_size, buffer_len);
return (-1);
}
+ assert (pkg_numval <= ((buffer_len - 6) / 9));
if (pkg_length != exp_size)
{
return (-1);
}
- pkg_types = (uint8_t *) malloc (pkg_numval * sizeof (uint8_t));
- pkg_values = (value_t *) malloc (pkg_numval * sizeof (value_t));
+ pkg_types = calloc (pkg_numval, sizeof (*pkg_types));
+ pkg_values = calloc (pkg_numval, sizeof (*pkg_values));
if ((pkg_types == NULL) || (pkg_values == NULL))
{
sfree (pkg_types);
sfree (pkg_values);
- ERROR ("network plugin: parse_part_values: malloc failed.");
+ ERROR ("network plugin: parse_part_values: calloc failed.");
return (-1);
}
- memcpy ((void *) pkg_types, (void *) buffer, pkg_numval * sizeof (uint8_t));
- buffer += pkg_numval * sizeof (uint8_t);
- memcpy ((void *) pkg_values, (void *) buffer, pkg_numval * sizeof (value_t));
- buffer += pkg_numval * sizeof (value_t);
+ memcpy (pkg_types, buffer, pkg_numval * sizeof (*pkg_types));
+ buffer += pkg_numval * sizeof (*pkg_types);
+ memcpy (pkg_values, buffer, pkg_numval * sizeof (*pkg_values));
+ buffer += pkg_numval * sizeof (*pkg_values);
for (i = 0; i < pkg_numval; i++)
{
char buffer[network_config_packet_size];
int buffer_len;
- int i;
+ size_t i;
int status = 0;
receive_list_entry_t *private_list_head;
memset (send_buffer, 0, network_config_packet_size);
send_buffer_ptr = send_buffer;
send_buffer_fill = 0;
+ send_buffer_last_update = 0;
memset (&send_buffer_vl, 0, sizeof (send_buffer_vl));
} /* int network_init_buffer */
/* status == bytes added to the buffer */
send_buffer_fill += status;
send_buffer_ptr += status;
+ send_buffer_last_update = cdtime();
stats_values_sent++;
}
return ((status < 0) ? -1 : 0);
} /* int network_write */
-static int network_config_set_boolean (const oconfig_item_t *ci, /* {{{ */
- int *retval)
-{
- if ((ci->values_num != 1)
- || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN)
- && (ci->values[0].type != OCONFIG_TYPE_STRING)))
- {
- ERROR ("network plugin: The `%s' config option needs "
- "exactly one boolean argument.", ci->key);
- return (-1);
- }
-
- if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
- {
- if (ci->values[0].value.boolean)
- *retval = 1;
- else
- *retval = 0;
- }
- else
- {
- char *str = ci->values[0].value.string;
-
- if (IS_TRUE (str))
- *retval = 1;
- else if (IS_FALSE (str))
- *retval = 0;
- else
- {
- ERROR ("network plugin: Cannot parse string value `%s' of the `%s' "
- "option as boolean value.",
- str, ci->key);
- return (-1);
- }
- }
-
- return (0);
-} /* }}} int network_config_set_boolean */
-
static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */
{
- int tmp;
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
- {
- WARNING ("network plugin: The `TimeToLive' config option needs exactly "
- "one numeric argument.");
- return (-1);
- }
+ int tmp = 0;
- tmp = (int) ci->values[0].value.number;
- if ((tmp > 0) && (tmp <= 255))
+ if (cf_util_get_int (ci, &tmp) != 0)
+ return (-1);
+ else if ((tmp > 0) && (tmp <= 255))
network_config_ttl = tmp;
else {
WARNING ("network plugin: The `TimeToLive' must be between 1 and 255.");
static int network_config_set_interface (const oconfig_item_t *ci, /* {{{ */
int *interface)
{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("network plugin: The `Interface' config option needs exactly "
- "one string argument.");
- return (-1);
- }
+ char if_name[256];
- if (interface == NULL)
+ if (cf_util_get_string_buffer (ci, if_name, sizeof (if_name)) != 0)
return (-1);
- *interface = if_nametoindex (ci->values[0].value.string);
-
+ *interface = if_nametoindex (if_name);
return (0);
} /* }}} int network_config_set_interface */
static int network_config_set_buffer_size (const oconfig_item_t *ci) /* {{{ */
{
- int tmp;
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
- {
- WARNING ("network plugin: The `MaxPacketSize' config option needs exactly "
- "one numeric argument.");
- return (-1);
- }
+ int tmp = 0;
- tmp = (int) ci->values[0].value.number;
- if ((tmp >= 1024) && (tmp <= 65535))
+ if (cf_util_get_int (ci, &tmp) != 0)
+ return (-1);
+ else if ((tmp >= 1024) && (tmp <= 65535))
network_config_packet_size = tmp;
-
- return (0);
-} /* }}} int network_config_set_buffer_size */
-
-#if HAVE_LIBGCRYPT
-static int network_config_set_string (const oconfig_item_t *ci, /* {{{ */
- char **ret_string)
-{
- char *tmp;
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("network plugin: The `%s' config option needs exactly "
- "one string argument.", ci->key);
+ else {
+ WARNING ("network plugin: The `MaxPacketSize' must be between 1024 and 65535.");
return (-1);
}
- tmp = strdup (ci->values[0].value.string);
- if (tmp == NULL)
- return (-1);
-
- sfree (*ret_string);
- *ret_string = tmp;
-
return (0);
-} /* }}} int network_config_set_string */
-#endif /* HAVE_LIBGCRYPT */
+} /* }}} int network_config_set_buffer_size */
#if HAVE_LIBGCRYPT
static int network_config_set_security_level (oconfig_item_t *ci, /* {{{ */
#if HAVE_LIBGCRYPT
if (strcasecmp ("AuthFile", child->key) == 0)
- network_config_set_string (child, &se->data.server.auth_file);
+ cf_util_get_string (child, &se->data.server.auth_file);
else if (strcasecmp ("SecurityLevel", child->key) == 0)
network_config_set_security_level (child,
&se->data.server.security_level);
else
#endif /* HAVE_LIBGCRYPT */
if (strcasecmp ("Interface", child->key) == 0)
- network_config_set_interface (child,
- &se->interface);
+ network_config_set_interface (child, &se->interface);
else
{
WARNING ("network plugin: Option `%s' is not allowed here.",
status = sockent_server_listen (se);
if (status != 0)
{
- ERROR ("network plugin: network_config_add_server: sockent_server_listen failed.");
+ ERROR ("network plugin: network_config_add_listen: sockent_server_listen failed.");
sockent_destroy (se);
return (-1);
}
#if HAVE_LIBGCRYPT
if (strcasecmp ("Username", child->key) == 0)
- network_config_set_string (child, &se->data.client.username);
+ cf_util_get_string (child, &se->data.client.username);
else if (strcasecmp ("Password", child->key) == 0)
- network_config_set_string (child, &se->data.client.password);
+ cf_util_get_string (child, &se->data.client.password);
else if (strcasecmp ("SecurityLevel", child->key) == 0)
network_config_set_security_level (child,
&se->data.client.security_level);
else
#endif /* HAVE_LIBGCRYPT */
if (strcasecmp ("Interface", child->key) == 0)
- network_config_set_interface (child,
- &se->interface);
- else if (strcasecmp ("ResolveInterval", child->key) == 0)
- cf_util_get_cdtime(child, &se->data.client.resolve_interval);
+ network_config_set_interface (child, &se->interface);
+ else if (strcasecmp ("ResolveInterval", child->key) == 0)
+ cf_util_get_cdtime(child, &se->data.client.resolve_interval);
else
{
WARNING ("network plugin: Option `%s' is not allowed here.",
else if (strcasecmp ("MaxPacketSize", child->key) == 0)
network_config_set_buffer_size (child);
else if (strcasecmp ("Forward", child->key) == 0)
- network_config_set_boolean (child, &network_config_forward);
+ cf_util_get_boolean (child, &network_config_forward);
else if (strcasecmp ("ReportStats", child->key) == 0)
- network_config_set_boolean (child, &network_config_stats);
+ cf_util_get_boolean (child, &network_config_stats);
else
{
WARNING ("network plugin: Option `%s' is not allowed here.",
network_init_gcrypt ();
#endif
- if (network_config_stats != 0)
+ if (network_config_stats)
plugin_register_read ("network", network_stats_read);
plugin_register_shutdown ("network", network_shutdown);
* just send the buffer if `flush' is called - if the requested value was in
* there, good. If not, well, then there is nothing to flush.. -octo
*/
-static int network_flush (__attribute__((unused)) cdtime_t timeout,
+static int network_flush (cdtime_t timeout,
__attribute__((unused)) const char *identifier,
__attribute__((unused)) user_data_t *user_data)
{
pthread_mutex_lock (&send_buffer_lock);
if (send_buffer_fill > 0)
- flush_buffer ();
-
+ {
+ if (timeout > 0)
+ {
+ cdtime_t now = cdtime ();
+ if ((send_buffer_last_update + timeout) > now)
+ {
+ pthread_mutex_unlock (&send_buffer_lock);
+ return (0);
+ }
+ }
+ flush_buffer ();
+ }
pthread_mutex_unlock (&send_buffer_lock);
return (0);
diff --git a/src/nfs.c b/src/nfs.c
index be823720b489ec3ddd8f1f75d7976b28469fd5ab..a921a1774d9cdcc1a0fa95fbfb44c77f17077a77 100644 (file)
--- a/src/nfs.c
+++ b/src/nfs.c
return (0);
}
-static void nfs_read_linux (FILE *fh, char *inst)
+static void nfs_read_linux (FILE *fh, const char *inst)
{
char buffer[1024];
#endif /* KERNEL_LINUX */
#if HAVE_LIBKSTAT
-static int nfs_read_kstat (kstat_t *ksp, int nfs_version, char *inst,
+static int nfs_read_kstat (kstat_t *ksp, int nfs_version, const char *inst,
char const **proc_names, size_t proc_names_num)
{
char plugin_instance[DATA_MAX_NAME_LEN];
diff --git a/src/nginx.c b/src/nginx.c
index 4e4ce3bbc6115572873668a76507f80ccd82b316..e493cc941560c35b50d684c24cd0ca0edca0dbff 100644 (file)
--- a/src/nginx.c
+++ b/src/nginx.c
}
else
{
- curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
}
#endif
return (0);
} /* void init */
-static void submit (char *type, char *inst, long long value)
+static void submit (const char *type, const char *inst, long long value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
diff --git a/src/notify_nagios.c b/src/notify_nagios.c
--- /dev/null
+++ b/src/notify_nagios.c
@@ -0,0 +1,170 @@
+/**
+ * collectd - src/notify_nagios.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "configfile.h"
+
+#define NAGIOS_OK 0
+#define NAGIOS_WARNING 1
+#define NAGIOS_CRITICAL 2
+#define NAGIOS_UNKNOWN 3
+
+#ifndef NAGIOS_COMMAND_FILE
+# define NAGIOS_COMMAND_FILE "/usr/local/nagios/var/rw/nagios.cmd"
+#endif
+
+static char *nagios_command_file;
+
+static int nagios_config (oconfig_item_t *ci) /* {{{ */
+{
+ int i;
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp ("CommandFile", child->key) == 0)
+ cf_util_get_string (child, &nagios_command_file);
+ else
+ WARNING ("notify_nagios plugin: Ignoring unknown config option \"%s\".",
+ child->key);
+ }
+
+ return 0;
+} /* }}} nagios_config */
+
+static int nagios_print (char const *buffer) /* {{{ */
+{
+ char const *file = NAGIOS_COMMAND_FILE;
+ int fd;
+ int status;
+ struct flock lock;
+
+ if (nagios_command_file != NULL)
+ file = nagios_command_file;
+
+ fd = open (file, O_WRONLY | O_APPEND);
+ if (fd < 0)
+ {
+ char errbuf[1024];
+ status = errno;
+ ERROR ("notify_nagios plugin: Opening \"%s\" failed: %s",
+ file, sstrerror (status, errbuf, sizeof (errbuf)));
+ return status;
+ }
+
+ memset (&lock, 0, sizeof (lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_END;
+ lock.l_start = 0;
+ lock.l_len = 0; /* to end of file */
+
+ status = fcntl (fd, F_GETLK, &lock);
+ if (status != 0)
+ {
+ char errbuf[1024];
+ status = errno;
+ ERROR ("notify_nagios plugin: Failed to acquire write lock on \"%s\": %s",
+ file, sstrerror (status, errbuf, sizeof (errbuf)));
+ close (fd);
+ return status;
+ }
+
+ status = (int) lseek (fd, 0, SEEK_END);
+ if (status == -1)
+ {
+ char errbuf[1024];
+ status = errno;
+ ERROR ("notify_nagios plugin: Seeking to end of \"%s\" failed: %s",
+ file, sstrerror (status, errbuf, sizeof (errbuf)));
+ close (fd);
+ return status;
+ }
+
+ status = (int) swrite (fd, buffer, strlen (buffer));
+ if (status != 0)
+ {
+ char errbuf[1024];
+ status = errno;
+ ERROR ("notify_nagios plugin: Writing to \"%s\" failed: %s",
+ file, sstrerror (status, errbuf, sizeof (errbuf)));
+ close (fd);
+ return status;
+ }
+
+ close (fd);
+ return status;
+} /* }}} int nagios_print */
+
+static int nagios_notify (const notification_t *n, /* {{{ */
+ __attribute__((unused)) user_data_t *user_data)
+{
+ char svc_description[4 * DATA_MAX_NAME_LEN];
+ char buffer[4096];
+ int code;
+ int status;
+
+ status = format_name (svc_description, (int) sizeof (svc_description),
+ /* host */ "", n->plugin, n->plugin_instance, n->type, n->type_instance);
+ if (status != 0)
+ {
+ ERROR ("notify_nagios plugin: Formatting service name failed.");
+ return status;
+ }
+
+ switch (n->severity)
+ {
+ case NOTIF_OKAY:
+ code = NAGIOS_OK;
+ break;
+ case NOTIF_WARNING:
+ code = NAGIOS_WARNING;
+ break;
+ case NOTIF_FAILURE:
+ code = NAGIOS_CRITICAL;
+ break;
+ default:
+ code = NAGIOS_UNKNOWN;
+ break;
+ }
+
+ ssnprintf (buffer, sizeof (buffer),
+ "[%.0f] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",
+ CDTIME_T_TO_DOUBLE (n->time), n->host, &svc_description[1], code,
+ n->message);
+
+ return nagios_print (buffer);
+} /* }}} int nagios_notify */
+
+void module_register (void)
+{
+ plugin_register_complex_config ("notify_nagios", nagios_config);
+ plugin_register_notification ("notify_nagios", nagios_notify, NULL);
+} /* void module_register (void) */
+
+/* vim: set sw=2 sts=2 ts=8 et : */
diff --git a/src/ntpd.c b/src/ntpd.c
index ce54e029e7124c673cddcc9a6293ded9e71e9bf7..4a31e455eece36ad595f8bbc41ac7ee6985c35e7 100644 (file)
--- a/src/ntpd.c
+++ b/src/ntpd.c
#if HAVE_NETDB_H
# include <netdb.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
};
/* List of reference clock names */
-static char *refclock_names[] =
+static const char *refclock_names[] =
{
"UNKNOWN", "LOCAL", "GPS_TRAK", "WWV_PST", /* 0- 3 */
"SPECTRACOM", "TRUETIME", "IRIG_AUDIO", "CHU_AUDIO", /* 4- 7 */
"JJY", "TT_IRIG", "GPS_ZYFER", "GPS_RIPENCC", /* 40-43 */
"NEOCLK4X" /* 44 */
};
-static int refclock_names_num = STATIC_ARRAY_SIZE (refclock_names);
+static size_t refclock_names_num = STATIC_ARRAY_SIZE (refclock_names);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* End of the copied stuff.. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
return (0);
}
-static void ntpd_submit (char *type, char *type_inst, gauge_t value)
+static void ntpd_submit (const char *type, const char *type_inst, gauge_t value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
/* Each time a peer is polled, ntpd shifts the reach register to the left and
* sets the LSB based on whether the peer was reachable. If the LSB is zero,
* the values are out of date. */
-static void ntpd_submit_reach (char *type, char *type_inst, uint8_t reach,
- gauge_t value)
+static void ntpd_submit_reach (const char *type, const char *type_inst,
+ uint8_t reach, gauge_t value)
{
if (!(reach & 1))
value = NAN;
static int ntpd_connect (void)
{
- char *host;
- char *port;
+ const char *host;
+ const char *port;
struct addrinfo ai_hints;
struct addrinfo *ai_list;
uint32_t refclock_id = ntpd_get_refclock_id (peer_info);
uint32_t unit_id = ntohl (peer_info->srcadr) & 0x00FF;
- if (refclock_id >= refclock_names_num)
+ if (((size_t) refclock_id) >= refclock_names_num)
return (ntpd_get_name_from_address (buffer, buffer_size,
peer_info,
/* do_reverse_lookup = */ 0));
diff --git a/src/olsrd.c b/src/olsrd.c
index 6d0576cf7bc7d26e39567646f40fa1ebd49262cc..bbf387f4123dfe12a375ca85b234fd315843e385 100644 (file)
--- a/src/olsrd.c
+++ b/src/olsrd.c
#include <sys/types.h>
#include <netdb.h>
-#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
diff --git a/src/onewire.c b/src/onewire.c
index 51e6407137b0f2c8bc64598f822cac804c5a9fab..3c441ecb3493791d4d650b7667f3d355ccdf9109 100644 (file)
--- a/src/onewire.c
+++ b/src/onewire.c
int status;
status = ssnprintf (subpath, sizeof (subpath), "%s/main", path);
- if ((status > 0) && (status < sizeof (subpath)))
+ if ((status > 0) && (status < (int) sizeof (subpath)))
cow_read_bus (subpath);
status = ssnprintf (subpath, sizeof (subpath), "%s/aux", path);
- if ((status > 0) && (status < sizeof (subpath)))
+ if ((status > 0) && (status < (int) sizeof (subpath)))
cow_read_bus (subpath);
return (0);
else
status = ssnprintf (subpath, sizeof (subpath), "%s/%s",
path, buffer_ptr);
- if ((status <= 0) || (status >= sizeof (subpath)))
+ if ((status <= 0) || (status >= (int) sizeof (subpath)))
continue;
for (i = 0; i < ow_family_features_num; i++)
static int cow_init (void)
{
int status;
- struct timespec cb_interval;
if (device_g == NULL)
{
return (1);
}
- CDTIME_T_TO_TIMESPEC (ow_interval, &cb_interval);
-
plugin_register_complex_read (/* group = */ NULL, "onewire", cow_read,
- (ow_interval != 0) ? &cb_interval : NULL,
- /* user data = */ NULL);
+ ow_interval, /* user data = */ NULL);
plugin_register_shutdown ("onewire", cow_shutdown);
return (0);
diff --git a/src/openldap.c b/src/openldap.c
index bd79b26b7312bf076c95a247f9d3331688e5f550..0a86d521e508158ebd97b8a84bfe67568e927b23 100644 (file)
--- a/src/openldap.c
+++ b/src/openldap.c
{
char *name;
+ char *binddn;
+ char *password;
char *cacert;
char *host;
int state;
if (st == NULL)
return;
+ sfree (st->binddn);
+ sfree (st->password);
sfree (st->cacert);
sfree (st->host);
sfree (st->name);
}
struct berval cred;
- cred.bv_val = "";
- cred.bv_len = 0;
+ if (st->password != NULL)
+ {
+ cred.bv_val = st->password;
+ cred.bv_len = strlen (st->password);
+ }
+ else
+ {
+ cred.bv_val = "";
+ cred.bv_len = 0;
+ }
- rc = ldap_sasl_bind_s (st->ld, NULL, NULL, &cred, NULL, NULL, NULL);
+ rc = ldap_sasl_bind_s (st->ld, st->binddn, LDAP_SASL_SIMPLE, &cred,
+ NULL, NULL, NULL);
if (rc != LDAP_SUCCESS)
{
ERROR ("openldap plugin: Failed to bind to %s: %s",
{
oconfig_item_t *child = ci->children + i;
- if (strcasecmp ("CACert", child->key) == 0)
+ if (strcasecmp ("BindDN", child->key) == 0)
+ status = cf_util_get_string (child, &st->binddn);
+ else if (strcasecmp ("Password", child->key) == 0)
+ status = cf_util_get_string (child, &st->password);
+ else if (strcasecmp ("CACert", child->key) == 0)
status = cf_util_get_string (child, &st->cacert);
else if (strcasecmp ("StartTLS", child->key) == 0)
status = cf_util_get_boolean (child, &st->starttls);
status = plugin_register_complex_read (/* group = */ NULL,
/* name = */ callback_name,
/* callback = */ cldap_read_host,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user_data = */ &ud);
}
diff --git a/src/openvpn.c b/src/openvpn.c
index 93c8f1b58363fbf8f7a27f4f03a5b4077f74fee8..8bccce3883a88664598416dbc5a7e0c676c9a051 100644 (file)
--- a/src/openvpn.c
+++ b/src/openvpn.c
} /* int openvpn_strsplit */
/* dispatches number of users */
-static void numusers_submit (char *pinst, char *tinst, gauge_t value)
+static void numusers_submit (const char *pinst, const char *tinst,
+ gauge_t value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
plugin_dispatch_values (&vl);
} /* void numusers_submit */
-/* dispatches stats about traffic (TCP or UDP) generated by the tunnel per single endpoint */
-static void iostats_submit (char *pinst, char *tinst, derive_t rx, derive_t tx)
+/* dispatches stats about traffic (TCP or UDP) generated by the tunnel
+ * per single endpoint */
+static void iostats_submit (const char *pinst, const char *tinst,
+ derive_t rx, derive_t tx)
{
value_t values[2];
value_list_t vl = VALUE_LIST_INIT;
} /* void traffic_submit */
/* dispatches stats about data compression shown when in single mode */
-static void compression_submit (char *pinst, char *tinst,
+static void compression_submit (const char *pinst, const char *tinst,
derive_t uncompressed, derive_t compressed)
{
value_t values[2];
plugin_dispatch_values (&vl);
} /* void compression_submit */
-static int single_read (char *name, FILE *fh)
+static int single_read (const char *name, FILE *fh)
{
char buffer[1024];
char *fields[4];
} /* int single_read */
/* for reading status version 1 */
-static int multi1_read (char *name, FILE *fh)
+static int multi1_read (const char *name, FILE *fh)
{
char buffer[1024];
char *fields[10];
} /* int multi1_read */
/* for reading status version 2 */
-static int multi2_read (char *name, FILE *fh)
+static int multi2_read (const char *name, FILE *fh)
{
char buffer[1024];
char *fields[10];
} /* int multi2_read */
/* for reading status version 3 */
-static int multi3_read (char *name, FILE *fh)
+static int multi3_read (const char *name, FILE *fh)
{
char buffer[1024];
char *fields[15];
} /* int multi3_read */
/* for reading status version 4 */
-static int multi4_read (char *name, FILE *fh)
+static int multi4_read (const char *name, FILE *fh)
{
char buffer[1024];
char *fields[11];
diff --git a/src/perl.c b/src/perl.c
index 19ac08d4274156c168a1c2f0bd7a8d461a55acfc..c25bfe897870a8a83457c1c60e91b59c6767aa3e 100644 (file)
--- a/src/perl.c
+++ b/src/perl.c
return 0;
} /* static int hv2data_source (HV *, data_source_t *) */
-static int av2value (pTHX_ char *name, AV *array, value_t *value, int len)
+/* av2value converts at most "len" elements from "array" to "value". Returns the
+ * number of elements converted or zero on error. */
+static size_t av2value (pTHX_ char *name, AV *array, value_t *value, size_t array_len)
{
const data_set_t *ds;
+ size_t i;
- int i = 0;
-
- if ((NULL == name) || (NULL == array) || (NULL == value))
- return -1;
-
- if (av_len (array) < len - 1)
- len = av_len (array) + 1;
-
- if (0 >= len)
- return -1;
+ if ((NULL == name) || (NULL == array) || (NULL == value) || (array_len == 0))
+ return 0;
ds = plugin_get_ds (name);
if (NULL == ds) {
log_err ("av2value: Unknown dataset \"%s\"", name);
- return -1;
+ return 0;
}
- if (ds->ds_num < len) {
- log_warn ("av2value: Value length exceeds data set length.");
- len = ds->ds_num;
+ if (array_len < ds->ds_num) {
+ log_warn ("av2value: array does not contain enough elements for type \"%s\": got %zu, want %zu",
+ name, array_len, ds->ds_num);
+ return 0;
+ } else if (array_len > ds->ds_num) {
+ log_warn ("av2value: array contains excess elements for type \"%s\": got %zu, want %zu",
+ name, array_len, ds->ds_num);
}
- for (i = 0; i < len; ++i) {
+ for (i = 0; i < ds->ds_num; ++i) {
SV **tmp = av_fetch (array, i, 0);
if (NULL != tmp) {
value[i].absolute = SvIV (*tmp);
}
else {
- return -1;
+ return 0;
}
}
- return len;
-} /* static int av2value (char *, AV *, value_t *, int) */
+
+ return ds->ds_num;
+} /* static size_t av2value (char *, AV *, value_t *, size_t) */
/*
* value list:
{
AV *array = (AV *)SvRV (*tmp);
- int len = av_len (array) + 1;
-
- if (len <= 0)
+ /* av_len returns the highest index, not the actual length. */
+ size_t array_len = (size_t) (av_len (array) + 1);
+ if (array_len == 0)
return -1;
- vl->values = (value_t *)smalloc (len * sizeof (value_t));
- vl->values_len = av2value (aTHX_ vl->type, (AV *)SvRV (*tmp),
- vl->values, len);
-
- if (-1 == vl->values_len) {
+ vl->values = calloc (array_len, sizeof (*vl->values));
+ vl->values_len = av2value (aTHX_ vl->type, (AV *)SvRV (*tmp), vl->values, array_len);
+ if (vl->values_len == 0) {
sfree (vl->values);
return -1;
}
static int data_set2av (pTHX_ data_set_t *ds, AV *array)
{
- int i = 0;
+ size_t i;
if ((NULL == ds) || (NULL == array))
return -1;
static int value_list2hv (pTHX_ value_list_t *vl, data_set_t *ds, HV *hash)
{
AV *values = NULL;
-
- int i = 0;
- int len = 0;
+ size_t i;
if ((NULL == vl) || (NULL == ds) || (NULL == hash))
return -1;
- len = vl->values_len;
-
- if (ds->ds_num < len) {
- log_warn ("value2av: Value length exceeds data set length.");
- len = ds->ds_num;
- }
-
values = newAV ();
- av_extend (values, len - 1);
+ /* av_extend takes the last *index* to which the array should be extended. */
+ av_extend (values, vl->values_len - 1);
- for (i = 0; i < len; ++i) {
+ assert (ds->ds_num == vl->values_len);
+ for (i = 0; i < vl->values_len; ++i) {
SV *val = NULL;
if (DS_TYPE_COUNTER == ds->ds[i].type)
diff --git a/src/pf.c b/src/pf.c
index 112e28f3554dee66efb5dd5dcd3fb15843ad4e85..a2bd5499916d735a3ec8143e93c8d79caa3485cf 100644 (file)
--- a/src/pf.c
+++ b/src/pf.c
#if HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NET_IF_H
# include <net/if.h>
#endif
diff --git a/src/pinba.c b/src/pinba.c
index e94ad8f61b667b0728085bff1c5a7129f9dcd802..d13d047b208aaab564889c4c3c24b570f2c92a68 100644 (file)
--- a/src/pinba.c
+++ b/src/pinba.c
#include "configfile.h"
#include <pthread.h>
-#include <sys/socket.h>
#include <netdb.h>
#include <poll.h>
diff --git a/src/ping.c b/src/ping.c
index c97571b85c066c695fd66369269b6035bba00097..da63d3a58c7bb9707b0b0d5763f0ee579b2c4dd5 100644 (file)
--- a/src/ping.c
+++ b/src/ping.c
#ifdef HAVE_OPING_1_3
static char *ping_device = NULL;
#endif
+static char *ping_data = NULL;
static int ping_ttl = PING_DEF_TTL;
static double ping_interval = 1.0;
static double ping_timeout = 0.9;
#ifdef HAVE_OPING_1_3
"Device",
#endif
+ "Size",
"TTL",
"Interval",
"Timeout",
hl->pkg_missed++;
/* if the host did not answer our last N packages, trigger a resolv. */
- if (ping_max_missed >= 0 && hl->pkg_missed >= ping_max_missed)
+ if ((ping_max_missed >= 0)
+ && (hl->pkg_missed >= ((uint32_t) ping_max_missed)))
{ /* {{{ */
/* we reset the missed package counter here, since we only want to
* trigger a resolv every N packages and not every package _AFTER_ N
ping_setopt (pingobj, PING_OPT_TIMEOUT, (void *) &ping_timeout);
ping_setopt (pingobj, PING_OPT_TTL, (void *) &ping_ttl);
+ if (ping_data != NULL)
+ ping_setopt (pingobj, PING_OPT_DATA, (void *) ping_data);
+
/* Add all the hosts to the ping object. */
count = 0;
for (hl = hostlist_head; hl != NULL; hl = hl->next)
WARNING ("ping plugin: Ignoring invalid interval %g (%s)",
tmp, value);
}
+ else if (strcasecmp (key, "Size") == 0) {
+ size_t size = (size_t) atoi (value);
+
+ /* Max IP packet size - (IPv6 + ICMP) = 65535 - (40 + 8) = 65487 */
+ if (size <= 65487)
+ {
+ size_t i;
+
+ sfree (ping_data);
+ ping_data = malloc (size + 1);
+ if (ping_data == NULL)
+ {
+ ERROR ("ping plugin: malloc failed.");
+ return (1);
+ }
+
+ /* Note: By default oping is using constant string
+ * "liboping -- ICMP ping library <http://octo.it/liboping/>"
+ * which is exactly 56 bytes.
+ *
+ * Optimally we would follow the ping(1) behaviour, but we
+ * cannot use byte 00 or start data payload at exactly same
+ * location, due to oping library limitations. */
+ for (i = 0; i < size; i++) /* {{{ */
+ {
+ /* This restricts data pattern to be only composed of easily
+ * printable characters, and not NUL character. */
+ ping_data[i] = ('0' + i % 64);
+ } /* }}} for (i = 0; i < size; i++) */
+ ping_data[size] = 0;
+ } else
+ WARNING ("ping plugin: Ignoring invalid Size %zu.", size);
+ }
else if (strcasecmp (key, "Timeout") == 0)
{
double tmp;
hl = hl_next;
}
+ if (ping_data != NULL) {
+ free (ping_data);
+ ping_data = NULL;
+ }
+
return (0);
} /* }}} int ping_shutdown */
diff --git a/src/postgresql.c b/src/postgresql.c
index 23c4af31e0909de86cb135fba2d8d3c41c9f33ca..79226830cb810c68579852165c889a3b176731e2 100644 (file)
--- a/src/postgresql.c
+++ b/src/postgresql.c
int ref_cnt;
} c_psql_database_t;
-static char *def_queries[] = {
+static const char *const def_queries[] = {
"backends",
"transactions",
"queries",
static PGresult *c_psql_exec_query_params (c_psql_database_t *db,
udb_query_t *q, c_psql_user_data_t *data)
{
- char *params[db->max_params_num];
- char interval[64];
- int i;
+ const char *params[db->max_params_num];
+ char interval[64];
+ int i;
if ((data == NULL) || (data->params_num == 0))
return (c_psql_exec_query_noparams (db, q));
c_psql_database_t *db;
int success = 0;
- int i;
+ size_t i;
if ((ud == NULL) || (ud->data == NULL)) {
log_err ("c_psql_read: Invalid user data.");
{
char *str_ptr;
size_t str_len;
-
- int i;
+ size_t i;
str_ptr = string;
str_len = string_len;
{
char *str_ptr;
size_t str_len;
-
- int i;
+ size_t i;
str_ptr = string;
str_len = string_len;
size_t str_len;
gauge_t *rates = NULL;
-
- int i;
+ size_t i;
str_ptr = string;
str_len = string_len;
{
c_psql_database_t *db;
- char time_str[32];
+ char time_str[RFC3339NANO_SIZE];
char values_name_str[1024];
char values_type_str[1024];
char values_str[1024];
const char *params[9];
int success = 0;
- int i;
+ size_t i;
if ((ud == NULL) || (ud->data == NULL)) {
log_err ("c_psql_write: Invalid user data.");
assert (db->database != NULL);
assert (db->writers != NULL);
- if (cdtime_to_iso8601 (time_str, sizeof (time_str), vl->time) == 0) {
- log_err ("c_psql_write: Failed to convert time to ISO 8601 format");
+ if (rfc3339nano (time_str, sizeof (time_str), vl->time) != 0) {
+ log_err ("c_psql_write: Failed to convert time to RFC 3339 format");
return -1;
}
c_psql_database_t *db;
char cb_name[DATA_MAX_NAME_LEN];
- struct timespec cb_interval = { 0, 0 };
user_data_t ud;
static _Bool have_flush = 0;
ssnprintf (cb_name, sizeof (cb_name), "postgresql-%s", db->instance);
if (db->queries_num > 0) {
- CDTIME_T_TO_TIMESPEC (db->interval, &cb_interval);
-
++db->ref_cnt;
plugin_register_complex_read ("postgresql", cb_name, c_psql_read,
- /* interval = */ (db->interval > 0) ? &cb_interval : NULL,
- &ud);
+ /* interval = */ db->interval, &ud);
}
if (db->writers_num > 0) {
++db->ref_cnt;
diff --git a/src/powerdns.c b/src/powerdns.c
index c9e9359acca8adec99e8a5fbbcdd04dc5d708929..ab62dcfdd646ef43077eeb9ce7ac5d17c789fcf7 100644 (file)
--- a/src/powerdns.c
+++ b/src/powerdns.c
#include <string.h>
#include <errno.h>
#include <sys/types.h>
-#include <sys/socket.h>
#include <sys/un.h>
#ifndef UNIX_PATH_MAX
struct statname_lookup_s
{
- char *name;
- char *type;
- char *type_instance;
+ const char *name;
+ const char *type;
+ const char *type_instance;
};
typedef struct statname_lookup_s statname_lookup_t;
/* Description of statistics returned by the recursor: {{{
-all-outqueries counts the number of outgoing UDP queries since starting
-answers0-1 counts the number of queries answered within 1 millisecond
-answers100-1000 counts the number of queries answered within 1 second
-answers10-100 counts the number of queries answered within 100 milliseconds
-answers1-10 counts the number of queries answered within 10 milliseconds
-answers-slow counts the number of queries answered after 1 second
-cache-entries shows the number of entries in the cache
-cache-hits counts the number of cache hits since starting
-cache-misses counts the number of cache misses since starting
-chain-resends number of queries chained to existing outstanding query
-client-parse-errors counts number of client packets that could not be parsed
-concurrent-queries shows the number of MThreads currently running
-dlg-only-drops number of records dropped because of delegation only setting
-negcache-entries shows the number of entries in the Negative answer cache
-noerror-answers counts the number of times it answered NOERROR since starting
-nsspeeds-entries shows the number of entries in the NS speeds map
-nsset-invalidations number of times an nsset was dropped because it no longer worked
-nxdomain-answers counts the number of times it answered NXDOMAIN since starting
-outgoing-timeouts counts the number of timeouts on outgoing UDP queries since starting
-qa-latency shows the current latency average
-questions counts all End-user initiated queries with the RD bit set
-resource-limits counts number of queries that could not be performed because of resource limits
-server-parse-errors counts number of server replied packets that could not be parsed
-servfail-answers counts the number of times it answered SERVFAIL since starting
-spoof-prevents number of times PowerDNS considered itself spoofed, and dropped the data
-sys-msec number of CPU milliseconds spent in 'system' mode
-tcp-client-overflow number of times an IP address was denied TCP access because it already had too many connections
-tcp-outqueries counts the number of outgoing TCP queries since starting
-tcp-questions counts all incoming TCP queries (since starting)
-throttled-out counts the number of throttled outgoing UDP queries since starting
-throttle-entries shows the number of entries in the throttle map
-unauthorized-tcp number of TCP questions denied because of allow-from restrictions
-unauthorized-udp number of UDP questions denied because of allow-from restrictions
-unexpected-packets number of answers from remote servers that were unexpected (might point to spoofing)
-uptime number of seconds process has been running (since 3.1.5)
-user-msec number of CPU milliseconds spent in 'user' mode
+all-outqueries counts the number of outgoing UDP queries since starting
+answers-slow counts the number of queries answered after 1 second
+answers0-1 counts the number of queries answered within 1 millisecond
+answers1-10 counts the number of queries answered within 10 milliseconds
+answers10-100 counts the number of queries answered within 100 milliseconds
+answers100-1000 counts the number of queries answered within 1 second
+cache-bytes size of the cache in bytes (since 3.3.1)
+cache-entries shows the number of entries in the cache
+cache-hits counts the number of cache hits since starting, this does not include hits that got answered from the packet-cache
+cache-misses counts the number of cache misses since starting
+case-mismatches counts the number of mismatches in character case since starting
+chain-resends number of queries chained to existing outstanding query
+client-parse-errors counts number of client packets that could not be parsed
+concurrent-queries shows the number of MThreads currently running
+dlg-only-drops number of records dropped because of delegation only setting
+dont-outqueries number of outgoing queries dropped because of 'dont-query' setting (since 3.3)
+edns-ping-matches number of servers that sent a valid EDNS PING respons
+edns-ping-mismatches number of servers that sent an invalid EDNS PING response
+failed-host-entries number of servers that failed to resolve
+ipv6-outqueries number of outgoing queries over IPv6
+ipv6-questions counts all End-user initiated queries with the RD bit set, received over IPv6 UDP
+malloc-bytes returns the number of bytes allocated by the process (broken, always returns 0)
+max-mthread-stack maximum amount of thread stack ever used
+negcache-entries shows the number of entries in the Negative answer cache
+no-packet-error number of errorneous received packets
+noedns-outqueries number of queries sent out without EDNS
+noerror-answers counts the number of times it answered NOERROR since starting
+noping-outqueries number of queries sent out without ENDS PING
+nsset-invalidations number of times an nsset was dropped because it no longer worked
+nsspeeds-entries shows the number of entries in the NS speeds map
+nxdomain-answers counts the number of times it answered NXDOMAIN since starting
+outgoing-timeouts counts the number of timeouts on outgoing UDP queries since starting
+over-capacity-drops questions dropped because over maximum concurrent query limit (since 3.2)
+packetcache-bytes size of the packet cache in bytes (since 3.3.1)
+packetcache-entries size of packet cache (since 3.2)
+packetcache-hits packet cache hits (since 3.2)
+packetcache-misses packet cache misses (since 3.2)
+policy-drops packets dropped because of (Lua) policy decision
+qa-latency shows the current latency average
+questions counts all end-user initiated queries with the RD bit set
+resource-limits counts number of queries that could not be performed because of resource limits
+security-status security status based on security polling
+server-parse-errors counts number of server replied packets that could not be parsed
+servfail-answers counts the number of times it answered SERVFAIL since starting
+spoof-prevents number of times PowerDNS considered itself spoofed, and dropped the data
+sys-msec number of CPU milliseconds spent in 'system' mode
+tcp-client-overflow number of times an IP address was denied TCP access because it already had too many connections
+tcp-clients counts the number of currently active TCP/IP clients
+tcp-outqueries counts the number of outgoing TCP queries since starting
+tcp-questions counts all incoming TCP queries (since starting)
+throttle-entries shows the number of entries in the throttle map
+throttled-out counts the number of throttled outgoing UDP queries since starting
+throttled-outqueries idem to throttled-out
+unauthorized-tcp number of TCP questions denied because of allow-from restrictions
+unauthorized-udp number of UDP questions denied because of allow-from restrictions
+unexpected-packets number of answers from remote servers that were unexpected (might point to spoofing)
+unreachables number of times nameservers were unreachable since starting
+uptime number of seconds process has been running (since 3.1.5)
+user-msec number of CPU milliseconds spent in 'user' mode
}}} */
-const char* const default_server_fields[] = /* {{{ */
+static const char* const default_server_fields[] = /* {{{ */
{
"latency",
"packetcache-hit",
"udp-answers",
"udp-queries",
}; /* }}} */
-int default_server_fields_num = STATIC_ARRAY_SIZE (default_server_fields);
+static int default_server_fields_num = STATIC_ARRAY_SIZE (default_server_fields);
-statname_lookup_t lookup_table[] = /* {{{ */
+static statname_lookup_t lookup_table[] = /* {{{ */
{
/*********************
* Server statistics *
{"udp-answers-bytes", "total_bytes", "udp-answers-bytes"},
/* Cache stuff */
+ {"cache-bytes", "cache_size", "cache-bytes"},
+ {"packetcache-bytes", "cache_size", "packet-bytes"},
+ {"packetcache-entries", "cache_size", "packet-entries"},
{"packetcache-hit", "cache_result", "packet-hit"},
+ {"packetcache-hits", "cache_result", "packet-hit"},
{"packetcache-miss", "cache_result", "packet-miss"},
+ {"packetcache-misses", "cache_result", "packet-miss"},
{"packetcache-size", "cache_size", "packet"},
{"key-cache-size", "cache_size", "key"},
{"meta-cache-size", "cache_size", "meta"},
{"corrupt-packets", "ipt_packets", "corrupt"},
{"deferred-cache-inserts", "counter", "cache-deferred_insert"},
{"deferred-cache-lookup", "counter", "cache-deferred_lookup"},
+ {"dont-outqueries", "dns_question", "dont-outqueries"},
{"qsize-a", "cache_size", "answers"},
{"qsize-q", "cache_size", "questions"},
{"servfail-packets", "ipt_packets", "servfail"},
* Recursor statistics *
***********************/
/* Answers by return code */
- {"noerror-answers", "dns_rcode", "NOERROR"},
- {"nxdomain-answers", "dns_rcode", "NXDOMAIN"},
- {"servfail-answers", "dns_rcode", "SERVFAIL"},
+ {"noerror-answers", "dns_rcode", "NOERROR"},
+ {"nxdomain-answers", "dns_rcode", "NXDOMAIN"},
+ {"servfail-answers", "dns_rcode", "SERVFAIL"},
/* CPU utilization */
- {"sys-msec", "cpu", "system"},
- {"user-msec", "cpu", "user"},
+ {"sys-msec", "cpu", "system"},
+ {"user-msec", "cpu", "user"},
/* Question-to-answer latency */
- {"qa-latency", "latency", NULL},
+ {"qa-latency", "latency", NULL},
/* Cache */
- {"cache-entries", "cache_size", NULL},
- {"cache-hits", "cache_result", "hit"},
- {"cache-misses", "cache_result", "miss"},
+ {"cache-entries", "cache_size", NULL},
+ {"cache-hits", "cache_result", "hit"},
+ {"cache-misses", "cache_result", "miss"},
/* Total number of questions.. */
- {"questions", "dns_qtype", "total"},
+ {"questions", "dns_qtype", "total"},
/* All the other stuff.. */
- {"all-outqueries", "dns_question", "outgoing"},
- {"answers0-1", "dns_answer", "0_1"},
- {"answers1-10", "dns_answer", "1_10"},
- {"answers10-100", "dns_answer", "10_100"},
- {"answers100-1000", "dns_answer", "100_1000"},
- {"answers-slow", "dns_answer", "slow"},
- {"chain-resends", "dns_question", "chained"},
- {"client-parse-errors", "counter", "drops-client_parse_error"},
- {"concurrent-queries", "dns_question", "concurrent"},
- {"dlg-only-drops", "counter", "drops-delegation_only"},
- {"negcache-entries", "cache_size", "negative"},
- {"nsspeeds-entries", "gauge", "entries-ns_speeds"},
- {"nsset-invalidations", "counter", "ns_set_invalidation"},
- {"outgoing-timeouts", "counter", "drops-timeout_outgoing"},
- {"resource-limits", "counter", "drops-resource_limit"},
- {"server-parse-errors", "counter", "drops-server_parse_error"},
- {"spoof-prevents", "counter", "drops-spoofed"},
- {"tcp-client-overflow", "counter", "denied-client_overflow_tcp"},
- {"tcp-outqueries", "dns_question", "outgoing-tcp"},
- {"tcp-questions", "dns_question", "incoming-tcp"},
- {"throttled-out", "dns_question", "outgoing-throttled"},
- {"throttle-entries", "gauge", "entries-throttle"},
- {"unauthorized-tcp", "counter", "denied-unauthorized_tcp"},
- {"unauthorized-udp", "counter", "denied-unauthorized_udp"},
- {"unexpected-packets", "dns_answer", "unexpected"},
- {"uptime", "uptime", NULL}
+ {"all-outqueries", "dns_question", "outgoing"},
+ {"answers0-1", "dns_answer", "0_1"},
+ {"answers1-10", "dns_answer", "1_10"},
+ {"answers10-100", "dns_answer", "10_100"},
+ {"answers100-1000", "dns_answer", "100_1000"},
+ {"answers-slow", "dns_answer", "slow"},
+ {"case-mismatches", "counter", "case_mismatches"},
+ {"chain-resends", "dns_question", "chained"},
+ {"client-parse-errors", "counter", "drops-client_parse_error"},
+ {"concurrent-queries", "dns_question", "concurrent"},
+ {"dlg-only-drops", "counter", "drops-delegation_only"},
+ {"edns-ping-matches", "counter", "edns-ping_matches"},
+ {"edns-ping-mismatches", "counter", "edns-ping_mismatches"},
+ {"failed-host-entries", "counter", "entries-failed_host"},
+ {"ipv6-outqueries", "dns_question", "outgoing-ipv6"},
+ {"ipv6-questions", "dns_question", "incoming-ipv6"},
+ {"malloc-bytes", "gauge", "malloc_bytes"},
+ {"max-mthread-stack", "gauge", "max_mthread_stack"},
+ {"no-packet-error", "gauge", "no_packet_error"},
+ {"noedns-outqueries", "dns_question", "outgoing-noedns"},
+ {"noping-outqueries", "dns_question", "outgoing-noping"},
+ {"over-capacity-drops", "dns_question", "incoming-over_capacity"},
+ {"negcache-entries", "cache_size", "negative"},
+ {"nsspeeds-entries", "gauge", "entries-ns_speeds"},
+ {"nsset-invalidations", "counter", "ns_set_invalidation"},
+ {"outgoing-timeouts", "counter", "drops-timeout_outgoing"},
+ {"policy-drops", "counter", "drops-policy"},
+ {"resource-limits", "counter", "drops-resource_limit"},
+ {"server-parse-errors", "counter", "drops-server_parse_error"},
+ {"spoof-prevents", "counter", "drops-spoofed"},
+ {"tcp-client-overflow", "counter", "denied-client_overflow_tcp"},
+ {"tcp-clients", "gauge", "clients-tcp"},
+ {"tcp-outqueries", "dns_question", "outgoing-tcp"},
+ {"tcp-questions", "dns_question", "incoming-tcp"},
+ {"throttled-out", "dns_question", "outgoing-throttled"},
+ {"throttle-entries", "gauge", "entries-throttle"},
+ {"throttled-outqueries", "dns_question", "outgoing-throttle"},
+ {"unauthorized-tcp", "counter", "denied-unauthorized_tcp"},
+ {"unauthorized-udp", "counter", "denied-unauthorized_udp"},
+ {"unexpected-packets", "dns_answer", "unexpected"},
+ {"uptime", "uptime", NULL}
}; /* }}} */
-int lookup_table_length = STATIC_ARRAY_SIZE (lookup_table);
+static int lookup_table_length = STATIC_ARRAY_SIZE (lookup_table);
static llist_t *list = NULL;
static char *local_sockpath = NULL;
/* TODO: Do this before 4.4:
- * - Recursor:
- * - Complete list of known pdns -> collectd mappings.
* - Update the collectd.conf(5) manpage.
*
* -octo
*/
-/* <http://doc.powerdns.com/recursor-stats.html> */
+/* <https://doc.powerdns.com/md/recursor/stats/> */
static void submit (const char *plugin_instance, /* {{{ */
const char *pdns_type, const char *value)
{
if (ds->ds_num != 1)
{
- ERROR ("powerdns plugin: type `%s' has %i data sources, "
+ ERROR ("powerdns plugin: type `%s' has %zu data sources, "
"but I can only handle one.",
type, ds->ds_num);
return;
return (-1);
}
buffer[sizeof (buffer) - 1] = 0;
- int i = strlen (buffer);
- if (i < sizeof (buffer) - 2)
+ size_t len = strlen (buffer);
+ if (len < sizeof (buffer) - 2)
{
- buffer[i++] = ' ';
- buffer[i++] = '\n';
- buffer[i++] = '\0';
+ buffer[len++] = ' ';
+ buffer[len++] = '\n';
+ buffer[len++] = '\0';
}
}
diff --git a/src/processes.c b/src/processes.c
index 90d4d79e863ed4f9d1abd24e7fb78f1152f4d1ee..d0d736154281f7f9819825d346c1a16b1e44b45d 100644 (file)
--- a/src/processes.c
+++ b/src/processes.c
derive_t io_syscr;
derive_t io_syscw;
+ derive_t cswitch_vol;
+ derive_t cswitch_invol;
+
struct procstat_entry_s *next;
} procstat_entry_t;
derive_t io_syscr;
derive_t io_syscw;
+ derive_t cswitch_vol;
+ derive_t cswitch_invol;
+
struct procstat *next;
struct procstat_entry_s *instances;
} procstat_t;
static procstat_t *list_head_g = NULL;
+static _Bool report_ctx_switch = 0;
+
#if HAVE_THREAD_INFO
static mach_port_t port_host_self;
static mach_port_t port_task_self;
if (status != 0)
{
DEBUG ("ProcessMatch: compiling the regular expression \"%s\" failed.", regexp);
- sfree(new->re);
- sfree(new);
+ sfree (new->re);
+ sfree (new);
return;
}
}
@@ -353,6 +361,31 @@ static int ps_list_match (const char *name, const char *cmdline, procstat_t *ps)
return (0);
} /* int ps_list_match */
+static void ps_update_counter (
+ _Bool init,
+ derive_t *group_counter,
+ derive_t *curr_counter, unsigned long *curr_value,
+ derive_t new_counter, unsigned long new_value) {
+ if (init)
+ {
+ *curr_value = new_value;
+ *curr_counter += new_value;
+ *group_counter += new_value;
+ return;
+ }
+
+ if (new_counter < *curr_counter)
+ {
+ *curr_value = new_counter + (ULONG_MAX - *curr_counter);
+ }
+ else
+ {
+ *curr_value = new_counter - *curr_counter;
+ }
+ *curr_counter = new_counter;
+ *group_counter += *curr_value;
+}
+
/* add process entry to 'instances' of process 'name' (or refresh it) */
static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t *entry)
{
@@ -364,6 +397,8 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t
for (ps = list_head_g; ps != NULL; ps = ps->next)
{
+ _Bool want_init;
+
if ((ps_list_match (name, cmdline, ps)) == 0)
continue;
@@ -401,6 +436,8 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t
pse->io_wchar = entry->io_wchar;
pse->io_syscr = entry->io_syscr;
pse->io_syscw = entry->io_syscw;
+ pse->cswitch_vol = entry->cswitch_vol;
+ pse->cswitch_invol = entry->cswitch_invol;
ps->num_proc += pse->num_proc;
ps->num_lwp += pse->num_lwp;
@@ -415,79 +452,30 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t
ps->io_syscr += ((pse->io_syscr == -1)?0:pse->io_syscr);
ps->io_syscw += ((pse->io_syscw == -1)?0:pse->io_syscw);
- if ((entry->vmem_minflt_counter == 0)
- && (entry->vmem_majflt_counter == 0))
- {
- pse->vmem_minflt_counter += entry->vmem_minflt;
- pse->vmem_minflt = entry->vmem_minflt;
-
- pse->vmem_majflt_counter += entry->vmem_majflt;
- pse->vmem_majflt = entry->vmem_majflt;
- }
- else
- {
- if (entry->vmem_minflt_counter < pse->vmem_minflt_counter)
- {
- pse->vmem_minflt = entry->vmem_minflt_counter
- + (ULONG_MAX - pse->vmem_minflt_counter);
- }
- else
- {
- pse->vmem_minflt = entry->vmem_minflt_counter - pse->vmem_minflt_counter;
- }
- pse->vmem_minflt_counter = entry->vmem_minflt_counter;
-
- if (entry->vmem_majflt_counter < pse->vmem_majflt_counter)
- {
- pse->vmem_majflt = entry->vmem_majflt_counter
- + (ULONG_MAX - pse->vmem_majflt_counter);
- }
- else
- {
- pse->vmem_majflt = entry->vmem_majflt_counter - pse->vmem_majflt_counter;
- }
- pse->vmem_majflt_counter = entry->vmem_majflt_counter;
- }
-
- ps->vmem_minflt_counter += pse->vmem_minflt;
- ps->vmem_majflt_counter += pse->vmem_majflt;
-
- if ((entry->cpu_user_counter == 0)
- && (entry->cpu_system_counter == 0))
- {
- pse->cpu_user_counter += entry->cpu_user;
- pse->cpu_user = entry->cpu_user;
-
- pse->cpu_system_counter += entry->cpu_system;
- pse->cpu_system = entry->cpu_system;
- }
- else
- {
- if (entry->cpu_user_counter < pse->cpu_user_counter)
- {
- pse->cpu_user = entry->cpu_user_counter
- + (ULONG_MAX - pse->cpu_user_counter);
- }
- else
- {
- pse->cpu_user = entry->cpu_user_counter - pse->cpu_user_counter;
- }
- pse->cpu_user_counter = entry->cpu_user_counter;
-
- if (entry->cpu_system_counter < pse->cpu_system_counter)
- {
- pse->cpu_system = entry->cpu_system_counter
- + (ULONG_MAX - pse->cpu_system_counter);
- }
- else
- {
- pse->cpu_system = entry->cpu_system_counter - pse->cpu_system_counter;
- }
- pse->cpu_system_counter = entry->cpu_system_counter;
- }
-
- ps->cpu_user_counter += pse->cpu_user;
- ps->cpu_system_counter += pse->cpu_system;
+ ps->cswitch_vol += ((pse->cswitch_vol == -1)?0:pse->cswitch_vol);
+ ps->cswitch_invol += ((pse->cswitch_invol == -1)?0:pse->cswitch_invol);
+
+ want_init = (entry->vmem_minflt_counter == 0)
+ && (entry->vmem_majflt_counter == 0);
+ ps_update_counter (want_init,
+ &ps->vmem_minflt_counter,
+ &pse->vmem_minflt_counter, &pse->vmem_minflt,
+ entry->vmem_minflt_counter, entry->vmem_minflt);
+ ps_update_counter (want_init,
+ &ps->vmem_majflt_counter,
+ &pse->vmem_majflt_counter, &pse->vmem_majflt,
+ entry->vmem_majflt_counter, entry->vmem_majflt);
+
+ want_init = (entry->cpu_user_counter == 0)
+ && (entry->cpu_system_counter == 0);
+ ps_update_counter (want_init,
+ &ps->cpu_user_counter,
+ &pse->cpu_user_counter, &pse->cpu_user,
+ entry->cpu_user_counter, entry->cpu_user);
+ ps_update_counter (want_init,
+ &ps->cpu_system_counter,
+ &pse->cpu_system_counter, &pse->cpu_system,
+ entry->cpu_system_counter, entry->cpu_system);
}
}
ps->io_wchar = -1;
ps->io_syscr = -1;
ps->io_syscw = -1;
+ ps->cswitch_vol = -1;
+ ps->cswitch_invol = -1;
pse_prev = NULL;
pse = ps->instances;
ps_list_register (c->values[0].value.string,
c->values[1].value.string);
}
+ else if (strcasecmp (c->key, "CollectContextSwitch") == 0)
+ {
+ cf_util_get_boolean (c, &report_ctx_switch);
+ }
else
{
ERROR ("processes plugin: The `%s' configuration option is not "
plugin_dispatch_values (&vl);
}
+ if ( report_ctx_switch )
+ {
+ sstrncpy (vl.type, "contextswitch", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "voluntary", sizeof (vl.type_instance));
+ vl.values[0].derive = ps->cswitch_vol;
+ vl.values_len = 1;
+ plugin_dispatch_values (&vl);
+
+ sstrncpy (vl.type, "contextswitch", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "involuntary", sizeof (vl.type_instance));
+ vl.values[0].derive = ps->cswitch_invol;
+ vl.values_len = 1;
+ plugin_dispatch_values (&vl);
+ }
+
DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; "
"vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
"vmem_code = %lu; "
"vmem_minflt_counter = %"PRIi64"; vmem_majflt_counter = %"PRIi64"; "
"cpu_user_counter = %"PRIi64"; cpu_system_counter = %"PRIi64"; "
"io_rchar = %"PRIi64"; io_wchar = %"PRIi64"; "
- "io_syscr = %"PRIi64"; io_syscw = %"PRIi64";",
+ "io_syscr = %"PRIi64"; io_syscw = %"PRIi64"; "
+ "cswitch_vol = %"PRIi64"; cswitch_invol = %"PRIi64";",
ps->name, ps->num_proc, ps->num_lwp,
ps->vmem_size, ps->vmem_rss,
ps->vmem_data, ps->vmem_code,
ps->vmem_minflt_counter, ps->vmem_majflt_counter,
ps->cpu_user_counter, ps->cpu_system_counter,
- ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw);
+ ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw,
+ ps->cswitch_vol, ps->cswitch_invol);
} /* void ps_submit_proc_list */
#if KERNEL_LINUX || KERNEL_SOLARIS
/* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
#if KERNEL_LINUX
-static int ps_read_tasks (long pid)
+static procstat_t *ps_read_tasks_status (long pid, procstat_t *ps)
{
char dirname[64];
DIR *dh;
+ char filename[64];
+ FILE *fh;
struct dirent *ent;
- int count = 0;
+ derive_t cswitch_vol = 0;
+ derive_t cswitch_invol = 0;
+ char buffer[1024];
+ char *fields[8];
+ int numfields;
ssnprintf (dirname, sizeof (dirname), "/proc/%li/task", pid);
if ((dh = opendir (dirname)) == NULL)
{
DEBUG ("Failed to open directory `%s'", dirname);
- return (-1);
+ return (NULL);
}
while ((ent = readdir (dh)) != NULL)
{
+ char *tpid;
+
if (!isdigit ((int) ent->d_name[0]))
continue;
- else
- count++;
+
+ tpid = ent->d_name;
+
+ ssnprintf (filename, sizeof (filename), "/proc/%li/task/%s/status", pid, tpid);
+ if ((fh = fopen (filename, "r")) == NULL)
+ {
+ DEBUG ("Failed to open file `%s'", filename);
+ continue;
+ }
+
+ while (fgets (buffer, sizeof(buffer), fh) != NULL)
+ {
+ derive_t tmp;
+ char *endptr;
+
+ if (strncmp (buffer, "voluntary_ctxt_switches", 23) != 0
+ && strncmp (buffer, "nonvoluntary_ctxt_switches", 26) != 0)
+ continue;
+
+ numfields = strsplit (buffer, fields,
+ STATIC_ARRAY_SIZE (fields));
+
+ if (numfields < 2)
+ continue;
+
+ errno = 0;
+ endptr = NULL;
+ tmp = (derive_t) strtoll (fields[1], &endptr, /* base = */ 10);
+ if ((errno == 0) && (endptr != fields[1]))
+ {
+ if (strncmp (buffer, "voluntary_ctxt_switches", 23) == 0)
+ {
+ cswitch_vol += tmp;
+ }
+ else if (strncmp (buffer, "nonvoluntary_ctxt_switches", 26) == 0)
+ {
+ cswitch_invol += tmp;
+ }
+ }
+ } /* while (fgets) */
+
+ if (fclose (fh))
+ {
+ char errbuf[1024];
+ WARNING ("processes: fclose: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ }
}
closedir (dh);
- return ((count >= 1) ? count : 1);
-} /* int *ps_read_tasks */
+ ps->cswitch_vol = cswitch_vol;
+ ps->cswitch_invol = cswitch_invol;
-/* Read advanced virtual memory data from /proc/pid/status */
-static procstat_t *ps_read_vmem (long pid, procstat_t *ps)
+ return (ps);
+} /* int *ps_read_tasks_status */
+
+/* Read data from /proc/pid/status */
+static procstat_t *ps_read_status (long pid, procstat_t *ps)
{
FILE *fh;
char buffer[1024];
char filename[64];
- unsigned long long lib = 0;
- unsigned long long exe = 0;
- unsigned long long data = 0;
+ unsigned long lib = 0;
+ unsigned long exe = 0;
+ unsigned long data = 0;
+ unsigned long threads = 0;
char *fields[8];
int numfields;
while (fgets (buffer, sizeof(buffer), fh) != NULL)
{
- long long tmp;
+ unsigned long tmp;
char *endptr;
- if (strncmp (buffer, "Vm", 2) != 0)
+ if (strncmp (buffer, "Vm", 2) != 0
+ && strncmp (buffer, "Threads", 7) != 0)
continue;
numfields = strsplit (buffer, fields,
errno = 0;
endptr = NULL;
- tmp = strtoll (fields[1], &endptr, /* base = */ 10);
+ tmp = strtoul (fields[1], &endptr, /* base = */ 10);
if ((errno == 0) && (endptr != fields[1]))
{
if (strncmp (buffer, "VmData", 6) == 0)
{
exe = tmp;
}
+ else if (strncmp(buffer, "Threads", 7) == 0)
+ {
+ threads = tmp;
+ }
}
} /* while (fgets) */
ps->vmem_data = data * 1024;
ps->vmem_code = (exe + lib) * 1024;
+ if (threads != 0)
+ ps->num_lwp = threads;
return (ps);
} /* procstat_t *ps_read_vmem */
char *fields[64];
char fields_len;
- int buffer_len;
+ size_t buffer_len;
- char *buffer_ptr;
+ char *buffer_ptr;
size_t name_start_pos;
size_t name_end_pos;
size_t name_len;
long long unsigned vmem_rss;
long long unsigned stack_size;
+ ssize_t status;
+
memset (ps, 0, sizeof (procstat_t));
ssnprintf (filename, sizeof (filename), "/proc/%li/stat", pid);
- buffer_len = read_file_contents (filename,
- buffer, sizeof(buffer) - 1);
- if (buffer_len <= 0)
+ status = read_file_contents (filename, buffer, sizeof(buffer) - 1);
+ if (status <= 0)
return (-1);
+ buffer_len = (size_t) status;
buffer[buffer_len] = 0;
/* The name of the process is enclosed in parens. Since the name can
}
else
{
- if ( (ps->num_lwp = ps_read_tasks (pid)) == -1 )
+ ps->num_lwp = strtoul (fields[17], /* endptr = */ NULL, /* base = */ 10);
+ if ((ps_read_status(pid, ps)) == NULL)
{
- /* returns -1 => kernel 2.4 */
- ps->num_lwp = 1;
+ /* No VMem data */
+ ps->vmem_data = -1;
+ ps->vmem_code = -1;
+ DEBUG("ps_read_process: did not get vmem data for pid %li", pid);
}
+ if (ps->num_lwp <= 0)
+ ps->num_lwp = 1;
ps->num_proc = 1;
}
cpu_system_counter = cpu_system_counter * 1000000 / CONFIG_HZ;
vmem_rss = vmem_rss * pagesize_g;
- if ( (ps_read_vmem(pid, ps)) == NULL)
- {
- /* No VMem data */
- ps->vmem_data = -1;
- ps->vmem_code = -1;
- DEBUG("ps_read_process: did not get vmem data for pid %li", pid);
- }
-
ps->cpu_user_counter = cpu_user_counter;
ps->cpu_system_counter = cpu_system_counter;
ps->vmem_size = (unsigned long) vmem_size;
DEBUG("ps_read_process: not get io data for pid %li", pid);
}
+ if ( report_ctx_switch )
+ {
+ if ( (ps_read_tasks_status(pid, ps)) == NULL)
+ {
+ ps->cswitch_vol = -1;
+ ps->cswitch_invol = -1;
+
+ DEBUG("ps_read_tasks_status: not get context "
+ "switch data for pid %li", pid);
+ }
+ }
+
/* success */
return (0);
} /* int ps_read_process (...) */
@@ -1221,16 +1307,16 @@ static char *ps_get_cmdline (long pid, char *name __attribute__((unused)), /* {{
{
char path[PATH_MAX];
psinfo_t info;
- int status;
+ ssize_t status;
snprintf(path, sizeof (path), "/proc/%li/psinfo", pid);
status = read_file_contents (path, (void *) &info, sizeof (info));
- if (status != sizeof (info))
+ if ((status < 0) || (((size_t) status) != sizeof (info)))
{
ERROR ("processes plugin: Unexpected return value "
"while reading \"%s\": "
- "Returned %i but expected %zu.",
+ "Returned %zd but expected %zu.",
path, status, buffer_size);
return (NULL);
}
ps->io_syscr = myUsage->pr_sysc;
ps->io_syscw = myUsage->pr_sysc;
+ /*
+ * TODO: context switch counters for Solaris
+ */
+ ps->cswitch_vol = -1;
+ ps->cswitch_invol = -1;
+
/*
* TODO: Find way of setting BLOCKED and PAGING status
* are retrieved from kstat (module cpu, name sys, class misc, stat nthreads).
* The result is the sum for all the threads created on each cpu
*/
-static int read_fork_rate()
+static int read_fork_rate (void)
{
extern kstat_ctl_t *kc;
kstat_t *ksp_chain = NULL;
pse.cpu_user_counter = task_absolutetime_info.total_user;
pse.cpu_system_counter = task_absolutetime_info.total_system;
+
+ /* context switch counters not implemented */
+ pse.cswitch_vol = -1;
+ pse.cswitch_invol = -1;
}
status = task_threads (task_list[task], &thread_list,
pse.io_syscr = ps.io_syscr;
pse.io_syscw = ps.io_syscw;
+ pse.cswitch_vol = ps.cswitch_vol;
+ pse.cswitch_invol = ps.cswitch_invol;
+
switch (state)
{
case 'R': running++; break;
pse.io_syscr = -1;
pse.io_syscw = -1;
+ /* context switch counters not implemented */
+ pse.cswitch_vol = -1;
+ pse.cswitch_invol = -1;
+
ps_list_add (procs[i].ki_comm, have_cmdline ? cmdline : NULL, &pse);
switch (procs[i].ki_stat)
pse.io_syscr = -1;
pse.io_syscw = -1;
- pse.cswitch_vol = -1;
+ /* context switch counters not implemented */
+ pse.cswitch_vol = -1;
pse.cswitch_invol = -1;
ps_list_add (procs[i].p_comm, have_cmdline ? cmdline : NULL, &pse);
pse.io_syscr = -1;
pse.io_syscw = -1;
+ pse.cswitch_vol = -1;
+ pse.cswitch_invol = -1;
+
ps_list_add (cmdline, cargs, &pse);
} /* for (i = 0 .. nprocs) */
diff --git a/src/python.c b/src/python.c
index c7524143424aecbb87fa3c037eabb9f8fee5016a..b90902498d69fdb1b48e3048ac6515dda3200399 100644 (file)
--- a/src/python.c
+++ b/src/python.c
}
static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_list, user_data_t *data) {
- int i;
+ size_t i;
cpy_callback_t *c = data->data;
PyObject *ret, *list, *temp, *dict = NULL;
Values *v;
@@ -368,22 +368,13 @@ static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_li
}
for (i = 0; i < value_list->values_len; ++i) {
if (ds->ds[i].type == DS_TYPE_COUNTER) {
- if ((long) value_list->values[i].counter == value_list->values[i].counter)
- PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].counter));
- else
- PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
+ PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
} else if (ds->ds[i].type == DS_TYPE_GAUGE) {
PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].gauge));
} else if (ds->ds[i].type == DS_TYPE_DERIVE) {
- if ((long) value_list->values[i].derive == value_list->values[i].derive)
- PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].derive));
- else
- PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
+ PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
} else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) {
- if ((long) value_list->values[i].absolute == value_list->values[i].absolute)
- PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].absolute));
- else
- PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
+ PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
} else {
Py_BEGIN_ALLOW_THREADS
ERROR("cpy_write_callback: Unknown value type %d.", ds->ds[i].type);
}
static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
- int i;
+ size_t i;
char *name;
const data_set_t *ds;
PyObject *list, *tuple;
@@ -678,7 +669,6 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwd
double interval = 0;
char *name = NULL;
PyObject *callback = NULL, *data = NULL;
- struct timespec ts;
static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback, &interval, &data, NULL, &name) == 0) return NULL;
@@ -707,11 +697,8 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwd
user_data.free_func = cpy_destroy_user_data;
user_data.data = c;
- ts.tv_sec = interval;
- ts.tv_nsec = (interval - ts.tv_sec) * 1000000000;
plugin_register_complex_read(/* group = */ "python", buf,
- cpy_read_callback, &ts, &user_data);
-
+ cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), &user_data);
return cpy_string_to_unicode_or_bytes(buf);
}
diff --git a/src/pyvalues.c b/src/pyvalues.c
index 78e6cf9d450413ed242fb73e6126a09f4dd86057..1097f7ff9692a735d5a3763a344758a5e2c1093d 100644 (file)
--- a/src/pyvalues.c
+++ b/src/pyvalues.c
return ret;
}
-static char time_doc[] = "This is the Unix timestap of the time this value was read.\n"
+static char time_doc[] = "This is the Unix timestamp of the time this value was read.\n"
"For dispatching values this can be set to 0 which means \"now\".\n"
"This means the time the value is actually dispatched, not the time\n"
"it was set to 0.";
static char host_doc[] = "The hostname of the host this value was read from.\n"
"For dispatching this can be set to an empty string which means\n"
- "the local hostname as defined in the collectd.conf.";
+ "the local hostname as defined in collectd.conf.";
static char type_doc[] = "The type of this value. This type has to be defined\n"
- "in your types.db. Attempting to set it to any other value will\n"
- "raise a TypeError exception.\n"
- "Assigning a type is mandetory, calling dispatch without doing\n"
+ "in the types.db file. Attempting to set it to any other value\n"
+ "will raise a TypeError exception.\n"
+ "Assigning a type is mandatory, calling dispatch without doing\n"
"so will raise a RuntimeError exception.";
static char type_instance_doc[] = "";
@@ -129,7 +129,7 @@ static char plugin_doc[] = "The name of the plugin that read the data. Setting t
static char plugin_instance_doc[] = "";
static char PluginData_doc[] = "This is an internal class that is the base for Values\n"
- "and Notification. It is pretty useless by itself and was therefore not\n"
+ "and Notification. It is pretty useless by itself and is therefore not\n"
"exported to the collectd module.";
static PyObject *PluginData_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
@@ -312,8 +312,8 @@ static char interval_doc[] = "The interval is the timespan in seconds between tw
static char values_doc[] = "These are the actual values that get dispatched to collectd.\n"
"It has to be a sequence (a tuple or list) of numbers.\n"
"The size of the sequence and the type of its content depend on the type\n"
- "member your types.db file. For more information on this read the types.db\n"
- "man page.\n"
+ "member in the types.db file. For more information on this read the\n"
+ "types.db man page.\n"
"\n"
"If the sequence does not have the correct size upon dispatch a RuntimeError\n"
"exception will be raised. If the content of the sequence is not a number,\n"
@@ -322,7 +322,7 @@ static char values_doc[] = "These are the actual values that get dispatched to c
static char meta_doc[] = "These are the meta data for this Value object.\n"
"It has to be a dictionary of numbers, strings or bools. All keys must be\n"
"strings. int and long objects will be dispatched as signed integers unless\n"
- "they are between 2**63 and 2**64-1, which will result in a unsigned integer.\n"
+ "they are between 2**63 and 2**64-1, which will result in an unsigned integer.\n"
"You can force one of these storage classes by using the classes\n"
"collectd.Signed and collectd.Unsigned. A meta object received by a write\n"
"callback will always contain Signed or Unsigned objects.";
@@ -340,7 +340,7 @@ static char dispatch_doc[] = "dispatch([type][, values][, plugin_instance][, typ
static char write_doc[] = "write([destination][, type][, values][, plugin_instance][, type_instance]"
"[, plugin][, host][, time][, interval]) -> None. Dispatch a value list.\n"
"\n"
- "Write this instance to a single plugin or all plugins if 'destination' is obmitted.\n"
+ "Write this instance to a single plugin or all plugins if 'destination' is omitted.\n"
"This will bypass the main collectd process and all filtering and caching.\n"
"Other than that it works similar to 'dispatch'. In most cases 'dispatch' should be\n"
"used instead of 'write'.\n";
}
static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
- int i, ret;
+ int ret;
const data_set_t *ds;
- int size;
+ size_t size, i;
value_t *value;
value_list_t value_list = VALUE_LIST_INIT;
PyObject *values = self->values, *meta = self->meta;
@@ -542,15 +542,15 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
PyErr_Format(PyExc_TypeError, "meta must be a dict");
return NULL;
}
- size = (int) PySequence_Length(values);
+ size = (size_t) PySequence_Length(values);
if (size != ds->ds_num) {
- PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", value_list.type, ds->ds_num, size);
+ PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu", value_list.type, ds->ds_num, size);
return NULL;
}
- value = malloc(size * sizeof(*value));
+ value = calloc(size, sizeof(*value));
for (i = 0; i < size; ++i) {
PyObject *item, *num;
- item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
+ item = PySequence_Fast_GET_ITEM(values, (int) i); /* Borrowed reference. */
if (ds->ds->type == DS_TYPE_COUNTER) {
num = PyNumber_Long(item); /* New reference. */
if (num != NULL) {
@@ -611,9 +611,9 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
}
static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
- int i, ret;
+ int ret;
const data_set_t *ds;
- int size;
+ size_t size, i;
value_t *value;
value_list_t value_list = VALUE_LIST_INIT;
PyObject *values = self->values, *meta = self->meta;
PyErr_Format(PyExc_TypeError, "values must be list or tuple");
return NULL;
}
- size = (int) PySequence_Length(values);
+ size = (size_t) PySequence_Length(values);
if (size != ds->ds_num) {
- PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", value_list.type, ds->ds_num, size);
+ PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu", value_list.type, ds->ds_num, size);
return NULL;
}
- value = malloc(size * sizeof(*value));
+ value = calloc(size, sizeof(*value));
for (i = 0; i < size; ++i) {
PyObject *item, *num;
item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
diff --git a/src/redis.c b/src/redis.c
index 2586ca0c83325656c4ebfbee142cb5ddb9742768..4e3de56c8dfa854f5104f9f53b79bb91ee553dec 100644 (file)
--- a/src/redis.c
+++ b/src/redis.c
@@ -304,7 +304,7 @@ static int redis_handle_info (char *node, char const *info_line, char const *typ
int i;
str += strlen (field_name) + 1; /* also skip the ':' */
- for(i=0;(*str && (isdigit(*str) || *str == '.'));i++,str++)
+ for(i=0;(*str && (isdigit((unsigned char)*str) || *str == '.'));i++,str++)
buf[i] = *str;
buf[i] ='\0';
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, "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);
for (rq = rn->queries; rq != NULL; rq = rq->next)
redis_handle_query(rh, rn, rq);
diff --git a/src/routeros.c b/src/routeros.c
index 4863d7c082b1e8297b48152c379dc6a4701b0a1d..667c2fa581722e00ef01161e385d6e13d0c4e36a 100644 (file)
--- a/src/routeros.c
+++ b/src/routeros.c
user_data.free_func = (void *) cr_free_data;
if (status == 0)
status = plugin_register_complex_read (/* group = */ NULL, read_name,
- cr_read, /* interval = */ NULL, &user_data);
+ cr_read, /* interval = */ 0, &user_data);
if (status != 0)
cr_free_data (router_data);
diff --git a/src/rrdcached.c b/src/rrdcached.c
index 645032cbe189686a707c7e6d34db7343432b8882..5d98de8e0dbd5dec3aaba79ea5bda1a03363c85f 100644 (file)
--- a/src/rrdcached.c
+++ b/src/rrdcached.c
{
int offset;
int status;
- int i;
+ size_t i;
time_t t;
assert (0 == strcmp (ds->type, vl->type));
diff --git a/src/rrdtool.c b/src/rrdtool.c
index 7cfdae60302f5e26968288c50ec7572d455d3687..fd5fb56334346e406b7a1747b5e41ab2459f7722 100644 (file)
--- a/src/rrdtool.c
+++ b/src/rrdtool.c
int offset;
int status;
time_t tt;
- int i;
+ size_t i;
memset (buffer, '\0', buffer_len);
diff --git a/src/sensors.c b/src/sensors.c
index dc6a2101778ca4677e06d2f75dc954a294103672..c678dec99c2fbdb5e544bfded5fd5a8327173c1e 100644 (file)
--- a/src/sensors.c
+++ b/src/sensors.c
"as bug."
#endif
-featurelist_t *first_feature = NULL;
+static featurelist_t *first_feature = NULL;
static ignorelist_t *sensor_list;
#if SENSORS_API_VERSION < 0x400
diff --git a/src/serial.c b/src/serial.c
index 430082220595c58f2b927089871a76e4e482a157..0878d3c93b1dac2b4d4bc331e4d13e56a358ede9 100644 (file)
--- a/src/serial.c
+++ b/src/serial.c
FILE *fh;
char buffer[1024];
- derive_t rx = 0;
- derive_t tx = 0;
-
- char *fields[16];
- int i, numfields;
- int len;
-
/* there are a variety of names for the serial device */
if ((fh = fopen ("/proc/tty/driver/serial", "r")) == NULL &&
(fh = fopen ("/proc/tty/driver/ttyS", "r")) == NULL)
while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
- int have_rx = 0, have_tx = 0;
+ derive_t rx = 0;
+ derive_t tx = 0;
+ _Bool have_rx = 0, have_tx = 0;
+ size_t len;
- numfields = strsplit (buffer, fields, 16);
+ char *fields[16];
+ int numfields;
+ int i;
+ numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
if (numfields < 6)
continue;
* 0: uart:16550A port:000003F8 irq:4 tx:0 rx:0
* 1: uart:16550A port:000002F8 irq:3 tx:0 rx:0
*/
- len = strlen (fields[0]) - 1;
- if (len < 1)
+ len = strlen (fields[0]);
+ if (len < 2)
continue;
- if (fields[0][len] != ':')
+ if (fields[0][len - 1] != ':')
continue;
- fields[0][len] = '\0';
+ fields[0][len - 1] = 0;
for (i = 1; i < numfields; i++)
{
if (strncmp (fields[i], "tx:", 3) == 0)
{
- tx = atoll (fields[i] + 3);
- have_tx++;
+ if (strtoderive (fields[i] + 3, &tx) == 0)
+ have_tx = 1;
}
else if (strncmp (fields[i], "rx:", 3) == 0)
{
- rx = atoll (fields[i] + 3);
- have_rx++;
+ if (strtoderive (fields[i] + 3, &rx) == 0)
+ have_rx = 1;
}
}
- if ((have_rx == 0) || (have_tx == 0))
- continue;
-
- serial_submit (fields[0], rx, tx);
+ if (have_rx && have_tx)
+ serial_submit (fields[0], rx, tx);
}
fclose (fh);
diff --git a/src/sigrok.c b/src/sigrok.c
index 487f31a1b8030edbb299affb87368849d743064c..ad5c70c0b3eed5cfc5293c7348fcbddf7144b6b1 100644 (file)
--- a/src/sigrok.c
+++ b/src/sigrok.c
return 0;
}
-static char *sigrok_value_type(const struct sr_datafeed_analog *analog)
+static const char *sigrok_value_type(const struct sr_datafeed_analog *analog)
{
- char *s;
+ const char *s;
if (analog->mq == SR_MQ_VOLTAGE)
s = "voltage";
diff --git a/src/smart.c b/src/smart.c
index 2207bd6722449f4de11c3b89a976817ba8702558..7b39aaee867c83f8d5fdaa3cbb18535f19e6f58b 100644 (file)
--- a/src/smart.c
+++ b/src/smart.c
return (0);
} /* int smart_config */
-static void smart_submit (const char *dev, char *type, char *type_inst, double value)
+static void smart_submit (const char *dev, const char *type,
+ const char *type_inst, double value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
diff --git a/src/snmp.c b/src/snmp.c
index ae41d03ae8562781a5ba0f7ec1ff155666f63795..3ccf60c3fd8ff638ab90aaa21f8eafcbb5223261 100644 (file)
--- a/src/snmp.c
+++ b/src/snmp.c
instance_t instance;
char *instance_prefix;
oid_t *values;
- int values_len;
+ size_t values_len;
double scale;
double shift;
struct data_definition_s *next;
@@ -313,7 +313,7 @@ static int csnmp_config_add_data_values (data_definition_t *dd, oconfig_item_t *
dd->values = (oid_t *) malloc (sizeof (oid_t) * ci->values_num);
if (dd->values == NULL)
return (-1);
- dd->values_len = ci->values_num;
+ dd->values_len = (size_t) ci->values_num;
for (i = 0; i < ci->values_num; i++)
{
return (-1);
}
- DEBUG ("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = %i }",
+ DEBUG ("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = %zu }",
dd->name, dd->type, (dd->is_table != 0) ? "true" : "false", dd->values_len);
if (data_head == NULL)
/* Registration stuff. */
char cb_name[DATA_MAX_NAME_LEN];
user_data_t cb_data;
- struct timespec cb_interval;
hd = (host_definition_t *) malloc (sizeof (host_definition_t));
if (hd == NULL)
cb_data.data = hd;
cb_data.free_func = csnmp_host_definition_destroy;
- CDTIME_T_TO_TIMESPEC (hd->interval, &cb_interval);
-
status = plugin_register_complex_read (/* group = */ NULL, cb_name,
- csnmp_read_host, /* interval = */ &cb_interval,
- /* user_data = */ &cb_data);
+ csnmp_read_host, hd->interval, /* user_data = */ &cb_data);
if (status != 0)
{
ERROR ("snmp plugin: Registering complex read function failed.");
@@ -1055,6 +1051,10 @@ static value_t csnmp_value_list_to_value (struct variable_list *vl, int type,
return (ret);
} /* value_t csnmp_value_list_to_value */
+/* csnmp_strvbcopy_hexstring converts the bit string contained in "vb" to a hex
+ * representation and writes it to dst. Returns zero on success and ENOMEM if
+ * dst is not large enough to hold the string. dst is guaranteed to be
+ * nul-terminated. */
static int csnmp_strvbcopy_hexstring (char *dst, /* {{{ */
const struct variable_list *vb, size_t dst_size)
{
size_t buffer_free;
size_t i;
+ dst[0] = 0;
+
buffer_ptr = dst;
buffer_free = dst_size;
status = snprintf (buffer_ptr, buffer_free,
(i == 0) ? "%02x" : ":%02x", (unsigned int) vb->val.bitstring[i]);
+ assert (status >= 0);
- if (status >= buffer_free)
+ if (((size_t) status) >= buffer_free) /* truncated */
{
- buffer_ptr += (buffer_free - 1);
- *buffer_ptr = 0;
- return (dst_size + (buffer_free - status));
+ dst[dst_size - 1] = 0;
+ return ENOMEM;
}
else /* if (status < buffer_free) */
{
- buffer_ptr += status;
- buffer_free -= status;
+ buffer_ptr += (size_t) status;
+ buffer_free -= (size_t) status;
}
}
- return ((int) (dst_size - buffer_free));
+ return 0;
} /* }}} int csnmp_strvbcopy_hexstring */
+/* csnmp_strvbcopy copies the octet string or bit string contained in vb to
+ * dst. If non-printable characters are detected, it will switch to a hex
+ * representation of the string. Returns zero on success, EINVAL if vb does not
+ * contain a string and ENOMEM if dst is not large enough to contain the
+ * string. */
static int csnmp_strvbcopy (char *dst, /* {{{ */
const struct variable_list *vb, size_t dst_size)
{
src = (char *) vb->val.string;
else if (vb->type == ASN_BIT_STR)
src = (char *) vb->val.bitstring;
+ else if (vb->type == ASN_IPADDRESS)
+ {
+ return ssnprintf (dst, dst_size, "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8"",
+ (uint8_t) vb->val.string[0],
+ (uint8_t) vb->val.string[1],
+ (uint8_t) vb->val.string[2],
+ (uint8_t) vb->val.string[3]);
+ }
else
{
dst[0] = 0;
dst[i] = src[i];
}
dst[num_chars] = 0;
+ dst[dst_size - 1] = 0;
- return ((int) vb->val_len);
+ if (dst_size <= vb->val_len)
+ return ENOMEM;
+
+ return 0;
} /* }}} int csnmp_strvbcopy */
static int csnmp_instance_list_add (csnmp_list_instances_t **head,
}
/* Get instance name */
- if ((vb->type == ASN_OCTET_STR) || (vb->type == ASN_BIT_STR))
+ if ((vb->type == ASN_OCTET_STR) || (vb->type == ASN_BIT_STR) || (vb->type == ASN_IPADDRESS))
{
char *ptr;
@@ -1226,7 +1245,7 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
csnmp_list_instances_t *instance_list_ptr;
csnmp_table_values_t **value_table_ptr;
- int i;
+ size_t i;
_Bool have_more;
oid_t current_suffix;
@@ -1241,7 +1260,7 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
instance_list_ptr = instance_list;
- value_table_ptr = calloc ((size_t) data->values_len, sizeof (*value_table_ptr));
+ value_table_ptr = calloc (data->values_len, sizeof (*value_table_ptr));
if (value_table_ptr == NULL)
return (-1);
for (i = 0; i < data->values_len; i++)
@@ -1384,7 +1403,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
const data_set_t *ds;
- uint32_t oid_list_len = (uint32_t) (data->values_len + 1);
+ size_t oid_list_len = data->values_len + 1;
/* Holds the last OID returned by the device. We use this in the GETNEXT
* request to proceed. */
oid_t oid_list[oid_list_len];
@@ -1393,8 +1412,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
_Bool oid_list_todo[oid_list_len];
int status;
- int i;
- uint32_t j;
+ size_t i;
/* `value_list_head' and `value_list_tail' implement a linked list for each
* value. `instance_list_head' and `instance_list_tail' implement a linked list of
@@ -1422,7 +1440,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
if (ds->ds_num != data->values_len)
{
- ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i",
+ ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu",
data->type, ds->ds_num, data->values_len);
return (-1);
}
@@ -1435,8 +1453,8 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
else /* no InstanceFrom option specified. */
oid_list_len--;
- for (j = 0; j < oid_list_len; j++)
- oid_list_todo[j] = 1;
+ for (i = 0; i < oid_list_len; i++)
+ oid_list_todo[i] = 1;
/* We're going to construct n linked lists, one for each "value".
* value_list_head will contain pointers to the heads of these linked lists,
@@ -1468,13 +1486,13 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
}
oid_list_todo_num = 0;
- for (j = 0; j < oid_list_len; j++)
+ for (i = 0; i < oid_list_len; i++)
{
/* Do not rerequest already finished OIDs */
- if (!oid_list_todo[j])
+ if (!oid_list_todo[i])
continue;
oid_list_todo_num++;
- snmp_add_null_var (req, oid_list[j].oid, oid_list[j].oid_len);
+ snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len);
}
if (oid_list_todo_num == 0)
@@ -1570,7 +1588,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
if (ret != 0)
{
- DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
+ DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; "
"Value probably left its subtree.",
host->name, data->name, i);
oid_list_todo[i] = 0;
@@ -1582,7 +1600,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
if ((value_list_tail[i] != NULL)
&& (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0))
{
- DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
+ DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; "
"Suffix is not increasing.",
host->name, data->name, i);
oid_list_todo[i] = 0;
@@ -1666,7 +1684,7 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
value_list_t vl = VALUE_LIST_INIT;
int status;
- int i;
+ size_t i;
DEBUG ("snmp plugin: csnmp_read_value (host = %s, data = %s)",
host->name, data->name);
@@ -1686,7 +1704,7 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
if (ds->ds_num != data->values_len)
{
- ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i",
+ ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu",
data->type, ds->ds_num, data->values_len);
return (-1);
}
@@ -1774,8 +1792,6 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
static int csnmp_read_host (user_data_t *ud)
{
host_definition_t *host;
- cdtime_t time_start;
- cdtime_t time_end;
int status;
int success;
int i;
if (host->interval == 0)
host->interval = plugin_get_interval ();
- time_start = cdtime ();
-
if (host->sess_handle == NULL)
csnmp_host_open_session (host);
success++;
}
- time_end = cdtime ();
- if ((time_end - time_start) > host->interval)
- {
- WARNING ("snmp plugin: Host `%s' should be queried every %.3f "
- "seconds, but reading all values takes %.3f seconds.",
- host->name,
- CDTIME_T_TO_DOUBLE (host->interval),
- CDTIME_T_TO_DOUBLE (time_end - time_start));
- }
-
if (success == 0)
return (-1);
diff --git a/src/statsd.c b/src/statsd.c
index d12cb0d5b83d5677f0ba8125c7d29250e7db3353..d0a677e70476c79dc5fa0299c3da4af8292cdfd9 100644 (file)
--- a/src/statsd.c
+++ b/src/statsd.c
#include <pthread.h>
#include <sys/types.h>
-#include <sys/socket.h>
#include <netdb.h>
#include <poll.h>
{
metric_type_t type;
double value;
+ derive_t counter;
latency_counter_t *latency;
c_avl_tree_t *set;
unsigned long updates_num;
static double *conf_timer_percentile = NULL;
static size_t conf_timer_percentile_num = 0;
+static _Bool conf_counter_sum = 0;
static _Bool conf_timer_lower = 0;
static _Bool conf_timer_upper = 0;
static _Bool conf_timer_sum = 0;
if (status != 0)
return (status);
+ /* Changes to the counter are added to (statsd_metric_t*)->value. ->counter is
+ * only updated in statsd_metric_submit_unsafe(). */
return (statsd_metric_add (name, (double) (value.gauge / scale.gauge),
STATSD_COUNTER));
} /* }}} int statsd_handle_counter */
cf_util_get_boolean (child, &conf_delete_gauges);
else if (strcasecmp ("DeleteSets", child->key) == 0)
cf_util_get_boolean (child, &conf_delete_sets);
+ else if (strcasecmp ("CounterSum", child->key) == 0)
+ cf_util_get_boolean (child, &conf_counter_sum);
else if (strcasecmp ("TimerLower", child->key) == 0)
cf_util_get_boolean (child, &conf_timer_lower);
else if (strcasecmp ("TimerUpper", child->key) == 0)
} /* }}} int statsd_metric_clear_set_unsafe */
/* Must hold metrics_lock when calling this function. */
-static int statsd_metric_submit_unsafe (char const *name, /* {{{ */
- statsd_metric_t const *metric)
+static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metric) /* {{{ */
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
values[0].gauge = (gauge_t) c_avl_size (metric->set);
}
else { /* STATSD_COUNTER */
- /*
- * Expand a single value to two metrics:
- *
- * - The absolute counter, as a gauge
- * - A derived rate for this counter
- */
- values[0].derive = (derive_t) metric->value;
- plugin_dispatch_values(&vl);
-
- sstrncpy(vl.type, "gauge", sizeof (vl.type));
- values[0].gauge = (gauge_t) metric->value;
+ gauge_t delta = nearbyint (metric->value);
+
+ /* Etsy's statsd writes counters as two metrics: a rate and the change since
+ * the last write. Since collectd does not reset its DERIVE metrics to zero,
+ * this makes little sense, but we're dispatching a "count" metric here
+ * anyway - if requested by the user - for compatibility reasons. */
+ if (conf_counter_sum)
+ {
+ sstrncpy (vl.type, "count", sizeof (vl.type));
+ values[0].gauge = delta;
+ plugin_dispatch_values (&vl);
+
+ /* restore vl.type */
+ sstrncpy (vl.type, "derive", sizeof (vl.type));
+ }
+
+ /* Rather than resetting value to zero, subtract delta so we correctly keep
+ * track of residuals. */
+ metric->value -= delta;
+ metric->counter += (derive_t) delta;
+
+ values[0].derive = metric->counter;
}
return (plugin_dispatch_values (&vl));
diff --git a/src/swap.c b/src/swap.c
index e4c5d24f23bccc918b440c06db86260c0715d44d..d714b5fcdb8d7e558eb02d1c7a787b506bc07230 100644 (file)
--- a/src/swap.c
+++ b/src/swap.c
static _Bool report_by_device = 0;
/* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS */
+#elif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS
+/* No global variables */
+/* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS */
+
#elif defined(VM_SWAPUSAGE)
/* No global variables */
/* #endif defined(VM_SWAPUSAGE) */
diff --git a/src/syslog.c b/src/syslog.c
index 3f73178fa5e09283dec5efee71f57a3d941b0735..849f7d1b1331a04daec6de6d6888c6234044912d 100644 (file)
--- a/src/syslog.c
+++ b/src/syslog.c
char buf[1024] = "";
size_t offset = 0;
int log_severity;
- char *severity_string;
+ const char *severity_string;
int status;
if (n->severity > notif_severity)
diff --git a/src/table.c b/src/table.c
index fcbac4f5e475f9499eacf6d68caa891585f10d6d..aebf0bbfad39123fba3f34b58d02c06bd743f1be 100644 (file)
--- a/src/table.c
+++ b/src/table.c
*/
typedef struct {
- char *type;
- char *instance_prefix;
- int *instances;
- size_t instances_num;
- int *values;
- size_t values_num;
+ char *type;
+ char *instance_prefix;
+ size_t *instances;
+ size_t instances_num;
+ size_t *values;
+ size_t values_num;
const data_set_t *ds;
} tbl_result_t;
return 0;
} /* tbl_config_set_separator */
-static int tbl_config_append_array_i (char *name, int **var, size_t *len,
+static int tbl_config_append_array_i (char *name, size_t **var, size_t *len,
oconfig_item_t *ci)
{
- int *tmp;
-
+ size_t *tmp;
+ size_t num;
size_t i;
if (1 > ci->values_num) {
return 1;
}
- for (i = 0; i < ci->values_num; ++i) {
+ num = (size_t) ci->values_num;
+ for (i = 0; i < num; ++i) {
if (OCONFIG_TYPE_NUMBER != ci->values[i].type) {
log_err ("\"%s\" expects numerical arguments only.", name);
return 1;
}
}
- *len += ci->values_num;
- tmp = (int *)realloc (*var, *len * sizeof (**var));
+ tmp = realloc (*var, ((*len) + num) * sizeof (**var));
if (NULL == tmp) {
char errbuf[1024];
log_err ("realloc failed: %s.",
sstrerror (errno, errbuf, sizeof (errbuf)));
return -1;
}
-
*var = tmp;
- for (i = *len - ci->values_num; i < *len; ++i)
- (*var)[i] = (int)ci->values[i].value.number;
+ for (i = 0; i < num; ++i) {
+ (*var)[*len] = (size_t) ci->values[i].value.number;
+ (*len)++;
+ }
+
return 0;
} /* tbl_config_append_array_s */
tbl_result_t *res;
int status = 0;
- size_t i;
+ int i;
if (0 != ci->values_num) {
log_err ("<Result> does not expect any arguments.");
tbl = tables + tables_num - 1;
tbl_setup (tbl, ci->values[0].value.string);
- for (i = 0; i < ci->children_num; ++i) {
+ for (i = 0; i < ((size_t) ci->children_num); ++i) {
oconfig_item_t *c = ci->children + i;
if (0 == strcasecmp (c->key, "Separator"))
static int tbl_config (oconfig_item_t *ci)
{
- size_t i;
+ int i;
for (i = 0; i < ci->children_num; ++i) {
oconfig_item_t *c = ci->children + i;
return -1;
}
- if (res->values_num != (size_t)res->ds->ds_num) {
+ if (res->values_num != res->ds->ds_num) {
log_err ("Invalid type \"%s\". Expected %zu data source%s, "
- "got %i.", res->type, res->values_num,
+ "got %zu.", res->type, res->values_num,
(1 == res->values_num) ? "" : "s",
res->ds->ds_num);
return -1;
}
if (i <= tbl->max_colnum) {
- log_err ("Not enough columns in line "
+ log_warn ("Not enough columns in line "
"(expected at least %zu, got %zu).",
tbl->max_colnum + 1, i);
return -1;
while (NULL != fgets (buf, sizeof (buf), fh)) {
if ('\0' != buf[sizeof (buf) - 1]) {
buf[sizeof (buf) - 1] = '\0';
- log_err ("Table %s: Truncated line: %s", tbl->file, buf);
+ log_warn ("Table %s: Truncated line: %s", tbl->file, buf);
}
if (0 != tbl_parse_line (tbl, buf, sizeof (buf))) {
- log_err ("Table %s: Failed to parse line: %s", tbl->file, buf);
+ log_warn ("Table %s: Failed to parse line: %s", tbl->file, buf);
continue;
}
}
diff --git a/src/tail.c b/src/tail.c
index 708cd2a32737e0a10678bc7d650c48c4c6029ba8..ffdba8ae3e6ee62eeacf59200a1c4de00b2d1500 100644 (file)
--- a/src/tail.c
+++ b/src/tail.c
};
typedef struct ctail_config_match_s ctail_config_match_t;
-cu_tail_match_t **tail_match_list = NULL;
-size_t tail_match_list_num = 0;
-cdtime_t tail_match_list_intervals[255];
+static cu_tail_match_t **tail_match_list = NULL;
+static size_t tail_match_list_num = 0;
+static cdtime_t tail_match_list_intervals[255];
static int ctail_config_add_match_dstype (ctail_config_match_t *cm,
oconfig_item_t *ci)
static int ctail_init (void)
{
- struct timespec cb_interval;
char str[255];
user_data_t ud;
size_t i;
{
ud.data = (void *)tail_match_list[i];
ssnprintf(str, sizeof(str), "tail-%zu", i);
- CDTIME_T_TO_TIMESPEC (tail_match_list_intervals[i], &cb_interval);
- plugin_register_complex_read (NULL, str, ctail_read, &cb_interval, &ud);
+ plugin_register_complex_read (NULL, str, ctail_read, tail_match_list_intervals[i], &ud);
}
return (0);
diff --git a/src/tail_csv.c b/src/tail_csv.c
index c3efcc9a3d3c79c844590f5a898b5c45ccb00de0..bb9b58aceaa1edc459bbf7220f581c5e796997db 100644 (file)
--- a/src/tail_csv.c
+++ b/src/tail_csv.c
#include <string.h>
struct metric_definition_s {
- char *name;
- char *type;
- char *instance;
- int data_source_type;
- int value_from;
+ char *name;
+ char *type;
+ char *instance;
+ int data_source_type;
+ ssize_t value_from;
struct metric_definition_s *next;
};
typedef struct metric_definition_s metric_definition_t;
struct instance_definition_s {
- char *instance;
- char *path;
- cu_tail_t *tail;
+ char *instance;
+ char *path;
+ cu_tail_t *tail;
metric_definition_t **metric_list;
- size_t metric_list_len;
- cdtime_t interval;
- int time_from;
+ size_t metric_list_len;
+ cdtime_t interval;
+ ssize_t time_from;
struct instance_definition_s *next;
};
typedef struct instance_definition_s instance_definition_t;
char **fields, size_t fields_num)
{
value_t v;
- cdtime_t t;
+ cdtime_t t = 0;
int status;
if (md->data_source_type == -1)
return (EINVAL);
- if (md->value_from >= fields_num)
+ assert (md->value_from >= 0);
+ if (((size_t) md->value_from) >= fields_num)
return (EINVAL);
- if (id->time_from >= 0 && (id->time_from >= fields_num))
- return (EINVAL);
-
- t = 0;
- if (id->time_from >= 0)
- t = parse_time (fields[id->time_from]);
-
status = parse_value (fields[md->value_from], &v, md->data_source_type);
if (status != 0)
return (status);
+ if (id->time_from >= 0) {
+ if (((size_t) id->time_from) >= fields_num)
+ return (EINVAL);
+ t = parse_time (fields[id->time_from]);
+ }
+
return (tcsv_submit (id, md, v, t));
}
-static _Bool tcsv_check_index (int index, size_t fields_num, char const *name)
+static _Bool tcsv_check_index (ssize_t index, size_t fields_num, char const *name)
{
if (index < 0)
return 1;
else if (((size_t) index) < fields_num)
return 1;
- ERROR ("tail_csv plugin: Metric \"%s\": Request for index %i when "
+ ERROR ("tail_csv plugin: Metric \"%s\": Request for index %zd when "
"only %zu fields are available.",
name, index, fields_num);
return (0);
tcsv_metric_definition_destroy (next);
}
-static int tcsv_config_get_index(oconfig_item_t *ci, int *ret_index) {
- int index;
-
+static int tcsv_config_get_index(oconfig_item_t *ci, ssize_t *ret_index) {
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)){
WARNING("tail_csv plugin: The \"%s\" config option needs exactly one "
"integer argument.", ci->key);
return (-1);
}
- index = (int) ci->values[0].value.number;
- if (index < 0) {
+ if (ci->values[0].value.number < 0) {
WARNING("tail_csv plugin: The \"%s\" config option must be positive "
"(or zero).", ci->key);
return (-1);
}
- *ret_index = index;
+ *ret_index = (ssize_t) ci->values[0].value.number;
return (0);
}
/* Parse metric */
static int tcsv_config_add_metric(oconfig_item_t *ci){
metric_definition_t *md;
- int status = 0;
+ int status;
int i;
md = (metric_definition_t *)malloc(sizeof(*md));
/* Registration variables */
char cb_name[DATA_MAX_NAME_LEN];
user_data_t cb_data;
- struct timespec cb_interval;
id = malloc(sizeof(*id));
if (id == NULL)
memset(&cb_data, 0, sizeof(cb_data));
cb_data.data = id;
cb_data.free_func = tcsv_instance_definition_destroy;
- CDTIME_T_TO_TIMESPEC(id->interval, &cb_interval);
- status = plugin_register_complex_read(NULL, cb_name, tcsv_read, &cb_interval, &cb_data);
+ status = plugin_register_complex_read(NULL, cb_name, tcsv_read, id->interval, &cb_data);
if (status != 0){
ERROR("tail_csv plugin: Registering complex read function failed.");
}
else if (ds->ds_num != 1)
{
- ERROR ("tail_csv plugin: The type \"%s\" has %i data sources. "
+ ERROR ("tail_csv plugin: The type \"%s\" has %zu data sources. "
"Only types with a single data soure are supported.",
ds->type, ds->ds_num);
continue;
index ceb454ecba7bb6e8579e27044468c876310437e0..14fb5418addc659a5c429c03160ff3ef8e84871a 100644 (file)
gauge_t *rates;
int rates_failed;
- int i;
+ size_t i;
if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
return (-EINVAL);
diff --git a/src/target_replace.c b/src/target_replace.c
index a85eced33532a75b7e81732ec7755ded9d2c1f66..bd8f9e5c51d443650545bc94325fe53df25233e3 100644 (file)
--- a/src/target_replace.c
+++ b/src/target_replace.c
}
subst_status = subst (temp, sizeof (temp), buffer,
- matches[0].rm_so, matches[0].rm_eo, act->replacement);
+ (size_t) matches[0].rm_so, (size_t) matches[0].rm_eo, act->replacement);
if (subst_status == NULL)
{
ERROR ("Target `replace': subst (buffer = %s, start = %zu, end = %zu, "
diff --git a/src/target_scale.c b/src/target_scale.c
index b29a02bfa64801d9e967294ba4d1af7e6ce0cb48..6169fa05d585ce4c7a97abc6c882b80dbbeb78db 100644 (file)
--- a/src/target_scale.c
+++ b/src/target_scale.c
if (failure == 0)
{
- uint64_t difference;
+ uint64_t diff;
double rate;
- /* Calcualte the rate */
- if (prev_counter > curr_counter) /* => counter overflow */
- {
- if (prev_counter <= 4294967295UL) /* 32 bit overflow */
- difference = (4294967295UL - prev_counter) + curr_counter;
- else /* 64 bit overflow */
- difference = (18446744073709551615ULL - prev_counter) + curr_counter;
- }
- else /* no overflow */
- {
- difference = curr_counter - prev_counter;
- }
- rate = ((double) difference) / CDTIME_T_TO_DOUBLE (vl->interval);
+ diff = (uint64_t) counter_diff (prev_counter, curr_counter);
+ rate = ((double) diff) / CDTIME_T_TO_DOUBLE (vl->interval);
/* Modify the rate. */
if (!isnan (data->factor))
/* Calculate the internal counter. */
int_fraction += (rate * CDTIME_T_TO_DOUBLE (vl->interval));
- difference = (uint64_t) int_fraction;
- int_fraction -= ((double) difference);
- int_counter += difference;
+ diff = (uint64_t) int_fraction;
+ int_fraction -= ((double) diff);
+ int_counter += diff;
assert (int_fraction >= 0.0);
assert (int_fraction < 1.0);
notification_meta_t __attribute__((unused)) **meta, void **user_data)
{
ts_data_t *data;
- int i;
+ size_t i;
if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
return (-EINVAL);
diff --git a/src/tcpconns.c b/src/tcpconns.c
index 5d4bb6966f98b024e57ffc7fd0956082777212ab..5b47ff5354a090167992024e2d8ddfffebaec728 100644 (file)
--- a/src/tcpconns.c
+++ b/src/tcpconns.c
#if KERNEL_LINUX
# include <asm/types.h>
-/* sys/socket.h is necessary to compile when using netlink on older systems. */
-# include <sys/socket.h>
# include <linux/netlink.h>
#if HAVE_LINUX_INET_DIAG_H
# include <linux/inet_diag.h>
#endif
-# include <sys/socket.h>
# include <arpa/inet.h>
/* #endif KERNEL_LINUX */
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NET_IF_H
# include <net/if.h>
#endif
/* This is for OpenBSD and NetBSD. */
#elif HAVE_LIBKVM_NLIST
# include <sys/queue.h>
-# include <sys/socket.h>
# include <net/route.h>
# include <netinet/in.h>
# include <netinet/in_systm.h>
static uint32_t sequence_number = 0;
#endif
-enum
+static enum
{
SRC_DUNNO,
SRC_NETLINK,
diff --git a/src/teamspeak2.c b/src/teamspeak2.c
index 0e683ce9fc42cb17a3f18802904f90df94bc4bfd..058eb7c38362a7cc972ca609556698e1537933f6 100644 (file)
--- a/src/teamspeak2.c
+++ b/src/teamspeak2.c
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
-#include <sys/socket.h>
#include <netdb.h>
/*
diff --git a/src/ted.c b/src/ted.c
index 5dd75bc924b7bdea84f6664d89e8c85c77f33139..37ab85dd02e863834e054c167e22ad92ee0240d6 100644 (file)
--- a/src/ted.c
+++ b/src/ted.c
WARNING ("ted plugin: Received EOF from file descriptor.");
return (-1);
}
- else if (receive_buffer_length > sizeof (receive_buffer))
+ else if (((size_t) receive_buffer_length) > sizeof (receive_buffer))
{
ERROR ("ted plugin: read(2) returned invalid value %zi.",
receive_buffer_length);
return (0);
} /* int ted_open_device */
-static void ted_submit (char *type, double value)
+static void ted_submit (const char *type, double value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
diff --git a/src/testing.h b/src/testing.h
index 5df1b83a3e0f076b3a35bff53df09b021b9a0ea5..2e4bf054b3855ea9717a6e08d8e3d1aa08b2991c 100644 (file)
--- a/src/testing.h
+++ b/src/testing.h
/**
* collectd - src/tests/macros.h
- * Copyright (C) 2013 Florian octo Forster
+ * Copyright (C) 2013-2015 Florian octo Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* Florian octo Forster <octo at collectd.org>
*/
+#ifndef TESTING_H
+#define TESTING_H 1
+
+#include <inttypes.h>
+
static int fail_count__ = 0;
static int check_count__ = 0;
-#define DEF_TEST(func) static int test_##func ()
+#ifndef DBL_PRECISION
+# define DBL_PRECISION 1e-12
+#endif
+
+#define DEF_TEST(func) static int test_##func (void)
#define RUN_TEST(func) do { \
int status; \
#define OK1(cond, text) do { \
_Bool result = (cond); \
printf ("%s %i - %s\n", result ? "ok" : "not ok", ++check_count__, text); \
+ if (!result) { return -1; } \
} while (0)
#define OK(cond) OK1(cond, #cond)
-#define STREQ(expect, actual) do { \
+#define EXPECT_EQ_STR(expect, actual) do { \
if (strcmp (expect, actual) != 0) { \
- printf ("not ok %i - %s incorrect: expected \"%s\", got \"%s\"\n", \
- ++check_count__, #actual, expect, actual); \
+ printf ("not ok %i - %s = \"%s\", want \"%s\"\n", \
+ ++check_count__, #actual, actual, expect); \
return (-1); \
} \
- printf ("ok %i - %s evaluates to \"%s\"\n", ++check_count__, #actual, expect); \
+ printf ("ok %i - %s = \"%s\"\n", ++check_count__, #actual, actual); \
+} while (0)
+
+#define EXPECT_EQ_INT(expect, actual) do { \
+ int want__ = (int) expect; \
+ int got__ = (int) actual; \
+ if (got__ != want__) { \
+ printf ("not ok %i - %s = %d, want %d\n", \
+ ++check_count__, #actual, got__, want__); \
+ return (-1); \
+ } \
+ printf ("ok %i - %s = %d\n", ++check_count__, #actual, got__); \
+} while (0)
+
+#define EXPECT_EQ_UINT64(expect, actual) do { \
+ uint64_t want__ = (uint64_t) expect; \
+ uint64_t got__ = (uint64_t) actual; \
+ if (got__ != want__) { \
+ printf ("not ok %i - %s = %"PRIu64", want %"PRIu64"\n", \
+ ++check_count__, #actual, got__, want__); \
+ return (-1); \
+ } \
+ printf ("ok %i - %s = %"PRIu64"\n", ++check_count__, #actual, got__); \
+} while (0)
+
+#define EXPECT_EQ_DOUBLE(expect, actual) do { \
+ double want__ = (double) expect; \
+ double got__ = (double) actual; \
+ if (isnan (want__) && !isnan (got__)) { \
+ printf ("not ok %i - %s = %.15g, want %.15g\n", \
+ ++check_count__, #actual, got__, want__); \
+ return (-1); \
+ } else if (!isnan (want__) && (((want__-got__) < -DBL_PRECISION) || ((want__-got__) > DBL_PRECISION))) { \
+ printf ("not ok %i - %s = %.15g, want %.15g\n", \
+ ++check_count__, #actual, got__, want__); \
+ return (-1); \
+ } \
+ printf ("ok %i - %s = %.15g\n", ++check_count__, #actual, got__); \
} while (0)
#define CHECK_NOT_NULL(expr) do { \
status_ = (long) (expr); \
OK1(status_ == 0L, #expr); \
} while (0)
+
+#endif /* TESTING_H */
diff --git a/src/thermal.c b/src/thermal.c
index 27c92bc730c65b44c54c25bd9dc27a75c279980c..54311a647cc786aa40c27e85b4b1a514e0dbad11 100644 (file)
--- a/src/thermal.c
+++ b/src/thermal.c
"ForceUseProcfs"
};
-const char *const dirname_sysfs = "/sys/class/thermal";
-const char *const dirname_procfs = "/proc/acpi/thermal_zone";
+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 ignorelist_t *device_list;
diff --git a/src/threshold.c b/src/threshold.c
index 45ee3b4d02c61b722419577ee607580dcdb4cb26..ed8312992b437c9984d6885309bc972f1450fb4d 100644 (file)
--- a/src/threshold.c
+++ b/src/threshold.c
{
gauge_t value;
gauge_t sum;
- int i;
+ size_t i;
sum = 0.0;
for (i = 0; i < vl->values_len; i++)
{ /* {{{ */
int ret = -1;
int ds_index = -1;
- int i;
+ size_t i;
gauge_t values_copy[ds->ds_num];
memcpy (values_copy, values, sizeof (values_copy));
diff --git a/src/tokyotyrant.c b/src/tokyotyrant.c
index f04a5fceb3a51b9ae3b9738d505f5ee977b896f3..befbd50a91c52d1464e03934076ec7145c40b209 100644 (file)
--- a/src/tokyotyrant.c
+++ b/src/tokyotyrant.c
static void tt_open_db (void)
{
- char* host = NULL;
- int port = DEFAULT_PORT;
+ const char *host;
+ int port = DEFAULT_PORT;
if (rdb != NULL)
return;
diff --git a/src/types.db b/src/types.db
index 303f605b08dc2d4886c281b80deaa641b4b0dc0a..d5034e95a5c1eee771b6cd251aa4a36e5465c33f 100644 (file)
--- a/src/types.db
+++ b/src/types.db
cache_operation value:DERIVE:0:U
cache_ratio value:GAUGE:0:100
cache_result value:DERIVE:0:U
-cache_size value:GAUGE:0:U
+cache_size value:GAUGE:0:1125899906842623
capacity value:GAUGE:0:U
ceph_bytes value:GAUGE:U:U
ceph_latency value:GAUGE:U:U
email_size value:GAUGE:0:U
entropy value:GAUGE:0:4294967295
expired_keys value:DERIVE:0:U
+evicted_keys value:DERIVE:0:U
fanspeed value:GAUGE:0:U
file_handles value:GAUGE:0:U
file_size value:GAUGE:0:U
diff --git a/src/unixsock.c b/src/unixsock.c
index e62ed6c0596b5ddb29848e66805d6e5ffd036f1c..795f7abe2120f7e4d4930895f9c1af014a7addeb 100644 (file)
--- a/src/unixsock.c
+++ b/src/unixsock.c
/* Folks without pthread will need to disable this plugin. */
#include <pthread.h>
-#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
do
{
- char *grpname;
+ const char *grpname;
struct group *g;
struct group sg;
char grbuf[2048];
diff --git a/src/utils_cmd_flush.c b/src/utils_cmd_flush.c
index a01d2343c9cb46f904dd295988f10fa9731418ca..410616640bd00ae5e1d2ebe9aa502e3af111e6ea 100644 (file)
--- a/src/utils_cmd_flush.c
+++ b/src/utils_cmd_flush.c
for (i = 0; (i == 0) || (i < plugins_num); i++)
{
char *plugin = NULL;
- int j;
+ size_t j;
if (plugins_num != 0)
plugin = plugins[i];
diff --git a/src/utils_cmd_getval.c b/src/utils_cmd_getval.c
index 2d162224a4034bcf212845efe066c8a44f01af1c..4d679f000e1650a51224767eea4e2ee5ab3702ac 100644 (file)
--- a/src/utils_cmd_getval.c
+++ b/src/utils_cmd_getval.c
return (-1);
}
- if ((size_t) ds->ds_num != values_num)
+ if (ds->ds_num != values_num)
{
- ERROR ("ds[%s]->ds_num = %i, "
- "but uc_get_rate_by_name returned %u values.",
- ds->type, ds->ds_num, (unsigned int) values_num);
+ ERROR ("ds[%s]->ds_num = %zu, "
+ "but uc_get_rate_by_name returned %zu values.",
+ ds->type, ds->ds_num, values_num);
print_to_socket (fh, "-1 Error reading value from cache.\n");
sfree (values);
sfree (identifier_copy);
return (-1);
}
- print_to_socket (fh, "%u Value%s found\n", (unsigned int) values_num,
+ print_to_socket (fh, "%zu Value%s found\n", values_num,
(values_num == 1) ? "" : "s");
for (i = 0; i < values_num; i++)
{
diff --git a/src/utils_db_query.c b/src/utils_db_query.c
index 36181ee1423a9832692dd4c190984ee4b013d859..c7be9f0d49445b8efe6e390885e535678d7e3424 100644 (file)
--- a/src/utils_db_query.c
+++ b/src/utils_db_query.c
BAIL_OUT (-1);
}
- if (((size_t) prep_area->ds->ds_num) != r->values_num)
+ if (prep_area->ds->ds_num != r->values_num)
{
ERROR ("db query utils: udb_result_prepare_result: The type `%s' "
- "requires exactly %i value%s, but the configuration specifies %zu.",
+ "requires exactly %zu value%s, but the configuration specifies %zu.",
r->type,
prep_area->ds->ds_num, (prep_area->ds->ds_num == 1) ? "" : "s",
r->values_num);
diff --git a/src/utils_dns.c b/src/utils_dns.c
index 6abfde16fba0f5cd2da6e1da4f98832717f48519..2c7a59d343fb938ea7017c162317791830dbf646 100644 (file)
--- a/src/utils_dns.c
+++ b/src/utils_dns.c
#include "plugin.h"
#include "common.h"
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-
#if HAVE_NET_IF_ARP_H
# include <net/if_arp.h>
#endif
#if HAVE_NETINET_IP6_H
# include <netinet/ip6.h>
#endif
-#if HAVE_NETINET_IP_COMPAT_H
-# include <netinet/ip_compat.h>
-#endif
#if HAVE_NETINET_IF_ETHER_H
# include <netinet/if_ether.h>
#endif
/*
* Global variables
*/
-int qtype_counts[T_MAX];
-int opcode_counts[OP_MAX];
-int qclass_counts[C_MAX];
#if HAVE_PCAP_H
static pcap_t *pcap_obj = NULL;
@@ -305,7 +295,7 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
if (ns <= 0)
return 4; /* probably compression loop */
do {
- if ((*off) >= sz)
+ if ((*off) >= ((off_t) sz))
break;
c = *(buf + (*off));
if (c > 191) {
@@ -317,11 +307,11 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
s = ntohs(s);
(*off) += sizeof(s);
/* Sanity check */
- if ((*off) >= sz)
+ if ((*off) >= ((off_t) sz))
return 1; /* message too short */
ptr = s & 0x3FFF;
/* Make sure the pointer is inside this message */
- if (ptr >= sz)
+ if (ptr >= ((off_t) sz))
return 2; /* bad compression ptr */
if (ptr < DNS_MSG_HDR_SZ)
return 2; /* bad compression ptr */
@@ -355,7 +345,7 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
if (no > 0)
*(name + no - 1) = '\0';
/* make sure we didn't allow someone to overflow the name buffer */
- assert(no <= ns);
+ assert(no <= ((off_t) ns));
return 0;
}
qh.length = (uint16_t) len;
- /* gather stats */
- qtype_counts[qh.qtype]++;
- qclass_counts[qh.qclass]++;
- opcode_counts[qh.opcode]++;
-
if (Callback != NULL)
Callback (&qh);
diff --git a/src/utils_dns.h b/src/utils_dns.h
index 83f0ea403e9809ab68c9261299119aa1537278d1..ef7de0a6ec8469b251d70d4664dc0d1b2cde784e 100644 (file)
--- a/src/utils_dns.h
+++ b/src/utils_dns.h
#define DNS_MSG_HDR_SZ 12
#define T_MAX 65536
-#define OP_MAX 16
-#define C_MAX 65536
#define MAX_QNAME_SZ 512
struct rfc1035_header_s {
};
typedef struct rfc1035_header_s rfc1035_header_t;
-extern int qtype_counts[T_MAX];
-extern int opcode_counts[OP_MAX];
-extern int qclass_counts[C_MAX];
-
#if HAVE_PCAP_H
void dnstop_set_pcap_obj (pcap_t *po);
#endif
index 023f7a46a5240f7a7f52e3c9d6f237c91f932223..eb5b4b327119210c4f2c6424ae99c47b3ec1dc5a 100644 (file)
unsigned int flags)
{
int status = 0;
- int i;
+ size_t i;
int buffer_pos = 0;
gauge_t *rates = NULL;
index 020d80beacb5f8401d26ec891a202cd2da226db1..2c0e4cd029b3f29c3b05521f1171541c9f591679 100644 (file)
--- a/src/utils_format_json.c
+++ b/src/utils_format_json.c
const data_set_t *ds, const value_list_t *vl, int store_rates)
{
size_t offset = 0;
- int i;
+ size_t i;
gauge_t *rates = NULL;
memset (buffer, 0, buffer_size);
const data_set_t *ds)
{
size_t offset = 0;
- int i;
+ size_t i;
memset (buffer, 0, buffer_size);
const data_set_t *ds)
{
size_t offset = 0;
- int i;
+ size_t i;
memset (buffer, 0, buffer_size);
diff --git a/src/utils_latency_test.c b/src/utils_latency_test.c
--- /dev/null
+++ b/src/utils_latency_test.c
@@ -0,0 +1,108 @@
+/**
+ * collectd - src/utils_latency_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#define DBL_PRECISION 1e-9
+
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "collectd.h"
+#include "testing.h"
+#include "utils_time.h"
+#include "utils_latency.h"
+
+DEF_TEST(simple)
+{
+ struct {
+ double val;
+ double min;
+ double max;
+ double sum;
+ double avg;
+ } cases[] = {
+ /* val min max sum avg */
+ {0.5, 0.5, 0.5, 0.5, 0.5},
+ {0.3, 0.3, 0.5, 0.8, 0.4},
+ {0.7, 0.3, 0.7, 1.5, 0.5},
+ {2.5, 0.3, 2.5, 4.0, 1.0},
+ { 99, 0.3, 99, 103, 20.6},
+ /* { -1, 0.3, 99, 103, 20.6}, see issue #1139 */
+ };
+ size_t i;
+ latency_counter_t *l;
+
+ CHECK_NOT_NULL (l = latency_counter_create ());
+
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ printf ("# case %zu: DOUBLE_TO_CDTIME_T(%g) = %"PRIu64"\n",
+ i, cases[i].val, DOUBLE_TO_CDTIME_T (cases[i].val));
+ latency_counter_add (l, DOUBLE_TO_CDTIME_T (cases[i].val));
+
+ EXPECT_EQ_DOUBLE (cases[i].min, CDTIME_T_TO_DOUBLE (latency_counter_get_min (l)));
+ EXPECT_EQ_DOUBLE (cases[i].max, CDTIME_T_TO_DOUBLE (latency_counter_get_max (l)));
+ EXPECT_EQ_DOUBLE (cases[i].sum, CDTIME_T_TO_DOUBLE (latency_counter_get_sum (l)));
+ EXPECT_EQ_DOUBLE (cases[i].avg, CDTIME_T_TO_DOUBLE (latency_counter_get_average (l)));
+ }
+
+ latency_counter_destroy (l);
+ return 0;
+}
+
+DEF_TEST(percentile)
+{
+ size_t i;
+ latency_counter_t *l;
+
+ CHECK_NOT_NULL (l = latency_counter_create ());
+
+ for (i = 0; i < 100; i++) {
+ latency_counter_add (l, TIME_T_TO_CDTIME_T (((time_t) i) + 1));
+ }
+
+ EXPECT_EQ_DOUBLE ( 1.0, CDTIME_T_TO_DOUBLE (latency_counter_get_min (l)));
+ EXPECT_EQ_DOUBLE (100.0, CDTIME_T_TO_DOUBLE (latency_counter_get_max (l)));
+ EXPECT_EQ_DOUBLE (100.0 * 101.0 / 2.0, CDTIME_T_TO_DOUBLE (latency_counter_get_sum (l)));
+ EXPECT_EQ_DOUBLE ( 50.5, CDTIME_T_TO_DOUBLE (latency_counter_get_average (l)));
+
+ EXPECT_EQ_DOUBLE (50.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 50.0)));
+ EXPECT_EQ_DOUBLE (80.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 80.0)));
+ EXPECT_EQ_DOUBLE (95.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 95.0)));
+ EXPECT_EQ_DOUBLE (99.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 99.0)));
+
+ CHECK_ZERO (latency_counter_get_percentile (l, -1.0));
+ CHECK_ZERO (latency_counter_get_percentile (l, 101.0));
+
+ latency_counter_destroy (l);
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(simple);
+ RUN_TEST(percentile);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/utils_mount.c b/src/utils_mount.c
index da53b980eee91537c9aecdbfef118b835bcea8d1..752d2e158a597e2b3b9e893d57c2d8267d1c71de 100644 (file)
--- a/src/utils_mount.c
+++ b/src/utils_mount.c
} /* void cu_mount_freelist(cu_mount_t *list) */
char *
-cu_mount_checkoption(char *line, char *keyword, int full)
+cu_mount_checkoption(char *line, const char *keyword, int full)
{
char *line2, *l2, *p1, *p2;
int l;
} /* char *cu_mount_checkoption(char *line, char *keyword, int full) */
char *
-cu_mount_getoptionvalue(char *line, char *keyword)
+cu_mount_getoptionvalue(char *line, const char *keyword)
{
char *r;
}
}
return r;
-} /* char *cu_mount_getoptionvalue(char *line, char *keyword) */
+} /* char *cu_mount_getoptionvalue(char *line, const char *keyword) */
int
cu_mount_type(const char *type)
diff --git a/src/utils_mount.h b/src/utils_mount.h
index 7518188dee7e048793802fac33f6824a90d3e434..0a5c980f39be58cd87df3d06667e220677d788af 100644 (file)
--- a/src/utils_mount.h
+++ b/src/utils_mount.h
allocated by *list and *list itself as well.
*/
-char *cu_mount_checkoption(char *line, char *keyword, int full);
+char *cu_mount_checkoption(char *line, const char *keyword, int full);
/*
DESCRIPTION
The cu_mount_checkoption() function is a replacement of
maybe you might want to try cu_mount_getoptionvalue()...
*/
-char *cu_mount_getoptionvalue(char *line, char *keyword);
+char *cu_mount_getoptionvalue(char *line, const char *keyword);
/*
DESCRIPTION
The cu_mount_getoptionvalue() function can be used to grab
diff --git a/src/utils_mount_test.c b/src/utils_mount_test.c
index c5ffbfbcf9fb9d701db96f02aafa1cc9873b4790..d9d685ae7bf09fafca10fb1278a97d0fb84a6d87 100644 (file)
--- a/src/utils_mount_test.c
+++ b/src/utils_mount_test.c
* Florian octo Forster <octo at collectd.org>
*/
-#include "testing.h"
#include "collectd.h"
+#include "testing.h"
#include "utils_mount.h"
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc;
+#endif /* HAVE_LIBKSTAT */
+
DEF_TEST(cu_mount_checkoption)
{
char line_opts[] = "foo=one,bar=two,qux=three";
char line_opts[] = "foo=one,bar=two,qux=three";
char line_bool[] = "one,two,three";
- STREQ ("one", cu_mount_getoptionvalue (line_opts, "foo="));
- STREQ ("two", cu_mount_getoptionvalue (line_opts, "bar="));
- STREQ ("three", cu_mount_getoptionvalue (line_opts, "qux="));
+ EXPECT_EQ_STR ("one", cu_mount_getoptionvalue (line_opts, "foo="));
+ EXPECT_EQ_STR ("two", cu_mount_getoptionvalue (line_opts, "bar="));
+ EXPECT_EQ_STR ("three", cu_mount_getoptionvalue (line_opts, "qux="));
OK (NULL == cu_mount_getoptionvalue (line_opts, "unknown="));
- STREQ ("", cu_mount_getoptionvalue (line_bool, "one"));
- STREQ ("", cu_mount_getoptionvalue (line_bool, "two"));
- STREQ ("", cu_mount_getoptionvalue (line_bool, "three"));
+ EXPECT_EQ_STR ("", cu_mount_getoptionvalue (line_bool, "one"));
+ EXPECT_EQ_STR ("", cu_mount_getoptionvalue (line_bool, "two"));
+ EXPECT_EQ_STR ("", cu_mount_getoptionvalue (line_bool, "three"));
OK (NULL == cu_mount_getoptionvalue (line_bool, "four"));
return (0);
diff --git a/src/utils_rrdcreate.c b/src/utils_rrdcreate.c
index 5add32373cd3d91f861265df88dc459d4bb57c99..06e4f21b7acfc517a0445ed64627ab0ca0b21f36 100644 (file)
--- a/src/utils_rrdcreate.c
+++ b/src/utils_rrdcreate.c
};
static int rra_timespans_num = STATIC_ARRAY_SIZE (rra_timespans);
-static char *rra_types[] =
+static const char *const rra_types[] =
{
"AVERAGE",
"MIN",
const rrdcreate_config_t *cfg)
{
char **ds_def;
- int ds_num;
+ size_t ds_num;
char min[32];
char max[32];
for (ds_num = 0; ds_num < ds->ds_num; ds_num++)
{
data_source_t *d = ds->ds + ds_num;
- char *type;
+ const char *type;
int status;
ds_def[ds_num] = NULL;
diff --git a/src/utils_vl_lookup.c b/src/utils_vl_lookup.c
index f0f0b4632ecafda01572e7d3252e25fc77c5136d..f85910e1737e7b5d1c328a6e9e15896be2d60d99 100644 (file)
--- a/src/utils_vl_lookup.c
+++ b/src/utils_vl_lookup.c
#include "utils_vl_lookup.h"
#include "utils_avltree.h"
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc;
+#endif /* HAVE_LIBKSTAT */
+
#if BUILD_TEST
# define sstrncpy strncpy
# define plugin_log(s, ...) do { \
index 6a2676a89e1d8ccee1cddc6735d2f5e7d9335ff7..6d23c8c5e32ea3e0dc66137edd1ef591f0c8b016 100644 (file)
* Florian Forster <octo at collectd.org>
**/
-#include "testing.h"
#include "collectd.h"
+#include "testing.h"
#include "utils_vl_lookup.h"
static _Bool expect_new_obj = 0;
identifier_t *class = user_class;
identifier_t *obj;
- OK(expect_new_obj);
+ assert (expect_new_obj);
memcpy (&last_class_ident, class, sizeof (last_class_ident));
return ((void *) obj);
}
-static void checked_lookup_add (lookup_t *obj, /* {{{ */
+static int checked_lookup_add (lookup_t *obj, /* {{{ */
char const *host,
char const *plugin, char const *plugin_instance,
char const *type, char const *type_instance,
memmove (user_class, &ident, sizeof (ident));
OK(lookup_add (obj, &ident, group_by, user_class) == 0);
-} /* }}} void test_add */
+ return 0;
+} /* }}} int checked_lookup_add */
static int checked_lookup_search (lookup_t *obj,
char const *host,
return (status);
}
-static lookup_t *checked_lookup_create (void)
-{
- lookup_t *obj = lookup_create (
- lookup_class_callback,
- lookup_obj_callback,
- (void *) free,
- (void *) free);
- OK(obj != NULL);
- return (obj);
-}
-
DEF_TEST(group_by_specific_host)
{
- lookup_t *obj = checked_lookup_create ();
+ lookup_t *obj;
+ CHECK_NOT_NULL (obj = lookup_create (
+ lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
checked_lookup_add (obj, "/.*/", "test", "", "test", "/.*/", LU_GROUP_BY_HOST);
checked_lookup_search (obj, "host0", "test", "", "test", "0",
DEF_TEST(group_by_any_host)
{
- lookup_t *obj = checked_lookup_create ();
+ lookup_t *obj;
+ CHECK_NOT_NULL (obj = lookup_create (
+ lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
checked_lookup_add (obj, "/.*/", "/.*/", "/.*/", "test", "/.*/", LU_GROUP_BY_HOST);
checked_lookup_search (obj, "host0", "plugin0", "", "test", "0",
DEF_TEST(multiple_lookups)
{
- lookup_t *obj = checked_lookup_create ();
+ lookup_t *obj;
int status;
+ CHECK_NOT_NULL (obj = lookup_create (
+ lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
+
checked_lookup_add (obj, "/.*/", "plugin0", "", "test", "/.*/", LU_GROUP_BY_HOST);
checked_lookup_add (obj, "/.*/", "/.*/", "", "test", "ti0", LU_GROUP_BY_HOST);
DEF_TEST(regex)
{
- lookup_t *obj = checked_lookup_create ();
+ lookup_t *obj;
+ CHECK_NOT_NULL (obj = lookup_create (
+ lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
checked_lookup_add (obj, "/^db[0-9]\\./", "cpu", "/.*/", "cpu", "/.*/",
LU_GROUP_BY_TYPE_INSTANCE);
diff --git a/src/varnish.c b/src/varnish.c
index a138d1813ffaa5109a9310714744a3404e9d6891..aee72471a4d6b62d8e8d13266b47e8ff742b34a0 100644 (file)
--- a/src/varnish.c
+++ b/src/varnish.c
{
struct VSM_data *vd;
const c_varnish_stats_t *stats;
+ _Bool ok;
user_config_t *conf;
}
#if HAVE_VARNISH_V3
- if (VSC_Open (vd, /* diag = */ 1))
+ ok = (VSC_Open (vd, /* diag = */ 1) == 0);
#else /* if HAVE_VARNISH_V4 */
- if (VSM_Open (vd))
+ ok = (VSM_Open (vd) == 0);
#endif
+ if (!ok)
{
VSM_Delete (vd);
ERROR ("varnish plugin: Unable to open connection.");
plugin_register_complex_read (/* group = */ "varnish",
/* name = */ "varnish/localhost",
/* callback = */ varnish_read,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user data = */ &ud);
return (0);
plugin_register_complex_read (/* group = */ "varnish",
/* name = */ callback_name,
/* callback = */ varnish_read,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user data = */ &ud);
have_instance = 1;
diff --git a/src/virt.c b/src/virt.c
index c9355c4a1cd961417ce8611befb2c1454c488bfe..79d46826997d2222590839769137a0ea28155c34 100644 (file)
--- a/src/virt.c
+++ b/src/virt.c
};
static enum plginst_field plugin_instance_format[PLGINST_MAX_FIELDS] =
- { plginst_name };
+ { plginst_none };
/* InterfaceFormat. */
enum if_field {
}
for (i = 0; i < n; ++i) {
- if (strcasecmp (fields[i], "name") == 0)
+ if (strcasecmp (fields[i], "none") == 0) {
+ plugin_instance_format[i] = plginst_none;
+ break;
+ } else if (strcasecmp (fields[i], "name") == 0)
plugin_instance_format[i] = plginst_name;
else if (strcasecmp (fields[i], "uuid") == 0)
plugin_instance_format[i] = plginst_uuid;
}
static void
-free_domains ()
+free_domains (void)
{
int i;
}
static void
-free_block_devices ()
+free_block_devices (void)
{
int i;
}
static void
-free_interface_devices ()
+free_interface_devices (void)
{
int i;
diff --git a/src/vserver.c b/src/vserver.c
index bd2e867384870ef7212af60d88d678b21bdd3db5..6c09f439b1a157e1c8b29d41796fa0f4b0ef3b22 100644 (file)
--- a/src/vserver.c
+++ b/src/vserver.c
{
derive_t rx;
derive_t tx;
- char *type_instance;
+ const char *type_instance;
if (strsplit (buffer, cols, 4) < 4)
continue;
if (2 == n)
{
- char *type_instance;
+ const char *type_instance;
gauge_t value;
if (0 == strcmp (cols[0], "nr_threads:"))
while ((fh != NULL) && (NULL != fgets (buffer, BUFSIZE, fh)))
{
- char *type = "vs_memory";
- char *type_instance;
+ const char *type = "vs_memory";
+ const char *type_instance;
gauge_t value;
if (strsplit (buffer, cols, 2) < 2)
diff --git a/src/write_graphite.c b/src/write_graphite.c
index a7eef3fb435616ca6093207c385eb8ba90a104a2..6baace14410e48f72761d21d6d2db1c9fdb854ad 100644 (file)
--- a/src/write_graphite.c
+++ b/src/write_graphite.c
/* Folks without pthread will need to disable this plugin. */
#include <pthread.h>
-#include <sys/socket.h>
#include <netdb.h>
-#ifndef WG_DEFAULT_NODE
-# define WG_DEFAULT_NODE "localhost"
-#endif
-
-#ifndef WG_DEFAULT_SERVICE
-# define WG_DEFAULT_SERVICE "2003"
-#endif
-
-#ifndef WG_DEFAULT_PROTOCOL
-# define WG_DEFAULT_PROTOCOL "tcp"
-#endif
-
-#ifndef WG_DEFAULT_LOG_SEND_ERRORS
-# define WG_DEFAULT_LOG_SEND_ERRORS 1
-#endif
-
-#ifndef WG_DEFAULT_ESCAPE
-# define WG_DEFAULT_ESCAPE '_'
-#endif
+#define WG_DEFAULT_NODE "localhost"
+#define WG_DEFAULT_SERVICE "2003"
+#define WG_DEFAULT_PROTOCOL "tcp"
+#define WG_DEFAULT_LOG_SEND_ERRORS 1
+#define WG_DEFAULT_ESCAPE '_'
/* Ethernet - (IPv6 + TCP) = 1500 - (40 + 32) = 1428 */
-#ifndef WG_SEND_BUF_SIZE
-# define WG_SEND_BUF_SIZE 1428
-#endif
+#define WG_SEND_BUF_SIZE 1428
-#ifndef WG_MIN_RECONNECT_INTERVAL
-# define WG_MIN_RECONNECT_INTERVAL TIME_T_TO_CDTIME_T (1)
-#endif
+#define WG_MIN_RECONNECT_INTERVAL TIME_T_TO_CDTIME_T (1)
/*
* Private variables
pthread_mutex_t send_lock;
c_complain_t init_complaint;
cdtime_t last_connect_time;
+
+ /* Force reconnect useful for load balanced environments */
+ cdtime_t last_reconnect_time;
+ cdtime_t reconnect_interval;
+ _Bool reconnect_interval_reached;
};
+/* wg_force_reconnect_check closes cb->sock_fd when it was open for longer
+ * than cb->reconnect_interval. Must hold cb->send_lock when calling. */
+static void wg_force_reconnect_check (struct wg_callback *cb)
+{
+ cdtime_t now;
+
+ if (cb->reconnect_interval == 0)
+ return;
+
+ /* check if address changes if addr_timeout */
+ now = cdtime ();
+ if ((now - cb->last_reconnect_time) < cb->reconnect_interval)
+ return;
+
+ /* here we should close connection on next */
+ close (cb->sock_fd);
+ cb->sock_fd = -1;
+ cb->last_reconnect_time = now;
+ cb->reconnect_interval_reached = 1;
+
+ INFO ("write_graphite plugin: Connection closed after %.3f seconds.",
+ CDTIME_T_TO_DOUBLE (now - cb->last_reconnect_time));
+}
/*
* Functions
status = swrite (cb->sock_fd, cb->send_buf, strlen (cb->send_buf));
if (status != 0)
{
- const char *protocol = cb->protocol ? cb->protocol : WG_DEFAULT_PROTOCOL;
-
if (cb->log_send_errors)
{
char errbuf[1024];
ERROR ("write_graphite plugin: send to %s:%s (%s) failed with status %zi (%s)",
- cb->node, cb->service, protocol,
+ cb->node, cb->service, cb->protocol,
status, sstrerror (errno, errbuf, sizeof (errbuf)));
}
cdtime_t now;
int status;
- const char *node = cb->node ? cb->node : WG_DEFAULT_NODE;
- const char *service = cb->service ? cb->service : WG_DEFAULT_SERVICE;
- const char *protocol = cb->protocol ? cb->protocol : WG_DEFAULT_PROTOCOL;
-
char connerr[1024] = "";
if (cb->sock_fd > 0)
#endif
ai_hints.ai_family = AF_UNSPEC;
- if (0 == strcasecmp ("tcp", protocol))
+ if (0 == strcasecmp ("tcp", cb->protocol))
ai_hints.ai_socktype = SOCK_STREAM;
else
ai_hints.ai_socktype = SOCK_DGRAM;
ai_list = NULL;
- status = getaddrinfo (node, service, &ai_hints, &ai_list);
+ status = getaddrinfo (cb->node, cb->service, &ai_hints, &ai_list);
if (status != 0)
{
ERROR ("write_graphite plugin: getaddrinfo (%s, %s, %s) failed: %s",
- node, service, protocol, gai_strerror (status));
+ cb->node, cb->service, cb->protocol, gai_strerror (status));
return (-1);
}
sstrerror (errno, connerr, sizeof (connerr));
c_complain (LOG_ERR, &cb->init_complaint,
"write_graphite plugin: Connecting to %s:%s via %s failed. "
- "The last error was: %s", node, service, protocol, connerr);
+ "The last error was: %s", cb->node, cb->service, cb->protocol, connerr);
return (-1);
}
else
{
c_release (LOG_INFO, &cb->init_complaint,
"write_graphite plugin: Successfully connected to %s:%s via %s.",
- node, service, protocol);
+ cb->node, cb->service, cb->protocol);
}
- wg_reset_buffer (cb);
+ /* wg_force_reconnect_check does not flush the buffer before closing a
+ * sending socket, so only call wg_reset_buffer() if the socket was closed
+ * for a different reason (tracked in cb->reconnect_interval_reached). */
+ if (!cb->reconnect_interval_reached || (cb->send_buf_free == 0))
+ wg_reset_buffer (cb);
+ else
+ cb->reconnect_interval_reached = 0;
return (0);
}
pthread_mutex_lock (&cb->send_lock);
+ wg_force_reconnect_check (cb);
+
if (cb->sock_fd < 0)
{
status = wg_callback_init (cb);
cb->send_buf_free -= message_len;
DEBUG ("write_graphite plugin: [%s]:%s (%s) buf %zu/%zu (%.1f %%) \"%s\"",
- cb->node,
- cb->service,
- cb->protocol,
+ cb->node, cb->service, cb->protocol,
cb->send_buf_fill, sizeof (cb->send_buf),
100.0 * ((double) cb->send_buf_fill) / ((double) sizeof (cb->send_buf)),
message);
memset (cb, 0, sizeof (*cb));
cb->sock_fd = -1;
cb->name = NULL;
- cb->node = NULL;
- cb->service = NULL;
- cb->protocol = NULL;
+ cb->node = strdup (WG_DEFAULT_NODE);
+ cb->service = strdup (WG_DEFAULT_SERVICE);
+ cb->protocol = strdup (WG_DEFAULT_PROTOCOL);
+ cb->last_reconnect_time = cdtime();
+ cb->reconnect_interval = 0;
+ cb->reconnect_interval_reached = 0;
cb->log_send_errors = WG_DEFAULT_LOG_SEND_ERRORS;
cb->prefix = NULL;
cb->postfix = NULL;
status = -1;
}
}
+ else if (strcasecmp ("ReconnectInterval", child->key) == 0)
+ cf_util_get_cdtime (child, &cb->reconnect_interval);
else if (strcasecmp ("LogSendErrors", child->key) == 0)
cf_util_get_boolean (child, &cb->log_send_errors);
else if (strcasecmp ("Prefix", child->key) == 0)
/* FIXME: Legacy configuration syntax. */
if (cb->name == NULL)
ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s/%s/%s",
- cb->node != NULL ? cb->node : WG_DEFAULT_NODE,
- cb->service != NULL ? cb->service : WG_DEFAULT_SERVICE,
- cb->protocol != NULL ? cb->protocol : WG_DEFAULT_PROTOCOL);
+ cb->node, cb->service, cb->protocol);
else
ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s",
cb->name);
diff --git a/src/write_http.c b/src/write_http.c
index 65197e6c64f1fcedda9e4b75a52a82ffe49860a5..ec3a01ce228aeb7798a611333b90fdb9d2b4630d 100644 (file)
--- a/src/write_http.c
+++ b/src/write_http.c
char *clientkeypass;
long sslversion;
_Bool store_rates;
+ _Bool log_http_error;
int low_speed_limit;
time_t low_speed_time;
int timeout;
};
typedef struct wh_callback_s wh_callback_t;
+static void wh_log_http_error (wh_callback_t *cb)
+{
+ if (!cb->log_http_error)
+ return;
+
+ long http_code = 0;
+
+ curl_easy_getinfo (cb->curl, CURLINFO_RESPONSE_CODE, &http_code);
+
+ if (http_code != 200)
+ INFO ("write_http plugin: HTTP Error code: %lu", http_code);
+}
+
static void wh_reset_buffer (wh_callback_t *cb) /* {{{ */
{
memset (cb->send_buffer, 0, cb->send_buffer_size);
curl_easy_setopt (cb->curl, CURLOPT_POSTFIELDS, cb->send_buffer);
status = curl_easy_perform (cb->curl);
+
+ wh_log_http_error (cb);
+
if (status != CURLE_OK)
{
ERROR ("write_http plugin: curl_easy_perform failed with "
int buffer_size = 0;
user_data_t user_data;
char callback_name[DATA_MAX_NAME_LEN];
+ int status = 0;
int i;
cb = malloc (sizeof (*cb));
cb->sslversion = CURL_SSLVERSION_DEFAULT;
cb->low_speed_limit = 0;
cb->timeout = 0;
+ cb->log_http_error = 0;
cb->headers = NULL;
+
pthread_mutex_init (&cb->send_lock, /* attr = */ NULL);
cf_util_get_string (ci, &cb->name);
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("URL", child->key) == 0)
- cf_util_get_string (child, &cb->location);
+ status = cf_util_get_string (child, &cb->location);
else if (strcasecmp ("User", child->key) == 0)
- cf_util_get_string (child, &cb->user);
+ status = cf_util_get_string (child, &cb->user);
else if (strcasecmp ("Password", child->key) == 0)
- cf_util_get_string (child, &cb->pass);
+ status = cf_util_get_string (child, &cb->pass);
else if (strcasecmp ("VerifyPeer", child->key) == 0)
- cf_util_get_boolean (child, &cb->verify_peer);
+ status = cf_util_get_boolean (child, &cb->verify_peer);
else if (strcasecmp ("VerifyHost", child->key) == 0)
- cf_util_get_boolean (child, &cb->verify_host);
+ status = cf_util_get_boolean (child, &cb->verify_host);
else if (strcasecmp ("CACert", child->key) == 0)
- cf_util_get_string (child, &cb->cacert);
+ status = cf_util_get_string (child, &cb->cacert);
else if (strcasecmp ("CAPath", child->key) == 0)
- cf_util_get_string (child, &cb->capath);
+ status = cf_util_get_string (child, &cb->capath);
else if (strcasecmp ("ClientKey", child->key) == 0)
- cf_util_get_string (child, &cb->clientkey);
+ status = cf_util_get_string (child, &cb->clientkey);
else if (strcasecmp ("ClientCert", child->key) == 0)
- cf_util_get_string (child, &cb->clientcert);
+ status = cf_util_get_string (child, &cb->clientcert);
else if (strcasecmp ("ClientKeyPass", child->key) == 0)
- cf_util_get_string (child, &cb->clientkeypass);
+ status = cf_util_get_string (child, &cb->clientkeypass);
else if (strcasecmp ("SSLVersion", child->key) == 0)
{
char *value = NULL;
- cf_util_get_string (child, &value);
+ status = cf_util_get_string (child, &value);
+ if (status != 0)
+ break;
if (value == NULL || strcasecmp ("default", value) == 0)
cb->sslversion = CURL_SSLVERSION_DEFAULT;
cb->sslversion = CURL_SSLVERSION_TLSv1_2;
#endif
else
+ {
ERROR ("write_http plugin: Invalid SSLVersion "
"option: %s.", value);
+ status = EINVAL;
+ }
sfree(value);
}
else if (strcasecmp ("Format", child->key) == 0)
- config_set_format (cb, child);
+ status = config_set_format (cb, child);
else if (strcasecmp ("StoreRates", child->key) == 0)
- cf_util_get_boolean (child, &cb->store_rates);
+ status = cf_util_get_boolean (child, &cb->store_rates);
else if (strcasecmp ("BufferSize", child->key) == 0)
- cf_util_get_int (child, &buffer_size);
+ status = cf_util_get_int (child, &buffer_size);
else if (strcasecmp ("LowSpeedLimit", child->key) == 0)
- cf_util_get_int (child, &cb->low_speed_limit);
+ status = cf_util_get_int (child, &cb->low_speed_limit);
else if (strcasecmp ("Timeout", child->key) == 0)
- cf_util_get_int (child, &cb->timeout);
+ status = cf_util_get_int (child, &cb->timeout);
+ else if (strcasecmp ("LogHttpError", child->key) == 0)
+ status = cf_util_get_boolean (child, &cb->log_http_error);
else
{
ERROR ("write_http plugin: Invalid configuration "
"option: %s.", child->key);
+ status = EINVAL;
}
+
+ if (status != 0)
+ break;
+ }
+
+ if (status != 0)
+ {
+ wh_callback_free (cb);
+ return (status);
}
if (cb->location == NULL)
diff --git a/src/write_kafka.c b/src/write_kafka.c
index 775e2e0934f55613d69e5521a3829a495a8a8c4a..a5371d4c0a933e40d3c2c9051babf5b39383909f 100644 (file)
--- a/src/write_kafka.c
+++ b/src/write_kafka.c
#define KAFKA_FORMAT_JSON 0
#define KAFKA_FORMAT_COMMAND 1
#define KAFKA_FORMAT_GRAPHITE 2
- uint8_t format;
+ uint8_t format;
unsigned int graphite_flags;
_Bool store_rates;
rd_kafka_topic_conf_t *conf;
rd_kafka_topic_t *topic;
rd_kafka_conf_t *kafka_conf;
rd_kafka_t *kafka;
- int has_key;
- uint32_t key;
+ char *key;
char *prefix;
char *postfix;
char escape_char;
char *topic_name;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
static int kafka_handle(struct kafka_topic_context *);
{
uint32_t key = *((uint32_t *)keydata );
uint32_t target = key % partition_cnt;
- int32_t i = partition_cnt;
+ int32_t i = partition_cnt;
while (--i > 0 && !rd_kafka_topic_partition_available(rkt, target)) {
target = (target + 1) % partition_cnt;
if ((ctx->kafka = rd_kafka_new(RD_KAFKA_PRODUCER, conf,
errbuf, sizeof(errbuf))) == NULL) {
- ERROR("write_kafka plugin: cannot create kafka handle.");
- return 1;
+ ERROR("write_kafka plugin: cannot create kafka handle.");
+ return 1;
}
- rd_kafka_conf_destroy(ctx->kafka_conf);
- ctx->kafka_conf = NULL;
+ rd_kafka_conf_destroy(ctx->kafka_conf);
+ ctx->kafka_conf = NULL;
- INFO ("write_kafka plugin: created KAFKA handle : %s", rd_kafka_name(ctx->kafka));
+ INFO ("write_kafka plugin: created KAFKA handle : %s", rd_kafka_name(ctx->kafka));
#ifdef HAVE_LIBRDKAFKA_LOGGER
- rd_kafka_set_logger(ctx->kafka, kafka_log);
+ rd_kafka_set_logger(ctx->kafka, kafka_log);
#endif
}
if (ctx->topic == NULL ) {
- if ((topic_conf = rd_kafka_topic_conf_dup(ctx->conf)) == NULL) {
+ if ((topic_conf = rd_kafka_topic_conf_dup(ctx->conf)) == NULL) {
ERROR("write_kafka plugin: cannot duplicate kafka topic config");
return 1;
- }
+ }
- if ((ctx->topic = rd_kafka_topic_new(ctx->kafka, ctx->topic_name,
- topic_conf)) == NULL) {
- ERROR("write_kafka plugin: cannot create topic : %s\n",
- rd_kafka_err2str(rd_kafka_errno2err(errno)));
- return errno;
- }
+ if ((ctx->topic = rd_kafka_topic_new(ctx->kafka, ctx->topic_name,
+ topic_conf)) == NULL) {
+ ERROR("write_kafka plugin: cannot create topic : %s\n",
+ rd_kafka_err2str(rd_kafka_errno2err(errno)));
+ return errno;
+ }
- rd_kafka_topic_conf_destroy(ctx->conf);
- ctx->conf = NULL;
+ rd_kafka_topic_conf_destroy(ctx->conf);
+ ctx->conf = NULL;
- INFO ("write_kafka plugin: handle created for topic : %s", rd_kafka_topic_name(ctx->topic));
+ INFO ("write_kafka plugin: handle created for topic : %s", rd_kafka_topic_name(ctx->topic));
}
return(0);
} /* }}} int kafka_handle */
static int kafka_write(const data_set_t *ds, /* {{{ */
- const value_list_t *vl,
- user_data_t *ud)
+ const value_list_t *vl,
+ user_data_t *ud)
{
- int status = 0;
- uint32_t key;
- char buffer[8192];
- size_t bfree = sizeof(buffer);
- size_t bfill = 0;
- size_t blen = 0;
- struct kafka_topic_context *ctx = ud->data;
+ int status = 0;
+ void *key;
+ size_t keylen = 0;
+ char buffer[8192];
+ size_t bfree = sizeof(buffer);
+ size_t bfill = 0;
+ size_t blen = 0;
+ struct kafka_topic_context *ctx = ud->data;
if ((ds == NULL) || (vl == NULL) || (ctx == NULL))
return EINVAL;
blen = strlen(buffer);
break;
case KAFKA_FORMAT_JSON:
-
format_json_initialize(buffer, &bfill, &bfree);
format_json_value_list(buffer, &bfill, &bfree, ds, vl,
ctx->store_rates);
return -1;
}
- /*
- * We partition our stream by metric name
- */
- if (ctx->has_key)
- key = ctx->key;
- else
- key = rand();
+ key = ctx->key;
+ if (key != NULL)
+ keylen = strlen (key);
rd_kafka_produce(ctx->topic, RD_KAFKA_PARTITION_UA,
RD_KAFKA_MSG_F_COPY, buffer, blen,
- &key, sizeof(key), NULL);
+ key, keylen, NULL);
- return status;
+ return status;
} /* }}} int kafka_write */
static void kafka_topic_context_free(void *p) /* {{{ */
{
- struct kafka_topic_context *ctx = p;
+ struct kafka_topic_context *ctx = p;
- if (ctx == NULL)
- return;
+ if (ctx == NULL)
+ return;
if (ctx->topic_name != NULL)
sfree(ctx->topic_name);
@@ -246,13 +241,13 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
char callback_name[DATA_MAX_NAME_LEN];
char errbuf[1024];
user_data_t ud;
- oconfig_item_t *child;
+ oconfig_item_t *child;
rd_kafka_conf_res_t ret;
- if ((tctx = calloc(1, sizeof (*tctx))) == NULL) {
- ERROR ("write_kafka plugin: calloc failed.");
+ if ((tctx = calloc(1, sizeof (*tctx))) == NULL) {
+ ERROR ("write_kafka plugin: calloc failed.");
return;
- }
+ }
tctx->escape_char = '.';
tctx->store_rates = 1;
@@ -290,48 +285,36 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
goto errout;
}
- for (i = 0; i < ci->children_num; i++) {
- /*
- * The code here could be simplified but makes room
- * for easy adding of new options later on.
- */
- child = &ci->children[i];
- status = 0;
-
- if (strcasecmp ("Property", child->key) == 0) {
- if (child->values_num != 2) {
- WARNING("kafka properties need both a key and a value.");
+ for (i = 0; i < ci->children_num; i++) {
+ /*
+ * The code here could be simplified but makes room
+ * for easy adding of new options later on.
+ */
+ child = &ci->children[i];
+ status = 0;
+
+ if (strcasecmp ("Property", child->key) == 0) {
+ if (child->values_num != 2) {
+ WARNING("kafka properties need both a key and a value.");
goto errout;
- }
- if (child->values[0].type != OCONFIG_TYPE_STRING ||
- child->values[1].type != OCONFIG_TYPE_STRING) {
- WARNING("kafka properties needs string arguments.");
+ }
+ if (child->values[0].type != OCONFIG_TYPE_STRING ||
+ child->values[1].type != OCONFIG_TYPE_STRING) {
+ WARNING("kafka properties needs string arguments.");
goto errout;
- }
+ }
key = child->values[0].value.string;
val = child->values[1].value.string;
ret = rd_kafka_topic_conf_set(tctx->conf,key, val,
errbuf, sizeof(errbuf));
if (ret != RD_KAFKA_CONF_OK) {
- WARNING("cannot set kafka topic property %s to %s: %s.",
+ WARNING("cannot set kafka topic property %s to %s: %s.",
key, val, errbuf);
goto errout;
- }
-
- } else if (strcasecmp ("Key", child->key) == 0) {
- char *tmp_buf = NULL;
- status = cf_util_get_string(child, &tmp_buf);
- if (status != 0) {
- WARNING("write_kafka plugin: invalid key supplied");
- break;
}
- if (strcasecmp(tmp_buf, "Random") != 0) {
- tctx->has_key = 1;
- tctx->key = crc32_buffer((u_char *)tmp_buf, strlen(tmp_buf));
- }
- sfree(tmp_buf);
-
+ } else if (strcasecmp ("Key", child->key) == 0) {
+ cf_util_get_string (child, &tctx->key);
} else if (strcasecmp ("Format", child->key) == 0) {
status = cf_util_get_string(child, &key);
if (status != 0)
@@ -397,11 +380,11 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
ud.data = tctx;
ud.free_func = kafka_topic_context_free;
- status = plugin_register_write (callback_name, kafka_write, &ud);
- if (status != 0) {
- WARNING ("write_kafka plugin: plugin_register_write (\"%s\") "
- "failed with status %i.",
- callback_name, status);
+ status = plugin_register_write (callback_name, kafka_write, &ud);
+ if (status != 0) {
+ WARNING ("write_kafka plugin: plugin_register_write (\"%s\") "
+ "failed with status %i.",
+ callback_name, status);
goto errout;
}
@@ -414,14 +397,14 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
if (tctx->conf != NULL)
rd_kafka_topic_conf_destroy(tctx->conf);
if (tctx->kafka_conf != NULL)
- rd_kafka_conf_destroy(tctx->kafka_conf);
+ rd_kafka_conf_destroy(tctx->kafka_conf);
sfree(tctx);
} /* }}} int kafka_config_topic */
static int kafka_config(oconfig_item_t *ci) /* {{{ */
{
- int i;
- oconfig_item_t *child;
+ int i;
+ oconfig_item_t *child;
rd_kafka_conf_t *conf;
rd_kafka_conf_res_t ret;
char errbuf[1024];
WARNING("cannot allocate kafka configuration.");
return -1;
}
- for (i = 0; i < ci->children_num; i++) {
- child = &ci->children[i];
+ for (i = 0; i < ci->children_num; i++) {
+ child = &ci->children[i];
- if (strcasecmp("Topic", child->key) == 0) {
- kafka_config_topic (conf, child);
- } else if (strcasecmp(child->key, "Property") == 0) {
- char *key = NULL;
- char *val = NULL;
+ if (strcasecmp("Topic", child->key) == 0) {
+ kafka_config_topic (conf, child);
+ } else if (strcasecmp(child->key, "Property") == 0) {
+ char *key = NULL;
+ char *val = NULL;
- if (child->values_num != 2) {
- WARNING("kafka properties need both a key and a value.");
+ if (child->values_num != 2) {
+ WARNING("kafka properties need both a key and a value.");
goto errout;
- }
- if (child->values[0].type != OCONFIG_TYPE_STRING ||
- child->values[1].type != OCONFIG_TYPE_STRING) {
- WARNING("kafka properties needs string arguments.");
+ }
+ if (child->values[0].type != OCONFIG_TYPE_STRING ||
+ child->values[1].type != OCONFIG_TYPE_STRING) {
+ WARNING("kafka properties needs string arguments.");
goto errout;
- }
- if ((key = strdup(child->values[0].value.string)) == NULL) {
- WARNING("cannot allocate memory for attribute key.");
+ }
+ if ((key = strdup(child->values[0].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute key.");
goto errout;
- }
- if ((val = strdup(child->values[1].value.string)) == NULL) {
- WARNING("cannot allocate memory for attribute value.");
+ }
+ if ((val = strdup(child->values[1].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute value.");
+ sfree(key);
goto errout;
- }
+ }
ret = rd_kafka_conf_set(conf, key, val, errbuf, sizeof(errbuf));
if (ret != RD_KAFKA_CONF_OK) {
WARNING("cannot set kafka property %s to %s: %s",
key, val, errbuf);
+ sfree(key);
+ sfree(val);
goto errout;
}
- sfree(key);
- sfree(val);
- } else {
- WARNING ("write_kafka plugin: Ignoring unknown "
- "configuration option \"%s\" at top level.",
- child->key);
- }
- }
+ sfree(key);
+ sfree(val);
+ } else {
+ WARNING ("write_kafka plugin: Ignoring unknown "
+ "configuration option \"%s\" at top level.",
+ child->key);
+ }
+ }
if (conf != NULL)
rd_kafka_conf_destroy(conf);
- return (0);
+ return (0);
errout:
if (conf != NULL)
rd_kafka_conf_destroy(conf);
void module_register(void)
{
- plugin_register_complex_config ("write_kafka", kafka_config);
+ plugin_register_complex_config ("write_kafka", kafka_config);
}
-/* vim: set sw=8 sts=8 ts=8 noet : */
diff --git a/src/write_log.c b/src/write_log.c
index e37aae9fd594fcce3ecd6d5abac7a6fb33adf32c..ebf0e12445cc9e9e3900a8416c3cedcf6db1a9eb 100644 (file)
--- a/src/write_log.c
+++ b/src/write_log.c
/* Folks without pthread will need to disable this plugin. */
#include <pthread.h>
-#include <sys/socket.h>
#include <netdb.h>
#define WL_BUF_SIZE 8192
diff --git a/src/write_redis.c b/src/write_redis.c
index 231738c5bc6993e6c25b0f66dcc1c53a635ba4b0..4bfcc73d2b5b92fa61bd37e8855a6b2d2657aad9 100644 (file)
--- a/src/write_redis.c
+++ b/src/write_redis.c
/**
* collectd - src/write_redis.c
- * Copyright (C) 2010 Florian Forster
+ * Copyright (C) 2010-2015 Florian Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
#include <sys/time.h>
#include <hiredis/hiredis.h>
+#ifndef REDIS_DEFAULT_PREFIX
+# define REDIS_DEFAULT_PREFIX "collectd/"
+#endif
+
struct wr_node_s
{
char name[DATA_MAX_NAME_LEN];
char *host;
int port;
struct timeval timeout;
+ char *prefix;
+ int database;
+ int max_set_size;
+ _Bool store_rates;
redisContext *conn;
pthread_mutex_t lock;
status = FORMAT_VL (ident, sizeof (ident), vl);
if (status != 0)
return (status);
- ssnprintf (key, sizeof (key), "collectd/%s", ident);
+ ssnprintf (key, sizeof (key), "%s%s",
+ (node->prefix != NULL) ? node->prefix : REDIS_DEFAULT_PREFIX,
+ ident);
ssnprintf (time, sizeof (time), "%.9f", CDTIME_T_TO_DOUBLE(vl->time));
memset (value, 0, sizeof (value));
value_size = sizeof (value);
value_ptr = &value[0];
- status = format_values (value_ptr, value_size, ds, vl, /* store rates = */ 0);
+ status = format_values (value_ptr, value_size, ds, vl, node->store_rates);
if (status != 0)
return (status);
pthread_mutex_unlock (&node->lock);
return (-1);
}
+
+ rr = redisCommand(node->conn, "SELECT %d", node->database);
+ if (rr == NULL)
+ WARNING("SELECT command error. database:%d message:%s", node->database, node->conn->errstr);
+ else
+ freeReplyObject (rr);
}
rr = redisCommand (node->conn, "ZADD %s %s %s", key, time, value);
else
freeReplyObject (rr);
+ if (node->max_set_size >= 0)
+ {
+ rr = redisCommand (node->conn, "ZREMRANGEBYRANK %s %d %d", key, 0, (-1 * node->max_set_size) - 1);
+ if (rr == NULL)
+ WARNING("ZREMRANGEBYRANK command error. key:%s message:%s", key, node->conn->errstr);
+ else
+ freeReplyObject (rr);
+ }
+
/* TODO(octo): This is more overhead than necessary. Use the cache and
* metadata to determine if it is a new metric and call SADD only once for
* each metric. */
- rr = redisCommand (node->conn, "SADD collectd/values %s", ident);
+ rr = redisCommand (node->conn, "SADD %svalues %s",
+ (node->prefix != NULL) ? node->prefix : REDIS_DEFAULT_PREFIX,
+ ident);
if (rr==NULL)
WARNING("SADD command error. ident:%s message:%s", ident, node->conn->errstr);
else
node->timeout.tv_sec = 0;
node->timeout.tv_usec = 1000;
node->conn = NULL;
+ node->prefix = NULL;
+ node->database = 0;
+ node->max_set_size = -1;
+ node->store_rates = 1;
pthread_mutex_init (&node->lock, /* attr = */ NULL);
status = cf_util_get_string_buffer (ci, node->name, sizeof (node->name));
status = cf_util_get_int (child, &timeout);
if (status == 0) node->timeout.tv_usec = timeout;
}
+ else if (strcasecmp ("Prefix", child->key) == 0) {
+ status = cf_util_get_string (child, &node->prefix);
+ }
+ else if (strcasecmp ("Database", child->key) == 0) {
+ status = cf_util_get_int (child, &node->database);
+ }
+ else if (strcasecmp ("MaxSetSize", child->key) == 0) {
+ status = cf_util_get_int (child, &node->max_set_size);
+ }
+ else if (strcasecmp ("StoreRates", child->key) == 0) {
+ status = cf_util_get_boolean (child, &node->store_rates);
+ }
else
WARNING ("write_redis plugin: Ignoring unknown config option \"%s\".",
child->key);
diff --git a/src/write_riemann.c b/src/write_riemann.c
index 58611a96fe2ec40adff997503eea1ae8dcf2284b..6a47ba3224cd52d6bbf5d75ca24cf73af6d55f41 100644 (file)
--- a/src/write_riemann.c
+++ b/src/write_riemann.c
* Florian octo Forster <octo at collectd.org>
*/
-#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
@@ -364,7 +363,7 @@ static Msg *riemann_notification_to_protobuf(struct riemann_host *host, /* {{{ *
char service_buffer[6 * DATA_MAX_NAME_LEN];
char const *severity;
notification_meta_t *meta;
- int i;
+ size_t i;
msg = malloc (sizeof (*msg));
if (msg == NULL)
char name_buffer[5 * DATA_MAX_NAME_LEN];
char service_buffer[6 * DATA_MAX_NAME_LEN];
double ttl;
- int i;
+ size_t i;
event = malloc (sizeof (*event));
if (event == NULL)
msg__init (msg);
/* Set up events. First, the list of pointers. */
- msg->n_events = (size_t) vl->values_len;
+ msg->n_events = vl->values_len;
msg->events = calloc (msg->n_events, sizeof (*msg->events));
if (msg->events == NULL)
{
len = msg__get_packed_size(host->batch_msg);
ret = 0;
- if (len >= host->batch_max) {
- ret = riemann_batch_flush_nolock(0, host);
+ if ((host->batch_max < 0) || (((size_t) host->batch_max) <= len)) {
+ ret = riemann_batch_flush_nolock(0, host);
}
pthread_mutex_unlock(&host->lock);
@@ -777,35 +776,35 @@ static int riemann_notification(const notification_t *n, user_data_t *ud) /* {{{
} /* }}} int riemann_notification */
static int riemann_write(const data_set_t *ds, /* {{{ */
- const value_list_t *vl,
- user_data_t *ud)
+ const value_list_t *vl,
+ user_data_t *ud)
{
int status = 0;
int statuses[vl->values_len];
struct riemann_host *host = ud->data;
- Msg *msg;
-
- if (host->check_thresholds)
- write_riemann_threshold_check(ds, vl, statuses);
-
- if (host->use_tcp == 1 && host->batch_mode) {
-
- riemann_batch_add_value_list (host, ds, vl, statuses);
+ if (host->check_thresholds) {
+ status = write_riemann_threshold_check(ds, vl, statuses);
+ if (status != 0)
+ return status;
+ } else {
+ memset (statuses, 0, sizeof (statuses));
+ }
- } else {
+ if (host->use_tcp == 1 && host->batch_mode) {
+ riemann_batch_add_value_list (host, ds, vl, statuses);
+ } else {
+ Msg *msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
+ if (msg == NULL)
+ return (-1);
- msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
- if (msg == NULL)
- return (-1);
+ status = riemann_send (host, msg);
+ if (status != 0)
+ ERROR ("write_riemann plugin: riemann_send failed with status %i", status);
- status = riemann_send (host, msg);
- if (status != 0)
- ERROR ("write_riemann plugin: riemann_send failed with status %i",
- status);
+ riemann_msg_protobuf_free (msg);
+ }
- riemann_msg_protobuf_free (msg);
- }
return status;
} /* }}} int riemann_write */
index b1f7297eec9b06e90d03df594599b87e5418b979..85672882a096ef5b14ba6876b05df32ed620b3d1 100644 (file)
int *statuses)
{ /* {{{ */
int ret = -1;
- int i;
+ size_t i;
int status;
gauge_t values_copy[ds->ds_num];
@@ -203,7 +203,9 @@ int write_riemann_threshold_check (const data_set_t *ds, const value_list_t *vl,
gauge_t *values;
int status;
+ assert (vl->values_len > 0);
memset(statuses, 0, vl->values_len * sizeof(*statuses));
+
if (threshold_tree == NULL)
return 0;
diff --git a/src/write_sensu.c b/src/write_sensu.c
index 0d568fe6118d8b9808710e22f10db2ff7d548d59..aae5d8bbfa73dc4929e2c51db1e5319d3807a7e4 100644 (file)
--- a/src/write_sensu.c
+++ b/src/write_sensu.c
#include "common.h"
#include "configfile.h"
#include "utils_cache.h"
-#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
{
char name_buffer[5 * DATA_MAX_NAME_LEN];
char service_buffer[6 * DATA_MAX_NAME_LEN];
- int i;
+ size_t i;
char *ret_str;
char *temp_str;
char *value_str;
char *ret_str;
char *temp_str;
int status;
- int i;
+ size_t i;
int res;
// add the severity/status
switch (n->severity) {
int statuses[vl->values_len];
struct sensu_host *host = ud->data;
gauge_t *rates = NULL;
- int i;
+ size_t i;
char *msg;
pthread_mutex_lock(&host->lock);
return -1;
}
}
- for (i = 0; i < (size_t) vl->values_len; i++) {
+ for (i = 0; i < vl->values_len; i++) {
msg = sensu_value_to_json(host, ds, vl, (int) i, rates, statuses[i]);
if (msg == NULL) {
sfree(rates);
diff --git a/src/write_tsdb.c b/src/write_tsdb.c
index ee4db2384a2848b9466b3bbedf155579f3225877..c562596b6d753525aafa663ee532d71bcec5d873 100644 (file)
--- a/src/write_tsdb.c
+++ b/src/write_tsdb.c
#include "utils_cache.h"
#include <pthread.h>
-#include <sys/socket.h>
#include <netdb.h>
#ifndef WT_DEFAULT_NODE
{
int status;
char *temp = NULL;
- char *prefix = "";
+ const char *prefix = "";
const char *meta_prefix = "tsdb_prefix";
if (vl->meta) {
const char* host, meta_data_t *md)
{
int status;
- int message_len;
+ size_t message_len;
char *temp = NULL;
- char *tags = "";
+ const char *tags = "";
char message[1024];
- char *host_tags = cb->host_tags ? cb->host_tags : "";
+ const char *host_tags = cb->host_tags ? cb->host_tags : "";
const char *meta_tsdb = "tsdb_tags";
/* skip if value is NaN */
}
}
- message_len = ssnprintf (message,
+ status = ssnprintf (message,
sizeof(message),
"put %s %.0f %s fqdn=%s %s %s\r\n",
key,
host,
tags,
host_tags);
-
sfree(temp);
+ if (status < 0)
+ return -1;
+ message_len = (size_t) status;
if (message_len >= sizeof(message)) {
ERROR("write_tsdb plugin: message buffer too small: "
- "Need %d bytes.", message_len + 1);
+ "Need %zu bytes.", message_len + 1);
return -1;
}
char key[10*DATA_MAX_NAME_LEN];
char values[512];
- int status, i;
+ int status;
+ size_t i;
if (0 != strcmp(ds->type, vl->type))
{
diff --git a/src/zfs_arc.c b/src/zfs_arc.c
index 8feb31d55c0bfc75f571e0398edfef965e8fcc78..e1c39372b55c7996eef6fc11d1f24556792e6192 100644 (file)
--- a/src/zfs_arc.c
+++ b/src/zfs_arc.c
typedef llist_t kstat_t;
-static long long get_zfs_value(kstat_t *zfs_stats __attribute__((unused)),
- char *name)
+static int put_zfs_value (kstat_t *ksp, char const *k, value_t v)
{
llentry_t *e;
+ char *k_copy;
+ value_t *v_copy;
- e = llist_search (zfs_stats, name);
+ k_copy = strdup (k);
+ if (k_copy == NULL)
+ return ENOMEM;
+
+ v_copy = malloc (sizeof (*v_copy));
+ if (v_copy == NULL)
+ {
+ sfree (k_copy);
+ return ENOMEM;
+ }
+ *v_copy = v;
+
+ e = llentry_create (k_copy, v_copy);
if (e == NULL)
{
- ERROR ("zfs_arc plugin: `llist_search` failed for key: '%s'.", name);
+ sfree (v_copy);
+ sfree (k_copy);
+ return ENOMEM;
+ }
+
+ llist_append (ksp, e);
+ return 0;
+}
+
+static long long get_zfs_value(kstat_t *ksp, const char *key)
+{
+ llentry_t *e;
+ value_t *v;
+
+ e = llist_search (ksp, key);
+ if (e == NULL)
+ {
+ ERROR ("zfs_arc plugin: `llist_search` failed for key: '%s'.", key);
return (-1);
}
- return (*(long long int*)e->value);
+ v = e->value;
+ return ((long long) v->derive);
+}
+
+static void free_zfs_values (kstat_t *ksp)
+{
+ llentry_t *e;
+
+ if (ksp == NULL)
+ return;
+
+ for (e = llist_head (ksp); e != NULL; e = e->next)
+ {
+ sfree (e->key);
+ sfree (e->value);
+ }
+
+ llist_destroy (ksp);
}
#elif !defined(__FreeBSD__) // Solaris
kstat_t *ksp = NULL;
#if KERNEL_LINUX
- long long int *llvalues = NULL;
- char file_contents[1024 * 10];
- char *fields[3];
- int numfields;
- ssize_t len;
+ FILE *fh;
+ char buffer[1024];
+
+ fh = fopen (ZOL_ARCSTATS_FILE, "r");
+ if (fh == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("zfs_arc plugin: Opening \"%s\" failed: %s", ZOL_ARCSTATS_FILE,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
ksp = llist_create ();
if (ksp == NULL)
{
ERROR ("zfs_arc plugin: `llist_create' failed.");
+ fclose (fh);
return (-1);
}
- len = read_file_contents (ZOL_ARCSTATS_FILE, file_contents, sizeof(file_contents) - 1);
- if (len > 1)
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
+ char *fields[3];
+ value_t v;
+ int status;
+
+ status = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+ if (status != 3)
+ continue;
- int i=0;
- char *pnl = file_contents;
- char *pnnl;
-
- file_contents[len] = '\0';
-
- while (pnl != NULL)
- {
- pnl = strchr(pnl, '\n');
- i++;
- if (pnl && (*pnl != '\0'))
- pnl++;
- }
-
- if (i > 0)
- {
- llentry_t *e;
- llvalues = malloc(sizeof(long long int) * i);
- if (llvalues == NULL)
- {
- ERROR ("zfs_arc plugin: `malloc' failed.");
- llist_destroy (ksp);
- return (-1);
- }
- int j = 0;
-
- pnl = file_contents;
- while (pnl != NULL)
- {
- pnnl = strchr(pnl, '\n');
- if (pnnl != NULL)
- *pnnl = '\0';
-
- numfields = strsplit (pnl, fields, 4);
- if (numfields == 3)
- {
- llvalues[j] = atoll (fields[2]);
-
- e = llentry_create (fields[0], &llvalues[j]);
- if (e == NULL)
- {
- ERROR ("zfs_arc plugin: `llentry_create' failed.");
- }
- else
- {
- llist_append (ksp, e);
- }
- j++;
- }
- pnl = pnnl;
- if (pnl != NULL)
- pnl ++;
- }
- }
+ status = parse_value (fields[2], &v, DS_TYPE_DERIVE);
+ if (status != 0)
+ continue;
+
+ put_zfs_value (ksp, fields[0], v);
}
+ fclose (fh);
+
#elif !defined(__FreeBSD__) // Solaris
get_kstat (&ksp, "zfs", 0, "arcstats");
if (ksp == NULL)
/* Sizes */
za_read_gauge (ksp, "size", "cache_size", "arc");
+ za_read_gauge (ksp, "c", "cache_size", "c");
+ za_read_gauge (ksp, "c_min", "cache_size", "c_min");
+ za_read_gauge (ksp, "c_max", "cache_size", "c_max");
/* The "l2_size" value has disappeared from Solaris some time in
* early 2013, and has only reappeared recently in Solaris 11.2.
za_submit ("io_octets", "L2", l2_io, /* num values = */ 2);
#if defined(KERNEL_LINUX)
- if (llvalues != NULL)
- {
- free(llvalues);
- }
- if (ksp != NULL)
- {
- llist_destroy (ksp);
- }
+ free_zfs_values (ksp);
#endif
return (0);
diff --git a/src/zone.c b/src/zone.c
--- /dev/null
+++ b/src/zone.c
@@ -0,0 +1,214 @@
+/**
+ * collectd - src/zone.c
+ * Copyright (C) 2011 Mathijs Mohlmann
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Mathijs Mohlmann
+ * Dagobert Michelsen (forward-porting)
+ **/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+# undef HAVE_CONFIG_H
+#endif
+/* avoid procfs.h error "Cannot use procfs in the large file compilation environment" */
+#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
+# undef _FILE_OFFSET_BITS
+# undef _LARGEFILE64_SOURCE
+#endif
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <sys/types.h>
+#include <sys/vm_usage.h>
+#include <procfs.h>
+#include <zone.h>
+
+#include "utils_avltree.h"
+
+#define MAX_PROCFS_PATH 40
+#define FRC2PCT(pp)(((float)(pp))/0x8000*100)
+
+typedef struct zone_stats {
+ ushort_t pctcpu;
+ ushort_t pctmem;
+} zone_stats_t;
+
+static long pagesize;
+
+static int zone_init (void)
+{
+ pagesize = sysconf(_SC_PAGESIZE);
+ return (0);
+}
+
+static int
+zone_compare(const zoneid_t *a, const zoneid_t *b)
+{
+ if (*a == *b)
+ return(0);
+ if (*a < *b)
+ return(-1);
+ return(1);
+}
+
+static int
+zone_read_procfile(char const *pidstr, char const *name, void *buf, size_t bufsize)
+{
+ int fd;
+
+ char procfile[MAX_PROCFS_PATH];
+ (void)snprintf(procfile, sizeof(procfile), "/proc/%s/%s", pidstr, name);
+ if ((fd = open(procfile, O_RDONLY)) == -1) {
+ return (1);
+ }
+
+ if (sread(fd, buf, bufsize) != 0) {
+ char errbuf[1024];
+ ERROR ("zone plugin: Reading \"%s\" failed: %s", procfile,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ close(fd);
+ return (1);
+ }
+
+ close(fd);
+ return (0);
+}
+
+static int
+zone_submit_value(char *zone, gauge_t value)
+{
+ value_list_t vl = VALUE_LIST_INIT;
+ value_t values[1];
+
+ values[0].gauge = value;
+
+ vl.values = values;
+ vl.values_len = 1; /*STATIC_ARRAY_SIZE (values);*/
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "zone", sizeof (vl.plugin));
+ sstrncpy (vl.type, "percent", sizeof (vl.type));
+ sstrncpy (vl.type_instance, zone, sizeof (vl.type_instance));
+
+ return(plugin_dispatch_values (&vl));
+}
+
+static zone_stats_t *
+zone_find_stats(c_avl_tree_t *tree, zoneid_t zoneid)
+{
+ zone_stats_t *ret = NULL;
+ zoneid_t *key = NULL;
+
+ if (c_avl_get(tree, (void **)&zoneid, (void **)&ret)) {
+ if (!(ret = malloc(sizeof(zone_stats_t)))) {
+ WARNING("zone plugin: no memory");
+ return(NULL);
+ }
+ if (!(key = malloc(sizeof(zoneid_t)))) {
+ WARNING("zone plugin: no memory");
+ return(NULL);
+ }
+ *key = zoneid;
+ if (c_avl_insert(tree, key, ret)) {
+ WARNING("zone plugin: error inserting into tree");
+ return(NULL);
+ }
+ }
+ return(ret);
+}
+
+static void
+zone_submit_values(c_avl_tree_t *tree)
+{
+ char zonename[ZONENAME_MAX];
+ zoneid_t *zoneid = NULL;
+ zone_stats_t *stats = NULL;
+
+ while (c_avl_pick (tree, (void **)&zoneid, (void **)&stats) == 0)
+ {
+ if (getzonenamebyid(*zoneid, zonename, sizeof( zonename )) == -1) {
+ WARNING("zone plugin: error retreiving zonename");
+ } else {
+ zone_submit_value(zonename, (gauge_t)FRC2PCT(stats->pctcpu));
+ }
+ free(stats);
+ free(zoneid);
+ }
+ c_avl_destroy(tree);
+}
+
+static c_avl_tree_t *
+zone_scandir(DIR *procdir)
+{
+ pid_t pid;
+ dirent_t *direntp;
+ psinfo_t psinfo;
+ c_avl_tree_t *tree;
+ zone_stats_t *stats;
+
+ if (!(tree=c_avl_create((void *) zone_compare))) {
+ WARNING("zone plugin: Failed to create tree");
+ return(NULL);
+ }
+
+ rewinddir(procdir);
+ while ((direntp = readdir(procdir))) {
+ char const *pidstr = direntp->d_name;
+ if (pidstr[0] == '.') /* skip "." and ".." */
+ continue;
+
+ pid = atoi(pidstr);
+ if (pid == 0 || pid == 2 || pid == 3)
+ continue; /* skip sched, pageout and fsflush */
+
+ if (zone_read_procfile(pidstr, "psinfo", &psinfo, sizeof(psinfo_t)) != 0)
+ continue;
+
+ stats = zone_find_stats(tree, psinfo.pr_zoneid);
+ if( stats ) {
+ stats->pctcpu += psinfo.pr_pctcpu;
+ stats->pctmem += psinfo.pr_pctmem;
+ }
+ }
+ return(tree);
+}
+
+static int zone_read (void)
+{
+ DIR *procdir;
+ c_avl_tree_t *tree;
+
+ if ((procdir = opendir("/proc")) == NULL) {
+ ERROR("zone plugin: cannot open /proc directory\n");
+ return (-1);
+ }
+
+ tree=zone_scandir(procdir);
+ closedir(procdir);
+ if (tree == NULL) {
+ return (-1);
+ }
+ zone_submit_values(tree); /* this also frees tree */
+ return (0);
+}
+
+void module_register (void)
+{
+ plugin_register_init ("zone", zone_init);
+ plugin_register_read ("zone", zone_read);
+} /* void module_register */
diff --git a/src/zookeeper.c b/src/zookeeper.c
index 5aa94e3469091101a559dd2116e34d1d5dbba668..1eed1fb35d1b02281ea050cc12d9cffa250e2270 100644 (file)
--- a/src/zookeeper.c
+++ b/src/zookeeper.c
#include "plugin.h"
#include <netdb.h>
-#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
struct addrinfo ai_hints;
struct addrinfo *ai;
struct addrinfo *ai_list;
- char *host;
- char *port;
+ const char *host;
+ const char *port;
memset ((void *) &ai_hints, '\0', sizeof (ai_hints));
ai_hints.ai_family = AF_UNSPEC;
diff --git a/version-gen.sh b/version-gen.sh
index e0ad124e237e063416099a588ada8fc4158e7d44..d7c6a7655e28fd5e311a08a2911ddd4ddb1a773a 100755 (executable)
--- a/version-gen.sh
+++ b/version-gen.sh
DEFAULT_VERSION="5.5.1.git"
-VERSION="`git describe 2> /dev/null | grep collectd | sed -e 's/^collectd-//'`"
+if [ -d .git ]; then
+ VERSION="`git describe --dirty=+ --abbrev=7 2> /dev/null | grep collectd | sed -e 's/^collectd-//' -e 's/-/./g'`"
+fi
if test -z "$VERSION"; then
VERSION="$DEFAULT_VERSION"
fi
-VERSION="`echo \"$VERSION\" | sed -e 's/-/./g'`"
-
printf "%s" "$VERSION"