X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fplugin.c;h=1dd6daf33a9963ef18a897fc5e4221308c3ba80e;hb=a00feb12d82ae2f46db99d0336b955f387f7f354;hp=c927522afe14f8940cdc08a1ec1a7015a8f7897e;hpb=d44e16e085418afe43f554cc22fe55c08d948079;p=collectd.git diff --git a/src/plugin.c b/src/plugin.c index c927522a..1dd6daf3 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -30,7 +30,10 @@ #include "common.h" #include "plugin.h" #include "configfile.h" +#include "utils_avltree.h" #include "utils_llist.h" +#include "utils_cache.h" +#include "utils_threshold.h" /* * Private structures @@ -51,8 +54,10 @@ static llist_t *list_init; static llist_t *list_read; static llist_t *list_write; static llist_t *list_shutdown; -static llist_t *list_data_set; static llist_t *list_log; +static llist_t *list_notification; + +static c_avl_tree_t *data_sets; static char *plugindir = NULL; @@ -76,6 +81,7 @@ static const char *plugin_get_dir (void) static int register_callback (llist_t **list, const char *name, void *callback) { llentry_t *le; + char *key; if ((*list == NULL) && ((*list = llist_create ()) == NULL)) @@ -84,9 +90,16 @@ static int register_callback (llist_t **list, const char *name, void *callback) le = llist_search (*list, name); if (le == NULL) { - le = llentry_create (name, callback); + key = strdup (name); + if (key == NULL) + return (-1); + + le = llentry_create (key, callback); if (le == NULL) + { + free (key); return (-1); + } llist_append (*list, le); } @@ -108,6 +121,7 @@ static int plugin_unregister (llist_t *list, const char *name) return (-1); llist_remove (list, e); + free (e->key); llentry_destroy (e); return (0); @@ -118,10 +132,10 @@ static int plugin_unregister (llist_t *list, const char *name) * object, but it will bitch about a shared object not having a * ``module_register'' symbol.. */ -static int plugin_load_file (char *file, modreg_e load) +static int plugin_load_file (char *file) { lt_dlhandle dlh; - void (*reg_handle) (modreg_e mr); + void (*reg_handle) (void); DEBUG ("file = %s", file); @@ -133,11 +147,11 @@ static int plugin_load_file (char *file, modreg_e load) const char *error = lt_dlerror (); ERROR ("lt_dlopen failed: %s", error); - DEBUG ("lt_dlopen failed: %s", error); + fprintf (stderr, "lt_dlopen failed: %s\n", error); return (1); } - if ((reg_handle = (void (*) (modreg_e)) lt_dlsym (dlh, "module_register")) == NULL) + if ((reg_handle = (void (*) (void)) lt_dlsym (dlh, "module_register")) == NULL) { WARNING ("Couldn't find symbol ``module_register'' in ``%s'': %s\n", file, lt_dlerror ()); @@ -145,7 +159,7 @@ static int plugin_load_file (char *file, modreg_e load) return (-1); } - (*reg_handle) (load); + (*reg_handle) (); return (0); } @@ -186,13 +200,15 @@ static void *plugin_read_thread (void *args) 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; NOTICE ("read-function of plugin `%s' " - "failed. Will syspend it for %i " + "failed. Will suspend it for %i " "seconds.", le->key, rf->wait_left); } else @@ -291,7 +307,7 @@ void plugin_set_dir (const char *dir) } #define BUFSIZE 512 -int plugin_load (const char *type, modreg_e mr) +int plugin_load (const char *type) { DIR *dh; const char *dir; @@ -348,12 +364,16 @@ int plugin_load (const char *type, modreg_e mr) continue; } - if (plugin_load_file (filename, mr) == 0) + if (plugin_load_file (filename) == 0) { /* success */ ret = 0; break; } + else + { + fprintf (stderr, "Unable to load plugin %s.\n", type); + } } closedir (dh); @@ -372,6 +392,12 @@ int plugin_register_config (const char *name, return (0); } /* int plugin_register_config */ +int plugin_register_complex_config (const char *type, + int (*callback) (oconfig_item_t *)) +{ + return (cf_register_complex (type, callback)); +} /* int plugin_register_complex_config */ + int plugin_register_init (const char *name, int (*callback) (void)) { @@ -415,7 +441,39 @@ int plugin_register_shutdown (char *name, int plugin_register_data_set (const data_set_t *ds) { - return (register_callback (&list_data_set, ds->type, (void *) ds)); + data_set_t *ds_copy; + int i; + + if ((data_sets != NULL) + && (c_avl_get (data_sets, ds->type, NULL) == 0)) + { + NOTICE ("Replacing DS `%s' with another version.", ds->type); + plugin_unregister_data_set (ds->type); + } + else if (data_sets == NULL) + { + data_sets = c_avl_create ((int (*) (const void *, const void *)) strcmp); + if (data_sets == NULL) + return (-1); + } + + ds_copy = (data_set_t *) malloc (sizeof (data_set_t)); + if (ds_copy == NULL) + return (-1); + memcpy(ds_copy, ds, sizeof (data_set_t)); + + ds_copy->ds = (data_source_t *) malloc (sizeof (data_source_t) + * ds->ds_num); + if (ds_copy->ds == NULL) + { + free (ds_copy); + return (-1); + } + + for (i = 0; i < ds->ds_num; i++) + memcpy (ds_copy->ds + i, ds->ds + i, sizeof (data_source_t)); + + return (c_avl_insert (data_sets, (void *) ds_copy->type, (void *) ds_copy)); } /* int plugin_register_data_set */ int plugin_register_log (char *name, @@ -424,12 +482,24 @@ int plugin_register_log (char *name, return (register_callback (&list_log, name, (void *) callback)); } /* int plugin_register_log */ +int plugin_register_notification (const char *name, + int (*callback) (const notification_t *notif)) +{ + return (register_callback (&list_notification, name, (void *) callback)); +} /* int plugin_register_log */ + int plugin_unregister_config (const char *name) { cf_unregister (name); return (0); } /* int plugin_unregister_config */ +int plugin_unregister_complex_config (const char *name) +{ + cf_unregister_complex (name); + return (0); +} /* int plugin_unregister_complex_config */ + int plugin_unregister_init (const char *name) { return (plugin_unregister (list_init, name)); @@ -446,6 +516,7 @@ int plugin_unregister_read (const char *name) llist_remove (list_read, e); free (e->value); + free (e->key); llentry_destroy (e); return (0); @@ -463,14 +534,30 @@ int plugin_unregister_shutdown (const char *name) int plugin_unregister_data_set (const char *name) { - return (plugin_unregister (list_data_set, name)); -} + data_set_t *ds; + + if (data_sets == NULL) + return (-1); + + if (c_avl_remove (data_sets, name, NULL, (void *) &ds) != 0) + return (-1); + + sfree (ds->ds); + sfree (ds); + + return (0); +} /* int plugin_unregister_data_set */ int plugin_unregister_log (const char *name) { return (plugin_unregister (list_log, name)); } +int plugin_unregister_notification (const char *name) +{ + return (plugin_unregister (list_notification, name)); +} + void plugin_init_all (void) { int (*callback) (void); @@ -487,6 +574,9 @@ void plugin_init_all (void) start_threads ((num > 0) ? num : 5); } + /* Init the value cache */ + uc_init (); + if (list_init == NULL) return; @@ -500,8 +590,9 @@ void plugin_init_all (void) { ERROR ("Initialization of plugin `%s' " "failed with status %i. " - "Plugin will be unloaded. TODO!", + "Plugin will be unloaded.", le->key, status); + /* FIXME: Unload _all_ functions */ plugin_unregister_read (le->key); } @@ -509,11 +600,13 @@ void plugin_init_all (void) } } /* void plugin_init_all */ -void plugin_read_all (const int *loop) +void plugin_read_all (void) { llentry_t *le; read_func_t *rf; + uc_check_timeout (); + if (list_read == NULL) return; @@ -560,37 +653,62 @@ void plugin_shutdown_all (void) while (le != NULL) { callback = (int (*) (void)) le->value; - (*callback) (); + /* Advance the pointer before calling the callback allows + * shutdown functions to unregister themselves. If done the + * other way around the memory `le' points to will be freed + * after callback returns. */ le = le->next; + + (*callback) (); } } /* void plugin_shutdown_all */ -int plugin_dispatch_values (const char *name, const value_list_t *vl) +int plugin_dispatch_values (const char *name, value_list_t *vl) { int (*callback) (const data_set_t *, const value_list_t *); data_set_t *ds; llentry_t *le; - if (list_write == NULL) + if ((list_write == NULL) || (data_sets == NULL)) return (-1); - le = llist_search (list_data_set, name); - if (le == NULL) + if (c_avl_get (data_sets, name, (void *) &ds) != 0) { DEBUG ("No such dataset registered: %s", name); return (-1); } - ds = (data_set_t *) le->value; - - DEBUG ("plugin: plugin_dispatch_values: time = %u; host = %s; " - "plugin = %s; plugin_instance = %s; type = %s; " - "type_instance = %s;", - (unsigned int) vl->time, vl->host, + DEBUG ("plugin: plugin_dispatch_values: time = %u; interval = %i; " + "host = %s; " + "plugin = %s; plugin_instance = %s; " + "type = %s; type_instance = %s;", + (unsigned int) vl->time, vl->interval, + vl->host, vl->plugin, vl->plugin_instance, ds->type, vl->type_instance); +#if COLLECT_DEBUG + assert (ds->ds_num == vl->values_len); +#else + if (ds->ds_num != vl->values_len) + { + ERROR ("plugin: ds->type = %s: (ds->ds_num = %i) != " + "(vl->values_len = %i)", + ds->type, ds->ds_num, vl->values_len); + return (-1); + } +#endif + + escape_slashes (vl->host, sizeof (vl->host)); + escape_slashes (vl->plugin, sizeof (vl->plugin)); + escape_slashes (vl->plugin_instance, sizeof (vl->plugin_instance)); + escape_slashes (vl->type_instance, sizeof (vl->type_instance)); + + /* Update the value cache */ + uc_update (ds, vl); + ut_check_threshold (ds, vl); + le = llist_head (list_write); while (le != NULL) { @@ -601,7 +719,34 @@ int plugin_dispatch_values (const char *name, const value_list_t *vl) } return (0); -} +} /* int plugin_dispatch_values */ + +int plugin_dispatch_notification (const notification_t *notif) +{ + int (*callback) (const notification_t *); + llentry_t *le; + /* Possible TODO: Add flap detection here */ + + DEBUG ("plugin_dispatch_notification: severity = %i; message = %s; " + "time = %u; host = %s;", + notif->severity, notif->message, + (unsigned int) notif->time, notif->host); + + /* Nobody cares for notifications */ + if (list_notification == NULL) + return (-1); + + le = llist_head (list_notification); + while (le != NULL) + { + callback = (int (*) (const notification_t *)) le->value; + (*callback) (notif); + + le = le->next; + } + + return (0); +} /* int plugin_dispatch_notification */ void plugin_log (int level, const char *format, ...) { @@ -634,66 +779,15 @@ void plugin_log (int level, const char *format, ...) } } /* void plugin_log */ -void plugin_complain (int level, complain_t *c, const char *format, ...) -{ - char message[512]; - va_list ap; - - if (c->delay > 0) - { - c->delay--; - return; - } - - if (c->interval < interval_g) - c->interval = interval_g; - else - c->interval *= 2; - - if (c->interval > 86400) - c->interval = 86400; - - c->delay = c->interval / interval_g; - - va_start (ap, format); - vsnprintf (message, 512, format, ap); - message[511] = '\0'; - va_end (ap); - - plugin_log (level, message); -} - -void plugin_relief (int level, complain_t *c, const char *format, ...) -{ - char message[512]; - va_list ap; - - if (c->interval == 0) - return; - - c->interval = 0; - - va_start (ap, format); - vsnprintf (message, 512, format, ap); - message[511] = '\0'; - va_end (ap); - - plugin_log (level, message); -} - const data_set_t *plugin_get_ds (const char *name) { data_set_t *ds; - llentry_t *le; - le = llist_search (list_data_set, name); - if (le == NULL) + if (c_avl_get (data_sets, name, (void *) &ds) != 0) { DEBUG ("No such dataset registered: %s", name); return (NULL); } - ds = (data_set_t *) le->value; - return (ds); } /* data_set_t *plugin_get_ds */