/[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 767806 - (hide annotations)
Thu Apr 23 05:38:45 2009 UTC (7 months ago) by wrowe
File MIME type: text/plain
File size: 29810 byte(s)
Fix module scope, to avoid this, copy and past from loadable modules, not core
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 chrisd 503931 #include "apr_tables.h"
27 chrisd 491884 #include "apr_lib.h"
28     #include "apr_dbd.h"
29 niq 170729
30 chrisd 491884 #define APR_WANT_MEMFUNC
31     #define APR_WANT_STRFUNC
32     #include "apr_want.h"
33    
34 niq 170729 #include "http_protocol.h"
35     #include "http_config.h"
36     #include "http_log.h"
37 rpluem 483630 #include "http_request.h"
38 niq 170729 #include "mod_dbd.h"
39 niq 290711
40 niq 170729 extern module AP_MODULE_DECLARE_DATA dbd_module;
41    
42 wrowe 767806 APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(dbd, DBD, apr_status_t, post_connect,
43 niq 766938 (apr_pool_t *pool, dbd_cfg_t *cfg,
44     ap_dbd_t *dbd),
45     (pool, cfg, dbd), OK, DECLINED)
46    
47 niq 170729 /************ svr cfg: manage db connection pool ****************/
48    
49 niq 348026 #define NMIN_SET 0x1
50     #define NKEEP_SET 0x2
51     #define NMAX_SET 0x4
52     #define EXPTIME_SET 0x8
53    
54 chrisd 503931 typedef struct dbd_group_t dbd_group_t;
55    
56     struct dbd_group_t {
57     dbd_cfg_t *cfg;
58     dbd_group_t *next;
59     apr_pool_t *pool;
60     #if APR_HAS_THREADS
61     apr_thread_mutex_t *mutex;
62     apr_reslist_t *reslist;
63     int destroyed;
64 niq 170729 #else
65 chrisd 491729 ap_dbd_t *rec;
66 niq 170729 #endif
67 chrisd 503931 };
68    
69     typedef struct {
70     dbd_cfg_t *cfg;
71     dbd_group_t *group;
72 niq 170729 } svr_cfg;
73    
74     typedef enum { cmd_name, cmd_params, cmd_persist,
75     cmd_min, cmd_keep, cmd_max, cmd_exp
76     } cmd_parts;
77    
78 chrisd 503931 static apr_pool_t *config_pool;
79     static dbd_group_t *group_list;
80 niq 424798
81 niq 413015 /* a default DBDriver value that'll generate meaningful error messages */
82     static const char *const no_dbdriver = "[DBDriver unset]";
83 niq 170729
84 chrisd 491729 /* A default nmin of >0 will help with generating meaningful
85     * startup error messages if the database is down.
86     */
87     #define DEFAULT_NMIN 1
88     #define DEFAULT_NKEEP 2
89     #define DEFAULT_NMAX 10
90     #define DEFAULT_EXPTIME 300
91    
92 niq 766938 #define DEFAULT_SQL_INIT_ARRAY_SIZE 5
93    
94 chrisd 491729 static void *create_dbd_config(apr_pool_t *pool, server_rec *s)
95     {
96     svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg));
97 chrisd 503931 dbd_cfg_t *cfg = svr->cfg = apr_pcalloc(pool, sizeof(dbd_cfg_t));
98 chrisd 491729
99 chrisd 503931 cfg->server = s;
100     cfg->name = no_dbdriver; /* to generate meaningful error messages */
101     cfg->params = ""; /* don't risk segfault on misconfiguration */
102     cfg->persist = -1;
103 chrisd 491729 #if APR_HAS_THREADS
104 chrisd 503931 cfg->nmin = DEFAULT_NMIN;
105     cfg->nkeep = DEFAULT_NKEEP;
106     cfg->nmax = DEFAULT_NMAX;
107     cfg->exptime = DEFAULT_EXPTIME;
108 chrisd 491729 #endif
109 chrisd 503931 cfg->queries = apr_hash_make(pool);
110 niq 766938 cfg->init_queries = apr_array_make(pool, DEFAULT_SQL_INIT_ARRAY_SIZE,
111     sizeof(const char *));
112 chrisd 491729
113     return svr;
114     }
115    
116     static void *merge_dbd_config(apr_pool_t *pool, void *basev, void *addv)
117     {
118 chrisd 503931 dbd_cfg_t *base = ((svr_cfg*) basev)->cfg;
119     dbd_cfg_t *add = ((svr_cfg*) addv)->cfg;
120 chrisd 491729 svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg));
121 chrisd 503931 dbd_cfg_t *new = svr->cfg = apr_pcalloc(pool, sizeof(dbd_cfg_t));
122 chrisd 491729
123 chrisd 503931 new->server = add->server;
124     new->name = (add->name != no_dbdriver) ? add->name : base->name;
125     new->params = strcmp(add->params, "") ? add->params : base->params;
126     new->persist = (add->persist != -1) ? add->persist : base->persist;
127 chrisd 491729 #if APR_HAS_THREADS
128 chrisd 503931 new->nmin = (add->set&NMIN_SET) ? add->nmin : base->nmin;
129     new->nkeep = (add->set&NKEEP_SET) ? add->nkeep : base->nkeep;
130     new->nmax = (add->set&NMAX_SET) ? add->nmax : base->nmax;
131     new->exptime = (add->set&EXPTIME_SET) ? add->exptime : base->exptime;
132 chrisd 491729 #endif
133 chrisd 503931 new->queries = apr_hash_overlay(pool, add->queries, base->queries);
134 niq 766938 new->init_queries = apr_array_append(pool, add->init_queries,
135     base->init_queries);
136 chrisd 491729
137     return svr;
138     }
139    
140 niq 766938 static void ap_dbd_sql_init(server_rec *s, const char *query)
141     {
142     svr_cfg *svr;
143     const char **arr_item;
144    
145     svr = ap_get_module_config(s->module_config, &dbd_module);
146     if (!svr) {
147     /* some modules may call from within config directive handlers, and
148     * if these are called in a server context that contains no mod_dbd
149     * config directives, then we have to create our own server config
150     */
151     svr = create_dbd_config(config_pool, s);
152     ap_set_module_config(s->module_config, &dbd_module, svr);
153     }
154    
155     if (query) {
156     arr_item = apr_array_push(svr->cfg->init_queries);
157     *arr_item = query;
158     }
159     }
160    
161 chrisd 491729 static const char *dbd_param(cmd_parms *cmd, void *dconf, const char *val)
162 niq 170729 {
163 niq 231464 const apr_dbd_driver_t *driver = NULL;
164 chrisd 491729 svr_cfg *svr = ap_get_module_config(cmd->server->module_config,
165     &dbd_module);
166 chrisd 503931 dbd_cfg_t *cfg = svr->cfg;
167 niq 170729
168 niq 291100 switch ((long) cmd->info) {
169 niq 170729 case cmd_name:
170 chrisd 503931 cfg->name = val;
171 niq 170729 /* loading the driver involves once-only dlloading that is
172     * best done at server startup. This also guarantees that
173 niq 345040 * we won't return an error later.
174 niq 170729 */
175 chrisd 503931 switch (apr_dbd_get_driver(cmd->pool, cfg->name, &driver)) {
176 niq 170729 case APR_ENOTIMPL:
177 chrisd 503931 return apr_psprintf(cmd->pool, "DBD: No driver for %s", cfg->name);
178 niq 170729 case APR_EDSOOPEN:
179     return apr_psprintf(cmd->pool,
180 fuankg 553563 #ifdef NETWARE
181     "DBD: Can't load driver file dbd%s.nlm",
182     #else
183     "DBD: Can't load driver file apr_dbd_%s.so",
184     #endif
185 chrisd 503931 cfg->name);
186 niq 170729 case APR_ESYMNOTFOUND:
187     return apr_psprintf(cmd->pool,
188     "DBD: Failed to load driver apr_dbd_%s_driver",
189 chrisd 503931 cfg->name);
190 niq 170729 }
191     break;
192     case cmd_params:
193 chrisd 503931 cfg->params = val;
194 niq 170729 break;
195 chrisd 646453 }
196    
197     return NULL;
198     }
199    
200 niq 170729 #if APR_HAS_THREADS
201 chrisd 646453 static const char *dbd_param_int(cmd_parms *cmd, void *dconf, const char *val)
202     {
203     svr_cfg *svr = ap_get_module_config(cmd->server->module_config,
204     &dbd_module);
205     dbd_cfg_t *cfg = svr->cfg;
206     const char *p;
207    
208     for (p = val; *p; ++p) {
209     if (!apr_isdigit(*p)) {
210     return "Argument must be numeric!";
211     }
212     }
213    
214     switch ((long) cmd->info) {
215 niq 170729 case cmd_min:
216 chrisd 503931 cfg->nmin = atoi(val);
217     cfg->set |= NMIN_SET;
218 niq 170729 break;
219     case cmd_keep:
220 chrisd 503931 cfg->nkeep = atoi(val);
221     cfg->set |= NKEEP_SET;
222 niq 170729 break;
223     case cmd_max:
224 chrisd 503931 cfg->nmax = atoi(val);
225     cfg->set |= NMAX_SET;
226 niq 170729 break;
227     case cmd_exp:
228 chrisd 503931 cfg->exptime = atoi(val);
229     cfg->set |= EXPTIME_SET;
230 niq 170729 break;
231     }
232 chrisd 491729
233 niq 170729 return NULL;
234     }
235 chrisd 646453 #endif
236 chrisd 491729
237     static const char *dbd_param_flag(cmd_parms *cmd, void *dconf, int flag)
238 niq 348026 {
239 chrisd 491729 svr_cfg *svr = ap_get_module_config(cmd->server->module_config,
240     &dbd_module);
241 niq 348026
242     switch ((long) cmd->info) {
243     case cmd_persist:
244 chrisd 503931 svr->cfg->persist = flag;
245 niq 348026 break;
246     }
247 chrisd 491729
248 niq 348026 return NULL;
249     }
250 chrisd 491729
251     static const char *dbd_prepare(cmd_parms *cmd, void *dconf, const char *query,
252 niq 234017 const char *label)
253     {
254 chrisd 503931 if (!label) {
255     label = query;
256     query = "";
257     }
258    
259 niq 234017 ap_dbd_prepare(cmd->server, query, label);
260 chrisd 491729
261 niq 170729 return NULL;
262     }
263 chrisd 491729
264 niq 766938 static const char *dbd_init_sql(cmd_parms *cmd, void *dconf, const char *query)
265     {
266     if (!query || *query == '\n') {
267     return "You should specify SQL statement";
268     }
269    
270     ap_dbd_sql_init(cmd->server, query);
271    
272     return NULL;
273     }
274    
275 niq 170729 static const command_rec dbd_cmds[] = {
276     AP_INIT_TAKE1("DBDriver", dbd_param, (void*)cmd_name, RSRC_CONF,
277     "SQL Driver"),
278     AP_INIT_TAKE1("DBDParams", dbd_param, (void*)cmd_params, RSRC_CONF,
279     "SQL Driver Params"),
280 niq 348026 AP_INIT_FLAG("DBDPersist", dbd_param_flag, (void*)cmd_persist, RSRC_CONF,
281     "Use persistent connection/pool"),
282 chrisd 503931 AP_INIT_TAKE12("DBDPrepareSQL", dbd_prepare, NULL, RSRC_CONF,
283     "SQL statement to prepare (or nothing, to override "
284     "statement inherited from main server) and label"),
285 niq 766938 AP_INIT_TAKE1("DBDInitSQL", dbd_init_sql, NULL, RSRC_CONF,
286     "SQL statement to be executed after connection is created"),
287 niq 170729 #if APR_HAS_THREADS
288 chrisd 646453 AP_INIT_TAKE1("DBDMin", dbd_param_int, (void*)cmd_min, RSRC_CONF,
289 niq 170729 "Minimum number of connections"),
290 niq 348026 /* XXX: note that mod_proxy calls this "smax" */
291 chrisd 646453 AP_INIT_TAKE1("DBDKeep", dbd_param_int, (void*)cmd_keep, RSRC_CONF,
292 niq 170729 "Maximum number of sustained connections"),
293 chrisd 646453 AP_INIT_TAKE1("DBDMax", dbd_param_int, (void*)cmd_max, RSRC_CONF,
294 niq 170729 "Maximum number of connections"),
295 niq 348026 /* XXX: note that mod_proxy calls this "ttl" (time to live) */
296 chrisd 646453 AP_INIT_TAKE1("DBDExptime", dbd_param_int, (void*)cmd_exp, RSRC_CONF,
297 niq 170729 "Keepalive time for idle connections"),
298     #endif
299     {NULL}
300     };
301 chrisd 491729
302     static int dbd_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
303     apr_pool_t *ptemp)
304     {
305 chrisd 503931 config_pool = pconf;
306     group_list = NULL;
307 chrisd 491729 return OK;
308 niq 348026 }
309 chrisd 491729
310 wrowe 664160 DBD_DECLARE_NONSTD(void) ap_dbd_prepare(server_rec *s, const char *query,
311     const char *label)
312 niq 170729 {
313 chrisd 503931 svr_cfg *svr;
314 chrisd 491729
315 chrisd 503931 svr = ap_get_module_config(s->module_config, &dbd_module);
316     if (!svr) {
317     /* some modules may call from within config directive handlers, and
318     * if these are called in a server context that contains no mod_dbd
319     * config directives, then we have to create our own server config
320     */
321     svr = create_dbd_config(config_pool, s);
322     ap_set_module_config(s->module_config, &dbd_module, svr);
323     }
324 chrisd 491729
325 chrisd 503931 if (apr_hash_get(svr->cfg->queries, label, APR_HASH_KEY_STRING)
326     && strcmp(query, "")) {
327     ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
328     "conflicting SQL statements with label %s", label);
329     }
330    
331     apr_hash_set(svr->cfg->queries, label, APR_HASH_KEY_STRING, query);
332 niq 170729 }
333 chrisd 491729
334 chrisd 503931 typedef struct {
335     const char *label, *query;
336     } dbd_query_t;
337    
338 chrisd 491729 static int dbd_post_config(apr_pool_t *pconf, apr_pool_t *plog,
339     apr_pool_t *ptemp, server_rec *s)
340     {
341     server_rec *sp;
342 chrisd 503931 apr_array_header_t *add_queries = apr_array_make(ptemp, 10,
343     sizeof(dbd_query_t));
344 chrisd 491729
345     for (sp = s; sp; sp = sp->next) {
346     svr_cfg *svr = ap_get_module_config(sp->module_config, &dbd_module);
347 chrisd 503931 dbd_cfg_t *cfg = svr->cfg;
348     apr_hash_index_t *hi_first = apr_hash_first(ptemp, cfg->queries);
349     dbd_group_t *group;
350 chrisd 491729
351 chrisd 503931 /* dbd_setup in 2.2.3 and under was causing spurious error messages
352     * when dbd isn't configured. We can stop that with a quick check here
353     * together with a similar check in ap_dbd_open (where being
354     * unconfigured is a genuine error that must be reported).
355     */
356     if (cfg->name == no_dbdriver || !cfg->persist) {
357     continue;
358     }
359    
360     for (group = group_list; group; group = group->next) {
361     dbd_cfg_t *group_cfg = group->cfg;
362     apr_hash_index_t *hi;
363     int group_ok = 1;
364    
365     if (strcmp(cfg->name, group_cfg->name)
366     || strcmp(cfg->params, group_cfg->params)) {
367     continue;
368     }
369    
370     #if APR_HAS_THREADS
371     if (cfg->nmin != group_cfg->nmin
372     || cfg->nkeep != group_cfg->nkeep
373     || cfg->nmax != group_cfg->nmax
374     || cfg->exptime != group_cfg->exptime) {
375     continue;
376     }
377     #endif
378    
379     add_queries->nelts = 0;
380    
381     for (hi = hi_first; hi; hi = apr_hash_next(hi)) {
382     const char *label, *query;
383     const char *group_query;
384    
385     apr_hash_this(hi, (void*) &label, NULL, (void*) &query);
386    
387     group_query = apr_hash_get(group_cfg->queries, label,
388     APR_HASH_KEY_STRING);
389    
390     if (!group_query) {
391     dbd_query_t *add_query = apr_array_push(add_queries);
392    
393     add_query->label = label;
394     add_query->query = query;
395     }
396     else if (strcmp(query, group_query)) {
397     group_ok = 0;
398     break;
399     }
400     }
401    
402     if (group_ok) {
403     int i;
404    
405     for (i = 0; i < add_queries->nelts; ++i) {
406     dbd_query_t *add_query = ((dbd_query_t*) add_queries->elts)
407     + i;
408    
409     apr_hash_set(group_cfg->queries, add_query->label,
410     APR_HASH_KEY_STRING, add_query->query);
411     }
412    
413     svr->group = group;
414     break;
415     }
416     }
417    
418     if (!svr->group) {
419     svr->group = group = apr_pcalloc(pconf, sizeof(dbd_group_t));
420    
421     group->cfg = cfg;
422    
423     group->next = group_list;
424     group_list = group;
425     }
426 chrisd 491729 }
427    
428     return OK;
429     }
430    
431 chrisd 503931 static apr_status_t dbd_prepared_init(apr_pool_t *pool, dbd_cfg_t *cfg,
432 chrisd 491729 ap_dbd_t *rec)
433 niq 170729 {
434 chrisd 503931 apr_hash_index_t *hi;
435 chrisd 491729 apr_status_t rv = APR_SUCCESS;
436 niq 170729
437 chrisd 491729 rec->prepared = apr_hash_make(pool);
438    
439 chrisd 503931 for (hi = apr_hash_first(pool, cfg->queries); hi;
440     hi = apr_hash_next(hi)) {
441     const char *label, *query;
442     apr_dbd_prepared_t *stmt;
443    
444     apr_hash_this(hi, (void*) &label, NULL, (void*) &query);
445    
446     if (!strcmp(query, "")) {
447     continue;
448     }
449    
450 niq 344140 stmt = NULL;
451 chrisd 503931 if (apr_dbd_prepare(rec->driver, pool, rec->handle, query,
452     label, &stmt)) {
453     rv = APR_EGENERAL;
454 niq 170729 }
455     else {
456 chrisd 503931 apr_hash_set(rec->prepared, label, APR_HASH_KEY_STRING, stmt);
457 niq 170729 }
458     }
459 chrisd 491729
460     return rv;
461 niq 170729 }
462 chrisd 491729
463 niq 766938 static apr_status_t dbd_init_sql_init(apr_pool_t *pool, dbd_cfg_t *cfg,
464     ap_dbd_t *rec)
465     {
466     int i;
467     apr_status_t rv = APR_SUCCESS;
468    
469     for (i = 0; i < cfg->init_queries->nelts; i++) {
470     int nrows;
471     char **query_p;
472    
473     query_p = (char **)cfg->init_queries->elts + i;
474    
475     if (apr_dbd_query(rec->driver, rec->handle, &nrows, *query_p)) {
476     rv = APR_EGENERAL;
477     break;
478     }
479     }
480    
481     return rv;
482     }
483    
484 chrisd 491729 static apr_status_t dbd_close(void *data)
485     {
486     ap_dbd_t *rec = data;
487    
488 chrisd 496831 return apr_dbd_close(rec->driver, rec->handle);
489 chrisd 491729 }
490    
491     #if APR_HAS_THREADS
492     static apr_status_t dbd_destruct(void *data, void *params, apr_pool_t *pool)
493     {
494 chrisd 503931 dbd_group_t *group = params;
495 chrisd 496831
496 chrisd 503931 if (!group->destroyed) {
497 chrisd 496831 ap_dbd_t *rec = data;
498    
499     apr_pool_destroy(rec->pool);
500     }
501    
502     return APR_SUCCESS;
503 chrisd 491729 }
504     #endif
505    
506 niq 234017 /* an apr_reslist_constructor for SQL connections
507     * Also use this for opening in non-reslist modes, since it gives
508     * us all the error-handling in one place.
509     */
510 chrisd 491729 static apr_status_t dbd_construct(void **data_ptr,
511     void *params, apr_pool_t *pool)
512 niq 170729 {
513 chrisd 503931 dbd_group_t *group = params;
514     dbd_cfg_t *cfg = group->cfg;
515 chrisd 496831 apr_pool_t *rec_pool, *prepared_pool;
516     ap_dbd_t *rec;
517 niq 348026 apr_status_t rv;
518 niq 689224 const char *err = "";
519 niq 170729
520 chrisd 496831 rv = apr_pool_create(&rec_pool, pool);
521 niq 348026 if (rv != APR_SUCCESS) {
522 chrisd 503931 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->server,
523 chrisd 491884 "DBD: Failed to create memory pool");
524     return rv;
525 niq 348026 }
526    
527 chrisd 496831 rec = apr_pcalloc(rec_pool, sizeof(ap_dbd_t));
528    
529     rec->pool = rec_pool;
530    
531 chrisd 491729 /* The driver is loaded at config time now, so this just checks a hash.
532     * If that changes, the driver DSO could be registered to unload against
533     * our pool, which is probably not what we want. Error checking isn't
534     * necessary now, but in case that changes in the future ...
535     */
536 chrisd 503931 rv = apr_dbd_get_driver(rec->pool, cfg->name, &rec->driver);
537 chrisd 491729 if (rv != APR_SUCCESS) {
538     switch (rv) {
539     case APR_ENOTIMPL:
540 chrisd 503931 ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
541     "DBD: driver for %s not available", cfg->name);
542 chrisd 491729 break;
543     case APR_EDSOOPEN:
544 chrisd 503931 ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
545     "DBD: can't find driver for %s", cfg->name);
546 chrisd 491729 break;
547     case APR_ESYMNOTFOUND:
548 chrisd 503931 ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
549 chrisd 491884 "DBD: driver for %s is invalid or corrupted",
550 chrisd 503931 cfg->name);
551 chrisd 491729 break;
552     default:
553 chrisd 503931 ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
554 chrisd 491884 "DBD: mod_dbd not compatible with APR in get_driver");
555 chrisd 491729 break;
556     }
557    
558 chrisd 491884 apr_pool_destroy(rec->pool);
559 niq 234017 return rv;
560     }
561    
562 niq 689224 rv = apr_dbd_open_ex(rec->driver, rec->pool, cfg->params, &rec->handle, &err);
563 chrisd 491729 if (rv != APR_SUCCESS) {
564     switch (rv) {
565     case APR_EGENERAL:
566 chrisd 503931 ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
567 niq 689246 "DBD: Can't connect to %s: %s", cfg->name, err);
568 chrisd 491729 break;
569     default:
570 chrisd 503931 ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
571 chrisd 491884 "DBD: mod_dbd not compatible with APR in open");
572 chrisd 491729 break;
573     }
574    
575 chrisd 491884 apr_pool_destroy(rec->pool);
576 niq 170729 return rv;
577     }
578 chrisd 491729
579 chrisd 496831 apr_pool_cleanup_register(rec->pool, rec, dbd_close,
580     apr_pool_cleanup_null);
581    
582     /* we use a sub-pool for the prepared statements for each connection so
583     * that they will be cleaned up first, before the connection is closed
584     */
585     rv = apr_pool_create(&prepared_pool, rec->pool);
586 niq 386321 if (rv != APR_SUCCESS) {
587 chrisd 503931 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->server,
588 chrisd 496831 "DBD: Failed to create memory pool");
589    
590     apr_pool_destroy(rec->pool);
591     return rv;
592     }
593    
594 chrisd 503931 rv = dbd_prepared_init(prepared_pool, cfg, rec);
595 chrisd 496831 if (rv != APR_SUCCESS) {
596 niq 424798 const char *errmsg = apr_dbd_error(rec->driver, rec->handle, rv);
597 chrisd 503931 ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
598 chrisd 491884 "DBD: failed to prepare SQL statements: %s",
599     (errmsg ? errmsg : "[???]"));
600    
601     apr_pool_destroy(rec->pool);
602     return rv;
603 niq 386321 }
604 chrisd 491729
605 niq 766938 dbd_run_post_connect(prepared_pool, cfg, rec);
606    
607 chrisd 491884 *data_ptr = rec;
608    
609     return APR_SUCCESS;
610 niq 170729 }
611 chrisd 491729
612 niq 234017 #if APR_HAS_THREADS
613 chrisd 496831 static apr_status_t dbd_destroy(void *data)
614 niq 170729 {
615 chrisd 503931 dbd_group_t *group = data;
616 chrisd 496831
617 chrisd 503931 group->destroyed = 1;
618 chrisd 496831
619     return APR_SUCCESS;
620     }
621    
622 chrisd 503931 static apr_status_t dbd_setup(server_rec *s, dbd_group_t *group)
623 chrisd 496831 {
624 chrisd 503931 dbd_cfg_t *cfg = group->cfg;
625 niq 348026 apr_status_t rv;
626    
627 chrisd 496831 /* We create the reslist using a sub-pool of the pool passed to our
628     * child_init hook. No other threads can be here because we're
629     * either in the child_init phase or dbd_setup_lock() acquired our mutex.
630     * No other threads will use this sub-pool after this, except via
631     * reslist calls, which have an internal mutex.
632     *
633     * We need to short-circuit the cleanup registered internally by
634     * apr_reslist_create(). We do this by registering dbd_destroy()
635     * as a cleanup afterwards, so that it will run before the reslist's
636     * internal cleanup.
637     *
638     * If we didn't do this, then we could free memory twice when the pool
639     * was destroyed. When apr_pool_destroy() runs, it first destroys all
640     * all the per-connection sub-pools created in dbd_construct(), and
641     * then it runs the reslist's cleanup. The cleanup calls dbd_destruct()
642     * on each resource, which would then attempt to destroy the sub-pools
643     * a second time.
644 niq 348026 */
645 chrisd 503931 rv = apr_reslist_create(&group->reslist,
646     cfg->nmin, cfg->nkeep, cfg->nmax,
647     apr_time_from_sec(cfg->exptime),
648     dbd_construct, dbd_destruct, group,
649     group->pool);
650 chrisd 491884 if (rv != APR_SUCCESS) {
651     ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
652     "DBD: failed to initialise");
653     return rv;
654 niq 170729 }
655 niq 348026
656 chrisd 503931 apr_pool_cleanup_register(group->pool, group, dbd_destroy,
657 chrisd 496831 apr_pool_cleanup_null);
658    
659 chrisd 491884 return APR_SUCCESS;
660 niq 170729 }
661 chrisd 496831 #endif
662 chrisd 491729
663 niq 348026 static apr_status_t dbd_setup_init(apr_pool_t *pool, server_rec *s)
664     {
665 chrisd 503931 dbd_group_t *group;
666     apr_status_t rv = APR_SUCCESS;
667 niq 170729
668 chrisd 503931 for (group = group_list; group; group = group->next) {
669     apr_status_t rv2;
670 niq 485311
671 chrisd 503931 rv2 = apr_pool_create(&group->pool, pool);
672     if (rv2 != APR_SUCCESS) {
673     ap_log_error(APLOG_MARK, APLOG_CRIT, rv2, s,
674     "DBD: Failed to create reslist cleanup memory pool");
675     return rv2;
676     }
677 niq 348026
678 chrisd 496831 #if APR_HAS_THREADS
679 chrisd 503931 rv2 = dbd_setup(s, group);
680     if (rv2 == APR_SUCCESS) {
681     continue;
682     }
683     else if (rv == APR_SUCCESS) {
684     rv = rv2;
685     }
686 niq 348026
687 chrisd 503931 /* we failed, so create a mutex so that subsequent competing callers
688     * to ap_dbd_open can serialize themselves while they retry
689     */
690     rv2 = apr_thread_mutex_create(&group->mutex,
691     APR_THREAD_MUTEX_DEFAULT, pool);
692     if (rv2 != APR_SUCCESS) {
693     ap_log_error(APLOG_MARK, APLOG_CRIT, rv2, s,
694     "DBD: Failed to create thread mutex");
695     return rv2;
696     }
697     #endif
698 niq 348026 }
699 chrisd 491729
700 niq 348026 return rv;
701     }
702 chrisd 491729
703 pquerna 708820 static void dbd_child_init(apr_pool_t *p, server_rec *s)
704     {
705     apr_status_t rv = dbd_setup_init(p, s);
706     if (rv) {
707     ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
708     "DBD: child init failed!");
709     }
710     }
711    
712 chrisd 496831 #if APR_HAS_THREADS
713 chrisd 503931 static apr_status_t dbd_setup_lock(server_rec *s, dbd_group_t *group)
714 niq 348026 {
715 chrisd 491729 apr_status_t rv = APR_SUCCESS, rv2;
716 niq 348026
717     /* several threads could be here at the same time, all trying to
718     * initialize the reslist because dbd_setup_init failed to do so
719     */
720 chrisd 503931 if (!group->mutex) {
721 niq 348026 /* we already logged an error when the mutex couldn't be created */
722     return APR_EGENERAL;
723     }
724    
725 chrisd 503931 rv2 = apr_thread_mutex_lock(group->mutex);
726 chrisd 491729 if (rv2 != APR_SUCCESS) {
727 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s,
728     "DBD: Failed to acquire thread mutex");
729 chrisd 491729 return rv2;
730 niq 348026 }
731    
732 chrisd 503931 if (!group->reslist) {
733     rv = dbd_setup(s, group);
734 niq 348026 }
735    
736 chrisd 503931 rv2 = apr_thread_mutex_unlock(group->mutex);
737 chrisd 491729 if (rv2 != APR_SUCCESS) {
738 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s,
739     "DBD: Failed to release thread mutex");
740 chrisd 491729 if (rv == APR_SUCCESS) {
741     rv = rv2;
742 niq 348026 }
743     }
744 chrisd 491729
745     return rv;
746 niq 348026 }
747 niq 170729 #endif
748    
749     /* Functions we export for modules to use:
750     - open acquires a connection from the pool (opens one if necessary)
751     - close releases it back in to the pool
752     */
753 wrowe 664160 DBD_DECLARE_NONSTD(void) ap_dbd_close(server_rec *s, ap_dbd_t *rec)
754 niq 345040 {
755     svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);
756 chrisd 491729
757 chrisd 503931 if (!svr->cfg->persist) {
758 chrisd 496831 apr_pool_destroy(rec->pool);
759 niq 345040 }
760     #if APR_HAS_THREADS
761     else {
762 chrisd 503931 apr_reslist_release(svr->group->reslist, rec);
763 niq 345040 }
764     #endif
765     }
766 chrisd 491729
767 chrisd 491884 static apr_status_t dbd_check(apr_pool_t *pool, server_rec *s, ap_dbd_t *rec)
768     {
769     svr_cfg *svr;
770     apr_status_t rv = apr_dbd_check_conn(rec->driver, pool, rec->handle);
771     const char *errmsg;
772 chrisd 491729
773 chrisd 491884 if ((rv == APR_SUCCESS) || (rv == APR_ENOTIMPL)) {
774     return APR_SUCCESS;
775     }
776    
777 chrisd 539687 /* we don't have a driver-specific error code, so we'll just pass
778     * a "success" value and rely on the driver to ignore it
779     */
780     errmsg = apr_dbd_error(rec->driver, rec->handle, 0);
781 chrisd 491884 if (!errmsg) {
782     errmsg = "(unknown)";
783     }
784    
785     svr = ap_get_module_config(s->module_config, &dbd_module);
786     ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
787 chrisd 503931 "DBD [%s] Error: %s", svr->cfg->name, errmsg);
788 chrisd 491884 return rv;
789     }
790    
791 wrowe 664160 DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_open(apr_pool_t *pool, server_rec *s)
792 niq 170729 {
793 chrisd 491729 svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);
794 chrisd 503931 dbd_group_t *group = svr->group;
795     dbd_cfg_t *cfg = svr->cfg;
796 chrisd 491884 ap_dbd_t *rec = NULL;
797     #if APR_HAS_THREADS
798     apr_status_t rv;
799     #endif
800 niq 170729
801 niq 485311 /* If nothing is configured, we shouldn't be here */
802 chrisd 503931 if (cfg->name == no_dbdriver) {
803 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "DBD: not configured");
804 niq 485311 return NULL;
805     }
806    
807 chrisd 503931 if (!cfg->persist) {
808 niq 234017 /* Return a once-only connection */
809 chrisd 503931 group = apr_pcalloc(pool, sizeof(dbd_group_t));
810    
811     group->cfg = cfg;
812    
813     dbd_construct((void*) &rec, group, pool);
814 chrisd 491884 return rec;
815 niq 170729 }
816    
817 chrisd 491884 #if APR_HAS_THREADS
818 chrisd 503931 if (!group->reslist) {
819     if (dbd_setup_lock(s, group) != APR_SUCCESS) {
820 niq 170729 return NULL;
821     }
822     }
823 chrisd 491729
824 chrisd 503931 rv = apr_reslist_acquire(group->reslist, (void*) &rec);
825 niq 348026 if (rv != APR_SUCCESS) {
826 chrisd 491884 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
827     "Failed to acquire DBD connection from pool!");
828 niq 170729 return NULL;
829     }
830 chrisd 491729
831 chrisd 491884 if (dbd_check(pool, s, rec) != APR_SUCCESS) {
832 chrisd 503931 apr_reslist_invalidate(group->reslist, rec);
833 niq 170729 return NULL;
834     }
835     #else
836 chrisd 491729 /* If we have a persistent connection and it's good, we'll use it;
837     * since this is non-threaded, we can update without a mutex
838     */
839 chrisd 503931 rec = group->rec;
840     if (rec) {
841 chrisd 491884 if (dbd_check(pool, s, rec) != APR_SUCCESS) {
842 chrisd 496831 apr_pool_destroy(rec->pool);
843 chrisd 491884 rec = NULL;
844 niq 170729 }
845     }
846 chrisd 491729
847     /* We don't have a connection right now, so we'll open one */
848 chrisd 491884 if (!rec) {
849 chrisd 503931 dbd_construct((void*) &rec, group, group->pool);
850     group->rec = rec;
851 niq 170729 }
852 chrisd 491884 #endif
853 chrisd 491729
854 chrisd 491884 return rec;
855 niq 170729 }
856 chrisd 491729
857 niq 170729 #if APR_HAS_THREADS
858     typedef struct {
859 chrisd 491729 ap_dbd_t *rec;
860     apr_reslist_t *reslist;
861     } dbd_acquire_t;
862    
863     static apr_status_t dbd_release(void *data)
864 niq 170729 {
865 chrisd 491729 dbd_acquire_t *acq = data;
866     apr_reslist_release(acq->reslist, acq->rec);
867 niq 170729 return APR_SUCCESS;
868     }
869 chrisd 491729
870 wrowe 664160 DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_acquire(request_rec *r)
871 niq 170729 {
872 chrisd 491729 dbd_acquire_t *acq;
873 chrisd 481509
874     while (!ap_is_initial_req(r)) {
875     if (r->prev) {
876     r = r->prev;
877     }
878     else if (r->main) {
879     r = r->main;
880     }
881     }
882    
883 chrisd 491729 acq = ap_get_module_config(r->request_config, &dbd_module);
884     if (!acq) {
885     acq = apr_palloc(r->pool, sizeof(dbd_acquire_t));
886     acq->rec = ap_dbd_open(r->pool, r->server);
887     if (acq->rec) {
888     svr_cfg *svr = ap_get_module_config(r->server->module_config,
889     &dbd_module);
890    
891     ap_set_module_config(r->request_config, &dbd_module, acq);
892 chrisd 503931 if (svr->cfg->persist) {
893     acq->reslist = svr->group->reslist;
894 chrisd 491729 apr_pool_cleanup_register(r->pool, acq, dbd_release,
895 niq 170729 apr_pool_cleanup_null);
896     }
897     }
898     }
899 chrisd 491729
900     return acq->rec;
901 niq 170729 }
902 chrisd 491729
903 wrowe 664160 DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_cacquire(conn_rec *c)
904 niq 307439 {
905 chrisd 491729 dbd_acquire_t *acq = ap_get_module_config(c->conn_config, &dbd_module);
906    
907     if (!acq) {
908     acq = apr_palloc(c->pool, sizeof(dbd_acquire_t));
909     acq->rec = ap_dbd_open(c->pool, c->base_server);
910     if (acq->rec) {
911     svr_cfg *svr = ap_get_module_config(c->base_server->module_config,
912     &dbd_module);
913    
914     ap_set_module_config(c->conn_config, &dbd_module, acq);
915 chrisd 503931 if (svr->cfg->persist) {
916     acq->reslist = svr->group->reslist;
917 chrisd 491729 apr_pool_cleanup_register(c->pool, acq, dbd_release,
918 niq 307439 apr_pool_cleanup_null);
919     }
920     }
921     }
922 chrisd 491729
923     return acq->rec;
924 niq 307439 }
925 niq 170729 #else
926 wrowe 664160 DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_acquire(request_rec *r)
927 niq 170729 {
928 chrisd 491729 ap_dbd_t *rec;
929 chrisd 481509
930     while (!ap_is_initial_req(r)) {
931     if (r->prev) {
932     r = r->prev;
933     }
934     else if (r->main) {
935     r = r->main;
936     }
937     }
938    
939 chrisd 491729 rec = ap_get_module_config(r->request_config, &dbd_module);
940     if (!rec) {
941     rec = ap_dbd_open(r->pool, r->server);
942     if (rec) {
943     ap_set_module_config(r->request_config, &dbd_module, rec);
944 niq 170729 }
945     }
946 chrisd 491729
947     return rec;
948 niq 170729 }
949 chrisd 491729
950 wrowe 664160 DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_cacquire(conn_rec *c)
951 niq 307439 {
952 chrisd 491729 ap_dbd_t *rec = ap_get_module_config(c->conn_config, &dbd_module);
953    
954     if (!rec) {
955     rec = ap_dbd_open(c->pool, c->base_server);
956     if (rec) {
957     ap_set_module_config(c->conn_config, &dbd_module, rec);
958 niq 307439 }
959     }
960 chrisd 491729
961     return rec;
962 niq 307439 }
963 niq 170729 #endif
964    
965     static void dbd_hooks(apr_pool_t *pool)
966     {
967 chrisd 491729 ap_hook_pre_config(dbd_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
968     ap_hook_post_config(dbd_post_config, NULL, NULL, APR_HOOK_MIDDLE);
969 pquerna 708820 ap_hook_child_init(dbd_child_init, NULL, NULL, APR_HOOK_MIDDLE);
970 chrisd 491729
971     APR_REGISTER_OPTIONAL_FN(ap_dbd_prepare);
972 niq 170729 APR_REGISTER_OPTIONAL_FN(ap_dbd_open);
973     APR_REGISTER_OPTIONAL_FN(ap_dbd_close);
974     APR_REGISTER_OPTIONAL_FN(ap_dbd_acquire);
975 niq 307439 APR_REGISTER_OPTIONAL_FN(ap_dbd_cacquire);
976 chrisd 491729
977 niq 766938 APR_OPTIONAL_HOOK(dbd, post_connect, dbd_init_sql_init,
978     NULL, NULL, APR_HOOK_MIDDLE);
979    
980 niq 170729 apr_dbd_init(pool);
981     }
982    
983     module AP_MODULE_DECLARE_DATA dbd_module = {
984     STANDARD20_MODULE_STUFF,
985     NULL,
986     NULL,
987 chrisd 491729 create_dbd_config,
988     merge_dbd_config,
989 niq 170729 dbd_cmds,
990     dbd_hooks
991     };
992 chrisd 491729

Properties

Name Value
svn:eol-style native

apache@apache.org
ViewVC Help
Powered by ViewVC 1.1.2