X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fcore%2Fplugin.c;h=929abaee8467cf4bc7f419c324cdd7c6b46a339f;hb=3970ba2a54fdf360d425452d0d29f6cd3c09915a;hp=45d3940ff2a36b829fd1559f51074d5b6c03c2c0;hpb=fdfe2a68ba1838cdb1c34d3275d129fb217fbd9d;p=sysdb.git diff --git a/src/core/plugin.c b/src/core/plugin.c index 45d3940..929abae 100644 --- a/src/core/plugin.c +++ b/src/core/plugin.c @@ -81,6 +81,7 @@ typedef struct { sdb_plugin_ctx_t public; sdb_plugin_info_t info; + lt_dlhandle handle; /* The usage count differs from the object's ref count * in that it provides higher level information about how @@ -88,7 +89,7 @@ typedef struct { size_t use_cnt; } ctx_t; #define CTX_INIT { SDB_OBJECT_INIT, \ - SDB_PLUGIN_CTX_INIT, SDB_PLUGIN_INFO_INIT, 0 } + SDB_PLUGIN_CTX_INIT, SDB_PLUGIN_INFO_INIT, NULL, 0 } #define CTX(obj) ((ctx_t *)(obj)) @@ -204,6 +205,7 @@ plugin_lookup_by_name(const sdb_object_t *obj, const void *id) static void plugin_unregister_by_name(const char *plugin_name) { + sdb_object_t *obj; size_t i; struct { @@ -223,19 +225,25 @@ plugin_unregister_by_name(const char *plugin_name) 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); + sdb_plugin_cb_t *cb; - if (! obj) + cb = SDB_PLUGIN_CB(sdb_llist_remove(list, + plugin_lookup_by_name, plugin_name)); + if (! cb) break; sdb_log(SDB_LOG_INFO, "core: Unregistering " - "%s callback '%s' (module %s)", type, obj->name, + "%s callback '%s' (module %s)", type, cb->super.name, cb->cb_ctx->info.plugin_name); - sdb_object_deref(obj); + sdb_object_deref(SDB_OBJ(cb)); } } + + obj = sdb_llist_search_by_name(all_plugins, plugin_name); + if (obj->ref_cnt <= 1) + sdb_llist_remove_by_name(all_plugins, plugin_name); + /* else: other callbacks still reference it */ + sdb_object_deref(obj); } /* plugin_unregister_by_name */ /* @@ -251,6 +259,7 @@ ctx_init(sdb_object_t *obj, va_list __attribute__((unused)) ap) ctx->public = plugin_default_ctx; ctx->info = plugin_default_info; + ctx->handle = NULL; ctx->use_cnt = 1; return 0; } /* ctx_init */ @@ -259,6 +268,20 @@ static void ctx_destroy(sdb_object_t *obj) { ctx_t *ctx = CTX(obj); + + if (ctx->handle) { + const char *err; + + sdb_log(SDB_LOG_INFO, "core: Unloading module %s", + ctx->info.plugin_name); + + lt_dlerror(); + lt_dlclose(ctx->handle); + if ((err = lt_dlerror())) + sdb_log(SDB_LOG_WARNING, "core: Failed to unload module %s: %s", + ctx->info.plugin_name, err); + } + plugin_info_clear(&ctx->info); } /* ctx_destroy */ @@ -280,6 +303,7 @@ ctx_create(const char *name) if (! plugin_ctx_key_initialized) ctx_key_init(); + sdb_object_ref(SDB_OBJ(ctx)); pthread_setspecific(plugin_ctx_key, ctx); return ctx; } /* ctx_create */ @@ -301,6 +325,10 @@ ctx_set(ctx_t *new) ctx_key_init(); old = pthread_getspecific(plugin_ctx_key); + if (old) + sdb_object_deref(SDB_OBJ(old)); + if (new) + sdb_object_ref(SDB_OBJ(new)); pthread_setspecific(plugin_ctx_key, new); return old; } /* ctx_set */ @@ -356,60 +384,41 @@ static sdb_type_t sdb_plugin_collector_cb_type = { }; static int -plugin_add_callback(sdb_llist_t **list, const char *type, - const char *name, void *callback, sdb_object_t *user_data) +module_init(const char *name, lt_dlhandle lh, sdb_plugin_info_t *info) { - sdb_object_t *obj; - - if ((! name) || (! callback)) - return -1; - - assert(list); - - if (! *list) - *list = sdb_llist_create(); - if (! *list) - return -1; + int (*mod_init)(sdb_plugin_info_t *); + int status; - obj = sdb_object_create(name, sdb_plugin_cb_type, - list, type, callback, user_data); - if (! obj) + mod_init = (int (*)(sdb_plugin_info_t *))lt_dlsym(lh, "sdb_module_init"); + if (! mod_init) { + sdb_log(SDB_LOG_ERR, "core: Failed to load plugin '%s': " + "could not find symbol 'sdb_module_init'", name); return -1; + } - if (sdb_llist_append(*list, obj)) { - sdb_object_deref(obj); + status = mod_init(info); + if (status) { + sdb_log(SDB_LOG_ERR, "core: Failed to initialize " + "module '%s'", name); + plugin_unregister_by_name(name); return -1; } - - /* pass control to the list */ - sdb_object_deref(obj); - - sdb_log(SDB_LOG_INFO, "core: Registered %s callback '%s'.", - type, name); return 0; -} /* plugin_add_callback */ +} /* module_init */ -/* - * public API - */ - -int -sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx) +static int +module_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx) { char base_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 *); - int status; + ctx_t *ctx; - if ((! name) || (! *name)) - return -1; + int status; base_name[0] = '\0'; name_ptr = name; @@ -421,13 +430,6 @@ sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx) } strcat(base_name, name_ptr); - ctx = CTX(sdb_llist_search_by_name(all_plugins, base_name)); - if (ctx) { - /* plugin already loaded */ - ++ctx->use_cnt; - return 0; - } - snprintf(filename, sizeof(filename), "%s/%s.so", PKGLIBDIR, base_name); filename[sizeof(filename) - 1] = '\0'; @@ -461,25 +463,14 @@ sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx) ctx->info.plugin_name = strdup(name); ctx->info.filename = strdup(filename); + ctx->handle = lh; 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, "core: Failed to load plugin '%s': " - "could not find symbol 'sdb_module_init'", name); + if ((status = module_init(name, lh, &ctx->info))) { sdb_object_deref(SDB_OBJ(ctx)); - return -1; - } - - status = mod_init(&ctx->info); - if (status) { - 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; + return status; } /* compare minor version */ @@ -491,16 +482,6 @@ sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx) name, SDB_VERSION_DECODE(ctx->info.version), SDB_VERSION_DECODE(SDB_VERSION)); - 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 " @@ -516,6 +497,70 @@ sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx) /* reset */ ctx_set(NULL); return 0; +} /* module_load */ + +static int +plugin_add_callback(sdb_llist_t **list, const char *type, + const char *name, void *callback, sdb_object_t *user_data) +{ + sdb_object_t *obj; + + if ((! name) || (! callback)) + return -1; + + assert(list); + + if (! *list) + *list = sdb_llist_create(); + if (! *list) + return -1; + + obj = sdb_object_create(name, sdb_plugin_cb_type, + list, type, callback, user_data); + if (! obj) + return -1; + + if (sdb_llist_append(*list, obj)) { + sdb_object_deref(obj); + return -1; + } + + /* pass control to the list */ + sdb_object_deref(obj); + + sdb_log(SDB_LOG_INFO, "core: Registered %s callback '%s'.", + type, name); + return 0; +} /* plugin_add_callback */ + +/* + * public API + */ + +int +sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx) +{ + ctx_t *ctx; + + if ((! name) || (! *name)) + return -1; + + 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); + return -1; + } + } + + ctx = CTX(sdb_llist_search_by_name(all_plugins, name)); + if (ctx) { + /* plugin already loaded */ + ++ctx->use_cnt; + return 0; + } + + return module_load(name, plugin_ctx); } /* sdb_plugin_load */ int