/**
* collectd - src/filter_chain.h
- * Copyright (C) 2008,2009 Florian octo Forster
+ * Copyright (C) 2008-2010 Florian octo 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
* Florian octo Forster <octo at verplant.org>
**/
-/*
- * 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 "configfile.h"
#include "plugin.h"
+#include "utils_complain.h"
#include "common.h"
#include "filter_chain.h"
fc_chain_t *next;
}; /* }}} */
+/* Writer configuration. */
+struct fc_writer_s;
+typedef struct fc_writer_s fc_writer_t; /* {{{ */
+struct fc_writer_s
+{
+ char *plugin;
+ c_complain_t complaint;
+}; /* }}} */
+
/*
* Global variables
*/
(*m->proc.destroy) (&m->user_data);
else if (m->user_data != NULL)
{
- ERROR ("Filter sybsystem: fc_free_matches: There is user data, but no "
+ ERROR ("Filter subsystem: fc_free_matches: There is user data, but no "
"destroy functions has been specified. "
"Memory will probably be lost!");
}
(*t->proc.destroy) (&t->user_data);
else if (t->user_data != NULL)
{
- ERROR ("Filter sybsystem: fc_free_targets: There is user data, but no "
+ ERROR ("Filter subsystem: fc_free_targets: There is user data, but no "
"destroy functions has been specified. "
"Memory will probably be lost!");
}
*
* The configuration looks somewhat like this:
*
- * <Chain "main">
+ * <Chain "PreCache">
* <Rule>
* <Match "regex">
* Plugin "^mysql$"
sstrncpy (m->name, ptr->name, sizeof (m->name));
memcpy (&m->proc, &ptr->proc, sizeof (m->proc));
- assert (m->proc.create != NULL);
m->user_data = NULL;
m->next = NULL;
- status = (*m->proc.create) (ci, &m->user_data);
- if (status != 0)
+ if (m->proc.create != NULL)
{
- WARNING ("Filter subsystem: Failed to create a %s match.",
- m->name);
- fc_free_matches (m);
- return (-1);
+ status = (*m->proc.create) (ci, &m->user_data);
+ if (status != 0)
+ {
+ WARNING ("Filter subsystem: Failed to create a %s match.",
+ m->name);
+ fc_free_matches (m);
+ return (-1);
+ }
}
-
+
if (*matches_head != NULL)
{
ptr = *matches_head;
t = (fc_target_t *) malloc (sizeof (*t));
if (t == NULL)
{
- ERROR ("fc_config_add_match: malloc failed.");
+ ERROR ("fc_config_add_target: malloc failed.");
return (-1);
}
memset (t, 0, sizeof (*t));
status = (*t->proc.create) (ci, &t->user_data);
if (status != 0)
{
- WARNING ("Filter subsystem: Failed to create a %s match.",
+ WARNING ("Filter subsystem: Failed to create a %s target.",
t->name);
fc_free_targets (t);
return (-1);
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
- status = 0;
if (strcasecmp ("Match", option->key) == 0)
status = fc_config_add_match (&rule->matches, option);
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
- status = 0;
if (strcasecmp ("Rule", option->key) == 0)
status = fc_config_add_rule (chain, option);
break;
} /* for (ci->children) */
- /* Additional sanity checking. */
- while (status == 0)
- {
- if (chain->targets == NULL)
- {
- WARNING ("Filter subsystem: Chain %s: No default target has been "
- "specified. Please make sure that there is a <Target> block within "
- "the <Chain> block!", chain->name);
- status = -1;
- break;
- }
-
- break;
- } /* while (status == 0) */
-
if (status != 0)
{
fc_free_chains (chain);
} /* }}} int fc_bit_jump_destroy */
static int fc_bit_jump_invoke (const data_set_t *ds, /* {{{ */
- value_list_t *vl, notification_meta_t **meta, void **user_data)
+ value_list_t *vl, notification_meta_t __attribute__((unused)) **meta,
+ void **user_data)
{
char *chain_name;
fc_chain_t *chain;
return (FC_TARGET_CONTINUE);
} /* }}} int fc_bit_jump_invoke */
-static int fc_bit_stop_invoke (const data_set_t *ds, /* {{{ */
- value_list_t *vl, notification_meta_t **meta, void **user_data)
+static int fc_bit_stop_invoke (const data_set_t __attribute__((unused)) *ds, /* {{{ */
+ value_list_t __attribute__((unused)) *vl,
+ notification_meta_t __attribute__((unused)) **meta,
+ void __attribute__((unused)) **user_data)
{
return (FC_TARGET_STOP);
} /* }}} int fc_bit_stop_invoke */
-static int fc_bit_return_invoke (const data_set_t *ds, /* {{{ */
- value_list_t *vl, notification_meta_t **meta, void **user_data)
+static int fc_bit_return_invoke (const data_set_t __attribute__((unused)) *ds, /* {{{ */
+ value_list_t __attribute__((unused)) *vl,
+ notification_meta_t __attribute__((unused)) **meta,
+ void __attribute__((unused)) **user_data)
{
return (FC_TARGET_RETURN);
} /* }}} int fc_bit_return_invoke */
{
int i;
- char **plugin_list;
- size_t plugin_list_len;
-
- plugin_list = NULL;
- plugin_list_len = 0;
+ fc_writer_t *plugin_list = NULL;
+ size_t plugin_list_len = 0;
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
- char **temp;
+ fc_writer_t *temp;
int j;
if (strcasecmp ("Plugin", child->key) != 0)
for (j = 0; j < child->values_num; j++)
{
+ char *plugin;
+
if (child->values[j].type != OCONFIG_TYPE_STRING)
{
ERROR ("Filter subsystem: Built-in target `write': "
"The `Plugin' option accepts only string arguments.");
continue;
}
+ plugin = child->values[j].value.string;
- temp = (char **) realloc (plugin_list, (plugin_list_len + 2)
+ temp = (fc_writer_t *) realloc (plugin_list, (plugin_list_len + 2)
* (sizeof (*plugin_list)));
if (temp == NULL)
{
}
plugin_list = temp;
- plugin_list[plugin_list_len] = fc_strdup (child->values[j].value.string);
- if (plugin_list[plugin_list_len] == NULL)
+ plugin_list[plugin_list_len].plugin = fc_strdup (plugin);
+ if (plugin_list[plugin_list_len].plugin == NULL)
{
ERROR ("fc_bit_write_create: fc_strdup failed.");
continue;
}
+ C_COMPLAIN_INIT (&plugin_list[plugin_list_len].complaint);
plugin_list_len++;
- plugin_list[plugin_list_len] = NULL;
+ plugin_list[plugin_list_len].plugin = NULL;
} /* for (j = 0; j < child->values_num; j++) */
} /* for (i = 0; i < ci->children_num; i++) */
static int fc_bit_write_destroy (void **user_data) /* {{{ */
{
- char **plugin_list;
+ fc_writer_t *plugin_list;
size_t i;
if ((user_data == NULL) || (*user_data == NULL))
plugin_list = *user_data;
- for (i = 0; plugin_list[i] != NULL; i++)
- free (plugin_list[i]);
+ for (i = 0; plugin_list[i].plugin != NULL; i++)
+ free (plugin_list[i].plugin);
free (plugin_list);
return (0);
} /* }}} int fc_bit_write_destroy */
static int fc_bit_write_invoke (const data_set_t *ds, /* {{{ */
- value_list_t *vl, notification_meta_t **meta, void **user_data)
+ value_list_t *vl, notification_meta_t __attribute__((unused)) **meta,
+ void **user_data)
{
- char **plugin_list;
+ fc_writer_t *plugin_list;
int status;
plugin_list = NULL;
if (user_data != NULL)
plugin_list = *user_data;
- if ((plugin_list == NULL) || (plugin_list[0] == NULL))
+ if ((plugin_list == NULL) || (plugin_list[0].plugin == NULL))
{
+ static c_complain_t write_complaint = C_COMPLAIN_INIT_STATIC;
+
status = plugin_write (/* plugin = */ NULL, ds, vl);
- if (status != 0)
+ if (status == ENOENT)
{
- INFO ("Filter subsystem: Built-in target `write': Dispatching value to "
+ /* in most cases this is a permanent error, so use the complain
+ * mechanism rather than spamming the logs */
+ c_complain (LOG_INFO, &write_complaint,
+ "Filter subsystem: Built-in target `write': Dispatching value to "
+ "all write plugins failed with status %i (ENOENT). "
+ "Most likely this means you didn't load any write plugins.",
+ status);
+ }
+ else if (status != 0)
+ {
+ /* often, this is a permanent error (e.g. target system unavailable),
+ * so use the complain mechanism rather than spamming the logs */
+ c_complain (LOG_INFO, &write_complaint,
+ "Filter subsystem: Built-in target `write': Dispatching value to "
"all write plugins failed with status %i.", status);
}
+ else
+ {
+ assert (status == 0);
+ c_release (LOG_INFO, &write_complaint, "Filter subsystem: "
+ "Built-in target `write': Some write plugin is back to normal "
+ "operation. `write' succeeded.");
+ }
}
else
{
size_t i;
- for (i = 0; plugin_list[i] != NULL; i++)
+ for (i = 0; plugin_list[i].plugin != NULL; i++)
{
- status = plugin_write (plugin_list[i], ds, vl);
+ status = plugin_write (plugin_list[i].plugin, ds, vl);
if (status != 0)
{
- INFO ("Filter subsystem: Built-in target `write': Dispatching value to "
- "the `%s' plugin failed with status %i.", plugin_list[i], status);
+ c_complain (LOG_INFO, &plugin_list[i].complaint,
+ "Filter subsystem: Built-in target `write': Dispatching value to "
+ "the `%s' plugin failed with status %i.",
+ plugin_list[i].plugin, status);
+ }
+ else
+ {
+ c_release (LOG_INFO, &plugin_list[i].complaint,
+ "Filter subsystem: Built-in target `write': Plugin `%s' is back "
+ "to normal operation. `write' succeeded.", plugin_list[i].plugin);
}
} /* for (i = 0; plugin_list[i] != NULL; i++) */
}
/* N. B.: rule->matches may be NULL. */
for (match = rule->matches; match != NULL; match = match->next)
{
+ /* FIXME: Pass the meta-data to match targets here (when implemented). */
status = (*match->proc.match) (ds, vl, /* meta = */ NULL,
&match->user_data);
if (status < 0)
{
/* If we get here, all matches have matched the value. Execute the
* target. */
+ /* FIXME: Pass the meta-data to match targets here (when implemented). */
status = (*target->proc.invoke) (ds, vl, /* meta = */ NULL,
&target->user_data);
if (status < 0)
{
/* If we get here, all matches have matched the value. Execute the
* target. */
+ /* FIXME: Pass the meta-data to match targets here (when implemented). */
status = (*target->proc.invoke) (ds, vl, /* meta = */ NULL,
&target->user_data);
if (status < 0)
* matches match. */
int fc_default_action (const data_set_t *ds, value_list_t *vl) /* {{{ */
{
+ /* FIXME: Pass the meta-data to match targets here (when implemented). */
return (fc_bit_write_invoke (ds, vl,
/* meta = */ NULL, /* user_data = */ NULL));
} /* }}} int fc_default_action */