]> granicus.if.org Git - pgbouncer/commitdiff
<usual/strpool.h>
authorMarko Kreen <markokr@gmail.com>
Tue, 4 May 2010 13:56:33 +0000 (16:56 +0300)
committerMarko Kreen <markokr@gmail.com>
Tue, 4 May 2010 14:20:43 +0000 (17:20 +0300)
Removes fixed-length limit from parameter values.

include/bouncer.h
include/varcache.h
src/admin.c
src/janitor.c
src/objects.c
src/varcache.c

index 7747a560b51778856cb4cc71308da1beed16beb4..a6ab8c7af91217d1312e3d037cb3ba674abdb38b 100644 (file)
@@ -34,6 +34,7 @@
 #include <usual/safeio.h>
 #include <usual/mbuf.h>
 #include <usual/event.h>
+#include <usual/strpool.h>
 
 #ifdef DBGVER
 #define FULLVER   PACKAGE_NAME " version " PACKAGE_VERSION " (" DBGVER ")"
index 1cf48210c334e20d6c73413ce2892f9bc0cd4f31..b9004bfec07ddb104b926397d93a02895238e374 100644 (file)
@@ -1,16 +1,16 @@
 
-#define VAR_ENCODING_LEN       16
-#define VAR_DATESTYLE_LEN      32
-#define VAR_TIMEZONE_LEN       36
-#define VAR_STDSTR_LEN         4
+enum VarCacheIdx {
+       VDateStyle = 0,
+       VClientEncoding,
+       VTimeZone,
+       VStdStr,
+       NumVars
+};
 
 typedef struct VarCache VarCache;
 
 struct VarCache {
-       char client_encoding[VAR_ENCODING_LEN];
-       char datestyle[VAR_DATESTYLE_LEN];
-       char timezone[VAR_TIMEZONE_LEN];
-       char std_strings[VAR_STDSTR_LEN];
+       struct PStr *var_list[NumVars];
 };
 
 bool varcache_set(VarCache *cache, const char *key, const char *value) /* _MUSTCHECK */;
index 8cb896a0fad7258d9e98613197994690fc0faba6..79404932aa52c80c7298af587164cbf6c12a53f5 100644 (file)
@@ -286,6 +286,10 @@ static bool show_one_fd(PgSocket *admin, PgSocket *sk)
        struct MBuf tmp;
        VarCache *v = &sk->vars;
        uint64_t ckey;
+       const struct PStr *client_encoding = v->var_list[VClientEncoding];
+       const struct PStr *std_strings = v->var_list[VStdStr];
+       const struct PStr *datestyle = v->var_list[VDateStyle];
+       const struct PStr *timezone = v->var_list[VTimeZone];
 
        mbuf_init_fixed_reader(&tmp, sk->cancel_key, 8);
        if (!mbuf_get_uint64be(&tmp, &ckey))
@@ -299,10 +303,10 @@ static bool show_one_fd(PgSocket *admin, PgSocket *sk)
                           addr->port,
                           ckey,
                           sk->link ? sbuf_socket(&sk->link->sbuf) : 0,
-                          v->client_encoding[0] ? v->client_encoding : NULL,
-                          v->std_strings[0] ? v->std_strings : NULL,
-                          v->datestyle[0] ? v->datestyle : NULL,
-                          v->timezone[0] ? v->timezone : NULL);
+                          client_encoding ? client_encoding->str : NULL,
+                          std_strings ? std_strings->str : NULL,
+                          datestyle ? datestyle->str : NULL,
+                          timezone ? timezone->str : NULL);
 }
 
 /* send a row with sendmsg, optionally attaching a fd */
index 40ffb565710e7986bec7150d7a02c0221757cdb1..409167ddfcafe7c4c4b39065fa1e1119091a119e 100644 (file)
@@ -578,6 +578,7 @@ static void kill_pool(PgPool *pool)
 
        list_del(&pool->map_head);
        statlist_remove(&pool_list, &pool->head);
+       varcache_clean(&pool->orig_vars);
        slab_free(pool_cache, pool);
 }
 
