diff options
Diffstat (limited to 'dbm/apr_dbm.c')
-rw-r--r-- | dbm/apr_dbm.c | 198 |
1 files changed, 141 insertions, 57 deletions
diff --git a/dbm/apr_dbm.c b/dbm/apr_dbm.c index d4fed7b1..04b517b5 100644 --- a/dbm/apr_dbm.c +++ b/dbm/apr_dbm.c @@ -24,6 +24,7 @@ #include "apr_general.h" #include "apu.h" +#include "apr_dbm_private.h" #include "apu_select_dbm.h" #include "apr_dbm.h" #include "apr_dbm_private.h" @@ -34,56 +35,165 @@ ### API entirely? Oh, what to do. We need an APU_DEFAULT_DBM #define. ### Sounds like a job for autoconf. */ -#if APU_USE_SDBM -#define DBM_VTABLE apr_dbm_type_sdbm +#if APU_USE_DB +#define DBM_VTABLE apr_dbm_type_db +#define DBM_NAME "db" #elif APU_USE_GDBM #define DBM_VTABLE apr_dbm_type_gdbm -#elif APU_USE_DB -#define DBM_VTABLE apr_dbm_type_db +#define DBM_NAME "gdbm" #elif APU_USE_NDBM #define DBM_VTABLE apr_dbm_type_ndbm +#define DBM_NAME "ndbm" +#elif APU_USE_SDBM +#define DBM_VTABLE apr_dbm_type_sdbm +#define DBM_NAME "sdbm" #else /* Not in the USE_xDBM list above */ #error a DBM implementation was not specified #endif -APU_DECLARE(apr_status_t) apr_dbm_open_ex(apr_dbm_t **pdb, const char*type, - const char *pathname, - apr_int32_t mode, apr_fileperms_t perm, - apr_pool_t *pool) +#ifdef APU_DSO_BUILD + +static apr_hash_t *drivers = NULL; + +static apr_status_t apr_dbd_term(void *ptr) { + /* set drivers to NULL so init can work again */ + drivers = NULL; + + /* Everything else we need is handled by cleanups registered + * when we created mutexes and loaded DSOs + */ + return APR_SUCCESS; +} + +#endif /* APU_DSO_BUILD */ + +static apr_status_t dbm_open_type(apr_dbm_type_t const* * vtable, + const char *type, + apr_pool_t *pool) +{ +#ifndef APU_DSO_BUILD + + *vtable = NULL; + if (!strcasecmp(type, "default")) *vtable = &DBM_VTABLE; +#if APU_HAVE_DB + else if (!strcasecmp(type, "db")) *vtable = &apr_dbm_type_db; +#endif + else if (*type && !strcasecmp(type + 1, "dbm")) { #if APU_HAVE_GDBM - if (!strcasecmp(type, "GDBM")) { - return (*apr_dbm_type_gdbm.open)(pdb, pathname, mode, perm, pool); - } + if (*type == 'G' && *type == 'g') *vtable = &apr_dbm_type_gdbm; +#endif +#if APU_HAVE_NDBM + if (*type == 'N' && *type == 'n') *vtable = &apr_dbm_type_ndbm; #endif #if APU_HAVE_SDBM - if (!strcasecmp(type, "SDBM")) { - return (*apr_dbm_type_sdbm.open)(pdb, pathname, mode, perm, pool); - } + if (*type == 'S' && *type == 's') *vtable = &apr_dbm_type_sdbm; #endif -#if APU_HAVE_DB - if (!strcasecmp(type, "DB")) { - return (*apr_dbm_type_db.open)(pdb, pathname, mode, perm, pool); + /* avoid empty block */ ; } -#endif -#if APU_HAVE_NDBM - if (!strcasecmp(type, "NDBM")) { - return (*apr_dbm_type_ndbm.open)(pdb, pathname, mode, perm, pool); + if (*vtable) + return APR_SUCCESS; + return APR_ENOTIMPL; + +#else /* APU_DSO_BUILD */ + + char modname[32]; + char symname[34]; + apr_dso_handle_sym_t symbol; + apr_status_t rv; + int usertype = 0; + + if (!strcasecmp(type, "default")) type = DBM_NAME; + else if (!strcasecmp(type, "db")) type = "db"; + else if (*type && !strcasecmp(type + 1, "dbm")) { + if (type == 'G' || type == 'g') type = "gdbm"; + else if (type == 'N' || type == 'n') type = "ndbm"; + else if (type == 'S' || type == 's') type = "sdbm"; + } + else usertype = 1; + + if (!drivers) + { + apr_pool_t *ppool = pool; + apr_pool_t *parent; + + /* Top level pool scope, need process-scope lifetime */ + for (parent = pool; parent; parent = apr_pool_parent_get(ppool)) + ppool = parent; + + /* deprecate in 2.0 - permit implicit initialization */ + apu_dso_init(ppool); + + drivers = apr_hash_make(ppool); + apr_hash_set(drivers, "sdbm", APR_HASH_KEY_STRING, &apr_dbm_type_sdbm); + + apr_pool_cleanup_register(ppool, NULL, dbm_term, + apr_pool_cleanup_null); } + + rv = apu_dso_mutex_lock(); + if (rv) { + *vtable = NULL + return rv; + } + + *vtable = apr_hash_get(drivers, type, APR_HASH_KEY_STRING); + if (*vtable) { + apu_dso_mutex_unlock(); + return APR_SUCCESS; + } + + /* The driver DSO must have exactly the same lifetime as the + * drivers hash table; ignore the passed-in pool */ + pool = apr_hash_pool_get(drivers); + +#if defined(NETWARE) + apr_snprintf(modname, sizeof(modname), "dbm%s.nlm", type); +#elif defined(WIN32) + apr_snprintf(modname, sizeof(modname), + "apr_dbm_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".dll", type); +#else + apr_snprintf(modname, sizeof(modname), + "apr_dbm_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".so", type); #endif + apr_snprintf(symname, sizeof(symname), "apr_dbm_type_%s", type); - if (!strcasecmp(type, "default")) { - return (*DBM_VTABLE.open)(pdb, pathname, mode, perm, pool); + rv = apu_dso_load(&symbol, modname, symname, pool); + if (rv != APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */ + *vtable = symbol; + if (usertype) + type = apr_pstrdup(pool, type); + apr_hash_set(drivers, type, APR_HASH_KEY_STRING, *vtable); } + else + *vtable = NULL; - return APR_ENOTIMPL; + apu_dso_mutex_unlock(); + return rv; + +#endif /* APU_DSO_BUILD */ +} + +APU_DECLARE(apr_status_t) apr_dbm_open_ex(apr_dbm_t **pdb, const char *type, + const char *pathname, + apr_int32_t mode, + apr_fileperms_t perm, + apr_pool_t *pool) +{ + apr_dbm_type_t const* vtable = NULL; + apr_status_t rv = dbm_open_type(&vtable, type, pool); + + if (rv == APR_SUCCESS) { + rv = (vtable->open)(pdb, pathname, mode, perm, pool); + } + return rv; } APU_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t **pdb, const char *pathname, apr_int32_t mode, apr_fileperms_t perm, apr_pool_t *pool) { - return (*DBM_VTABLE.open)(pdb, pathname, mode, perm, pool); + return apr_dbm_open_ex(pdb, DBM_NAME, pathname, mode, perm, pool); } APU_DECLARE(void) apr_dbm_close(apr_dbm_t *dbm) @@ -149,37 +259,14 @@ APU_DECLARE(apr_status_t) apr_dbm_get_usednames_ex(apr_pool_t *p, const char **used1, const char **used2) { -#if APU_HAVE_GDBM - if (!strcasecmp(type, "GDBM")) { - (*apr_dbm_type_gdbm.getusednames)(p,pathname,used1,used2); - return APR_SUCCESS; - } -#endif -#if APU_HAVE_SDBM - if (!strcasecmp(type, "SDBM")) { - (*apr_dbm_type_sdbm.getusednames)(p,pathname,used1,used2); - return APR_SUCCESS; - } -#endif -#if APU_HAVE_DB - if (!strcasecmp(type, "DB")) { - (*apr_dbm_type_db.getusednames)(p,pathname,used1,used2); - return APR_SUCCESS; - } -#endif -#if APU_HAVE_NDBM - if (!strcasecmp(type, "NDBM")) { - (*apr_dbm_type_ndbm.getusednames)(p,pathname,used1,used2); - return APR_SUCCESS; - } -#endif + apr_dbm_type_t const* vtable; + apr_status_t rv = dbm_open_type(&vtable, type, p); - if (!strcasecmp(type, "default")) { - (*DBM_VTABLE.getusednames)(p, pathname, used1, used2); + if (rv == APR_SUCCESS) { + (vtable->getusednames)(p, pathname, used1, used2); return APR_SUCCESS; } - - return APR_ENOTIMPL; + return rv; } APU_DECLARE(void) apr_dbm_get_usednames(apr_pool_t *p, @@ -187,10 +274,7 @@ APU_DECLARE(void) apr_dbm_get_usednames(apr_pool_t *p, const char **used1, const char **used2) { - /* ### one day, a DBM type name will be passed and we'll need to look it - ### up. for now, it is constant. */ - - (*DBM_VTABLE.getusednames)(p, pathname, used1, used2); + apr_dbm_get_usednames_ex(p, DBM_NAME, pathname, used1, used2); } /* Most DBM libraries take a POSIX mode for creating files. Don't trust |