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

Reply via email to