]> git.saurik.com Git - redis.git/blobdiff - redis.c
check if the list encoding needs to be changed on LPUSHX, RPUSHX, LINSERT
[redis.git] / redis.c
diff --git a/redis.c b/redis.c
index ca4d9f870e79b213fc44b144124361b1f4cd2f8f..efaeb0f1c6616e8938af8cf32a9419a1784aac50 100644 (file)
--- a/redis.c
+++ b/redis.c
@@ -4926,7 +4926,7 @@ static void listTypePush(robj *subject, robj *value, int where) {
     /* Check if we need to convert the ziplist */
     listTypeTryConversion(subject,value);
     if (subject->encoding == REDIS_ENCODING_ZIPLIST &&
-        ziplistLen(subject->ptr) > server.list_max_ziplist_entries)
+        ziplistLen(subject->ptr) >= server.list_max_ziplist_entries)
             listTypeConvert(subject,REDIS_ENCODING_LIST);
 
     if (subject->encoding == REDIS_ENCODING_ZIPLIST) {
@@ -5214,6 +5214,7 @@ static void pushxGenericCommand(redisClient *c, robj *refval, robj *val, int whe
     robj *subject;
     listTypeIterator *iter;
     listTypeEntry entry;
+    int inserted = 0;
 
     if ((subject = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||
         checkType(c,subject,REDIS_LIST)) return;
@@ -5227,20 +5228,36 @@ static void pushxGenericCommand(redisClient *c, robj *refval, robj *val, int whe
          * last argument of the multi-bulk LINSERT. */
         redisAssert(refval->encoding == REDIS_ENCODING_RAW);
 
+        /* We're not sure if this value can be inserted yet, but we cannot
+         * convert the list inside the iterator. We don't want to loop over
+         * the list twice (once to see if the value can be inserted and once
+         * to do the actual insert), so we assume this value can be inserted
+         * and convert the ziplist to a regular list if necessary. */
+        listTypeTryConversion(subject,val);
+
         /* Seek refval from head to tail */
         iter = listTypeInitIterator(subject,0,REDIS_TAIL);
         while (listTypeNext(iter,&entry)) {
             if (listTypeEqual(&entry,refval)) {
                 listTypeInsert(&entry,val,where);
+                inserted = 1;
                 break;
             }
         }
         listTypeReleaseIterator(iter);
+
+        if (inserted) {
+            /* Check if the length exceeds the ziplist length threshold. */
+            if (subject->encoding == REDIS_ENCODING_ZIPLIST &&
+                ziplistLen(subject->ptr) > server.list_max_ziplist_entries)
+                    listTypeConvert(subject,REDIS_ENCODING_LIST);
+            server.dirty++;
+        }
     } else {
         listTypePush(subject,val,where);
+        server.dirty++;
     }
 
-    server.dirty++;
     addReplyUlong(c,listTypeLength(subject));
 }