From: Marko Kreen Date: Wed, 1 Aug 2007 21:28:46 +0000 (+0000) Subject: server_reset_query X-Git-Tag: pgbouncer_1_1~69 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c34d005c131211e14bf504d04ad1ef813af66a30;p=pgbouncer server_reset_query --- diff --git a/NEWS b/NEWS index 0c5ebdd..17f038d 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ - Accept hostname in host= - Accept custom unix socket location in host= - Accept quoted values: password=' asd''foo' + * server_reset_query, to be sent immidiately after release * Cancel pkt sent for idle connection does not drop it anymore, just ReadyForQuery is re-sent. * Print FD limits on startup. diff --git a/doc/todo.txt b/doc/todo.txt index 00ed3d3..da65c86 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -3,7 +3,6 @@ == Small stuff == * cancel of SUSPEND/PAUSE - * reset_command to be issued immidiately after release * suspend_timeout - drop stalled conns == Low-prio == diff --git a/etc/pgbouncer.ini b/etc/pgbouncer.ini index 13b4406..a796f62 100644 --- a/etc/pgbouncer.ini +++ b/etc/pgbouncer.ini @@ -58,17 +58,25 @@ stats_users = stats, root ; statement - after statement finishes pool_mode = session -; When taking idle server into use, this query is ran first. ; -; Query for session pooling: -; ABORT; RESET ALL; SET SESSION AUTHORIZATION DEFAULT -; Query for statement/transaction pooling: +; Query for cleaning connection immidiately after releasing from client. +; +; Query for 8.3+: +; DISCARD ALL; +; +; Older versions: +; RESET ALL; SET SESSION AUTHORIZATION DEFAULT +; +server_reset_query = + +; +; When taking idle server into use, this query is ran first. ; SELECT 1 -; Empty query disables the functionality +; server_check_query = select 1 ; If server was used more recently that this many seconds ago, -; skip the check query. If 0, the check query is always ran. +; skip the check query. Value 0 may or may not run in immidiately. server_check_delay = 10 ;;; diff --git a/src/bouncer.h b/src/bouncer.h index cb93033..bf5e529 100644 --- a/src/bouncer.h +++ b/src/bouncer.h @@ -253,6 +253,7 @@ extern int cf_default_pool_size; extern usec_t cf_server_lifetime; extern usec_t cf_server_idle_timeout; +extern char * cf_server_reset_query; extern char * cf_server_check_query; extern usec_t cf_server_check_delay; extern usec_t cf_server_connect_timeout; diff --git a/src/main.c b/src/main.c index ea7f710..e6b2af2 100644 --- a/src/main.c +++ b/src/main.c @@ -77,6 +77,7 @@ char *cf_auth_file = "unconfigured_file"; int cf_max_client_conn = 20; int cf_default_pool_size = 10; +char *cf_server_reset_query = ""; char *cf_server_check_query = "select 1"; usec_t cf_server_check_delay = 30 * USEC; @@ -117,6 +118,7 @@ ConfElem bouncer_params[] = { {"max_client_conn", true, CF_INT, &cf_max_client_conn}, {"default_pool_size", true, CF_INT, &cf_default_pool_size}, +{"server_reset_query", true, CF_STR, &cf_server_reset_query}, {"server_check_query", true, CF_STR, &cf_server_check_query}, {"server_check_delay", true, CF_TIME, &cf_server_check_delay}, {"query_timeout", true, CF_TIME, &cf_query_timeout}, diff --git a/src/objects.c b/src/objects.c index b8304d1..ebb9b28 100644 --- a/src/objects.c +++ b/src/objects.c @@ -546,6 +546,37 @@ bool find_server(PgSocket *client) return res; } +/* pick waiting client */ +static bool reuse_on_release(PgSocket *server) +{ + bool res = true; + PgPool *pool = server->pool; + PgSocket *client = first_socket(&pool->waiting_client_list); + if (client) { + activate_client(client); + + /* + * As the activate_client() does full read loop, + * then it may happen that linked client close + * couses server close. Report it. + */ + if (server->state == SV_FREE || server->state == SV_JUSTFREE) + res = false; + } + return res; +} + +/* send reset query */ +static bool reset_on_release(PgSocket *server) +{ + bool res; + slog_debug(server, "Resetting: %s", cf_server_reset_query); + SEND_generic(res, server, 'Q', "s", cf_server_reset_query); + if (!res) + disconnect_server(server, false, "reset query failed"); + return res; +} + /* connecting/active -> idle, unlink if needed */ bool release_server(PgSocket *server) { @@ -560,7 +591,15 @@ bool release_server(PgSocket *server) server->link->link = NULL; server->link = NULL; - if (cf_server_check_delay == 0 && *cf_server_check_query) + if (*cf_server_reset_query) + /* notify reset is required */ + newstate = SV_TESTED; + else if (cf_server_check_delay == 0 && *cf_server_check_query) + /* + * depreceted: before reset_query, the check_delay = 0 + * was used to get same effect. This if() can be removed + * after couple of releases. + */ newstate = SV_USED; case SV_USED: case SV_TESTED: @@ -573,31 +612,15 @@ bool release_server(PgSocket *server) } Assert(server->link == NULL); - log_debug("release_server: new state=%d", newstate); - change_server_state(server, newstate); - /* immediately process waiters, to give fair chance */ - if (newstate == SV_IDLE) { - PgSocket *client = first_socket(&pool->waiting_client_list); - if (client) { - activate_client(client); + if (newstate == SV_IDLE) + /* immediately process waiters, to give fair chance */ + return reuse_on_release(server); + else if (newstate == SV_TESTED) + return reset_on_release(server); - /* - * As the activate_client() does full read loop, - * then it may happen that linked client close - * couses server close. Report it. - */ - switch (server->state) { - case SV_FREE: - case SV_JUSTFREE: - return false; - default: - break; - } - } - } return true; }