From c1db214eeb2b7385c32889e17748429fcbe5cbae Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 29 Feb 2012 14:41:57 +0100 Subject: [PATCH] Better implementation for BRPOP/BLPOP in the non blocking case. --- src/redis.c | 2 ++ src/redis.h | 2 +- src/t_list.c | 44 +++++++++++++++----------------------------- 3 files changed, 18 insertions(+), 30 deletions(-) diff --git a/src/redis.c b/src/redis.c index 78067d31..64df9073 100644 --- a/src/redis.c +++ b/src/redis.c @@ -852,6 +852,8 @@ void createSharedObjects(void) { shared.psubscribebulk = createStringObject("$10\r\npsubscribe\r\n",17); shared.punsubscribebulk = createStringObject("$12\r\npunsubscribe\r\n",19); shared.del = createStringObject("DEL",3); + shared.rpop = createStringObject("RPOP",4); + shared.lpop = createStringObject("LPOP",4); for (j = 0; j < REDIS_SHARED_INTEGERS; j++) { shared.integers[j] = createObject(REDIS_STRING,(void*)(long)j); shared.integers[j]->encoding = REDIS_ENCODING_INT; diff --git a/src/redis.h b/src/redis.h index c2617870..cccdcc81 100644 --- a/src/redis.h +++ b/src/redis.h @@ -365,7 +365,7 @@ struct sharedObjectsStruct { *select0, *select1, *select2, *select3, *select4, *select5, *select6, *select7, *select8, *select9, *messagebulk, *pmessagebulk, *subscribebulk, *unsubscribebulk, - *psubscribebulk, *punsubscribebulk, *del, + *psubscribebulk, *punsubscribebulk, *del, *rpop, *lpop, *integers[REDIS_SHARED_INTEGERS], *mbulkhdr[REDIS_SHARED_BULKHDR_LEN], /* "*\r\n" */ *bulkhdr[REDIS_SHARED_BULKHDR_LEN]; /* "$\r\n" */ diff --git a/src/t_list.c b/src/t_list.c index d6e28b7e..2be8074a 100644 --- a/src/t_list.c +++ b/src/t_list.c @@ -933,36 +933,22 @@ void blockingPopGenericCommand(redisClient *c, int where) { return; } else { if (listTypeLength(o) != 0) { - /* If the list contains elements fall back to the usual - * non-blocking POP operation */ - struct redisCommand *orig_cmd; - robj *argv[2], **orig_argv; - int orig_argc; - - /* We need to alter the command arguments before to call - * popGenericCommand() as the command takes a single key. */ - orig_argv = c->argv; - orig_argc = c->argc; - orig_cmd = c->cmd; - argv[1] = c->argv[j]; - c->argv = argv; - c->argc = 2; - - /* Also the return value is different, we need to output - * the multi bulk reply header and the key name. The - * "real" command will add the last element (the value) - * for us. If this souds like an hack to you it's just - * because it is... */ - addReplyMultiBulkLen(c,2); - addReplyBulk(c,argv[1]); - - popGenericCommand(c,where); - - /* Fix the client structure with the original stuff */ - c->argv = orig_argv; - c->argc = orig_argc; - c->cmd = orig_cmd; + /* Non empty list, this is like a non normal [LR]POP. */ + robj *value = listTypePop(o,where); + redisAssert(value != NULL); + addReplyMultiBulkLen(c,2); + addReplyBulk(c,c->argv[j]); + addReplyBulk(c,value); + decrRefCount(value); + if (listTypeLength(o) == 0) dbDelete(c->db,c->argv[j]); + signalModifiedKey(c->db,c->argv[j]); + server.dirty++; + + /* Replicate it as an [LR]POP instead of B[LR]POP. */ + rewriteClientCommandVector(c,2, + (where == REDIS_HEAD) ? shared.lpop : shared.rpop, + c->argv[j]); return; } } -- 2.47.2