]> granicus.if.org Git - pgbouncer/commitdiff
Fix autodb cleanup
authorMarko Kreen <markokr@gmail.com>
Tue, 29 Mar 2011 06:26:12 +0000 (09:26 +0300)
committerMarko Kreen <markokr@gmail.com>
Tue, 29 Mar 2011 06:26:12 +0000 (09:26 +0300)
Old cleanup code was mixing up databases and pools
- as soon as one empty pool was found, the database
was tagged as 'idle', potentially later killing database
with active users.

Change the code to tag database as active when active
pool is found and later checking for inactive databases.

Reported-By: Hubert Depesz Lubaczewski
include/bouncer.h
src/janitor.c

index 77eb3b2eeaedf4fb043a014ae8f4710407385472..df84fa883023146056f47e532a34f2b352e7013c 100644 (file)
@@ -269,7 +269,8 @@ struct PgDatabase {
        /* startup commands to send to server after connect. malloc-ed */
        const char *connect_query;
 
-       usec_t inactive_time; /* when auto-database became inactive (to kill it after timeout) */
+       usec_t inactive_time;   /* when auto-database became inactive (to kill it after timeout) */
+       unsigned active_stamp;  /* set if autodb has connections */
 };
 
 
index bed166d9b37f3bd9db903311e799b140c644b6a7..ea964fa44733bae17e4a5f6cb155f374b9b1c98c 100644 (file)
@@ -502,6 +502,7 @@ static void cleanup_inactive_autodatabases(void)
        if (cf_autodb_idle_timeout <= 0)
                return;
 
+       /* now kill the old ones */
        statlist_for_each_safe(item, &autodatabase_idle_list, tmp) {
                db = container_of(item, PgDatabase, head);
                age = now - db->inactive_time;
@@ -517,6 +518,10 @@ static void do_full_maint(int sock, short flags, void *arg)
 {
        struct List *item, *tmp;
        PgPool *pool;
+       PgDatabase *db;
+
+       static unsigned int seq;
+       seq++;
 
        /*
         * Avoid doing anything that may surprise other pgbouncer.
@@ -530,9 +535,21 @@ static void do_full_maint(int sock, short flags, void *arg)
                        continue;
                pool_server_maint(pool);
                pool_client_maint(pool);
-               if (pool->db->db_auto && pool->db->inactive_time == 0 &&
-                               pool_client_count(pool) == 0 && pool_server_count(pool) == 0 ) {
-                       pool->db->inactive_time = get_cached_time();
+
+               /* is autodb active? */
+               if (pool->db->db_auto && pool->db->inactive_time == 0) {
+                       if (pool_client_count(pool) > 0 || pool_server_count(pool) > 0)
+                               pool->db->active_stamp = seq;
+               }
+       }
+
+       /* find inactive autodbs */
+       statlist_for_each_safe(item, &database_list, tmp) {
+               db = container_of(item, PgDatabase, head);
+               if (db->db_auto && db->inactive_time == 0) {
+                       if (db->active_stamp == seq)
+                               continue;
+                       db->inactive_time = get_cached_time();
                        statlist_remove(&database_list, &pool->db->head);
                        statlist_append(&autodatabase_idle_list, &pool->db->head);
                }