View | Details | Raw Unified | Return to bug 39673
Collapse All | Expand All

(-)modules/proxy/mod_proxy.h (+40 lines)
Lines 234-239 typedef struct { Link Here
234
    apr_array_header_t* cookie_domains;
234
    apr_array_header_t* cookie_domains;
235
} proxy_req_conf;
235
} proxy_req_conf;
236
236
237
/* Opaque aside connection record */
238
typedef struct ap_proxy_aside_rec ap_proxy_aside_rec;
239
237
typedef struct {
240
typedef struct {
238
    conn_rec     *connection;
241
    conn_rec     *connection;
239
    request_rec  *r;           /* Request record of the backend request
242
    request_rec  *r;           /* Request record of the backend request
Lines 254-259 typedef struct { Link Here
254
                                * filter chain or not */
257
                                * filter chain or not */
255
    unsigned int inreslist:1;  /* connection in apr_reslist? */
258
    unsigned int inreslist:1;  /* connection in apr_reslist? */
256
    const char   *uds_path;    /* Unix domain socket path */
259
    const char   *uds_path;    /* Unix domain socket path */
260
    ap_proxy_aside_rec *aside; /* Aside context */
257
} proxy_conn_rec;
261
} proxy_conn_rec;
258
262
259
typedef struct {
263
typedef struct {
Lines 834-840 PROXY_DECLARE(int) ap_proxy_acquire_connection(con Link Here
834
                                               proxy_conn_rec **conn,
838
                                               proxy_conn_rec **conn,
835
                                               proxy_worker *worker,
839
                                               proxy_worker *worker,
836
                                               server_rec *s);
840
                                               server_rec *s);
841
837
/**
842
/**
843
 * Function types usable by ap_proxy_acquire_connection_ex().
844
 */
845
typedef apr_status_t (*ap_proxy_acquire_fn)(void *baton, proxy_conn_rec **conn,
846
                                            proxy_worker *worker,
847
                                            server_rec *s);
848
typedef apr_status_t (*ap_proxy_release_fn)(void *baton, proxy_conn_rec *conn);
849
850
/**
851
 * Acquire a connection using the given @acquire function and register
852
 * a @release callback for it on cleanup, or use the worker connection
853
 * pool if the associated @baton is NULL.
854
 * @param proxy_function calling proxy scheme (http, ajp, ...)
855
 * @param conn    acquired connection
856
 * @param worker  worker used for obtaining connection
857
 * @param s       current server record
858
 * @param baton   associated baton (or conn_rec if @acquire is NULL)
859
 * @param acquire function (if not NULL) used to acquire aside connections,
860
 *                given @baton, @conn, @worker, and @s
861
 * @param release function (if not NULL) used to release acquired connection,
862
 *                given @baton, @conn, @worker, and @s, as callback
863
 * @return        OK or HTTP_XXX error
864
 * @note If the connection limit has been reached, the function will
865
 * block until a connection becomes available or the timeout has
866
 * elapsed.
867
 * @note If the given @baton is not NULL and @acquire is NULL, the baton is
868
 * considered to be a conn_rec to which the connection is attached (by worker).
869
 */
870
PROXY_DECLARE(int) ap_proxy_acquire_connection_ex(const char *proxy_function,
871
                                                  proxy_conn_rec **conn,
872
                                                  proxy_worker *worker,
873
                                                  server_rec *s, void *baton,
874
                                                  ap_proxy_acquire_fn acquire,
875
                                                  ap_proxy_release_fn release);
876
877
/**
838
 * Release a connection back to worker connection pool
878
 * Release a connection back to worker connection pool
839
 * @param proxy_function calling proxy scheme (http, ajp, ...)
879
 * @param proxy_function calling proxy scheme (http, ajp, ...)
840
 * @param conn    acquired connection
880
 * @param conn    acquired connection
(-)modules/proxy/mod_proxy_http.c (-2 / +10 lines)
Lines 1924-1931 static int proxy_http_handler(request_rec *r, prox Link Here
1924
1924
1925
1925
1926
    /* create space for state information */
1926
    /* create space for state information */
1927
    if ((status = ap_proxy_acquire_connection(proxy_function, &backend,
1927
    if (apr_table_get(r->subprocess_env, "proxy-aside-c")) {
1928
                                              worker, r->server)) != OK)
1928
        status = ap_proxy_acquire_connection_ex(proxy_function, &backend,
1929
                                                worker, r->server, c,
1930
                                                NULL, NULL);
1931
    }
1932
    else {
1933
        status = ap_proxy_acquire_connection(proxy_function, &backend,
1934
                                             worker, r->server);
1935
    }
1936
    if (status != OK)
1929
        goto cleanup;
1937
        goto cleanup;
1930
1938
1931
1939
(-)modules/proxy/mod_proxy_ajp.c (+6 lines)
Lines 718-723 static int proxy_ajp_handler(request_rec *r, proxy Link Here
718
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00895) "serving URL %s", url);
718
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00895) "serving URL %s", url);
719
719
720
    /* create space for state information */
720
    /* create space for state information */
