]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: stream-int: queue idle connections at the server
authorWilly Tarreau <w@1wt.eu>
Tue, 4 Aug 2015 17:00:17 +0000 (19:00 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 6 Aug 2015 09:06:25 +0000 (11:06 +0200)
Now we get a per-server list of all idle connections. That way we'll
be able to reclaim them upon shortage later.

include/proto/stream_interface.h
src/backend.c
src/proto_http.c
src/stream_interface.c

index 6e4cfe878a888c7691c81c75d8b960ef1175ea78..09c2a4e5e13a8335211d95e6742ea9bbe7eb5217 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 
 #include <common/config.h>
+#include <types/server.h>
 #include <types/stream.h>
 #include <types/stream_interface.h>
 #include <proto/applet.h>
@@ -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 <si> 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 <pool> 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);
 }
index f8185d7fefffca5621f6341b2c0eb0abf8a3c7e3..bbe9573a52561eec2f6363f7e6bd2bcb31904572 100644 (file)
@@ -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;
index 161939a374b5f4dc7513f75545c6cd75f6885551..352dd75b08f07d979b7ab39b3acf2a1d39143655 100644 (file)
@@ -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;
index 4b8d924f6a5e94a1274c9894f4a2426fb8b0c412..2ea59c7339d73be22691fa03a31824775b6a52a8 100644 (file)
@@ -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 <conn> after this call ! */
+               LIST_DEL(&conn->list);
                conn_force_close(conn);
                conn_free(conn);
                si->end = NULL;