]> granicus.if.org Git - pgbouncer/commitdiff
Add DISABLE/ENABLE commands to prevent new connections.
authorWilliam Grant <william.grant@canonical.com>
Wed, 12 Sep 2012 09:59:31 +0000 (19:59 +1000)
committerWilliam Grant <william.grant@canonical.com>
Wed, 12 Sep 2012 10:02:12 +0000 (20:02 +1000)
DISABLE causes new connections to a particular database to be rejected
while existing ones continue. ENABLE allows new connections again.

NEWS
include/bouncer.h
src/admin.c
src/client.c

diff --git a/NEWS b/NEWS
index 859ba8cd781d7c66c73547da2abefe817540d1d1..ae0f986a3dc99a2553d19b4bb0aa420762169b37 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,10 @@
 2012-07-xx  -  PgBouncer 1.5.3  -  ""
 
-  = Minor Feature =
+  = Features =
+
+    * ENABLE/DISABLE commands to forbid or allow access to one database.
+
+  = Minor Features =
 
     * max_packet_size - config parameter to tune maximum packet size
       that is allowed through.  Default is kept same: (2G-1), but now
index 687126a146873b3841cac84cfd7e39c503f5dd0f..5dc47ebe5b05427a66a8dcf5554d7e7a0f18b8e5 100644 (file)
@@ -253,6 +253,7 @@ struct PgDatabase {
        bool db_paused;         /* PAUSE <db>; was issued */
        bool db_dead;           /* used on RELOAD/SIGHUP to later detect removed dbs */
        bool db_auto;           /* is the database auto-created by autodb_connstr */
+       bool db_disabled;       /* is the database accepting new connections? */
        bool admin;             /* internal console db */
 
        struct PktBuf *startup_params; /* partial StartupMessage (without user) be sent to server */
index 7bf9e8034d4acba8fecf2d93bc19738cda825279..9b2c7a6b233233c3502bbf7a8cd5ec4f6b8994b6 100644 (file)
@@ -980,6 +980,56 @@ static bool admin_cmd_pause(PgSocket *admin, const char *arg)
        return true;
 }
 
+/* Command: DISABLE */
+static bool admin_cmd_disable(PgSocket *admin, const char *arg)
+{
+       PgDatabase *db;
+
+       if (!admin->admin_user)
+               return admin_error(admin, "admin access needed");
+
+       if (!arg[0])
+               return admin_error(admin, "a database is required");
+
+       log_info("DISABLE '%s' command issued", arg);
+       db = find_database(arg);
+       if (db == NULL) {
+               db = register_auto_database(arg);
+               if (db == NULL) {
+                       return admin_error(admin, "no such database: %s", arg);
+               } else {
+                       slog_info(admin, "registered new auto-database for DISABLE: %s", arg);
+               }
+       }
+       if (db == admin->pool->db)
+               return admin_error(admin, "cannot disable admin db: %s", arg);
+
+       db->db_disabled = 1;
+       return admin_ready(admin, "DISABLE");
+}
+
+/* Command: ENABLE */
+static bool admin_cmd_enable(PgSocket *admin, const char *arg)
+{
+       PgDatabase *db;
+
+       if (!admin->admin_user)
+               return admin_error(admin, "admin access needed");
+
+       if (!arg[0])
+               return admin_error(admin, "a database is required");
+
+       log_info("ENABLE '%s' command issued", arg);
+       db = find_database(arg);
+       if (db == NULL)
+               return admin_error(admin, "no such database: %s", arg);
+       if (db == admin->pool->db)
+               return admin_error(admin, "cannot disable admin db: %s", arg);
+
+       db->db_disabled = 0;
+       return admin_ready(admin, "ENABLE");
+}
+
 /* Command: KILL */
 static bool admin_cmd_kill(PgSocket *admin, const char *arg)
 {
@@ -1133,6 +1183,8 @@ static bool admin_cmd_show(PgSocket *admin, const char *arg)
 }
 
 static struct cmd_lookup cmd_list [] = {
+       {"disable", admin_cmd_disable},
+       {"enable", admin_cmd_enable},
        {"kill", admin_cmd_kill},
        {"pause", admin_cmd_pause},
        {"reload", admin_cmd_reload},
index 056fb96927ee5f6bafe8d87befedf8cd9a8a73c7..c28bd7f4841ada8e813f660c33b5d08b88b21138 100644 (file)
@@ -105,6 +105,10 @@ bool set_pool(PgSocket *client, const char *dbname, const char *username)
                disconnect_client(client, true, "no memory for pool");
                return false;
        }
+       if (client->pool->db->db_disabled) {
+               disconnect_client(client, true, "pgbouncer database is disabled");
+               return false;
+       }
 
        return check_fast_fail(client);
 }