index 966ca0a537aaba8bea93e07718537ff90b374a71..6251ef7e9520a67ec6ee382d0bf6b405df4d6317 100644 (file)
@@ -153,6 +153,7 @@ void change_client_state(PgSocket *client, SocketState newstate)
        /* put to new location */
        switch (client->state) {
        case CL_FREE:
+               varcache_clean(&client->vars);
                slab_free(client_cache, client);
                break;
        case CL_JUSTFREE:
@@ -211,6 +212,7 @@ void change_server_state(PgSocket *server, SocketState newstate)
        /* put to new location */
        switch (server->state) {
        case SV_FREE:
+               varcache_clean(&server->vars);
                slab_free(server_cache, server);
                break;
        case SV_JUSTFREE:
index d6f54f93b2bb5725f1ba224661181ca4f01d986a..ce3fc8eb77c3ba5c9881ec2f15fb6cd3abd4a56c 100644 (file)
 
 struct var_lookup {
        const char *name;
-       int offset;
-       int len;
+       enum VarCacheIdx idx;
 };
 
 static const struct var_lookup lookup [] = {
- {"client_encoding",             offsetof(VarCache, client_encoding), VAR_ENCODING_LEN },
- {"datestyle",                   offsetof(VarCache, datestyle),       VAR_DATESTYLE_LEN },
- {"timezone",                    offsetof(VarCache, timezone),        VAR_TIMEZONE_LEN },
- {"standard_conforming_strings", offsetof(VarCache, std_strings),     VAR_STDSTR_LEN },
+ {"client_encoding",             VClientEncoding },
+ {"datestyle",                   VDateStyle },
+ {"timezone",                    VTimeZone },
+ {"standard_conforming_strings", VStdStr },
  {NULL},
 };
 
-static inline char *get_value(VarCache *cache, const struct var_lookup *lk)
+static struct StrPool *vpool;
+
+static inline struct PStr *get_value(VarCache *cache, const struct var_lookup *lk)
 {
-       return (char *)(cache) + lk->offset;
+       return cache->var_list[lk->idx];
 }
 
 bool varcache_set(VarCache *cache, const char *key, const char *value)
 {
-       int vlen;
-       char *pos;
        const struct var_lookup *lk;
+       struct PStr *pstr = NULL;
 
-       /* convert NULL to empty string */
-       if (value == NULL)
-               value = "";
-
-       for (lk = lookup; lk->name; lk++) {
-               if (strcasecmp(lk->name, key) != 0)
-                       continue;
-
-               vlen = strlen(value);
-               if (vlen >= lk->len) {
-                       log_warning("varcache_set overflow: %s", key);
+       if (!vpool) {
+               vpool = strpool_create();
+               if (!vpool)
                        return false;
-               }
+       }
 
-               pos = get_value(cache, lk);
-               memcpy(pos, value, vlen + 1);
-               return true;
+       for (lk = lookup; lk->name; lk++) {
+               if (strcasecmp(lk->name, key) == 0)
+                       goto set_value;
        }
        return false;
+
+set_value:
+       /* drop old value */
+       strpool_decref(cache->var_list[lk->idx]);
+       cache->var_list[lk->idx] = NULL;
+
+       /* ignore empty value */
+       if (!value && !value[0])
+               return false;
+
+       /* set new value */
+       pstr = strpool_get(vpool, value, strlen(value));
+       if (!pstr)
+               return false;
+       cache->var_list[lk->idx] = pstr;
+       return true;
 }
 
 static bool is_std_quote(VarCache *vars)
 {
-       const char *val = vars->std_strings;
-       return strcasecmp(val, "on") == 0;
+       const struct PStr *s = vars->var_list[VStdStr];
+       return s && strcasecmp(s->str, "on") == 0;
 }
 
 static bool quote_literal(char *buf, int buflen, const char *src, bool std_quote)
@@ -134,7 +142,7 @@ bool varcache_apply(PgSocket *server, PgSocket *client, bool *changes_p)
        PktBuf pkt;
        uint8_t buf[STARTUP_BUF];
        int changes = 0;
-       const char *cval, *sval;
+       struct PStr *cval, *sval;
        const struct var_lookup *lk;
        uint8_t *debug_sql;
        bool std_quote = is_std_quote(&server->vars);
@@ -148,7 +156,8 @@ bool varcache_apply(PgSocket *server, PgSocket *client, bool *changes_p)
        for (lk = lookup; lk->name; lk++) {
                sval = get_value(&server->vars, lk);
                cval = get_value(&client->vars, lk);
-               changes += apply_var(&pkt, lk->name, cval, sval, std_quote);
+               if (cval)
+                       changes += apply_var(&pkt, lk->name, cval->str, sval->str, std_quote);
        }
        *changes_p = changes > 0;
        if (!changes)
@@ -163,32 +172,35 @@ bool varcache_apply(PgSocket *server, PgSocket *client, bool *changes_p)
 
 void varcache_fill_unset(VarCache *src, PgSocket *dst)
 {
-       char *srcval, *dstval;
+       struct PStr *srcval, *dstval;
        const struct var_lookup *lk;
        for (lk = lookup; lk->name; lk++) {
-               srcval = get_value(src, lk);
-               dstval = get_value(&dst->vars, lk);
-               if (!*dstval)
-                       memcpy(dstval, srcval, lk->len);
+               srcval = src->var_list[lk->idx];
+               dstval = dst->vars.var_list[lk->idx];
+               if (!dstval) {
+                       strpool_incref(srcval);
+                       dst->vars.var_list[lk->idx] = srcval;
+               }
        }
 }
 
 void varcache_clean(VarCache *cache)
 {
-       cache->client_encoding[0] = 0;
-       cache->datestyle[0] = 0;
-       cache->timezone[0] = 0;
-       cache->std_strings[0] = 0;
+       int i;
+       for (i = 0; i < NumVars; i++) {
+               strpool_decref(cache->var_list[i]);
+               cache->var_list[i] = NULL;
+       }
 }
 
 void varcache_add_params(PktBuf *pkt, VarCache *vars)
 {
-       char *val;
+       struct PStr *val;
        const struct var_lookup *lk;
        for (lk = lookup; lk->name; lk++) {
-               val = get_value(vars, lk);
-               if (*val)
-                       pktbuf_write_ParameterStatus(pkt, lk->name, val);
+               val = vars->var_list[lk->idx];
+               if (val)
+                       pktbuf_write_ParameterStatus(pkt, lk->name, val->str);
        }
 }