httpd-modules-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Kean Johnston <kean.johns...@gmail.com>
Subject Re: Apache module avoiding re-initialization of connection pool in every worker process
Date Wed, 01 Jan 2014 09:59:10 GMT
On 12/31/2013 10:52 AM, ksakhare wrote:
 > How can i initialization connection in once and use these connections across
 > the different worker process. Thanks in advacne.

I had a similar need and was pointed in the direction of APR "resource 
lists". Certainly the way I used them was a little different but this may 
address your needs.

First I ap_hook_child_init() with a function that does:
static void extfcgi_child_init(apr_pool_t *p, server_rec *s)
{
     apr_status_t rv;
     apr_hash_index_t *hi;
     extfcgi_ext_srv *esrv;
     int mpm_threads = 0;

     ap_mpm_query(AP_MPMQ_MAX_THREADS, &mpm_threads);
     if (mpm_threads < 1) {
         mpm_threads = 1;
     }

     for (hi = apr_hash_first(p, extfcgi_servers); hi; hi = 
apr_hash_next(hi)) {
         apr_hash_this(hi, NULL, NULL, &esrv);

         if (0 == esrv->pool) {
             rv = apr_pool_create(&esrv->pool, p);

             if (APR_SUCCESS != rv) {
                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
                              "Failed to create ExtfcgiServer '%s' pool",
                              esrv->name);
                 return;
             }
         }

         if (0 == esrv->reslist) {
             rv = apr_reslist_create(&esrv->reslist, 0, mpm_threads, 
mpm_threads,
                                     0, extfcgi_res_ctor, extfcgi_res_dtor, 
esrv,
                                     esrv->pool);

             if (APR_SUCCESS != rv) {
                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
                              "Failed to create ExtfcgiServer resource list");
                 return;
             }

             apr_pool_cleanup_register(esrv->pool, esrv, extfcgi_destroy,
                                       apr_pool_cleanup_none);
         }

         if (0 == esrv->keep_alive) {
             continue;
         }

         if (0 == esrv->is_lazy) {
             /* Prepare mpm_threads number of connections */
             int i;
             void **dummy = apr_pcalloc(p, mpm_threads * sizeof (void *));

             for (i = 0; i < mpm_threads; i++) {
                 rv = apr_reslist_acquire(esrv->reslist, &dummy[i]);
                 if (APR_SUCCESS != rv) {
                     ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
                         "Failed to create connection %d of %d for "
                         "ExtfcgiServer '%s'", i+1, mpm_threads,
                         esrv->name);
                     return;
                 }
             }

             /* Now release them so they are available to threads */
             for (i = 0; i < mpm_threads; i++) {
                 rv = apr_reslist_release(esrv->reslist, dummy[i]);
                 if (APR_SUCCESS != rv) {
                     ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
                         "Failed to release connection %d of %d for "
                         "ExtfcgiServer '%s'", i+1, mpm_threads,
                         esrv->name);
                     return;
                 }
             }
         }
     }
}

What this does is as each child process is created, it creates as many 
connections as there are threads in the MPM. It releases them so that when 
you get around to request handling and need a connection, it can just 
"acquire" the resource. Since the resource list has a number of open 
connections in it, that act of acquiring the resource gives you a 
connection you can use. For example this is what I do in my request handler:

     rv = apr_reslist_acquire(dconf->responder->reslist, &rctx->conn);
     if (APR_SUCCESS != rv) {
         ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
                       "could not acquire connection to ExtfcgiServer '%s'",
                       dconf->responder->name);
         return HTTP_INTERNAL_SERVER_ERROR;
     }

     /*
      * We need to register a cleanup handler for this request to ensure that
      * we release or destroy the reslist resource we just acquired when this
      * request is dealt with.
      */
     apr_pool_cleanup_register(r->pool, rctx, extfcgi_rctx_cleanup,
                               apr_pool_cleanup_null);

In extfcgi_rctx_cleanup among other things I do an apr_reslist_release() to 
release the connection back to the pool.

Hope this helps you.

Sincerely,
Kean

Mime
View raw message