mod_dbd.c revision 1ec08bba27851a4ffca9e6eb88d5c01b5fb6affb
842ae4bd224140319ae7feec1872b93dfd491143fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding * contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding * this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding * The ASF licenses this file to You under the Apache License, Version 2.0
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"); you may not use this file except in compliance with
842ae4bd224140319ae7feec1872b93dfd491143fielding * the License. You may obtain a copy of the License at
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * Unless required by applicable law or agreed to in writing, software
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * distributed under the License is distributed on an "AS IS" BASIS,
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * See the License for the specific language governing permissions and
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * limitations under the License.
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb/* Overview of what this is and does:
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh/************ svr cfg: manage db connection pool ****************/
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianhtypedef struct {
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh const char *name;
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh const char *params;
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbbtypedef struct {
44da058d96ca5577a8b9fe7d6b89d79fe9a0a849wrowe/* a default DBDriver value that'll generate meaningful error messages */
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowestatic const char *const no_dbdriver = "[DBDriver unset]";
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe/* A default nmin of >0 will help with generating meaningful
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe * startup error messages if the database is down.
44da058d96ca5577a8b9fe7d6b89d79fe9a0a849wrowestatic void *create_dbd_config(apr_pool_t *pool, server_rec *s)
efa1a34b0a7785fc72863eff175b0cfc1ecb0e38wrowe dbd_cfg_t *cfg = svr->cfg = apr_pcalloc(pool, sizeof(dbd_cfg_t));
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe cfg->name = no_dbdriver; /* to generate meaningful error messages */
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb cfg->params = ""; /* don't risk segfault on misconfiguration */
59d7dc153347a9f606c5712f0fae7b65e96682d9rbbstatic void *merge_dbd_config(apr_pool_t *pool, void *basev, void *addv)
dd95dce618f5c95c71733a363f7e3c8acb02f8d4rbb dbd_cfg_t *new = svr->cfg = apr_pcalloc(pool, sizeof(dbd_cfg_t));
f0c7e2f3f183d7c289eb176434d68a922b66a008wrowe new->name = (add->name != no_dbdriver) ? add->name : base->name;
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe new->params = strcmp(add->params, "") ? add->params : base->params;
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb new->persist = (add->persist != -1) ? add->persist : base->persist;
0ec08ecdcb42129d147888bda504787b164da39cerikabele new->nmin = (add->set&NMIN_SET) ? add->nmin : base->nmin;
0ec08ecdcb42129d147888bda504787b164da39cerikabele new->nkeep = (add->set&NKEEP_SET) ? add->nkeep : base->nkeep;
0ec08ecdcb42129d147888bda504787b164da39cerikabele new->nmax = (add->set&NMAX_SET) ? add->nmax : base->nmax;
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb new->exptime = (add->set&EXPTIME_SET) ? add->exptime : base->exptime;
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb new->queries = apr_hash_overlay(pool, add->queries, base->queries);
2d2eda71267231c2526be701fe655db125852c1ffielding const char *p; \
2d2eda71267231c2526be701fe655db125852c1ffielding for (p = val; *p; ++p) { \
2d2eda71267231c2526be701fe655db125852c1ffielding if (!apr_isdigit(*p)) { \
2d2eda71267231c2526be701fe655db125852c1ffielding return "Argument must be numeric!"; \
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb } while (0)
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbbstatic const char *dbd_param(cmd_parms *cmd, void *dconf, const char *val)
3d96ee83babeec32482c9082c9426340cee8c44dwrowe svr_cfg *svr = ap_get_module_config(cmd->server->module_config,
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb /* loading the driver involves once-only dlloading that is
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb * best done at server startup. This also guarantees that
3d96ee83babeec32482c9082c9426340cee8c44dwrowe * we won't return an error later.
299509b1b45b2fc814f1d57bf93171439295b25ewrowe switch (apr_dbd_get_driver(cmd->pool, cfg->name, &driver)) {
299509b1b45b2fc814f1d57bf93171439295b25ewrowe return apr_psprintf(cmd->pool, "DBD: No driver for %s", cfg->name);
299509b1b45b2fc814f1d57bf93171439295b25ewrowe "DBD: Can't load driver file dbd%s.nlm",
299509b1b45b2fc814f1d57bf93171439295b25ewrowe "DBD: Can't load driver file apr_dbd_%s.so",
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb "DBD: Failed to load driver apr_dbd_%s_driver",
3d96ee83babeec32482c9082c9426340cee8c44dwrowestatic const char *dbd_param_flag(cmd_parms *cmd, void *dconf, int flag)
798c7c11dc2fe3b08e591e9c76fc1a84857f2cd4jerenkrantz svr_cfg *svr = ap_get_module_config(cmd->server->module_config,
798c7c11dc2fe3b08e591e9c76fc1a84857f2cd4jerenkrantzstatic const char *dbd_prepare(cmd_parms *cmd, void *dconf, const char *query,
798c7c11dc2fe3b08e591e9c76fc1a84857f2cd4jerenkrantz const char *label)
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh AP_INIT_TAKE1("DBDriver", dbd_param, (void*)cmd_name, RSRC_CONF,
2d2eda71267231c2526be701fe655db125852c1ffielding "SQL Driver"),
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh AP_INIT_TAKE1("DBDParams", dbd_param, (void*)cmd_params, RSRC_CONF,
a623efbff95aab78da9e030524b0fa69b054f6d0brianp "SQL Driver Params"),
a623efbff95aab78da9e030524b0fa69b054f6d0brianp AP_INIT_FLAG("DBDPersist", dbd_param_flag, (void*)cmd_persist, RSRC_CONF,
a623efbff95aab78da9e030524b0fa69b054f6d0brianp "Use persistent connection/pool"),
a623efbff95aab78da9e030524b0fa69b054f6d0brianp AP_INIT_TAKE12("DBDPrepareSQL", dbd_prepare, NULL, RSRC_CONF,
a623efbff95aab78da9e030524b0fa69b054f6d0brianp "SQL statement to prepare (or nothing, to override "
a623efbff95aab78da9e030524b0fa69b054f6d0brianp "statement inherited from main server) and label"),
a623efbff95aab78da9e030524b0fa69b054f6d0brianp AP_INIT_TAKE1("DBDMin", dbd_param, (void*)cmd_min, RSRC_CONF,
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb "Minimum number of connections"),
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb /* XXX: note that mod_proxy calls this "smax" */
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb AP_INIT_TAKE1("DBDKeep", dbd_param, (void*)cmd_keep, RSRC_CONF,
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb "Maximum number of sustained connections"),
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb AP_INIT_TAKE1("DBDMax", dbd_param, (void*)cmd_max, RSRC_CONF,
3d96ee83babeec32482c9082c9426340cee8c44dwrowe "Maximum number of connections"),
2d2eda71267231c2526be701fe655db125852c1ffielding /* XXX: note that mod_proxy calls this "ttl" (time to live) */
2d2eda71267231c2526be701fe655db125852c1ffielding AP_INIT_TAKE1("DBDExptime", dbd_param, (void*)cmd_exp, RSRC_CONF,
3ef7956b993aff4b4882c643910fb688a0e707e3ben "Keepalive time for idle connections"),
b45c1c292ff1fa635004ae81fa691f8cb3cdda85rbbstatic int dbd_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbbDBD_DECLARE_NONSTD(void) ap_dbd_prepare(server_rec *s, const char *query,
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb const char *label)
42ce672c516baf6e4eaed18ccc1647de2d456d8edougm svr = ap_get_module_config(s->module_config, &dbd_module);
a2a0abd88b19e042a3eb2a9fa1702c25ad51303dwrowe /* some modules may call from within config directive handlers, and
a2a0abd88b19e042a3eb2a9fa1702c25ad51303dwrowe * if these are called in a server context that contains no mod_dbd
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh * config directives, then we have to create our own server config
a2a0abd88b19e042a3eb2a9fa1702c25ad51303dwrowe ap_set_module_config(s->module_config, &dbd_module, svr);
e8eee56a2ea20f673e5942fb58e1426a7561c7acstas if (apr_hash_get(svr->cfg->queries, label, APR_HASH_KEY_STRING)
a2a0abd88b19e042a3eb2a9fa1702c25ad51303dwrowe apr_hash_set(svr->cfg->queries, label, APR_HASH_KEY_STRING, query);
8476daed795d573496033d88015364df09fe9c68gsteintypedef struct {
8476daed795d573496033d88015364df09fe9c68gsteinstatic int dbd_post_config(apr_pool_t *pconf, apr_pool_t *plog,
3ef7956b993aff4b4882c643910fb688a0e707e3ben apr_array_header_t *add_queries = apr_array_make(ptemp, 10,
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb svr_cfg *svr = ap_get_module_config(sp->module_config, &dbd_module);
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb apr_hash_index_t *hi_first = apr_hash_first(ptemp, cfg->queries);
3ef7956b993aff4b4882c643910fb688a0e707e3ben /* dbd_setup in 2.2.3 and under was causing spurious error messages
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb * when dbd isn't configured. We can stop that with a quick check here
42ce672c516baf6e4eaed18ccc1647de2d456d8edougm * together with a similar check in ap_dbd_open (where being
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb * unconfigured is a genuine error that must be reported).
4743e6e0c6d5bc44f086d4f0032ae41a68192dd1rbb apr_hash_this(hi, (void*) &label, NULL, (void*) &query);
a623efbff95aab78da9e030524b0fa69b054f6d0brianp dbd_query_t *add_query = ((dbd_query_t*) add_queries->elts)
a623efbff95aab78da9e030524b0fa69b054f6d0brianp svr->group = group = apr_pcalloc(pconf, sizeof(dbd_group_t));
2d2eda71267231c2526be701fe655db125852c1ffieldingstatic apr_status_t dbd_prepared_init(apr_pool_t *pool, dbd_cfg_t *cfg,
return rv;
#if APR_HAS_THREADS
return APR_SUCCESS;
return rv;
switch (rv) {
case APR_ENOTIMPL:
case APR_EDSOOPEN:
case APR_ESYMNOTFOUND:
return rv;
switch (rv) {
case APR_EGENERAL:
return rv;
return rv;
return rv;
return APR_SUCCESS;
#if APR_HAS_THREADS
return APR_SUCCESS;
return rv;
return APR_SUCCESS;
return rv2;
#if APR_HAS_THREADS
return rv2;
return rv;
#if APR_HAS_THREADS
return APR_EGENERAL;
return rv2;
return rv;
#if APR_HAS_THREADS
const char *errmsg;
return APR_SUCCESS;
if (!errmsg) {
return rv;
#if APR_HAS_THREADS
return NULL;
return rec;
#if APR_HAS_THREADS
return NULL;
return NULL;
return NULL;
if (rec) {
if (!rec) {
return rec;
#if APR_HAS_THREADS
return APR_SUCCESS;
while (!ap_is_initial_req(r)) {
if (r->prev) {
r = r->prev;
else if (r->main) {
r = r->main;
if (!acq) {
&dbd_module);
if (!acq) {
&dbd_module);
while (!ap_is_initial_req(r)) {
if (r->prev) {
r = r->prev;
else if (r->main) {
r = r->main;
if (!rec) {
if (rec) {
return rec;
if (!rec) {
if (rec) {
return rec;
NULL,
NULL,