Author: jfrederic.clere(a)jboss.com
Date: 2008-11-23 05:47:56 -0500 (Sun, 23 Nov 2008)
New Revision: 2065
Modified:
trunk/mod_cluster/native/mod_proxy_cluster/mod_proxy_cluster.c
Log:
move the relist creation to mod_proxy_cluster.c
Modified: trunk/mod_cluster/native/mod_proxy_cluster/mod_proxy_cluster.c
===================================================================
--- trunk/mod_cluster/native/mod_proxy_cluster/mod_proxy_cluster.c 2008-11-19 02:00:59 UTC
(rev 2064)
+++ trunk/mod_cluster/native/mod_proxy_cluster/mod_proxy_cluster.c 2008-11-23 10:47:56 UTC
(rev 2065)
@@ -34,6 +34,7 @@
#include "http_request.h"
#include "http_protocol.h"
#include "http_core.h"
+#include "ap_mpm.h"
#include "mod_proxy.h"
#include "mod_proxy_cluster.h"
@@ -66,20 +67,176 @@
#define WAITFORREMOVE 10 /* seconds */
#define TIMEINTERVAL apr_time_from_sec(1) /* recalcul the lbstatus based on number of
request in the time interval */
+
+
+/* reslist constructor */
+/* XXX: Should use the proxy_util one. */
+static apr_status_t connection_constructor(void **resource, void *params,
+ apr_pool_t *pool)
+{
+ apr_pool_t *ctx;
+ apr_pool_t *scpool;
+ proxy_conn_rec *conn;
+ proxy_worker *worker = (proxy_worker *)params;
+
+ /*
+ * Create the subpool for each connection
+ * This keeps the memory consumption constant
+ * when disconnecting from backend.
+ */
+ apr_pool_create(&ctx, pool);
+ conn = apr_pcalloc(pool, sizeof(proxy_conn_rec));
+
+ /*
+ * Create another subpool that manages the data for the
+ * socket and the connection member of the proxy_conn_rec struct as we
+ * destroy this data more frequently than other data in the proxy_conn_rec
+ * struct like hostname and addr (at least in the case where we have
+ * keepalive connections that timed out).
+ */
+#if AP_MODULE_MAGIC_AT_LEAST(20051115,13)
+ apr_pool_create(&scpool, ctx);
+ apr_pool_tag(scpool, "proxy_conn_scpool");
+ conn->scpool = scpool;
+#endif
+
+ conn->pool = ctx;
+ conn->worker = worker;
+#if APR_HAS_THREADS
+ conn->inreslist = 1;
+#endif
+ *resource = conn;
+
+ return APR_SUCCESS;
+}
+
+#if APR_HAS_THREADS /* only needed when threads are used */
+/* reslist destructor */
+/* XXX: Should use the proxy_util one. */
+static apr_status_t connection_destructor(void *resource, void *params,
+ apr_pool_t *pool)
+{
+ proxy_conn_rec *conn = (proxy_conn_rec *)resource;
+
+ /* Destroy the pool only if not called from reslist_destroy */
+ if (conn->worker->cp->pool) {
+ apr_pool_destroy(conn->pool);
+ }
+
+ return APR_SUCCESS;
+}
+#endif
+
+/* connection cleanup routine */
+/* XXX: Should use the proxy_util one. */
+static apr_status_t connection_cleanup(void *theconn)
+{
+ proxy_conn_rec *conn = (proxy_conn_rec *)theconn;
+ proxy_worker *worker = conn->worker;
+
+ /*
+ * If the connection pool is NULL the worker
+ * cleanup has been run. Just return.
+ */
+ if (!worker->cp) {
+ return APR_SUCCESS;
+ }
+
+#if APR_HAS_THREADS
+ /* Sanity check: Did we already return the pooled connection? */
+ if (conn->inreslist) {
+ ap_log_perror(APLOG_MARK, APLOG_ERR, 0, conn->pool,
+ "proxy: Pooled connection 0x%pp for worker %s has been"
+ " already returned to the connection pool.",
+ (void *) conn,
+ worker->name);
+ return APR_SUCCESS;
+ }
+#endif
+
+ /* determine if the connection need to be closed */
+#if MODULE_MAGIC_NUMBER_MAJOR>=20080722
+ if (conn->close)
+#else
+ if (conn->close_on_recycle || conn->close)
+#endif
+ {
+ apr_pool_t *p = conn->pool;
+ apr_pool_clear(conn->pool);
+ memset(conn, 0, sizeof(proxy_conn_rec));
+ conn->pool = p;
+ conn->worker = worker;
+ }
+#if APR_HAS_THREADS
+ if (worker->hmax && worker->cp->res) {
+ conn->inreslist = 1;
+ apr_reslist_release(worker->cp->res, (void *)conn);
+ }
+ else
+#endif
+ {
+ worker->cp->conn = conn;
+ }
+
+ /* Always return the SUCCESS */
+ return APR_SUCCESS;
+}
+
+/* XXX: Should use the proxy_util one. */
+#if APR_HAS_THREADS
+static apr_status_t conn_pool_cleanup(void *theworker)
+{
+ proxy_worker *worker = (proxy_worker *)theworker;
+ if (worker->cp->res) {
+ worker->cp->pool = NULL;
+ }
+ return APR_SUCCESS;
+}
+#endif
+
+/* XXX: Should use the proxy_util one. */
+static void init_conn_pool(apr_pool_t *p, proxy_worker *worker)
+{
+ apr_pool_t *pool;
+ proxy_conn_pool *cp;
+
+ /*
+ * Create a connection pool's subpool.
+ * This pool is used for connection recycling.
+ * Once the worker is added it is never removed but
+ * it can be disabled.
+ */
+ apr_pool_create(&pool, p);
+ apr_pool_tag(pool, "proxy_worker_cp");
+ /*
+ * Alloc from the same pool as worker.
+ * proxy_conn_pool is permanently attached to the worker.
+ */
+ cp = (proxy_conn_pool *)apr_pcalloc(p, sizeof(proxy_conn_pool));
+ cp->pool = pool;
+ worker->cp = cp;
+}
+
/*
* Create/Get the worker before using it
+ * XXX: Contains code of ap_proxy_initialize_worker (proxy_util.c)
+ * XXX: If something goes wrong the worker can't be used and we leak memory... in a
pool
*/
-static void create_worker(proxy_server_conf *conf, proxy_balancer *balancer,
+static apr_status_t create_worker(proxy_server_conf *conf, proxy_balancer *balancer,
server_rec *server, proxy_worker **worker,
nodeinfo_t *node, apr_pool_t *pool)
{
char *url;
char *ptr;
int reuse = 0;
+ apr_status_t rv = APR_SUCCESS;
#if AP_MODULE_MAGIC_AT_LEAST(20051115,4)
#else
proxy_cluster_helper *helperping;
#endif
+#if APR_HAS_THREADS
+ int mpm_threads;
+#endif
/* build the name (scheme and port) when needed */
url = apr_pstrcat(pool, node->mess.Type, "://", node->mess.Host,
":", node->mess.Port, NULL);
@@ -93,9 +250,11 @@
if (err) {
ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, server,
"Created: worker for %s failed: %s", url, err);
- return;
+ return APR_EGENERAL;
}
(*worker)->opaque = apr_pcalloc(conf->pool,
sizeof(proxy_cluster_helper));
+ if (!(*worker)->opaque)
+ return APR_EGENERAL;
helper = (*worker)->opaque;
helper->count_active = 0;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server,
@@ -117,7 +276,7 @@
reuse = 1;
} else {
/* XXX: (*worker)->id ?= node->mess.id; */
- return; /* Done Already existing */
+ return APR_SUCCESS; /* Done Already existing */
}
/* Get the shared memory for this worker */
@@ -150,7 +309,62 @@
(*worker)->is_address_reusable = 1;
(*worker)->acquire = apr_time_make(0, 2 * 1000); /* 2 ms */
(*worker)->retry = apr_time_from_sec(PROXY_WORKER_DEFAULT_RETRY);
-
+
+ /* from ap_proxy_initialize_worker() */
+#if APR_HAS_THREADS
+ ap_mpm_query(AP_MPMQ_MAX_THREADS, &mpm_threads);
+ if (mpm_threads > 1) {
+ /* Set hard max to no more then mpm_threads */
+ if ((*worker)->hmax == 0 || (*worker)->hmax > mpm_threads) {
+ (*worker)->hmax = mpm_threads;
+ }
+ if ((*worker)->smax == -1 || (*worker)->smax > (*worker)->hmax) {
+ (*worker)->smax = (*worker)->hmax;
+ }
+ /* Set min to be lower then smax */
+ if ((*worker)->min > (*worker)->smax) {
+ (*worker)->min = (*worker)->smax;
+ }
+ }
+ else {
+ /* This will supress the apr_reslist creation */
+ (*worker)->min = (*worker)->smax = (*worker)->hmax = 0;
+ }
+
+ if ((*worker)->hmax) {
+ rv = apr_reslist_create(&((*worker)->cp->res),
+ (*worker)->min, (*worker)->smax,
+ (*worker)->hmax, (*worker)->ttl,
+ connection_constructor, connection_destructor,
+ (*worker), (*worker)->cp->pool);
+
+ apr_pool_cleanup_register((*worker)->cp->pool, (void *)(*worker),
+ conn_pool_cleanup,
+ apr_pool_cleanup_null);
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server,
+ "proxy: initialized worker %d in child %" APR_PID_T_FMT " for
(%s) min=%d max=%d smax=%d",
+ (*worker)->id, getpid(), (*worker)->hostname, (*worker)->min,
+ (*worker)->hmax, (*worker)->smax);
+
+#if (APR_MAJOR_VERSION > 0)
+ /* Set the acquire timeout */
+ if (rv == APR_SUCCESS && (*worker)->acquire_set) {
+ apr_reslist_timeout_set((*worker)->cp->res, (*worker)->acquire);
+ }
+#endif
+ }
+ else
+#endif
+ {
+
+ rv = connection_constructor((void **)&((*worker)->cp->conn), (*worker),
(*worker)->cp->pool);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server,
+ "proxy: initialized single connection worker %d in child %"
APR_PID_T_FMT " for (%s)",
+ (*worker)->id, getpid(), (*worker)->hostname);
+ }
+ /* end from ap_proxy_initialize_worker() */
+
/*
* The Shared datastatus may already contains a valid information
*/
@@ -188,6 +402,7 @@
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server,
"Created: worker for %s %d (status): %d", url,
(*worker)->id, (*worker)->s->status);
+ return rv;
}
/*
@@ -408,102 +623,6 @@
}
}
-/* reslist constructor */
-/* XXX: Should use the proxy_util one. */
-static apr_status_t connection_constructor(void **resource, void *params,
- apr_pool_t *pool)
-{
- apr_pool_t *ctx;
- apr_pool_t *scpool;
- proxy_conn_rec *conn;
- proxy_worker *worker = (proxy_worker *)params;
-
- /*
- * Create the subpool for each connection
- * This keeps the memory consumption constant
- * when disconnecting from backend.
- */
- apr_pool_create(&ctx, pool);
- conn = apr_pcalloc(pool, sizeof(proxy_conn_rec));
-
- /*
- * Create another subpool that manages the data for the
- * socket and the connection member of the proxy_conn_rec struct as we
- * destroy this data more frequently than other data in the proxy_conn_rec
- * struct like hostname and addr (at least in the case where we have
- * keepalive connections that timed out).
- */
-#if AP_MODULE_MAGIC_AT_LEAST(20051115,13)
- apr_pool_create(&scpool, ctx);
- apr_pool_tag(scpool, "proxy_conn_scpool");
- conn->scpool = scpool;
-#endif
-
- conn->pool = ctx;
- conn->worker = worker;
-#if APR_HAS_THREADS
- conn->inreslist = 1;
-#endif
- *resource = conn;
-
- return APR_SUCCESS;
-}
-
-/* connection cleanup routine */
-/* XXX: Should use the proxy_util one. */
-static apr_status_t connection_cleanup(void *theconn)
-{
- proxy_conn_rec *conn = (proxy_conn_rec *)theconn;
- proxy_worker *worker = conn->worker;
-
- /*
- * If the connection pool is NULL the worker
- * cleanup has been run. Just return.
- */
- if (!worker->cp) {
- return APR_SUCCESS;
- }
-
-#if APR_HAS_THREADS
- /* Sanity check: Did we already return the pooled connection? */
- if (conn->inreslist) {
- ap_log_perror(APLOG_MARK, APLOG_ERR, 0, conn->pool,
- "proxy: Pooled connection 0x%pp for worker %s has been"
- " already returned to the connection pool.",
- (void *) conn,
- worker->name);
- return APR_SUCCESS;
- }
-#endif
-
- /* determine if the connection need to be closed */
-#if MODULE_MAGIC_NUMBER_MAJOR>=20080722
- if (conn->close)
-#else
- if (conn->close_on_recycle || conn->close)
-#endif
- {
- apr_pool_t *p = conn->pool;
- apr_pool_clear(conn->pool);
- memset(conn, 0, sizeof(proxy_conn_rec));
- conn->pool = p;
- conn->worker = worker;
- }
-#if APR_HAS_THREADS
- if (worker->hmax && worker->cp->res) {
- conn->inreslist = 1;
- apr_reslist_release(worker->cp->res, (void *)conn);
- }
- else
-#endif
- {
- worker->cp->conn = conn;
- }
-
- /* Always return the SUCCESS */
- return APR_SUCCESS;
-}
-
/* Retrieve the parameter with the given name
* Something like 'JSESSIONID=12345...N'
* XXX: Should use the mod_proxy_balancer ones.