diff --git a/src/core/plugin.c b/src/core/plugin.c
index c248d37eff6c15f9abce00d3d0b53b0b636a580e..8250dde1e7c1825cd4e676b2ac7f6239bff4e824 100644 (file)
--- a/src/core/plugin.c
+++ b/src/core/plugin.c
*/
struct sdb_plugin_info {
+ char *plugin_name;
+ char *filename;
+
+ /* public attributes */
char *name;
char *description;
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;
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, \
* 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;
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;
*/
static void
-sdb_plugin_ctx_destructor(void *ctx)
+sdb_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;
+} /* sdb_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 */
+} /* 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;
+ ctx->info = plugin_default_info;
+ return 0;
+} /* ctx_init */
+
+static void
+ctx_destroy(sdb_object_t *obj)
+{
+ ctx_t *ctx = CTX(obj);
+ sdb_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(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 = {
sizeof(sdb_plugin_cb_t),
sdb_plugin_cb_init,
- sdb_plugin_cb_destroy,
- /* clone = */ NULL
+ sdb_plugin_cb_destroy
};
static sdb_type_t sdb_plugin_collector_cb_type = {
sizeof(sdb_plugin_collector_cb_t),
sdb_plugin_cb_init,
- sdb_plugin_cb_destroy,
- /* clone = */ NULL
+ sdb_plugin_cb_destroy
};
static int
*/
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;
int (*mod_init)(sdb_plugin_info_t *);
- sdb_plugin_info_t plugin_info = SDB_PLUGIN_INFO_INIT;
-
int status;
if ((! name) || (! *name))
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;
+ }
+
+ 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': "
"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_object_deref(SDB_OBJ(ctx));
return -1;
}
/* compare minor version */
- if ((plugin_info.version < 0)
- || ((int)(plugin_info.version / 100) != (int)(SDB_VERSION / 100)))
+ if ((ctx->info.version < 0)
+ || ((int)(ctx->info.version / 100) != (int)(SDB_VERSION / 100)))
sdb_log(SDB_LOG_WARNING, "plugin: 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);
+ "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 */
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:
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 sdb_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)
@@ -471,37 +598,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, "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)
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)
{