src/module.c
branchnew-lib-errors
changeset 217 7728d6ec3abf
parent 216 a10ba529ae39
child 218 5229a5d098b2
--- a/src/module.c	Wed May 27 23:07:00 2009 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,394 +0,0 @@
-#include "module.h"
-#include "log.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <dlfcn.h>
-#include <string.h>
-#include <assert.h>
-
-err_t modules_create (struct modules **modules_ptr, struct nexus *nexus)
-{
-    struct modules *modules;
-
-    // alloc
-    if ((modules = calloc(1, sizeof(*modules))) == NULL)
-        return ERR_CALLOC;
-    
-    // init
-    TAILQ_INIT(&modules->list);
-
-    // store
-    modules->nexus = nexus;
-
-    // ok
-    *modules_ptr = modules;
-
-    return SUCCESS;
-}
-
-const char* modules_path (struct modules *modules, const char *path)
-{
-    const char *old_path = modules->path;
-
-    if (path)
-        // replace
-        modules->path = path;
-
-    return old_path;
-}
-
-/**
- * module_get without the refcount stuff
- */
-static struct module* modules_lookup (struct modules *modules, const char *name)
-{
-    struct module *module = NULL;
-
-    // look for it...
-    TAILQ_FOREACH(module, &modules->list, modules_list) {
-        if (strcasecmp(module->info.name, name) == 0) {
-            // found it
-            return module;
-        }
-    }
-
-    // no such module
-    return NULL;
-}
-
-struct module* modules_get (struct modules *modules, const char *name)
-{
-    struct module *module;
-    
-    // get it
-    if (!(module = modules_lookup(modules, name)))
-        return NULL;
-
-    // up the refcount
-    module->refcount++;
-    
-    // ok
-    return module;
-}
-
-err_t modules_unload (struct modules *modules)
-{
-    struct module *module;
-    err_t err;
-
-    // unload each module in turn
-    while ((module = TAILQ_FIRST(&modules->list))) {
-        if ((err = module_unload(module)))
-            log_warn("module_unload(%s) failed: %s", module->info.name, error_name(err));
-    }
-
-    // ok
-    return SUCCESS;
-}
-
-void modules_destroy (struct modules *modules)
-{
-    struct module *module;
-
-    // destroy each module
-    while ((module = TAILQ_FIRST(&modules->list)))
-        module_destroy(module);
-
-    // ourselves
-    free(modules);
-}
-
-
-const char* module_name (struct module *module)
-{
-    return module ? module->info.name : NULL;
-}
-
-/**
- * Load the symbol named "<module>_<suffix>".
- */ 
-static err_t module_symbol (struct module *module, void **sym, const char *suffix)
-{
-    char sym_name[MODULE_SYMBOL_MAX];
-
-    // validate the length of the suffix
-    assert(strlen(module->info.name) <= MODULE_NAME_MAX);
-    assert(strlen(suffix) <= MODULE_SUFFIX_MAX);
-
-    // format
-    sprintf(sym_name, "%s_%s", module->info.name, suffix);
-
-    // load
-    if ((*sym = dlsym(module->handle, sym_name)) == NULL)
-       return ERR_MODULE_SYM;
-
-    // ok
-    return SUCCESS;
-}
-
-/**
- * XXX: ugly function to format to a dynamically allocated string
- */
-char *strfmt (const char *fmt, ...)
-{
-    va_list vargs;
-    size_t len;
-    char *buf;
-
-    // figure out the length of the resulting string
-    va_start(vargs, fmt);
-
-    len = vsnprintf(NULL, 0, fmt, vargs) + 1;
-
-    va_end(vargs);
-
-    // malloc
-    if ((buf = malloc(len)) == NULL)
-        return NULL;
-
-    // format
-    va_start(vargs, fmt);
-
-    vsnprintf(buf, len, fmt, vargs);
-
-    va_end(vargs);
-
-    // ok
-    return buf;
-}
-
-/**
- * Looks up a module's path by name, returning a dynamically allocated string with the path on success
- */
-static char* module_find (struct modules *modules, struct module_info *info, struct error_info *err)
-{
-    char *path = NULL;
-
-    // build the path...
-    if ((path = strfmt("%s/mod_%s.so", modules->path, info->name)) == NULL)
-        JUMP_SET_ERROR(err, ERR_STRDUP);
-
-    // exists and readable?
-    if (access(path, R_OK))
-        // XXX: this doesn't contain the path...
-        JUMP_SET_ERROR_STR(err, ERR_MODULE_PATH, "module not found in search path");
-    
-    // ok
-    return path;
-
-error:
-    // release the dynamically allocated path
-    free(path);
-
-    return NULL;
-}
-
-err_t module_load (struct modules *modules, struct module **module_ptr, const struct module_info *_info, struct error_info *err)
-{
-    struct module *module;
-
-    // validate the module name
-    if (strlen(_info->name) > MODULE_NAME_MAX)
-        return SET_ERROR(err, ERR_MODULE_NAME);
-    
-    // already open with the same name?
-    if (modules_lookup(modules, _info->name))
-        return SET_ERROR(err, ERR_MODULE_DUP);
-
-    // alloc
-    if ((module = calloc(1, sizeof(*module))) == NULL)
-        return SET_ERROR(err, ERR_CALLOC);
-    
-    // initialize
-    module->info = *_info;
-    module->modules = modules;
-    module->refcount = 1;
- 
-    // add to modules list
-    TAILQ_INSERT_TAIL(&modules->list, module, modules_list);
-   
-    // lookup path?
-    if (!module->info.path) {
-        // have a search path?
-        if (!modules->path)
-            JUMP_SET_ERROR_STR(err, ERR_MODULE_PATH, "no module search path defined");
-
-        // try and resolve the path automatically
-        if ((module->path_buf = module_find(modules, &module->info, err)) == NULL)
-            goto error;
-        
-        // use that path
-        module->info.path = module->path_buf;
-    }
-
-    // clear dlerrors
-    (void) dlerror();
-
-    // load it
-    if ((module->handle = dlopen(module->info.path, RTLD_NOW)) == NULL)
-        JUMP_SET_ERROR_STR(err, ERR_MODULE_OPEN, dlerror());
-    
-    // load the funcs symbol
-    if ((ERROR_CODE(err) = module_symbol(module, (void **) &module->desc, "module")))
-        JUMP_SET_ERROR_STR(err, ERROR_CODE(err), dlerror());
-
-    // call the init func
-    if ((module->desc->init(modules->nexus, &module->ctx, err)))
-        goto error;
-
-    // ok
-    if (module_ptr) {
-        module->refcount++;
-        *module_ptr = module;
-    }
-
-    return SUCCESS;
-
-error:
-    // cleanup
-    module->refcount = 0;
-    module_destroy(module);
-
-    return ERROR_CODE(err);    
-}
-
-void module_put (struct module *module)
-{
-    assert(module->refcount > 0);
-    
-    // decrement, just return if still alive
-    if (--module->refcount > 0)
-        return;
-    
-    // refcount zero, destroy
-    module_destroy(module);
-}
-
-err_t module_conf_raw (struct module *module, const char *name, char *value, struct error_info *err)
-{
-    // sanity-check
-    if (!module->desc->config_options)
-        RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "module does not have any config options");
-
-    // wrong state
-    if (module->unloading)
-        RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "module is being unloaded");
-    
-    // parse/apply using the module's stuff    
-    return config_apply_raw(module->desc->config_options, module->modules->nexus, module->ctx, name, value, err);
-}
-
-const struct config_option* module_conf_lookup (struct module *module, const char *name, struct error_info *err)
-{
-    // sanity-check
-    if (!module->desc->config_options)
-        JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "module does not have any config options");
-    
-    // direct lookup
-    return config_lookup(module->desc->config_options, name, err);
-
-error:
-    return NULL;    
-}
-
-err_t module_conf (struct module *module, const struct config_option *opt, const struct config_value *value, struct error_info *err)
-{
-    // wrong state
-    if (module->unloading)
-        RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "module is being unloaded");
-    
-    // apply with the module's ctx
-    return config_apply_opt(opt, module->ctx, value, err);
-}
-
-err_t module_unload (struct module *module)
-{
-    err_t err;
-    
-    // wrong state
-    if (module->unloading)
-        return ERR_MODULE_STATE;
-
-    // remove from modules list
-    TAILQ_REMOVE(&module->modules->list, module, modules_list);
-    
-    // update status
-    module->unloading = true;
-
-    if (module->desc->unload) {
-        // invoke the unload func, passing it our reference
-        // note that the module might not exist anymore after calling this
-        if ((err = module->desc->unload(module->ctx, module))) {
-            // mark it as "unloaded"
-            module_unloaded(module);
-
-            return err;
-        }
-
-    } else {
-        // no unload procedure, just destroy it as soon as needed
-        module_unloaded(module);
-
-    }
-    // ok
-    return SUCCESS;
-}
-
-/**
- * A wrapper for module_destroy suitable for use as a libevent callback
- */
-static void _module_destroy (int fd, short what, void *arg)
-{
-    struct module *module = arg;
-
-    (void) fd;
-    (void) what;
-    
-    // execute
-    module_destroy(module);
-}
-
-void module_unloaded (struct module *module)
-{
-    struct timeval tv = { 0, 0 };
-    assert(module->refcount > 0);
-    
-    // decrement, just return if still alive
-    if (--module->refcount > 0)
-        return;
-    
-    // schedule a deferred module_destroy
-    if (event_base_once(module->modules->nexus->ev_base, -1, EV_TIMEOUT, &_module_destroy, module, &tv))
-        // XXX: how to reach?
-        log_fatal("event_base_once failed, unable to schedule deferred module_destroy");
-}
-
-void module_destroy (struct module *module)
-{
-    // XXX: warn about destroy with significant refcount...
-    if (module->refcount)
-        log_warn("destroying module %s with refcount>0: %zu", module_name(module), module->refcount);
-    else
-        log_debug("destroying module %s", module_name(module));
-
-    // still need to remove from modules_list?
-    if (!module->unloading)
-        TAILQ_REMOVE(&module->modules->list, module, modules_list);
-
-    // run the destroy hook
-    if (module->desc && module->desc->destroy && module->ctx)
-        module->desc->destroy(module->ctx);
-
-    // unload the dl handle
-    if (module->handle && dlclose(module->handle))
-        log_warn("dlclose(%s): %s", module->info.name, dlerror());
-    
-    // release the path buf, if any
-    free(module->path_buf);
-
-    // free the module info
-    free(module);
-}
-
-