mirror of
https://github.com/fluencelabs/redis
synced 2025-04-01 23:31:03 +00:00
ZINCRSCOREBY implemented
This commit is contained in:
parent
37f68e6102
commit
e2665397a7
@ -93,6 +93,7 @@ static struct redisCommand cmdTable[] = {
|
|||||||
{"sdiffstore",-3,REDIS_CMD_INLINE},
|
{"sdiffstore",-3,REDIS_CMD_INLINE},
|
||||||
{"smembers",2,REDIS_CMD_INLINE},
|
{"smembers",2,REDIS_CMD_INLINE},
|
||||||
{"zadd",4,REDIS_CMD_BULK},
|
{"zadd",4,REDIS_CMD_BULK},
|
||||||
|
{"zincrscoreby",4,REDIS_CMD_BULK},
|
||||||
{"zrem",3,REDIS_CMD_BULK},
|
{"zrem",3,REDIS_CMD_BULK},
|
||||||
{"zremrangebyscore",4,REDIS_CMD_INLINE},
|
{"zremrangebyscore",4,REDIS_CMD_INLINE},
|
||||||
{"zrange",4,REDIS_CMD_INLINE},
|
{"zrange",4,REDIS_CMD_INLINE},
|
||||||
|
91
redis.c
91
redis.c
@ -466,6 +466,7 @@ static void debugCommand(redisClient *c);
|
|||||||
static void msetCommand(redisClient *c);
|
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 zincrscorebyCommand(redisClient *c);
|
||||||
static void zrangeCommand(redisClient *c);
|
static void zrangeCommand(redisClient *c);
|
||||||
static void zrangebyscoreCommand(redisClient *c);
|
static void zrangebyscoreCommand(redisClient *c);
|
||||||
static void zrevrangeCommand(redisClient *c);
|
static void zrevrangeCommand(redisClient *c);
|
||||||
@ -513,6 +514,7 @@ static struct redisCommand cmdTable[] = {
|
|||||||
{"sdiffstore",sdiffstoreCommand,-3,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM},
|
{"sdiffstore",sdiffstoreCommand,-3,REDIS_CMD_INLINE|REDIS_CMD_DENYOOM},
|
||||||
{"smembers",sinterCommand,2,REDIS_CMD_INLINE},
|
{"smembers",sinterCommand,2,REDIS_CMD_INLINE},
|
||||||
{"zadd",zaddCommand,4,REDIS_CMD_BULK|REDIS_CMD_DENYOOM},
|
{"zadd",zaddCommand,4,REDIS_CMD_BULK|REDIS_CMD_DENYOOM},
|
||||||
|
{"zincrscoreby",zincrscorebyCommand,4,REDIS_CMD_BULK|REDIS_CMD_DENYOOM},
|
||||||
{"zrem",zremCommand,3,REDIS_CMD_BULK},
|
{"zrem",zremCommand,3,REDIS_CMD_BULK},
|
||||||
{"zremrangebyscore",zremrangebyscoreCommand,4,REDIS_CMD_INLINE},
|
{"zremrangebyscore",zremrangebyscoreCommand,4,REDIS_CMD_INLINE},
|
||||||
{"zrange",zrangeCommand,4,REDIS_CMD_INLINE},
|
{"zrange",zrangeCommand,4,REDIS_CMD_INLINE},
|
||||||
@ -1383,7 +1385,6 @@ static void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask)
|
|||||||
REDIS_NOTUSED(el);
|
REDIS_NOTUSED(el);
|
||||||
REDIS_NOTUSED(mask);
|
REDIS_NOTUSED(mask);
|
||||||
|
|
||||||
|
|
||||||
/* Use writev() if we have enough buffers to send */
|
/* Use writev() if we have enough buffers to send */
|
||||||
if (!server.glueoutputbuf &&
|
if (!server.glueoutputbuf &&
|
||||||
listLength(c->reply) > REDIS_WRITEV_THRESHOLD &&
|
listLength(c->reply) > REDIS_WRITEV_THRESHOLD &&
|
||||||
@ -1939,6 +1940,14 @@ static void addReplySds(redisClient *c, sds s) {
|
|||||||
decrRefCount(o);
|
decrRefCount(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void addReplyDouble(redisClient *c, double d) {
|
||||||
|
char buf[128];
|
||||||
|
|
||||||
|
snprintf(buf,sizeof(buf),"%.17g",d);
|
||||||
|
addReplySds(c,sdscatprintf(sdsempty(),"$%d\r\n%s\r\n",
|
||||||
|
strlen(buf),buf));
|
||||||
|
}
|
||||||
|
|
||||||
static void addReplyBulkLen(redisClient *c, robj *obj) {
|
static void addReplyBulkLen(redisClient *c, robj *obj) {
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
@ -4220,56 +4229,101 @@ static zskiplistNode *zslFirstWithScore(zskiplist *zsl, double score) {
|
|||||||
|
|
||||||
/* The actual Z-commands implementations */
|
/* The actual Z-commands implementations */
|
||||||
|
|
||||||
static void zaddCommand(redisClient *c) {
|
/* This generic command implements both ZADD and ZINCRSCOREBY.
|
||||||
|
* scoreval is the score if the operation is a ZADD (doincrement == 0) or
|
||||||
|
* the increment if the operation is a ZINCRSCOREBY (doincrement == 1). */
|
||||||
|
static void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, int doincrement) {
|
||||||
robj *zsetobj;
|
robj *zsetobj;
|
||||||
zset *zs;
|
zset *zs;
|
||||||
double *score;
|
double *score;
|
||||||
|
|
||||||
zsetobj = lookupKeyWrite(c->db,c->argv[1]);
|
zsetobj = lookupKeyWrite(c->db,key);
|
||||||
if (zsetobj == NULL) {
|
if (zsetobj == NULL) {
|
||||||
zsetobj = createZsetObject();
|
zsetobj = createZsetObject();
|
||||||
dictAdd(c->db->dict,c->argv[1],zsetobj);
|
dictAdd(c->db->dict,key,zsetobj);
|
||||||
incrRefCount(c->argv[1]);
|
incrRefCount(key);
|
||||||
} else {
|
} else {
|
||||||
if (zsetobj->type != REDIS_ZSET) {
|
if (zsetobj->type != REDIS_ZSET) {
|
||||||
addReply(c,shared.wrongtypeerr);
|
addReply(c,shared.wrongtypeerr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
score = zmalloc(sizeof(double));
|
|
||||||
*score = strtod(c->argv[2]->ptr,NULL);
|
|
||||||
zs = zsetobj->ptr;
|
zs = zsetobj->ptr;
|
||||||
if (dictAdd(zs->dict,c->argv[3],score) == DICT_OK) {
|
|
||||||
|
/* Ok now since we implement both ZADD and ZINCRSCOREBY here the code
|
||||||
|
* needs to handle the two different conditions. It's all about setting
|
||||||
|
* '*score', that is, the new score to set, to the right value. */
|
||||||
|
score = zmalloc(sizeof(double));
|
||||||
|
if (doincrement) {
|
||||||
|
dictEntry *de;
|
||||||
|
|
||||||
|
/* Read the old score. If the element was not present starts from 0 */
|
||||||
|
de = dictFind(zs->dict,ele);
|
||||||
|
if (de) {
|
||||||
|
double *oldscore = dictGetEntryVal(de);
|
||||||
|
*score = *oldscore + scoreval;
|
||||||
|
} else {
|
||||||
|
*score = scoreval;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*score = scoreval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* What follows is a simple remove and re-insert operation that is common
|
||||||
|
* to both ZADD and ZINCRSCOREBY... */
|
||||||
|
if (dictAdd(zs->dict,ele,score) == DICT_OK) {
|
||||||
/* case 1: New element */
|
/* case 1: New element */
|
||||||
incrRefCount(c->argv[3]); /* added to hash */
|
incrRefCount(ele); /* added to hash */
|
||||||
zslInsert(zs->zsl,*score,c->argv[3]);
|
zslInsert(zs->zsl,*score,ele);
|
||||||
incrRefCount(c->argv[3]); /* added to skiplist */
|
incrRefCount(ele); /* added to skiplist */
|
||||||
server.dirty++;
|
server.dirty++;
|
||||||
|
if (doincrement)
|
||||||
addReply(c,shared.cone);
|
addReply(c,shared.cone);
|
||||||
|
else
|
||||||
|
addReplyDouble(c,*score);
|
||||||
} else {
|
} else {
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
double *oldscore;
|
double *oldscore;
|
||||||
|
|
||||||
/* case 2: Score update operation */
|
/* case 2: Score update operation */
|
||||||
de = dictFind(zs->dict,c->argv[3]);
|
de = dictFind(zs->dict,ele);
|
||||||
assert(de != NULL);
|
assert(de != NULL);
|
||||||
oldscore = dictGetEntryVal(de);
|
oldscore = dictGetEntryVal(de);
|
||||||
if (*score != *oldscore) {
|
if (*score != *oldscore) {
|
||||||
int deleted;
|
int deleted;
|
||||||
|
|
||||||
deleted = zslDelete(zs->zsl,*oldscore,c->argv[3]);
|
/* Remove and insert the element in the skip list with new score */
|
||||||
|
deleted = zslDelete(zs->zsl,*oldscore,ele);
|
||||||
assert(deleted != 0);
|
assert(deleted != 0);
|
||||||
zslInsert(zs->zsl,*score,c->argv[3]);
|
zslInsert(zs->zsl,*score,ele);
|
||||||
incrRefCount(c->argv[3]);
|
incrRefCount(ele);
|
||||||
dictReplace(zs->dict,c->argv[3],score);
|
/* Update the score in the hash table */
|
||||||
|
dictReplace(zs->dict,ele,score);
|
||||||
server.dirty++;
|
server.dirty++;
|
||||||
} else {
|
} else {
|
||||||
zfree(score);
|
zfree(score);
|
||||||
}
|
}
|
||||||
|
if (doincrement)
|
||||||
|
addReplyDouble(c,*score);
|
||||||
|
else
|
||||||
addReply(c,shared.czero);
|
addReply(c,shared.czero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void zaddCommand(redisClient *c) {
|
||||||
|
double scoreval;
|
||||||
|
|
||||||
|
scoreval = strtod(c->argv[2]->ptr,NULL);
|
||||||
|
zaddGenericCommand(c,c->argv[1],c->argv[3],scoreval,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void zincrscorebyCommand(redisClient *c) {
|
||||||
|
double scoreval;
|
||||||
|
|
||||||
|
scoreval = strtod(c->argv[2]->ptr,NULL);
|
||||||
|
zaddGenericCommand(c,c->argv[1],c->argv[3],scoreval,1);
|
||||||
|
}
|
||||||
|
|
||||||
static void zremCommand(redisClient *c) {
|
static void zremCommand(redisClient *c) {
|
||||||
robj *zsetobj;
|
robj *zsetobj;
|
||||||
zset *zs;
|
zset *zs;
|
||||||
@ -4478,12 +4532,9 @@ static void zscoreCommand(redisClient *c) {
|
|||||||
if (!de) {
|
if (!de) {
|
||||||
addReply(c,shared.nullbulk);
|
addReply(c,shared.nullbulk);
|
||||||
} else {
|
} else {
|
||||||
char buf[128];
|
|
||||||
double *score = dictGetEntryVal(de);
|
double *score = dictGetEntryVal(de);
|
||||||
|
|
||||||
snprintf(buf,sizeof(buf),"%.17g",*score);
|
addReplyDouble(c,*score);
|
||||||
addReplySds(c,sdscatprintf(sdsempty(),"$%d\r\n%s\r\n",
|
|
||||||
strlen(buf),buf));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user