X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fplugin.c;h=d185ef2fb3d6c0be41e861ffe4baed6bb5f8de6e;hb=45aa6a65c24e38c0a3fa3880a300fbb02db50486;hp=4d503f7c457196493cdb1ce5c9e852d9f44cc8a5;hpb=c87da66245197f489bb0e9efffc23538cf07e70b;p=collectd.git diff --git a/src/plugin.c b/src/plugin.c index 4d503f7c..d185ef2f 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -1,6 +1,6 @@ /** * collectd - src/plugin.c - * Copyright (C) 2005-2008 Florian octo Forster + * Copyright (C) 2005-2009 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 @@ -36,16 +36,31 @@ #include "utils_llist.h" #include "utils_cache.h" #include "utils_threshold.h" +#include "filter_chain.h" /* * Private structures */ +struct callback_func_s +{ + void *cf_callback; + user_data_t cf_udata; +}; +typedef struct callback_func_s callback_func_t; + +#define RF_SIMPLE 0 +#define RF_COMPLEX 1 struct read_func_s { - int wait_time; - int wait_left; - int (*callback) (void); - enum { DONE = 0, TODO = 1, ACTIVE = 2 } needs_read; + /* `read_func_t' "inherits" from `callback_func_t'. + * The `rf_super' member MUST be the first one in this structure! */ +#define rf_callback rf_super.cf_callback +#define rf_udata rf_super.cf_udata + callback_func_t rf_super; + int rf_type; + int rf_wait_time; + int rf_wait_left; + enum { DONE = 0, TODO = 1, ACTIVE = 2 } rf_needs_read; }; typedef struct read_func_s read_func_t; @@ -55,12 +70,14 @@ typedef struct read_func_s read_func_t; static llist_t *list_init; static llist_t *list_read; static llist_t *list_write; -static llist_t *list_filter; static llist_t *list_flush; static llist_t *list_shutdown; static llist_t *list_log; static llist_t *list_notification; +static fc_chain_t *pre_cache_chain = NULL; +static fc_chain_t *post_cache_chain = NULL; + static c_avl_tree_t *data_sets; static char *plugindir = NULL; @@ -82,26 +99,81 @@ static const char *plugin_get_dir (void) return (plugindir); } -static int register_callback (llist_t **list, const char *name, void *callback) +static void destroy_callback (callback_func_t *cf) /* {{{ */ +{ + if (cf == NULL) + return; + + if ((cf->cf_udata.data != NULL) && (cf->cf_udata.free_func != NULL)) + { + cf->cf_udata.free_func (cf->cf_udata.data); + cf->cf_udata.data = NULL; + cf->cf_udata.free_func = NULL; + } + sfree (cf); +} /* }}} void destroy_callback */ + +static void destroy_all_callbacks (llist_t **list) /* {{{ */ +{ + llentry_t *le; + + if (*list == NULL) + return; + + le = llist_head (*list); + while (le != NULL) + { + llentry_t *le_next; + + le_next = le->next; + + sfree (le->key); + destroy_callback (le->value); + le->value = NULL; + + le = le_next; + } + + llist_destroy (*list); + *list = NULL; +} /* }}} void destroy_all_callbacks */ + +static int register_callback (llist_t **list, /* {{{ */ + const char *name, callback_func_t *cf) { llentry_t *le; char *key; - if ((*list == NULL) - && ((*list = llist_create ()) == NULL)) + if (*list == NULL) + { + *list = llist_create (); + if (*list == NULL) + { + ERROR ("plugin: create_register_callback: " + "llist_create failed."); + destroy_callback (cf); + return (-1); + } + } + + key = strdup (name); + if (key == NULL) + { + ERROR ("plugin: create_register_callback: strdup failed."); + destroy_callback (cf); return (-1); + } le = llist_search (*list, name); if (le == NULL) { - key = strdup (name); - if (key == NULL) - return (-1); - - le = llentry_create (key, callback); + le = llentry_create (key, cf); if (le == NULL) { + ERROR ("plugin: create_register_callback: " + "llentry_create failed."); free (key); + destroy_callback (cf); return (-1); } @@ -109,27 +181,67 @@ static int register_callback (llist_t **list, const char *name, void *callback) } else { - le->value = callback; + callback_func_t *old_cf; + + old_cf = le->value; + le->value = cf; + + destroy_callback (old_cf); + sfree (key); } return (0); -} /* int register_callback */ +} /* }}} int register_callback */ + +static int create_register_callback (llist_t **list, /* {{{ */ + const char *name, void *callback, user_data_t *ud) +{ + char *key; + callback_func_t *cf; + + cf = (callback_func_t *) malloc (sizeof (*cf)); + if (cf == NULL) + { + ERROR ("plugin: create_register_callback: malloc failed."); + sfree (key); + return (-1); + } + memset (cf, 0, sizeof (*cf)); -static int plugin_unregister (llist_t *list, const char *name) + cf->cf_callback = callback; + if (ud == NULL) + { + cf->cf_udata.data = NULL; + cf->cf_udata.free_func = NULL; + } + else + { + cf->cf_udata = *ud; + } + + return (register_callback (list, name, cf)); +} /* }}} int create_register_callback */ + +static int plugin_unregister (llist_t *list, const char *name) /* {{{ */ { llentry_t *e; - e = llist_search (list, name); + if (list == NULL) + return (-1); + e = llist_search (list, name); if (e == NULL) return (-1); llist_remove (list, e); - free (e->key); + + sfree (e->key); + destroy_callback (e->value); + llentry_destroy (e); return (0); -} /* int plugin_unregister */ +} /* }}} int plugin_unregister */ /* * (Try to) load the shared object `file'. Won't complain if it isn't a shared @@ -168,7 +280,7 @@ static int plugin_load_file (char *file) return (0); } -static void *plugin_read_thread (void *args) +static void *plugin_read_thread (void __attribute__((unused)) *args) { llentry_t *le; read_func_t *rf; @@ -186,44 +298,58 @@ static void *plugin_read_thread (void *args) { rf = (read_func_t *) le->value; - if (rf->needs_read != TODO) + if (rf->rf_needs_read != TODO) { le = le->next; continue; } /* We will do this read function */ - rf->needs_read = ACTIVE; + rf->rf_needs_read = ACTIVE; DEBUG ("[thread #%5lu] plugin: plugin_read_thread: Handling %s", (unsigned long int) pthread_self (), le->key); pthread_mutex_unlock (&read_lock); - status = rf->callback (); + if (rf->rf_type == RF_SIMPLE) + { + int (*callback) (void); + + callback = rf->rf_callback; + status = (*callback) (); + } + else + { + plugin_read_cb callback; + + callback = rf->rf_callback; + status = (*callback) (&rf->rf_udata); + } + done++; if (status != 0) { - if (rf->wait_time < interval_g) - rf->wait_time = interval_g; - rf->wait_left = rf->wait_time; - rf->wait_time = rf->wait_time * 2; - if (rf->wait_time > 86400) - rf->wait_time = 86400; + if (rf->rf_wait_time < interval_g) + rf->rf_wait_time = interval_g; + rf->rf_wait_left = rf->rf_wait_time; + rf->rf_wait_time = rf->rf_wait_time * 2; + if (rf->rf_wait_time > 86400) + rf->rf_wait_time = 86400; NOTICE ("read-function of plugin `%s' " "failed. Will suspend it for %i " - "seconds.", le->key, rf->wait_left); + "seconds.", le->key, rf->rf_wait_left); } else { - rf->wait_left = 0; - rf->wait_time = interval_g; + rf->rf_wait_left = 0; + rf->rf_wait_time = interval_g; } pthread_mutex_lock (&read_lock); - rf->needs_read = DONE; + rf->rf_needs_read = DONE; le = le->next; } /* while (le != NULL) */ @@ -241,7 +367,7 @@ static void *plugin_read_thread (void *args) return ((void *) 0); } /* void *plugin_read_thread */ -static void start_threads (int num) +static void start_read_threads (int num) { int i; @@ -251,7 +377,7 @@ static void start_threads (int num) read_threads = (pthread_t *) calloc (num, sizeof (pthread_t)); if (read_threads == NULL) { - ERROR ("plugin: start_threads: calloc failed."); + ERROR ("plugin: start_read_threads: calloc failed."); return; } @@ -265,19 +391,22 @@ static void start_threads (int num) } else { - ERROR ("plugin: start_threads: pthread_create failed."); + ERROR ("plugin: start_read_threads: pthread_create failed."); return; } } /* for (i) */ -} /* void start_threads */ +} /* void start_read_threads */ -static void stop_threads (void) +static void stop_read_threads (void) { int i; + if (read_threads == NULL) + return; + pthread_mutex_lock (&read_lock); read_loop = 0; - DEBUG ("plugin: stop_threads: Signalling `read_cond'"); + DEBUG ("plugin: stop_read_threads: Signalling `read_cond'"); pthread_cond_broadcast (&read_cond); pthread_mutex_unlock (&read_lock); @@ -285,13 +414,13 @@ static void stop_threads (void) { if (pthread_join (read_threads[i], NULL) != 0) { - ERROR ("plugin: stop_threads: pthread_join failed."); + ERROR ("plugin: stop_read_threads: pthread_join failed."); } read_threads[i] = (pthread_t) 0; } sfree (read_threads); read_threads_num = 0; -} /* void stop_threads */ +} /* void stop_read_threads */ /* * Public functions @@ -322,6 +451,7 @@ int plugin_load (const char *type) int ret; struct stat statbuf; struct dirent *de; + int status; DEBUG ("type = %s", type); @@ -330,8 +460,8 @@ int plugin_load (const char *type) /* `cpu' should not match `cpufreq'. To solve this we add `.so' to the * type when matching the filename */ - if (ssnprintf (typename, sizeof (typename), - "%s.so", type) >= sizeof (typename)) + status = ssnprintf (typename, sizeof (typename), "%s.so", type); + if ((status < 0) || ((size_t) status >= sizeof (typename))) { WARNING ("snprintf: truncated: `%s.so'", type); return (-1); @@ -351,8 +481,9 @@ int plugin_load (const char *type) if (strncasecmp (de->d_name, typename, typename_len)) continue; - if (ssnprintf (filename, sizeof (filename), - "%s/%s", dir, de->d_name) >= sizeof (filename)) + status = ssnprintf (filename, sizeof (filename), + "%s/%s", dir, de->d_name); + if ((status < 0) || ((size_t) status >= sizeof (filename))) { WARNING ("snprintf: truncated: `%s/%s'", dir, de->d_name); continue; @@ -411,7 +542,8 @@ int plugin_register_complex_config (const char *type, int plugin_register_init (const char *name, int (*callback) (void)) { - return (register_callback (&list_init, name, (void *) callback)); + return (create_register_callback (&list_init, name, (void *) callback, + /* user_data = */ NULL)); } /* plugin_register_init */ int plugin_register_read (const char *name, @@ -428,37 +560,70 @@ int plugin_register_read (const char *name, return (-1); } - memset (rf, '\0', sizeof (read_func_t)); - rf->wait_time = interval_g; - rf->wait_left = 0; - rf->callback = callback; - rf->needs_read = DONE; + memset (rf, 0, sizeof (read_func_t)); + rf->rf_callback = (void *) callback; + rf->rf_udata.data = NULL; + rf->rf_udata.free_func = NULL; + rf->rf_wait_time = interval_g; + rf->rf_wait_left = 0; + rf->rf_type = RF_SIMPLE; + rf->rf_needs_read = DONE; - return (register_callback (&list_read, name, (void *) rf)); + return (register_callback (&list_read, name, (callback_func_t *) rf)); } /* int plugin_register_read */ -int plugin_register_write (const char *name, - int (*callback) (const data_set_t *ds, const value_list_t *vl)) +int plugin_register_complex_read (const char *name, + plugin_read_cb callback, user_data_t *user_data) { - return (register_callback (&list_write, name, (void *) callback)); -} /* int plugin_register_write */ + read_func_t *rf; + + rf = (read_func_t *) malloc (sizeof (read_func_t)); + if (rf == NULL) + { + ERROR ("plugin_register_complex_read: malloc failed."); + return (-1); + } + + memset (rf, 0, sizeof (read_func_t)); + rf->rf_callback = (void *) callback; + rf->rf_wait_time = interval_g; + rf->rf_wait_left = 0; + rf->rf_type = RF_COMPLEX; + rf->rf_needs_read = DONE; + + /* Set user data */ + if (user_data == NULL) + { + rf->rf_udata.data = NULL; + rf->rf_udata.free_func = NULL; + } + else + { + rf->rf_udata = *user_data; + } -int plugin_register_filter (const char *name, - int (*callback) (const data_set_t *ds, value_list_t *vl)) + return (register_callback (&list_read, name, (callback_func_t *) rf)); +} /* int plugin_register_complex_read */ + +int plugin_register_write (const char *name, + plugin_write_cb callback, user_data_t *ud) { - return (register_callback (&list_filter, name, (void *) callback)); -} /* int plugin_register_filter */ + return (create_register_callback (&list_write, name, + (void *) callback, ud)); +} /* int plugin_register_write */ int plugin_register_flush (const char *name, - int (*callback) (const int timeout, const char *identifier)) + plugin_flush_cb callback, user_data_t *ud) { - return (register_callback (&list_flush, name, (void *) callback)); + return (create_register_callback (&list_flush, name, + (void *) callback, ud)); } /* int plugin_register_flush */ int plugin_register_shutdown (char *name, int (*callback) (void)) { - return (register_callback (&list_shutdown, name, (void *) callback)); + return (create_register_callback (&list_shutdown, name, + (void *) callback, /* user_data = */ NULL)); } /* int plugin_register_shutdown */ int plugin_register_data_set (const data_set_t *ds) @@ -498,16 +663,18 @@ int plugin_register_data_set (const data_set_t *ds) return (c_avl_insert (data_sets, (void *) ds_copy->type, (void *) ds_copy)); } /* int plugin_register_data_set */ -int plugin_register_log (char *name, - void (*callback) (int priority, const char *msg)) +int plugin_register_log (const char *name, + plugin_log_cb callback, user_data_t *ud) { - return (register_callback (&list_log, name, (void *) callback)); + return (create_register_callback (&list_log, name, + (void *) callback, ud)); } /* int plugin_register_log */ int plugin_register_notification (const char *name, - int (*callback) (const notification_t *notif)) + plugin_notification_cb callback, user_data_t *ud) { - return (register_callback (&list_notification, name, (void *) callback)); + return (create_register_callback (&list_notification, name, + (void *) callback, ud)); } /* int plugin_register_log */ int plugin_unregister_config (const char *name) @@ -529,19 +696,7 @@ int plugin_unregister_init (const char *name) int plugin_unregister_read (const char *name) { - llentry_t *e; - - e = llist_search (list_read, name); - - if (e == NULL) - return (-1); - - llist_remove (list_read, e); - free (e->value); - free (e->key); - llentry_destroy (e); - - return (0); + return (plugin_unregister (list_read, name)); } int plugin_unregister_write (const char *name) @@ -549,11 +704,6 @@ int plugin_unregister_write (const char *name) return (plugin_unregister (list_write, name)); } -int plugin_unregister_filter (const char *name) -{ - return (plugin_unregister (list_filter, name)); -} - int plugin_unregister_flush (const char *name) { return (plugin_unregister (list_flush, name)); @@ -592,13 +742,20 @@ int plugin_unregister_notification (const char *name) void plugin_init_all (void) { - int (*callback) (void); + const char *chain_name; llentry_t *le; int status; /* Init the value cache */ uc_init (); + chain_name = global_option_get ("PreCacheChain"); + pre_cache_chain = fc_chain_get_by_name (chain_name); + + chain_name = global_option_get ("PostCacheChain"); + post_cache_chain = fc_chain_get_by_name (chain_name); + + if ((list_init == NULL) && (list_read == NULL)) return; @@ -608,7 +765,11 @@ void plugin_init_all (void) le = llist_head (list_init); while (le != NULL) { - callback = (int (*) (void)) le->value; + callback_func_t *cf; + plugin_init_cb callback; + + cf = le->value; + callback = cf->cf_callback; status = (*callback) (); if (status != 0) @@ -634,7 +795,8 @@ void plugin_init_all (void) int num; rt = global_option_get ("ReadThreads"); num = atoi (rt); - start_threads ((num > 0) ? num : 5); + if (num != -1) + start_read_threads ((num > 0) ? num : 5); } } /* void plugin_init_all */ @@ -655,18 +817,18 @@ void plugin_read_all (void) { rf = (read_func_t *) le->value; - if (rf->needs_read != DONE) + if (rf->rf_needs_read != DONE) { le = le->next; continue; } - if (rf->wait_left > 0) - rf->wait_left -= interval_g; + if (rf->rf_wait_left > 0) + rf->rf_wait_left -= interval_g; - if (rf->wait_left <= 0) + if (rf->rf_wait_left <= 0) { - rf->needs_read = TODO; + rf->rf_needs_read = TODO; } le = le->next; @@ -677,9 +839,130 @@ void plugin_read_all (void) pthread_mutex_unlock (&read_lock); } /* void plugin_read_all */ +/* Read function called when the `-T' command line argument is given. */ +int plugin_read_all_once (void) +{ + llentry_t *le; + read_func_t *rf; + int status; + int return_status = 0; + + if (list_read == NULL) + { + NOTICE ("No read-functions are registered."); + return (0); + } + + for (le = llist_head (list_read); + le != NULL; + le = le->next) + { + rf = (read_func_t *) le->value; + + if (rf->rf_type == RF_SIMPLE) + { + int (*callback) (void); + + callback = rf->rf_callback; + status = (*callback) (); + } + else + { + plugin_read_cb callback; + + callback = rf->rf_callback; + status = (*callback) (&rf->rf_udata); + } + + if (status != 0) + { + NOTICE ("read-function of plugin `%s' failed.", + le->key); + return_status = -1; + } + } + + return (return_status); +} /* int plugin_read_all_once */ + +int plugin_write (const char *plugin, /* {{{ */ + const data_set_t *ds, const value_list_t *vl) +{ + llentry_t *le; + int status; + + if (vl == NULL) + return (EINVAL); + + if (list_write == NULL) + return (ENOENT); + + if (ds == NULL) + { + ds = plugin_get_ds (vl->type); + if (ds == NULL) + { + ERROR ("plugin_write: Unable to lookup type `%s'.", vl->type); + return (ENOENT); + } + } + + if (plugin == NULL) + { + int success = 0; + int failure = 0; + + le = llist_head (list_write); + while (le != NULL) + { + callback_func_t *cf = le->value; + plugin_write_cb callback; + + DEBUG ("plugin: plugin_write: Writing values via %s.", le->key); + callback = cf->cf_callback; + status = (*callback) (ds, vl, &cf->cf_udata); + if (status != 0) + failure++; + else + success++; + + le = le->next; + } + + if ((success == 0) && (failure != 0)) + status = -1; + else + status = 0; + } + else /* plugin != NULL */ + { + callback_func_t *cf; + plugin_write_cb callback; + + le = llist_head (list_write); + while (le != NULL) + { + if (strcasecmp (plugin, le->key) == 0) + break; + + le = le->next; + } + + if (le == NULL) + return (ENOENT); + + cf = le->value; + + DEBUG ("plugin: plugin_write: Writing values via %s.", le->key); + callback = cf->cf_callback; + status = (*callback) (ds, vl, &cf->cf_udata); + } + + return (status); +} /* }}} int plugin_write */ + int plugin_flush (const char *plugin, int timeout, const char *identifier) { - int (*callback) (int timeout, const char *identifier); llentry_t *le; if (list_flush == NULL) @@ -688,6 +971,9 @@ int plugin_flush (const char *plugin, int timeout, const char *identifier) le = llist_head (list_flush); while (le != NULL) { + callback_func_t *cf; + plugin_flush_cb callback; + if ((plugin != NULL) && (strcmp (plugin, le->key) != 0)) { @@ -695,8 +981,10 @@ int plugin_flush (const char *plugin, int timeout, const char *identifier) continue; } - callback = (int (*) (int, const char *)) le->value; - (*callback) (timeout, identifier); + cf = le->value; + callback = cf->cf_callback; + + (*callback) (timeout, identifier, &cf->cf_udata); le = le->next; } @@ -705,18 +993,27 @@ int plugin_flush (const char *plugin, int timeout, const char *identifier) void plugin_shutdown_all (void) { - int (*callback) (void); llentry_t *le; - stop_threads (); + stop_read_threads (); - if (list_shutdown == NULL) - return; + destroy_all_callbacks (&list_init); + destroy_all_callbacks (&list_read); + + plugin_flush (/* plugin = */ NULL, /* timeout = */ -1, + /* identifier = */ NULL); + + le = NULL; + if (list_shutdown != NULL) + le = llist_head (list_shutdown); - le = llist_head (list_shutdown); while (le != NULL) { - callback = (int (*) (void)) le->value; + callback_func_t *cf; + plugin_shutdown_cb callback; + + cf = le->value; + callback = cf->cf_callback; /* Advance the pointer before calling the callback allows * shutdown functions to unregister themselves. If done the @@ -726,18 +1023,27 @@ void plugin_shutdown_all (void) (*callback) (); } + + destroy_all_callbacks (&list_write); + destroy_all_callbacks (&list_flush); + destroy_all_callbacks (&list_notification); + destroy_all_callbacks (&list_shutdown); + destroy_all_callbacks (&list_log); } /* void plugin_shutdown_all */ int plugin_dispatch_values (value_list_t *vl) { + int status; static c_complain_t no_write_complaint = C_COMPLAIN_INIT_STATIC; - data_set_t *ds; - llentry_t *le; + value_t *saved_values; + int saved_values_len; - int filter = 0; + data_set_t *ds; - if ((vl == NULL) || (*vl->type == '\0')) { + if ((vl == NULL) || (vl->type[0] == 0) + || (vl->values == NULL) || (vl->values_len < 1)) + { ERROR ("plugin_dispatch_values: Invalid value list."); return (-1); } @@ -762,6 +1068,9 @@ int plugin_dispatch_values (value_list_t *vl) return (-1); } + if (vl->time == 0) + vl->time = time (NULL); + DEBUG ("plugin_dispatch_values: time = %u; interval = %i; " "host = %s; " "plugin = %s; plugin_instance = %s; " @@ -798,38 +1107,79 @@ int plugin_dispatch_values (value_list_t *vl) escape_slashes (vl->type, sizeof (vl->type)); escape_slashes (vl->type_instance, sizeof (vl->type_instance)); - le = llist_head (list_filter); - while (le != NULL) + /* Copy the values. This way, we can assure `targets' that they get + * dynamically allocated values, which they can free and replace if + * they like. */ + if ((pre_cache_chain != NULL) || (post_cache_chain != NULL)) { - int (*filter_callback) (const data_set_t *, value_list_t *) = - (int (*) (const data_set_t *, value_list_t *)) le->value; + saved_values = vl->values; + saved_values_len = vl->values_len; - filter |= (*filter_callback) (ds, vl); - - if (filter == FILTER_IGNORE) + vl->values = (value_t *) calloc (vl->values_len, + sizeof (*vl->values)); + if (vl->values == NULL) + { + ERROR ("plugin_dispatch_values: calloc failed."); + vl->values = saved_values; return (-1); + } + memcpy (vl->values, saved_values, + vl->values_len * sizeof (*vl->values)); + } + else /* if ((pre == NULL) && (post == NULL)) */ + { + saved_values = NULL; + saved_values_len = 0; + } - le = le->next; + if (pre_cache_chain != NULL) + { + status = fc_process_chain (ds, vl, pre_cache_chain); + if (status < 0) + { + WARNING ("plugin_dispatch_values: Running the " + "pre-cache chain failed with " + "status %i (%#x).", + status, status); + } + else if (status == FC_TARGET_STOP) + { + /* Restore the state of the value_list so that plugins + * don't get confused.. */ + if (saved_values != NULL) + { + free (vl->values); + vl->values = saved_values; + vl->values_len = saved_values_len; + } + return (0); + } } /* Update the value cache */ uc_update (ds, vl); - if ((filter & FILTER_NOTHRESHOLD_CHECK) == 0) - ut_check_threshold (ds, vl); - - if (filter & FILTER_NOWRITE) - return (0); - - le = llist_head (list_write); - while (le != NULL) + if (post_cache_chain != NULL) { - int (*write_callback) (const data_set_t *, const value_list_t *) = - (int (*) (const data_set_t *, const value_list_t *)) le->value; - - (*write_callback) (ds, vl); + status = fc_process_chain (ds, vl, post_cache_chain); + if (status < 0) + { + WARNING ("plugin_dispatch_values: Running the " + "post-cache chain failed with " + "status %i (%#x).", + status, status); + } + } + else + fc_default_action (ds, vl); - le = le->next; + /* Restore the state of the value_list so that plugins don't get + * confused.. */ + if (saved_values != NULL) + { + free (vl->values); + vl->values = saved_values; + vl->values_len = saved_values_len; } return (0); @@ -837,7 +1187,6 @@ int plugin_dispatch_values (value_list_t *vl) int plugin_dispatch_notification (const notification_t *notif) { - int (*callback) (const notification_t *); llentry_t *le; /* Possible TODO: Add flap detection here */ @@ -853,8 +1202,19 @@ int plugin_dispatch_notification (const notification_t *notif) le = llist_head (list_notification); while (le != NULL) { - callback = (int (*) (const notification_t *)) le->value; - (*callback) (notif); + callback_func_t *cf; + plugin_notification_cb callback; + int status; + + cf = le->value; + callback = cf->cf_callback; + status = (*callback) (notif, &cf->cf_udata); + if (status != 0) + { + WARNING ("plugin_dispatch_notification: Notification " + "callback %s returned %i.", + le->key, status); + } le = le->next; } @@ -866,8 +1226,6 @@ void plugin_log (int level, const char *format, ...) { char msg[1024]; va_list ap; - - void (*callback) (int, const char *); llentry_t *le; if (list_log == NULL) @@ -886,8 +1244,13 @@ void plugin_log (int level, const char *format, ...) le = llist_head (list_log); while (le != NULL) { - callback = (void (*) (int, const char *)) le->value; - (*callback) (level, msg); + callback_func_t *cf; + plugin_log_cb callback; + + cf = le->value; + callback = cf->cf_callback; + + (*callback) (level, msg, &cf->cf_udata); le = le->next; } @@ -935,8 +1298,8 @@ static int plugin_notification_meta_add (notification_t *n, { case NM_TYPE_STRING: { - meta->value_string = strdup ((const char *) value); - if (meta->value_string == NULL) + meta->nm_value.nm_string = strdup ((const char *) value); + if (meta->nm_value.nm_string == NULL) { ERROR ("plugin_notification_meta_add: strdup failed."); sfree (meta); @@ -946,22 +1309,22 @@ static int plugin_notification_meta_add (notification_t *n, } case NM_TYPE_SIGNED_INT: { - meta->value_signed_int = *((int64_t *) value); + meta->nm_value.nm_signed_int = *((int64_t *) value); break; } case NM_TYPE_UNSIGNED_INT: { - meta->value_unsigned_int = *((uint64_t *) value); + meta->nm_value.nm_unsigned_int = *((uint64_t *) value); break; } case NM_TYPE_DOUBLE: { - meta->value_double = *((double *) value); + meta->nm_value.nm_double = *((double *) value); break; } case NM_TYPE_BOOLEAN: { - meta->value_boolean = *((bool *) value); + meta->nm_value.nm_boolean = *((bool *) value); break; } default: @@ -1034,25 +1397,25 @@ int plugin_notification_meta_copy (notification_t *dst, { if (meta->type == NM_TYPE_STRING) plugin_notification_meta_add_string (dst, meta->name, - meta->value_string); + meta->nm_value.nm_string); else if (meta->type == NM_TYPE_SIGNED_INT) plugin_notification_meta_add_signed_int (dst, meta->name, - meta->value_signed_int); + meta->nm_value.nm_signed_int); else if (meta->type == NM_TYPE_UNSIGNED_INT) plugin_notification_meta_add_unsigned_int (dst, meta->name, - meta->value_unsigned_int); + meta->nm_value.nm_unsigned_int); else if (meta->type == NM_TYPE_DOUBLE) plugin_notification_meta_add_double (dst, meta->name, - meta->value_double); + meta->nm_value.nm_double); else if (meta->type == NM_TYPE_BOOLEAN) plugin_notification_meta_add_boolean (dst, meta->name, - meta->value_boolean); + meta->nm_value.nm_boolean); } return (0); } /* int plugin_notification_meta_copy */ -int plugin_notification_meta_free (notification_t *n) +int plugin_notification_meta_free (notification_meta_t *n) { notification_meta_t *this; notification_meta_t *next; @@ -1063,16 +1426,15 @@ int plugin_notification_meta_free (notification_t *n) return (-1); } - this = n->meta; - n->meta = NULL; + this = n; while (this != NULL) { next = this->next; if (this->type == NM_TYPE_STRING) { - free ((char *)this->value_string); - this->value_string = NULL; + free ((char *)this->nm_value.nm_string); + this->nm_value.nm_string = NULL; } sfree (this); @@ -1081,3 +1443,5 @@ int plugin_notification_meta_free (notification_t *n) return (0); } /* int plugin_notification_meta_free */ + +/* vim: set sw=8 ts=8 noet fdm=marker : */