From 92d840921668dfc6a80684551d916206933b9c70 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Sun, 23 Nov 2008 18:19:34 +0100 Subject: [PATCH] set target: Implement a target to set fields in a value list. It's currently possible to re-set the `type'. This is most likely not good and will result in unpredictable behavior. I'll remove that, probably. --- configure.in | 2 + src/Makefile.am | 8 ++ src/target_set.c | 253 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 src/target_set.c diff --git a/configure.in b/configure.in index bcd4cc45..04fd27ba 100644 --- a/configure.in +++ b/configure.in @@ -2998,6 +2998,7 @@ AC_PLUGIN([swap], [$plugin_swap], [Swap usage statistics]) AC_PLUGIN([syslog], [$have_syslog], [Syslog logging plugin]) AC_PLUGIN([tail], [yes], [Parsing of logfiles]) AC_PLUGIN([tape], [$plugin_tape], [Tape drive statistics]) +AC_PLUGIN([target_set], [yes], [The set target]) AC_PLUGIN([tcpconns], [$plugin_tcpconns], [TCP connection statistics]) AC_PLUGIN([teamspeak2], [yes], [TeamSpeak2 server statistics]) AC_PLUGIN([thermal], [$plugin_thermal], [Linux ACPI thermal zone statistics]) @@ -3174,6 +3175,7 @@ Configuration: syslog . . . . . . . $enable_syslog tail . . . . . . . . $enable_tail tape . . . . . . . . $enable_tape + target_set . . . . . $enable_target_set tcpconns . . . . . . $enable_tcpconns teamspeak2 . . . . . $enable_teamspeak2 thermal . . . . . . . $enable_thermal diff --git a/src/Makefile.am b/src/Makefile.am index d26f9b85..d868f963 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -734,6 +734,14 @@ collectd_LDADD += "-dlopen" tape.la collectd_DEPENDENCIES += tape.la endif +if BUILD_PLUGIN_TARGET_SET +pkglib_LTLIBRARIES += target_set.la +target_set_la_SOURCES = target_set.c +target_set_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" target_set.la +collectd_DEPENDENCIES += target_set.la +endif + if BUILD_PLUGIN_TCPCONNS pkglib_LTLIBRARIES += tcpconns.la tcpconns_la_SOURCES = tcpconns.c diff --git a/src/target_set.c b/src/target_set.c new file mode 100644 index 00000000..3a4220ef --- /dev/null +++ b/src/target_set.c @@ -0,0 +1,253 @@ +/** + * collectd - src/target_set.c + * Copyright (C) 2008 Florian Forster + * + * 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: + * Florian Forster + **/ + +/* + * First tell the compiler to stick to the C99 and POSIX standards as close as + * possible. + */ +#ifndef __STRICT_ANSI__ /* {{{ */ +# define __STRICT_ANSI__ +#endif + +#ifndef _ISOC99_SOURCE +# define _ISOC99_SOURCE +#endif + +#ifdef _POSIX_C_SOURCE +# undef _POSIX_C_SOURCE +#endif +#define _POSIX_C_SOURCE 200112L + +#if 0 +/* Single UNIX needed for strdup. */ +#ifdef _XOPEN_SOURCE +# undef _XOPEN_SOURCE +#endif +#define _XOPEN_SOURCE 500 +#endif + +#ifndef _REENTRANT +# define _REENTRANT +#endif + +#ifndef _THREAD_SAFE +# define _THREAD_SAFE +#endif + +#ifdef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* }}} */ + +#include "collectd.h" +#include "common.h" +#include "filter_chain.h" + +struct ts_data_s +{ + char *host; + char *plugin; + char *plugin_instance; + char *type; + char *type_instance; +}; +typedef struct ts_data_s ts_data_t; + +static char *ts_strdup (const char *orig) /* {{{ */ +{ + size_t sz; + char *dest; + + if (orig == NULL) + return (NULL); + + sz = strlen (orig) + 1; + dest = (char *) malloc (sz); + if (dest == NULL) + return (NULL); + + memcpy (dest, orig, sz); + + return (dest); +} /* }}} char *ts_strdup */ + +static int ts_config_add_string (char **dest, /* {{{ */ + const oconfig_item_t *ci) +{ + char *temp; + + if (dest == NULL) + return (-EINVAL); + + if ((ci->values_num != 1) + || (ci->values[0].type != OCONFIG_TYPE_STRING)) + { + ERROR ("Target `set': The `%s' option requires exactly one string " + "argument.", ci->key); + return (-1); + } + + temp = ts_strdup (ci->values[0].value.string); + if (temp == NULL) + { + ERROR ("ts_config_add_string: ts_strdup failed."); + return (-1); + } + + free (*dest); + *dest = temp; + + return (0); +} /* }}} int ts_config_add_string */ + +static int ts_destroy (void **user_data) /* {{{ */ +{ + ts_data_t *data; + + if (user_data == NULL) + return (-EINVAL); + + data = *user_data; + if (data == NULL) + return (0); + + free (data->host); + free (data->plugin); + free (data->plugin_instance); + free (data->type); + free (data->type_instance); + free (data); + + return (0); +} /* }}} int ts_destroy */ + +static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */ +{ + ts_data_t *data; + int status; + int i; + + data = (ts_data_t *) malloc (sizeof (*data)); + if (data == NULL) + { + ERROR ("ts_create: malloc failed."); + return (-ENOMEM); + } + memset (data, 0, sizeof (*data)); + + data->host = NULL; + data->plugin = NULL; + data->plugin_instance = NULL; + data->type = NULL; + data->type_instance = NULL; + + status = 0; + for (i = 0; i < ci->children_num; i++) + { + oconfig_item_t *child = ci->children + i; + + if ((strcasecmp ("Host", child->key) == 0) + || (strcasecmp ("Hostname", child->key) == 0)) + status = ts_config_add_string (&data->host, child); + else if (strcasecmp ("Plugin", child->key) == 0) + status = ts_config_add_string (&data->plugin, child); + else if (strcasecmp ("PluginInstance", child->key) == 0) + status = ts_config_add_string (&data->plugin_instance, child); + else if (strcasecmp ("Type", child->key) == 0) + status = ts_config_add_string (&data->type, child); + else if (strcasecmp ("TypeInstance", child->key) == 0) + status = ts_config_add_string (&data->type_instance, child); + else + { + ERROR ("Target `set': The `%s' configuration option is not understood " + "and will be ignored.", child->key); + status = 0; + } + + if (status != 0) + break; + } + + /* Additional sanity-checking */ + while (status == 0) + { + if ((data->host == NULL) + && (data->plugin == NULL) + && (data->plugin_instance == NULL) + && (data->type == NULL) + && (data->type_instance == NULL)) + { + ERROR ("Target `set': You need to set at lease one of `Host', " + "`Plugin', `PluginInstance', `Type', or `TypeInstance'."); + status = -1; + } + + break; + } + + if (status != 0) + { + ts_destroy ((void *) &data); + return (status); + } + + *user_data = data; + return (0); +} /* }}} int ts_create */ + +static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */ + notification_meta_t **meta, void **user_data) +{ + ts_data_t *data; + + if ((ds == NULL) || (vl == NULL) || (user_data == NULL)) + return (-EINVAL); + + data = *user_data; + if (data == NULL) + { + ERROR ("Target `set': Invoke: `data' is NULL."); + return (-EINVAL); + } + +#define SET_FIELD(f) if (data->f != NULL) { sstrncpy (vl->f, data->f, sizeof (vl->f)); } + SET_FIELD (host); + SET_FIELD (plugin); + SET_FIELD (plugin_instance); + SET_FIELD (type); + SET_FIELD (type_instance); + + return (0); +} /* }}} int ts_invoke */ + +void module_register (void) +{ + target_proc_t tproc; + + memset (&tproc, 0, sizeof (tproc)); + tproc.create = ts_create; + tproc.destroy = ts_destroy; + tproc.invoke = ts_invoke; + fc_register_target ("set", tproc); +} /* module_register */ + +/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */ + -- 2.11.0