721
    if (apr_table_get(r->subprocess_env, "proxy-aside-c")) {
722
        status = ap_proxy_acquire_connection_ex(scheme, &backend, worker,
723
                                                r->server, r->connection,
724
                                                NULL, NULL);
725
    }
726
    else
721
    status = ap_proxy_acquire_connection(scheme, &backend, worker,
727
    status = ap_proxy_acquire_connection(scheme, &backend, worker,
722
                                         r->server);
728
                                         r->server);
723
    if (status != OK) {
729
    if (status != OK) {
(-)modules/proxy/proxy_util.c (-16 / +129 lines)
Lines 71-76 static struct wstat { Link Here
71
    {0x0, '\0', NULL}
71
    {0x0, '\0', NULL}
72
};
72
};
73
73
74
/* Opaque aside connection record */
75
struct ap_proxy_aside_rec {
76
    void *baton;
77
    ap_proxy_release_fn release;
78
    apr_time_t expiry; /* idle connection expiry */
79
};
80
74
/* Global balancer counter */
81
/* Global balancer counter */
75
int PROXY_DECLARE_DATA proxy_lb_workers = 0;
82
int PROXY_DECLARE_DATA proxy_lb_workers = 0;
76
static int lb_workers_limit = 0;
83
static int lb_workers_limit = 0;
Lines 1347-1352 static void init_conn_pool(apr_pool_t *p, proxy_wo Link Here
1347
    worker->cp = cp;
1354
    worker->cp = cp;
1348
}
1355
}
1349
1356
1357
static void socket_cleanup(proxy_conn_rec *conn)
1358
{
1359
    conn->sock = NULL;
1360
    conn->connection = NULL;
1361
    apr_pool_clear(conn->scpool);
1362
}
1363
1350
static apr_status_t connection_cleanup(void *theconn)
1364
static apr_status_t connection_cleanup(void *theconn)
1351
{
1365
{
1352
    proxy_conn_rec *conn = (proxy_conn_rec *)theconn;
1366
    proxy_conn_rec *conn = (proxy_conn_rec *)theconn;
Lines 1374-1379 static apr_status_t connection_cleanup(void *theco Link Here
1374
        return APR_SUCCESS;
1388
        return APR_SUCCESS;
1375
    }
1389
    }
1376
1390
1391
    /* If the connection is aside (not acquired from the reslist),
1392
     * let it be released by the callback if any, or live with its
1393
     * parent pool otherwise (still ensuring it is closed if asked to).
1394
     */
1395
    if (conn->aside) {
1396
        if (conn->close) {
1397
            socket_cleanup(conn);
1398
            conn->close = 0;
1399
        }
1400
        if (conn->aside->release) {
1401
            conn->aside->release(conn->aside->baton, conn);
1402
        }
1403
        return APR_SUCCESS;
1404
    }
1405
1377
    /* determine if the connection need to be closed */
1406
    /* determine if the connection need to be closed */
1378
    if (conn->close || !worker->s->is_address_reusable || worker->s->disablereuse) {
1407
    if (conn->close || !worker->s->is_address_reusable || worker->s->disablereuse) {
1379
        apr_pool_t *p = conn->pool;
1408
        apr_pool_t *p = conn->pool;
Lines 1398-1410 static apr_status_t connection_cleanup(void *theco Link Here
1398
    return APR_SUCCESS;
1427
    return APR_SUCCESS;
1399
}
1428
}
1400
1429
1401
static void socket_cleanup(proxy_conn_rec *conn)
1402
{
1403
    conn->sock = NULL;
1404
    conn->connection = NULL;
1405
    apr_pool_clear(conn->scpool);
1406
}
1407
1408
PROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn,
1430
PROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn,
1409
                                                            request_rec *r)
1431
                                                            request_rec *r)
1410
{
1432
{
Lines 2049-2059 PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr Link Here
2049
    return connected ? 0 : 1;
2071
    return connected ? 0 : 1;
2050
}
2072
}
2051
2073
2052
PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
2074
/* For the given conn_rec (baton), handle a connection per worker */
2053
                                               proxy_conn_rec **conn,
2075
static apr_status_t proxy_acquire_from_c(void *baton, proxy_conn_rec **conn,
2054
                                               proxy_worker *worker,
2076
                                         proxy_worker *worker, server_rec *s)
2055
                                               server_rec *s)
