mirror of
https://github.com/fluencelabs/redis
synced 2025-03-19 09:00:51 +00:00
lookup rank of a zset entry in a different function
This commit is contained in:
parent
8fe7fad771
commit
27b0ccca71
75
redis.c
75
redis.c
@ -5054,6 +5054,33 @@ static zskiplistNode *zslFirstWithScore(zskiplist *zsl, double score) {
|
|||||||
return x->forward[0];
|
return x->forward[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find the rank for an element by both score and key.
|
||||||
|
* Returns 0 when the element cannot be found, rank otherwise.
|
||||||
|
* Note that the rank is 1-based due to the span of zsl->header to the
|
||||||
|
* first element. */
|
||||||
|
static unsigned long zslGetRank(zskiplist *zsl, double score, robj *o) {
|
||||||
|
zskiplistNode *x;
|
||||||
|
unsigned long rank = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
x = zsl->header;
|
||||||
|
for (i = zsl->level-1; i >= 0; i--) {
|
||||||
|
while (x->forward[i] &&
|
||||||
|
(x->forward[i]->score < score ||
|
||||||
|
(x->forward[i]->score == score &&
|
||||||
|
compareStringObjects(x->forward[i]->obj,o) <= 0))) {
|
||||||
|
rank += x->span[i];
|
||||||
|
x = x->forward[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* x might be equal to zsl->header, so test if obj is non-NULL */
|
||||||
|
if (x->obj && compareStringObjects(x->obj,o) == 0) {
|
||||||
|
return rank;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* The actual Z-commands implementations */
|
/* The actual Z-commands implementations */
|
||||||
|
|
||||||
/* This generic command implements both ZADD and ZINCRBY.
|
/* This generic command implements both ZADD and ZINCRBY.
|
||||||
@ -5467,42 +5494,26 @@ static void zrankCommand(redisClient *c) {
|
|||||||
}
|
}
|
||||||
if (o->type != REDIS_ZSET) {
|
if (o->type != REDIS_ZSET) {
|
||||||
addReply(c,shared.wrongtypeerr);
|
addReply(c,shared.wrongtypeerr);
|
||||||
return;
|
} else {
|
||||||
}
|
zset *zs = o->ptr;
|
||||||
|
zskiplist *zsl = zs->zsl;
|
||||||
|
dictEntry *de;
|
||||||
|
unsigned long rank;
|
||||||
|
|
||||||
zset *zs = o->ptr;
|
de = dictFind(zs->dict,c->argv[2]);
|
||||||
zskiplist *zsl = zs->zsl;
|
if (!de) {
|
||||||
dictEntry *de = dictFind(zs->dict,c->argv[2]);
|
addReply(c,shared.nullbulk);
|
||||||
if (!de) {
|
|
||||||
addReply(c,shared.nullbulk);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
double *score = dictGetEntryVal(de);
|
|
||||||
zskiplistNode *x;
|
|
||||||
unsigned int rank = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
x = zsl->header;
|
|
||||||
for (i = zsl->level-1; i >= 0; i--) {
|
|
||||||
while (x->forward[i] &&
|
|
||||||
(x->forward[i]->score < *score ||
|
|
||||||
(x->forward[i]->score == *score &&
|
|
||||||
compareStringObjects(x->forward[i]->obj,c->argv[2]) <= 0))) {
|
|
||||||
rank += x->span[i];
|
|
||||||
x = x->forward[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* x might be equal to zsl->header, so test if obj is non-NULL */
|
|
||||||
if (x->obj && compareStringObjects(x->obj,c->argv[2]) == 0) {
|
|
||||||
/* the pointer from zsl->header to the first element also spans one,
|
|
||||||
* which makes the rank 1-based */
|
|
||||||
addReplyLong(c, rank-1);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
addReply(c,shared.nullbulk);
|
double *score = dictGetEntryVal(de);
|
||||||
|
rank = zslGetRank(zsl, *score, c->argv[2]);
|
||||||
|
if (rank) {
|
||||||
|
addReplyLong(c, rank-1);
|
||||||
|
} else {
|
||||||
|
addReply(c,shared.nullbulk);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================= Non type-specific commands ==================== */
|
/* ========================= Non type-specific commands ==================== */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user