From: Cody Cutrer Date: Wed, 18 Jan 2012 16:55:14 +0000 (-0700) Subject: implement per-database pool_mode X-Git-Tag: pgbouncer_1_6_rc1~28^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6f89bfea50551c475a99df6a71c35cd0f724284d;p=pgbouncer implement per-database pool_mode --- diff --git a/doc/config.txt b/doc/config.txt index e8b4809..8ca116f 100644 --- a/doc/config.txt +++ b/doc/config.txt @@ -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. diff --git a/doc/usage.txt b/doc/usage.txt index fd0942e..3033e5d 100644 --- a/doc/usage.txt +++ b/doc/usage.txt @@ -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. diff --git a/include/bouncer.h b/include/bouncer.h index b3091d6..3398e94 100644 --- a/include/bouncer.h +++ b/include/bouncer.h @@ -22,6 +22,7 @@ #include "system.h" +#include #include #include #include @@ -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; diff --git a/src/admin.c b/src/admin.c index dafcfa4..a30eff1 100644 --- a/src/admin.c +++ b/src/admin.c @@ -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"); diff --git a/src/loader.c b/src/loader.c index 9b914a6..e7db4fd 100644 --- a/src/loader.c +++ b/src/loader.c @@ -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); diff --git a/src/main.c b/src/main.c index 1b83d6a..923b530 100644 --- a/src/main.c +++ b/src/main.c @@ -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 }, diff --git a/src/server.c b/src/server.c index cb2a115..ffa2515 100644 --- a/src/server.c +++ b/src/server.c @@ -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: