]> git.saurik.com Git - redis.git/commitdiff
some work on ZADD against existing element (score update), still broken...
authorantirez <antirez@gmail.com>
Fri, 23 Oct 2009 23:27:18 +0000 (01:27 +0200)
committerantirez <antirez@gmail.com>
Fri, 23 Oct 2009 23:27:18 +0000 (01:27 +0200)
client-libraries/tcl/redis.tcl
redis-cli.c
redis.c

index 1a2bda5e31cfadb209c55f86b9a0888060c61dbe..86b7eb485588a22600d974de816f97a184d8e89e 100644 (file)
@@ -20,7 +20,7 @@ array set ::redis::multibulkarg {}
 
 # Flag commands requiring last argument as a bulk write operation
 foreach redis_bulk_cmd {
-    set setnx rpush lpush lset lrem sadd srem sismember echo getset smove
+    set setnx rpush lpush lset lrem sadd srem sismember echo getset smove zadd
 } {
     set ::redis::bulkarg($redis_bulk_cmd) {}
 }
index b53eae65c883a6715fe6e3fbd6c48f2859e0d21e..dc16617f61f1c44c964b573c88ed1843e5a8147f 100644 (file)
@@ -91,6 +91,7 @@ static struct redisCommand cmdTable[] = {
     {"smembers",2,REDIS_CMD_INLINE},
     {"zadd",4,REDIS_CMD_BULK},
     {"zrange",4,REDIS_CMD_INLINE},
+    {"zlen",2,REDIS_CMD_INLINE},
     {"incrby",3,REDIS_CMD_INLINE},
     {"decrby",3,REDIS_CMD_INLINE},
     {"getset",3,REDIS_CMD_BULK},
diff --git a/redis.c b/redis.c
index 65e62172b3e4b149872117aa2b545bdccaa43661..2e78d9c77e48ae86b5d1b24c8fff4e0dbd4ef732 100644 (file)
--- a/redis.c
+++ b/redis.c
@@ -435,6 +435,7 @@ static void msetCommand(redisClient *c);
 static void msetnxCommand(redisClient *c);
 static void zaddCommand(redisClient *c);
 static void zrangeCommand(redisClient *c);
+static void zlenCommand(redisClient *c);
 
 /*================================= Globals ================================= */
 
@@ -475,6 +476,7 @@ static struct redisCommand cmdTable[] = {
     {"smembers",sinterCommand,2,REDIS_CMD_INLINE},
     {"zadd",zaddCommand,4,REDIS_CMD_BULK|REDIS_CMD_DENYOOM},
     {"zrange",zrangeCommand,4,REDIS_CMD_INLINE},
+    {"zlen",zlenCommand,2,REDIS_CMD_INLINE},
     {"incrby",incrbyCommand,3,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM},
     {"decrby",decrbyCommand,3,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM},
     {"getset",getsetCommand,3,REDIS_CMD_BULK|REDIS_CMD_DENYOOM},
@@ -2052,6 +2054,7 @@ static robj *getDecodedObject(const robj *o) {
 static int compareStringObjects(robj *a, robj *b) {
     assert(a->type == REDIS_STRING && b->type == REDIS_STRING);
 
+    if (a == b) return 0;
     if (a->encoding == REDIS_ENCODING_INT && b->encoding == REDIS_ENCODING_INT){
         return (long)a->ptr - (long)b->ptr;
     } else {
@@ -3751,7 +3754,6 @@ static void zslInsert(zskiplist *zsl, double score, robj *obj) {
             x = x->forward[i];
         update[i] = x;
     }
-    x = x->forward[1];
     /* we assume the key is not already inside, since we allow duplicated
      * scores, and the re-insertion of score and redis object should never
      * happpen since the caller of zslInsert() should test in the hash table
@@ -3771,7 +3773,34 @@ static void zslInsert(zskiplist *zsl, double score, robj *obj) {
 }
 
 static int zslDelete(zskiplist *zsl, double score, robj *obj) {
-    return 1;
+    zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
+    int i;
+
+    x = zsl->header;
+    for (i = zsl->level-1; i >= 0; i--) {
+        while (x->forward[i] && x->forward[i]->score < score)
+            x = x->forward[i];
+        update[i] = x;
+    }
+    /* We may have multiple elements with the same score, what we need
+     * is to find the element with both the right score and object. */
+    x = x->forward[0];
+    while(x->score == score) {
+        if (compareStringObjects(x->obj,obj) == 0) {
+            for (i = 0; i < zsl->level; i++) {
+                if (update[i]->forward[i] != x) break;
+                update[i]->forward[i] = x->forward[i];
+            }
+            zslFreeNode(x);
+            while(zsl->level > 1 && zsl->header->forward[zsl->level-1] == NULL)
+                zsl->level--;
+            return 1;
+        } else {
+            x = x->forward[0];
+            if (!x) return 0; /* end of the list reached, not found */
+        }
+    }
+    return 0; /* not found */
 }
 
 /* The actual Z-commands implementations */
@@ -3813,7 +3842,7 @@ static void zaddCommand(redisClient *c) {
         if (*score != *oldscore) {
             int deleted;
 
-            deleted = zslDelete(zs->zsl,*score,c->argv[3]);
+            deleted = zslDelete(zs->zsl,*oldscore,c->argv[3]);
             assert(deleted != 0);
             zslInsert(zs->zsl,*score,c->argv[3]);
             incrRefCount(c->argv[3]);
@@ -3875,6 +3904,24 @@ static void zrangeCommand(redisClient *c) {
     }
 }
 
+static void zlenCommand(redisClient *c) {
+    robj *o;
+    zset *zs;
+    
+    o = lookupKeyRead(c->db,c->argv[1]);
+    if (o == NULL) {
+        addReply(c,shared.czero);
+        return;
+    } else {
+        if (o->type != REDIS_ZSET) {
+            addReply(c,shared.wrongtypeerr);
+        } else {
+            zs = o->ptr;
+            addReplySds(c,sdscatprintf(sdsempty(),":%d\r\n",zs->zsl->length));
+        }
+    }
+}
+
 /* ========================= Non type-specific commands  ==================== */
 
 static void flushdbCommand(redisClient *c) {