diff --git a/src/core/plugin.c b/src/core/plugin.c
index 26677979b26257e4a9ef89aeed363e9d032e3418..a31ede30f2ed4104f104d9780bb6104ed484ed17 100644 (file)
--- a/src/core/plugin.c
+++ b/src/core/plugin.c
#define INFO_GET(i, attr) \
((i)->attr ? (i)->attr : #attr" not set")
+typedef struct {
+ sdb_object_t super;
+ sdb_plugin_ctx_t public;
+} ctx_t;
+#define CTX_INIT { SDB_OBJECT_INIT, \
+ SDB_PLUGIN_CTX_INIT }
+
+#define CTX(obj) ((ctx_t *)(obj))
+
typedef struct {
sdb_object_t super;
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, \
/* callback = */ NULL, /* user_data = */ NULL, \
static sdb_plugin_ctx_t plugin_default_ctx = SDB_PLUGIN_CTX_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;
static sdb_llist_t *config_list = NULL;
static sdb_llist_t *init_list = NULL;
} /* sdb_plugin_info_clear */
static void
-sdb_plugin_ctx_destructor(void *ctx)
-{
- if (! ctx)
- return;
- free(ctx);
-} /* sdb_plugin_ctx_destructor */
-
-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 */
+} /* ctx_key_init */
static int
sdb_plugin_cmp_next_update(const sdb_object_t *a, const sdb_object_t *b)
* 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;
+ return 0;
+} /* ctx_init */
+
+static sdb_type_t ctx_type = {
+ sizeof(ctx_t),
+
+ ctx_init,
+ NULL
+};
+
+static ctx_t *
+ctx_create(void)
+{
+ ctx_t *ctx;
+
+ ctx = CTX(sdb_object_create("plugin-context", ctx_type));
+ if (! ctx)
+ return NULL;
+
+ 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)
{
}
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;
{
assert(obj);
sdb_object_deref(SDB_PLUGIN_CB(obj)->cb_user_data);
+ sdb_object_deref(SDB_OBJ(SDB_PLUGIN_CB(obj)->cb_ctx));
} /* sdb_plugin_cb_destroy */
static sdb_type_t sdb_plugin_cb_type = {
*/
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];
const char *name_ptr;
char *tmp;
char filename[1024];
+ ctx_t *ctx;
lt_dlhandle lh;
return -1;
}
+ if (ctx_get())
+ sdb_log(SDB_LOG_WARNING, "plugin: Discarding old plugin context");
+
+ ctx = ctx_create();
+ if (! ctx) {
+ sdb_log(SDB_LOG_ERR, "plugin: Failed to initialize plugin context");
+ return -1;
+ }
+
+ 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': "
"could not find symbol 'sdb_module_init'", name);
+ sdb_object_deref(SDB_OBJ(ctx));
return -1;
}
sdb_log(SDB_LOG_ERR, "plugin: Failed to initialize "
"plugin '%s'", name);
sdb_plugin_info_clear(&info);
+ sdb_object_deref(SDB_OBJ(ctx));
return -1;
}
INFO_GET(&info, description),
INFO_GET(&info, copyright),
INFO_GET(&info, license));
+
sdb_plugin_info_clear(&info);
+ /* any registered callbacks took ownership of the context */
+ sdb_object_deref(SDB_OBJ(ctx));
+
+ /* reset */
+ ctx_set(NULL);
return 0;
} /* sdb_plugin_load */
@@ -516,37 +577,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;
-
- if (! plugin_ctx_key_initialized)
- sdb_plugin_ctx_init();
- ctx = pthread_getspecific(plugin_ctx_key);
+ ctx_t *c;
- if (! ctx)
- ctx = sdb_plugin_ctx_create();
- if (! ctx)
+ c = ctx_get();
+ if (! c) {
+ sdb_plugin_log(SDB_LOG_ERR, "plugin: 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, "plugin: 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
sdb_plugin_cb_t *plugin;
sdb_plugin_config_cb callback;
- sdb_plugin_ctx_t old_ctx;
+ ctx_t *old_ctx;
int status;
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 */
iter = sdb_llist_get_iter(init_list);
while (sdb_llist_iter_has_next(iter)) {
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);
callback = SDB_PLUGIN_CB(obj)->cb_callback;
- old_ctx = sdb_plugin_set_ctx(SDB_PLUGIN_CB(obj)->cb_ctx);
+ old_ctx = ctx_set(SDB_PLUGIN_CB(obj)->cb_ctx);
if (callback(SDB_PLUGIN_CB(obj)->cb_user_data)) {
/* XXX: unload plugin */
}
- sdb_plugin_set_ctx(old_ctx);
+ ctx_set(old_ctx);
}
sdb_llist_iter_destroy(iter);
return 0;
while (loop->do_loop) {
sdb_plugin_collector_cb callback;
- sdb_plugin_ctx_t old_ctx;
+ ctx_t *old_ctx;
sdb_time_t interval, now;
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)