struct connection *session_get_conn(struct session *sess, void *target, int64_t hash);
void session_unown_conn(struct session *sess, struct connection *conn);
int session_detach_idle_conn(struct session *sess, struct connection *conn);
+int sess_conns_cleanup_all_idle(struct sess_priv_conns *sess_conns);
/* Remove the refcount from the session to the tracked counters, and clear the
* pointer to ensure this is only performed once. The caller is responsible for
*/
static void srv_cleanup_connections(struct server *srv)
{
+ struct sess_priv_conns *sess_conns;
int did_remove;
int i;
for (i = tid;;) {
did_remove = 0;
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[i].idle_conns_lock);
+
+ /* idle connections */
if (srv_migrate_conns_to_remove(&srv->per_thr[i].idle_conn_list, &idle_conns[i].toremove_conns, -1) > 0)
did_remove = 1;
+
+ /* session attached connections */
+ while ((sess_conns = MT_LIST_POP(&srv->per_thr[i].sess_conns, struct sess_priv_conns *, srv_el))) {
+ if (sess_conns_cleanup_all_idle(sess_conns)) {
+ did_remove = 1;
+
+ if (LIST_ISEMPTY(&sess_conns->conn_list)) {
+ LIST_DELETE(&sess_conns->sess_el);
+ pool_free(pool_head_sess_priv_conns, sess_conns);
+ }
+ }
+ }
+
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[i].idle_conns_lock);
if (did_remove)
task_wakeup(idle_conns[i].cleanup_task, TASK_WOKEN_OTHER);
return 1;
}
+/* Remove every idle backend connections stored in <sess_conns> and move them
+ * into the purge list. If <sess_conns> is empty it is also removed from the
+ * session and freed.
+ *
+ * Returns the number of connections moved to purge list.
+ */
+int sess_conns_cleanup_all_idle(struct sess_priv_conns *sess_conns)
+{
+ struct connection *conn, *back;
+ int conn_tid = sess_conns->tid;
+ int i = 0;
+
+ list_for_each_entry_safe(conn, back, &sess_conns->conn_list, sess_el) {
+ if (!(conn->flags & CO_FL_SESS_IDLE))
+ continue;
+
+ /* Decrement session idle counter. */
+ --((struct session *)conn->owner)->idle_conns;
+
+ LIST_DEL_INIT(&conn->sess_el);
+ MT_LIST_APPEND(&idle_conns[conn_tid].toremove_conns,
+ &conn->toremove_list);
+ ++i;
+ }
+
+ return i;
+}
+
/*
* Local variables: