/[Apache-SVN]/httpd/httpd/trunk/modules/database/mod_dbd.c
ViewVC logotype

Contents of /httpd/httpd/trunk/modules/database/mod_dbd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 496831 - (hide annotations)
Tue Jan 16 19:36:26 2007 UTC (2 years, 10 months ago) by chrisd
File MIME type: text/plain
File size: 23593 byte(s)
We now create memory sub-pools for each DB connection and close DB
connections in a pool cleanup function.  This simplifies the ap_dbd_acquire()
and ap_dbd_cacquire() functions, and also stops us from leaking ap_dbd_t
structures when using reslists.

We ensure that prepared statements are destroyed before their DB connection
is closed, in case any drivers would have problems cleaning up prepared
statements after the DB connection is closed.

The combination of reslists and memory pool cleanup functions was causing
segfaults when child processes exited, as reported in PR 39985.  To prevent
this, we register dbd_destroy() as a cleanup that will execute prior to
the internal cleanup function registered by apr_reslist_create().  When the
reslist's memory pool is destroyed, dbd_destroy() informs dbd_destruct() not
to do anything when subsequently called by the reslist's internal cleanup
function.

We avoid the use of s->process->pool (the global pool) since it isn't
destroyed by exiting child processes in most multi-process MPMs.
1 fielding 420983 /* Licensed to the Apache Software Foundation (ASF) under one or more
2     * contributor license agreements. See the NOTICE file distributed with
3     * this work for additional information regarding copyright ownership.
4     * The ASF licenses this file to You under the Apache License, Version 2.0
5     * (the "License"); you may not use this file except in compliance with
6     * the License. You may obtain a copy of the License at
7 niq 170729 *
8     * http://www.apache.org/licenses/LICENSE-2.0
9     *
10     * Unless required by applicable law or agreed to in writing, software
11     * distributed under the License is distributed on an "AS IS" BASIS,
12     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     * See the License for the specific language governing permissions and
14     * limitations under the License.
15     */
16    
17     /* Overview of what this is and does:
18     * http://www.apache.org/~niq/dbd.html
19     * or
20     * http://apache.webthing.com/database/
21     */
22    
23 chrisd 491884 #include "apr_reslist.h"
24     #include "apr_strings.h"
25     #include "apr_hash.h"
26     #include "apr_lib.h"
27     #include "apr_dbd.h"
28 niq 170729
29 chrisd 491884 #define APR_WANT_MEMFUNC
30     #define APR_WANT_STRFUNC
31     #include "apr_want.h"
32    
33 niq 170729 #include "http_protocol.h"
34     #include "http_config.h"
35     #include "http_log.h"
36 rpluem 483630 #include "http_request.h"
37 niq 170729 #include "mod_dbd.h"
38 niq 290711
39 niq 170729 extern module AP_MODULE_DECLARE_DATA dbd_module;
40    
41     /************ svr cfg: manage db connection pool ****************/
42    
43 niq 348026 #define NMIN_SET 0x1
44     #define NKEEP_SET 0x2
45     #define NMAX_SET 0x4
46     #define EXPTIME_SET 0x8
47    
48 chrisd 491729 typedef struct dbd_prepared dbd_prepared;
49    
50     struct dbd_prepared {
51 niq 170729 const char *label;
52     const char *query;
53 chrisd 491729 dbd_prepared *next;
54     };
55    
56     typedef struct {
57 chrisd 491884 server_rec *server;
58 niq 170729 const char *name;
59     const char *params;
60     int persist;
61     dbd_prepared *prepared;
62 chrisd 496831 apr_pool_t *pool;
63 niq 170729 #if APR_HAS_THREADS
64 niq 348026 apr_thread_mutex_t *mutex;
65 chrisd 491729 apr_reslist_t *reslist;
66 chrisd 496831 int destroyed;
67 niq 170729 int nmin;
68     int nkeep;
69     int nmax;
70     int exptime;
71 chrisd 491884 int set;
72 niq 170729 #else
73 chrisd 491729 ap_dbd_t *rec;
74 niq 170729 #endif
75     } svr_cfg;
76    
77     typedef enum { cmd_name, cmd_params, cmd_persist,
78     cmd_min, cmd_keep, cmd_max, cmd_exp
79     } cmd_parts;
80    
81 niq 424798 static apr_hash_t *dbd_prepared_defns;
82    
83 niq 413015 /* a default DBDriver value that'll generate meaningful error messages */
84     static const char *const no_dbdriver = "[DBDriver unset]";
85 niq 170729
86 chrisd 491729 /* A default nmin of >0 will help with generating meaningful
87     * startup error messages if the database is down.
88     */
89     #define DEFAULT_NMIN 1
90     #define DEFAULT_NKEEP 2
91     #define DEFAULT_NMAX 10
92     #define DEFAULT_EXPTIME 300
93    
94     static void *create_dbd_config(apr_pool_t *pool, server_rec *s)
95     {
96     svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg));
97    
98 chrisd 491884 svr->server = s;
99 chrisd 491729 svr->name = no_dbdriver; /* to generate meaningful error messages */
100     svr->params = ""; /* don't risk segfault on misconfiguration */
101     svr->persist = -1;
102     #if APR_HAS_THREADS
103     svr->nmin = DEFAULT_NMIN;
104     svr->nkeep = DEFAULT_NKEEP;
105     svr->nmax = DEFAULT_NMAX;
106     svr->exptime = DEFAULT_EXPTIME;
107     #endif
108    
109     return svr;
110     }
111    
112     static void *merge_dbd_config(apr_pool_t *pool, void *basev, void *addv)
113     {
114     svr_cfg *base = (svr_cfg*) basev;
115     svr_cfg *add = (svr_cfg*) addv;
116     svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg));
117    
118 chrisd 491884 svr->server = add->server;
119 chrisd 491729 svr->name = (add->name != no_dbdriver) ? add->name : base->name;
120     svr->params = strcmp(add->params, "") ? add->params : base->params;
121 chrisd 491884 svr->persist = (add->persist != -1) ? add->persist : base->persist;
122 chrisd 491729 #if APR_HAS_THREADS
123     svr->nmin = (add->set&NMIN_SET) ? add->nmin : base->nmin;
124     svr->nkeep = (add->set&NKEEP_SET) ? add->nkeep : base->nkeep;
125     svr->nmax = (add->set&NMAX_SET) ? add->nmax : base->nmax;
126     svr->exptime = (add->set&EXPTIME_SET) ? add->exptime : base->exptime;
127     #endif
128    
129     return svr;
130     }
131    
132 chrisd 492394 #define ISINT(val) do { \
133     const char *p; \
134     \
135     for (p = val; *p; ++p) { \
136     if (!apr_isdigit(*p)) { \
137     return "Argument must be numeric!"; \
138     } \
139     } \
140     } while (0)
141 chrisd 491729
142     static const char *dbd_param(cmd_parms *cmd, void *dconf, const char *val)
143 niq 170729 {
144 niq 231464 const apr_dbd_driver_t *driver = NULL;
145 chrisd 491729 svr_cfg *svr = ap_get_module_config(cmd->server->module_config,
146     &dbd_module);
147 niq 170729
148 niq 291100 switch ((long) cmd->info) {
149 niq 170729 case cmd_name:
150     svr->name = val;
151     /* loading the driver involves once-only dlloading that is
152     * best done at server startup. This also guarantees that
153 niq 345040 * we won't return an error later.
154 niq 170729 */
155     switch (apr_dbd_get_driver(cmd->pool, svr->name, &driver)) {
156     case APR_ENOTIMPL:
157     return apr_psprintf(cmd->pool, "DBD: No driver for %s", svr->name);
158     case APR_EDSOOPEN:
159     return apr_psprintf(cmd->pool,
160     "DBD: Can't load driver file apr_dbd_%s.so",
161     svr->name);
162     case APR_ESYMNOTFOUND:
163     return apr_psprintf(cmd->pool,
164     "DBD: Failed to load driver apr_dbd_%s_driver",
165     svr->name);
166     }
167     break;
168     case cmd_params:
169     svr->params = val;
170     break;
171     #if APR_HAS_THREADS
172     case cmd_min:
173     ISINT(val);
174     svr->nmin = atoi(val);
175 niq 348026 svr->set |= NMIN_SET;
176 niq 170729 break;
177     case cmd_keep:
178     ISINT(val);
179     svr->nkeep = atoi(val);
180 niq 348026 svr->set |= NKEEP_SET;
181 niq 170729 break;
182     case cmd_max:
183     ISINT(val);
184     svr->nmax = atoi(val);
185 niq 348026 svr->set |= NMAX_SET;
186 niq 170729 break;
187     case cmd_exp:
188     ISINT(val);
189     svr->exptime = atoi(val);
190 niq 348026 svr->set |= EXPTIME_SET;
191 niq 170729 break;
192     #endif
193     }
194 chrisd 491729
195 niq 170729 return NULL;
196     }
197 chrisd 491729
198     static const char *dbd_param_flag(cmd_parms *cmd, void *dconf, int flag)
199 niq 348026 {
200 chrisd 491729 svr_cfg *svr = ap_get_module_config(cmd->server->module_config,
201     &dbd_module);
202 niq 348026
203     switch ((long) cmd->info) {
204     case cmd_persist:
205     svr->persist = flag;
206     break;
207     }
208 chrisd 491729
209 niq 348026 return NULL;
210     }
211 chrisd 491729
212     static const char *dbd_prepare(cmd_parms *cmd, void *dconf, const char *query,
213 niq 234017 const char *label)
214     {
215     ap_dbd_prepare(cmd->server, query, label);
216 chrisd 491729
217 niq 170729 return NULL;
218     }
219 chrisd 491729
220 niq 170729 static const command_rec dbd_cmds[] = {
221     AP_INIT_TAKE1("DBDriver", dbd_param, (void*)cmd_name, RSRC_CONF,
222     "SQL Driver"),
223     AP_INIT_TAKE1("DBDParams", dbd_param, (void*)cmd_params, RSRC_CONF,
224     "SQL Driver Params"),
225 niq 348026 AP_INIT_FLAG("DBDPersist", dbd_param_flag, (void*)cmd_persist, RSRC_CONF,
226     "Use persistent connection/pool"),
227 niq 170729 AP_INIT_TAKE2("DBDPrepareSQL", dbd_prepare, NULL, RSRC_CONF,
228 chrisd 491729 "SQL statement to prepare and label"),
229 niq 170729 #if APR_HAS_THREADS
230     AP_INIT_TAKE1("DBDMin", dbd_param, (void*)cmd_min, RSRC_CONF,
231     "Minimum number of connections"),
232 niq 348026 /* XXX: note that mod_proxy calls this "smax" */
233 niq 170729 AP_INIT_TAKE1("DBDKeep", dbd_param, (void*)cmd_keep, RSRC_CONF,
234     "Maximum number of sustained connections"),
235     AP_INIT_TAKE1("DBDMax", dbd_param, (void*)cmd_max, RSRC_CONF,
236     "Maximum number of connections"),
237 niq 348026 /* XXX: note that mod_proxy calls this "ttl" (time to live) */
238 niq 170729 AP_INIT_TAKE1("DBDExptime", dbd_param, (void*)cmd_exp, RSRC_CONF,
239     "Keepalive time for idle connections"),
240     #endif
241     {NULL}
242     };
243 chrisd 491729
244     static int dbd_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
245     apr_pool_t *ptemp)
246     {
247     dbd_prepared_defns = apr_hash_make(ptemp);
248     return OK;
249 niq 348026 }
250 chrisd 491729
251     DBD_DECLARE_NONSTD(void) ap_dbd_prepare(server_rec *s, const char *query,
252     const char *label)
253 niq 170729 {
254 chrisd 491729 dbd_prepared *prepared = apr_pcalloc(s->process->pool,
255     sizeof(dbd_prepared));
256     const char *key = apr_psprintf(s->process->pool, "%pp", s);
257    
258     prepared->label = label;
259     prepared->query = query;
260     prepared->next = apr_hash_get(dbd_prepared_defns, key, APR_HASH_KEY_STRING);
261    
262     apr_hash_set(dbd_prepared_defns, key, APR_HASH_KEY_STRING, prepared);
263 niq 170729 }
264 chrisd 491729
265     static int dbd_post_config(apr_pool_t *pconf, apr_pool_t *plog,
266     apr_pool_t *ptemp, server_rec *s)
267     {
268     server_rec *sp;
269    
270     for (sp = s; sp; sp = sp->next) {
271     svr_cfg *svr = ap_get_module_config(sp->module_config, &dbd_module);
272 chrisd 491884 const char *key = apr_psprintf(ptemp, "%pp", s);
273 chrisd 491729
274     svr->prepared = apr_hash_get(dbd_prepared_defns, key,
275     APR_HASH_KEY_STRING);
276     }
277    
278     return OK;
279     }
280    
281 niq 170729 static apr_status_t dbd_prepared_init(apr_pool_t *pool, svr_cfg *svr,
282 chrisd 491729 ap_dbd_t *rec)
283 niq 170729 {
284     dbd_prepared *p;
285 chrisd 491729 apr_status_t rv = APR_SUCCESS;
286 niq 344140 apr_dbd_prepared_t *stmt;
287 niq 170729
288 chrisd 491729 rec->prepared = apr_hash_make(pool);
289    
290 niq 170729 for (p = svr->prepared; p; p = p->next) {
291 niq 344140 stmt = NULL;
292 chrisd 491729 if (apr_dbd_prepare(rec->driver, pool, rec->handle, p->query,
293 niq 170729 p->label, &stmt) == 0) {
294 chrisd 491729 apr_hash_set(rec->prepared, p->label, APR_HASH_KEY_STRING, stmt);
295 niq 170729 }
296     else {
297 chrisd 491729 rv = APR_EGENERAL;
298 niq 170729 }
299     }
300 chrisd 491729
301     return rv;
302 niq 170729 }
303 chrisd 491729
304     static apr_status_t dbd_close(void *data)
305     {
306     ap_dbd_t *rec = data;
307    
308 chrisd 496831 return apr_dbd_close(rec->driver, rec->handle);
309 chrisd 491729 }
310    
311     #if APR_HAS_THREADS
312     static apr_status_t dbd_destruct(void *data, void *params, apr_pool_t *pool)
313     {
314 chrisd 496831 svr_cfg *svr = params;
315    
316     if (!svr->destroyed) {
317     ap_dbd_t *rec = data;
318    
319     apr_pool_destroy(rec->pool);
320     }
321    
322     return APR_SUCCESS;
323 chrisd 491729 }
324     #endif
325    
326 niq 234017 /* an apr_reslist_constructor for SQL connections
327     * Also use this for opening in non-reslist modes, since it gives
328     * us all the error-handling in one place.
329     */
330 chrisd 491729 static apr_status_t dbd_construct(void **data_ptr,
331     void *params, apr_pool_t *pool)
332 niq 170729 {
333 chrisd 491729 svr_cfg *svr = params;
334 chrisd 496831 apr_pool_t *rec_pool, *prepared_pool;
335     ap_dbd_t *rec;
336 niq 348026 apr_status_t rv;
337 niq 170729
338 chrisd 496831 rv = apr_pool_create(&rec_pool, pool);
339 niq 348026 if (rv != APR_SUCCESS) {
340 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, svr->server,
341     "DBD: Failed to create memory pool");
342     return rv;
343 niq 348026 }
344    
345 chrisd 496831 rec = apr_pcalloc(rec_pool, sizeof(ap_dbd_t));
346    
347     rec->pool = rec_pool;
348    
349 chrisd 491729 /* The driver is loaded at config time now, so this just checks a hash.
350     * If that changes, the driver DSO could be registered to unload against
351     * our pool, which is probably not what we want. Error checking isn't
352     * necessary now, but in case that changes in the future ...
353     */
354 niq 348026 rv = apr_dbd_get_driver(rec->pool, svr->name, &rec->driver);
355 chrisd 491729 if (rv != APR_SUCCESS) {
356     switch (rv) {
357     case APR_ENOTIMPL:
358 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,
359     "DBD: driver for %s not available", svr->name);
360 chrisd 491729 break;
361     case APR_EDSOOPEN:
362 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,
363     "DBD: can't find driver for %s", svr->name);
364 chrisd 491729 break;
365     case APR_ESYMNOTFOUND:
366 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,
367     "DBD: driver for %s is invalid or corrupted",
368     svr->name);
369 chrisd 491729 break;
370     default:
371 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,
372     "DBD: mod_dbd not compatible with APR in get_driver");
373 chrisd 491729 break;
374     }
375    
376 chrisd 491884 apr_pool_destroy(rec->pool);
377 niq 234017 return rv;
378     }
379    
380 niq 348026 rv = apr_dbd_open(rec->driver, rec->pool, svr->params, &rec->handle);
381 chrisd 491729 if (rv != APR_SUCCESS) {
382     switch (rv) {
383     case APR_EGENERAL:
384 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,
385     "DBD: Can't connect to %s", svr->name);
386 chrisd 491729 break;
387     default:
388 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,
389     "DBD: mod_dbd not compatible with APR in open");
390 chrisd 491729 break;
391     }
392    
393 chrisd 491884 apr_pool_destroy(rec->pool);
394 niq 170729 return rv;
395     }
396 chrisd 491729
397 chrisd 496831 apr_pool_cleanup_register(rec->pool, rec, dbd_close,
398     apr_pool_cleanup_null);
399    
400     /* we use a sub-pool for the prepared statements for each connection so
401     * that they will be cleaned up first, before the connection is closed
402     */
403     rv = apr_pool_create(&prepared_pool, rec->pool);
404 niq 386321 if (rv != APR_SUCCESS) {
405 chrisd 496831 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, svr->server,
406     "DBD: Failed to create memory pool");
407    
408     apr_pool_destroy(rec->pool);
409     return rv;
410     }
411    
412     rv = dbd_prepared_init(prepared_pool, svr, rec);
413     if (rv != APR_SUCCESS) {
414 niq 424798 const char *errmsg = apr_dbd_error(rec->driver, rec->handle, rv);
415 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,
416     "DBD: failed to prepare SQL statements: %s",
417     (errmsg ? errmsg : "[???]"));
418    
419     apr_pool_destroy(rec->pool);
420     return rv;
421 niq 386321 }
422 chrisd 491729
423 chrisd 491884 *data_ptr = rec;
424    
425     return APR_SUCCESS;
426 niq 170729 }
427 chrisd 491729
428 niq 234017 #if APR_HAS_THREADS
429 chrisd 496831 static apr_status_t dbd_destroy(void *data)
430 niq 170729 {
431 chrisd 496831 svr_cfg *svr = data;
432    
433     svr->destroyed = 1;
434    
435     return APR_SUCCESS;
436     }
437    
438     static apr_status_t dbd_setup(server_rec *s, svr_cfg *svr)
439     {
440 niq 348026 apr_status_t rv;
441    
442 chrisd 496831 /* We create the reslist using a sub-pool of the pool passed to our
443     * child_init hook. No other threads can be here because we're
444     * either in the child_init phase or dbd_setup_lock() acquired our mutex.
445     * No other threads will use this sub-pool after this, except via
446     * reslist calls, which have an internal mutex.
447     *
448     * We need to short-circuit the cleanup registered internally by
449     * apr_reslist_create(). We do this by registering dbd_destroy()
450     * as a cleanup afterwards, so that it will run before the reslist's
451     * internal cleanup.
452     *
453     * If we didn't do this, then we could free memory twice when the pool
454     * was destroyed. When apr_pool_destroy() runs, it first destroys all
455     * all the per-connection sub-pools created in dbd_construct(), and
456     * then it runs the reslist's cleanup. The cleanup calls dbd_destruct()
457     * on each resource, which would then attempt to destroy the sub-pools
458     * a second time.
459 niq 348026 */
460 chrisd 491729 rv = apr_reslist_create(&svr->reslist,
461     svr->nmin, svr->nkeep, svr->nmax,
462 niq 354400 apr_time_from_sec(svr->exptime),
463 chrisd 491729 dbd_construct, dbd_destruct, svr,
464     svr->pool);
465 chrisd 491884 if (rv != APR_SUCCESS) {
466     ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
467     "DBD: failed to initialise");
468     return rv;
469 niq 170729 }
470 niq 348026
471 chrisd 496831 apr_pool_cleanup_register(svr->pool, svr, dbd_destroy,
472     apr_pool_cleanup_null);
473    
474 chrisd 491884 return APR_SUCCESS;
475 niq 170729 }
476 chrisd 496831 #endif
477 chrisd 491729
478 niq 348026 static apr_status_t dbd_setup_init(apr_pool_t *pool, server_rec *s)
479     {
480     svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);
481     apr_status_t rv;
482 niq 170729
483 niq 485311 /* dbd_setup in 2.2.3 and under was causing spurious error messages
484     * when dbd isn't configured. We can stop that with a quick check here
485     * together with a similar check in ap_dbd_open (where being
486     * unconfigured is a genuine error that must be reported).
487     */
488     if (svr->name == no_dbdriver) {
489     return APR_SUCCESS;
490     }
491    
492 niq 348026 if (!svr->persist) {
493     return APR_SUCCESS;
494     }
495    
496 chrisd 496831 rv = apr_pool_create(&svr->pool, pool);
497     if (rv != APR_SUCCESS) {
498     ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
499     "DBD: Failed to create reslist cleanup memory pool");
500     return rv;
501     }
502    
503     #if APR_HAS_THREADS
504     rv = dbd_setup(s, svr);
505 niq 348026 if (rv == APR_SUCCESS) {
506     return rv;
507     }
508    
509     /* we failed, so create a mutex so that subsequent competing callers
510     * to ap_dbd_open can serialize themselves while they retry
511     */
512 chrisd 491729 rv = apr_thread_mutex_create(&svr->mutex,
513     APR_THREAD_MUTEX_DEFAULT, pool);
514 niq 348026 if (rv != APR_SUCCESS) {
515 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
516     "DBD: Failed to create thread mutex");
517 niq 348026 }
518 chrisd 496831 #endif
519 chrisd 491729
520 niq 348026 return rv;
521     }
522 chrisd 491729
523 chrisd 496831 #if APR_HAS_THREADS
524     static apr_status_t dbd_setup_lock(server_rec *s, svr_cfg *svr)
525 niq 348026 {
526 chrisd 491729 apr_status_t rv = APR_SUCCESS, rv2;
527 niq 348026
528     /* several threads could be here at the same time, all trying to
529     * initialize the reslist because dbd_setup_init failed to do so
530     */
531     if (!svr->mutex) {
532     /* we already logged an error when the mutex couldn't be created */
533     return APR_EGENERAL;
534     }
535    
536 chrisd 491729 rv2 = apr_thread_mutex_lock(svr->mutex);
537     if (rv2 != APR_SUCCESS) {
538 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s,
539     "DBD: Failed to acquire thread mutex");
540 chrisd 491729 return rv2;
541 niq 348026 }
542    
543 chrisd 491729 if (!svr->reslist) {
544 chrisd 496831 rv = dbd_setup(s, svr);
545 niq 348026 }
546    
547 chrisd 491729 rv2 = apr_thread_mutex_unlock(svr->mutex);
548     if (rv2 != APR_SUCCESS) {
549 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s,
550     "DBD: Failed to release thread mutex");
551 chrisd 491729 if (rv == APR_SUCCESS) {
552     rv = rv2;
553 niq 348026 }
554     }
555 chrisd 491729
556     return rv;
557 niq 348026 }
558 niq 170729 #endif
559    
560     /* Functions we export for modules to use:
561     - open acquires a connection from the pool (opens one if necessary)
562     - close releases it back in to the pool
563     */
564 chrisd 491729 DBD_DECLARE_NONSTD(void) ap_dbd_close(server_rec *s, ap_dbd_t *rec)
565 niq 345040 {
566     svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);
567 chrisd 491729
568 niq 345040 if (!svr->persist) {
569 chrisd 496831 apr_pool_destroy(rec->pool);
570 niq 345040 }
571     #if APR_HAS_THREADS
572     else {
573 chrisd 491729 apr_reslist_release(svr->reslist, rec);
574 niq 345040 }
575     #endif
576     }
577 chrisd 491729
578 chrisd 491884 static apr_status_t dbd_check(apr_pool_t *pool, server_rec *s, ap_dbd_t *rec)
579     {
580     svr_cfg *svr;
581     apr_status_t rv = apr_dbd_check_conn(rec->driver, pool, rec->handle);
582     const char *errmsg;
583 chrisd 491729
584 chrisd 491884 if ((rv == APR_SUCCESS) || (rv == APR_ENOTIMPL)) {
585     return APR_SUCCESS;
586     }
587    
588     errmsg = apr_dbd_error(rec->driver, rec->handle, rv);
589     if (!errmsg) {
590     errmsg = "(unknown)";
591     }
592    
593     svr = ap_get_module_config(s->module_config, &dbd_module);
594     ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
595     "DBD [%s] Error: %s", svr->name, errmsg);
596     return rv;
597     }
598    
599 colm 349768 DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_open(apr_pool_t *pool, server_rec *s)
600 niq 170729 {
601 chrisd 491729 svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);
602 chrisd 491884 ap_dbd_t *rec = NULL;
603     #if APR_HAS_THREADS
604     apr_status_t rv;
605     #endif
606 niq 170729
607 niq 485311 /* If nothing is configured, we shouldn't be here */
608     if (svr->name == no_dbdriver) {
609 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "DBD: not configured");
610 niq 485311 return NULL;
611     }
612    
613 niq 170729 if (!svr->persist) {
614 niq 234017 /* Return a once-only connection */
615 chrisd 496831 dbd_construct((void*) &rec, svr, pool);
616 chrisd 491884 return rec;
617 niq 170729 }
618    
619 chrisd 491884 #if APR_HAS_THREADS
620 chrisd 491729 if (!svr->reslist) {
621 chrisd 496831 if (dbd_setup_lock(s, svr) != APR_SUCCESS) {
622 niq 170729 return NULL;
623     }
624     }
625 chrisd 491729
626 chrisd 492394 rv = apr_reslist_acquire(svr->reslist, (void*) &rec);
627 niq 348026 if (rv != APR_SUCCESS) {
628 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
629     "Failed to acquire DBD connection from pool!");
630 niq 170729 return NULL;
631     }
632 chrisd 491729
633 chrisd 491884 if (dbd_check(pool, s, rec) != APR_SUCCESS) {
634 chrisd 491729 apr_reslist_invalidate(svr->reslist, rec);
635 niq 170729 return NULL;
636     }
637     #else
638 chrisd 491729 /* If we have a persistent connection and it's good, we'll use it;
639     * since this is non-threaded, we can update without a mutex
640     */
641 chrisd 491884 rec = svr->rec;
642     if (rec) {
643     if (dbd_check(pool, s, rec) != APR_SUCCESS) {
644 chrisd 496831 apr_pool_destroy(rec->pool);
645 chrisd 491884 rec = NULL;
646 niq 170729 }
647     }
648 chrisd 491729
649     /* We don't have a connection right now, so we'll open one */
650 chrisd 491884 if (!rec) {
651 chrisd 496831 dbd_construct((void*) &rec, svr, svr->pool);
652 chrisd 491884 svr->rec = rec;
653 niq 170729 }
654 chrisd 491884 #endif
655 chrisd 491729
656 chrisd 491884 return rec;
657 niq 170729 }
658 chrisd 491729
659 niq 170729 #if APR_HAS_THREADS
660     typedef struct {
661 chrisd 491729 ap_dbd_t *rec;
662     apr_reslist_t *reslist;
663     } dbd_acquire_t;
664    
665     static apr_status_t dbd_release(void *data)
666 niq 170729 {
667 chrisd 491729 dbd_acquire_t *acq = data;
668     apr_reslist_release(acq->reslist, acq->rec);
669 niq 170729 return APR_SUCCESS;
670     }
671 chrisd 491729
672 colm 349768 DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_acquire(request_rec *r)
673 niq 170729 {
674 chrisd 491729 dbd_acquire_t *acq;
675 chrisd 481509
676     while (!ap_is_initial_req(r)) {
677     if (r->prev) {
678     r = r->prev;
679     }
680     else if (r->main) {
681     r = r->main;
682     }
683     }
684    
685 chrisd 491729 acq = ap_get_module_config(r->request_config, &dbd_module);
686     if (!acq) {
687     acq = apr_palloc(r->pool, sizeof(dbd_acquire_t));
688     acq->rec = ap_dbd_open(r->pool, r->server);
689     if (acq->rec) {
690     svr_cfg *svr = ap_get_module_config(r->server->module_config,
691     &dbd_module);
692    
693     ap_set_module_config(r->request_config, &dbd_module, acq);
694 niq 170729 if (svr->persist) {
695 chrisd 491729 acq->reslist = svr->reslist;
696     apr_pool_cleanup_register(r->pool, acq, dbd_release,
697 niq 170729 apr_pool_cleanup_null);
698     }
699     }
700     }
701 chrisd 491729
702     return acq->rec;
703 niq 170729 }
704 chrisd 491729
705 colm 349768 DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_cacquire(conn_rec *c)
706 niq 307439 {
707 chrisd 491729 dbd_acquire_t *acq = ap_get_module_config(c->conn_config, &dbd_module);
708    
709     if (!acq) {
710     acq = apr_palloc(c->pool, sizeof(dbd_acquire_t));
711     acq->rec = ap_dbd_open(c->pool, c->base_server);
712     if (acq->rec) {
713     svr_cfg *svr = ap_get_module_config(c->base_server->module_config,
714     &dbd_module);
715    
716     ap_set_module_config(c->conn_config, &dbd_module, acq);
717 niq 307439 if (svr->persist) {
718 chrisd 491729 acq->reslist = svr->reslist;
719     apr_pool_cleanup_register(c->pool, acq, dbd_release,
720 niq 307439 apr_pool_cleanup_null);
721     }
722     }
723     }
724 chrisd 491729
725     return acq->rec;
726 niq 307439 }
727 niq 170729 #else
728 colm 349768 DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_acquire(request_rec *r)
729 niq 170729 {
730 chrisd 491729 ap_dbd_t *rec;
731 chrisd 481509
732     while (!ap_is_initial_req(r)) {
733     if (r->prev) {
734     r = r->prev;
735     }
736     else if (r->main) {
737     r = r->main;
738     }
739     }
740    
741 chrisd 491729 rec = ap_get_module_config(r->request_config, &dbd_module);
742     if (!rec) {
743     rec = ap_dbd_open(r->pool, r->server);
744     if (rec) {
745     ap_set_module_config(r->request_config, &dbd_module, rec);
746 niq 170729 }
747     }
748 chrisd 491729
749     return rec;
750 niq 170729 }
751 chrisd 491729
752 colm 349768 DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_cacquire(conn_rec *c)
753 niq 307439 {
754 chrisd 491729 ap_dbd_t *rec = ap_get_module_config(c->conn_config, &dbd_module);
755    
756     if (!rec) {
757     rec = ap_dbd_open(c->pool, c->base_server);
758     if (rec) {
759     ap_set_module_config(c->conn_config, &dbd_module, rec);
760 niq 307439 }
761     }
762 chrisd 491729
763     return rec;
764 niq 307439 }
765 niq 170729 #endif
766    
767     static void dbd_hooks(apr_pool_t *pool)
768     {
769 chrisd 491729 ap_hook_pre_config(dbd_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
770     ap_hook_post_config(dbd_post_config, NULL, NULL, APR_HOOK_MIDDLE);
771 niq 348026 ap_hook_child_init((void*)dbd_setup_init, NULL, NULL, APR_HOOK_MIDDLE);
772 chrisd 491729
773     APR_REGISTER_OPTIONAL_FN(ap_dbd_prepare);
774 niq 170729 APR_REGISTER_OPTIONAL_FN(ap_dbd_open);
775     APR_REGISTER_OPTIONAL_FN(ap_dbd_close);
776     APR_REGISTER_OPTIONAL_FN(ap_dbd_acquire);
777 niq 307439 APR_REGISTER_OPTIONAL_FN(ap_dbd_cacquire);
778 chrisd 491729
779 niq 170729 apr_dbd_init(pool);
780     }
781    
782     module AP_MODULE_DECLARE_DATA dbd_module = {
783     STANDARD20_MODULE_STUFF,
784     NULL,
785     NULL,
786 chrisd 491729 create_dbd_config,
787     merge_dbd_config,
788 niq 170729 dbd_cmds,
789     dbd_hooks
790     };
791 chrisd 491729

Properties

Name Value
svn:eol-style native

apache@apache.org
ViewVC Help
Powered by ViewVC 1.1.2