From 0a5da11bd3761db9cde51e22803cc89a219c2dd5 Mon Sep 17 00:00:00 2001 From: Marko Kreen Date: Wed, 9 Jan 2008 13:42:47 +0000 Subject: [PATCH] suspend_timeout, to force suspend --- include/bouncer.h | 2 ++ include/janitor.h | 2 +- src/admin.c | 2 ++ src/janitor.c | 56 +++++++++++++++++++++++++++++++++++------------ src/main.c | 4 ++++ 5 files changed, 51 insertions(+), 15 deletions(-) diff --git a/include/bouncer.h b/include/bouncer.h index 47dfdb9..2678d6f 100644 --- a/include/bouncer.h +++ b/include/bouncer.h @@ -282,6 +282,7 @@ extern int cf_pool_mode; extern int cf_max_client_conn; extern int cf_default_pool_size; +extern usec_t cf_suspend_timeout; extern usec_t cf_server_lifetime; extern usec_t cf_server_idle_timeout; extern char * cf_server_reset_query; @@ -322,6 +323,7 @@ extern int cf_log_pooler_errors; extern ConfElem bouncer_params[]; +extern usec_t g_suspend_start; static inline PgSocket * _MUSTCHECK pop_socket(StatList *slist) diff --git a/include/janitor.h b/include/janitor.h index a01fdda..665a213 100644 --- a/include/janitor.h +++ b/include/janitor.h @@ -20,5 +20,5 @@ void janitor_setup(void); void config_postprocess(void); void resume_all(void); void per_loop_maint(void); -bool suspend_socket(PgSocket *sk) _MUSTCHECK; +bool suspend_socket(PgSocket *sk, bool force) _MUSTCHECK; diff --git a/src/admin.c b/src/admin.c index d00ca39..f40bae7 100644 --- a/src/admin.c +++ b/src/admin.c @@ -772,6 +772,8 @@ static bool admin_cmd_suspend(PgSocket *admin, const char *arg) admin->wait_for_response = 1; suspend_pooler(); + g_suspend_start = get_cached_time(); + return true; } diff --git a/src/janitor.c b/src/janitor.c index 344cef0..f6685b4 100644 --- a/src/janitor.c +++ b/src/janitor.c @@ -38,20 +38,38 @@ static void close_server_list(StatList *sk_list, const char *reason) } } -bool suspend_socket(PgSocket *sk) +static void close_client_list(StatList *sk_list, const char *reason) { + List *item, *tmp; + PgSocket *client; + + statlist_for_each_safe(item, sk_list, tmp) { + client = container_of(item, PgSocket, head); + disconnect_client(client, true, reason); + } +} + +bool suspend_socket(PgSocket *sk, bool force_suspend) +{ + bool done = true; if (!sk->suspended) { if (sbuf_is_empty(&sk->sbuf)) { sbuf_pause(&sk->sbuf); sk->suspended = 1; } else - return false; + done = false; } - return true; + if (!done && force_suspend) { + if (is_server_socket(sk)) + disconnect_server(sk, true, "suspend_timeout"); + else + disconnect_client(sk, true, "suspend_timeout"); + } + return done; } /* suspend all sockets in socket list */ -static int suspend_socket_list(StatList *list) +static int suspend_socket_list(StatList *list, bool force_suspend) { List *item; PgSocket *sk; @@ -59,7 +77,7 @@ static int suspend_socket_list(StatList *list) statlist_for_each(item, list) { sk = container_of(item, PgSocket, head); - if (!suspend_socket(sk)) + if (!suspend_socket(sk, force_suspend)) active++; } return active; @@ -204,23 +222,23 @@ static int per_loop_pause(PgPool *pool) /* * suspend active clients and servers */ -static int per_loop_suspend(PgPool *pool) +static int per_loop_suspend(PgPool *pool, bool force_suspend) { int active = 0; if (pool->admin) return 0; - active += suspend_socket_list(&pool->active_client_list); + active += suspend_socket_list(&pool->active_client_list, force_suspend); - if (!statlist_empty(&pool->waiting_client_list)) { - active += statlist_count(&pool->waiting_client_list); + /* this list is unsuspendable, but still need force_suspend and counting */ + active += suspend_socket_list(&pool->waiting_client_list, force_suspend); + if (active) per_loop_activate(pool); - } if (!active) { - active += suspend_socket_list(&pool->active_server_list); - active += suspend_socket_list(&pool->idle_server_list); + active += suspend_socket_list(&pool->active_server_list, force_suspend); + active += suspend_socket_list(&pool->idle_server_list, force_suspend); /* as all clients are done, no need for them */ close_server_list(&pool->tested_server_list, "close unsafe file descriptors on suspend"); @@ -239,6 +257,13 @@ void per_loop_maint(void) PgPool *pool; int active = 0; int partial_pause = 0; + bool force_suspend = false; + + if (cf_pause_mode == P_SUSPEND && cf_suspend_timeout > 0) { + usec_t stime = get_cached_time() - g_suspend_start; + if (stime >= cf_suspend_timeout) + force_suspend = true; + } statlist_for_each(item, &pool_list) { pool = container_of(item, PgPool, head); @@ -256,14 +281,17 @@ void per_loop_maint(void) active += per_loop_pause(pool); break; case P_SUSPEND: - active += per_loop_suspend(pool); + active += per_loop_suspend(pool, force_suspend); break; } } switch (cf_pause_mode) { case P_SUSPEND: - active += statlist_count(&login_client_list); + if (force_suspend) { + close_client_list(&login_client_list, "suspend_timeout"); + } else + active += statlist_count(&login_client_list); case P_PAUSE: if (!active) admin_pause_done(); diff --git a/src/main.c b/src/main.c index a896bd0..1239033 100644 --- a/src/main.c +++ b/src/main.c @@ -92,6 +92,9 @@ usec_t cf_server_login_retry = 15*USEC; usec_t cf_query_timeout = 0*USEC; usec_t cf_client_idle_timeout = 0*USEC; usec_t cf_client_login_timeout = 60*USEC; +usec_t cf_suspend_timeout = 10*USEC; + +usec_t g_suspend_start = 0; char *cf_logfile = NULL; char *cf_pidfile = NULL; @@ -135,6 +138,7 @@ ConfElem bouncer_params[] = { {"server_connect_timeout",true, CF_TIME, &cf_server_connect_timeout}, {"server_login_retry", true, CF_TIME, &cf_server_login_retry}, {"server_round_robin", true, CF_INT, &cf_server_round_robin}, +{"suspend_timeout", true, CF_TIME, &cf_suspend_timeout}, {"pkt_buf", false, CF_INT, &cf_sbuf_len}, {"tcp_defer_accept", false, CF_INT, &cf_tcp_defer_accept}, -- 2.40.0