AM_YFLAGS = -d
if BUILD_WIN32
-pkgdatadir=$(datadir)
-pkglibdir=$(libdir)/plugins
-pkglocalstatedir=${localstatedir}
+cpkgdatadir=$(datadir)
+cpkglibdir=$(libdir)/plugins
+cpkglocalstatedir=${localstatedir}
else
-pkglocalstatedir=${localstatedir}/lib/${PACKAGE_NAME}
+cpkgdatadir=$(pkgdatadir)
+cpkglibdir=$(pkglibdir)
+cpkglocalstatedir=${localstatedir}/lib/${PACKAGE_NAME}
endif
BUILT_SOURCES = \
LOG_COMPILER = env VALGRIND="@VALGRIND@" $(abs_srcdir)/testwrapper.sh
-jardir = $(pkgdatadir)/java
+jardir = $(cpkgdatadir)/java
pkglib_LTLIBRARIES =
-DPREFIX='"${prefix}"' \
-DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"' \
-DLOCALSTATEDIR='"${localstatedir}"' \
- -DPKGLOCALSTATEDIR='"${pkglocalstatedir}"' \
- -DPLUGINDIR='"${pkglibdir}"' \
- -DPKGDATADIR='"${pkgdatadir}"'
+ -DPKGLOCALSTATEDIR='"${cpkglocalstatedir}"' \
+ -DPLUGINDIR='"${cpkglibdir}"' \
+ -DPKGDATADIR='"${cpkgdatadir}"'
if BUILD_WIN32
AM_CPPFLAGS += -DNOGDI
endif
else \
$(INSTALL) -m 0640 $(builddir)/src/collectd.conf $(DESTDIR)$(sysconfdir)/collectd.conf; \
fi; \
- $(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
- $(INSTALL) -m 0644 $(srcdir)/src/types.db $(DESTDIR)$(pkgdatadir)/types.db;
+ $(mkinstalldirs) $(DESTDIR)$(cpkgdatadir)
+ $(INSTALL) -m 0644 $(srcdir)/src/types.db $(DESTDIR)$(cpkgdatadir)/types.db;
$(INSTALL) -m 0644 $(srcdir)/src/postgresql_default.conf \
- $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
+ $(DESTDIR)$(cpkgdatadir)/postgresql_default.conf;
uninstall-hook:
- rm -f $(DESTDIR)$(pkgdatadir)/types.db;
+ rm -f $(DESTDIR)$(cpkgdatadir)/types.db;
rm -f $(DESTDIR)$(sysconfdir)/collectd.conf
- rm -f $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
+ rm -f $(DESTDIR)$(cpkgdatadir)/postgresql_default.conf;
all-local: @PERL_BINDINGS@
: ${DATADIR:="${INSTALL_DIR}"}
echo "Installing collectd to ${INSTALL_DIR}."
- TOP_SRCDIR=$(pwd)
+ TOP_SRCDIR="$(pwd)"
MINGW_ROOT="$(x86_64-w64-mingw32-gcc -print-sysroot)/mingw"
export GNULIB_DIR="${TOP_SRCDIR}/gnulib/build/gllib"
AC_SUBST([BUILD_WITH_LIBVARNISH_LIBS])
# }}}
-# pkg-config --exists 'libxml-2.0' {{{
-$PKG_CONFIG --exists 'libxml-2.0' 2>/dev/null
-if test $? -eq 0; then
- with_libxml2="yes"
-else
- with_libxml2="no (pkg-config doesn't know libxml-2.0)"
-fi
-
-if test "x$with_libxml2" = "xyes"; then
- with_libxml2_cflags="`$PKG_CONFIG --cflags libxml-2.0`"
- if test $? -ne 0; then
- with_libxml2="no"
- fi
-
- with_libxml2_ldflags="`$PKG_CONFIG --libs libxml-2.0`"
- if test $? -ne 0; then
- with_libxml2="no"
- fi
-fi
+# --with-libxml2 {{{
+AC_ARG_WITH(libxml2,
+ [AS_HELP_STRING([--with-libxml2@<:@=PREFIX@:>@], [Path to libxml2.])],
+ [
+ if test "x$withval" = "xno"; then
+ with_libxml2="no"
+ else if test "x$withval" = "xyes"; then
+ $PKG_CONFIG --exists 'libxml-2.0' 2>/dev/null
+ if test $? -eq 0; then
+ with_libxml2="yes"
+ with_libxml2_cflags="`$PKG_CONFIG --cflags libxml-2.0`"
+ with_libxml2_ldflags="`$PKG_CONFIG --libs libxml-2.0`"
+ else
+ with_libxml2="no (pkg-config doesn't know libxml-2.0)"
+ fi
+ else
+ with_libxml2="yes"
+ with_libxml2_cflags="-I$withval/include"
+ with_libxml2_ldflags="-L$withval/lib"
+ fi; fi
+ ],
+ dnl if no argument --with-libxml2 was passed, find the library locations
+ dnl with pkg-config just like above, when --with-libxml2=yes.
+ [
+ with_libxml2="yes"
+ $PKG_CONFIG --exists 'libxml-2.0' 2>/dev/null
+ if test $? -eq 0; then
+ with_libxml2="yes"
+ with_libxml2_cflags="`$PKG_CONFIG --cflags libxml-2.0`"
+ with_libxml2_ldflags="`$PKG_CONFIG --libs libxml-2.0`"
+ else
+ with_libxml2="no (pkg-config doesn't know libxml-2.0)"
+ fi
+ ]
+)
if test "x$with_libxml2" = "xyes"; then
SAVE_CPPFLAGS="$CPPFLAGS"
+/**
+ * collectd - contrib/docker/rootfs_prefix/rootfs_prefix.c
+ * Copyright (C) 2016-2018 Marc Fournier
+ * Copyright (C) 2016-2018 Ruben Kerkhof
+ *
+ * MIT License:
+ *
+ * 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 Fournier <marc.fournier at camptocamp.com>
+ * Ruben Kerkhof <ruben at rubenkerkhof.com>
+ **/
+
#define _GNU_SOURCE
#include <dirent.h>
#include <arpa/inet.h> /* ntohs/ntohl */
#endif
+/* AIX doesn't have MSG_DONTWAIT */
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT MSG_NONBLOCK
+#endif
+
#define CONFIG_KEY_HOST "Host"
#define CONFIG_KEY_PORT "Port"
#define CONFIG_KEY_TIMEOUT "Timeout"
}
}
+static void chrony_flush_recv_queue(void) {
+ char buf[1];
+
+ if (g_chrony_is_connected) {
+ while (recv(g_chrony_socket, buf, sizeof(buf), MSG_DONTWAIT) > 0)
+ ;
+ }
+}
+
static int chrony_query(const int p_command, tChrony_Request *p_req,
tChrony_Response *p_resp, size_t *p_resp_size) {
/* Check connection. We simply perform one try as collectd already handles
g_chrony_seq_is_initialized = 1;
}
+ /* Ignore late responses that may have been received */
+ chrony_flush_recv_queue();
+
/* Get daemon stats */
rc = chrony_request_daemon_stats();
if (rc != CHRONY_RC_OK)
# <Node example>
# Host "redis.example.com"
# Port "6379"
+# #Socket "/var/run/redis/redis.sock"
# Timeout 2000
# <Query "LLEN myqueue">
# #Database 0
<Node "example">
Host "localhost"
Port "6379"
+ #Socket "/var/run/redis/redis.sock"
Timeout 2000
ReportCommandStats false
ReportCpuUsage true
connections. Either a service name of a port number may be given. Please note
that numerical port numbers must be given as a string, too.
+=item B<Socket> I<Path>
+
+Connect to Redis using the UNIX domain socket at I<Path>. If this
+setting is given, the B<Hostname> and B<Port> settings are ignored.
+
=item B<Password> I<Password>
Use I<Password> to authenticate when connecting to I<Redis>.
*
* DESCRIPTION
* Calls the write function of the given plugin with the provided data set and
- * value list. It differs from `plugin_dispatch_value' in that it does not
+ * value list. It differs from `plugin_dispatch_values' in that it does not
* update the cache, does not do threshold checking, call the chain subsystem
* and so on. It looks up the requested plugin and invokes the function, end
* of story.
return -1;
if (iter->node == NULL) {
- for (n = iter->tree->root; n != NULL; n = n->left)
+ for (n = iter->tree->root; n != NULL; n = n->right)
if (n->right == NULL)
break;
iter->node = n;
return strcmp(v0, v1);
}
+struct kv_t {
+ char *key;
+ char *value;
+};
+
+static int kv_compare(const void *a_ptr, const void *b_ptr) {
+ return strcmp(((struct kv_t *)a_ptr)->key, ((struct kv_t *)b_ptr)->key);
+}
+
DEF_TEST(success) {
- struct {
- char *key;
- char *value;
- } cases[] = {
+ struct kv_t cases[] = {
{"Eeph7chu", "vai1reiV"}, {"igh3Paiz", "teegh1Ee"},
{"caip6Uu8", "ooteQu8n"}, {"Aech6vah", "AijeeT0l"},
{"Xah0et2L", "gah8Taep"}, {"BocaeB8n", "oGaig8io"},
{"ieN5engi", "Aevou1ah"}, {"ooTe4OhP", "aingai5Y"},
};
+ struct kv_t sorted_cases[STATIC_ARRAY_SIZE(cases)];
+ memcpy(sorted_cases, cases, sizeof(cases));
+ qsort(sorted_cases, STATIC_ARRAY_SIZE(cases), sizeof(struct kv_t),
+ kv_compare);
+
c_avl_tree_t *t;
RESET_COUNTS();
EXPECT_EQ_STR(cases[i].value, value_ret);
}
+ /* iterate forward */
+ {
+ c_avl_iterator_t *iter = c_avl_get_iterator(t);
+ char *key;
+ char *value;
+ size_t i = 0;
+ while (c_avl_iterator_next(iter, (void **)&key, (void **)&value) == 0) {
+ EXPECT_EQ_STR(sorted_cases[i].key, key);
+ EXPECT_EQ_STR(sorted_cases[i].value, value);
+ i++;
+ }
+ c_avl_iterator_destroy(iter);
+ EXPECT_EQ_INT(i, STATIC_ARRAY_SIZE(cases));
+ }
+
+ /* iterate backward */
+ {
+ c_avl_iterator_t *iter = c_avl_get_iterator(t);
+ char *key;
+ char *value;
+ size_t i = 0;
+ while (c_avl_iterator_prev(iter, (void **)&key, (void **)&value) == 0) {
+ EXPECT_EQ_STR(sorted_cases[STATIC_ARRAY_SIZE(cases) - 1 - i].key, key);
+ EXPECT_EQ_STR(sorted_cases[STATIC_ARRAY_SIZE(cases) - 1 - i].value,
+ value);
+ i++;
+ }
+ c_avl_iterator_destroy(iter);
+ EXPECT_EQ_INT(i, STATIC_ARRAY_SIZE(cases));
+ }
+
/* remove half */
for (size_t i = 0; i < STATIC_ARRAY_SIZE(cases) / 2; i++) {
char *key = NULL;
} program_list_and_notification_t;
/*
+ * constants
+ */
+const long int MAX_GRBUF_SIZE = 65536;
+
+/*
* Private variables
*/
static program_list_t *pl_head;
} /* }}} void close_pipe */
/*
+ * Get effective group ID from group name.
+ * Input arguments:
+ * pl :program list struct with group name
+ * gid :group id to fallback in case egid cannot be determined.
+ * Returns:
+ * egid effective group id if successfull,
+ * -1 if group is not defined/not found.
+ * -2 for any buffer allocation error.
+ */
+static int getegr_id(program_list_t *pl, int gid) /* {{{ */
+{
+ if (pl->group == NULL) {
+ return -1;
+ }
+ if (strcmp(pl->group, "") == 0) {
+ return gid;
+ }
+ struct group *gr_ptr = NULL;
+ struct group gr;
+
+ long int grbuf_size = sysconf(_SC_GETGR_R_SIZE_MAX);
+ if (grbuf_size <= 0)
+ grbuf_size = sysconf(_SC_PAGESIZE);
+ if (grbuf_size <= 0)
+ grbuf_size = 4096;
+
+ char *temp = NULL;
+ char *grbuf = NULL;
+
+ do {
+ temp = realloc(grbuf, grbuf_size);
+ if (temp == NULL) {
+ ERROR("exec plugin: getegr_id for %s: realloc buffer[%ld] failed ",
+ pl->group, grbuf_size);
+ sfree(grbuf);
+ return -2;
+ }
+ grbuf = temp;
+ if (getgrnam_r(pl->group, &gr, grbuf, grbuf_size, &gr_ptr) == 0) {
+ sfree(grbuf);
+ if (gr_ptr == NULL) {
+ ERROR("exec plugin: No such group: `%s'", pl->group);
+ return -1;
+ }
+ return gr.gr_gid;
+ } else if (errno == ERANGE) {
+ grbuf_size += grbuf_size; // increment buffer size and try again
+ } else {
+ ERROR("exec plugin: getegr_id failed %s", STRERRNO);
+ sfree(grbuf);
+ return -2;
+ }
+ } while (grbuf_size <= MAX_GRBUF_SIZE);
+ ERROR("exec plugin: getegr_id Max grbuf size reached for %s", pl->group);
+ sfree(grbuf);
+ return -2;
+}
+
+/*
* Creates three pipes (one for reading, one for writing and one for errors),
* forks a child, sets up the pipes so that fd_in is connected to STDIN of
* the child and fd_out is connected to STDOUT and fd_err is connected to STDERR
/* The group configured in the configfile is set as effective group, because
* this way the forked process can (re-)gain the user's primary group. */
- egid = -1;
- if (pl->group != NULL) {
- if (*pl->group != '\0') {
- struct group *gr_ptr = NULL;
- struct group gr;
-
- long int grbuf_size = sysconf(_SC_GETGR_R_SIZE_MAX);
- if (grbuf_size <= 0)
- grbuf_size = sysconf(_SC_PAGESIZE);
- if (grbuf_size <= 0)
- grbuf_size = 4096;
- char grbuf[grbuf_size];
-
- status = getgrnam_r(pl->group, &gr, grbuf, sizeof(grbuf), &gr_ptr);
- if (status != 0) {
- ERROR("exec plugin: Failed to get group information "
- "for group ``%s'': %s",
- pl->group, STRERROR(status));
- goto failed;
- }
- if (gr_ptr == NULL) {
- ERROR("exec plugin: No such group: `%s'", pl->group);
- goto failed;
- }
-
- egid = gr.gr_gid;
- } else {
- egid = gid;
- }
- } /* if (pl->group == NULL) */
+ egid = getegr_id(pl, gid);
+ if (egid == -2) {
+ goto failed;
+ }
pid = fork();
if (pid < 0) {
static void nfs_read_linux(FILE *fh, const char *inst) {
char buffer[1024];
- char *fields[64];
+ // The stats line is prefixed with type and number of fields, thus plus 2
+ char *fields[MAX(NFS4_SERVER_MAX_PROC, NFS4_CLIENT_MAX_PROC) + 2];
int fields_num = 0;
if (fh == NULL)
struct redis_node_s {
char *name;
char *host;
+ char *socket;
char *passwd;
int port;
struct timeval timeout;
rq = next;
}
- redisFree(rn->redisContext);
+ if (rn->redisContext)
+ redisFree(rn->redisContext);
sfree(rn->name);
sfree(rn->host);
+ sfree(rn->socket);
sfree(rn->passwd);
sfree(rn);
} /* void redis_node_free */
rn->port = status;
status = 0;
}
+ } else if (strcasecmp("Socket", option->key) == 0) {
+ status = cf_util_get_string(option, &rn->socket);
} else if (strcasecmp("Query", option->key) == 0) {
redis_query_t *rq = redis_config_query(option);
if (rq == NULL) {
if (rn->redisContext)
return;
- redisContext *rh = redisConnectWithTimeout(rn->host, rn->port, rn->timeout);
+ redisContext *rh;
+ if (rn->socket != NULL)
+ rh = redisConnectUnixWithTimeout(rn->socket, rn->timeout);
+ else
+ rh = redisConnectWithTimeout(rn->host, rn->port, rn->timeout);
if (rh == NULL) {
ERROR("redis plugin: can't allocate redis context");
return;
}
if (rh->err) {
- ERROR("redis plugin: unable to connect to node `%s' (%s:%d): %s.", rn->name,
- rn->host, rn->port, rh->errstr);
+ if (rn->socket)
+ ERROR("redis plugin: unable to connect to node `%s' (%s): %s.", rn->name,
+ rn->socket, rh->errstr);
+ else
+ ERROR("redis plugin: unable to connect to node `%s' (%s:%d): %s.",
+ rn->name, rn->host, rn->port, rh->errstr);
redisFree(rh);
return;
}
{
redis_node_t *rn = user_data->data;
- DEBUG("redis plugin: querying info from node `%s' (%s:%d).", rn->name,
- rn->host, rn->port);
+#if COLLECT_DEBUG
+ if (rn->socket)
+ DEBUG("redis plugin: querying info from node `%s' (%s).", rn->name,
+ rn->socket);
+ else
+ DEBUG("redis plugin: querying info from node `%s' (%s:%d).", rn->name,
+ rn->host, rn->port);
+#endif
redis_check_connection(rn);
#if SENSORS_API_VERSION >= 0x402
(feature->type != SENSORS_FEATURE_CURR) &&
#endif
+#if SENSORS_API_VERSION >= 0x431
+ (feature->type != SENSORS_FEATURE_HUMIDITY) &&
+#endif
(feature->type != SENSORS_FEATURE_POWER)) {
DEBUG("sensors plugin: sensors_load_conf: "
"Ignoring feature `%s', "
#if SENSORS_API_VERSION >= 0x402
(subfeature->type != SENSORS_SUBFEATURE_CURR_INPUT) &&
#endif
+#if SENSORS_API_VERSION >= 0x431
+ (subfeature->type != SENSORS_SUBFEATURE_HUMIDITY_INPUT) &&
+#endif
(subfeature->type != SENSORS_SUBFEATURE_POWER_INPUT))
continue;
else if (fl->feature->type == SENSORS_FEATURE_CURR)
type = "current";
#endif
+#if SENSORS_API_VERSION >= 0x431
+ else if (fl->feature->type == SENSORS_FEATURE_HUMIDITY)
+ type = "humidity";
+#endif
else
continue;
#include "common.h"
#include "utils_dpdk.h"
+#if RTE_VERSION <= RTE_VERSION_NUM(18, 5, 0, 0)
#define DPDK_DEFAULT_RTE_CONFIG "/var/run/.rte_config"
+#else
+#define DPDK_DEFAULT_RTE_CONFIG "/var/run/dpdk/rte/config"
+#endif
#define DPDK_EAL_ARGC 10
// Complete trace should fit into 1024 chars. Trace contain some headers
// and text together with traced data from pipe. This is the reason why
status = cf_util_get_string_buffer(child, prefix, sizeof(prefix));
if (status == 0) {
+#if RTE_VERSION <= RTE_VERSION_NUM(18, 5, 0, 0)
snprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN,
"/var/run/.%s_config", prefix);
+#else
+ snprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN,
+ "/var/run/dpdk/%s/config", prefix);
+#endif
DEBUG("dpdk_common: EAL:File prefix %s", phc->eal_config.file_prefix);
}
} else if (strcasecmp("LogLevel", child->key) == 0) {
#undef BUFFER_ADD
- DEBUG("format_json: values_to_json: buffer = %s;", buffer);
sfree(rates);
return 0;
} /* }}} int values_to_json */
#undef BUFFER_ADD
- DEBUG("format_json: dstypes_to_json: buffer = %s;", buffer);
-
return 0;
} /* }}} int dstypes_to_json */
#undef BUFFER_ADD
- DEBUG("format_json: dsnames_to_json: buffer = %s;", buffer);
-
return 0;
} /* }}} int dsnames_to_json */
#undef BUFFER_ADD_KEYVAL
#undef BUFFER_ADD
- DEBUG("format_json: value_list_to_json: buffer = %s;", buffer);
-
return 0;
} /* }}} int value_list_to_json */
ERROR(PLUGIN_NAME
" failed to get stats for block device (%s) in domain %s",
state->block_devices[i].path,
- virDomainGetName(state->domains[i].ptr));
+ virDomainGetName(state->block_devices[i].dom));
}
/* Get interface stats for each domain. */