]> granicus.if.org Git - pgbouncer/commitdiff
implement per-database pool_mode
authorCody Cutrer <cody@cutrer.us>
Wed, 18 Jan 2012 16:55:14 +0000 (09:55 -0700)
committerCody Cutrer <cody@instructure.com>
Fri, 27 Sep 2013 19:39:44 +0000 (13:39 -0600)
doc/config.txt
doc/usage.txt
include/bouncer.h
src/admin.c
src/loader.c
src/main.c
src/server.c

index e8b48097de921aab1ef826884bba44469badc513..8ca116f200f24f41d340e656d3af3a0c9e56b8cc 100644 (file)
@@ -533,6 +533,11 @@ Query to be executed after a connection is established, but before
 allowing the connection to be used by any clients. If the query raises errors,
 they are logged but ignored otherwise.
 
+==== pool_mode ====
+
+Set the pool mode specific to this database. If not set,
+the default pool_mode is used.
+
 === Extra parameters ===
 
 They allow setting default parameters on server connection.
index fd0942ea6fcde1e859be959312e5788a3daeeaf3..3033e5d6905d2123ad80188865f7fcb5aff4dbba 100644 (file)
@@ -376,6 +376,9 @@ force_user::
 pool_size::
   Maximum number of server connections.
 
+pool_mode::
+  The pooling mode in user for this database.
+
 ==== SHOW FDS; ====
 
 Internal command - shows list of fds in use with internal state attached to them.
index b3091d6056b9ac09889b234aa1a15f257044f634..3398e94b7d4e6b77452eda127aebf21717371985 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "system.h"
 
+#include <usual/cfparser.h>
 #include <usual/time.h>
 #include <usual/list.h>
 #include <usual/statlist.h>
@@ -120,6 +121,7 @@ extern int cf_sbuf_len;
 #define POOL_SESSION   0
 #define POOL_TX                1
 #define POOL_STMT      2
+#define POOL_INHERIT   3
 
 /* old style V2 header: len:4b code:4b */
 #define OLD_HEADER_LEN 8
