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
104
src/session.c
104
src/session.c
@ -580,6 +580,56 @@ void __session_add_glitch_ctr(struct session *sess, uint inc)
|
||||
|
||||
/* 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
|
||||
* connection is indexed by their respective target in the session. Nothing is
|
||||
* 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)
|
||||
{
|
||||
struct sess_priv_conns *pconns = NULL;
|
||||
struct server *srv = objt_server(conn->target);
|
||||
int found = 0;
|
||||
struct sess_priv_conns *pconns;
|
||||
|
||||
/* 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));
|
||||
@ -611,29 +659,14 @@ int session_add_conn(struct session *sess, struct connection *conn)
|
||||
if (!LIST_ISEMPTY(&conn->sess_el))
|
||||
return 1;
|
||||
|
||||
list_for_each_entry(pconns, &sess->priv_conns, sess_el) {
|
||||
if (pconns->target == conn->target) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
/* The session has no connection for the server, create a new entry */
|
||||
pconns = pool_alloc(pool_head_sess_priv_conns);
|
||||
pconns = sess_get_sess_conns(sess, conn->target);
|
||||
if (!pconns) {
|
||||
pconns = sess_alloc_sess_conns(sess, conn->target);
|
||||
if (!pconns)
|
||||
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
|
||||
* prior on after a session_add_conn() failure.
|
||||
*/
|
||||
@ -679,11 +712,14 @@ 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 *srv_conn = NULL;
|
||||
struct connection *srv_conn, *res = NULL;
|
||||
struct sess_priv_conns *pconns;
|
||||
|
||||
list_for_each_entry(pconns, &sess->priv_conns, sess_el) {
|
||||
if (pconns->target == target) {
|
||||
pconns = sess_get_sess_conns(sess, target);
|
||||
if (!pconns)
|
||||
goto end;
|
||||
|
||||
/* Search into pconns for a connection with matching params and available streams. */
|
||||
list_for_each_entry(srv_conn, &pconns->conn_list, sess_el) {
|
||||
if ((srv_conn->hash_node && srv_conn->hash_node->node.key == hash) &&
|
||||
srv_conn->mux &&
|
||||
@ -693,16 +729,14 @@ struct connection *session_get_conn(struct session *sess, void *target, int64_t
|
||||
srv_conn->flags &= ~CO_FL_SESS_IDLE;
|
||||
sess->idle_conns--;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
srv_conn = NULL; /* No available connection found */
|
||||
goto end;
|
||||
|
||||
res = srv_conn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
return srv_conn;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Remove the connection from the session list, and destroy sess_priv_conns
|
||||
@ -728,16 +762,14 @@ void session_unown_conn(struct session *sess, struct connection *conn)
|
||||
sess->idle_conns--;
|
||||
LIST_DEL_INIT(&conn->sess_el);
|
||||
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);
|
||||
BUG_ON(!pconns); /* if conn is attached to session, its sess_conn must exists. */
|
||||
if (LIST_ISEMPTY(&pconns->conn_list)) {
|
||||
LIST_DELETE(&pconns->sess_el);
|
||||
MT_LIST_DELETE(&pconns->srv_el);
|
||||
pool_free(pool_head_sess_priv_conns, pconns);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user