From: Chris Darroch Date: Tue, 6 Feb 2007 00:25:15 +0000 (+0000) Subject: Introduce configuration groups to allow inheritance by virtual hosts of X-Git-Tag: 2.3.0~1914 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=11e2a1a700df54561d7c914c8dd8c96503b9b7e9;p=apache Introduce configuration groups to allow inheritance by virtual hosts of database configurations from the main server. The post_config hook function determines the minimal set of distinct configurations necessary so that database connection pools are shared between virtual hosts whenever possible. The SQL statements which should be prepared for each database connection are now stored in a hash for each virtual host during the configuration phase, and these hashes are merged in the normal manner using apr_hash_overlay() with that of the main server. This allows for statements to be de-registered by DBDPrepareSQL, if desired. The post_config hook function then compares the statements registered for each virtual host when determining if a separate configuration group is required. The changes in r424798, r432560, r432562, and r466641, which still have problems with configuration inheritance, are therefore no longer necessary. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@503931 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index af2a35a346..8c9799b3f3 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,12 @@ Changes with Apache 2.3.0 [Remove entries to the current 2.0 and 2.2 section below, when backported] + *) mod_dbd: Introduce configuration groups to allow inheritance by virtual + hosts of database configurations from the main server. Determine the + minimal set of distinct configurations and share connection pools + whenever possible. Allow virtual hosts to override inherited SQL + statements. [Chris Darroch] + *) core: Fix broken chunk filtering that causes all non blocking reads to be converted into blocking reads. PR 41056. [Jean-Frederic Clere, Jim Jagielski] diff --git a/modules/database/mod_dbd.c b/modules/database/mod_dbd.c index eba281c25b..a8d7521dc4 100644 --- a/modules/database/mod_dbd.c +++ b/modules/database/mod_dbd.c @@ -23,6 +23,7 @@ #include "apr_reslist.h" #include "apr_strings.h" #include "apr_hash.h" +#include "apr_tables.h" #include "apr_lib.h" #include "apr_dbd.h" @@ -45,40 +46,47 @@ extern module AP_MODULE_DECLARE_DATA dbd_module; #define NMAX_SET 0x4 #define EXPTIME_SET 0x8 -typedef struct dbd_prepared dbd_prepared; - -struct dbd_prepared { - const char *label; - const char *query; - dbd_prepared *next; -}; - typedef struct { server_rec *server; const char *name; const char *params; int persist; - dbd_prepared *prepared; - apr_pool_t *pool; #if APR_HAS_THREADS - apr_thread_mutex_t *mutex; - apr_reslist_t *reslist; - int destroyed; int nmin; int nkeep; int nmax; int exptime; int set; +#endif + apr_hash_t *queries; +} dbd_cfg_t; + +typedef struct dbd_group_t dbd_group_t; + +struct dbd_group_t { + dbd_cfg_t *cfg; + dbd_group_t *next; + apr_pool_t *pool; +#if APR_HAS_THREADS + apr_thread_mutex_t *mutex; + apr_reslist_t *reslist; + int destroyed; #else ap_dbd_t *rec; #endif +}; + +typedef struct { + dbd_cfg_t *cfg; + dbd_group_t *group; } svr_cfg; typedef enum { cmd_name, cmd_params, cmd_persist, cmd_min, cmd_keep, cmd_max, cmd_exp } cmd_parts; -static apr_hash_t *dbd_prepared_defns; +static apr_pool_t *config_pool; +static dbd_group_t *group_list; /* a default DBDriver value that'll generate meaningful error messages */ static const char *const no_dbdriver = "[DBDriver unset]"; @@ -94,37 +102,41 @@ static const char *const no_dbdriver = "[DBDriver unset]"; static void *create_dbd_config(apr_pool_t *pool, server_rec *s) { svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg)); + dbd_cfg_t *cfg = svr->cfg = apr_pcalloc(pool, sizeof(dbd_cfg_t)); - svr->server = s; - svr->name = no_dbdriver; /* to generate meaningful error messages */ - svr->params = ""; /* don't risk segfault on misconfiguration */ - svr->persist = -1; + cfg->server = s; + cfg->name = no_dbdriver; /* to generate meaningful error messages */ + cfg->params = ""; /* don't risk segfault on misconfiguration */ + cfg->persist = -1; #if APR_HAS_THREADS - svr->nmin = DEFAULT_NMIN; - svr->nkeep = DEFAULT_NKEEP; - svr->nmax = DEFAULT_NMAX; - svr->exptime = DEFAULT_EXPTIME; + cfg->nmin = DEFAULT_NMIN; + cfg->nkeep = DEFAULT_NKEEP; + cfg->nmax = DEFAULT_NMAX; + cfg->exptime = DEFAULT_EXPTIME; #endif + cfg->queries = apr_hash_make(pool); return svr; } static void *merge_dbd_config(apr_pool_t *pool, void *basev, void *addv) { - svr_cfg *base = (svr_cfg*) basev; - svr_cfg *add = (svr_cfg*) addv; + dbd_cfg_t *base = ((svr_cfg*) basev)->cfg; + dbd_cfg_t *add = ((svr_cfg*) addv)->cfg; svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg)); + dbd_cfg_t *new = svr->cfg = apr_pcalloc(pool, sizeof(dbd_cfg_t)); - svr->server = add->server; - svr->name = (add->name != no_dbdriver) ? add->name : base->name; - svr->params = strcmp(add->params, "") ? add->params : base->params; - svr->persist = (add->persist != -1) ? add->persist : base->persist; + new->server = add->server; + new->name = (add->name != no_dbdriver) ? add->name : base->name; + new->params = strcmp(add->params, "") ? add->params : base->params; + new->persist = (add->persist != -1) ? add->persist : base->persist; #if APR_HAS_THREADS - svr->nmin = (add->set&NMIN_SET) ? add->nmin : base->nmin; - svr->nkeep = (add->set&NKEEP_SET) ? add->nkeep : base->nkeep; - svr->nmax = (add->set&NMAX_SET) ? add->nmax : base->nmax; - svr->exptime = (add->set&EXPTIME_SET) ? add->exptime : base->exptime; + new->nmin = (add->set&NMIN_SET) ? add->nmin : base->nmin; + new->nkeep = (add->set&NKEEP_SET) ? add->nkeep : base->nkeep; + new->nmax = (add->set&NMAX_SET) ? add->nmax : base->nmax; + new->exptime = (add->set&EXPTIME_SET) ? add->exptime : base->exptime; #endif + new->queries = apr_hash_overlay(pool, add->queries, base->queries); return svr; } @@ -144,50 +156,51 @@ static const char *dbd_param(cmd_parms *cmd, void *dconf, const char *val) const apr_dbd_driver_t *driver = NULL; svr_cfg *svr = ap_get_module_config(cmd->server->module_config, &dbd_module); + dbd_cfg_t *cfg = svr->cfg; switch ((long) cmd->info) { case cmd_name: - svr->name = val; + cfg->name = val; /* loading the driver involves once-only dlloading that is * best done at server startup. This also guarantees that * we won't return an error later. */ - switch (apr_dbd_get_driver(cmd->pool, svr->name, &driver)) { + switch (apr_dbd_get_driver(cmd->pool, cfg->name, &driver)) { case APR_ENOTIMPL: - return apr_psprintf(cmd->pool, "DBD: No driver for %s", svr->name); + return apr_psprintf(cmd->pool, "DBD: No driver for %s", cfg->name); case APR_EDSOOPEN: return apr_psprintf(cmd->pool, "DBD: Can't load driver file apr_dbd_%s.so", - svr->name); + cfg->name); case APR_ESYMNOTFOUND: return apr_psprintf(cmd->pool, "DBD: Failed to load driver apr_dbd_%s_driver", - svr->name); + cfg->name); } break; case cmd_params: - svr->params = val; + cfg->params = val; break; #if APR_HAS_THREADS case cmd_min: ISINT(val); - svr->nmin = atoi(val); - svr->set |= NMIN_SET; + cfg->nmin = atoi(val); + cfg->set |= NMIN_SET; break; case cmd_keep: ISINT(val); - svr->nkeep = atoi(val); - svr->set |= NKEEP_SET; + cfg->nkeep = atoi(val); + cfg->set |= NKEEP_SET; break; case cmd_max: ISINT(val); - svr->nmax = atoi(val); - svr->set |= NMAX_SET; + cfg->nmax = atoi(val); + cfg->set |= NMAX_SET; break; case cmd_exp: ISINT(val); - svr->exptime = atoi(val); - svr->set |= EXPTIME_SET; + cfg->exptime = atoi(val); + cfg->set |= EXPTIME_SET; break; #endif } @@ -202,7 +215,7 @@ static const char *dbd_param_flag(cmd_parms *cmd, void *dconf, int flag) switch ((long) cmd->info) { case cmd_persist: - svr->persist = flag; + svr->cfg->persist = flag; break; } @@ -212,6 +225,11 @@ static const char *dbd_param_flag(cmd_parms *cmd, void *dconf, int flag) static const char *dbd_prepare(cmd_parms *cmd, void *dconf, const char *query, const char *label) { + if (!label) { + label = query; + query = ""; + } + ap_dbd_prepare(cmd->server, query, label); return NULL; @@ -224,8 +242,9 @@ static const command_rec dbd_cmds[] = { "SQL Driver Params"), AP_INIT_FLAG("DBDPersist", dbd_param_flag, (void*)cmd_persist, RSRC_CONF, "Use persistent connection/pool"), - AP_INIT_TAKE2("DBDPrepareSQL", dbd_prepare, NULL, RSRC_CONF, - "SQL statement to prepare and label"), + AP_INIT_TAKE12("DBDPrepareSQL", dbd_prepare, NULL, RSRC_CONF, + "SQL statement to prepare (or nothing, to override " + "statement inherited from main server) and label"), #if APR_HAS_THREADS AP_INIT_TAKE1("DBDMin", dbd_param, (void*)cmd_min, RSRC_CONF, "Minimum number of connections"), @@ -244,57 +263,158 @@ static const command_rec dbd_cmds[] = { static int dbd_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp) { - dbd_prepared_defns = apr_hash_make(ptemp); + config_pool = pconf; + group_list = NULL; return OK; } DBD_DECLARE_NONSTD(void) ap_dbd_prepare(server_rec *s, const char *query, const char *label) { - dbd_prepared *prepared = apr_pcalloc(s->process->pool, - sizeof(dbd_prepared)); - const char *key = apr_psprintf(s->process->pool, "%pp", s); + svr_cfg *svr; - prepared->label = label; - prepared->query = query; - prepared->next = apr_hash_get(dbd_prepared_defns, key, APR_HASH_KEY_STRING); + svr = ap_get_module_config(s->module_config, &dbd_module); + if (!svr) { + /* some modules may call from within config directive handlers, and + * if these are called in a server context that contains no mod_dbd + * config directives, then we have to create our own server config + */ + svr = create_dbd_config(config_pool, s); + ap_set_module_config(s->module_config, &dbd_module, svr); + } + + if (apr_hash_get(svr->cfg->queries, label, APR_HASH_KEY_STRING) + && strcmp(query, "")) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, + "conflicting SQL statements with label %s", label); + } - apr_hash_set(dbd_prepared_defns, key, APR_HASH_KEY_STRING, prepared); + apr_hash_set(svr->cfg->queries, label, APR_HASH_KEY_STRING, query); } +typedef struct { + const char *label, *query; +} dbd_query_t; + static int dbd_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { server_rec *sp; + apr_array_header_t *add_queries = apr_array_make(ptemp, 10, + sizeof(dbd_query_t)); for (sp = s; sp; sp = sp->next) { svr_cfg *svr = ap_get_module_config(sp->module_config, &dbd_module); - const char *key = apr_psprintf(ptemp, "%pp", s); + dbd_cfg_t *cfg = svr->cfg; + apr_hash_index_t *hi_first = apr_hash_first(ptemp, cfg->queries); + dbd_group_t *group; + + /* dbd_setup in 2.2.3 and under was causing spurious error messages + * when dbd isn't configured. We can stop that with a quick check here + * together with a similar check in ap_dbd_open (where being + * unconfigured is a genuine error that must be reported). + */ + if (cfg->name == no_dbdriver || !cfg->persist) { + continue; + } + + for (group = group_list; group; group = group->next) { + dbd_cfg_t *group_cfg = group->cfg; + apr_hash_index_t *hi; + int group_ok = 1; + + if (strcmp(cfg->name, group_cfg->name) + || strcmp(cfg->params, group_cfg->params)) { + continue; + } + +#if APR_HAS_THREADS + if (cfg->nmin != group_cfg->nmin + || cfg->nkeep != group_cfg->nkeep + || cfg->nmax != group_cfg->nmax + || cfg->exptime != group_cfg->exptime) { + continue; + } +#endif + + add_queries->nelts = 0; + + for (hi = hi_first; hi; hi = apr_hash_next(hi)) { + const char *label, *query; + const char *group_query; + + apr_hash_this(hi, (void*) &label, NULL, (void*) &query); + + group_query = apr_hash_get(group_cfg->queries, label, + APR_HASH_KEY_STRING); + + if (!group_query) { + dbd_query_t *add_query = apr_array_push(add_queries); + + add_query->label = label; + add_query->query = query; + } + else if (strcmp(query, group_query)) { + group_ok = 0; + break; + } + } + + if (group_ok) { + int i; + + for (i = 0; i < add_queries->nelts; ++i) { + dbd_query_t *add_query = ((dbd_query_t*) add_queries->elts) + + i; - svr->prepared = apr_hash_get(dbd_prepared_defns, key, - APR_HASH_KEY_STRING); + apr_hash_set(group_cfg->queries, add_query->label, + APR_HASH_KEY_STRING, add_query->query); + } + + svr->group = group; + break; + } + } + + if (!svr->group) { + svr->group = group = apr_pcalloc(pconf, sizeof(dbd_group_t)); + + group->cfg = cfg; + + group->next = group_list; + group_list = group; + } } return OK; } -static apr_status_t dbd_prepared_init(apr_pool_t *pool, svr_cfg *svr, +static apr_status_t dbd_prepared_init(apr_pool_t *pool, dbd_cfg_t *cfg, ap_dbd_t *rec) { - dbd_prepared *p; + apr_hash_index_t *hi; apr_status_t rv = APR_SUCCESS; - apr_dbd_prepared_t *stmt; rec->prepared = apr_hash_make(pool); - for (p = svr->prepared; p; p = p->next) { + for (hi = apr_hash_first(pool, cfg->queries); hi; + hi = apr_hash_next(hi)) { + const char *label, *query; + apr_dbd_prepared_t *stmt; + + apr_hash_this(hi, (void*) &label, NULL, (void*) &query); + + if (!strcmp(query, "")) { + continue; + } + stmt = NULL; - if (apr_dbd_prepare(rec->driver, pool, rec->handle, p->query, - p->label, &stmt) == 0) { - apr_hash_set(rec->prepared, p->label, APR_HASH_KEY_STRING, stmt); + if (apr_dbd_prepare(rec->driver, pool, rec->handle, query, + label, &stmt)) { + rv = APR_EGENERAL; } else { - rv = APR_EGENERAL; + apr_hash_set(rec->prepared, label, APR_HASH_KEY_STRING, stmt); } } @@ -311,9 +431,9 @@ static apr_status_t dbd_close(void *data) #if APR_HAS_THREADS static apr_status_t dbd_destruct(void *data, void *params, apr_pool_t *pool) { - svr_cfg *svr = params; + dbd_group_t *group = params; - if (!svr->destroyed) { + if (!group->destroyed) { ap_dbd_t *rec = data; apr_pool_destroy(rec->pool); @@ -330,14 +450,15 @@ static apr_status_t dbd_destruct(void *data, void *params, apr_pool_t *pool) static apr_status_t dbd_construct(void **data_ptr, void *params, apr_pool_t *pool) { - svr_cfg *svr = params; + dbd_group_t *group = params; + dbd_cfg_t *cfg = group->cfg; apr_pool_t *rec_pool, *prepared_pool; ap_dbd_t *rec; apr_status_t rv; rv = apr_pool_create(&rec_pool, pool); if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, svr->server, + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->server, "DBD: Failed to create memory pool"); return rv; } @@ -351,24 +472,24 @@ static apr_status_t dbd_construct(void **data_ptr, * our pool, which is probably not what we want. Error checking isn't * necessary now, but in case that changes in the future ... */ - rv = apr_dbd_get_driver(rec->pool, svr->name, &rec->driver); + rv = apr_dbd_get_driver(rec->pool, cfg->name, &rec->driver); if (rv != APR_SUCCESS) { switch (rv) { case APR_ENOTIMPL: - ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server, - "DBD: driver for %s not available", svr->name); + ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, + "DBD: driver for %s not available", cfg->name); break; case APR_EDSOOPEN: - ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server, - "DBD: can't find driver for %s", svr->name); + ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, + "DBD: can't find driver for %s", cfg->name); break; case APR_ESYMNOTFOUND: - ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server, + ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, "DBD: driver for %s is invalid or corrupted", - svr->name); + cfg->name); break; default: - ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server, + ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, "DBD: mod_dbd not compatible with APR in get_driver"); break; } @@ -377,15 +498,15 @@ static apr_status_t dbd_construct(void **data_ptr, return rv; } - rv = apr_dbd_open(rec->driver, rec->pool, svr->params, &rec->handle); + rv = apr_dbd_open(rec->driver, rec->pool, cfg->params, &rec->handle); if (rv != APR_SUCCESS) { switch (rv) { case APR_EGENERAL: - ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server, - "DBD: Can't connect to %s", svr->name); + ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, + "DBD: Can't connect to %s", cfg->name); break; default: - ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server, + ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, "DBD: mod_dbd not compatible with APR in open"); break; } @@ -402,17 +523,17 @@ static apr_status_t dbd_construct(void **data_ptr, */ rv = apr_pool_create(&prepared_pool, rec->pool); if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, svr->server, + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->server, "DBD: Failed to create memory pool"); apr_pool_destroy(rec->pool); return rv; } - rv = dbd_prepared_init(prepared_pool, svr, rec); + rv = dbd_prepared_init(prepared_pool, cfg, rec); if (rv != APR_SUCCESS) { const char *errmsg = apr_dbd_error(rec->driver, rec->handle, rv); - ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server, + ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, "DBD: failed to prepare SQL statements: %s", (errmsg ? errmsg : "[???]")); @@ -428,15 +549,16 @@ static apr_status_t dbd_construct(void **data_ptr, #if APR_HAS_THREADS static apr_status_t dbd_destroy(void *data) { - svr_cfg *svr = data; + dbd_group_t *group = data; - svr->destroyed = 1; + group->destroyed = 1; return APR_SUCCESS; } -static apr_status_t dbd_setup(server_rec *s, svr_cfg *svr) +static apr_status_t dbd_setup(server_rec *s, dbd_group_t *group) { + dbd_cfg_t *cfg = group->cfg; apr_status_t rv; /* We create the reslist using a sub-pool of the pool passed to our @@ -457,18 +579,18 @@ static apr_status_t dbd_setup(server_rec *s, svr_cfg *svr) * on each resource, which would then attempt to destroy the sub-pools * a second time. */ - rv = apr_reslist_create(&svr->reslist, - svr->nmin, svr->nkeep, svr->nmax, - apr_time_from_sec(svr->exptime), - dbd_construct, dbd_destruct, svr, - svr->pool); + rv = apr_reslist_create(&group->reslist, + cfg->nmin, cfg->nkeep, cfg->nmax, + apr_time_from_sec(cfg->exptime), + dbd_construct, dbd_destruct, group, + group->pool); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "DBD: failed to initialise"); return rv; } - apr_pool_cleanup_register(svr->pool, svr, dbd_destroy, + apr_pool_cleanup_register(group->pool, group, dbd_destroy, apr_pool_cleanup_null); return APR_SUCCESS; @@ -477,74 +599,69 @@ static apr_status_t dbd_setup(server_rec *s, svr_cfg *svr) static apr_status_t dbd_setup_init(apr_pool_t *pool, server_rec *s) { - svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module); - apr_status_t rv; - - /* dbd_setup in 2.2.3 and under was causing spurious error messages - * when dbd isn't configured. We can stop that with a quick check here - * together with a similar check in ap_dbd_open (where being - * unconfigured is a genuine error that must be reported). - */ - if (svr->name == no_dbdriver) { - return APR_SUCCESS; - } + dbd_group_t *group; + apr_status_t rv = APR_SUCCESS; - if (!svr->persist) { - return APR_SUCCESS; - } + for (group = group_list; group; group = group->next) { + apr_status_t rv2; - rv = apr_pool_create(&svr->pool, pool); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, - "DBD: Failed to create reslist cleanup memory pool"); - return rv; - } + rv2 = apr_pool_create(&group->pool, pool); + if (rv2 != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv2, s, + "DBD: Failed to create reslist cleanup memory pool"); + return rv2; + } #if APR_HAS_THREADS - rv = dbd_setup(s, svr); - if (rv == APR_SUCCESS) { - return rv; - } + rv2 = dbd_setup(s, group); + if (rv2 == APR_SUCCESS) { + continue; + } + else if (rv == APR_SUCCESS) { + rv = rv2; + } - /* we failed, so create a mutex so that subsequent competing callers - * to ap_dbd_open can serialize themselves while they retry - */ - rv = apr_thread_mutex_create(&svr->mutex, - APR_THREAD_MUTEX_DEFAULT, pool); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, - "DBD: Failed to create thread mutex"); - } + /* we failed, so create a mutex so that subsequent competing callers + * to ap_dbd_open can serialize themselves while they retry + */ + rv2 = apr_thread_mutex_create(&group->mutex, + APR_THREAD_MUTEX_DEFAULT, pool); + if (rv2 != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv2, s, + "DBD: Failed to create thread mutex"); + return rv2; + } #endif + } return rv; } #if APR_HAS_THREADS -static apr_status_t dbd_setup_lock(server_rec *s, svr_cfg *svr) +static apr_status_t dbd_setup_lock(server_rec *s, dbd_group_t *group) { apr_status_t rv = APR_SUCCESS, rv2; /* several threads could be here at the same time, all trying to * initialize the reslist because dbd_setup_init failed to do so */ - if (!svr->mutex) { + if (!group->mutex) { /* we already logged an error when the mutex couldn't be created */ return APR_EGENERAL; } - rv2 = apr_thread_mutex_lock(svr->mutex); + rv2 = apr_thread_mutex_lock(group->mutex); if (rv2 != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s, "DBD: Failed to acquire thread mutex"); return rv2; } - if (!svr->reslist) { - rv = dbd_setup(s, svr); + if (!group->reslist) { + rv = dbd_setup(s, group); } - rv2 = apr_thread_mutex_unlock(svr->mutex); + rv2 = apr_thread_mutex_unlock(group->mutex); if (rv2 != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s, "DBD: Failed to release thread mutex"); @@ -565,12 +682,12 @@ DBD_DECLARE_NONSTD(void) ap_dbd_close(server_rec *s, ap_dbd_t *rec) { svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module); - if (!svr->persist) { + if (!svr->cfg->persist) { apr_pool_destroy(rec->pool); } #if APR_HAS_THREADS else { - apr_reslist_release(svr->reslist, rec); + apr_reslist_release(svr->group->reslist, rec); } #endif } @@ -592,38 +709,44 @@ static apr_status_t dbd_check(apr_pool_t *pool, server_rec *s, ap_dbd_t *rec) svr = ap_get_module_config(s->module_config, &dbd_module); ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "DBD [%s] Error: %s", svr->name, errmsg); + "DBD [%s] Error: %s", svr->cfg->name, errmsg); return rv; } DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_open(apr_pool_t *pool, server_rec *s) { svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module); + dbd_group_t *group = svr->group; + dbd_cfg_t *cfg = svr->cfg; ap_dbd_t *rec = NULL; #if APR_HAS_THREADS apr_status_t rv; #endif /* If nothing is configured, we shouldn't be here */ - if (svr->name == no_dbdriver) { + if (cfg->name == no_dbdriver) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "DBD: not configured"); return NULL; } - if (!svr->persist) { + if (!cfg->persist) { /* Return a once-only connection */ - dbd_construct((void*) &rec, svr, pool); + group = apr_pcalloc(pool, sizeof(dbd_group_t)); + + group->cfg = cfg; + + dbd_construct((void*) &rec, group, pool); return rec; } #if APR_HAS_THREADS - if (!svr->reslist) { - if (dbd_setup_lock(s, svr) != APR_SUCCESS) { + if (!group->reslist) { + if (dbd_setup_lock(s, group) != APR_SUCCESS) { return NULL; } } - rv = apr_reslist_acquire(svr->reslist, (void*) &rec); + rv = apr_reslist_acquire(group->reslist, (void*) &rec); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "Failed to acquire DBD connection from pool!"); @@ -631,15 +754,15 @@ DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_open(apr_pool_t *pool, server_rec *s) } if (dbd_check(pool, s, rec) != APR_SUCCESS) { - apr_reslist_invalidate(svr->reslist, rec); + apr_reslist_invalidate(group->reslist, rec); return NULL; } #else /* If we have a persistent connection and it's good, we'll use it; * since this is non-threaded, we can update without a mutex */ - rec = svr->rec; - if (rec) { + rec = group->rec; + if (rec) { if (dbd_check(pool, s, rec) != APR_SUCCESS) { apr_pool_destroy(rec->pool); rec = NULL; @@ -648,8 +771,8 @@ DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_open(apr_pool_t *pool, server_rec *s) /* We don't have a connection right now, so we'll open one */ if (!rec) { - dbd_construct((void*) &rec, svr, svr->pool); - svr->rec = rec; + dbd_construct((void*) &rec, group, group->pool); + group->rec = rec; } #endif @@ -691,8 +814,8 @@ DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_acquire(request_rec *r) &dbd_module); ap_set_module_config(r->request_config, &dbd_module, acq); - if (svr->persist) { - acq->reslist = svr->reslist; + if (svr->cfg->persist) { + acq->reslist = svr->group->reslist; apr_pool_cleanup_register(r->pool, acq, dbd_release, apr_pool_cleanup_null); } @@ -714,8 +837,8 @@ DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_cacquire(conn_rec *c) &dbd_module); ap_set_module_config(c->conn_config, &dbd_module, acq); - if (svr->persist) { - acq->reslist = svr->reslist; + if (svr->cfg->persist) { + acq->reslist = svr->group->reslist; apr_pool_cleanup_register(c->pool, acq, dbd_release, apr_pool_cleanup_null); }