From: Marko Kreen Date: Fri, 11 Jan 2008 21:23:18 +0000 (+0000) Subject: actively kill databases removed from config X-Git-Tag: pgbouncer_1_2_rc2~66 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6601da54a2da71eba2419c9cb3ca4aac82d6c8a3;p=pgbouncer actively kill databases removed from config --- diff --git a/include/bouncer.h b/include/bouncer.h index 2678d6f..81fcfe6 100644 --- a/include/bouncer.h +++ b/include/bouncer.h @@ -201,6 +201,7 @@ struct PgDatabase { char name[MAX_DBNAME]; unsigned db_paused:1; + unsigned db_dead:1; /* key/val pairs (without user) for startup msg to be sent to server */ uint8_t startup_params[256]; diff --git a/src/janitor.c b/src/janitor.c index 4c4d100..a596313 100644 --- a/src/janitor.c +++ b/src/janitor.c @@ -511,16 +511,55 @@ void janitor_setup(void) safe_evtimer_add(&full_maint_ev, &full_maint_period); } +static void kill_pool(PgPool *pool) +{ + const char *reason = "database removed"; + + close_client_list(&pool->active_client_list, reason); + close_client_list(&pool->waiting_client_list, reason); + close_client_list(&pool->cancel_req_list, reason); + + close_server_list(&pool->active_server_list, reason); + close_server_list(&pool->idle_server_list, reason); + close_server_list(&pool->used_server_list, reason); + close_server_list(&pool->tested_server_list, reason); + close_server_list(&pool->new_server_list, reason); + + list_del(&pool->map_head); + statlist_remove(&pool->head, &pool_list); + free(pool); +} + +static void kill_database(PgDatabase *db) +{ + PgPool *pool; + List *item, *tmp; + + log_warning("dropping database '%s' as it does not exist anymore", db->name); + + statlist_for_each_safe(item, &pool_list, tmp) { + pool = container_of(item, PgPool, head); + if (pool->db == db) + kill_pool(pool); + } + if (db->forced_user) + free(db->forced_user); + statlist_remove(&db->head, &database_list); + free(db); +} + /* as [pgbouncer] section can be loaded after databases, there's need for review */ void config_postprocess(void) { - List *item; + List *item, *tmp; PgDatabase *db; - statlist_for_each(item, &database_list) { + statlist_for_each_safe(item, &database_list, tmp) { db = container_of(item, PgDatabase, head); - if (db->pool_size < 0) + if (db->db_dead) + kill_database(db); + else if (db->pool_size < 0) db->pool_size = cf_default_pool_size; } } diff --git a/src/loader.c b/src/loader.c index e57ccab..5ff6acf 100644 --- a/src/loader.c +++ b/src/loader.c @@ -234,6 +234,9 @@ void parse_database(char *name, char *connstr) return; } + /* tag the db as alive */ + db->db_dead = 0; + /* if updating old db, check if anything changed */ if (db->dbname) { bool changed = false; diff --git a/src/main.c b/src/main.c index 9d1c3f7..828d5e5 100644 --- a/src/main.c +++ b/src/main.c @@ -223,18 +223,39 @@ static bool set_auth(ConfElem *elem, const char *val, PgSocket *console) return true; } +static void set_dbs_dead(bool flag) +{ + List *item; + PgDatabase *db; + + statlist_for_each(item, &database_list) { + db = container_of(item, PgDatabase, head); + if (strcmp(db->name, "pgbouncer") == 0) + continue; + db->db_dead = flag; + } +} + /* config loading, tries to be tolerant to errors */ void load_config(bool reload) { - /* actual loading */ - iniparser(cf_config_file, bouncer_config, reload); + bool ok; - /* load users if needed */ - if (cf_auth_type >= AUTH_TRUST) - load_auth_file(cf_auth_file); + set_dbs_dead(true); - /* reset pool_size */ - config_postprocess(); + /* actual loading */ + ok = iniparser(cf_config_file, bouncer_config, reload); + if (ok) { + /* load users if needed */ + if (cf_auth_type >= AUTH_TRUST) + load_auth_file(cf_auth_file); + + /* reset pool_size, kill dbs */ + config_postprocess(); + } else { + /* if ini file missing, dont kill anybody */ + set_dbs_dead(false); + } /* reopen logfile */ if (reload)