Support dual encoding for ZREMRANGEBYRANK

This commit is contained in:
Pieter Noordhuis 2011-03-09 10:30:55 +01:00
parent 5d1b4fb698
commit 63b7b7fb34

View File

@ -666,6 +666,14 @@ unsigned long zzlDeleteRangeByScore(robj *zobj, zrangespec range) {
return deleted; return deleted;
} }
/* Delete all the elements with rank between start and end from the skiplist.
* Start and end are inclusive. Note that start and end need to be 1-based */
unsigned long zzlDeleteRangeByRank(robj *zobj, unsigned int start, unsigned int end) {
unsigned int num = (end-start)+1;
zobj->ptr = ziplistDeleteRange(zobj->ptr,2*(start-1),2*num);
return num;
}
/*----------------------------------------------------------------------------- /*-----------------------------------------------------------------------------
* Common sorted set API * Common sorted set API
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
@ -892,22 +900,21 @@ void zremrangebyscoreCommand(redisClient *c) {
} }
void zremrangebyrankCommand(redisClient *c) { void zremrangebyrankCommand(redisClient *c) {
robj *key = c->argv[1];
robj *zobj;
long start; long start;
long end; long end;
int llen; int llen;
long deleted; unsigned long deleted;
robj *zsetobj;
zset *zs;
if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != REDIS_OK) || if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != REDIS_OK) ||
(getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != REDIS_OK)) return; (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != REDIS_OK)) return;
if ((zsetobj = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL || if ((zobj = lookupKeyWriteOrReply(c,key,shared.czero)) == NULL ||
checkType(c,zsetobj,REDIS_ZSET)) return; checkType(c,zobj,REDIS_ZSET)) return;
zs = zsetobj->ptr;
llen = zs->zsl->length;
/* convert negative indexes */ /* Sanitize indexes. */
llen = zsLength(zobj);
if (start < 0) start = llen+start; if (start < 0) start = llen+start;
if (end < 0) end = llen+end; if (end < 0) end = llen+end;
if (start < 0) start = 0; if (start < 0) start = 0;
@ -920,14 +927,23 @@ void zremrangebyrankCommand(redisClient *c) {
} }
if (end >= llen) end = llen-1; if (end >= llen) end = llen-1;
/* increment start and end because zsl*Rank functions if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
* use 1-based rank */ /* Correct for 1-based rank. */
deleted = zslDeleteRangeByRank(zs->zsl,start+1,end+1,zs->dict); deleted = zzlDeleteRangeByRank(zobj,start+1,end+1);
if (htNeedsResize(zs->dict)) dictResize(zs->dict); } else if (zobj->encoding == REDIS_ENCODING_RAW) {
if (dictSize(zs->dict) == 0) dbDelete(c->db,c->argv[1]); zset *zs = zobj->ptr;
if (deleted) signalModifiedKey(c->db,c->argv[1]);
/* Correct for 1-based rank. */
deleted = zslDeleteRangeByRank(zs->zsl,start+1,end+1,zs->dict);
if (htNeedsResize(zs->dict)) dictResize(zs->dict);
if (dictSize(zs->dict) == 0) dbDelete(c->db,key);
} else {
redisPanic("Unknown sorted set encoding");
}
if (deleted) signalModifiedKey(c->db,key);
server.dirty += deleted; server.dirty += deleted;
addReplyLongLong(c, deleted); addReplyLongLong(c,deleted);
} }
typedef struct { typedef struct {