summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Kreen2011-03-29 06:26:12 +0000
committerMarko Kreen2011-03-29 06:26:12 +0000
commitfea8fcf8ba42581d64a12e5922260e28c7494f0a (patch)
tree03ec7d0db51752847b14b8f88e72e64f025d0050
parent30032a9f8431a7abaea6d2c325690a0470c6807d (diff)
Fix autodb cleanup
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
-rw-r--r--include/bouncer.h3
-rw-r--r--src/janitor.c23
2 files changed, 22 insertions, 4 deletions
diff --git a/include/bouncer.h b/include/bouncer.h
index 77eb3b2..df84fa8 100644
--- a/include/bouncer.h
+++ b/include/bouncer.h
@@ -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 */
};
diff --git a/src/janitor.c b/src/janitor.c
index bed166d..ea964fa 100644
--- a/src/janitor.c
+++ b/src/janitor.c
@@ -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);
}