const struct mux_ops *force_mux_ops);
int conn_install_mux_chk(struct connection *conn, void *ctx, struct session *sess);
-void conn_delete_from_tree(struct connection *conn, int thr);
+void conn_delete_from_tree(struct connection *conn, int thr, int permanent);
void conn_init(struct connection *conn, void *target);
struct connection *conn_new(void *target);
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
conn = srv_lookup_conn(is_safe ? &srv->per_thr[tid].safe_conns : &srv->per_thr[tid].idle_conns, hash);
if (conn)
- conn_delete_from_tree(conn, tid);
+ conn_delete_from_tree(conn, tid, 0);
/* If we failed to pick a connection from the idle list, let's try again with
* the safe list.
if (!conn && !is_safe && srv->curr_safe_nb > 0) {
conn = srv_lookup_conn(&srv->per_thr[tid].safe_conns, hash);
if (conn) {
- conn_delete_from_tree(conn, tid);
+ conn_delete_from_tree(conn, tid, 0);
is_safe = 1;
}
}
conn = srv_lookup_conn(tree, hash);
while (conn) {
if (conn->mux->takeover && conn->mux->takeover(conn, i, 0) == 0) {
- conn_delete_from_tree(conn, i);
+ conn_delete_from_tree(conn, i, 0);
_HA_ATOMIC_INC(&activity[tid].fd_takeover);
found = 1;
break;
conn = ceb64_item_first(root, hash_node.node, hash_node.key, struct connection);
while (conn) {
if (conn->mux->takeover && conn->mux->takeover(conn, curtid, 1) == 0) {
- conn_delete_from_tree(conn, curtid);
+ conn_delete_from_tree(conn, curtid, 0);
return conn;
}
conn = ceb64_item_next(root, hash_node.node, hash_node.key, conn);
if (avail <= 1) {
/* no more streams available, remove it from the list */
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
- conn_delete_from_tree(srv_conn, tid);
+ conn_delete_from_tree(srv_conn, tid, 0);
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
}
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
if (!LIST_ISEMPTY(&srv->per_thr[tid].idle_conn_list)) {
tokill_conn = LIST_ELEM(srv->per_thr[tid].idle_conn_list.n, struct connection *, idle_list);
- conn_delete_from_tree(tokill_conn, tid);
+ conn_delete_from_tree(tokill_conn, tid, 1);
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
/* Release the idle lock before calling mux->destroy.
if (!LIST_ISEMPTY(&srv->per_thr[i].idle_conn_list)) {
tokill_conn = LIST_ELEM(srv->per_thr[i].idle_conn_list.n, struct connection *, idle_list);
- conn_delete_from_tree(tokill_conn, i);
+ conn_delete_from_tree(tokill_conn, i, 1);
}
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[i].idle_conns_lock);
/* Remove <conn> idle connection from its attached tree (idle, safe or avail)
* for the server in the connection's target and thread <thr>. If also present
- * in the secondary server idle list, conn is removed from it.
+ * in the secondary server idle list, conn is removed from it. Finally, if
+ * <permanent> is non-nul, the idle connection flags are cleared as well so
+ * that the connection is not re-inserted later.
*
* Must be called with idle_conns_lock held.
*/
-void conn_delete_from_tree(struct connection *conn, int thr)
+void conn_delete_from_tree(struct connection *conn, int thr, int permanent)
{
struct ceb_root **conn_tree;
struct server *srv = __objt_server(conn->target);
}
ceb64_item_delete(conn_tree, hash_node.node, hash_node.key, conn);
+ if (permanent)
+ conn->flags &= ~CO_FL_LIST_MASK;
}
int conn_create_mux(struct connection *conn, int *closed_connection)
conn_in_list = 0;
}
else {
- conn_delete_from_tree(conn, tid);
+ conn_delete_from_tree(conn, tid, 0);
}
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
}
conn_in_list = 0;
}
else {
- conn_delete_from_tree(conn, tid);
+ conn_delete_from_tree(conn, tid, 0);
}
}
* to steal it from us.
*/
if (fconn->conn->flags & CO_FL_LIST_MASK)
- conn_delete_from_tree(fconn->conn, tid);
+ conn_delete_from_tree(fconn->conn, tid, 0);
else if (fconn->conn->flags & CO_FL_SESS_IDLE)
session_detach_idle_conn(fconn->conn->owner, fconn->conn);
conn_in_list = 0;
}
else {
- conn_delete_from_tree(conn, tid);
+ conn_delete_from_tree(conn, tid, 0);
}
}
* to steal it from us.
*/
if (h1c->conn->flags & CO_FL_LIST_MASK)
- conn_delete_from_tree(h1c->conn, tid);
+ conn_delete_from_tree(h1c->conn, tid, 1);
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
conn_in_list = 0;
}
else {
- conn_delete_from_tree(conn, tid);
+ conn_delete_from_tree(conn, tid, 0);
}
}
/* connections in error must be removed from the idle lists */
if (conn->flags & CO_FL_LIST_MASK) {
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
- conn_delete_from_tree(conn, tid);
+ conn_delete_from_tree(conn, tid, 1);
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
}
}
/* connections in error must be removed from the idle lists */
if (conn->flags & CO_FL_LIST_MASK) {
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
- conn_delete_from_tree(conn, tid);
+ conn_delete_from_tree(conn, tid, 1);
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
}
}
* to steal it from us.
*/
if (h2c->conn->flags & CO_FL_LIST_MASK)
- conn_delete_from_tree(h2c->conn, tid);
+ conn_delete_from_tree(h2c->conn, tid, 1);
else if (h2c->conn->flags & CO_FL_SESS_IDLE)
session_detach_idle_conn(h2c->conn->owner, h2c->conn);
/* in any case this connection must not be considered idle anymore */
if (h2c->conn->flags & CO_FL_LIST_MASK) {
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
- conn_delete_from_tree(h2c->conn, tid);
+ conn_delete_from_tree(h2c->conn, tid, 1);
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
}
/* A connection is not reusable if app layer is closed. */
if (qcc->flags & QC_CF_IS_BACK)
- conn_delete_from_tree(qcc->conn, tid);
+ conn_delete_from_tree(qcc->conn, tid, 1);
out:
qcc->app_st = QCC_APP_ST_SHUT;
if (conn->flags & CO_FL_SESS_IDLE)
session_detach_idle_conn(conn->owner, conn);
else
- conn_delete_from_tree(conn, tid);
+ conn_delete_from_tree(conn, tid, 0);
}
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
* attempts to steal it from us.
*/
if (qcc->conn->flags & CO_FL_LIST_MASK)
- conn_delete_from_tree(qcc->conn, tid);
+ conn_delete_from_tree(qcc->conn, tid, 1);
else if (qcc->conn->flags & CO_FL_SESS_IDLE)
session_unown_conn(qcc->conn->owner, qcc->conn);
conn_in_list = 0;
}
else {
- conn_delete_from_tree(conn, tid);
+ conn_delete_from_tree(conn, tid, 0);
}
}
/* connections in error must be removed from the idle lists */
if (conn->flags & CO_FL_LIST_MASK) {
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
- conn_delete_from_tree(conn, tid);
+ conn_delete_from_tree(conn, tid, 1);
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
}
}
* to steal it from us.
*/
if (spop_conn->conn->flags & CO_FL_LIST_MASK)
- conn_delete_from_tree(spop_conn->conn, tid);
+ conn_delete_from_tree(spop_conn->conn, tid, 1);
else if (spop_conn->conn->flags & CO_FL_SESS_IDLE)
session_detach_idle_conn(spop_conn->conn->owner, spop_conn->conn);
break;
conn = LIST_ELEM(srv->per_thr[thr].idle_conn_list.n, struct connection *, idle_list);
- conn_delete_from_tree(conn, thr);
+ conn_delete_from_tree(conn, thr, 1);
MT_LIST_APPEND(&idle_conns[thr].toremove_conns, &conn->toremove_list);
i++;
}
/* Remove the connection from any tree (safe, idle or available) */
if (ceb_intree(&conn->hash_node.node)) {
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
- conn_delete_from_tree(conn, tid);
- conn->flags &= ~CO_FL_LIST_MASK;
+ conn_delete_from_tree(conn, tid, 1);
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
}
}
_HA_ATOMIC_DEC(&srv->curr_used_conns);
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
- conn_delete_from_tree(conn, tid);
+ conn_delete_from_tree(conn, tid, 0);
if (is_safe) {
conn->flags = (conn->flags & ~CO_FL_LIST_MASK) | CO_FL_SAFE_LIST;
hash_node.key, struct connection))) {
if (conn->ctrl->ctrl_close)
conn->ctrl->ctrl_close(conn);
- conn_delete_from_tree(conn, i);
+ conn_delete_from_tree(conn, i, 1);
}
}
}
conn_in_list = 0;
}
else {
- conn_delete_from_tree(conn, tid);
+ conn_delete_from_tree(conn, tid, 0);
}
}