diff --git a/src/core/plugin.c b/src/core/plugin.c
index 559e6eb4d7db1aa803a55783025d2dc4a8ee6afb..e6df9e9c2a9da7b1746fba2121492dbce630f0bc 100644 (file)
--- a/src/core/plugin.c
+++ b/src/core/plugin.c
sdb_plugin_ctx_t public;
sdb_plugin_info_t info;
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
+ * the plugin is in use. */
+ size_t use_cnt;
} ctx_t;
#define CTX_INIT { SDB_OBJECT_INIT, \
} ctx_t;
#define CTX_INIT { SDB_OBJECT_INIT, \
- SDB_PLUGIN_CTX_INIT, SDB_PLUGIN_INFO_INIT }
+ SDB_PLUGIN_CTX_INIT, SDB_PLUGIN_INFO_INIT, NULL, 0 }
#define CTX(obj) ((ctx_t *)(obj))
#define CTX(obj) ((ctx_t *)(obj))
static void
plugin_unregister_by_name(const char *plugin_name)
{
static void
plugin_unregister_by_name(const char *plugin_name)
{
+ sdb_object_t *obj;
size_t i;
struct {
size_t i;
struct {
sdb_llist_t *list = all_lists[i].list;
while (1) {
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 "
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);
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 */
/*
} /* plugin_unregister_by_name */
/*
ctx->public = plugin_default_ctx;
ctx->info = plugin_default_info;
ctx->public = plugin_default_ctx;
ctx->info = plugin_default_info;
+ ctx->handle = NULL;
+ ctx->use_cnt = 1;
return 0;
} /* ctx_init */
return 0;
} /* ctx_init */
ctx_destroy(sdb_object_t *obj)
{
ctx_t *ctx = CTX(obj);
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 */
plugin_info_clear(&ctx->info);
} /* ctx_destroy */
if (! plugin_ctx_key_initialized)
ctx_key_init();
if (! plugin_ctx_key_initialized)
ctx_key_init();
+ sdb_object_ref(SDB_OBJ(ctx));
pthread_setspecific(plugin_ctx_key, ctx);
return ctx;
} /* ctx_create */
pthread_setspecific(plugin_ctx_key, ctx);
return ctx;
} /* ctx_create */
ctx_key_init();
old = pthread_getspecific(plugin_ctx_key);
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 */
pthread_setspecific(plugin_ctx_key, new);
return old;
} /* ctx_set */
int
sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx)
{
int
sdb_plugin_load(const char *name, const sdb_plugin_ctx_t *plugin_ctx)
{
- char real_name[name ? strlen(name) + 1 : 1];
+ char base_name[name ? strlen(name) + 1 : 1];
const char *name_ptr;
char *tmp;
const char *name_ptr;
char *tmp;
if ((! name) || (! *name))
return -1;
if ((! name) || (! *name))
return -1;
- real_name[0] = '\0';
+ base_name[0] = '\0';
name_ptr = name;
while ((tmp = strstr(name_ptr, "::"))) {
name_ptr = name;
while ((tmp = strstr(name_ptr, "::"))) {
- strncat(real_name, name_ptr, (size_t)(tmp - name_ptr));
- strcat(real_name, "/");
+ strncat(base_name, name_ptr, (size_t)(tmp - name_ptr));
+ strcat(base_name, "/");
name_ptr = tmp + strlen("::");
}
name_ptr = tmp + strlen("::");
}
- strcat(real_name, name_ptr);
+ 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",
snprintf(filename, sizeof(filename), "%s/%s.so",
- PKGLIBDIR, real_name);
+ PKGLIBDIR, base_name);
filename[sizeof(filename) - 1] = '\0';
if (access(filename, R_OK)) {
filename[sizeof(filename) - 1] = '\0';
if (access(filename, R_OK)) {
if (ctx_get())
sdb_log(SDB_LOG_WARNING, "core: Discarding old plugin context");
if (ctx_get())
sdb_log(SDB_LOG_WARNING, "core: Discarding old plugin context");
- ctx = ctx_create(real_name);
+ ctx = ctx_create(name);
if (! ctx) {
sdb_log(SDB_LOG_ERR, "core: Failed to initialize plugin context");
return -1;
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);
ctx->info.plugin_name = strdup(name);
ctx->info.filename = strdup(filename);
+ ctx->handle = lh;
if (plugin_ctx)
ctx->public = *plugin_ctx;
if (plugin_ctx)
ctx->public = *plugin_ctx;
sdb_plugin_register_config(const char *name, sdb_plugin_config_cb callback)
{
return plugin_add_callback(&config_list, "init", name,
sdb_plugin_register_config(const char *name, sdb_plugin_config_cb callback)
{
return plugin_add_callback(&config_list, "init", name,
- callback, NULL);
+ (void *)callback, NULL);
} /* sdb_plugin_register_config */
int
} /* sdb_plugin_register_config */
int
sdb_object_t *user_data)
{
return plugin_add_callback(&init_list, "init", name,
sdb_object_t *user_data)
{
return plugin_add_callback(&init_list, "init", name,
- callback, user_data);
+ (void *)callback, user_data);
} /* sdb_plugin_register_init */
int
} /* sdb_plugin_register_init */
int
@@ -594,14 +636,14 @@ sdb_plugin_register_shutdown(const char *name, sdb_plugin_shutdown_cb callback,
sdb_object_t *user_data)
{
return plugin_add_callback(&shutdown_list, "shutdown", name,
sdb_object_t *user_data)
{
return plugin_add_callback(&shutdown_list, "shutdown", name,
- callback, user_data);
+ (void *)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)
{
} /* 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,
+ return plugin_add_callback(&log_list, "log", name, (void *)callback,
user_data);
} /* sdb_plugin_register_log */
user_data);
} /* sdb_plugin_register_log */
sdb_plugin_register_cname(const char *name, sdb_plugin_cname_cb callback,
sdb_object_t *user_data)
{
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,
+ return plugin_add_callback(&cname_list, "cname", name, (void *)callback,
user_data);
} /* sdb_plugin_register_cname */
user_data);
} /* sdb_plugin_register_cname */
plugin = SDB_PLUGIN_CB(sdb_llist_search_by_name(config_list, name));
if (! plugin) {
plugin = SDB_PLUGIN_CB(sdb_llist_search_by_name(config_list, name));
if (! plugin) {
- /* XXX: check if any such plugin has been loaded */
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);
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);
}
old_ctx = ctx_set(plugin->cb_ctx);
}
old_ctx = ctx_set(plugin->cb_ctx);
- callback = plugin->cb_callback;
+ callback = (sdb_plugin_config_cb)plugin->cb_callback;
status = callback(ci);
ctx_set(old_ctx);
return status;
status = callback(ci);
ctx_set(old_ctx);
return status;
assert(obj);
cb = SDB_PLUGIN_CB(obj);
assert(obj);
cb = SDB_PLUGIN_CB(obj);
- callback = cb->cb_callback;
+ callback = (sdb_plugin_init_cb)cb->cb_callback;
old_ctx = ctx_set(cb->cb_ctx);
if (callback(cb->cb_user_data)) {
old_ctx = ctx_set(cb->cb_ctx);
if (callback(cb->cb_user_data)) {
if (! obj)
return -1;
if (! obj)
return -1;
- callback = SDB_PLUGIN_CCB(obj)->ccb_callback;
+ callback = (sdb_plugin_collector_cb)SDB_PLUGIN_CCB(obj)->ccb_callback;
if (! (now = sdb_gettime())) {
char errbuf[1024];
if (! (now = sdb_gettime())) {
char errbuf[1024];
sdb_object_t *obj = sdb_llist_iter_get_next(iter);
assert(obj);
sdb_object_t *obj = sdb_llist_iter_get_next(iter);
assert(obj);
- callback = SDB_PLUGIN_CB(obj)->cb_callback;
+ callback = (sdb_plugin_cname_cb)SDB_PLUGIN_CB(obj)->cb_callback;
cname = callback(hostname, SDB_PLUGIN_CB(obj)->cb_user_data);
if (cname) {
free(hostname);
cname = callback(hostname, SDB_PLUGIN_CB(obj)->cb_user_data);
if (cname) {
free(hostname);
sdb_object_t *obj = sdb_llist_iter_get_next(iter);
assert(obj);
sdb_object_t *obj = sdb_llist_iter_get_next(iter);
assert(obj);
- callback = SDB_PLUGIN_CB(obj)->cb_callback;
+ callback = (sdb_plugin_log_cb)SDB_PLUGIN_CB(obj)->cb_callback;
tmp = callback(prio, msg, SDB_PLUGIN_CB(obj)->cb_user_data);
if (tmp > ret)
ret = tmp;
tmp = callback(prio, msg, SDB_PLUGIN_CB(obj)->cb_user_data);
if (tmp > ret)
ret = tmp;