suspend_timeout, to force suspend
authorMarko Kreen <markokr@gmail.com>
Wed, 9 Jan 2008 13:42:47 +0000 (13:42 +0000)
committerMarko Kreen <markokr@gmail.com>
Wed, 9 Jan 2008 13:42:47 +0000 (13:42 +0000)
include/bouncer.h
include/janitor.h
src/admin.c
src/janitor.c
src/main.c

index 47dfdb926577e825ee942ab9518f6a58968c29f7..2678d6fb5dd056a9f6f03f67e8c04adb1956ab8d 100644 (file)
@@ -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)
index a01fddaa2f7128fbacdc6b2528b246ef33a085cc..665a213709801afa4f3d01cd2a293e4e8979b388 100644 (file)
@@ -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;
 
index d00ca3982ea01bf5b5c52acadf68dc0259d03094..f40bae722d9663b432131dc353ce2033ab47b698 100644 (file)
@@ -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;
 }
 
index 344cef0fef77e1c1323f7953f294b69eb73fccf7..f6685b4c54b6a9ec14086084f92d2c5f772597f7 100644 (file)
@@ -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();
index a896bd0c791a0dee448be907dbde880ad1684a15..1239033511157da3806d4308b27056d83494da58 100644 (file)
@@ -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},