]> git.saurik.com Git - redis.git/blobdiff - src/t_list.c
Merge pull request #58 from hampus/fix-autorewrite
[redis.git] / src / t_list.c
index d5db6feb324c21e7811203e0ed320662d6e0dd4c..7c1b848a814b3a9cc08ceb61e615d3eb5e167744 100644 (file)
@@ -259,30 +259,35 @@ void listTypeConvert(robj *subject, int enc) {
  *----------------------------------------------------------------------------*/
 
 void pushGenericCommand(redisClient *c, int where) {
+    int j, addlen = 0, pushed = 0;
     robj *lobj = lookupKeyWrite(c->db,c->argv[1]);
-    c->argv[2] = tryObjectEncoding(c->argv[2]);
-    if (lobj == NULL) {
-        if (handleClientsWaitingListPush(c,c->argv[1],c->argv[2])) {
-            addReply(c,shared.cone);
-            return;
-        }
-        lobj = createZiplistObject();
-        dbAdd(c->db,c->argv[1],lobj);
-    } else {
-        if (lobj->type != REDIS_LIST) {
-            addReply(c,shared.wrongtypeerr);
-            return;
+    int may_have_waiting_clients = (lobj == NULL);
+
+    if (lobj && lobj->type != REDIS_LIST) {
+        addReply(c,shared.wrongtypeerr);
+        return;
+    }
+
+    for (j = 2; j < c->argc; j++) {
+        c->argv[j] = tryObjectEncoding(c->argv[j]);
+        if (may_have_waiting_clients) {
+            if (handleClientsWaitingListPush(c,c->argv[1],c->argv[j])) {
+                addlen++;
+                continue;
+            } else {
+                may_have_waiting_clients = 0;
+            }
         }
-        if (handleClientsWaitingListPush(c,c->argv[1],c->argv[2])) {
-            signalModifiedKey(c->db,c->argv[1]);
-            addReply(c,shared.cone);
-            return;
+        if (!lobj) {
+            lobj = createZiplistObject();
+            dbAdd(c->db,c->argv[1],lobj);
         }
+        listTypePush(lobj,c->argv[j],where);
+        pushed++;
     }
-    listTypePush(lobj,c->argv[2],where);
-    addReplyLongLong(c,listTypeLength(lobj));
-    signalModifiedKey(c->db,c->argv[1]);
-    server.dirty++;
+    addReplyLongLong(c,addlen + (lobj ? listTypeLength(lobj) : 0));
+    if (pushed) signalModifiedKey(c->db,c->argv[1]);
+    server.dirty += pushed;
 }
 
 void lpushCommand(redisClient *c) {
@@ -773,7 +778,8 @@ void unblockClientWaitingData(redisClient *c) {
     zfree(c->bpop.keys);
     c->bpop.keys = NULL;
     c->bpop.target = NULL;
-    c->flags &= (~REDIS_BLOCKED);
+    c->flags &= ~REDIS_BLOCKED;
+    c->flags |= REDIS_UNBLOCKED;
     server.bpop_blocked_clients--;
     listAddNodeTail(server.unblocked_clients,c);
 }
@@ -816,7 +822,6 @@ int handleClientsWaitingListPush(redisClient *c, robj *key, robj *ele) {
 
         /* This should remove the first element of the "clients" list. */
         unblockClientWaitingData(receiver);
-        redisAssert(ln != listFirst(clients));
 
         if (dstkey == NULL) {
             /* BRPOP/BLPOP */
@@ -825,7 +830,7 @@ int handleClientsWaitingListPush(redisClient *c, robj *key, robj *ele) {
             addReplyBulk(receiver,ele);
             return 1;
         } else {
-            /* BRPOPLPUSH */
+            /* BRPOPLPUSH, note that receiver->db is always equal to c->db. */
             dstobj = lookupKeyWrite(receiver->db,dstkey);
             if (dstobj && checkType(receiver,dstobj,REDIS_LIST)) {
                 decrRefCount(dstkey);
@@ -940,7 +945,7 @@ void brpoplpushCommand(redisClient *c) {
 
             /* Blocking against an empty list in a multi state
              * returns immediately. */
-            addReply(c, shared.nullmultibulk);
+            addReply(c, shared.nullbulk);
         } else {
             /* The list is empty and the client blocks. */
             blockForKeys(c, c->argv + 1, 1, timeout, c->argv[2]);