Index: include/apr_reslist.h =================================================================== --- include/apr_reslist.h (revision 161086) +++ include/apr_reslist.h (revision 161087) @@ -112,6 +112,24 @@ APU_DECLARE(apr_status_t) apr_reslist_release(apr_reslist_t *reslist, void *resource); +/** + * Set the timeout the acquire will wait for a free resource + * when the maximum number of resources is exceeded. + * @param reslist The resource list. + * @param timeout Timeout to wait. The zero waits forewer. + */ +APU_DECLARE(void) apr_reslist_timeout_set(apr_reslist_t *reslist, + apr_interval_time_t timeout); + +/** + * Invalidate a resource in the pool - e.g. a database connection + * that returns a "lost connection" error and can't be restored. + * Use this instead of apr_reslist_release if the resource is bad. + */ +APU_DECLARE(apr_status_t) apr_reslist_invalidate(apr_reslist_t *reslist, + void *resource); + + #ifdef __cplusplus } #endif Index: misc/apr_reslist.c =================================================================== --- misc/apr_reslist.c (revision 161086) +++ misc/apr_reslist.c (revision 161087) @@ -50,6 +50,7 @@ int smax; /* soft maximum on the total number of resources */ int hmax; /* hard maximum on the total number of resources */ apr_interval_time_t ttl; /* TTL when we have too many resources */ + apr_interval_time_t timeout; /* Timeout for waiting on resource */ apr_reslist_constructor constructor; apr_reslist_destructor destructor; void *params; /* opaque data passed to constructor and destructor calls */ @@ -119,12 +120,9 @@ res = apr_pcalloc(reslist->pool, sizeof(*res)); rv = reslist->constructor(&res->opaque, reslist->params, reslist->pool); - if (rv != APR_SUCCESS) { - return rv; - } *ret_res = res; - return APR_SUCCESS; + return rv; } /** @@ -133,14 +131,7 @@ */ static apr_status_t destroy_resource(apr_reslist_t *reslist, apr_res_t *res) { - apr_status_t rv; - - rv = reslist->destructor(res->opaque, reslist->params, reslist->pool); - if (rv != APR_SUCCESS) { - return rv; - } - - return APR_SUCCESS; + return reslist->destructor(res->opaque, reslist->params, reslist->pool); } static apr_status_t reslist_cleanup(void *data_) @@ -188,6 +179,7 @@ /* Create the resource */ rv = create_resource(reslist, &res); if (rv != APR_SUCCESS) { + free_container(reslist, res); apr_thread_mutex_unlock(reslist->listlock); return rv; } @@ -314,7 +306,15 @@ * a new one, or something becomes free. */ else while (reslist->ntotal >= reslist->hmax && reslist->nidle <= 0) { - apr_thread_cond_wait(reslist->avail, reslist->listlock); + if (reslist->timeout) { + if ((rv = apr_thread_cond_timedwait(reslist->avail, + reslist->listlock, reslist->timeout)) != APR_SUCCESS) { + apr_thread_mutex_unlock(reslist->listlock); + return rv; + } + } + else + apr_thread_cond_wait(reslist->avail, reslist->listlock); } /* If we popped out of the loop, first try to see if there * are new resources available for immediate use. */ @@ -330,17 +330,13 @@ * a resource to fill the slot and use it. */ else { rv = create_resource(reslist, &res); - - if (rv != APR_SUCCESS) { - apr_thread_mutex_unlock(reslist->listlock); - return rv; + if (rv == APR_SUCCESS) { + reslist->ntotal++; + *resource = res->opaque; } - - reslist->ntotal++; - *resource = res->opaque; free_container(reslist, res); apr_thread_mutex_unlock(reslist->listlock); - return APR_SUCCESS; + return rv; } } @@ -359,4 +355,21 @@ return reslist_maint(reslist); } +APU_DECLARE(void) apr_reslist_timeout_set(apr_reslist_t *reslist, + apr_interval_time_t timeout) +{ + reslist->timeout = timeout; +} + +APU_DECLARE(apr_status_t) apr_reslist_invalidate(apr_reslist_t *reslist, + void *resource) +{ + apr_status_t ret; + apr_thread_mutex_lock(reslist->listlock); + ret = reslist->destructor(resource, reslist->params, reslist->pool); + reslist->ntotal--; + apr_thread_mutex_unlock(reslist->listlock); + return ret; +} + #endif /* APR_HAS_THREADS */