From c966f70cb7b4362deb0f5bc80349685399a8206f Mon Sep 17 00:00:00 2001 From: "Alan T. DeKok" Date: Wed, 25 Dec 2024 12:54:54 -0500 Subject: [PATCH] add and use idle_timeout configuration --- src/lib/server/trunk.c | 39 +++++++++++++++++++++++++++++++++++++++ src/lib/server/trunk.h | 2 ++ 2 files changed, 41 insertions(+) diff --git a/src/lib/server/trunk.c b/src/lib/server/trunk.c index c8ada1a6d4606..46804bba8f637 100644 --- a/src/lib/server/trunk.c +++ b/src/lib/server/trunk.c @@ -319,6 +319,7 @@ conf_parser_t const trunk_config[] = { { FR_CONF_OFFSET("connecting", trunk_conf_t, connecting), .dflt = "2" }, { FR_CONF_OFFSET("uses", trunk_conf_t, max_uses), .dflt = "0" }, { FR_CONF_OFFSET("lifetime", trunk_conf_t, lifetime), .dflt = "0" }, + { FR_CONF_OFFSET("idle_timeout", trunk_conf_t, idle_timeout), .dflt = "0" }, { FR_CONF_OFFSET("open_delay", trunk_conf_t, open_delay), .dflt = "0.2" }, { FR_CONF_OFFSET("close_delay", trunk_conf_t, close_delay), .dflt = "10.0" }, @@ -4167,6 +4168,34 @@ static void trunk_manage(trunk_t *trunk, fr_time_t now) while ((treq = fr_dlist_tail(&trunk->free_requests)) && fr_time_lteq(fr_time_add(treq->last_freed, trunk->conf.req_cleanup_delay), now)) talloc_free(treq); + /* + * If we have idle connections, then close them. + */ + if (fr_time_delta_ispos(trunk->conf.idle_timeout)) { + fr_minmax_heap_iter_t iter; + fr_time_t idle_cutoff = fr_time_sub(now, trunk->conf.idle_timeout); + + for (tconn = fr_minmax_heap_iter_init(trunk->active, &iter); + tconn; + tconn = fr_minmax_heap_iter_next(trunk->active, &iter)) { + /* + * The connection has outstanding requests without replies, don't do anything. + */ + if (fr_heap_num_elements(tconn->pending) > 0) continue; + + /* + * The connection was last active after the idle cutoff time, don't do anything. + */ + if (fr_time_gt(tconn->pub.last_write_success, idle_cutoff)) continue; + + /* + * This connection has been inactive since before the idle timeout. Drain it, + * and free it. + */ + trunk_connection_enter_draining_to_free(tconn); + } + } + /* * Free any connections which have drained * and we didn't reactivate during the last @@ -4736,6 +4765,16 @@ int trunk_start(trunk_t *trunk) if (trunk_connection_spawn(trunk, fr_time()) != 0) return -1; } + /* + * If the idle timeout is set, AND there's no management interval, OR the management interval is + * less than the idle timeout, update the management interval. + */ + if (fr_time_delta_ispos(trunk->conf.idle_timeout) && + (!fr_time_delta_ispos(trunk->conf.manage_interval) || + fr_time_delta_gt(trunk->conf.manage_interval, trunk->conf.idle_timeout))) { + trunk->conf.manage_interval = trunk->conf.idle_timeout; + } + if (fr_time_delta_ispos(trunk->conf.manage_interval)) { /* * Insert the event timer to manage diff --git a/src/lib/server/trunk.h b/src/lib/server/trunk.h index 86b1fc8be711b..ae29dba62c25d 100644 --- a/src/lib/server/trunk.h +++ b/src/lib/server/trunk.h @@ -247,6 +247,8 @@ typedef struct { fr_time_delta_t lifetime; //!< Time between reconnects. + fr_time_delta_t idle_timeout; //!< how long a connection can remain idle for + fr_time_delta_t open_delay; //!< How long we must be above target utilisation ///< to spawn a new connection.