From: Marko Kreen Date: Sun, 9 Oct 2011 08:08:06 +0000 (+0200) Subject: idle_transaction_timeout: new config option X-Git-Tag: pgbouncer_1_5_rc1~48 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7ab965d06938c6690da6be060c64b1410a5aa4b6;p=pgbouncer idle_transaction_timeout: new config option --- diff --git a/doc/config.txt b/doc/config.txt index 9b12526..30c6a18 100644 --- a/doc/config.txt +++ b/doc/config.txt @@ -372,6 +372,13 @@ for network problems. [seconds] Default: 0 (disabled) +==== idle_transaction_timeout ==== + +If client has been in "idle in transaction" state longer, it will be disconnected. +[seconds] + +Default: 0 (disabled) + === Low-level network settings === ==== pkt_buf ==== diff --git a/include/bouncer.h b/include/bouncer.h index 3ef0fa2..6e9f66b 100644 --- a/include/bouncer.h +++ b/include/bouncer.h @@ -290,6 +290,7 @@ struct PgSocket { SocketState state:8; /* this also specifies socket location */ bool ready:1; /* server: accepts new query */ + bool idle_tx:1; /* server: idling in tx */ bool close_needed:1; /* server: this socket must be closed ASAP */ bool setting_vars:1; /* server: setting client vars */ bool exec_on_connect:1; /* server: executing connect_query */ @@ -361,6 +362,7 @@ extern usec_t cf_query_timeout; extern usec_t cf_query_wait_timeout; extern usec_t cf_client_idle_timeout; extern usec_t cf_client_login_timeout; +extern usec_t cf_idle_transaction_timeout; extern int cf_server_round_robin; extern int cf_disable_pqexec; extern usec_t cf_dns_max_ttl; diff --git a/src/client.c b/src/client.c index 8d14937..43ca9e9 100644 --- a/src/client.c +++ b/src/client.c @@ -337,7 +337,8 @@ static bool handle_client_work(PgSocket *client, PktHdr *pkt) client->pool->stats.client_bytes += pkt->len; /* tag the server as dirty */ - client->link->ready = 0; + client->link->ready = false; + client->link->idle_tx = false; /* forward the packet */ sbuf_prepare_send(sbuf, &client->link->sbuf, pkt->len); diff --git a/src/janitor.c b/src/janitor.c index 9a7baee..d8e01ca 100644 --- a/src/janitor.c +++ b/src/janitor.c @@ -458,15 +458,21 @@ static void pool_server_maint(PgPool *pool) check_unused_servers(pool, &pool->idle_server_list, 1); /* where query got did not get answer in query_timeout */ - if (cf_query_timeout > 0) { + if (cf_query_timeout > 0 || cf_idle_transaction_timeout > 0) { statlist_for_each_safe(item, &pool->active_server_list, tmp) { server = container_of(item, PgSocket, head); Assert(server->state == SV_ACTIVE); if (server->ready) continue; age = now - server->link->request_time; - if (age > cf_query_timeout) + if (cf_query_timeout > 0 && age > cf_query_timeout) { disconnect_server(server, true, "query timeout"); + } else if (cf_idle_transaction_timeout > 0 && + server->idle_tx && + age > cf_idle_transaction_timeout) + { + disconnect_server(server, true, "idle transaction timeout"); + } } } diff --git a/src/main.c b/src/main.c index 25847cd..aeaa2ee 100644 --- a/src/main.c +++ b/src/main.c @@ -112,6 +112,7 @@ usec_t cf_query_timeout; usec_t cf_query_wait_timeout; usec_t cf_client_idle_timeout; usec_t cf_client_login_timeout; +usec_t cf_idle_transaction_timeout; usec_t cf_suspend_timeout; usec_t g_suspend_start; @@ -190,6 +191,7 @@ CF_ABS("query_timeout", CF_TIME_USEC, cf_query_timeout, 0, "0"), CF_ABS("query_wait_timeout", CF_TIME_USEC, cf_query_wait_timeout, 0, "0"), CF_ABS("client_idle_timeout", CF_TIME_USEC, cf_client_idle_timeout, 0, "0"), CF_ABS("client_login_timeout", CF_TIME_USEC, cf_client_login_timeout, 0, "60"), +CF_ABS("idle_transaction_timeout", CF_TIME_USEC, cf_idle_transaction_timeout, 0, "0"), CF_ABS("server_lifetime", CF_TIME_USEC, cf_server_lifetime, 0, "3600"), CF_ABS("server_idle_timeout", CF_TIME_USEC, cf_server_idle_timeout, 0, "600"), CF_ABS("server_connect_timeout", CF_TIME_USEC, cf_server_connect_timeout, 0, "15"), diff --git a/src/server.c b/src/server.c index 2e3c44d..c79052a 100644 --- a/src/server.c +++ b/src/server.c @@ -188,7 +188,8 @@ static bool handle_server_startup(PgSocket *server, PktHdr *pkt) /* process packets on logged in connection */ static bool handle_server_work(PgSocket *server, PktHdr *pkt) { - bool ready = 0; + bool ready = false; + bool idle_tx = false; char state; SBuf *sbuf = &server->sbuf; PgSocket *client = server->link; @@ -209,11 +210,13 @@ static bool handle_server_work(PgSocket *server, PktHdr *pkt) return false; /* set ready only if no tx */ - if (state == 'I') - ready = 1; - else if (cf_pool_mode == POOL_STMT) { + if (state == 'I') { + ready = true; + } else if (cf_pool_mode == POOL_STMT) { disconnect_server(server, true, "Long transactions not allowed"); return false; + } else if (state == 'T' || state == 'E') { + idle_tx = true; } break; @@ -279,6 +282,7 @@ static bool handle_server_work(PgSocket *server, PktHdr *pkt) case 'T': /* RowDescription */ break; } + server->idle_tx = idle_tx; server->ready = ready; server->pool->stats.server_bytes += pkt->len;