summaryrefslogtreecommitdiff
path: root/src/t_zset.c
diff options
context:
space:
mode:
authorPieter Noordhuis <pcnoordhuis@gmail.com>2011-03-08 17:11:15 +0100
committerPieter Noordhuis <pcnoordhuis@gmail.com>2011-03-08 17:11:15 +0100
commit0b10e1044496699585b401196dd86e19a9f87cc4 (patch)
treee1dc4b0de2514ec736a5e763c5acff51a9db8762 /src/t_zset.c
parent3ca7532a2d20ea88109cd4f0c3c527c37e3fe52f (diff)
downloadredis-0b10e1044496699585b401196dd86e19a9f87cc4.tar.gz
Support dual encoding in ZREM
Diffstat (limited to 'src/t_zset.c')
-rw-r--r--src/t_zset.c66
1 files changed, 43 insertions, 23 deletions
diff --git a/src/t_zset.c b/src/t_zset.c
index 9fd524c3d..790fb573c 100644
--- a/src/t_zset.c
+++ b/src/t_zset.c
@@ -449,6 +449,11 @@ int zzlCompareElements(unsigned char *eptr, unsigned char *cstr, unsigned int cl
return cmp;
}
+unsigned int *zzlLength(robj *zobj) {
+ unsigned char *zl = zobj->ptr;
+ return ziplistLen(zl)/2;
+}
+
unsigned char *zzlFind(robj *zobj, robj *ele, double *score) {
unsigned char *zl = zobj->ptr;
unsigned char *eptr = ziplistIndex(zl,0), *sptr;
@@ -460,7 +465,7 @@ unsigned char *zzlFind(robj *zobj, robj *ele, double *score) {
if (ziplistCompare(eptr,ele->ptr,sdslen(ele->ptr))) {
/* Matching element, pull out score. */
- *score = zzlGetScore(sptr);
+ if (score != NULL) *score = zzlGetScore(sptr);
decrRefCount(ele);
return eptr;
}
@@ -688,32 +693,47 @@ void zincrbyCommand(redisClient *c) {
}
void zremCommand(redisClient *c) {
- robj *zsetobj;
- zset *zs;
- dictEntry *de;
- double curscore;
- int deleted;
+ robj *key = c->argv[1];
+ robj *ele = c->argv[2];
+ robj *zobj;
- if ((zsetobj = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL ||
- checkType(c,zsetobj,REDIS_ZSET)) return;
+ if ((zobj = lookupKeyWriteOrReply(c,key,shared.czero)) == NULL ||
+ checkType(c,zobj,REDIS_ZSET)) return;
- zs = zsetobj->ptr;
- c->argv[2] = tryObjectEncoding(c->argv[2]);
- de = dictFind(zs->dict,c->argv[2]);
- if (de == NULL) {
- addReply(c,shared.czero);
- return;
+ if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
+ unsigned char *eptr;
+
+ if ((eptr = zzlFind(zobj,ele,NULL)) != NULL) {
+ redisAssert(zzlDelete(zobj,eptr) == REDIS_OK);
+ if (zzlLength(zobj) == 0) dbDelete(c->db,key);
+ } else {
+ addReply(c,shared.czero);
+ return;
+ }
+ } else if (zobj->encoding == REDIS_ENCODING_RAW) {
+ zset *zs = zobj->ptr;
+ dictEntry *de;
+ double score;
+
+ de = dictFind(zs->dict,ele);
+ if (de != NULL) {
+ /* Delete from the skiplist */
+ score = *(double*)dictGetEntryVal(de);
+ redisAssert(zslDelete(zs->zsl,score,ele));
+
+ /* Delete from the hash table */
+ dictDelete(zs->dict,ele);
+ if (htNeedsResize(zs->dict)) dictResize(zs->dict);
+ if (dictSize(zs->dict) == 0) dbDelete(c->db,key);
+ } else {
+ addReply(c,shared.czero);
+ return;
+ }
+ } else {
+ redisPanic("Unknown sorted set encoding");
}
- /* Delete from the skiplist */
- curscore = *(double*)dictGetEntryVal(de);
- deleted = zslDelete(zs->zsl,curscore,c->argv[2]);
- redisAssert(deleted != 0);
- /* Delete from the hash table */
- dictDelete(zs->dict,c->argv[2]);
- if (htNeedsResize(zs->dict)) dictResize(zs->dict);
- if (dictSize(zs->dict) == 0) dbDelete(c->db,c->argv[1]);
- signalModifiedKey(c->db,c->argv[1]);
+ signalModifiedKey(c->db,key);
server.dirty++;
addReply(c,shared.cone);
}