*----------------------------------------------------------------------------*/
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])) {
- touchWatchedKey(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));
- touchWatchedKey(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) {
if (subject->encoding == REDIS_ENCODING_ZIPLIST &&
ziplistLen(subject->ptr) > server.list_max_ziplist_entries)
listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);
- touchWatchedKey(c->db,c->argv[1]);
+ signalModifiedKey(c->db,c->argv[1]);
server.dirty++;
} else {
/* Notify client of a failed insert */
}
} else {
listTypePush(subject,val,where);
- touchWatchedKey(c->db,c->argv[1]);
+ signalModifiedKey(c->db,c->argv[1]);
server.dirty++;
}
o->ptr = ziplistInsert(o->ptr,p,value->ptr,sdslen(value->ptr));
decrRefCount(value);
addReply(c,shared.ok);
- touchWatchedKey(c->db,c->argv[1]);
+ signalModifiedKey(c->db,c->argv[1]);
server.dirty++;
}
} else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {
listNodeValue(ln) = value;
incrRefCount(value);
addReply(c,shared.ok);
- touchWatchedKey(c->db,c->argv[1]);
+ signalModifiedKey(c->db,c->argv[1]);
server.dirty++;
}
} else {
addReplyBulk(c,value);
decrRefCount(value);
if (listTypeLength(o) == 0) dbDelete(c->db,c->argv[1]);
- touchWatchedKey(c->db,c->argv[1]);
+ signalModifiedKey(c->db,c->argv[1]);
server.dirty++;
}
}
redisPanic("Unknown list encoding");
}
if (listTypeLength(o) == 0) dbDelete(c->db,c->argv[1]);
- touchWatchedKey(c->db,c->argv[1]);
+ signalModifiedKey(c->db,c->argv[1]);
server.dirty++;
addReply(c,shared.ok);
}
if (listTypeLength(subject) == 0) dbDelete(c->db,c->argv[1]);
addReplyLongLong(c,removed);
- if (removed) touchWatchedKey(c->db,c->argv[1]);
+ if (removed) signalModifiedKey(c->db,c->argv[1]);
}
/* This is the semantic of this command:
dstobj = createZiplistObject();
dbAdd(c->db,dstkey,dstobj);
} else {
- touchWatchedKey(c->db,dstkey);
+ signalModifiedKey(c->db,dstkey);
server.dirty++;
}
listTypePush(dstobj,value,REDIS_HEAD);
/* Delete the source list when it is empty */
if (listTypeLength(sobj) == 0) dbDelete(c->db,c->argv[1]);
- touchWatchedKey(c->db,c->argv[1]);
+ signalModifiedKey(c->db,c->argv[1]);
server.dirty++;
}
}
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);
}
/* This should remove the first element of the "clients" list. */
unblockClientWaitingData(receiver);
- redisAssert(ln != listFirst(clients));
if (dstkey == NULL) {
/* BRPOP/BLPOP */
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);
/* 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]);