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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 496831, Tue Jan 16 19:36:26 2007 UTC revision 503931, Tue Feb 6 00:25:15 2007 UTC
# Line 23  Line 23 
23  #include "apr_reslist.h"  #include "apr_reslist.h"
24  #include "apr_strings.h"  #include "apr_strings.h"
25  #include "apr_hash.h"  #include "apr_hash.h"
26    #include "apr_tables.h"
27  #include "apr_lib.h"  #include "apr_lib.h"
28  #include "apr_dbd.h"  #include "apr_dbd.h"
29    
# Line 45  extern module AP_MODULE_DECLARE_DATA dbd Line 46  extern module AP_MODULE_DECLARE_DATA dbd
46  #define NMAX_SET     0x4  #define NMAX_SET     0x4
47  #define EXPTIME_SET  0x8  #define EXPTIME_SET  0x8
48    
 typedef struct dbd_prepared dbd_prepared;  
   
 struct dbd_prepared {  
     const char *label;  
     const char *query;  
     dbd_prepared *next;  
 };  
   
49  typedef struct {  typedef struct {
50      server_rec *server;      server_rec *server;
51      const char *name;      const char *name;
52      const char *params;      const char *params;
53      int persist;      int persist;
     dbd_prepared *prepared;  
     apr_pool_t *pool;  
54  #if APR_HAS_THREADS  #if APR_HAS_THREADS
     apr_thread_mutex_t *mutex;  
     apr_reslist_t *reslist;  
     int destroyed;  
55      int nmin;      int nmin;
56      int nkeep;      int nkeep;
57      int nmax;      int nmax;
58      int exptime;      int exptime;
59      int set;      int set;
60    #endif
61        apr_hash_t *queries;
62    } dbd_cfg_t;
63    
64    typedef struct dbd_group_t dbd_group_t;
65    
66    struct dbd_group_t {
67        dbd_cfg_t *cfg;
68        dbd_group_t *next;
69        apr_pool_t *pool;
70    #if APR_HAS_THREADS
71        apr_thread_mutex_t *mutex;
72        apr_reslist_t *reslist;
73        int destroyed;
74  #else  #else
75      ap_dbd_t *rec;      ap_dbd_t *rec;
76  #endif  #endif
77    };
78    
79    typedef struct {
80        dbd_cfg_t *cfg;
81        dbd_group_t *group;
82  } svr_cfg;  } svr_cfg;
83    
84  typedef enum { cmd_name, cmd_params, cmd_persist,  typedef enum { cmd_name, cmd_params, cmd_persist,
85                 cmd_min, cmd_keep, cmd_max, cmd_exp                 cmd_min, cmd_keep, cmd_max, cmd_exp
86  } cmd_parts;  } cmd_parts;
87    
88  static apr_hash_t *dbd_prepared_defns;  static apr_pool_t *config_pool;
89    static dbd_group_t *group_list;
90    
91  /* a default DBDriver value that'll generate meaningful error messages */  /* a default DBDriver value that'll generate meaningful error messages */
92  static const char *const no_dbdriver = "[DBDriver unset]";  static const char *const no_dbdriver = "[DBDriver unset]";
# Line 94  static const char *const no_dbdriver = " Line 102  static const char *const no_dbdriver = "
102  static void *create_dbd_config(apr_pool_t *pool, server_rec *s)  static void *create_dbd_config(apr_pool_t *pool, server_rec *s)
103  {  {
104      svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg));      svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg));
105        dbd_cfg_t *cfg = svr->cfg = apr_pcalloc(pool, sizeof(dbd_cfg_t));
106    
107      svr->server = s;      cfg->server = s;
108      svr->name = no_dbdriver; /* to generate meaningful error messages */      cfg->name = no_dbdriver; /* to generate meaningful error messages */
109      svr->params = ""; /* don't risk segfault on misconfiguration */      cfg->params = ""; /* don't risk segfault on misconfiguration */
110      svr->persist = -1;      cfg->persist = -1;
111  #if APR_HAS_THREADS  #if APR_HAS_THREADS
112      svr->nmin = DEFAULT_NMIN;      cfg->nmin = DEFAULT_NMIN;
113      svr->nkeep = DEFAULT_NKEEP;      cfg->nkeep = DEFAULT_NKEEP;
114      svr->nmax = DEFAULT_NMAX;      cfg->nmax = DEFAULT_NMAX;
115      svr->exptime = DEFAULT_EXPTIME;      cfg->exptime = DEFAULT_EXPTIME;
116  #endif  #endif
117        cfg->queries = apr_hash_make(pool);
118    
119      return svr;      return svr;
120  }  }
121    
122  static void *merge_dbd_config(apr_pool_t *pool, void *basev, void *addv)  static void *merge_dbd_config(apr_pool_t *pool, void *basev, void *addv)
123  {  {
124      svr_cfg *base = (svr_cfg*) basev;      dbd_cfg_t *base = ((svr_cfg*) basev)->cfg;
125      svr_cfg *add = (svr_cfg*) addv;      dbd_cfg_t *add = ((svr_cfg*) addv)->cfg;
126      svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg));      svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg));
127        dbd_cfg_t *new = svr->cfg = apr_pcalloc(pool, sizeof(dbd_cfg_t));
128    
129      svr->server = add->server;      new->server = add->server;
130      svr->name = (add->name != no_dbdriver) ? add->name : base->name;      new->name = (add->name != no_dbdriver) ? add->name : base->name;
131      svr->params = strcmp(add->params, "") ? add->params : base->params;      new->params = strcmp(add->params, "") ? add->params : base->params;
132      svr->persist = (add->persist != -1) ? add->persist : base->persist;      new->persist = (add->persist != -1) ? add->persist : base->persist;
133  #if APR_HAS_THREADS  #if APR_HAS_THREADS
134      svr->nmin = (add->set&NMIN_SET) ? add->nmin : base->nmin;      new->nmin = (add->set&NMIN_SET) ? add->nmin : base->nmin;
135      svr->nkeep = (add->set&NKEEP_SET) ? add->nkeep : base->nkeep;      new->nkeep = (add->set&NKEEP_SET) ? add->nkeep : base->nkeep;
136      svr->nmax = (add->set&NMAX_SET) ? add->nmax : base->nmax;      new->nmax = (add->set&NMAX_SET) ? add->nmax : base->nmax;
137      svr->exptime = (add->set&EXPTIME_SET) ? add->exptime : base->exptime;      new->exptime = (add->set&EXPTIME_SET) ? add->exptime : base->exptime;
138  #endif  #endif
139        new->queries = apr_hash_overlay(pool, add->queries, base->queries);
140    
141      return svr;      return svr;
142  }  }
# Line 144  static const char *dbd_param(cmd_parms * Line 156  static const char *dbd_param(cmd_parms *
156      const apr_dbd_driver_t *driver = NULL;      const apr_dbd_driver_t *driver = NULL;
157      svr_cfg *svr = ap_get_module_config(cmd->server->module_config,      svr_cfg *svr = ap_get_module_config(cmd->server->module_config,
158                                          &dbd_module);                                          &dbd_module);
159        dbd_cfg_t *cfg = svr->cfg;
160    
161      switch ((long) cmd->info) {      switch ((long) cmd->info) {
162      case cmd_name:      case cmd_name:
163          svr->name = val;          cfg->name = val;
164          /* loading the driver involves once-only dlloading that is          /* loading the driver involves once-only dlloading that is
165           * best done at server startup.  This also guarantees that           * best done at server startup.  This also guarantees that
166           * we won't return an error later.           * we won't return an error later.
167           */           */
168          switch (apr_dbd_get_driver(cmd->pool, svr->name, &driver)) {          switch (apr_dbd_get_driver(cmd->pool, cfg->name, &driver)) {
169          case APR_ENOTIMPL:          case APR_ENOTIMPL:
170              return apr_psprintf(cmd->pool, "DBD: No driver for %s", svr->name);              return apr_psprintf(cmd->pool, "DBD: No driver for %s", cfg->name);
171          case APR_EDSOOPEN:          case APR_EDSOOPEN:
172              return apr_psprintf(cmd->pool,              return apr_psprintf(cmd->pool,
173                                  "DBD: Can't load driver file apr_dbd_%s.so",                                  "DBD: Can't load driver file apr_dbd_%s.so",
174                                  svr->name);                                  cfg->name);
175          case APR_ESYMNOTFOUND:          case APR_ESYMNOTFOUND:
176              return apr_psprintf(cmd->pool,              return apr_psprintf(cmd->pool,
177                                  "DBD: Failed to load driver apr_dbd_%s_driver",                                  "DBD: Failed to load driver apr_dbd_%s_driver",
178                                  svr->name);                                  cfg->name);
179          }          }
180          break;          break;
181      case cmd_params:      case cmd_params:
182          svr->params = val;          cfg->params = val;
183          break;          break;
184  #if APR_HAS_THREADS  #if APR_HAS_THREADS
185      case cmd_min:      case cmd_min:
186          ISINT(val);          ISINT(val);
187          svr->nmin = atoi(val);          cfg->nmin = atoi(val);
188          svr->set |= NMIN_SET;          cfg->set |= NMIN_SET;
189          break;          break;
190      case cmd_keep:      case cmd_keep:
191          ISINT(val);          ISINT(val);
192          svr->nkeep = atoi(val);          cfg->nkeep = atoi(val);
193          svr->set |= NKEEP_SET;          cfg->set |= NKEEP_SET;
194          break;          break;
195      case cmd_max:      case cmd_max:
196          ISINT(val);          ISINT(val);
197          svr->nmax = atoi(val);          cfg->nmax = atoi(val);
198          svr->set |= NMAX_SET;          cfg->set |= NMAX_SET;
199          break;          break;
200      case cmd_exp:      case cmd_exp:
201          ISINT(val);          ISINT(val);
202          svr->exptime = atoi(val);          cfg->exptime = atoi(val);
203          svr->set |= EXPTIME_SET;          cfg->set |= EXPTIME_SET;
204          break;          break;
205  #endif  #endif
206      }      }
# Line 202  static const char *dbd_param_flag(cmd_pa Line 215  static const char *dbd_param_flag(cmd_pa
215    
216      switch ((long) cmd->info) {      switch ((long) cmd->info) {
217      case cmd_persist:      case cmd_persist:
218          svr->persist = flag;          svr->cfg->persist = flag;
219          break;          break;
220      }      }
221    
# Line 212  static const char *dbd_param_flag(cmd_pa Line 225  static const char *dbd_param_flag(cmd_pa
225  static const char *dbd_prepare(cmd_parms *cmd, void *dconf, const char *query,  static const char *dbd_prepare(cmd_parms *cmd, void *dconf, const char *query,
226                                 const char *label)                                 const char *label)
227  {  {
228        if (!label) {
229            label = query;
230            query = "";
231        }
232    
233      ap_dbd_prepare(cmd->server, query, label);      ap_dbd_prepare(cmd->server, query, label);
234    
235      return NULL;      return NULL;
# Line 224  static const command_rec dbd_cmds[] = { Line 242  static const command_rec dbd_cmds[] = {
242                    "SQL Driver Params"),                    "SQL Driver Params"),
243      AP_INIT_FLAG("DBDPersist", dbd_param_flag, (void*)cmd_persist, RSRC_CONF,      AP_INIT_FLAG("DBDPersist", dbd_param_flag, (void*)cmd_persist, RSRC_CONF,
244                   "Use persistent connection/pool"),                   "Use persistent connection/pool"),
245      AP_INIT_TAKE2("DBDPrepareSQL", dbd_prepare, NULL, RSRC_CONF,      AP_INIT_TAKE12("DBDPrepareSQL", dbd_prepare, NULL, RSRC_CONF,
246                    "SQL statement to prepare and label"),                     "SQL statement to prepare (or nothing, to override "
247                       "statement inherited from main server) and label"),
248  #if APR_HAS_THREADS  #if APR_HAS_THREADS
249      AP_INIT_TAKE1("DBDMin", dbd_param, (void*)cmd_min, RSRC_CONF,      AP_INIT_TAKE1("DBDMin", dbd_param, (void*)cmd_min, RSRC_CONF,
250                    "Minimum number of connections"),                    "Minimum number of connections"),
# Line 244  static const command_rec dbd_cmds[] = { Line 263  static const command_rec dbd_cmds[] = {
263  static int dbd_pre_config(apr_pool_t *pconf, apr_pool_t *plog,  static int dbd_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
264                            apr_pool_t *ptemp)                            apr_pool_t *ptemp)
265  {  {
266     dbd_prepared_defns = apr_hash_make(ptemp);     config_pool = pconf;
267       group_list = NULL;
268     return OK;     return OK;
269  }  }
270    
271  DBD_DECLARE_NONSTD(void) ap_dbd_prepare(server_rec *s, const char *query,  DBD_DECLARE_NONSTD(void) ap_dbd_prepare(server_rec *s, const char *query,
272                                          const char *label)                                          const char *label)
273  {  {
274      dbd_prepared *prepared = apr_pcalloc(s->process->pool,      svr_cfg *svr;
275                                           sizeof(dbd_prepared));  
276      const char *key = apr_psprintf(s->process->pool, "%pp", s);      svr = ap_get_module_config(s->module_config, &dbd_module);
277        if (!svr) {
278      prepared->label = label;           /* some modules may call from within config directive handlers, and
279      prepared->query = query;            * if these are called in a server context that contains no mod_dbd
280      prepared->next = apr_hash_get(dbd_prepared_defns, key, APR_HASH_KEY_STRING);            * config directives, then we have to create our own server config
281              */
282             svr = create_dbd_config(config_pool, s);
283             ap_set_module_config(s->module_config, &dbd_module, svr);
284        }
285    
286      apr_hash_set(dbd_prepared_defns, key, APR_HASH_KEY_STRING, prepared);      if (apr_hash_get(svr->cfg->queries, label, APR_HASH_KEY_STRING)
287            && strcmp(query, "")) {
288            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
289                         "conflicting SQL statements with label %s", label);
290  }  }
291    
292        apr_hash_set(svr->cfg->queries, label, APR_HASH_KEY_STRING, query);
293    }
294    
295    typedef struct {
296        const char *label, *query;
297    } dbd_query_t;
298    
299  static int dbd_post_config(apr_pool_t *pconf, apr_pool_t *plog,  static int dbd_post_config(apr_pool_t *pconf, apr_pool_t *plog,
300                             apr_pool_t *ptemp, server_rec *s)                             apr_pool_t *ptemp, server_rec *s)
301  {  {
302      server_rec *sp;      server_rec *sp;
303        apr_array_header_t *add_queries = apr_array_make(ptemp, 10,
304                                                         sizeof(dbd_query_t));
305    
306      for (sp = s; sp; sp = sp->next) {      for (sp = s; sp; sp = sp->next) {
307          svr_cfg *svr = ap_get_module_config(sp->module_config, &dbd_module);          svr_cfg *svr = ap_get_module_config(sp->module_config, &dbd_module);
308          const char *key = apr_psprintf(ptemp, "%pp", s);          dbd_cfg_t *cfg = svr->cfg;
309            apr_hash_index_t *hi_first = apr_hash_first(ptemp, cfg->queries);
310            dbd_group_t *group;
311    
312          svr->prepared = apr_hash_get(dbd_prepared_defns, key,          /* dbd_setup in 2.2.3 and under was causing spurious error messages
313             * when dbd isn't configured.  We can stop that with a quick check here
314             * together with a similar check in ap_dbd_open (where being
315             * unconfigured is a genuine error that must be reported).
316             */
317            if (cfg->name == no_dbdriver || !cfg->persist) {
318                continue;
319            }
320    
321            for (group = group_list; group; group = group->next) {
322                dbd_cfg_t *group_cfg = group->cfg;
323                apr_hash_index_t *hi;
324                int group_ok = 1;
325    
326                if (strcmp(cfg->name, group_cfg->name)
327                    || strcmp(cfg->params, group_cfg->params)) {
328                    continue;
329                }
330    
331    #if APR_HAS_THREADS
332                if (cfg->nmin != group_cfg->nmin
333                    || cfg->nkeep != group_cfg->nkeep
334                    || cfg->nmax != group_cfg->nmax
335                    || cfg->exptime != group_cfg->exptime) {
336                    continue;
337                }
338    #endif
339    
340                add_queries->nelts = 0;
341    
342                for (hi = hi_first; hi; hi = apr_hash_next(hi)) {
343                    const char *label, *query;
344                    const char *group_query;
345    
346                    apr_hash_this(hi, (void*) &label, NULL, (void*) &query);
347    
348                    group_query = apr_hash_get(group_cfg->queries, label,
349                                       APR_HASH_KEY_STRING);                                       APR_HASH_KEY_STRING);
350    
351                    if (!group_query) {
352                        dbd_query_t *add_query = apr_array_push(add_queries);
353    
354                        add_query->label = label;
355                        add_query->query = query;
356                    }
357                    else if (strcmp(query, group_query)) {
358                        group_ok = 0;
359                        break;
360                    }
361                }
362    
363                if (group_ok) {
364                    int i;
365    
366                    for (i = 0; i < add_queries->nelts; ++i) {
367                        dbd_query_t *add_query = ((dbd_query_t*) add_queries->elts)
368                                                 + i;
369    
370                        apr_hash_set(group_cfg->queries, add_query->label,
371                                     APR_HASH_KEY_STRING, add_query->query);
372                    }
373    
374                    svr->group = group;
375                    break;
376                }
377            }
378    
379            if (!svr->group) {
380                svr->group = group = apr_pcalloc(pconf, sizeof(dbd_group_t));
381    
382                group->cfg = cfg;
383    
384                group->next = group_list;
385                group_list = group;
386            }
387      }      }
388    
389      return OK;      return OK;
390  }  }
391    
392  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,
393                                        ap_dbd_t *rec)                                        ap_dbd_t *rec)
394  {  {
395      dbd_prepared *p;      apr_hash_index_t *hi;
396      apr_status_t rv = APR_SUCCESS;      apr_status_t rv = APR_SUCCESS;
     apr_dbd_prepared_t *stmt;  
397    
398      rec->prepared = apr_hash_make(pool);      rec->prepared = apr_hash_make(pool);
399    
400      for (p = svr->prepared; p; p = p->next) {      for (hi = apr_hash_first(pool, cfg->queries); hi;
401             hi = apr_hash_next(hi)) {
402            const char *label, *query;
403            apr_dbd_prepared_t *stmt;
404    
405            apr_hash_this(hi, (void*) &label, NULL, (void*) &query);
406    
407            if (!strcmp(query, "")) {
408                continue;
409            }
410    
411          stmt = NULL;          stmt = NULL;
412          if (apr_dbd_prepare(rec->driver, pool, rec->handle, p->query,          if (apr_dbd_prepare(rec->driver, pool, rec->handle, query,
413                              p->label, &stmt) == 0) {                              label, &stmt)) {
414              apr_hash_set(rec->prepared, p->label, APR_HASH_KEY_STRING, stmt);              rv = APR_EGENERAL;
415          }          }
416          else {          else {
417              rv = APR_EGENERAL;              apr_hash_set(rec->prepared, label, APR_HASH_KEY_STRING, stmt);
418          }          }
419      }      }
420    
# Line 311  static apr_status_t dbd_close(void *data Line 431  static apr_status_t dbd_close(void *data
431  #if APR_HAS_THREADS  #if APR_HAS_THREADS
432  static apr_status_t dbd_destruct(void *data, void *params, apr_pool_t *pool)  static apr_status_t dbd_destruct(void *data, void *params, apr_pool_t *pool)
433  {  {
434      svr_cfg *svr = params;      dbd_group_t *group = params;
435    
436      if (!svr->destroyed) {      if (!group->destroyed) {
437          ap_dbd_t *rec = data;          ap_dbd_t *rec = data;
438    
439          apr_pool_destroy(rec->pool);          apr_pool_destroy(rec->pool);
# Line 330  static apr_status_t dbd_destruct(void *d Line 450  static apr_status_t dbd_destruct(void *d
450  static apr_status_t dbd_construct(void **data_ptr,  static apr_status_t dbd_construct(void **data_ptr,
451                                    void *params, apr_pool_t *pool)                                    void *params, apr_pool_t *pool)
452  {  {
453      svr_cfg *svr = params;      dbd_group_t *group = params;
454        dbd_cfg_t *cfg = group->cfg;
455      apr_pool_t *rec_pool, *prepared_pool;      apr_pool_t *rec_pool, *prepared_pool;
456      ap_dbd_t *rec;      ap_dbd_t *rec;
457      apr_status_t rv;      apr_status_t rv;
458    
459      rv = apr_pool_create(&rec_pool, pool);      rv = apr_pool_create(&rec_pool, pool);
460      if (rv != APR_SUCCESS) {      if (rv != APR_SUCCESS) {
461          ap_log_error(APLOG_MARK, APLOG_CRIT, rv, svr->server,          ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->server,
462                       "DBD: Failed to create memory pool");                       "DBD: Failed to create memory pool");
463          return rv;          return rv;
464      }      }
# Line 351  static apr_status_t dbd_construct(void * Line 472  static apr_status_t dbd_construct(void *
472       * our pool, which is probably not what we want.  Error checking isn't       * our pool, which is probably not what we want.  Error checking isn't
473       * necessary now, but in case that changes in the future ...       * necessary now, but in case that changes in the future ...
474       */       */
475      rv = apr_dbd_get_driver(rec->pool, svr->name, &rec->driver);      rv = apr_dbd_get_driver(rec->pool, cfg->name, &rec->driver);
476      if (rv != APR_SUCCESS) {      if (rv != APR_SUCCESS) {
477          switch (rv) {          switch (rv) {
478          case APR_ENOTIMPL:          case APR_ENOTIMPL:
479              ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,              ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
480                           "DBD: driver for %s not available", svr->name);                           "DBD: driver for %s not available", cfg->name);
481              break;              break;
482          case APR_EDSOOPEN:          case APR_EDSOOPEN:
483              ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,              ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
484                           "DBD: can't find driver for %s", svr->name);                           "DBD: can't find driver for %s", cfg->name);
485              break;              break;
486          case APR_ESYMNOTFOUND:          case APR_ESYMNOTFOUND:
487              ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,              ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
488                           "DBD: driver for %s is invalid or corrupted",                           "DBD: driver for %s is invalid or corrupted",
489                           svr->name);                           cfg->name);
490              break;              break;
491          default:          default:
492              ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,              ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
493                           "DBD: mod_dbd not compatible with APR in get_driver");                           "DBD: mod_dbd not compatible with APR in get_driver");
494              break;              break;
495          }          }
# Line 377  static apr_status_t dbd_construct(void * Line 498  static apr_status_t dbd_construct(void *
498          return rv;          return rv;
499      }      }
500    
501      rv = apr_dbd_open(rec->driver, rec->pool, svr->params, &rec->handle);      rv = apr_dbd_open(rec->driver, rec->pool, cfg->params, &rec->handle);
502      if (rv != APR_SUCCESS) {      if (rv != APR_SUCCESS) {
503          switch (rv) {          switch (rv) {
504          case APR_EGENERAL:          case APR_EGENERAL:
505              ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,              ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
506                           "DBD: Can't connect to %s", svr->name);                           "DBD: Can't connect to %s", cfg->name);
507              break;              break;
508          default:          default:
509              ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,              ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
510                           "DBD: mod_dbd not compatible with APR in open");                           "DBD: mod_dbd not compatible with APR in open");
511              break;              break;
512          }          }
# Line 402  static apr_status_t dbd_construct(void * Line 523  static apr_status_t dbd_construct(void *
523       */       */
524      rv = apr_pool_create(&prepared_pool, rec->pool);      rv = apr_pool_create(&prepared_pool, rec->pool);
525      if (rv != APR_SUCCESS) {      if (rv != APR_SUCCESS) {
526          ap_log_error(APLOG_MARK, APLOG_CRIT, rv, svr->server,          ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->server,
527                       "DBD: Failed to create memory pool");                       "DBD: Failed to create memory pool");
528    
529          apr_pool_destroy(rec->pool);          apr_pool_destroy(rec->pool);
530          return rv;          return rv;
531      }      }
532    
533      rv = dbd_prepared_init(prepared_pool, svr, rec);      rv = dbd_prepared_init(prepared_pool, cfg, rec);
534      if (rv != APR_SUCCESS) {      if (rv != APR_SUCCESS) {
535          const char *errmsg = apr_dbd_error(rec->driver, rec->handle, rv);          const char *errmsg = apr_dbd_error(rec->driver, rec->handle, rv);
536          ap_log_error(APLOG_MARK, APLOG_ERR, rv, svr->server,          ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
537                       "DBD: failed to prepare SQL statements: %s",                       "DBD: failed to prepare SQL statements: %s",
538                       (errmsg ? errmsg : "[???]"));                       (errmsg ? errmsg : "[???]"));
539    
# Line 428  static apr_status_t dbd_construct(void * Line 549  static apr_status_t dbd_construct(void *
549  #if APR_HAS_THREADS  #if APR_HAS_THREADS
550  static apr_status_t dbd_destroy(void *data)  static apr_status_t dbd_destroy(void *data)
551  {  {
552      svr_cfg *svr = data;      dbd_group_t *group = data;
553    
554      svr->destroyed = 1;      group->destroyed = 1;
555    
556      return APR_SUCCESS;      return APR_SUCCESS;
557  }  }
558    
559  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)
560  {  {
561        dbd_cfg_t *cfg = group->cfg;
562      apr_status_t rv;      apr_status_t rv;
563    
564      /* We create the reslist using a sub-pool of the pool passed to our      /* We create the reslist using a sub-pool of the pool passed to our
# Line 457  static apr_status_t dbd_setup(server_rec Line 579  static apr_status_t dbd_setup(server_rec
579       * on each resource, which would then attempt to destroy the sub-pools       * on each resource, which would then attempt to destroy the sub-pools
580       * a second time.       * a second time.
581       */       */
582      rv = apr_reslist_create(&svr->reslist,      rv = apr_reslist_create(&group->reslist,
583                              svr->nmin, svr->nkeep, svr->nmax,                              cfg->nmin, cfg->nkeep, cfg->nmax,
584                              apr_time_from_sec(svr->exptime),                              apr_time_from_sec(cfg->exptime),
585                              dbd_construct, dbd_destruct, svr,                              dbd_construct, dbd_destruct, group,
586                              svr->pool);                              group->pool);
587      if (rv != APR_SUCCESS) {      if (rv != APR_SUCCESS) {
588          ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,          ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
589                       "DBD: failed to initialise");                       "DBD: failed to initialise");
590          return rv;          return rv;
591      }      }
592    
593      apr_pool_cleanup_register(svr->pool, svr, dbd_destroy,      apr_pool_cleanup_register(group->pool, group, dbd_destroy,
594                                apr_pool_cleanup_null);                                apr_pool_cleanup_null);
595    
596      return APR_SUCCESS;      return APR_SUCCESS;
# Line 477  static apr_status_t dbd_setup(server_rec Line 599  static apr_status_t dbd_setup(server_rec
599    
600  static apr_status_t dbd_setup_init(apr_pool_t *pool, server_rec *s)  static apr_status_t dbd_setup_init(apr_pool_t *pool, server_rec *s)
601  {  {
602      svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);      dbd_group_t *group;
603      apr_status_t rv;      apr_status_t rv = APR_SUCCESS;
   
     /* 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;  
     }  
604    
605      if (!svr->persist) {      for (group = group_list; group; group = group->next) {
606          return APR_SUCCESS;          apr_status_t rv2;
     }  
607    
608      rv = apr_pool_create(&svr->pool, pool);          rv2 = apr_pool_create(&group->pool, pool);
609      if (rv != APR_SUCCESS) {          if (rv2 != APR_SUCCESS) {
610          ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,              ap_log_error(APLOG_MARK, APLOG_CRIT, rv2, s,
611                       "DBD: Failed to create reslist cleanup memory pool");                       "DBD: Failed to create reslist cleanup memory pool");
612          return rv;              return rv2;
613      }      }
614    
615  #if APR_HAS_THREADS  #if APR_HAS_THREADS
616      rv = dbd_setup(s, svr);          rv2 = dbd_setup(s, group);
617      if (rv == APR_SUCCESS) {          if (rv2 == APR_SUCCESS) {
618          return rv;              continue;
619            }
620            else if (rv == APR_SUCCESS) {
621                rv = rv2;
622      }      }
623    
624      /* we failed, so create a mutex so that subsequent competing callers      /* we failed, so create a mutex so that subsequent competing callers
625       * to ap_dbd_open can serialize themselves while they retry       * to ap_dbd_open can serialize themselves while they retry
626       */       */
627      rv = apr_thread_mutex_create(&svr->mutex,          rv2 = apr_thread_mutex_create(&group->mutex,
628                                   APR_THREAD_MUTEX_DEFAULT, pool);                                   APR_THREAD_MUTEX_DEFAULT, pool);
629      if (rv != APR_SUCCESS) {          if (rv2 != APR_SUCCESS) {
630          ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,               ap_log_error(APLOG_MARK, APLOG_CRIT, rv2, s,
631                       "DBD: Failed to create thread mutex");                       "DBD: Failed to create thread mutex");
632                 return rv2;
633      }      }
634  #endif  #endif
635        }
636    
637      return rv;      return rv;
638  }  }
639    
640  #if APR_HAS_THREADS  #if APR_HAS_THREADS
641  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)
642  {  {
643      apr_status_t rv = APR_SUCCESS, rv2;      apr_status_t rv = APR_SUCCESS, rv2;
644    
645      /* several threads could be here at the same time, all trying to      /* several threads could be here at the same time, all trying to
646       * initialize the reslist because dbd_setup_init failed to do so       * initialize the reslist because dbd_setup_init failed to do so
647       */       */
648      if (!svr->mutex) {      if (!group->mutex) {
649          /* we already logged an error when the mutex couldn't be created */          /* we already logged an error when the mutex couldn't be created */
650          return APR_EGENERAL;          return APR_EGENERAL;
651      }      }
652    
653      rv2 = apr_thread_mutex_lock(svr->mutex);      rv2 = apr_thread_mutex_lock(group->mutex);
654      if (rv2 != APR_SUCCESS) {      if (rv2 != APR_SUCCESS) {
655          ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s,          ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s,
656                       "DBD: Failed to acquire thread mutex");                       "DBD: Failed to acquire thread mutex");
657          return rv2;          return rv2;
658      }      }
659    
660      if (!svr->reslist) {      if (!group->reslist) {
661          rv = dbd_setup(s, svr);          rv = dbd_setup(s, group);
662      }      }
663    
664      rv2 = apr_thread_mutex_unlock(svr->mutex);      rv2 = apr_thread_mutex_unlock(group->mutex);
665      if (rv2 != APR_SUCCESS) {      if (rv2 != APR_SUCCESS) {
666          ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s,          ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s,
667                       "DBD: Failed to release thread mutex");                       "DBD: Failed to release thread mutex");
# Line 565  DBD_DECLARE_NONSTD(void) ap_dbd_close(se Line 682  DBD_DECLARE_NONSTD(void) ap_dbd_close(se
682  {  {
683      svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);      svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);
684    
685      if (!svr->persist) {      if (!svr->cfg->persist) {
686          apr_pool_destroy(rec->pool);          apr_pool_destroy(rec->pool);
687      }      }
688  #if APR_HAS_THREADS  #if APR_HAS_THREADS
689      else {      else {
690          apr_reslist_release(svr->reslist, rec);          apr_reslist_release(svr->group->reslist, rec);
691      }      }
692  #endif  #endif
693  }  }
# Line 592  static apr_status_t dbd_check(apr_pool_t Line 709  static apr_status_t dbd_check(apr_pool_t
709    
710      svr = ap_get_module_config(s->module_config, &dbd_module);      svr = ap_get_module_config(s->module_config, &dbd_module);
711      ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,      ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
712                   "DBD [%s] Error: %s", svr->name, errmsg);                   "DBD [%s] Error: %s", svr->cfg->name, errmsg);
713      return rv;      return rv;
714  }  }
715    
716  DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_open(apr_pool_t *pool, server_rec *s)  DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_open(apr_pool_t *pool, server_rec *s)
717  {  {
718      svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);      svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);
719        dbd_group_t *group = svr->group;
720        dbd_cfg_t *cfg = svr->cfg;
721      ap_dbd_t *rec = NULL;      ap_dbd_t *rec = NULL;
722  #if APR_HAS_THREADS  #if APR_HAS_THREADS
723      apr_status_t rv;      apr_status_t rv;
724  #endif  #endif
725    
726      /* If nothing is configured, we shouldn't be here */      /* If nothing is configured, we shouldn't be here */
727      if (svr->name == no_dbdriver) {      if (cfg->name == no_dbdriver) {
728          ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "DBD: not configured");          ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "DBD: not configured");
729          return NULL;          return NULL;
730      }      }
731    
732      if (!svr->persist) {      if (!cfg->persist) {
733          /* Return a once-only connection */          /* Return a once-only connection */
734          dbd_construct((void*) &rec, svr, pool);          group = apr_pcalloc(pool, sizeof(dbd_group_t));
735    
736            group->cfg = cfg;
737    
738            dbd_construct((void*) &rec, group, pool);
739          return rec;          return rec;
740      }      }
741    
742  #if APR_HAS_THREADS  #if APR_HAS_THREADS
743      if (!svr->reslist) {      if (!group->reslist) {
744          if (dbd_setup_lock(s, svr) != APR_SUCCESS) {          if (dbd_setup_lock(s, group) != APR_SUCCESS) {
745              return NULL;              return NULL;
746          }          }
747      }      }
748    
749      rv = apr_reslist_acquire(svr->reslist, (void*) &rec);      rv = apr_reslist_acquire(group->reslist, (void*) &rec);
750      if (rv != APR_SUCCESS) {      if (rv != APR_SUCCESS) {
751          ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,          ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
752                       "Failed to acquire DBD connection from pool!");                       "Failed to acquire DBD connection from pool!");
# Line 631  DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_ope Line 754  DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_ope
754      }      }
755    
756      if (dbd_check(pool, s, rec) != APR_SUCCESS) {      if (dbd_check(pool, s, rec) != APR_SUCCESS) {
757          apr_reslist_invalidate(svr->reslist, rec);          apr_reslist_invalidate(group->reslist, rec);
758          return NULL;          return NULL;
759      }      }
760  #else  #else
761      /* If we have a persistent connection and it's good, we'll use it;      /* If we have a persistent connection and it's good, we'll use it;
762       * since this is non-threaded, we can update without a mutex       * since this is non-threaded, we can update without a mutex
763       */       */
764      rec = svr->rec;      rec = group->rec;
765      if (rec) {      if (rec) {
766          if (dbd_check(pool, s, rec) != APR_SUCCESS) {          if (dbd_check(pool, s, rec) != APR_SUCCESS) {
767              apr_pool_destroy(rec->pool);              apr_pool_destroy(rec->pool);
# Line 648  DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_ope Line 771  DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_ope
771    
772      /* We don't have a connection right now, so we'll open one */      /* We don't have a connection right now, so we'll open one */
773      if (!rec) {      if (!rec) {
774          dbd_construct((void*) &rec, svr, svr->pool);          dbd_construct((void*) &rec, group, group->pool);
775          svr->rec = rec;          group->rec = rec;
776      }      }
777  #endif  #endif
778    
# Line 691  DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_ac Line 814  DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_ac
814                                                  &dbd_module);                                                  &dbd_module);
815    
816              ap_set_module_config(r->request_config, &dbd_module, acq);              ap_set_module_config(r->request_config, &dbd_module, acq);
817              if (svr->persist) {              if (svr->cfg->persist) {
818                  acq->reslist = svr->reslist;                  acq->reslist = svr->group->reslist;
819                  apr_pool_cleanup_register(r->pool, acq, dbd_release,                  apr_pool_cleanup_register(r->pool, acq, dbd_release,
820                                            apr_pool_cleanup_null);                                            apr_pool_cleanup_null);
821              }              }
# Line 714  DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_ca Line 837  DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_ca
837                                                  &dbd_module);                                                  &dbd_module);
838    
839              ap_set_module_config(c->conn_config, &dbd_module, acq);              ap_set_module_config(c->conn_config, &dbd_module, acq);
840              if (svr->persist) {              if (svr->cfg->persist) {
841                  acq->reslist = svr->reslist;                  acq->reslist = svr->group->reslist;
842                  apr_pool_cleanup_register(c->pool, acq, dbd_release,                  apr_pool_cleanup_register(c->pool, acq, dbd_release,
843                                            apr_pool_cleanup_null);                                            apr_pool_cleanup_null);
844              }              }

Legend:
Removed from v.496831  
changed lines
  Added in v.503931

apache@apache.org
ViewVC Help
Powered by ViewVC 1.1.2