X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Fcore%2Fplugin.c;h=a3aba99ed40b70b05cb91be314c7ac434eeb58a6;hp=5fdaca0db885b9ba3c0870ac301cd13c17017602;hb=43d4ef45a3f0ef8c04f9fb9426be8ee2cf25f68a;hpb=fa5c130fbd0c75f3c47f1b28feb8d76a4791a93e diff --git a/src/core/plugin.c b/src/core/plugin.c index 5fdaca0..a3aba99 100644 --- a/src/core/plugin.c +++ b/src/core/plugin.c @@ -27,9 +27,10 @@ #include "sysdb.h" #include "core/plugin.h" -#include "core/error.h" #include "core/time.h" +#include "utils/error.h" #include "utils/llist.h" +#include "utils/strbuf.h" #include @@ -50,6 +51,10 @@ */ struct sdb_plugin_info { + char *plugin_name; + char *filename; + + /* public attributes */ char *name; char *description; @@ -59,24 +64,37 @@ struct sdb_plugin_info { int version; int plugin_version; }; -#define SDB_PLUGIN_INFO_INIT { "no name set", "no description set", \ - /* copyright */ "", /* license */ "", \ +#define SDB_PLUGIN_INFO_INIT { \ + /* plugin_name */ NULL, /* filename */ NULL, \ + /* name */ NULL, /* desc */ NULL, \ + /* copyright */ NULL, /* license */ NULL, \ /* version */ -1, /* plugin_version */ -1 } +#define INFO_GET(i, attr) \ + ((i)->attr ? (i)->attr : #attr" not set") + +typedef struct { + sdb_object_t super; + sdb_plugin_ctx_t public; + + sdb_plugin_info_t info; +} ctx_t; +#define CTX_INIT { SDB_OBJECT_INIT, \ + SDB_PLUGIN_CTX_INIT, SDB_PLUGIN_INFO_INIT } + +#define CTX(obj) ((ctx_t *)(obj)) typedef struct { sdb_object_t super; - char cb_name[64]; void *cb_callback; sdb_object_t *cb_user_data; - sdb_plugin_ctx_t cb_ctx; + ctx_t *cb_ctx; } sdb_plugin_cb_t; -#define SDB_PLUGIN_CB_INIT { SDB_OBJECT_INIT, /* name = */ "", \ +#define SDB_PLUGIN_CB_INIT { SDB_OBJECT_INIT, \ /* callback = */ NULL, /* user_data = */ NULL, \ SDB_PLUGIN_CTX_INIT } typedef struct { sdb_plugin_cb_t super; -#define ccb_name super.cb_name #define ccb_callback super.cb_callback #define ccb_user_data super.cb_user_data #define ccb_ctx super.cb_ctx @@ -85,73 +103,70 @@ typedef struct { } sdb_plugin_collector_cb_t; #define SDB_PLUGIN_CB(obj) ((sdb_plugin_cb_t *)(obj)) +#define SDB_CONST_PLUGIN_CB(obj) ((const sdb_plugin_cb_t *)(obj)) #define SDB_PLUGIN_CCB(obj) ((sdb_plugin_collector_cb_t *)(obj)) +#define SDB_CONST_PLUGIN_CCB(obj) ((const sdb_plugin_collector_cb_t *)(obj)) /* * private variables */ -static sdb_plugin_ctx_t plugin_default_ctx = SDB_PLUGIN_CTX_INIT; +static sdb_plugin_ctx_t plugin_default_ctx = SDB_PLUGIN_CTX_INIT; +static sdb_plugin_info_t plugin_default_info = SDB_PLUGIN_INFO_INIT; + +static pthread_key_t plugin_ctx_key; +static _Bool plugin_ctx_key_initialized = 0; -static pthread_key_t plugin_ctx_key; -static _Bool plugin_ctx_key_initialized = 0; +/* a list of the plugin contexts of all registered plugins */ +static sdb_llist_t *all_plugins = NULL; static sdb_llist_t *config_list = NULL; static sdb_llist_t *init_list = NULL; static sdb_llist_t *collector_list = NULL; +static sdb_llist_t *cname_list = NULL; static sdb_llist_t *shutdown_list = NULL; +static sdb_llist_t *log_list = NULL; /* * private helper functions */ static void -sdb_plugin_ctx_destructor(void *ctx) +plugin_info_clear(sdb_plugin_info_t *info) { - if (! ctx) + sdb_plugin_info_t empty_info = SDB_PLUGIN_INFO_INIT; + if (! info) return; - free(ctx); -} /* sdb_plugin_ctx_destructor */ + + if (info->plugin_name) + free(info->plugin_name); + if (info->filename) + free(info->filename); + + if (info->name) + free(info->name); + if (info->description) + free(info->description); + if (info->copyright) + free(info->copyright); + if (info->license) + free(info->license); + + *info = empty_info; +} /* plugin_info_clear */ static void -sdb_plugin_ctx_init(void) +ctx_key_init(void) { if (plugin_ctx_key_initialized) return; - pthread_key_create(&plugin_ctx_key, sdb_plugin_ctx_destructor); + pthread_key_create(&plugin_ctx_key, /* destructor */ NULL); plugin_ctx_key_initialized = 1; -} /* sdb_plugin_ctx_init */ - -static sdb_plugin_ctx_t * -sdb_plugin_ctx_create(void) -{ - sdb_plugin_ctx_t *ctx; - - ctx = malloc(sizeof(*ctx)); - if (! ctx) - return NULL; - - *ctx = plugin_default_ctx; - - if (! plugin_ctx_key_initialized) - sdb_plugin_ctx_init(); - pthread_setspecific(plugin_ctx_key, ctx); - return ctx; -} /* sdb_plugin_ctx_create */ - -static int -sdb_plugin_cmp_name(const sdb_object_t *a, const sdb_object_t *b) -{ - const sdb_plugin_cb_t *cb1 = (const sdb_plugin_cb_t *)a; - const sdb_plugin_cb_t *cb2 = (const sdb_plugin_cb_t *)b; - - assert(cb1 && cb2); - return strcasecmp(cb1->cb_name, cb2->cb_name); -} /* sdb_plugin_cmp_name */ +} /* ctx_key_init */ static int -sdb_plugin_cmp_next_update(const sdb_object_t *a, const sdb_object_t *b) +plugin_cmp_next_update(const sdb_object_t *a, const sdb_object_t *b) { const sdb_plugin_collector_cb_t *ccb1 = (const sdb_plugin_collector_cb_t *)a; @@ -163,68 +178,175 @@ sdb_plugin_cmp_next_update(const sdb_object_t *a, const sdb_object_t *b) return (ccb1->ccb_next_update > ccb2->ccb_next_update) ? 1 : (ccb1->ccb_next_update < ccb2->ccb_next_update) ? -1 : 0; -} /* sdb_plugin_cmp_next_update */ +} /* plugin_cmp_next_update */ -static sdb_plugin_cb_t * -sdb_plugin_find_by_name(sdb_llist_t *list, const char *name) +static int +plugin_lookup_by_name(const sdb_object_t *obj, const void *id) { - sdb_plugin_cb_t tmp = SDB_PLUGIN_CB_INIT; + const sdb_plugin_cb_t *cb = SDB_CONST_PLUGIN_CB(obj); + const char *name = id; - sdb_object_t *obj; - assert(name); + assert(cb && id && cb->cb_ctx); + if (!strcasecmp(cb->cb_ctx->info.plugin_name, name)) + return 0; + return 1; +} /* plugin_lookup_by_name */ - if (! list) - return NULL; +static void +plugin_unregister_by_name(const char *plugin_name) +{ + size_t i; + + struct { + const char *type; + sdb_llist_t *list; + } all_lists[] = { + { "config", config_list }, + { "init", init_list }, + { "collector", collector_list }, + { "cname", cname_list }, + { "shutdown", shutdown_list }, + { "log", log_list }, + }; + + for (i = 0; i < SDB_STATIC_ARRAY_LEN(all_lists); ++i) { + const char *type = all_lists[i].type; + sdb_llist_t *list = all_lists[i].list; + + while (1) { + sdb_object_t *obj = sdb_llist_remove(list, + plugin_lookup_by_name, plugin_name); + sdb_plugin_cb_t *cb = SDB_PLUGIN_CB(obj); + + if (! obj) + break; + + sdb_log(SDB_LOG_INFO, "core: Unregistering " + "%s callback '%s' (module %s)", type, obj->name, + cb->cb_ctx->info.plugin_name); + sdb_object_deref(obj); + } + } +} /* plugin_unregister_by_name */ - snprintf(tmp.cb_name, sizeof(tmp.cb_name), "%s", name); - tmp.cb_name[sizeof(tmp.cb_name) - 1] = '\0'; - obj = sdb_llist_search(list, SDB_OBJ(&tmp), sdb_plugin_cmp_name); - if (! obj) +/* + * private types + */ + +static int +ctx_init(sdb_object_t *obj, va_list __attribute__((unused)) ap) +{ + ctx_t *ctx = CTX(obj); + + assert(ctx); + + ctx->public = plugin_default_ctx; + ctx->info = plugin_default_info; + return 0; +} /* ctx_init */ + +static void +ctx_destroy(sdb_object_t *obj) +{ + ctx_t *ctx = CTX(obj); + plugin_info_clear(&ctx->info); +} /* ctx_destroy */ + +static sdb_type_t ctx_type = { + sizeof(ctx_t), + + ctx_init, + ctx_destroy +}; + +static ctx_t * +ctx_create(const char *name) +{ + ctx_t *ctx; + + ctx = CTX(sdb_object_create(name, ctx_type)); + if (! ctx) return NULL; - return SDB_PLUGIN_CB(obj); -} /* sdb_plugin_find_by_name */ + + if (! plugin_ctx_key_initialized) + ctx_key_init(); + pthread_setspecific(plugin_ctx_key, ctx); + return ctx; +} /* ctx_create */ + +static ctx_t * +ctx_get(void) +{ + if (! plugin_ctx_key_initialized) + ctx_key_init(); + return pthread_getspecific(plugin_ctx_key); +} /* ctx_get */ + +static ctx_t * +ctx_set(ctx_t *new) +{ + ctx_t *old; + + if (! plugin_ctx_key_initialized) + ctx_key_init(); + + old = pthread_getspecific(plugin_ctx_key); + pthread_setspecific(plugin_ctx_key, new); + return old; +} /* ctx_set */ static int -sdb_plugin_cb_init(sdb_object_t *obj, va_list ap) +plugin_cb_init(sdb_object_t *obj, va_list ap) { sdb_llist_t **list = va_arg(ap, sdb_llist_t **); - const char *type = va_arg(ap, const char *); - const char *name = va_arg(ap, const char *); - void *callback = va_arg(ap, void *); + const char *type = va_arg(ap, const char *); + void *callback = va_arg(ap, void *); sdb_object_t *ud = va_arg(ap, sdb_object_t *); assert(list); assert(type); assert(obj); - if (sdb_plugin_find_by_name(*list, name)) { - sdb_log(SDB_LOG_WARNING, "plugin: %s callback '%s' " + if (sdb_llist_search_by_name(*list, obj->name)) { + sdb_log(SDB_LOG_WARNING, "core: %s callback '%s' " "has already been registered. Ignoring newly " - "registered version.", type, name); + "registered version.", type, obj->name); return -1; } - snprintf(SDB_PLUGIN_CB(obj)->cb_name, - sizeof(SDB_PLUGIN_CB(obj)->cb_name), - "%s", name); - SDB_PLUGIN_CB(obj)->cb_name[sizeof(SDB_PLUGIN_CB(obj)->cb_name) - 1] = '\0'; SDB_PLUGIN_CB(obj)->cb_callback = callback; - SDB_PLUGIN_CB(obj)->cb_ctx = sdb_plugin_get_ctx(); + SDB_PLUGIN_CB(obj)->cb_ctx = ctx_get(); + sdb_object_ref(SDB_OBJ(SDB_PLUGIN_CB(obj)->cb_ctx)); sdb_object_ref(ud); SDB_PLUGIN_CB(obj)->cb_user_data = ud; return 0; -} /* sdb_plugin_cb_init */ +} /* plugin_cb_init */ static void -sdb_plugin_cb_destroy(sdb_object_t *obj) +plugin_cb_destroy(sdb_object_t *obj) { assert(obj); sdb_object_deref(SDB_PLUGIN_CB(obj)->cb_user_data); -} /* sdb_plugin_cb_destroy */ + sdb_object_deref(SDB_OBJ(SDB_PLUGIN_CB(obj)->cb_ctx)); +} /* plugin_cb_destroy */ + +static sdb_type_t sdb_plugin_cb_type = { + sizeof(sdb_plugin_cb_t), + + plugin_cb_init, + plugin_cb_destroy +}; + +static sdb_type_t sdb_plugin_collector_cb_type = { + sizeof(sdb_plugin_collector_cb_t), + + plugin_cb_init, + plugin_cb_destroy +}; static int -sdb_plugin_add_callback(sdb_llist_t **list, const char *type, +plugin_add_callback(sdb_llist_t **list, const char *type, const char *name, void *callback, sdb_object_t *user_data) { sdb_object_t *obj; @@ -239,8 +361,8 @@ sdb_plugin_add_callback(sdb_llist_t **list, const char *type, if (! *list) return -1; - obj = sdb_object_create(sizeof(sdb_plugin_cb_t), sdb_plugin_cb_init, - sdb_plugin_cb_destroy, list, type, name, callback, user_data); + obj = sdb_object_create(name, sdb_plugin_cb_type, + list, type, callback, user_data); if (! obj) return -1; @@ -252,29 +374,28 @@ sdb_plugin_add_callback(sdb_llist_t **list, const char *type, /* pass control to the list */ sdb_object_deref(obj); - sdb_log(SDB_LOG_INFO, "plugin: Registered %s callback '%s'.", + sdb_log(SDB_LOG_INFO, "core: Registered %s callback '%s'.", type, name); return 0; -} /* sdb_plugin_add_callback */ +} /* plugin_add_callback */ /* * public API */ int -sdb_plugin_load(const char *name) +sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx) { - char real_name[strlen(name) > 0 ? strlen(name) : 1]; + char real_name[name ? strlen(name) + 1 : 1]; const char *name_ptr; char *tmp; char filename[1024]; + ctx_t *ctx; lt_dlhandle lh; int (*mod_init)(sdb_plugin_info_t *); - sdb_plugin_info_t plugin_info = SDB_PLUGIN_INFO_INIT; - int status; if ((! name) || (! *name)) @@ -296,7 +417,7 @@ sdb_plugin_load(const char *name) if (access(filename, R_OK)) { char errbuf[1024]; - sdb_log(SDB_LOG_ERR, "plugin: Failed to load plugin '%s' (%s): %s", + sdb_log(SDB_LOG_ERR, "core: Failed to load plugin '%s' (%s): %s", name, filename, sdb_strerror(errno, errbuf, sizeof(errbuf))); return -1; } @@ -306,39 +427,77 @@ sdb_plugin_load(const char *name) lh = lt_dlopen(filename); if (! lh) { - sdb_log(SDB_LOG_ERR, "plugin: Failed to load plugin '%s': %s" + sdb_log(SDB_LOG_ERR, "core: Failed to load plugin '%s': %s" "The most common cause for this problem are missing " "dependencies.\n", name, lt_dlerror()); return -1; } + if (ctx_get()) + sdb_log(SDB_LOG_WARNING, "core: Discarding old plugin context"); + + ctx = ctx_create(real_name); + if (! ctx) { + sdb_log(SDB_LOG_ERR, "core: Failed to initialize plugin context"); + return -1; + } + + ctx->info.plugin_name = strdup(name); + ctx->info.filename = strdup(filename); + + if (plugin_ctx) + ctx->public = *plugin_ctx; + mod_init = (int (*)(sdb_plugin_info_t *))lt_dlsym(lh, "sdb_module_init"); if (! mod_init) { - sdb_log(SDB_LOG_ERR, "plugin: Failed to load plugin '%s': " + sdb_log(SDB_LOG_ERR, "core: Failed to load plugin '%s': " "could not find symbol 'sdb_module_init'", name); + sdb_object_deref(SDB_OBJ(ctx)); return -1; } - status = mod_init(&plugin_info); + status = mod_init(&ctx->info); if (status) { - sdb_log(SDB_LOG_ERR, "plugin: Failed to initialize " - "plugin '%s'", name); + sdb_log(SDB_LOG_ERR, "core: Failed to initialize " + "module '%s'", name); + plugin_unregister_by_name(ctx->info.plugin_name); + sdb_object_deref(SDB_OBJ(ctx)); return -1; } /* compare minor version */ - if ((plugin_info.version < 0) - || ((int)(plugin_info.version / 100) != (int)(SDB_VERSION / 100))) - sdb_log(SDB_LOG_WARNING, "plugin: WARNING: version of " + if ((ctx->info.version < 0) + || ((int)(ctx->info.version / 100) != (int)(SDB_VERSION / 100))) + sdb_log(SDB_LOG_WARNING, "core: WARNING: version of " "plugin '%s' (%i.%i.%i) does not match our version " "(%i.%i.%i); this might cause problems", - name, SDB_VERSION_DECODE(plugin_info.version), + name, SDB_VERSION_DECODE(ctx->info.version), SDB_VERSION_DECODE(SDB_VERSION)); - sdb_log(SDB_LOG_INFO, "plugin: Successfully loaded " - "plugin '%s' v%i (%s)\n\t%s", - plugin_info.name, plugin_info.plugin_version, - plugin_info.description, plugin_info.copyright); + if (! all_plugins) { + if (! (all_plugins = sdb_llist_create())) { + sdb_log(SDB_LOG_ERR, "core: Failed to load plugin '%s': " + "internal error while creating linked list", name); + plugin_unregister_by_name(ctx->info.plugin_name); + sdb_object_deref(SDB_OBJ(ctx)); + return -1; + } + } + + sdb_llist_append(all_plugins, SDB_OBJ(ctx)); + + sdb_log(SDB_LOG_INFO, "core: Successfully loaded " + "plugin '%s' v%i (%s)\n\t%s\n\tLicense: %s", + INFO_GET(&ctx->info, name), ctx->info.plugin_version, + INFO_GET(&ctx->info, description), + INFO_GET(&ctx->info, copyright), + INFO_GET(&ctx->info, license)); + + /* any registered callbacks took ownership of the context */ + sdb_object_deref(SDB_OBJ(ctx)); + + /* reset */ + ctx_set(NULL); return 0; } /* sdb_plugin_load */ @@ -356,25 +515,38 @@ sdb_plugin_set_info(sdb_plugin_info_t *info, int type, ...) case SDB_PLUGIN_INFO_NAME: { char *name = va_arg(ap, char *); - info->name = name; + if (name) { + if (info->name) + free(info->name); + info->name = strdup(name); + } } break; case SDB_PLUGIN_INFO_DESC: { char *desc = va_arg(ap, char *); - info->description = desc; + if (desc) { + if (info->description) + free(info->description); + info->description = strdup(desc); + } } break; case SDB_PLUGIN_INFO_COPYRIGHT: { char *copyright = va_arg(ap, char *); - info->copyright = copyright; + if (copyright) + info->copyright = strdup(copyright); } break; case SDB_PLUGIN_INFO_LICENSE: { char *license = va_arg(ap, char *); - info->license = license; + if (license) { + if (info->license) + free(info->license); + info->license = strdup(license); + } } break; case SDB_PLUGIN_INFO_VERSION: @@ -401,7 +573,7 @@ sdb_plugin_set_info(sdb_plugin_info_t *info, int type, ...) int sdb_plugin_register_config(const char *name, sdb_plugin_config_cb callback) { - return sdb_plugin_add_callback(&config_list, "init", name, + return plugin_add_callback(&config_list, "init", name, callback, NULL); } /* sdb_plugin_register_config */ @@ -409,7 +581,7 @@ int sdb_plugin_register_init(const char *name, sdb_plugin_init_cb callback, sdb_object_t *user_data) { - return sdb_plugin_add_callback(&init_list, "init", name, + return plugin_add_callback(&init_list, "init", name, callback, user_data); } /* sdb_plugin_register_init */ @@ -417,10 +589,26 @@ int sdb_plugin_register_shutdown(const char *name, sdb_plugin_shutdown_cb callback, sdb_object_t *user_data) { - return sdb_plugin_add_callback(&shutdown_list, "shutdown", name, + return plugin_add_callback(&shutdown_list, "shutdown", name, callback, user_data); } /* sdb_plugin_register_shutdown */ +int +sdb_plugin_register_log(const char *name, sdb_plugin_log_cb callback, + sdb_object_t *user_data) +{ + return plugin_add_callback(&log_list, "log", name, callback, + user_data); +} /* sdb_plugin_register_log */ + +int +sdb_plugin_register_cname(const char *name, sdb_plugin_cname_cb callback, + sdb_object_t *user_data) +{ + return plugin_add_callback(&cname_list, "cname", name, callback, + user_data); +} /* sdb_plugin_register_cname */ + int sdb_plugin_register_collector(const char *name, sdb_plugin_collector_cb callback, const sdb_time_t *interval, sdb_object_t *user_data) @@ -435,9 +623,8 @@ sdb_plugin_register_collector(const char *name, sdb_plugin_collector_cb callback if (! collector_list) return -1; - obj = sdb_object_create(sizeof(sdb_plugin_collector_cb_t), - sdb_plugin_cb_init, sdb_plugin_cb_destroy, - &collector_list, "collector", name, callback, user_data); + obj = sdb_object_create(name, sdb_plugin_collector_cb_type, + &collector_list, "collector", callback, user_data); if (! obj) return -1; @@ -454,14 +641,14 @@ sdb_plugin_register_collector(const char *name, sdb_plugin_collector_cb callback if (! (SDB_PLUGIN_CCB(obj)->ccb_next_update = sdb_gettime())) { char errbuf[1024]; - sdb_log(SDB_LOG_ERR, "plugin: Failed to determine current " + sdb_log(SDB_LOG_ERR, "core: Failed to determine current " "time: %s", sdb_strerror(errno, errbuf, sizeof(errbuf))); sdb_object_deref(obj); return -1; } if (sdb_llist_insert_sorted(collector_list, obj, - sdb_plugin_cmp_next_update)) { + plugin_cmp_next_update)) { sdb_object_deref(obj); return -1; } @@ -469,7 +656,7 @@ sdb_plugin_register_collector(const char *name, sdb_plugin_collector_cb callback /* pass control to the list */ sdb_object_deref(obj); - sdb_log(SDB_LOG_INFO, "plugin: Registered collector callback '%s' " + sdb_log(SDB_LOG_INFO, "core: Registered collector callback '%s' " "(interval = %.3fs).", name, SDB_TIME_TO_DOUBLE(SDB_PLUGIN_CCB(obj)->ccb_interval)); return 0; @@ -478,37 +665,33 @@ sdb_plugin_register_collector(const char *name, sdb_plugin_collector_cb callback sdb_plugin_ctx_t sdb_plugin_get_ctx(void) { - sdb_plugin_ctx_t *ctx; + ctx_t *c; - if (! plugin_ctx_key_initialized) - sdb_plugin_ctx_init(); - ctx = pthread_getspecific(plugin_ctx_key); - - if (! ctx) - ctx = sdb_plugin_ctx_create(); - if (! ctx) + c = ctx_get(); + if (! c) { + sdb_plugin_log(SDB_LOG_ERR, "core: Invalid read access to plugin " + "context outside a plugin"); return plugin_default_ctx; - return *ctx; + } + return c->public; } /* sdb_plugin_get_ctx */ -sdb_plugin_ctx_t -sdb_plugin_set_ctx(sdb_plugin_ctx_t ctx) +int +sdb_plugin_set_ctx(sdb_plugin_ctx_t ctx, sdb_plugin_ctx_t *old) { - sdb_plugin_ctx_t *tmp; - sdb_plugin_ctx_t old; - - if (! plugin_ctx_key_initialized) - sdb_plugin_ctx_init(); - tmp = pthread_getspecific(plugin_ctx_key); + ctx_t *c; - if (! tmp) - tmp = sdb_plugin_ctx_create(); - if (! tmp) - return plugin_default_ctx; + c = ctx_get(); + if (! c) { + sdb_plugin_log(SDB_LOG_ERR, "core: Invalid write access to plugin " + "context outside a plugin"); + return -1; + } - old = *tmp; - *tmp = ctx; - return old; + if (old) + *old = c->public; + c->public = ctx; + return 0; } /* sdb_plugin_set_ctx */ int @@ -517,26 +700,30 @@ sdb_plugin_configure(const char *name, oconfig_item_t *ci) sdb_plugin_cb_t *plugin; sdb_plugin_config_cb callback; - sdb_plugin_ctx_t old_ctx; + ctx_t *old_ctx; int status; if ((! name) || (! ci)) return -1; - plugin = sdb_plugin_find_by_name(config_list, name); + plugin = SDB_PLUGIN_CB(sdb_llist_search_by_name(config_list, name)); if (! plugin) { /* XXX: check if any such plugin has been loaded */ - sdb_log(SDB_LOG_ERR, "plugin: Plugin '%s' did not register " - "a config callback.", name); + ctx_t *ctx = CTX(sdb_llist_search_by_name(all_plugins, name)); + if (! ctx) + sdb_log(SDB_LOG_ERR, "core: Plugin '%s' not loaded.", name); + else + sdb_log(SDB_LOG_ERR, "core: Plugin '%s' did not register " + "a config callback.", name); errno = ENOENT; return -1; } - old_ctx = sdb_plugin_set_ctx(plugin->cb_ctx); + old_ctx = ctx_set(plugin->cb_ctx); callback = plugin->cb_callback; status = callback(ci); - sdb_plugin_set_ctx(old_ctx); + ctx_set(old_ctx); return status; } /* sdb_plugin_configure */ @@ -544,31 +731,38 @@ int sdb_plugin_init_all(void) { sdb_llist_iter_t *iter; + int ret = 0; iter = sdb_llist_get_iter(init_list); while (sdb_llist_iter_has_next(iter)) { + sdb_plugin_cb_t *cb; sdb_plugin_init_cb callback; - sdb_plugin_ctx_t old_ctx; + ctx_t *old_ctx; sdb_object_t *obj = sdb_llist_iter_get_next(iter); assert(obj); + cb = SDB_PLUGIN_CB(obj); - callback = SDB_PLUGIN_CB(obj)->cb_callback; + callback = cb->cb_callback; - old_ctx = sdb_plugin_set_ctx(SDB_PLUGIN_CB(obj)->cb_ctx); - if (callback(SDB_PLUGIN_CB(obj)->cb_user_data)) { - /* XXX: unload plugin */ + old_ctx = ctx_set(cb->cb_ctx); + if (callback(cb->cb_user_data)) { + sdb_log(SDB_LOG_ERR, "core: Failed to initialize plugin " + "'%s'. Unregistering all callbacks.", obj->name); + plugin_unregister_by_name(cb->cb_ctx->info.plugin_name); + ++ret; } - sdb_plugin_set_ctx(old_ctx); + ctx_set(old_ctx); } - return 0; + sdb_llist_iter_destroy(iter); + return ret; } /* sdb_plugin_init_all */ int sdb_plugin_collector_loop(sdb_plugin_loop_t *loop) { if (! collector_list) { - sdb_log(SDB_LOG_WARNING, "plugin: No collectors registered. " + sdb_log(SDB_LOG_WARNING, "core: No collectors registered. " "Quiting main loop."); return -1; } @@ -578,7 +772,7 @@ sdb_plugin_collector_loop(sdb_plugin_loop_t *loop) while (loop->do_loop) { sdb_plugin_collector_cb callback; - sdb_plugin_ctx_t old_ctx; + ctx_t *old_ctx; sdb_time_t interval, now; @@ -590,8 +784,9 @@ sdb_plugin_collector_loop(sdb_plugin_loop_t *loop) if (! (now = sdb_gettime())) { char errbuf[1024]; - sdb_log(SDB_LOG_ERR, "plugin: Failed to determine current " - "time: %s", sdb_strerror(errno, errbuf, sizeof(errbuf))); + sdb_log(SDB_LOG_ERR, "core: Failed to determine current " + "time in collector main loop: %s", + sdb_strerror(errno, errbuf, sizeof(errbuf))); now = SDB_PLUGIN_CCB(obj)->ccb_next_update; } @@ -602,7 +797,8 @@ sdb_plugin_collector_loop(sdb_plugin_loop_t *loop) while (loop->do_loop && sdb_sleep(interval, &interval)) { if (errno != EINTR) { char errbuf[1024]; - sdb_log(SDB_LOG_ERR, "plugin: Failed to sleep: %s", + sdb_log(SDB_LOG_ERR, "core: Failed to sleep " + "in collector main loop: %s", sdb_strerror(errno, errbuf, sizeof(errbuf))); return -1; } @@ -613,19 +809,19 @@ sdb_plugin_collector_loop(sdb_plugin_loop_t *loop) return 0; } - old_ctx = sdb_plugin_set_ctx(SDB_PLUGIN_CCB(obj)->ccb_ctx); + old_ctx = ctx_set(SDB_PLUGIN_CCB(obj)->ccb_ctx); if (callback(SDB_PLUGIN_CCB(obj)->ccb_user_data)) { /* XXX */ } - sdb_plugin_set_ctx(old_ctx); + ctx_set(old_ctx); interval = SDB_PLUGIN_CCB(obj)->ccb_interval; if (! interval) interval = loop->default_interval; if (! interval) { - sdb_log(SDB_LOG_WARNING, "plugin: No interval configured " + sdb_log(SDB_LOG_WARNING, "core: No interval configured " "for plugin '%s'; skipping any further " - "iterations.", SDB_PLUGIN_CCB(obj)->ccb_name); + "iterations.", obj->name); sdb_object_deref(obj); continue; } @@ -634,24 +830,25 @@ sdb_plugin_collector_loop(sdb_plugin_loop_t *loop) if (! (now = sdb_gettime())) { char errbuf[1024]; - sdb_log(SDB_LOG_ERR, "plugin: Failed to determine current " - "time: %s", sdb_strerror(errno, errbuf, sizeof(errbuf))); + sdb_log(SDB_LOG_ERR, "core: Failed to determine current " + "time in collector main loop: %s", + sdb_strerror(errno, errbuf, sizeof(errbuf))); now = SDB_PLUGIN_CCB(obj)->ccb_next_update; } if (now > SDB_PLUGIN_CCB(obj)->ccb_next_update) { - sdb_log(SDB_LOG_WARNING, "plugin: Plugin '%s' took too " + sdb_log(SDB_LOG_WARNING, "core: Plugin '%s' took too " "long; skipping iterations to keep up.", - SDB_PLUGIN_CCB(obj)->ccb_name); + obj->name); SDB_PLUGIN_CCB(obj)->ccb_next_update = now; } if (sdb_llist_insert_sorted(collector_list, obj, - sdb_plugin_cmp_next_update)) { - sdb_log(SDB_LOG_ERR, "plugin: Failed to re-insert " + plugin_cmp_next_update)) { + sdb_log(SDB_LOG_ERR, "core: Failed to re-insert " "plugin '%s' into collector list. Unable to further " "use the plugin.", - SDB_PLUGIN_CCB(obj)->ccb_name); + obj->name); sdb_object_deref(obj); return -1; } @@ -662,5 +859,106 @@ sdb_plugin_collector_loop(sdb_plugin_loop_t *loop) return 0; } /* sdb_plugin_read_loop */ +char * +sdb_plugin_cname(char *hostname) +{ + sdb_llist_iter_t *iter; + + if (! hostname) + return NULL; + + if (! cname_list) + return hostname; + + iter = sdb_llist_get_iter(cname_list); + while (sdb_llist_iter_has_next(iter)) { + sdb_plugin_cname_cb callback; + char *cname; + + sdb_object_t *obj = sdb_llist_iter_get_next(iter); + assert(obj); + + callback = SDB_PLUGIN_CB(obj)->cb_callback; + cname = callback(hostname, SDB_PLUGIN_CB(obj)->cb_user_data); + if (cname) { + free(hostname); + hostname = cname; + } + /* else: don't change hostname */ + } + sdb_llist_iter_destroy(iter); + return hostname; +} /* sdb_plugin_cname */ + +int +sdb_plugin_log(int prio, const char *msg) +{ + sdb_llist_iter_t *iter; + int ret = -1; + + if (! msg) + return 0; + + if (! log_list) + return fprintf(stderr, "[%s] %s\n", SDB_LOG_PRIO_TO_STRING(prio), msg); + + iter = sdb_llist_get_iter(log_list); + while (sdb_llist_iter_has_next(iter)) { + sdb_plugin_log_cb callback; + int tmp; + + sdb_object_t *obj = sdb_llist_iter_get_next(iter); + assert(obj); + + callback = SDB_PLUGIN_CB(obj)->cb_callback; + tmp = callback(prio, msg, SDB_PLUGIN_CB(obj)->cb_user_data); + if (tmp > ret) + ret = tmp; + } + sdb_llist_iter_destroy(iter); + return ret; +} /* sdb_plugin_log */ + +int +sdb_plugin_vlogf(int prio, const char *fmt, va_list ap) +{ + sdb_strbuf_t *buf; + int ret; + + if (! fmt) + return 0; + + buf = sdb_strbuf_create(64); + if (! buf) { + ret = fprintf(stderr, "[%s] ", SDB_LOG_PRIO_TO_STRING(prio)); + ret += vfprintf(stderr, fmt, ap); + return ret; + } + + if (sdb_strbuf_vsprintf(buf, fmt, ap) < 0) { + sdb_strbuf_destroy(buf); + return -1; + } + + ret = sdb_plugin_log(prio, sdb_strbuf_string(buf)); + sdb_strbuf_destroy(buf); + return ret; +} /* sdb_plugin_vlogf */ + +int +sdb_plugin_logf(int prio, const char *fmt, ...) +{ + va_list ap; + int ret; + + if (! fmt) + return 0; + + va_start(ap, fmt); + ret = sdb_plugin_vlogf(prio, fmt, ap); + va_end(ap); + return ret; +} /* sdb_plugin_logf */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */