diff --git a/src/db.c b/src/db.c index bcfe9b5d5..3f85d43a8 100644 --- a/src/db.c +++ b/src/db.c @@ -780,17 +780,30 @@ unsigned int getKeysInSlot(unsigned int hashslot, robj **keys, unsigned int coun } unsigned int countKeysInSlot(unsigned int hashslot) { - zskiplistNode *n; + zskiplist *zsl = server.cluster->slots_to_keys; + zskiplistNode *zn; zrangespec range; - int j = 0; + int rank, count = 0; range.min = range.max = hashslot; range.minex = range.maxex = 0; - - n = zslFirstInRange(server.cluster->slots_to_keys, range); - while(n && n->score == hashslot) { - j++; - n = n->level[0].forward; + + /* Find first element in range */ + zn = zslFirstInRange(zsl, range); + + /* Use rank of first element, if any, to determine preliminary count */ + if (zn != NULL) { + rank = zslGetRank(zsl, zn->score, zn->obj); + count = (zsl->length - (rank - 1)); + + /* Find last element in range */ + zn = zslLastInRange(zsl, range); + + /* Use rank of last element, if any, to determine the actual count */ + if (zn != NULL) { + rank = zslGetRank(zsl, zn->score, zn->obj); + count -= (zsl->length - rank); + } } - return j; + return count; } diff --git a/src/redis.h b/src/redis.h index 4006aaa6f..b2f8e6e49 100644 --- a/src/redis.h +++ b/src/redis.h @@ -1129,11 +1129,13 @@ zskiplistNode *zslInsert(zskiplist *zsl, double score, robj *obj); unsigned char *zzlInsert(unsigned char *zl, robj *ele, double score); int zslDelete(zskiplist *zsl, double score, robj *obj); zskiplistNode *zslFirstInRange(zskiplist *zsl, zrangespec range); +zskiplistNode *zslLastInRange(zskiplist *zsl, zrangespec range); double zzlGetScore(unsigned char *sptr); void zzlNext(unsigned char *zl, unsigned char **eptr, unsigned char **sptr); void zzlPrev(unsigned char *zl, unsigned char **eptr, unsigned char **sptr); unsigned int zsetLength(robj *zobj); void zsetConvert(robj *zobj, int encoding); +unsigned long zslGetRank(zskiplist *zsl, double score, robj *o); /* Core functions */ int freeMemoryIfNeeded(void);