]> git.saurik.com Git - redis.git/commitdiff
make sure sets have the right encoding when loaded from rdb
authorPieter Noordhuis <pcnoordhuis@gmail.com>
Sun, 13 Jun 2010 19:42:04 +0000 (21:42 +0200)
committerPieter Noordhuis <pcnoordhuis@gmail.com>
Sun, 13 Jun 2010 19:42:04 +0000 (21:42 +0200)
redis.c
tests/unit/type/set.tcl

diff --git a/redis.c b/redis.c
index 0cf768ac895c559cf4de4e565e69d890edebaa26..0d6648eeb82b389fd6e14ee87977d35e5603a8a1 100644 (file)
--- a/redis.c
+++ b/redis.c
@@ -4234,16 +4234,38 @@ static robj *rdbLoadObject(int type, FILE *fp) {
     } else if (type == REDIS_SET) {
         /* Read list/set value */
         if ((len = rdbLoadLen(fp,NULL)) == REDIS_RDB_LENERR) return NULL;
-        o = createSetObject();
-        /* It's faster to expand the dict to the right size asap in order
-         * to avoid rehashing */
-        if (len > DICT_HT_INITIAL_SIZE)
-            dictExpand(o->ptr,len);
+
+        /* Use a regular set when there are too many entries. */
+        if (len > server.set_max_intset_entries) {
+            o = createSetObject();
+            /* It's faster to expand the dict to the right size asap in order
+             * to avoid rehashing */
+            if (len > DICT_HT_INITIAL_SIZE)
+                dictExpand(o->ptr,len);
+        } else {
+            o = createIntsetObject();
+        }
+
         /* Load every single element of the list/set */
         while(len--) {
+            long long llval;
             if ((ele = rdbLoadEncodedStringObject(fp)) == NULL) return NULL;
             ele = tryObjectEncoding(ele);
-            dictAdd((dict*)o->ptr,ele,NULL);
+
+            if (o->encoding == REDIS_ENCODING_INTSET) {
+                /* Fetch integer value from element */
+                if (getLongLongFromObject(ele,&llval) == REDIS_OK) {
+                    o->ptr = intsetAdd(o->ptr,llval,NULL);
+                } else {
+                    setTypeConvert(o,REDIS_ENCODING_HT);
+                }
+            }
+
+            /* This will also be called when the set was just converted
+             * to regular hashtable encoded set */
+            if (o->encoding == REDIS_ENCODING_HT) {
+                dictAdd((dict*)o->ptr,ele,NULL);
+            }
         }
     } else if (type == REDIS_ZSET) {
         /* Read list/set value */
index f9e7f4bdc84121dc415373ae36e0492664229753..a1b655ef8891abb6b0cf54f3d862080056120d0a 100644 (file)
@@ -53,6 +53,21 @@ start_server {
         assert_encoding hashtable myset
     }
 
+    test "Set encoding after DEBUG RELOAD" {
+        r del myintset myhashset mylargeintset
+        for {set i 0} {$i <  100} {incr i} { r sadd myintset $i }
+        for {set i 0} {$i < 1280} {incr i} { r sadd mylargeintset $i }
+        for {set i 0} {$i <  256} {incr i} { r sadd myhashset [format "i%03d" $i] }
+        assert_encoding intset myintset
+        assert_encoding hashtable mylargeintset
+        assert_encoding hashtable myhashset
+
+        r debug reload
+        assert_encoding intset myintset
+        assert_encoding hashtable mylargeintset
+        assert_encoding hashtable myhashset
+    }
+
     test {SREM basics - regular set} {
         create_set myset {foo bar ciao}
         assert_encoding hashtable myset