mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-20 21:31:28 +02:00
MINOR: session: refactor alloc/lookup of sess_conns elements
By default backend connections are stored into idle/avail server trees. However, if such connections cannot be shared between multiple clients, session serves as the alternative storage. To be able to quickly reuse a backend conn from a session, they are indexed by their target, which is either a server or a backend proxy. This is the purpose of 'struct sess_priv_conns' intermediary stockage element. Lookup and allocation of these elements are performed in several session function, for example to add, get or remove a backend connection from a session. The purpose of this patch is to simplify this by providing two internal functions sess_alloc_sess_conns() and sess_get_sess_conns(). Along with this, a new BUG_ON() is added into session_unown_conn(), which ensure that sess_priv_conns element is found when the connection is removed from the session.
This commit is contained in:
parent
d4f7a2dbcc
commit
f3e8e863c9
128
src/session.c
128
src/session.c
@ -580,6 +580,56 @@ void __session_add_glitch_ctr(struct session *sess, uint inc)
|
|||||||
|
|
||||||
/* Session management of backend connections. */
|
/* Session management of backend connections. */
|
||||||
|
|
||||||
|
/* Allocate a storage element into <sess> session which refers to <target>
|
||||||
|
* endpoint. This storage can be used to attach new connections
|
||||||
|
* to the session.
|
||||||
|
*
|
||||||
|
* Returns the allocated element or NULL on failure.
|
||||||
|
*/
|
||||||
|
static struct sess_priv_conns *sess_alloc_sess_conns(struct session *sess,
|
||||||
|
enum obj_type *target)
|
||||||
|
{
|
||||||
|
struct sess_priv_conns *pconns;
|
||||||
|
struct server *srv;
|
||||||
|
|
||||||
|
pconns = pool_alloc(pool_head_sess_priv_conns);
|
||||||
|
if (!pconns)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pconns->target = target;
|
||||||
|
LIST_INIT(&pconns->conn_list);
|
||||||
|
LIST_APPEND(&sess->priv_conns, &pconns->sess_el);
|
||||||
|
|
||||||
|
MT_LIST_INIT(&pconns->srv_el);
|
||||||
|
/* If <target> endpoint is a server, also attach storage element into it. */
|
||||||
|
if ((srv = objt_server(target)))
|
||||||
|
MT_LIST_APPEND(&srv->sess_conns, &pconns->srv_el);
|
||||||
|
|
||||||
|
pconns->tid = tid;
|
||||||
|
|
||||||
|
return pconns;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve the backend connections storage element from <sess> session which
|
||||||
|
* refers to <target> endpoint.
|
||||||
|
*
|
||||||
|
* This function usage must be protected with idle_conns lock.
|
||||||
|
*
|
||||||
|
* Returns the storage element or NULL if not found;
|
||||||
|
*/
|
||||||
|
static struct sess_priv_conns *sess_get_sess_conns(struct session *sess,
|
||||||
|
enum obj_type *target)
|
||||||
|
{
|
||||||
|
struct sess_priv_conns *pconns;
|
||||||
|
|
||||||
|
list_for_each_entry(pconns, &sess->priv_conns, sess_el) {
|
||||||
|
if (pconns->target == target)
|
||||||
|
return pconns;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Add the connection <conn> to the private conns list of session <sess>. Each
|
/* Add the connection <conn> to the private conns list of session <sess>. Each
|
||||||
* connection is indexed by their respective target in the session. Nothing is
|
* connection is indexed by their respective target in the session. Nothing is
|
||||||
* performed if the connection is already in the session list.
|
* performed if the connection is already in the session list.
|
||||||
@ -589,9 +639,7 @@ void __session_add_glitch_ctr(struct session *sess, uint inc)
|
|||||||
*/
|
*/
|
||||||
int session_add_conn(struct session *sess, struct connection *conn)
|
int session_add_conn(struct session *sess, struct connection *conn)
|
||||||
{
|
{
|
||||||
struct sess_priv_conns *pconns = NULL;
|
struct sess_priv_conns *pconns;
|
||||||
struct server *srv = objt_server(conn->target);
|
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
/* Connection target is used to index it in the session. Only BE conns are expected in session list. */
|
/* Connection target is used to index it in the session. Only BE conns are expected in session list. */
|
||||||
BUG_ON(!conn->target || objt_listener(conn->target));
|
BUG_ON(!conn->target || objt_listener(conn->target));
|
||||||
@ -611,29 +659,14 @@ int session_add_conn(struct session *sess, struct connection *conn)
|
|||||||
if (!LIST_ISEMPTY(&conn->sess_el))
|
if (!LIST_ISEMPTY(&conn->sess_el))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
list_for_each_entry(pconns, &sess->priv_conns, sess_el) {
|
pconns = sess_get_sess_conns(sess, conn->target);
|
||||||
if (pconns->target == conn->target) {
|
if (!pconns) {
|
||||||
found = 1;
|
pconns = sess_alloc_sess_conns(sess, conn->target);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
/* The session has no connection for the server, create a new entry */
|
|
||||||
pconns = pool_alloc(pool_head_sess_priv_conns);
|
|
||||||
if (!pconns)
|
if (!pconns)
|
||||||
return 0;
|
return 0;
|
||||||
pconns->target = conn->target;
|
|
||||||
LIST_INIT(&pconns->conn_list);
|
|
||||||
LIST_APPEND(&sess->priv_conns, &pconns->sess_el);
|
|
||||||
|
|
||||||
MT_LIST_INIT(&pconns->srv_el);
|
|
||||||
if (srv)
|
|
||||||
MT_LIST_APPEND(&srv->sess_conns, &pconns->srv_el);
|
|
||||||
|
|
||||||
pconns->tid = tid;
|
|
||||||
}
|
}
|
||||||
LIST_APPEND(&pconns->conn_list, &conn->sess_el);
|
|
||||||
|
|
||||||
|
LIST_APPEND(&pconns->conn_list, &conn->sess_el);
|
||||||
/* Ensure owner is set for connection. It could have been reset
|
/* Ensure owner is set for connection. It could have been reset
|
||||||
* prior on after a session_add_conn() failure.
|
* prior on after a session_add_conn() failure.
|
||||||
*/
|
*/
|
||||||
@ -679,30 +712,31 @@ int session_check_idle_conn(struct session *sess, struct connection *conn)
|
|||||||
*/
|
*/
|
||||||
struct connection *session_get_conn(struct session *sess, void *target, int64_t hash)
|
struct connection *session_get_conn(struct session *sess, void *target, int64_t hash)
|
||||||
{
|
{
|
||||||
struct connection *srv_conn = NULL;
|
struct connection *srv_conn, *res = NULL;
|
||||||
struct sess_priv_conns *pconns;
|
struct sess_priv_conns *pconns;
|
||||||
|
|
||||||
list_for_each_entry(pconns, &sess->priv_conns, sess_el) {
|
pconns = sess_get_sess_conns(sess, target);
|
||||||
if (pconns->target == target) {
|
if (!pconns)
|
||||||
list_for_each_entry(srv_conn, &pconns->conn_list, sess_el) {
|
goto end;
|
||||||
if ((srv_conn->hash_node && srv_conn->hash_node->node.key == hash) &&
|
|
||||||
srv_conn->mux &&
|
/* Search into pconns for a connection with matching params and available streams. */
|
||||||
(srv_conn->mux->avail_streams(srv_conn) > 0) &&
|
list_for_each_entry(srv_conn, &pconns->conn_list, sess_el) {
|
||||||
!(srv_conn->flags & CO_FL_WAIT_XPRT)) {
|
if ((srv_conn->hash_node && srv_conn->hash_node->node.key == hash) &&
|
||||||
if (srv_conn->flags & CO_FL_SESS_IDLE) {
|
srv_conn->mux &&
|
||||||
srv_conn->flags &= ~CO_FL_SESS_IDLE;
|
(srv_conn->mux->avail_streams(srv_conn) > 0) &&
|
||||||
sess->idle_conns--;
|
!(srv_conn->flags & CO_FL_WAIT_XPRT)) {
|
||||||
}
|
if (srv_conn->flags & CO_FL_SESS_IDLE) {
|
||||||
goto end;
|
srv_conn->flags &= ~CO_FL_SESS_IDLE;
|
||||||
}
|
sess->idle_conns--;
|
||||||
}
|
}
|
||||||
srv_conn = NULL; /* No available connection found */
|
|
||||||
goto end;
|
res = srv_conn;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
return srv_conn;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove the connection from the session list, and destroy sess_priv_conns
|
/* Remove the connection from the session list, and destroy sess_priv_conns
|
||||||
@ -728,15 +762,13 @@ void session_unown_conn(struct session *sess, struct connection *conn)
|
|||||||
sess->idle_conns--;
|
sess->idle_conns--;
|
||||||
LIST_DEL_INIT(&conn->sess_el);
|
LIST_DEL_INIT(&conn->sess_el);
|
||||||
conn->owner = NULL;
|
conn->owner = NULL;
|
||||||
list_for_each_entry(pconns, &sess->priv_conns, sess_el) {
|
|
||||||
if (pconns->target == conn->target) {
|
pconns = sess_get_sess_conns(sess, conn->target);
|
||||||
if (LIST_ISEMPTY(&pconns->conn_list)) {
|
BUG_ON(!pconns); /* if conn is attached to session, its sess_conn must exists. */
|
||||||
LIST_DELETE(&pconns->sess_el);
|
if (LIST_ISEMPTY(&pconns->conn_list)) {
|
||||||
MT_LIST_DELETE(&pconns->srv_el);
|
LIST_DELETE(&pconns->sess_el);
|
||||||
pool_free(pool_head_sess_priv_conns, pconns);
|
MT_LIST_DELETE(&pconns->srv_el);
|
||||||
}
|
pool_free(pool_head_sess_priv_conns, pconns);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user