@@ -273,6 +275,7 @@ struct PgDatabase {
 
        int pool_size;          /* max server connections in one pool */
        int res_pool_size;      /* additional server connections in case of trouble */
+       int pool_mode;          /* pool mode for this database */
 
        const char *dbname;     /* server-side name, pointer to inside startup_msg */
 
@@ -408,6 +411,8 @@ extern int cf_log_connections;
 extern int cf_log_disconnections;
 extern int cf_log_pooler_errors;
 
+extern const struct CfLookup pool_mode_map[];
+
 extern usec_t g_suspend_start;
 
 extern struct DNSContext *adns;
index dafcfa40b6cc77c544701de2cbfa0808f6fe6c35..a30eff1ca57956c5ca09548dc13532358ff8135c 100644 (file)
@@ -440,6 +440,8 @@ static bool admin_show_databases(PgSocket *admin, const char *arg)
        struct List *item;
        const char *f_user;
        PktBuf *buf;
+       struct CfValue cv;
+       int pool_mode;
 
        buf = pktbuf_dynamic(256);
        if (!buf) {
@@ -447,18 +449,25 @@ static bool admin_show_databases(PgSocket *admin, const char *arg)
                return true;
        }
 
-       pktbuf_write_RowDescription(buf, "ssissii",
+       pktbuf_write_RowDescription(buf, "ssissiis",
                                    "name", "host", "port",
-                                   "database", "force_user", "pool_size", "reserve_pool");
+                                   "database", "force_user", "pool_size", "reserve_pool",
+                                   "pool_mode");
        statlist_for_each(item, &database_list) {
                db = container_of(item, PgDatabase, head);
 
                f_user = db->forced_user ? db->forced_user->name : NULL;
-               pktbuf_write_DataRow(buf, "ssissii",
+               pool_mode = db->pool_mode;
+               if (pool_mode == POOL_INHERIT)
+                       pool_mode = cf_pool_mode;
+               cv.value_p = &pool_mode;
+               cv.extra = pool_mode_map;
+               pktbuf_write_DataRow(buf, "ssissiis",
                                     db->name, db->host, db->port,
                                     db->dbname, f_user,
                                     db->pool_size,
-                                    db->res_pool_size);
+                                    db->res_pool_size,
+                                    cf_get_lookup(&cv));
        }
        admin_flush(admin, buf, "SHOW");
        return true;
@@ -1351,6 +1360,7 @@ void admin_setup(void)
        db->port = cf_listen_port;
        db->pool_size = 2;
        db->admin = 1;
+       db->pool_mode = POOL_STMT;
        if (!force_user(db, "pgbouncer", ""))
                fatal("no mem on startup - cannot alloc pgbouncer user");
 
index 9b914a6ea73209ca9552ab6d368509f0f65d32c4..e7db4fd0559c40ef36a4b1d50a2763b4c90abc04 100644 (file)
@@ -177,9 +177,11 @@ bool parse_database(void *base, const char *name, const char *connstr)
        char *p, *key, *val;
        PktBuf *msg;
        PgDatabase *db;
+       struct CfValue cv;
        int pool_size = -1;
        int res_pool_size = -1;
        int dbname_ofs;
+       int pool_mode = POOL_INHERIT;
 
        char *tmp_connstr;
        const char *dbname = name;
@@ -195,6 +197,9 @@ bool parse_database(void *base, const char *name, const char *connstr)
 
        int v_port;
 
+       cv.value_p = &pool_mode;
+       cv.extra = (const void *)pool_mode_map;
+
        if (strcmp(name, "*") == 0) {
                set_autodb(connstr);
                return true;
@@ -233,7 +238,13 @@ bool parse_database(void *base, const char *name, const char *connstr)
                        pool_size = atoi(val);
                else if (strcmp("reserve_pool", key) == 0)
                        res_pool_size = atoi(val);
-               else if (strcmp("connect_query", key) == 0)
+               else if (strcmp("pool_mode", key) == 0) {
+                       if (!cf_set_lookup(&cv, val)) {
+                               log_error("skipping database %s because"
+                                         " of invalid pool mode: %s", name, val);
+                               goto fail;
+                       }
+               } else if (strcmp("connect_query", key) == 0)
                        connect_query = val;
                else if (strcmp("application_name", key) == 0)
                        appname = val;
@@ -302,6 +313,7 @@ bool parse_database(void *base, const char *name, const char *connstr)
        /* if pool_size < 0 it will be set later */
        db->pool_size = pool_size;
        db->res_pool_size = res_pool_size;
+       db->pool_mode = pool_mode;
 
        if (db->host)
                free(db->host);
index 1b83d6a470116a18fb82c3a914635cc1ecbec8fc..923b5302ab02a6896d5ba3238e2fb303f2430223 100644 (file)
@@ -150,7 +150,7 @@ static const struct CfLookup auth_type_map[] = {
        { NULL }
 };
 
-static const struct CfLookup pool_mode_map[] = {
+const struct CfLookup pool_mode_map[] = {
        { "session", POOL_SESSION },
        { "transaction", POOL_TX },
        { "statement", POOL_STMT },
index cb2a115ea4fa358f0f8dc1bdbd906d7a8dbb3df4..ffa2515b6cd50ed8ec3c58d8c1f8e30fe079fe86 100644 (file)
@@ -212,7 +212,8 @@ static bool handle_server_work(PgSocket *server, PktHdr *pkt)
                /* set ready only if no tx */
                if (state == 'I') {
                        ready = true;
-               } else if (cf_pool_mode == POOL_STMT) {
+               } else if (server->pool->db->pool_mode == POOL_STMT ||
+                       (server->pool->db->pool_mode == POOL_INHERIT && cf_pool_mode == POOL_STMT)) {
                        disconnect_server(server, true, "Long transactions not allowed");
                        return false;
                } else if (state == 'T' || state == 'E') {
@@ -351,6 +352,7 @@ bool server_proto(SBuf *sbuf, SBufEvent evtype, struct MBuf *data)
        PgSocket *server = container_of(sbuf, PgSocket, sbuf);
        PgPool *pool = server->pool;
        PktHdr pkt;
+       int pool_mode;
 
        Assert(is_server_socket(server));
        Assert(server->state != SV_FREE);
@@ -417,8 +419,11 @@ bool server_proto(SBuf *sbuf, SBufEvent evtype, struct MBuf *data)
                        sbuf_continue(&client->sbuf);
                        break;
                }
-               
-               if (cf_pool_mode  != POOL_SESSION || server->state == SV_TESTED) {
+
+               pool_mode = server->pool->db->pool_mode;
+               if (pool_mode == POOL_INHERIT)
+                       pool_mode = cf_pool_mode;               
+               if (pool_mode  != POOL_SESSION || server->state == SV_TESTED) {
                        switch (server->state) {
                        case SV_ACTIVE:
                        case SV_TESTED: