From: Willy Tarreau Date: Tue, 4 Aug 2015 17:00:17 +0000 (+0200) Subject: MEDIUM: stream-int: queue idle connections at the server X-Git-Tag: v1.6-dev4~115 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=323a2d925c85a26d539809424ee11556b80db936;p=thirdparty%2Fhaproxy.git MEDIUM: stream-int: queue idle connections at the server Now we get a per-server list of all idle connections. That way we'll be able to reclaim them upon shortage later. --- diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h index 6e4cfe878a..09c2a4e5e1 100644 --- a/include/proto/stream_interface.h +++ b/include/proto/stream_interface.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -154,6 +155,7 @@ static inline void si_release_endpoint(struct stream_interface *si) return; if ((conn = objt_conn(si->end))) { + LIST_DEL(&conn->list); conn_force_close(conn); conn_free(conn); } @@ -167,15 +169,19 @@ static inline void si_release_endpoint(struct stream_interface *si) /* Turn a possibly existing connection endpoint of stream interface to * idle mode, which means that the connection will be polled for incoming events - * and might be killed by the underlying I/O handler. + * and might be killed by the underlying I/O handler. If is not null, the + * connection will also be added at the head of this list. */ -static inline void si_idle_conn(struct stream_interface *si) +static inline void si_idle_conn(struct stream_interface *si, struct list *pool) { struct connection *conn = objt_conn(si->end); if (!conn) return; + if (pool) + LIST_ADD(pool, &conn->list); + conn_attach(conn, si, &si_idle_conn_cb); conn_data_want_recv(conn); } diff --git a/src/backend.c b/src/backend.c index f8185d7fef..bbe9573a52 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1052,6 +1052,11 @@ int connect_server(struct stream *s) if (!reuse) srv_conn = si_alloc_conn(&s->si[1]); + else { + /* reusing our connection, take it out of the idle list */ + LIST_DEL(&srv_conn->list); + LIST_INIT(&srv_conn->list); + } if (!srv_conn) return SF_ERR_RESOURCE; diff --git a/src/proto_http.c b/src/proto_http.c index 161939a374..352dd75b08 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -5030,12 +5030,15 @@ void http_end_txn_clean_session(struct stream *s) { int prev_status = s->txn->status; struct proxy *fe = strm_fe(s); + struct connection *srv_conn; + struct server *srv; /* FIXME: We need a more portable way of releasing a backend's and a * server's connections. We need a safer way to reinitialize buffer * flags. We also need a more accurate method for computing per-request * data. */ + srv_conn = objt_conn(s->si[1].end); /* unless we're doing keep-alive, we want to quickly close the connection * to the server. @@ -5125,6 +5128,7 @@ void http_end_txn_clean_session(struct stream *s) if (((s->txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_KAL) || !si_conn_ready(&s->si[1])) { si_release_endpoint(&s->si[1]); + srv_conn = NULL; } s->si[1].state = s->si[1].prev_state = SI_ST_INI; @@ -5182,7 +5186,11 @@ void http_end_txn_clean_session(struct stream *s) channel_auto_close(&s->res); /* we're in keep-alive with an idle connection, monitor it */ - si_idle_conn(&s->si[1]); + srv = NULL; + if (srv_conn) + srv = objt_server(srv_conn->target); + + si_idle_conn(&s->si[1], srv ? &srv->priv_conns : NULL); s->req.analysers = strm_li(s)->analysers; s->res.analysers = 0; diff --git a/src/stream_interface.c b/src/stream_interface.c index 4b8d924f6a..2ea59c7339 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -515,6 +515,7 @@ static int si_idle_conn_wake_cb(struct connection *conn) if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH)) { /* warning, we can't do anything on after this call ! */ + LIST_DEL(&conn->list); conn_force_close(conn); conn_free(conn); si->end = NULL;