]> granicus.if.org Git - pgbouncer/commitdiff
idle_transaction_timeout: new config option
authorMarko Kreen <markokr@gmail.com>
Sun, 9 Oct 2011 08:08:06 +0000 (10:08 +0200)
committerMarko Kreen <markokr@gmail.com>
Sun, 9 Oct 2011 08:08:06 +0000 (10:08 +0200)
doc/config.txt
include/bouncer.h
src/client.c
src/janitor.c
src/main.c
src/server.c

index 9b12526463bf2a7d254e511b08ee1bd995bdcec3..30c6a18aa80c741d20bb2791401a0754eba3df72 100644 (file)
@@ -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 ====
index 3ef0fa2ab708d826face6c3f409cc00d015ba28d..6e9f66b2c4406736bc6fcfa4765f9f3d679cd9f5 100644 (file)
@@ -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;
index 8d14937b9b61792c4aac1b091bb0e3c456a817bb..43ca9e991dc5f0f0a8a493b133c876e23d636828 100644 (file)
@@ -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);
index 9a7baee3e0551d7f033bb0e7ad69df3a9a02d683..d8e01ca99317b7e0782842e31d3b14cb4fa8915d 100644 (file)
@@ -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");
+                       }
                }
        }
 
index 25847cd77bb477b7e642d74a49efcf88875984cd..aeaa2ee860236311b88ee789eb043ec3eb9beb3e 100644 (file)
@@ -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"),
index 2e3c44d9f24fa5fda77d3d2b990e5c94225c4b0e..c79052ac16d207875c7f9fd0d18b3184c08016ce 100644 (file)
@@ -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;