backward support to skiplists for ZREVRANGE, still broken, committing since I've to merge the Solaris patches

This commit is contained in:
antirez 2009-10-26 16:14:49 +01:00
parent 9b1d5ebbe4
commit e3870fab57
2 changed files with 39 additions and 6 deletions

View File

@ -92,6 +92,7 @@ static struct redisCommand cmdTable[] = {
{"zadd",4,REDIS_CMD_BULK}, {"zadd",4,REDIS_CMD_BULK},
{"zrem",3,REDIS_CMD_BULK}, {"zrem",3,REDIS_CMD_BULK},
{"zrange",4,REDIS_CMD_INLINE}, {"zrange",4,REDIS_CMD_INLINE},
{"zrevrange",4,REDIS_CMD_INLINE},
{"zlen",2,REDIS_CMD_INLINE}, {"zlen",2,REDIS_CMD_INLINE},
{"incrby",3,REDIS_CMD_INLINE}, {"incrby",3,REDIS_CMD_INLINE},
{"decrby",3,REDIS_CMD_INLINE}, {"decrby",3,REDIS_CMD_INLINE},

44
redis.c
View File

@ -311,12 +311,13 @@ typedef struct _redisSortOperation {
typedef struct zskiplistNode { typedef struct zskiplistNode {
struct zskiplistNode **forward; struct zskiplistNode **forward;
struct zskiplistNode *backward;
double score; double score;
robj *obj; robj *obj;
} zskiplistNode; } zskiplistNode;
typedef struct zskiplist { typedef struct zskiplist {
struct zskiplistNode *header; struct zskiplistNode *header, *tail;
long length; long length;
int level; int level;
} zskiplist; } zskiplist;
@ -435,6 +436,7 @@ static void msetCommand(redisClient *c);
static void msetnxCommand(redisClient *c); static void msetnxCommand(redisClient *c);
static void zaddCommand(redisClient *c); static void zaddCommand(redisClient *c);
static void zrangeCommand(redisClient *c); static void zrangeCommand(redisClient *c);
static void zrevrangeCommand(redisClient *c);
static void zlenCommand(redisClient *c); static void zlenCommand(redisClient *c);
static void zremCommand(redisClient *c); static void zremCommand(redisClient *c);
@ -478,6 +480,7 @@ static struct redisCommand cmdTable[] = {
{"zadd",zaddCommand,4,REDIS_CMD_BULK|REDIS_CMD_DENYOOM}, {"zadd",zaddCommand,4,REDIS_CMD_BULK|REDIS_CMD_DENYOOM},
{"zrem",zremCommand,3,REDIS_CMD_BULK}, {"zrem",zremCommand,3,REDIS_CMD_BULK},
{"zrange",zrangeCommand,4,REDIS_CMD_INLINE}, {"zrange",zrangeCommand,4,REDIS_CMD_INLINE},
{"zrevrange",zrevrangeCommand,4,REDIS_CMD_INLINE},
{"zlen",zlenCommand,2,REDIS_CMD_INLINE}, {"zlen",zlenCommand,2,REDIS_CMD_INLINE},
{"incrby",incrbyCommand,3,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM}, {"incrby",incrbyCommand,3,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM},
{"decrby",decrbyCommand,3,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM}, {"decrby",decrbyCommand,3,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM},
@ -3721,6 +3724,8 @@ static zskiplist *zslCreate(void) {
zsl->header = zslCreateNode(ZSKIPLIST_MAXLEVEL,0,NULL); zsl->header = zslCreateNode(ZSKIPLIST_MAXLEVEL,0,NULL);
for (j = 0; j < ZSKIPLIST_MAXLEVEL; j++) for (j = 0; j < ZSKIPLIST_MAXLEVEL; j++)
zsl->header->forward[j] = NULL; zsl->header->forward[j] = NULL;
zsl->header->backward = NULL;
zsl->tail = NULL;
return zsl; return zsl;
} }
@ -3771,6 +3776,11 @@ static void zslInsert(zskiplist *zsl, double score, robj *obj) {
x->forward[i] = update[i]->forward[i]; x->forward[i] = update[i]->forward[i];
update[i]->forward[i] = x; update[i]->forward[i] = x;
} }
x->backward = (update[0] == zsl->header) ? NULL : update[i];
if (x->forward[0])
x->forward[0]->backward = x;
else
zsl->tail = x;
zsl->length++; zsl->length++;
} }
@ -3793,6 +3803,12 @@ static int zslDelete(zskiplist *zsl, double score, robj *obj) {
if (update[i]->forward[i] != x) break; if (update[i]->forward[i] != x) break;
update[i]->forward[i] = x->forward[i]; update[i]->forward[i] = x->forward[i];
} }
if (x->forward[0]) {
x->forward[0]->backward = (x->backward == zsl->header) ?
NULL : x->backward;
} else {
zsl->tail = x->backward;
}
zslFreeNode(x); zslFreeNode(x);
while(zsl->level > 1 && zsl->header->forward[zsl->level-1] == NULL) while(zsl->level > 1 && zsl->header->forward[zsl->level-1] == NULL)
zsl->level--; zsl->level--;
@ -3890,7 +3906,7 @@ static void zremCommand(redisClient *c) {
} }
} }
static void zrangeCommand(redisClient *c) { static void zrangeGenericCommand(redisClient *c, int reverse) {
robj *o; robj *o;
int start = atoi(c->argv[2]->ptr); int start = atoi(c->argv[2]->ptr);
int end = atoi(c->argv[3]->ptr); int end = atoi(c->argv[3]->ptr);
@ -3926,9 +3942,15 @@ static void zrangeCommand(redisClient *c) {
rangelen = (end-start)+1; rangelen = (end-start)+1;
/* Return the result in form of a multi-bulk reply */ /* Return the result in form of a multi-bulk reply */
ln = zsl->header->forward[0]; if (reverse) {
while (start--) ln = zsl->tail;
ln = ln->forward[0]; while (start--)
ln = ln->backward;
} else {
ln = zsl->header->forward[0];
while (start--)
ln = ln->forward[0];
}
addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",rangelen)); addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",rangelen));
for (j = 0; j < rangelen; j++) { for (j = 0; j < rangelen; j++) {
@ -3936,12 +3958,20 @@ static void zrangeCommand(redisClient *c) {
addReplyBulkLen(c,ele); addReplyBulkLen(c,ele);
addReply(c,ele); addReply(c,ele);
addReply(c,shared.crlf); addReply(c,shared.crlf);
ln = ln->forward[0]; ln = reverse ? ln->backward : ln->forward[0];
} }
} }
} }
} }
static void zrangeCommand(redisClient *c) {
zrangeGenericCommand(c,0);
}
static void zrevrangeCommand(redisClient *c) {
zrangeGenericCommand(c,1);
}
static void zlenCommand(redisClient *c) { static void zlenCommand(redisClient *c) {
robj *o; robj *o;
zset *zs; zset *zs;
@ -5016,7 +5046,9 @@ static struct redisFunctionSym symsTable[] = {
{"zslDelete",(unsigned long)zslDelete}, {"zslDelete",(unsigned long)zslDelete},
{"createZsetObject",(unsigned long)createZsetObject}, {"createZsetObject",(unsigned long)createZsetObject},
{"zaddCommand",(unsigned long)zaddCommand}, {"zaddCommand",(unsigned long)zaddCommand},
{"zrangeGenericCommand",(unsigned long)zrangeGenericCommand},
{"zrangeCommand",(unsigned long)zrangeCommand}, {"zrangeCommand",(unsigned long)zrangeCommand},
{"zrevrangeCommand",(unsigned long)zrevrangeCommand},
{"zremCommand",(unsigned long)zremCommand}, {"zremCommand",(unsigned long)zremCommand},
{NULL,0} {NULL,0}
}; };