X-Git-Url: https://git.tokkee.org/?p=collectd.git;a=blobdiff_plain;f=src%2Fplugin.c;fp=src%2Fplugin.c;h=2ad866e3bb2fbcb44012ff997b62932563bdd349;hp=d3767d1283b9678bec65e8665d5feb7b8c64bef7;hb=10b92353ea2ccf66eabad273799c36225d2efc3f;hpb=a320c4a23fee0e900a7cd2310c771b8dbd2a2d82 diff --git a/src/plugin.c b/src/plugin.c index d3767d12..2ad866e3 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -61,7 +61,7 @@ struct read_func_s #define rf_ctx rf_super.cf_ctx callback_func_t rf_super; char rf_group[DATA_MAX_NAME_LEN]; - char rf_name[DATA_MAX_NAME_LEN]; + char *rf_name; int rf_type; cdtime_t rf_interval; cdtime_t rf_effective_interval; @@ -81,6 +81,8 @@ struct write_queue_s /* * Private variables */ +static c_avl_tree_t *plugins_loaded = NULL; + static llist_t *list_init; static llist_t *list_write; static llist_t *list_flush; @@ -437,6 +439,7 @@ static void *plugin_read_thread (void __attribute__((unused)) *args) { DEBUG ("plugin_read_thread: Destroying the `%s' " "callback.", rf->rf_name); + sfree (rf->rf_name); destroy_callback ((callback_func_t *) rf); rf = NULL; continue; @@ -830,8 +833,52 @@ void plugin_set_dir (const char *dir) } } +static _Bool plugin_is_loaded (char const *name) +{ + int status; + + if (plugins_loaded == NULL) + plugins_loaded = c_avl_create ((void *) strcasecmp); + assert (plugins_loaded != NULL); + + status = c_avl_get (plugins_loaded, name, /* ret_value = */ NULL); + return (status == 0); +} + +static int plugin_mark_loaded (char const *name) +{ + char *name_copy; + int status; + + name_copy = strdup (name); + if (name_copy == NULL) + return (ENOMEM); + + status = c_avl_insert (plugins_loaded, + /* key = */ name_copy, /* value = */ NULL); + return (status); +} + +static void plugin_free_loaded () +{ + void *key; + void *value; + + if (plugins_loaded == NULL) + return; + + while (c_avl_pick (plugins_loaded, &key, &value) == 0) + { + sfree (key); + assert (value == NULL); + } + + c_avl_destroy (plugins_loaded); + plugins_loaded = NULL; +} + #define BUFSIZE 512 -int plugin_load (const char *type, uint32_t flags) +int plugin_load (char const *plugin_name, uint32_t flags) { DIR *dh; const char *dir; @@ -843,15 +890,38 @@ int plugin_load (const char *type, uint32_t flags) struct dirent *de; int status; + if (plugin_name == NULL) + return (EINVAL); + + /* Check if plugin is already loaded and don't do anything in this + * case. */ + if (plugin_is_loaded (plugin_name)) + return (0); + dir = plugin_get_dir (); ret = 1; + /* + * XXX: Magic at work: + * + * Some of the language bindings, for example the Python and Perl + * plugins, need to be able to export symbols to the scripts they run. + * For this to happen, the "Globals" flag needs to be set. + * Unfortunately, this technical detail is hard to explain to the + * average user and she shouldn't have to worry about this, ideally. + * So in order to save everyone's sanity use a different default for a + * handful of special plugins. --octo + */ + if ((strcasecmp ("perl", plugin_name) == 0) + || (strcasecmp ("python", plugin_name) == 0)) + flags |= PLUGIN_FLAGS_GLOBAL; + /* `cpu' should not match `cpufreq'. To solve this we add `.so' to the * type when matching the filename */ - status = ssnprintf (typename, sizeof (typename), "%s.so", type); + status = ssnprintf (typename, sizeof (typename), "%s.so", plugin_name); if ((status < 0) || ((size_t) status >= sizeof (typename))) { - WARNING ("plugin_load: Filename too long: \"%s.so\"", type); + WARNING ("plugin_load: Filename too long: \"%s.so\"", plugin_name); return (-1); } typename_len = strlen (typename); @@ -898,13 +968,14 @@ int plugin_load (const char *type, uint32_t flags) if (status == 0) { /* success */ + plugin_mark_loaded (plugin_name); ret = 0; break; } else { ERROR ("plugin_load: Load plugin \"%s\" failed with " - "status %i.", type, status); + "status %i.", plugin_name, status); } } @@ -912,7 +983,7 @@ int plugin_load (const char *type, uint32_t flags) if (filename[0] == 0) ERROR ("plugin_load: Could not find plugin \"%s\" in %s", - type, dir); + plugin_name, dir); return (ret); } @@ -1048,7 +1119,7 @@ int plugin_register_read (const char *name, rf->rf_udata.free_func = NULL; rf->rf_ctx = plugin_get_ctx (); rf->rf_group[0] = '\0'; - sstrncpy (rf->rf_name, name, sizeof (rf->rf_name)); + rf->rf_name = strdup (name); rf->rf_type = RF_SIMPLE; rf->rf_interval = plugin_get_interval (); @@ -1080,7 +1151,7 @@ int plugin_register_complex_read (const char *group, const char *name, sstrncpy (rf->rf_group, group, sizeof (rf->rf_group)); else rf->rf_group[0] = '\0'; - sstrncpy (rf->rf_name, name, sizeof (rf->rf_name)); + rf->rf_name = strdup (name); rf->rf_type = RF_COMPLEX; if (interval != NULL) rf->rf_interval = TIMESPEC_TO_CDTIME_T (interval); @@ -1679,6 +1750,7 @@ void plugin_shutdown_all (void) destroy_all_callbacks (&list_shutdown); destroy_all_callbacks (&list_log); + plugin_free_loaded (); plugin_free_data_sets (); } /* void plugin_shutdown_all */