diff --git a/src/plugin.c b/src/plugin.c
index 5387f9c4b8a0c6e8c6c6922dda3604400a8486d1..bbede051bbfaea4972c120b4c3e4f79f5e777fe8 100644 (file)
--- a/src/plugin.c
+++ b/src/plugin.c
static int read_threads_num = 0;
static pthread_key_t plugin_ctx_key;
+static _Bool plugin_ctx_key_initialized = 0;
/*
* Static functions
dlh = lt_dlopenadvise(file, advise);
lt_dladvise_destroy(&advise);
} else {
- dlh = lt_dlopen (file);
+ dlh = lt_dlopen (file);
}
#else /* if LIBTOOL_VERSION == 1 */
if (flags & PLUGIN_FLAGS_GLOBAL)
int rf_type;
int rc;
- /* Get the read function that needs to be read next. */
+ /* Get the read function that needs to be read next.
+ * We don't need to hold "read_lock" for the heap, but we need
+ * to call c_heap_get_root() and pthread_cond_wait() in the
+ * same protected block. */
+ pthread_mutex_lock (&read_lock);
rf = c_heap_get_root (read_heap);
if (rf == NULL)
{
- struct timespec abstime;
-
- now = cdtime ();
-
- CDTIME_T_TO_TIMESPEC (now + interval_g, &abstime);
-
- pthread_mutex_lock (&read_lock);
- pthread_cond_timedwait (&read_cond, &read_lock,
- &abstime);
- pthread_mutex_unlock (&read_lock);
+ pthread_cond_wait (&read_cond, &read_lock);
+ pthread_mutex_unlock (&read_lock);
continue;
}
+ pthread_mutex_unlock (&read_lock);
if ((rf->rf_interval.tv_sec == 0) && (rf->rf_interval.tv_nsec == 0))
{
+ /* this should not happen, because the interval is set
+ * for each plugin when loading it
+ * XXX: issue a warning? */
now = cdtime ();
- CDTIME_T_TO_TIMESPEC (interval_g, &rf->rf_interval);
+ CDTIME_T_TO_TIMESPEC (plugin_get_interval (), &rf->rf_interval);
rf->rf_effective_interval = rf->rf_interval;
/* This does not fail. */
llist_append (read_list, le);
+ /* Wake up all the read threads. */
+ pthread_cond_broadcast (&read_cond);
pthread_mutex_unlock (&read_lock);
return (0);
} /* int plugin_insert_read */
int status;
if (ctx.interval != 0) {
+ /* If ctx.interval is not zero (== use the plugin or global
+ * interval), we need to use the "complex" read callback,
+ * because only that allows to specify a different interval.
+ * Wrap the callback using read_cb_wrapper(). */
struct timespec interval;
user_data_t user_data;
- DEBUG ("plugin_register_read: plugin_interval = %.3f",
- CDTIME_T_TO_DOUBLE(plugin_interval));
-
user_data.data = callback;
user_data.free_func = NULL;
name, read_cb_wrapper, &interval, &user_data);
}
+ DEBUG ("plugin_register_read: default_interval = %.3f",
+ CDTIME_T_TO_DOUBLE(plugin_get_interval ()));
+
rf = malloc (sizeof (*rf));
if (rf == NULL)
{
}
rf->rf_effective_interval = rf->rf_interval;
+ DEBUG ("plugin_register_read: interval = %i.%09i",
+ (int) rf->rf_interval.tv_sec,
+ (int) rf->rf_interval.tv_nsec);
+
/* Set user data */
if (user_data == NULL)
{
{
callback_func_t *cf = le->value;
plugin_write_cb callback;
- plugin_ctx_t old_ctx = plugin_set_ctx (cf->cf_ctx);
+
+ /* do not switch plugin context; rather keep the context (interval)
+ * information of the calling read plugin */
DEBUG ("plugin: plugin_write: Writing values via %s.", le->key);
callback = cf->cf_callback;
else
success++;
- plugin_set_ctx (old_ctx);
-
le = le->next;
}
{
callback_func_t *cf;
plugin_write_cb callback;
- plugin_ctx_t old_ctx;
le = llist_head (list_write);
while (le != NULL)
cf = le->value;
- old_ctx = plugin_set_ctx (cf->cf_ctx);
+ /* do not switch plugin context; rather keep the context (interval)
+ * information of the calling read plugin */
DEBUG ("plugin: plugin_write: Writing values via %s.", le->key);
callback = cf->cf_callback;
status = (*callback) (ds, vl, &cf->cf_udata);
-
- plugin_set_ctx (old_ctx);
}
return (status);
if (vl->time == 0)
vl->time = cdtime ();
- if (vl->interval <= 0) {
+ if (vl->interval <= 0)
+ {
plugin_ctx_t ctx = plugin_get_ctx ();
if (ctx.interval != 0)
vl->interval = ctx.interval;
else
- vl->interval = interval_g;
+ {
+ char name[6 * DATA_MAX_NAME_LEN];
+ FORMAT_VL (name, sizeof (name), vl);
+ ERROR ("plugin_dispatch_values: Unable to determine "
+ "interval from context for "
+ "value list \"%s\". "
+ "This indicates a broken plugin. "
+ "Please report this problem to the "
+ "collectd mailing list or at "
+ "<http://collectd.org/bugs/>.", name);
+ vl->interval = cf_get_default_interval ();
+ }
}
DEBUG ("plugin_dispatch_values: time = %.3f; interval = %.3f; "
{
callback_func_t *cf;
plugin_notification_cb callback;
- plugin_ctx_t old_ctx;
int status;
+ /* do not switch plugin context; rather keep the context
+ * (interval) information of the calling plugin */
+
cf = le->value;
- old_ctx = plugin_set_ctx (cf->cf_ctx);
callback = cf->cf_callback;
status = (*callback) (notif, &cf->cf_udata);
- plugin_set_ctx (old_ctx);
if (status != 0)
{
WARNING ("plugin_dispatch_notification: Notification "
{
callback_func_t *cf;
plugin_log_cb callback;
- plugin_ctx_t old_ctx;
cf = le->value;
- old_ctx = plugin_set_ctx (cf->cf_ctx);
callback = cf->cf_callback;
+ /* do not switch plugin context; rather keep the context
+ * (interval) information of the calling plugin */
+
(*callback) (level, msg, &cf->cf_udata);
- plugin_set_ctx (old_ctx);
le = le->next;
}
} /* void plugin_log */
+int parse_log_severity (const char *severity)
+{
+ int log_level = -1;
+
+ if ((0 == strcasecmp (severity, "emerg"))
+ || (0 == strcasecmp (severity, "alert"))
+ || (0 == strcasecmp (severity, "crit"))
+ || (0 == strcasecmp (severity, "err")))
+ log_level = LOG_ERR;
+ else if (0 == strcasecmp (severity, "warning"))
+ log_level = LOG_WARNING;
+ else if (0 == strcasecmp (severity, "notice"))
+ log_level = LOG_NOTICE;
+ else if (0 == strcasecmp (severity, "info"))
+ log_level = LOG_INFO;
+#if COLLECT_DEBUG
+ else if (0 == strcasecmp (severity, "debug"))
+ log_level = LOG_DEBUG;
+#endif /* COLLECT_DEBUG */
+
+ return (log_level);
+} /* int parse_log_severity */
+
+int parse_notif_severity (const char *severity)
+{
+ int notif_severity = -1;
+
+ if (strcasecmp (severity, "FAILURE") == 0)
+ notif_severity = NOTIF_FAILURE;
+ else if (strcmp (severity, "OKAY") == 0)
+ notif_severity = NOTIF_OKAY;
+ else if ((strcmp (severity, "WARNING") == 0)
+ || (strcmp (severity, "WARN") == 0))
+ notif_severity = NOTIF_WARNING;
+
+ return (notif_severity);
+} /* int parse_notif_severity */
+
const data_set_t *plugin_get_ds (const char *name)
{
data_set_t *ds;
}
*ctx = ctx_init;
+ assert (plugin_ctx_key_initialized);
pthread_setspecific (plugin_ctx_key, ctx);
DEBUG("Created new plugin context.");
return (ctx);
void plugin_init_ctx (void)
{
pthread_key_create (&plugin_ctx_key, plugin_ctx_destructor);
+ plugin_ctx_key_initialized = 1;
} /* void plugin_init_ctx */
plugin_ctx_t plugin_get_ctx (void)
{
plugin_ctx_t *ctx;
+ assert (plugin_ctx_key_initialized);
ctx = pthread_getspecific (plugin_ctx_key);
if (ctx == NULL) {
plugin_ctx_t *c;
plugin_ctx_t old;
+ assert (plugin_ctx_key_initialized);
c = pthread_getspecific (plugin_ctx_key);
if (c == NULL) {
return (old);
} /* void plugin_set_ctx */
+cdtime_t plugin_get_interval (void)
+{
+ cdtime_t interval;
+
+ interval = plugin_get_ctx().interval;
+ if (interval > 0)
+ return interval;
+
+ return cf_get_default_interval ();
+} /* cdtime_t plugin_get_interval */
+
typedef struct {
plugin_ctx_t ctx;
void *(*start_routine) (void *);