2056
{
2077
{
2078
    apr_hash_t *conns;
2079
    ap_proxy_aside_rec *aside;
2080
    conn_rec *c = baton;
2081
2082
    conns = ap_get_module_config(c->conn_config, &proxy_module);
2083
    if (!conns) {
2084
        conns = apr_hash_make(c->pool);
2085
        ap_set_module_config(c->conn_config, &proxy_module, conns);
2086
        *conn = NULL;
2087
    }
2088
    else {
2089
        *conn = apr_hash_get(conns, &worker->s, sizeof worker->s);
2090
    }
2091
    if (!*conn) {
2092
        connection_constructor((void **)conn, worker, c->pool);
2093
        apr_hash_set(conns, &worker->s, sizeof worker->s, *conn);
2094
        aside = apr_pcalloc((*conn)->pool, sizeof *aside);
2095
        (*conn)->aside = aside;
2096
    }
2097
    else {
2098
        aside = (*conn)->aside;
2099
        if (aside->expiry) {
2100
            if (apr_time_now() >= aside->expiry) {
2101
                socket_cleanup(*conn);
2102
            }
2103
            aside->expiry = 0;
2104
        }
2105
    }
2106
2107
    return APR_SUCCESS;
2108
}
2109
2110
static apr_status_t proxy_release_to_c(void *baton, proxy_conn_rec *conn)
2111
{
2112
    if (conn->worker->s->ttl) {
2113
        conn->aside->expiry = apr_time_now() +
2114
                              apr_time_from_sec(conn->worker->s->ttl);
2115
    }
2116
    else {
2117
        conn->aside->expiry = 0;
2118
    }
2119
    return APR_SUCCESS;
2120
}
2121
2122
PROXY_DECLARE(int) ap_proxy_acquire_connection_ex(const char *proxy_function,
2123
                                                  proxy_conn_rec **conn,
2124
                                                  proxy_worker *worker,
2125
                                                  server_rec *s, void *baton,
2126
                                                  ap_proxy_acquire_fn acquire,
2127
                                                  ap_proxy_release_fn release)
2128
{
2057
    apr_status_t rv;
2129
    apr_status_t rv;
2058
2130
2059
    if (!PROXY_WORKER_IS_USABLE(worker)) {
2131
    if (!PROXY_WORKER_IS_USABLE(worker)) {
Lines 2068-2074 PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr Link Here
2068
        }
2140
        }
2069
    }
2141
    }
2070
2142
2071
    if (worker->s->hmax && worker->cp->res) {
2143
    /* Aside connection case, use the given functions.
2144
     * When a baton is given with no acquire function, it is
2145
     * assumed to be a conn_rec (to acquire from), hence the
2146
     * corresponding functions are installed.
2147
     */
2148
    if (acquire || (baton && (acquire = proxy_acquire_from_c)
2149
                          && (release = proxy_release_to_c))) {
2150
        rv = acquire(baton, conn, worker, s);
2151
        if (rv == APR_SUCCESS) {
2152
            if (!(*conn)->aside) {
2153
                (*conn)->aside = apr_pcalloc((*conn)->pool,
2154
                                             sizeof *(*conn)->aside);
2155
            }
2156
            (*conn)->aside->release = release;
2157
            (*conn)->aside->baton = baton;
2158
        }
2159
        else if (rv != APR_NOTFOUND) {
2160
            ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO()
2161
                         "%s: failed to acquire aside connection for (%s)",
2162
                         proxy_function, worker->s->hostname);
2163
            return HTTP_SERVICE_UNAVAILABLE;
2164
        }
2165
    }
2166
    else {
2167
        rv = APR_NOTFOUND;
2168
    }
2169
2170
    if (rv == APR_SUCCESS) {
2171
        /* got/use aside connection */
2172
    }
2173
    else if (worker->s->hmax && worker->cp->res) {
2072
        rv = apr_reslist_acquire(worker->cp->res, (void **)conn);
2174
        rv = apr_reslist_acquire(worker->cp->res, (void **)conn);
2073
    }
2175
    }
2074
    else {
2176
    else {
Lines 2090-2097 PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr Link Here
2090
        return HTTP_SERVICE_UNAVAILABLE;
2192
        return HTTP_SERVICE_UNAVAILABLE;
2091
    }
2193
    }
2092
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00942)
2194
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00942)
2093
                 "%s: has acquired connection for (%s)",
2195
                 "%s: has acquired %sconnection for (%s)",
2094
                 proxy_function, worker->s->hostname);
2196
                 proxy_function, (*conn)->aside ? "aside " : "",
2197
                 worker->s->hostname);
2095
2198
2096
    (*conn)->worker = worker;
2199
    (*conn)->worker = worker;
2097
    (*conn)->close  = 0;
2200
    (*conn)->close  = 0;
Lines 2123-2135 PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr Link Here
2123
    return OK;
2226
    return OK;
2124
}
2227
}
2125
2228
2229
PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
2230
                                               proxy_conn_rec **conn,
2231
                                               proxy_worker *worker,
2232
                                               server_rec *s)
2233
{
2234
    return ap_proxy_acquire_connection_ex(proxy_function, conn,
2235
                                          worker, s, NULL, NULL, NULL);
2236
}
2237
2126
PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
2238
PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
2127
                                               proxy_conn_rec *conn,
2239
                                               proxy_conn_rec *conn,
2128
                                               server_rec *s)
2240
                                               server_rec *s)
2129
{
2241
{
2130
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00943)
2242
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00943)
2131
                "%s: has released connection for (%s)",
2243
                 "%s: has released %sconnection for (%s)",
2132
                proxy_function, conn->worker->s->hostname);
2244
                 proxy_function, conn->aside ? "aside " : "",
2245
                 conn->worker->s->hostname);
2133
    connection_cleanup(conn);
2246
    connection_cleanup(conn);
2134
2247
2135
    return OK;
2248
    return OK;

Return to bug 39673