/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/
/* a default DBDriver value that'll generate meaningful error messages */ staticconstchar *const no_dbdriver = "[DBDriver unset]";
/* A default nmin of >0 will help with generating meaningful * startup error messages if the database is down.
*/ #define DEFAULT_NMIN 1 #define DEFAULT_NKEEP 2 #define DEFAULT_NMAX 10 #define DEFAULT_EXPTIME 300
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);
}
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);
}
/* 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;
}
/* an apr_reslist_constructor for SQL connections * Also use this for opening in non-reslist modes, since it gives * us all the error-handling in one place.
*/ static apr_status_t dbd_construct(void **data_ptr, void *params, apr_pool_t *pool)
{
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; constchar *err = "";
/* The driver is loaded at config time now, so this just checks a hash. * If that changes, the driver DSO could be registered to unload against * 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, cfg->name, &rec->driver); if (rv != APR_SUCCESS) { if (APR_STATUS_IS_ENOTIMPL(rv)) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, APLOGNO(00625) "driver for %s not available", cfg->name);
} elseif (APR_STATUS_IS_EDSOOPEN(rv)) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, APLOGNO(00626) "can't find driver for %s", cfg->name);
} elseif (APR_STATUS_IS_ESYMNOTFOUND(rv)) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, APLOGNO(00627) "driver for %s is invalid or corrupted",
cfg->name);
} else {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, APLOGNO(00628) "mod_dbd not compatible with APR in get_driver");
}
apr_pool_destroy(rec->pool); return rv;
}
rv = apr_dbd_open_ex(rec->driver, rec->pool, cfg->params, &rec->handle, &err); if (rv != APR_SUCCESS) { switch (rv) { case APR_EGENERAL:
ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, APLOGNO(00629) "Can't connect to %s: %s", cfg->name, err); break; default:
ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, APLOGNO(00630) "mod_dbd not compatible with APR in open"); break;
}
/* we use a sub-pool for the prepared statements for each connection so * that they will be cleaned up first, before the connection is closed
*/
rv = apr_pool_create(&prepared_pool, rec->pool); if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->server, APLOGNO(00631) "Failed to create memory pool");
/* We create the reslist using a sub-pool of the pool passed to our * child_init hook. No other threads can be here because we're * either in the child_init phase or dbd_setup_lock() acquired our mutex. * No other threads will use this sub-pool after this, except via * reslist calls, which have an internal mutex. * * We need to short-circuit the cleanup registered internally by * apr_reslist_create(). We do this by registering dbd_destroy() * as a cleanup afterwards, so that it will run before the reslist's * internal cleanup. * * If we didn't do this, then we could free memory twice when the pool * was destroyed. When apr_pool_destroy() runs, it first destroys all * all the per-connection sub-pools created in dbd_construct(), and * then it runs the reslist's cleanup. The cleanup calls dbd_destruct() * on each resource, which would then attempt to destroy the sub-pools * a second time.
*/
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, APLOGNO(00633) "failed to initialise"); return rv;
}
/* 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, APLOGNO(00635) "Failed to create thread mutex"); return rv2;
} #endif
}
/* several threads could be here at the same time, all trying to * initialize the reslist because dbd_setup_init failed to do so
*/ if (!group->mutex) { /* we already logged an error when the mutex couldn't be created */ return APR_EGENERAL;
}
if (!group->reslist) {
rv = dbd_setup(s, group);
}
rv2 = apr_thread_mutex_unlock(group->mutex); if (rv2 != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s, APLOGNO(00638) "Failed to release thread mutex"); if (rv == APR_SUCCESS) {
rv = rv2;
}
}
return rv;
} #endif
/* Functions we export for modules to use: - open acquires a connection from the pool (opens one if necessary) - close releases it back in to the pool
*/
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);
/* we don't have a driver-specific error code, so we'll just pass * a "success" value and rely on the driver to ignore it
*/
errmsg = apr_dbd_error(rec->driver, rec->handle, 0); if (!errmsg) {
errmsg = "(unknown)";
}
/* If nothing is configured, we shouldn't be here */ if (cfg->name == no_dbdriver) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02654) "not configured"); return NULL;
}
if (!cfg->persist) { /* Return a once-only connection */
group = apr_pcalloc(pool, sizeof(dbd_group_t));
#if APR_HAS_THREADS if (!group->reslist) { if (dbd_setup_lock(s, group) != APR_SUCCESS) { return NULL;
}
}
rv = apr_reslist_acquire(group->reslist, (void*) &rec); if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(02655) "Failed to acquire DBD connection from pool!"); return NULL;
}
if (dbd_check(pool, s, rec) != APR_SUCCESS) {
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 = group->rec; if (rec) { if (dbd_check(pool, s, rec) != APR_SUCCESS) {
apr_pool_destroy(rec->pool);
rec = NULL;
}
}
/* We don't have a connection right now, so we'll open one */ if (!rec) {
dbd_construct((void*) &rec, group, group->pool);
group->rec = rec;
} #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.