From 3e9c20f63b9649bf2a8ddce8f4743c7fb5d435b4 Mon Sep 17 00:00:00 2001 From: Pierre Chapuis Date: Sun, 5 Jun 2016 16:06:22 +0200 Subject: [PATCH 1/3] untangle LINSERT and {L,R}PUSHX implementations --- src/t_list.c | 85 +++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/src/t_list.c b/src/t_list.c index 7d5be11a..3e2f0020 100644 --- a/src/t_list.c +++ b/src/t_list.c @@ -232,68 +232,73 @@ void rpushCommand(client *c) { pushGenericCommand(c,LIST_TAIL); } -void pushxGenericCommand(client *c, robj *refval, robj *val, int where) { +void pushxGenericCommand(client *c, int where) { robj *subject; - listTypeIterator *iter; - listTypeEntry entry; - int inserted = 0; if ((subject = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL || checkType(c,subject,OBJ_LIST)) return; - if (refval != NULL) { - /* Seek refval from head to tail */ - iter = listTypeInitIterator(subject,0,LIST_TAIL); - while (listTypeNext(iter,&entry)) { - if (listTypeEqual(&entry,refval)) { - listTypeInsert(&entry,val,where); - inserted = 1; - break; - } - } - listTypeReleaseIterator(iter); - - if (inserted) { - signalModifiedKey(c->db,c->argv[1]); - notifyKeyspaceEvent(NOTIFY_LIST,"linsert", - c->argv[1],c->db->id); - server.dirty++; - } else { - /* Notify client of a failed insert */ - addReply(c,shared.cnegone); - return; - } - } else { - char *event = (where == LIST_HEAD) ? "lpush" : "rpush"; - - listTypePush(subject,val,where); - signalModifiedKey(c->db,c->argv[1]); - notifyKeyspaceEvent(NOTIFY_LIST,event,c->argv[1],c->db->id); - server.dirty++; - } + char *event = (where == LIST_HEAD) ? "lpush" : "rpush"; + c->argv[2] = tryObjectEncoding(c->argv[2]); + listTypePush(subject,c->argv[2],where); + signalModifiedKey(c->db,c->argv[1]); + notifyKeyspaceEvent(NOTIFY_LIST,event,c->argv[1],c->db->id); + server.dirty++; addReplyLongLong(c,listTypeLength(subject)); } void lpushxCommand(client *c) { - c->argv[2] = tryObjectEncoding(c->argv[2]); - pushxGenericCommand(c,NULL,c->argv[2],LIST_HEAD); + pushxGenericCommand(c,LIST_HEAD); } void rpushxCommand(client *c) { - c->argv[2] = tryObjectEncoding(c->argv[2]); - pushxGenericCommand(c,NULL,c->argv[2],LIST_TAIL); + pushxGenericCommand(c,LIST_TAIL); } void linsertCommand(client *c) { + int where; + robj *subject; + listTypeIterator *iter; + listTypeEntry entry; + int inserted = 0; + c->argv[4] = tryObjectEncoding(c->argv[4]); if (strcasecmp(c->argv[2]->ptr,"after") == 0) { - pushxGenericCommand(c,c->argv[3],c->argv[4],LIST_TAIL); + where = LIST_TAIL; } else if (strcasecmp(c->argv[2]->ptr,"before") == 0) { - pushxGenericCommand(c,c->argv[3],c->argv[4],LIST_HEAD); + where = LIST_HEAD; } else { addReply(c,shared.syntaxerr); + return; } + + if ((subject = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL || + checkType(c,subject,OBJ_LIST)) return; + + /* Seek pivot from head to tail */ + iter = listTypeInitIterator(subject,0,LIST_TAIL); + while (listTypeNext(iter,&entry)) { + if (listTypeEqual(&entry,c->argv[3])) { + listTypeInsert(&entry,c->argv[4],where); + inserted = 1; + break; + } + } + listTypeReleaseIterator(iter); + + if (inserted) { + signalModifiedKey(c->db,c->argv[1]); + notifyKeyspaceEvent(NOTIFY_LIST,"linsert", + c->argv[1],c->db->id); + server.dirty++; + } else { + /* Notify client of a failed insert */ + addReply(c,shared.cnegone); + return; + } + + addReplyLongLong(c,listTypeLength(subject)); } void llenCommand(client *c) { From b670a1628263cd2655e70ee5c9c947f49fc94647 Mon Sep 17 00:00:00 2001 From: Pierre Chapuis Date: Sun, 5 Jun 2016 16:09:55 +0200 Subject: [PATCH 2/3] remove unused variable --- src/t_list.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/t_list.c b/src/t_list.c index 3e2f0020..3777395e 100644 --- a/src/t_list.c +++ b/src/t_list.c @@ -195,7 +195,7 @@ void listTypeConvert(robj *subject, int enc) { *----------------------------------------------------------------------------*/ void pushGenericCommand(client *c, int where) { - int j, waiting = 0, pushed = 0; + int j, pushed = 0; robj *lobj = lookupKeyWrite(c->db,c->argv[1]); if (lobj && lobj->type != OBJ_LIST) { @@ -214,7 +214,7 @@ void pushGenericCommand(client *c, int where) { listTypePush(lobj,c->argv[j],where); pushed++; } - addReplyLongLong(c, waiting + (lobj ? listTypeLength(lobj) : 0)); + addReplyLongLong(c, (lobj ? listTypeLength(lobj) : 0)); if (pushed) { char *event = (where == LIST_HEAD) ? "lpush" : "rpush"; From d88c3c77beb975c84c23b7586ed6984b4c74b82d Mon Sep 17 00:00:00 2001 From: Pierre Chapuis Date: Sun, 5 Jun 2016 16:22:52 +0200 Subject: [PATCH 3/3] make RPUSHX and LPUSHX variadic --- src/server.c | 4 ++-- src/t_list.c | 19 +++++++++++++------ tests/unit/type/list.tcl | 4 +++- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/server.c b/src/server.c index 917fcc77..9ad9f2bc 100644 --- a/src/server.c +++ b/src/server.c @@ -145,8 +145,8 @@ struct redisCommand redisCommandTable[] = { {"mget",mgetCommand,-2,"r",0,NULL,1,-1,1,0,0}, {"rpush",rpushCommand,-3,"wmF",0,NULL,1,1,1,0,0}, {"lpush",lpushCommand,-3,"wmF",0,NULL,1,1,1,0,0}, - {"rpushx",rpushxCommand,3,"wmF",0,NULL,1,1,1,0,0}, - {"lpushx",lpushxCommand,3,"wmF",0,NULL,1,1,1,0,0}, + {"rpushx",rpushxCommand,-3,"wmF",0,NULL,1,1,1,0,0}, + {"lpushx",lpushxCommand,-3,"wmF",0,NULL,1,1,1,0,0}, {"linsert",linsertCommand,5,"wm",0,NULL,1,1,1,0,0}, {"rpop",rpopCommand,2,"wF",0,NULL,1,1,1,0,0}, {"lpop",lpopCommand,2,"wF",0,NULL,1,1,1,0,0}, diff --git a/src/t_list.c b/src/t_list.c index 3777395e..109aba9d 100644 --- a/src/t_list.c +++ b/src/t_list.c @@ -233,19 +233,26 @@ void rpushCommand(client *c) { } void pushxGenericCommand(client *c, int where) { + int j, pushed = 0; robj *subject; if ((subject = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL || checkType(c,subject,OBJ_LIST)) return; - char *event = (where == LIST_HEAD) ? "lpush" : "rpush"; - c->argv[2] = tryObjectEncoding(c->argv[2]); - listTypePush(subject,c->argv[2],where); - signalModifiedKey(c->db,c->argv[1]); - notifyKeyspaceEvent(NOTIFY_LIST,event,c->argv[1],c->db->id); - server.dirty++; + for (j = 2; j < c->argc; j++) { + c->argv[j] = tryObjectEncoding(c->argv[j]); + listTypePush(subject,c->argv[j],where); + pushed++; + } addReplyLongLong(c,listTypeLength(subject)); + + if (pushed) { + char *event = (where == LIST_HEAD) ? "lpush" : "rpush"; + signalModifiedKey(c->db,c->argv[1]); + notifyKeyspaceEvent(NOTIFY_LIST,event,c->argv[1],c->db->id); + } + server.dirty += pushed; } void lpushxCommand(client *c) { diff --git a/tests/unit/type/list.tcl b/tests/unit/type/list.tcl index e4d568cf..1557082a 100644 --- a/tests/unit/type/list.tcl +++ b/tests/unit/type/list.tcl @@ -507,7 +507,9 @@ start_server { create_list xlist "$large c" assert_equal 3 [r rpushx xlist d] assert_equal 4 [r lpushx xlist a] - assert_equal "a $large c d" [r lrange xlist 0 -1] + assert_equal 6 [r rpushx xlist 42 x] + assert_equal 9 [r lpushx xlist y3 y2 y1] + assert_equal "y1 y2 y3 a $large c d 42 x" [r lrange xlist 0 -1] } test "LINSERT - $type" {