xref: /redis-3.2.3/src/t_zset.c (revision 897adc1c)
1 /*
2  * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>
3  * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  *   * Redistributions of source code must retain the above copyright notice,
10  *     this list of conditions and the following disclaimer.
11  *   * Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *   * Neither the name of Redis nor the names of its contributors may be used
15  *     to endorse or promote products derived from this software without
16  *     specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /*-----------------------------------------------------------------------------
32  * Sorted set API
33  *----------------------------------------------------------------------------*/
34 
35 /* ZSETs are ordered sets using two data structures to hold the same elements
36  * in order to get O(log(N)) INSERT and REMOVE operations into a sorted
37  * data structure.
38  *
39  * The elements are added to a hash table mapping Redis objects to scores.
40  * At the same time the elements are added to a skip list mapping scores
41  * to Redis objects (so objects are sorted by scores in this "view"). */
42 
43 /* This skiplist implementation is almost a C translation of the original
44  * algorithm described by William Pugh in "Skip Lists: A Probabilistic
45  * Alternative to Balanced Trees", modified in three ways:
46  * a) this implementation allows for repeated scores.
47  * b) the comparison is not just by key (our 'score') but by satellite data.
48  * c) there is a back pointer, so it's a doubly linked list with the back
49  * pointers being only at "level 1". This allows to traverse the list
50  * from tail to head, useful for ZREVRANGE. */
51 
52 #include "redis.h"
53 #include <math.h>
54 
55 static int zslLexValueGteMin(robj *value, zlexrangespec *spec);
56 static int zslLexValueLteMax(robj *value, zlexrangespec *spec);
57 
58 zskiplistNode *zslCreateNode(int level, double score, robj *obj) {
59     zskiplistNode *zn = zmalloc(sizeof(*zn)+level*sizeof(struct zskiplistLevel));
60     zn->score = score;
61     zn->obj = obj;
62     return zn;
63 }
64 
65 zskiplist *zslCreate(void) {
66     int j;
67     zskiplist *zsl;
68 
69     zsl = zmalloc(sizeof(*zsl));
70     zsl->level = 1;
71     zsl->length = 0;
72     zsl->header = zslCreateNode(ZSKIPLIST_MAXLEVEL,0,NULL);
73     for (j = 0; j < ZSKIPLIST_MAXLEVEL; j++) {
74         zsl->header->level[j].forward = NULL;
75         zsl->header->level[j].span = 0;
76     }
77     zsl->header->backward = NULL;
78     zsl->tail = NULL;
79     return zsl;
80 }
81 
82 void zslFreeNode(zskiplistNode *node) {
83     decrRefCount(node->obj);
84     zfree(node);
85 }
86 
87 void zslFree(zskiplist *zsl) {
88     zskiplistNode *node = zsl->header->level[0].forward, *next;
89 
90     zfree(zsl->header);
91     while(node) {
92         next = node->level[0].forward;
93         zslFreeNode(node);
94         node = next;
95     }
96     zfree(zsl);
97 }
98 
99 /* Returns a random level for the new skiplist node we are going to create.
100  * The return value of this function is between 1 and ZSKIPLIST_MAXLEVEL
101  * (both inclusive), with a powerlaw-alike distribution where higher
102  * levels are less likely to be returned. */
103 int zslRandomLevel(void) {
104     int level = 1;
105     while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
106         level += 1;
107     return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
108 }
109 
110 zskiplistNode *zslInsert(zskiplist *zsl, double score, robj *obj) {
111     zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
112     unsigned int rank[ZSKIPLIST_MAXLEVEL];
113     int i, level;
114 
115     redisAssert(!isnan(score));
116     x = zsl->header;
117     for (i = zsl->level-1; i >= 0; i--) {
118         /* store rank that is crossed to reach the insert position */
119         rank[i] = i == (zsl->level-1) ? 0 : rank[i+1];
120         while (x->level[i].forward &&
121             (x->level[i].forward->score < score ||
122                 (x->level[i].forward->score == score &&
123                 compareStringObjects(x->level[i].forward->obj,obj) < 0))) {
124             rank[i] += x->level[i].span;
125             x = x->level[i].forward;
126         }
127         update[i] = x;
128     }
129     /* we assume the key is not already inside, since we allow duplicated
130      * scores, and the re-insertion of score and redis object should never
131      * happen since the caller of zslInsert() should test in the hash table
132      * if the element is already inside or not. */
133     level = zslRandomLevel();
134     if (level > zsl->level) {
135         for (i = zsl->level; i < level; i++) {
136             rank[i] = 0;
137             update[i] = zsl->header;
138             update[i]->level[i].span = zsl->length;
139         }
140         zsl->level = level;
141     }
142     x = zslCreateNode(level,score,obj);
143     for (i = 0; i < level; i++) {
144         x->level[i].forward = update[i]->level[i].forward;
145         update[i]->level[i].forward = x;
146 
147         /* update span covered by update[i] as x is inserted here */
148         x->level[i].span = update[i]->level[i].span - (rank[0] - rank[i]);
149         update[i]->level[i].span = (rank[0] - rank[i]) + 1;
150     }
151 
152     /* increment span for untouched levels */
153     for (i = level; i < zsl->level; i++) {
154         update[i]->level[i].span++;
155     }
156 
157     x->backward = (update[0] == zsl->header) ? NULL : update[0];
158     if (x->level[0].forward)
159         x->level[0].forward->backward = x;
160     else
161         zsl->tail = x;
162     zsl->length++;
163     return x;
164 }
165 
166 /* Internal function used by zslDelete, zslDeleteByScore and zslDeleteByRank */
167 void zslDeleteNode(zskiplist *zsl, zskiplistNode *x, zskiplistNode **update) {
168     int i;
169     for (i = 0; i < zsl->level; i++) {
170         if (update[i]->level[i].forward == x) {
171             update[i]->level[i].span += x->level[i].span - 1;
172             update[i]->level[i].forward = x->level[i].forward;
173         } else {
174             update[i]->level[i].span -= 1;
175         }
176     }
177     if (x->level[0].forward) {
178         x->level[0].forward->backward = x->backward;
179     } else {
180         zsl->tail = x->backward;
181     }
182     while(zsl->level > 1 && zsl->header->level[zsl->level-1].forward == NULL)
183         zsl->level--;
184     zsl->length--;
185 }
186 
187 /* Delete an element with matching score/object from the skiplist. */
188 int zslDelete(zskiplist *zsl, double score, robj *obj) {
189     zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
190     int i;
191 
192     x = zsl->header;
193     for (i = zsl->level-1; i >= 0; i--) {
194         while (x->level[i].forward &&
195             (x->level[i].forward->score < score ||
196                 (x->level[i].forward->score == score &&
197                 compareStringObjects(x->level[i].forward->obj,obj) < 0)))
198             x = x->level[i].forward;
199         update[i] = x;
200     }
201     /* We may have multiple elements with the same score, what we need
202      * is to find the element with both the right score and object. */
203     x = x->level[0].forward;
204     if (x && score == x->score && equalStringObjects(x->obj,obj)) {
205         zslDeleteNode(zsl, x, update);
206         zslFreeNode(x);
207         return 1;
208     } else {
209         return 0; /* not found */
210     }
211     return 0; /* not found */
212 }
213 
214 static int zslValueGteMin(double value, zrangespec *spec) {
215     return spec->minex ? (value > spec->min) : (value >= spec->min);
216 }
217 
218 static int zslValueLteMax(double value, zrangespec *spec) {
219     return spec->maxex ? (value < spec->max) : (value <= spec->max);
220 }
221 
222 /* Returns if there is a part of the zset is in range. */
223 int zslIsInRange(zskiplist *zsl, zrangespec *range) {
224     zskiplistNode *x;
225 
226     /* Test for ranges that will always be empty. */
227     if (range->min > range->max ||
228             (range->min == range->max && (range->minex || range->maxex)))
229         return 0;
230     x = zsl->tail;
231     if (x == NULL || !zslValueGteMin(x->score,range))
232         return 0;
233     x = zsl->header->level[0].forward;
234     if (x == NULL || !zslValueLteMax(x->score,range))
235         return 0;
236     return 1;
237 }
238 
239 /* Find the first node that is contained in the specified range.
240  * Returns NULL when no element is contained in the range. */
241 zskiplistNode *zslFirstInRange(zskiplist *zsl, zrangespec *range) {
242     zskiplistNode *x;
243     int i;
244 
245     /* If everything is out of range, return early. */
246     if (!zslIsInRange(zsl,range)) return NULL;
247 
248     x = zsl->header;
249     for (i = zsl->level-1; i >= 0; i--) {
250         /* Go forward while *OUT* of range. */
251         while (x->level[i].forward &&
252             !zslValueGteMin(x->level[i].forward->score,range))
253                 x = x->level[i].forward;
254     }
255 
256     /* This is an inner range, so the next node cannot be NULL. */
257     x = x->level[0].forward;
258     redisAssert(x != NULL);
259 
260     /* Check if score <= max. */
261     if (!zslValueLteMax(x->score,range)) return NULL;
262     return x;
263 }
264 
265 /* Find the last node that is contained in the specified range.
266  * Returns NULL when no element is contained in the range. */
267 zskiplistNode *zslLastInRange(zskiplist *zsl, zrangespec *range) {
268     zskiplistNode *x;
269     int i;
270 
271     /* If everything is out of range, return early. */
272     if (!zslIsInRange(zsl,range)) return NULL;
273 
274     x = zsl->header;
275     for (i = zsl->level-1; i >= 0; i--) {
276         /* Go forward while *IN* range. */
277         while (x->level[i].forward &&
278             zslValueLteMax(x->level[i].forward->score,range))
279                 x = x->level[i].forward;
280     }
281 
282     /* This is an inner range, so this node cannot be NULL. */
283     redisAssert(x != NULL);
284 
285     /* Check if score >= min. */
286     if (!zslValueGteMin(x->score,range)) return NULL;
287     return x;
288 }
289 
290 /* Delete all the elements with score between min and max from the skiplist.
291  * Min and max are inclusive, so a score >= min || score <= max is deleted.
292  * Note that this function takes the reference to the hash table view of the
293  * sorted set, in order to remove the elements from the hash table too. */
294 unsigned long zslDeleteRangeByScore(zskiplist *zsl, zrangespec *range, dict *dict) {
295     zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
296     unsigned long removed = 0;
297     int i;
298 
299     x = zsl->header;
300     for (i = zsl->level-1; i >= 0; i--) {
301         while (x->level[i].forward && (range->minex ?
302             x->level[i].forward->score <= range->min :
303             x->level[i].forward->score < range->min))
304                 x = x->level[i].forward;
305         update[i] = x;
306     }
307 
308     /* Current node is the last with score < or <= min. */
309     x = x->level[0].forward;
310 
311     /* Delete nodes while in range. */
312     while (x &&
313            (range->maxex ? x->score < range->max : x->score <= range->max))
314     {
315         zskiplistNode *next = x->level[0].forward;
316         zslDeleteNode(zsl,x,update);
317         dictDelete(dict,x->obj);
318         zslFreeNode(x);
319         removed++;
320         x = next;
321     }
322     return removed;
323 }
324 
325 unsigned long zslDeleteRangeByLex(zskiplist *zsl, zlexrangespec *range, dict *dict) {
326     zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
327     unsigned long removed = 0;
328     int i;
329 
330 
331     x = zsl->header;
332     for (i = zsl->level-1; i >= 0; i--) {
333         while (x->level[i].forward &&
334             !zslLexValueGteMin(x->level[i].forward->obj,range))
335                 x = x->level[i].forward;
336         update[i] = x;
337     }
338 
339     /* Current node is the last with score < or <= min. */
340     x = x->level[0].forward;
341 
342     /* Delete nodes while in range. */
343     while (x && zslLexValueLteMax(x->obj,range)) {
344         zskiplistNode *next = x->level[0].forward;
345         zslDeleteNode(zsl,x,update);
346         dictDelete(dict,x->obj);
347         zslFreeNode(x);
348         removed++;
349         x = next;
350     }
351     return removed;
352 }
353 
354 /* Delete all the elements with rank between start and end from the skiplist.
355  * Start and end are inclusive. Note that start and end need to be 1-based */
356 unsigned long zslDeleteRangeByRank(zskiplist *zsl, unsigned int start, unsigned int end, dict *dict) {
357     zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
358     unsigned long traversed = 0, removed = 0;
359     int i;
360 
361     x = zsl->header;
362     for (i = zsl->level-1; i >= 0; i--) {
363         while (x->level[i].forward && (traversed + x->level[i].span) < start) {
364             traversed += x->level[i].span;
365             x = x->level[i].forward;
366         }
367         update[i] = x;
368     }
369 
370     traversed++;
371     x = x->level[0].forward;
372     while (x && traversed <= end) {
373         zskiplistNode *next = x->level[0].forward;
374         zslDeleteNode(zsl,x,update);
375         dictDelete(dict,x->obj);
376         zslFreeNode(x);
377         removed++;
378         traversed++;
379         x = next;
380     }
381     return removed;
382 }
383 
384 /* Find the rank for an element by both score and key.
385  * Returns 0 when the element cannot be found, rank otherwise.
386  * Note that the rank is 1-based due to the span of zsl->header to the
387  * first element. */
388 unsigned long zslGetRank(zskiplist *zsl, double score, robj *o) {
389     zskiplistNode *x;
390     unsigned long rank = 0;
391     int i;
392 
393     x = zsl->header;
394     for (i = zsl->level-1; i >= 0; i--) {
395         while (x->level[i].forward &&
396             (x->level[i].forward->score < score ||
397                 (x->level[i].forward->score == score &&
398                 compareStringObjects(x->level[i].forward->obj,o) <= 0))) {
399             rank += x->level[i].span;
400             x = x->level[i].forward;
401         }
402 
403         /* x might be equal to zsl->header, so test if obj is non-NULL */
404         if (x->obj && equalStringObjects(x->obj,o)) {
405             return rank;
406         }
407     }
408     return 0;
409 }
410 
411 /* Finds an element by its rank. The rank argument needs to be 1-based. */
412 zskiplistNode* zslGetElementByRank(zskiplist *zsl, unsigned long rank) {
413     zskiplistNode *x;
414     unsigned long traversed = 0;
415     int i;
416 
417     x = zsl->header;
418     for (i = zsl->level-1; i >= 0; i--) {
419         while (x->level[i].forward && (traversed + x->level[i].span) <= rank)
420         {
421             traversed += x->level[i].span;
422             x = x->level[i].forward;
423         }
424         if (traversed == rank) {
425             return x;
426         }
427     }
428     return NULL;
429 }
430 
431 /* Populate the rangespec according to the objects min and max. */
432 static int zslParseRange(robj *min, robj *max, zrangespec *spec) {
433     char *eptr;
434     spec->minex = spec->maxex = 0;
435 
436     /* Parse the min-max interval. If one of the values is prefixed
437      * by the "(" character, it's considered "open". For instance
438      * ZRANGEBYSCORE zset (1.5 (2.5 will match min < x < max
439      * ZRANGEBYSCORE zset 1.5 2.5 will instead match min <= x <= max */
440     if (min->encoding == REDIS_ENCODING_INT) {
441         spec->min = (long)min->ptr;
442     } else {
443         if (((char*)min->ptr)[0] == '(') {
444             spec->min = strtod((char*)min->ptr+1,&eptr);
445             if (eptr[0] != '\0' || isnan(spec->min)) return REDIS_ERR;
446             spec->minex = 1;
447         } else {
448             spec->min = strtod((char*)min->ptr,&eptr);
449             if (eptr[0] != '\0' || isnan(spec->min)) return REDIS_ERR;
450         }
451     }
452     if (max->encoding == REDIS_ENCODING_INT) {
453         spec->max = (long)max->ptr;
454     } else {
455         if (((char*)max->ptr)[0] == '(') {
456             spec->max = strtod((char*)max->ptr+1,&eptr);
457             if (eptr[0] != '\0' || isnan(spec->max)) return REDIS_ERR;
458             spec->maxex = 1;
459         } else {
460             spec->max = strtod((char*)max->ptr,&eptr);
461             if (eptr[0] != '\0' || isnan(spec->max)) return REDIS_ERR;
462         }
463     }
464 
465     return REDIS_OK;
466 }
467 
468 /* ------------------------ Lexicographic ranges ---------------------------- */
469 
470 /* Parse max or min argument of ZRANGEBYLEX.
471   * (foo means foo (open interval)
472   * [foo means foo (closed interval)
473   * - means the min string possible
474   * + means the max string possible
475   *
476   * If the string is valid the *dest pointer is set to the redis object
477   * that will be used for the comparision, and ex will be set to 0 or 1
478   * respectively if the item is exclusive or inclusive. REDIS_OK will be
479   * returned.
480   *
481   * If the string is not a valid range REDIS_ERR is returned, and the value
482   * of *dest and *ex is undefined. */
483 int zslParseLexRangeItem(robj *item, robj **dest, int *ex) {
484     char *c = item->ptr;
485 
486     switch(c[0]) {
487     case '+':
488         if (c[1] != '\0') return REDIS_ERR;
489         *ex = 0;
490         *dest = shared.maxstring;
491         incrRefCount(shared.maxstring);
492         return REDIS_OK;
493     case '-':
494         if (c[1] != '\0') return REDIS_ERR;
495         *ex = 0;
496         *dest = shared.minstring;
497         incrRefCount(shared.minstring);
498         return REDIS_OK;
499     case '(':
500         *ex = 1;
501         *dest = createStringObject(c+1,sdslen(c)-1);
502         return REDIS_OK;
503     case '[':
504         *ex = 0;
505         *dest = createStringObject(c+1,sdslen(c)-1);
506         return REDIS_OK;
507     default:
508         return REDIS_ERR;
509     }
510 }
511 
512 /* Populate the rangespec according to the objects min and max.
513  *
514  * Return REDIS_OK on success. On error REDIS_ERR is returned.
515  * When OK is returned the structure must be freed with zslFreeLexRange(),
516  * otherwise no release is needed. */
517 static int zslParseLexRange(robj *min, robj *max, zlexrangespec *spec) {
518     /* The range can't be valid if objects are integer encoded.
519      * Every item must start with ( or [. */
520     if (min->encoding == REDIS_ENCODING_INT ||
521         max->encoding == REDIS_ENCODING_INT) return REDIS_ERR;
522 
523     spec->min = spec->max = NULL;
524     if (zslParseLexRangeItem(min, &spec->min, &spec->minex) == REDIS_ERR ||
525         zslParseLexRangeItem(max, &spec->max, &spec->maxex) == REDIS_ERR) {
526         if (spec->min) decrRefCount(spec->min);
527         if (spec->max) decrRefCount(spec->max);
528         return REDIS_ERR;
529     } else {
530         return REDIS_OK;
531     }
532 }
533 
534 /* Free a lex range structure, must be called only after zelParseLexRange()
535  * populated the structure with success (REDIS_OK returned). */
536 void zslFreeLexRange(zlexrangespec *spec) {
537     decrRefCount(spec->min);
538     decrRefCount(spec->max);
539 }
540 
541 /* This is just a wrapper to compareStringObjects() that is able to
542  * handle shared.minstring and shared.maxstring as the equivalent of
543  * -inf and +inf for strings */
544 int compareStringObjectsForLexRange(robj *a, robj *b) {
545     if (a == b) return 0; /* This makes sure that we handle inf,inf and
546                              -inf,-inf ASAP. One special case less. */
547     if (a == shared.minstring || b == shared.maxstring) return -1;
548     if (a == shared.maxstring || b == shared.minstring) return 1;
549     return compareStringObjects(a,b);
550 }
551 
552 static int zslLexValueGteMin(robj *value, zlexrangespec *spec) {
553     return spec->minex ?
554         (compareStringObjectsForLexRange(value,spec->min) > 0) :
555         (compareStringObjectsForLexRange(value,spec->min) >= 0);
556 }
557 
558 static int zslLexValueLteMax(robj *value, zlexrangespec *spec) {
559     return spec->maxex ?
560         (compareStringObjectsForLexRange(value,spec->max) < 0) :
561         (compareStringObjectsForLexRange(value,spec->max) <= 0);
562 }
563 
564 /* Returns if there is a part of the zset is in the lex range. */
565 int zslIsInLexRange(zskiplist *zsl, zlexrangespec *range) {
566     zskiplistNode *x;
567 
568     /* Test for ranges that will always be empty. */
569     if (compareStringObjectsForLexRange(range->min,range->max) > 1 ||
570             (compareStringObjects(range->min,range->max) == 0 &&
571             (range->minex || range->maxex)))
572         return 0;
573     x = zsl->tail;
574     if (x == NULL || !zslLexValueGteMin(x->obj,range))
575         return 0;
576     x = zsl->header->level[0].forward;
577     if (x == NULL || !zslLexValueLteMax(x->obj,range))
578         return 0;
579     return 1;
580 }
581 
582 /* Find the first node that is contained in the specified lex range.
583  * Returns NULL when no element is contained in the range. */
584 zskiplistNode *zslFirstInLexRange(zskiplist *zsl, zlexrangespec *range) {
585     zskiplistNode *x;
586     int i;
587 
588     /* If everything is out of range, return early. */
589     if (!zslIsInLexRange(zsl,range)) return NULL;
590 
591     x = zsl->header;
592     for (i = zsl->level-1; i >= 0; i--) {
593         /* Go forward while *OUT* of range. */
594         while (x->level[i].forward &&
595             !zslLexValueGteMin(x->level[i].forward->obj,range))
596                 x = x->level[i].forward;
597     }
598 
599     /* This is an inner range, so the next node cannot be NULL. */
600     x = x->level[0].forward;
601     redisAssert(x != NULL);
602 
603     /* Check if score <= max. */
604     if (!zslLexValueLteMax(x->obj,range)) return NULL;
605     return x;
606 }
607 
608 /* Find the last node that is contained in the specified range.
609  * Returns NULL when no element is contained in the range. */
610 zskiplistNode *zslLastInLexRange(zskiplist *zsl, zlexrangespec *range) {
611     zskiplistNode *x;
612     int i;
613 
614     /* If everything is out of range, return early. */
615     if (!zslIsInLexRange(zsl,range)) return NULL;
616 
617     x = zsl->header;
618     for (i = zsl->level-1; i >= 0; i--) {
619         /* Go forward while *IN* range. */
620         while (x->level[i].forward &&
621             zslLexValueLteMax(x->level[i].forward->obj,range))
622                 x = x->level[i].forward;
623     }
624 
625     /* This is an inner range, so this node cannot be NULL. */
626     redisAssert(x != NULL);
627 
628     /* Check if score >= min. */
629     if (!zslLexValueGteMin(x->obj,range)) return NULL;
630     return x;
631 }
632 
633 /*-----------------------------------------------------------------------------
634  * Ziplist-backed sorted set API
635  *----------------------------------------------------------------------------*/
636 
637 double zzlGetScore(unsigned char *sptr) {
638     unsigned char *vstr;
639     unsigned int vlen;
640     long long vlong;
641     char buf[128];
642     double score;
643 
644     redisAssert(sptr != NULL);
645     redisAssert(ziplistGet(sptr,&vstr,&vlen,&vlong));
646 
647     if (vstr) {
648         memcpy(buf,vstr,vlen);
649         buf[vlen] = '\0';
650         score = strtod(buf,NULL);
651     } else {
652         score = vlong;
653     }
654 
655     return score;
656 }
657 
658 /* Return a ziplist element as a Redis string object.
659  * This simple abstraction can be used to simplifies some code at the
660  * cost of some performance. */
661 robj *ziplistGetObject(unsigned char *sptr) {
662     unsigned char *vstr;
663     unsigned int vlen;
664     long long vlong;
665 
666     redisAssert(sptr != NULL);
667     redisAssert(ziplistGet(sptr,&vstr,&vlen,&vlong));
668 
669     if (vstr) {
670         return createStringObject((char*)vstr,vlen);
671     } else {
672         return createStringObjectFromLongLong(vlong);
673     }
674 }
675 
676 /* Compare element in sorted set with given element. */
677 int zzlCompareElements(unsigned char *eptr, unsigned char *cstr, unsigned int clen) {
678     unsigned char *vstr;
679     unsigned int vlen;
680     long long vlong;
681     unsigned char vbuf[32];
682     int minlen, cmp;
683 
684     redisAssert(ziplistGet(eptr,&vstr,&vlen,&vlong));
685     if (vstr == NULL) {
686         /* Store string representation of long long in buf. */
687         vlen = ll2string((char*)vbuf,sizeof(vbuf),vlong);
688         vstr = vbuf;
689     }
690 
691     minlen = (vlen < clen) ? vlen : clen;
692     cmp = memcmp(vstr,cstr,minlen);
693     if (cmp == 0) return vlen-clen;
694     return cmp;
695 }
696 
697 unsigned int zzlLength(unsigned char *zl) {
698     return ziplistLen(zl)/2;
699 }
700 
701 /* Move to next entry based on the values in eptr and sptr. Both are set to
702  * NULL when there is no next entry. */
703 void zzlNext(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) {
704     unsigned char *_eptr, *_sptr;
705     redisAssert(*eptr != NULL && *sptr != NULL);
706 
707     _eptr = ziplistNext(zl,*sptr);
708     if (_eptr != NULL) {
709         _sptr = ziplistNext(zl,_eptr);
710         redisAssert(_sptr != NULL);
711     } else {
712         /* No next entry. */
713         _sptr = NULL;
714     }
715 
716     *eptr = _eptr;
717     *sptr = _sptr;
718 }
719 
720 /* Move to the previous entry based on the values in eptr and sptr. Both are
721  * set to NULL when there is no next entry. */
722 void zzlPrev(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) {
723     unsigned char *_eptr, *_sptr;
724     redisAssert(*eptr != NULL && *sptr != NULL);
725 
726     _sptr = ziplistPrev(zl,*eptr);
727     if (_sptr != NULL) {
728         _eptr = ziplistPrev(zl,_sptr);
729         redisAssert(_eptr != NULL);
730     } else {
731         /* No previous entry. */
732         _eptr = NULL;
733     }
734 
735     *eptr = _eptr;
736     *sptr = _sptr;
737 }
738 
739 /* Returns if there is a part of the zset is in range. Should only be used
740  * internally by zzlFirstInRange and zzlLastInRange. */
741 int zzlIsInRange(unsigned char *zl, zrangespec *range) {
742     unsigned char *p;
743     double score;
744 
745     /* Test for ranges that will always be empty. */
746     if (range->min > range->max ||
747             (range->min == range->max && (range->minex || range->maxex)))
748         return 0;
749 
750     p = ziplistIndex(zl,-1); /* Last score. */
751     if (p == NULL) return 0; /* Empty sorted set */
752     score = zzlGetScore(p);
753     if (!zslValueGteMin(score,range))
754         return 0;
755 
756     p = ziplistIndex(zl,1); /* First score. */
757     redisAssert(p != NULL);
758     score = zzlGetScore(p);
759     if (!zslValueLteMax(score,range))
760         return 0;
761 
762     return 1;
763 }
764 
765 /* Find pointer to the first element contained in the specified range.
766  * Returns NULL when no element is contained in the range. */
767 unsigned char *zzlFirstInRange(unsigned char *zl, zrangespec *range) {
768     unsigned char *eptr = ziplistIndex(zl,0), *sptr;
769     double score;
770 
771     /* If everything is out of range, return early. */
772     if (!zzlIsInRange(zl,range)) return NULL;
773 
774     while (eptr != NULL) {
775         sptr = ziplistNext(zl,eptr);
776         redisAssert(sptr != NULL);
777 
778         score = zzlGetScore(sptr);
779         if (zslValueGteMin(score,range)) {
780             /* Check if score <= max. */
781             if (zslValueLteMax(score,range))
782                 return eptr;
783             return NULL;
784         }
785 
786         /* Move to next element. */
787         eptr = ziplistNext(zl,sptr);
788     }
789 
790     return NULL;
791 }
792 
793 /* Find pointer to the last element contained in the specified range.
794  * Returns NULL when no element is contained in the range. */
795 unsigned char *zzlLastInRange(unsigned char *zl, zrangespec *range) {
796     unsigned char *eptr = ziplistIndex(zl,-2), *sptr;
797     double score;
798 
799     /* If everything is out of range, return early. */
800     if (!zzlIsInRange(zl,range)) return NULL;
801 
802     while (eptr != NULL) {
803         sptr = ziplistNext(zl,eptr);
804         redisAssert(sptr != NULL);
805 
806         score = zzlGetScore(sptr);
807         if (zslValueLteMax(score,range)) {
808             /* Check if score >= min. */
809             if (zslValueGteMin(score,range))
810                 return eptr;
811             return NULL;
812         }
813 
814         /* Move to previous element by moving to the score of previous element.
815          * When this returns NULL, we know there also is no element. */
816         sptr = ziplistPrev(zl,eptr);
817         if (sptr != NULL)
818             redisAssert((eptr = ziplistPrev(zl,sptr)) != NULL);
819         else
820             eptr = NULL;
821     }
822 
823     return NULL;
824 }
825 
826 static int zzlLexValueGteMin(unsigned char *p, zlexrangespec *spec) {
827     robj *value = ziplistGetObject(p);
828     int res = zslLexValueGteMin(value,spec);
829     decrRefCount(value);
830     return res;
831 }
832 
833 static int zzlLexValueLteMax(unsigned char *p, zlexrangespec *spec) {
834     robj *value = ziplistGetObject(p);
835     int res = zslLexValueLteMax(value,spec);
836     decrRefCount(value);
837     return res;
838 }
839 
840 /* Returns if there is a part of the zset is in range. Should only be used
841  * internally by zzlFirstInRange and zzlLastInRange. */
842 int zzlIsInLexRange(unsigned char *zl, zlexrangespec *range) {
843     unsigned char *p;
844 
845     /* Test for ranges that will always be empty. */
846     if (compareStringObjectsForLexRange(range->min,range->max) > 1 ||
847             (compareStringObjects(range->min,range->max) == 0 &&
848             (range->minex || range->maxex)))
849         return 0;
850 
851     p = ziplistIndex(zl,-2); /* Last element. */
852     if (p == NULL) return 0;
853     if (!zzlLexValueGteMin(p,range))
854         return 0;
855 
856     p = ziplistIndex(zl,0); /* First element. */
857     redisAssert(p != NULL);
858     if (!zzlLexValueLteMax(p,range))
859         return 0;
860 
861     return 1;
862 }
863 
864 /* Find pointer to the first element contained in the specified lex range.
865  * Returns NULL when no element is contained in the range. */
866 unsigned char *zzlFirstInLexRange(unsigned char *zl, zlexrangespec *range) {
867     unsigned char *eptr = ziplistIndex(zl,0), *sptr;
868 
869     /* If everything is out of range, return early. */
870     if (!zzlIsInLexRange(zl,range)) return NULL;
871 
872     while (eptr != NULL) {
873         if (zzlLexValueGteMin(eptr,range)) {
874             /* Check if score <= max. */
875             if (zzlLexValueLteMax(eptr,range))
876                 return eptr;
877             return NULL;
878         }
879 
880         /* Move to next element. */
881         sptr = ziplistNext(zl,eptr); /* This element score. Skip it. */
882         redisAssert(sptr != NULL);
883         eptr = ziplistNext(zl,sptr); /* Next element. */
884     }
885 
886     return NULL;
887 }
888 
889 /* Find pointer to the last element contained in the specified lex range.
890  * Returns NULL when no element is contained in the range. */
891 unsigned char *zzlLastInLexRange(unsigned char *zl, zlexrangespec *range) {
892     unsigned char *eptr = ziplistIndex(zl,-2), *sptr;
893 
894     /* If everything is out of range, return early. */
895     if (!zzlIsInLexRange(zl,range)) return NULL;
896 
897     while (eptr != NULL) {
898         if (zzlLexValueLteMax(eptr,range)) {
899             /* Check if score >= min. */
900             if (zzlLexValueGteMin(eptr,range))
901                 return eptr;
902             return NULL;
903         }
904 
905         /* Move to previous element by moving to the score of previous element.
906          * When this returns NULL, we know there also is no element. */
907         sptr = ziplistPrev(zl,eptr);
908         if (sptr != NULL)
909             redisAssert((eptr = ziplistPrev(zl,sptr)) != NULL);
910         else
911             eptr = NULL;
912     }
913 
914     return NULL;
915 }
916 
917 unsigned char *zzlFind(unsigned char *zl, robj *ele, double *score) {
918     unsigned char *eptr = ziplistIndex(zl,0), *sptr;
919 
920     ele = getDecodedObject(ele);
921     while (eptr != NULL) {
922         sptr = ziplistNext(zl,eptr);
923         redisAssertWithInfo(NULL,ele,sptr != NULL);
924 
925         if (ziplistCompare(eptr,ele->ptr,sdslen(ele->ptr))) {
926             /* Matching element, pull out score. */
927             if (score != NULL) *score = zzlGetScore(sptr);
928             decrRefCount(ele);
929             return eptr;
930         }
931 
932         /* Move to next element. */
933         eptr = ziplistNext(zl,sptr);
934     }
935 
936     decrRefCount(ele);
937     return NULL;
938 }
939 
940 /* Delete (element,score) pair from ziplist. Use local copy of eptr because we
941  * don't want to modify the one given as argument. */
942 unsigned char *zzlDelete(unsigned char *zl, unsigned char *eptr) {
943     unsigned char *p = eptr;
944 
945     /* TODO: add function to ziplist API to delete N elements from offset. */
946     zl = ziplistDelete(zl,&p);
947     zl = ziplistDelete(zl,&p);
948     return zl;
949 }
950 
951 unsigned char *zzlInsertAt(unsigned char *zl, unsigned char *eptr, robj *ele, double score) {
952     unsigned char *sptr;
953     char scorebuf[128];
954     int scorelen;
955     size_t offset;
956 
957     redisAssertWithInfo(NULL,ele,sdsEncodedObject(ele));
958     scorelen = d2string(scorebuf,sizeof(scorebuf),score);
959     if (eptr == NULL) {
960         zl = ziplistPush(zl,ele->ptr,sdslen(ele->ptr),ZIPLIST_TAIL);
961         zl = ziplistPush(zl,(unsigned char*)scorebuf,scorelen,ZIPLIST_TAIL);
962     } else {
963         /* Keep offset relative to zl, as it might be re-allocated. */
964         offset = eptr-zl;
965         zl = ziplistInsert(zl,eptr,ele->ptr,sdslen(ele->ptr));
966         eptr = zl+offset;
967 
968         /* Insert score after the element. */
969         redisAssertWithInfo(NULL,ele,(sptr = ziplistNext(zl,eptr)) != NULL);
970         zl = ziplistInsert(zl,sptr,(unsigned char*)scorebuf,scorelen);
971     }
972 
973     return zl;
974 }
975 
976 /* Insert (element,score) pair in ziplist. This function assumes the element is
977  * not yet present in the list. */
978 unsigned char *zzlInsert(unsigned char *zl, robj *ele, double score) {
979     unsigned char *eptr = ziplistIndex(zl,0), *sptr;
980     double s;
981 
982     ele = getDecodedObject(ele);
983     while (eptr != NULL) {
984         sptr = ziplistNext(zl,eptr);
985         redisAssertWithInfo(NULL,ele,sptr != NULL);
986         s = zzlGetScore(sptr);
987 
988         if (s > score) {
989             /* First element with score larger than score for element to be
990              * inserted. This means we should take its spot in the list to
991              * maintain ordering. */
992             zl = zzlInsertAt(zl,eptr,ele,score);
993             break;
994         } else if (s == score) {
995             /* Ensure lexicographical ordering for elements. */
996             if (zzlCompareElements(eptr,ele->ptr,sdslen(ele->ptr)) > 0) {
997                 zl = zzlInsertAt(zl,eptr,ele,score);
998                 break;
999             }
1000         }
1001 
1002         /* Move to next element. */
1003         eptr = ziplistNext(zl,sptr);
1004     }
1005 
1006     /* Push on tail of list when it was not yet inserted. */
1007     if (eptr == NULL)
1008         zl = zzlInsertAt(zl,NULL,ele,score);
1009 
1010     decrRefCount(ele);
1011     return zl;
1012 }
1013 
1014 unsigned char *zzlDeleteRangeByScore(unsigned char *zl, zrangespec *range, unsigned long *deleted) {
1015     unsigned char *eptr, *sptr;
1016     double score;
1017     unsigned long num = 0;
1018 
1019     if (deleted != NULL) *deleted = 0;
1020 
1021     eptr = zzlFirstInRange(zl,range);
1022     if (eptr == NULL) return zl;
1023 
1024     /* When the tail of the ziplist is deleted, eptr will point to the sentinel
1025      * byte and ziplistNext will return NULL. */
1026     while ((sptr = ziplistNext(zl,eptr)) != NULL) {
1027         score = zzlGetScore(sptr);
1028         if (zslValueLteMax(score,range)) {
1029             /* Delete both the element and the score. */
1030             zl = ziplistDelete(zl,&eptr);
1031             zl = ziplistDelete(zl,&eptr);
1032             num++;
1033         } else {
1034             /* No longer in range. */
1035             break;
1036         }
1037     }
1038 
1039     if (deleted != NULL) *deleted = num;
1040     return zl;
1041 }
1042 
1043 unsigned char *zzlDeleteRangeByLex(unsigned char *zl, zlexrangespec *range, unsigned long *deleted) {
1044     unsigned char *eptr, *sptr;
1045     unsigned long num = 0;
1046 
1047     if (deleted != NULL) *deleted = 0;
1048 
1049     eptr = zzlFirstInLexRange(zl,range);
1050     if (eptr == NULL) return zl;
1051 
1052     /* When the tail of the ziplist is deleted, eptr will point to the sentinel
1053      * byte and ziplistNext will return NULL. */
1054     while ((sptr = ziplistNext(zl,eptr)) != NULL) {
1055         if (zzlLexValueLteMax(eptr,range)) {
1056             /* Delete both the element and the score. */
1057             zl = ziplistDelete(zl,&eptr);
1058             zl = ziplistDelete(zl,&eptr);
1059             num++;
1060         } else {
1061             /* No longer in range. */
1062             break;
1063         }
1064     }
1065 
1066     if (deleted != NULL) *deleted = num;
1067     return zl;
1068 }
1069 
1070 /* Delete all the elements with rank between start and end from the skiplist.
1071  * Start and end are inclusive. Note that start and end need to be 1-based */
1072 unsigned char *zzlDeleteRangeByRank(unsigned char *zl, unsigned int start, unsigned int end, unsigned long *deleted) {
1073     unsigned int num = (end-start)+1;
1074     if (deleted) *deleted = num;
1075     zl = ziplistDeleteRange(zl,2*(start-1),2*num);
1076     return zl;
1077 }
1078 
1079 /*-----------------------------------------------------------------------------
1080  * Common sorted set API
1081  *----------------------------------------------------------------------------*/
1082 
1083 unsigned int zsetLength(robj *zobj) {
1084     int length = -1;
1085     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
1086         length = zzlLength(zobj->ptr);
1087     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
1088         length = ((zset*)zobj->ptr)->zsl->length;
1089     } else {
1090         redisPanic("Unknown sorted set encoding");
1091     }
1092     return length;
1093 }
1094 
1095 void zsetConvert(robj *zobj, int encoding) {
1096     zset *zs;
1097     zskiplistNode *node, *next;
1098     robj *ele;
1099     double score;
1100 
1101     if (zobj->encoding == encoding) return;
1102     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
1103         unsigned char *zl = zobj->ptr;
1104         unsigned char *eptr, *sptr;
1105         unsigned char *vstr;
1106         unsigned int vlen;
1107         long long vlong;
1108 
1109         if (encoding != REDIS_ENCODING_SKIPLIST)
1110             redisPanic("Unknown target encoding");
1111 
1112         zs = zmalloc(sizeof(*zs));
1113         zs->dict = dictCreate(&zsetDictType,NULL);
1114         zs->zsl = zslCreate();
1115 
1116         eptr = ziplistIndex(zl,0);
1117         redisAssertWithInfo(NULL,zobj,eptr != NULL);
1118         sptr = ziplistNext(zl,eptr);
1119         redisAssertWithInfo(NULL,zobj,sptr != NULL);
1120 
1121         while (eptr != NULL) {
1122             score = zzlGetScore(sptr);
1123             redisAssertWithInfo(NULL,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));
1124             if (vstr == NULL)
1125                 ele = createStringObjectFromLongLong(vlong);
1126             else
1127                 ele = createStringObject((char*)vstr,vlen);
1128 
1129             /* Has incremented refcount since it was just created. */
1130             node = zslInsert(zs->zsl,score,ele);
1131             redisAssertWithInfo(NULL,zobj,dictAdd(zs->dict,ele,&node->score) == DICT_OK);
1132             incrRefCount(ele); /* Added to dictionary. */
1133             zzlNext(zl,&eptr,&sptr);
1134         }
1135 
1136         zfree(zobj->ptr);
1137         zobj->ptr = zs;
1138         zobj->encoding = REDIS_ENCODING_SKIPLIST;
1139     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
1140         unsigned char *zl = ziplistNew();
1141 
1142         if (encoding != REDIS_ENCODING_ZIPLIST)
1143             redisPanic("Unknown target encoding");
1144 
1145         /* Approach similar to zslFree(), since we want to free the skiplist at
1146          * the same time as creating the ziplist. */
1147         zs = zobj->ptr;
1148         dictRelease(zs->dict);
1149         node = zs->zsl->header->level[0].forward;
1150         zfree(zs->zsl->header);
1151         zfree(zs->zsl);
1152 
1153         while (node) {
1154             ele = getDecodedObject(node->obj);
1155             zl = zzlInsertAt(zl,NULL,ele,node->score);
1156             decrRefCount(ele);
1157 
1158             next = node->level[0].forward;
1159             zslFreeNode(node);
1160             node = next;
1161         }
1162 
1163         zfree(zs);
1164         zobj->ptr = zl;
1165         zobj->encoding = REDIS_ENCODING_ZIPLIST;
1166     } else {
1167         redisPanic("Unknown sorted set encoding");
1168     }
1169 }
1170 
1171 /*-----------------------------------------------------------------------------
1172  * Sorted set commands
1173  *----------------------------------------------------------------------------*/
1174 
1175 /* This generic command implements both ZADD and ZINCRBY. */
1176 void zaddGenericCommand(redisClient *c, int incr) {
1177     static char *nanerr = "resulting score is not a number (NaN)";
1178     robj *key = c->argv[1];
1179     robj *ele;
1180     robj *zobj;
1181     robj *curobj;
1182     double score = 0, *scores = NULL, curscore = 0.0;
1183     int j, elements = (c->argc-2)/2;
1184     int added = 0, updated = 0;
1185 
1186     if (c->argc % 2) {
1187         addReply(c,shared.syntaxerr);
1188         return;
1189     }
1190 
1191     /* Start parsing all the scores, we need to emit any syntax error
1192      * before executing additions to the sorted set, as the command should
1193      * either execute fully or nothing at all. */
1194     scores = zmalloc(sizeof(double)*elements);
1195     for (j = 0; j < elements; j++) {
1196         if (getDoubleFromObjectOrReply(c,c->argv[2+j*2],&scores[j],NULL)
1197             != REDIS_OK) goto cleanup;
1198     }
1199 
1200     /* Lookup the key and create the sorted set if does not exist. */
1201     zobj = lookupKeyWrite(c->db,key);
1202     if (zobj == NULL) {
1203         if (server.zset_max_ziplist_entries == 0 ||
1204             server.zset_max_ziplist_value < sdslen(c->argv[3]->ptr))
1205         {
1206             zobj = createZsetObject();
1207         } else {
1208             zobj = createZsetZiplistObject();
1209         }
1210         dbAdd(c->db,key,zobj);
1211     } else {
1212         if (zobj->type != REDIS_ZSET) {
1213             addReply(c,shared.wrongtypeerr);
1214             goto cleanup;
1215         }
1216     }
1217 
1218     for (j = 0; j < elements; j++) {
1219         score = scores[j];
1220 
1221         if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
1222             unsigned char *eptr;
1223 
1224             /* Prefer non-encoded element when dealing with ziplists. */
1225             ele = c->argv[3+j*2];
1226             if ((eptr = zzlFind(zobj->ptr,ele,&curscore)) != NULL) {
1227                 if (incr) {
1228                     score += curscore;
1229                     if (isnan(score)) {
1230                         addReplyError(c,nanerr);
1231                         goto cleanup;
1232                     }
1233                 }
1234 
1235                 /* Remove and re-insert when score changed. */
1236                 if (score != curscore) {
1237                     zobj->ptr = zzlDelete(zobj->ptr,eptr);
1238                     zobj->ptr = zzlInsert(zobj->ptr,ele,score);
1239                     server.dirty++;
1240                     updated++;
1241                 }
1242             } else {
1243                 /* Optimize: check if the element is too large or the list
1244                  * becomes too long *before* executing zzlInsert. */
1245                 zobj->ptr = zzlInsert(zobj->ptr,ele,score);
1246                 if (zzlLength(zobj->ptr) > server.zset_max_ziplist_entries)
1247                     zsetConvert(zobj,REDIS_ENCODING_SKIPLIST);
1248                 if (sdslen(ele->ptr) > server.zset_max_ziplist_value)
1249                     zsetConvert(zobj,REDIS_ENCODING_SKIPLIST);
1250                 server.dirty++;
1251                 added++;
1252             }
1253         } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
1254             zset *zs = zobj->ptr;
1255             zskiplistNode *znode;
1256             dictEntry *de;
1257 
1258             ele = c->argv[3+j*2] = tryObjectEncoding(c->argv[3+j*2]);
1259             de = dictFind(zs->dict,ele);
1260             if (de != NULL) {
1261                 curobj = dictGetKey(de);
1262                 curscore = *(double*)dictGetVal(de);
1263 
1264                 if (incr) {
1265                     score += curscore;
1266                     if (isnan(score)) {
1267                         addReplyError(c,nanerr);
1268                         /* Don't need to check if the sorted set is empty
1269                          * because we know it has at least one element. */
1270                         goto cleanup;
1271                     }
1272                 }
1273 
1274                 /* Remove and re-insert when score changed. We can safely
1275                  * delete the key object from the skiplist, since the
1276                  * dictionary still has a reference to it. */
1277                 if (score != curscore) {
1278                     redisAssertWithInfo(c,curobj,zslDelete(zs->zsl,curscore,curobj));
1279                     znode = zslInsert(zs->zsl,score,curobj);
1280                     incrRefCount(curobj); /* Re-inserted in skiplist. */
1281                     dictGetVal(de) = &znode->score; /* Update score ptr. */
1282                     server.dirty++;
1283                     updated++;
1284                 }
1285             } else {
1286                 znode = zslInsert(zs->zsl,score,ele);
1287                 incrRefCount(ele); /* Inserted in skiplist. */
1288                 redisAssertWithInfo(c,NULL,dictAdd(zs->dict,ele,&znode->score) == DICT_OK);
1289                 incrRefCount(ele); /* Added to dictionary. */
1290                 server.dirty++;
1291                 added++;
1292             }
1293         } else {
1294             redisPanic("Unknown sorted set encoding");
1295         }
1296     }
1297     if (incr) /* ZINCRBY */
1298         addReplyDouble(c,score);
1299     else /* ZADD */
1300         addReplyLongLong(c,added);
1301 
1302 cleanup:
1303     zfree(scores);
1304     if (added || updated) {
1305         signalModifiedKey(c->db,key);
1306         notifyKeyspaceEvent(REDIS_NOTIFY_ZSET,
1307             incr ? "zincr" : "zadd", key, c->db->id);
1308     }
1309 }
1310 
1311 void zaddCommand(redisClient *c) {
1312     zaddGenericCommand(c,0);
1313 }
1314 
1315 void zincrbyCommand(redisClient *c) {
1316     zaddGenericCommand(c,1);
1317 }
1318 
1319 void zremCommand(redisClient *c) {
1320     robj *key = c->argv[1];
1321     robj *zobj;
1322     int deleted = 0, keyremoved = 0, j;
1323 
1324     if ((zobj = lookupKeyWriteOrReply(c,key,shared.czero)) == NULL ||
1325         checkType(c,zobj,REDIS_ZSET)) return;
1326 
1327     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
1328         unsigned char *eptr;
1329 
1330         for (j = 2; j < c->argc; j++) {
1331             if ((eptr = zzlFind(zobj->ptr,c->argv[j],NULL)) != NULL) {
1332                 deleted++;
1333                 zobj->ptr = zzlDelete(zobj->ptr,eptr);
1334                 if (zzlLength(zobj->ptr) == 0) {
1335                     dbDelete(c->db,key);
1336                     break;
1337                 }
1338             }
1339         }
1340     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
1341         zset *zs = zobj->ptr;
1342         dictEntry *de;
1343         double score;
1344 
1345         for (j = 2; j < c->argc; j++) {
1346             de = dictFind(zs->dict,c->argv[j]);
1347             if (de != NULL) {
1348                 deleted++;
1349 
1350                 /* Delete from the skiplist */
1351                 score = *(double*)dictGetVal(de);
1352                 redisAssertWithInfo(c,c->argv[j],zslDelete(zs->zsl,score,c->argv[j]));
1353 
1354                 /* Delete from the hash table */
1355                 dictDelete(zs->dict,c->argv[j]);
1356                 if (htNeedsResize(zs->dict)) dictResize(zs->dict);
1357                 if (dictSize(zs->dict) == 0) {
1358                     dbDelete(c->db,key);
1359                     break;
1360                 }
1361             }
1362         }
1363     } else {
1364         redisPanic("Unknown sorted set encoding");
1365     }
1366 
1367     if (deleted) {
1368         notifyKeyspaceEvent(REDIS_NOTIFY_ZSET,"zrem",key,c->db->id);
1369         if (keyremoved)
1370             notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"del",key,c->db->id);
1371         signalModifiedKey(c->db,key);
1372         server.dirty += deleted;
1373     }
1374     addReplyLongLong(c,deleted);
1375 }
1376 
1377 /* Implements ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZREMRANGEBYLEX commands. */
1378 #define ZRANGE_RANK 0
1379 #define ZRANGE_SCORE 1
1380 #define ZRANGE_LEX 2
1381 void zremrangeGenericCommand(redisClient *c, int rangetype) {
1382     robj *key = c->argv[1];
1383     robj *zobj;
1384     int keyremoved = 0;
1385     unsigned long deleted;
1386     zrangespec range;
1387     zlexrangespec lexrange;
1388     long start, end, llen;
1389 
1390     /* Step 1: Parse the range. */
1391     if (rangetype == ZRANGE_RANK) {
1392         if ((getLongFromObjectOrReply(c,c->argv[2],&start,NULL) != REDIS_OK) ||
1393             (getLongFromObjectOrReply(c,c->argv[3],&end,NULL) != REDIS_OK))
1394             return;
1395     } else if (rangetype == ZRANGE_SCORE) {
1396         if (zslParseRange(c->argv[2],c->argv[3],&range) != REDIS_OK) {
1397             addReplyError(c,"min or max is not a float");
1398             return;
1399         }
1400     } else if (rangetype == ZRANGE_LEX) {
1401         if (zslParseLexRange(c->argv[2],c->argv[3],&lexrange) != REDIS_OK) {
1402             addReplyError(c,"min or max not valid string range item");
1403             return;
1404         }
1405     }
1406 
1407     /* Step 2: Lookup & range sanity checks if needed. */
1408     if ((zobj = lookupKeyWriteOrReply(c,key,shared.czero)) == NULL ||
1409         checkType(c,zobj,REDIS_ZSET)) goto cleanup;
1410 
1411     if (rangetype == ZRANGE_RANK) {
1412         /* Sanitize indexes. */
1413         llen = zsetLength(zobj);
1414         if (start < 0) start = llen+start;
1415         if (end < 0) end = llen+end;
1416         if (start < 0) start = 0;
1417 
1418         /* Invariant: start >= 0, so this test will be true when end < 0.
1419          * The range is empty when start > end or start >= length. */
1420         if (start > end || start >= llen) {
1421             addReply(c,shared.czero);
1422             goto cleanup;
1423         }
1424         if (end >= llen) end = llen-1;
1425     }
1426 
1427     /* Step 3: Perform the range deletion operation. */
1428     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
1429         switch(rangetype) {
1430         case ZRANGE_RANK:
1431             zobj->ptr = zzlDeleteRangeByRank(zobj->ptr,start+1,end+1,&deleted);
1432             break;
1433         case ZRANGE_SCORE:
1434             zobj->ptr = zzlDeleteRangeByScore(zobj->ptr,&range,&deleted);
1435             break;
1436         case ZRANGE_LEX:
1437             zobj->ptr = zzlDeleteRangeByLex(zobj->ptr,&lexrange,&deleted);
1438             break;
1439         }
1440         if (zzlLength(zobj->ptr) == 0) {
1441             dbDelete(c->db,key);
1442             keyremoved = 1;
1443         }
1444     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
1445         zset *zs = zobj->ptr;
1446         switch(rangetype) {
1447         case ZRANGE_RANK:
1448             deleted = zslDeleteRangeByRank(zs->zsl,start+1,end+1,zs->dict);
1449             break;
1450         case ZRANGE_SCORE:
1451             deleted = zslDeleteRangeByScore(zs->zsl,&range,zs->dict);
1452             break;
1453         case ZRANGE_LEX:
1454             deleted = zslDeleteRangeByLex(zs->zsl,&lexrange,zs->dict);
1455             break;
1456         }
1457         if (htNeedsResize(zs->dict)) dictResize(zs->dict);
1458         if (dictSize(zs->dict) == 0) {
1459             dbDelete(c->db,key);
1460             keyremoved = 1;
1461         }
1462     } else {
1463         redisPanic("Unknown sorted set encoding");
1464     }
1465 
1466     /* Step 4: Notifications and reply. */
1467     if (deleted) {
1468         char *event[3] = {"zremrangebyrank","zremrangebyscore","zremrangebylex"};
1469         signalModifiedKey(c->db,key);
1470         notifyKeyspaceEvent(REDIS_NOTIFY_ZSET,event[rangetype],key,c->db->id);
1471         if (keyremoved)
1472             notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"del",key,c->db->id);
1473     }
1474     server.dirty += deleted;
1475     addReplyLongLong(c,deleted);
1476 
1477 cleanup:
1478     if (rangetype == ZRANGE_LEX) zslFreeLexRange(&lexrange);
1479 }
1480 
1481 void zremrangebyrankCommand(redisClient *c) {
1482     zremrangeGenericCommand(c,ZRANGE_RANK);
1483 }
1484 
1485 void zremrangebyscoreCommand(redisClient *c) {
1486     zremrangeGenericCommand(c,ZRANGE_SCORE);
1487 }
1488 
1489 void zremrangebylexCommand(redisClient *c) {
1490     zremrangeGenericCommand(c,ZRANGE_LEX);
1491 }
1492 
1493 typedef struct {
1494     robj *subject;
1495     int type; /* Set, sorted set */
1496     int encoding;
1497     double weight;
1498 
1499     union {
1500         /* Set iterators. */
1501         union _iterset {
1502             struct {
1503                 intset *is;
1504                 int ii;
1505             } is;
1506             struct {
1507                 dict *dict;
1508                 dictIterator *di;
1509                 dictEntry *de;
1510             } ht;
1511         } set;
1512 
1513         /* Sorted set iterators. */
1514         union _iterzset {
1515             struct {
1516                 unsigned char *zl;
1517                 unsigned char *eptr, *sptr;
1518             } zl;
1519             struct {
1520                 zset *zs;
1521                 zskiplistNode *node;
1522             } sl;
1523         } zset;
1524     } iter;
1525 } zsetopsrc;
1526 
1527 
1528 /* Use dirty flags for pointers that need to be cleaned up in the next
1529  * iteration over the zsetopval. The dirty flag for the long long value is
1530  * special, since long long values don't need cleanup. Instead, it means that
1531  * we already checked that "ell" holds a long long, or tried to convert another
1532  * representation into a long long value. When this was successful,
1533  * OPVAL_VALID_LL is set as well. */
1534 #define OPVAL_DIRTY_ROBJ 1
1535 #define OPVAL_DIRTY_LL 2
1536 #define OPVAL_VALID_LL 4
1537 
1538 /* Store value retrieved from the iterator. */
1539 typedef struct {
1540     int flags;
1541     unsigned char _buf[32]; /* Private buffer. */
1542     robj *ele;
1543     unsigned char *estr;
1544     unsigned int elen;
1545     long long ell;
1546     double score;
1547 } zsetopval;
1548 
1549 typedef union _iterset iterset;
1550 typedef union _iterzset iterzset;
1551 
1552 void zuiInitIterator(zsetopsrc *op) {
1553     if (op->subject == NULL)
1554         return;
1555 
1556     if (op->type == REDIS_SET) {
1557         iterset *it = &op->iter.set;
1558         if (op->encoding == REDIS_ENCODING_INTSET) {
1559             it->is.is = op->subject->ptr;
1560             it->is.ii = 0;
1561         } else if (op->encoding == REDIS_ENCODING_HT) {
1562             it->ht.dict = op->subject->ptr;
1563             it->ht.di = dictGetIterator(op->subject->ptr);
1564             it->ht.de = dictNext(it->ht.di);
1565         } else {
1566             redisPanic("Unknown set encoding");
1567         }
1568     } else if (op->type == REDIS_ZSET) {
1569         iterzset *it = &op->iter.zset;
1570         if (op->encoding == REDIS_ENCODING_ZIPLIST) {
1571             it->zl.zl = op->subject->ptr;
1572             it->zl.eptr = ziplistIndex(it->zl.zl,0);
1573             if (it->zl.eptr != NULL) {
1574                 it->zl.sptr = ziplistNext(it->zl.zl,it->zl.eptr);
1575                 redisAssert(it->zl.sptr != NULL);
1576             }
1577         } else if (op->encoding == REDIS_ENCODING_SKIPLIST) {
1578             it->sl.zs = op->subject->ptr;
1579             it->sl.node = it->sl.zs->zsl->header->level[0].forward;
1580         } else {
1581             redisPanic("Unknown sorted set encoding");
1582         }
1583     } else {
1584         redisPanic("Unsupported type");
1585     }
1586 }
1587 
1588 void zuiClearIterator(zsetopsrc *op) {
1589     if (op->subject == NULL)
1590         return;
1591 
1592     if (op->type == REDIS_SET) {
1593         iterset *it = &op->iter.set;
1594         if (op->encoding == REDIS_ENCODING_INTSET) {
1595             REDIS_NOTUSED(it); /* skip */
1596         } else if (op->encoding == REDIS_ENCODING_HT) {
1597             dictReleaseIterator(it->ht.di);
1598         } else {
1599             redisPanic("Unknown set encoding");
1600         }
1601     } else if (op->type == REDIS_ZSET) {
1602         iterzset *it = &op->iter.zset;
1603         if (op->encoding == REDIS_ENCODING_ZIPLIST) {
1604             REDIS_NOTUSED(it); /* skip */
1605         } else if (op->encoding == REDIS_ENCODING_SKIPLIST) {
1606             REDIS_NOTUSED(it); /* skip */
1607         } else {
1608             redisPanic("Unknown sorted set encoding");
1609         }
1610     } else {
1611         redisPanic("Unsupported type");
1612     }
1613 }
1614 
1615 int zuiLength(zsetopsrc *op) {
1616     if (op->subject == NULL)
1617         return 0;
1618 
1619     if (op->type == REDIS_SET) {
1620         if (op->encoding == REDIS_ENCODING_INTSET) {
1621             return intsetLen(op->subject->ptr);
1622         } else if (op->encoding == REDIS_ENCODING_HT) {
1623             dict *ht = op->subject->ptr;
1624             return dictSize(ht);
1625         } else {
1626             redisPanic("Unknown set encoding");
1627         }
1628     } else if (op->type == REDIS_ZSET) {
1629         if (op->encoding == REDIS_ENCODING_ZIPLIST) {
1630             return zzlLength(op->subject->ptr);
1631         } else if (op->encoding == REDIS_ENCODING_SKIPLIST) {
1632             zset *zs = op->subject->ptr;
1633             return zs->zsl->length;
1634         } else {
1635             redisPanic("Unknown sorted set encoding");
1636         }
1637     } else {
1638         redisPanic("Unsupported type");
1639     }
1640 }
1641 
1642 /* Check if the current value is valid. If so, store it in the passed structure
1643  * and move to the next element. If not valid, this means we have reached the
1644  * end of the structure and can abort. */
1645 int zuiNext(zsetopsrc *op, zsetopval *val) {
1646     if (op->subject == NULL)
1647         return 0;
1648 
1649     if (val->flags & OPVAL_DIRTY_ROBJ)
1650         decrRefCount(val->ele);
1651 
1652     memset(val,0,sizeof(zsetopval));
1653 
1654     if (op->type == REDIS_SET) {
1655         iterset *it = &op->iter.set;
1656         if (op->encoding == REDIS_ENCODING_INTSET) {
1657             int64_t ell;
1658 
1659             if (!intsetGet(it->is.is,it->is.ii,&ell))
1660                 return 0;
1661             val->ell = ell;
1662             val->score = 1.0;
1663 
1664             /* Move to next element. */
1665             it->is.ii++;
1666         } else if (op->encoding == REDIS_ENCODING_HT) {
1667             if (it->ht.de == NULL)
1668                 return 0;
1669             val->ele = dictGetKey(it->ht.de);
1670             val->score = 1.0;
1671 
1672             /* Move to next element. */
1673             it->ht.de = dictNext(it->ht.di);
1674         } else {
1675             redisPanic("Unknown set encoding");
1676         }
1677     } else if (op->type == REDIS_ZSET) {
1678         iterzset *it = &op->iter.zset;
1679         if (op->encoding == REDIS_ENCODING_ZIPLIST) {
1680             /* No need to check both, but better be explicit. */
1681             if (it->zl.eptr == NULL || it->zl.sptr == NULL)
1682                 return 0;
1683             redisAssert(ziplistGet(it->zl.eptr,&val->estr,&val->elen,&val->ell));
1684             val->score = zzlGetScore(it->zl.sptr);
1685 
1686             /* Move to next element. */
1687             zzlNext(it->zl.zl,&it->zl.eptr,&it->zl.sptr);
1688         } else if (op->encoding == REDIS_ENCODING_SKIPLIST) {
1689             if (it->sl.node == NULL)
1690                 return 0;
1691             val->ele = it->sl.node->obj;
1692             val->score = it->sl.node->score;
1693 
1694             /* Move to next element. */
1695             it->sl.node = it->sl.node->level[0].forward;
1696         } else {
1697             redisPanic("Unknown sorted set encoding");
1698         }
1699     } else {
1700         redisPanic("Unsupported type");
1701     }
1702     return 1;
1703 }
1704 
1705 int zuiLongLongFromValue(zsetopval *val) {
1706     if (!(val->flags & OPVAL_DIRTY_LL)) {
1707         val->flags |= OPVAL_DIRTY_LL;
1708 
1709         if (val->ele != NULL) {
1710             if (val->ele->encoding == REDIS_ENCODING_INT) {
1711                 val->ell = (long)val->ele->ptr;
1712                 val->flags |= OPVAL_VALID_LL;
1713             } else if (sdsEncodedObject(val->ele)) {
1714                 if (string2ll(val->ele->ptr,sdslen(val->ele->ptr),&val->ell))
1715                     val->flags |= OPVAL_VALID_LL;
1716             } else {
1717                 redisPanic("Unsupported element encoding");
1718             }
1719         } else if (val->estr != NULL) {
1720             if (string2ll((char*)val->estr,val->elen,&val->ell))
1721                 val->flags |= OPVAL_VALID_LL;
1722         } else {
1723             /* The long long was already set, flag as valid. */
1724             val->flags |= OPVAL_VALID_LL;
1725         }
1726     }
1727     return val->flags & OPVAL_VALID_LL;
1728 }
1729 
1730 robj *zuiObjectFromValue(zsetopval *val) {
1731     if (val->ele == NULL) {
1732         if (val->estr != NULL) {
1733             val->ele = createStringObject((char*)val->estr,val->elen);
1734         } else {
1735             val->ele = createStringObjectFromLongLong(val->ell);
1736         }
1737         val->flags |= OPVAL_DIRTY_ROBJ;
1738     }
1739     return val->ele;
1740 }
1741 
1742 int zuiBufferFromValue(zsetopval *val) {
1743     if (val->estr == NULL) {
1744         if (val->ele != NULL) {
1745             if (val->ele->encoding == REDIS_ENCODING_INT) {
1746                 val->elen = ll2string((char*)val->_buf,sizeof(val->_buf),(long)val->ele->ptr);
1747                 val->estr = val->_buf;
1748             } else if (sdsEncodedObject(val->ele)) {
1749                 val->elen = sdslen(val->ele->ptr);
1750                 val->estr = val->ele->ptr;
1751             } else {
1752                 redisPanic("Unsupported element encoding");
1753             }
1754         } else {
1755             val->elen = ll2string((char*)val->_buf,sizeof(val->_buf),val->ell);
1756             val->estr = val->_buf;
1757         }
1758     }
1759     return 1;
1760 }
1761 
1762 /* Find value pointed to by val in the source pointer to by op. When found,
1763  * return 1 and store its score in target. Return 0 otherwise. */
1764 int zuiFind(zsetopsrc *op, zsetopval *val, double *score) {
1765     if (op->subject == NULL)
1766         return 0;
1767 
1768     if (op->type == REDIS_SET) {
1769         if (op->encoding == REDIS_ENCODING_INTSET) {
1770             if (zuiLongLongFromValue(val) &&
1771                 intsetFind(op->subject->ptr,val->ell))
1772             {
1773                 *score = 1.0;
1774                 return 1;
1775             } else {
1776                 return 0;
1777             }
1778         } else if (op->encoding == REDIS_ENCODING_HT) {
1779             dict *ht = op->subject->ptr;
1780             zuiObjectFromValue(val);
1781             if (dictFind(ht,val->ele) != NULL) {
1782                 *score = 1.0;
1783                 return 1;
1784             } else {
1785                 return 0;
1786             }
1787         } else {
1788             redisPanic("Unknown set encoding");
1789         }
1790     } else if (op->type == REDIS_ZSET) {
1791         zuiObjectFromValue(val);
1792 
1793         if (op->encoding == REDIS_ENCODING_ZIPLIST) {
1794             if (zzlFind(op->subject->ptr,val->ele,score) != NULL) {
1795                 /* Score is already set by zzlFind. */
1796                 return 1;
1797             } else {
1798                 return 0;
1799             }
1800         } else if (op->encoding == REDIS_ENCODING_SKIPLIST) {
1801             zset *zs = op->subject->ptr;
1802             dictEntry *de;
1803             if ((de = dictFind(zs->dict,val->ele)) != NULL) {
1804                 *score = *(double*)dictGetVal(de);
1805                 return 1;
1806             } else {
1807                 return 0;
1808             }
1809         } else {
1810             redisPanic("Unknown sorted set encoding");
1811         }
1812     } else {
1813         redisPanic("Unsupported type");
1814     }
1815 }
1816 
1817 int zuiCompareByCardinality(const void *s1, const void *s2) {
1818     return zuiLength((zsetopsrc*)s1) - zuiLength((zsetopsrc*)s2);
1819 }
1820 
1821 #define REDIS_AGGR_SUM 1
1822 #define REDIS_AGGR_MIN 2
1823 #define REDIS_AGGR_MAX 3
1824 #define zunionInterDictValue(_e) (dictGetVal(_e) == NULL ? 1.0 : *(double*)dictGetVal(_e))
1825 
1826 inline static void zunionInterAggregate(double *target, double val, int aggregate) {
1827     if (aggregate == REDIS_AGGR_SUM) {
1828         *target = *target + val;
1829         /* The result of adding two doubles is NaN when one variable
1830          * is +inf and the other is -inf. When these numbers are added,
1831          * we maintain the convention of the result being 0.0. */
1832         if (isnan(*target)) *target = 0.0;
1833     } else if (aggregate == REDIS_AGGR_MIN) {
1834         *target = val < *target ? val : *target;
1835     } else if (aggregate == REDIS_AGGR_MAX) {
1836         *target = val > *target ? val : *target;
1837     } else {
1838         /* safety net */
1839         redisPanic("Unknown ZUNION/INTER aggregate type");
1840     }
1841 }
1842 
1843 void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
1844     int i, j;
1845     long setnum;
1846     int aggregate = REDIS_AGGR_SUM;
1847     zsetopsrc *src;
1848     zsetopval zval;
1849     robj *tmp;
1850     unsigned int maxelelen = 0;
1851     robj *dstobj;
1852     zset *dstzset;
1853     zskiplistNode *znode;
1854     int touched = 0;
1855 
1856     /* expect setnum input keys to be given */
1857     if ((getLongFromObjectOrReply(c, c->argv[2], &setnum, NULL) != REDIS_OK))
1858         return;
1859 
1860     if (setnum < 1) {
1861         addReplyError(c,
1862             "at least 1 input key is needed for ZUNIONSTORE/ZINTERSTORE");
1863         return;
1864     }
1865 
1866     /* test if the expected number of keys would overflow */
1867     if (setnum > c->argc-3) {
1868         addReply(c,shared.syntaxerr);
1869         return;
1870     }
1871 
1872     /* read keys to be used for input */
1873     src = zcalloc(sizeof(zsetopsrc) * setnum);
1874     for (i = 0, j = 3; i < setnum; i++, j++) {
1875         robj *obj = lookupKeyWrite(c->db,c->argv[j]);
1876         if (obj != NULL) {
1877             if (obj->type != REDIS_ZSET && obj->type != REDIS_SET) {
1878                 zfree(src);
1879                 addReply(c,shared.wrongtypeerr);
1880                 return;
1881             }
1882 
1883             src[i].subject = obj;
1884             src[i].type = obj->type;
1885             src[i].encoding = obj->encoding;
1886         } else {
1887             src[i].subject = NULL;
1888         }
1889 
1890         /* Default all weights to 1. */
1891         src[i].weight = 1.0;
1892     }
1893 
1894     /* parse optional extra arguments */
1895     if (j < c->argc) {
1896         int remaining = c->argc - j;
1897 
1898         while (remaining) {
1899             if (remaining >= (setnum + 1) && !strcasecmp(c->argv[j]->ptr,"weights")) {
1900                 j++; remaining--;
1901                 for (i = 0; i < setnum; i++, j++, remaining--) {
1902                     if (getDoubleFromObjectOrReply(c,c->argv[j],&src[i].weight,
1903                             "weight value is not a float") != REDIS_OK)
1904                     {
1905                         zfree(src);
1906                         return;
1907                     }
1908                 }
1909             } else if (remaining >= 2 && !strcasecmp(c->argv[j]->ptr,"aggregate")) {
1910                 j++; remaining--;
1911                 if (!strcasecmp(c->argv[j]->ptr,"sum")) {
1912                     aggregate = REDIS_AGGR_SUM;
1913                 } else if (!strcasecmp(c->argv[j]->ptr,"min")) {
1914                     aggregate = REDIS_AGGR_MIN;
1915                 } else if (!strcasecmp(c->argv[j]->ptr,"max")) {
1916                     aggregate = REDIS_AGGR_MAX;
1917                 } else {
1918                     zfree(src);
1919                     addReply(c,shared.syntaxerr);
1920                     return;
1921                 }
1922                 j++; remaining--;
1923             } else {
1924                 zfree(src);
1925                 addReply(c,shared.syntaxerr);
1926                 return;
1927             }
1928         }
1929     }
1930 
1931     /* sort sets from the smallest to largest, this will improve our
1932      * algorithm's performance */
1933     qsort(src,setnum,sizeof(zsetopsrc),zuiCompareByCardinality);
1934 
1935     dstobj = createZsetObject();
1936     dstzset = dstobj->ptr;
1937     memset(&zval, 0, sizeof(zval));
1938 
1939     if (op == REDIS_OP_INTER) {
1940         /* Skip everything if the smallest input is empty. */
1941         if (zuiLength(&src[0]) > 0) {
1942             /* Precondition: as src[0] is non-empty and the inputs are ordered
1943              * by size, all src[i > 0] are non-empty too. */
1944             zuiInitIterator(&src[0]);
1945             while (zuiNext(&src[0],&zval)) {
1946                 double score, value;
1947 
1948                 score = src[0].weight * zval.score;
1949                 if (isnan(score)) score = 0;
1950 
1951                 for (j = 1; j < setnum; j++) {
1952                     /* It is not safe to access the zset we are
1953                      * iterating, so explicitly check for equal object. */
1954                     if (src[j].subject == src[0].subject) {
1955                         value = zval.score*src[j].weight;
1956                         zunionInterAggregate(&score,value,aggregate);
1957                     } else if (zuiFind(&src[j],&zval,&value)) {
1958                         value *= src[j].weight;
1959                         zunionInterAggregate(&score,value,aggregate);
1960                     } else {
1961                         break;
1962                     }
1963                 }
1964 
1965                 /* Only continue when present in every input. */
1966                 if (j == setnum) {
1967                     tmp = zuiObjectFromValue(&zval);
1968                     znode = zslInsert(dstzset->zsl,score,tmp);
1969                     incrRefCount(tmp); /* added to skiplist */
1970                     dictAdd(dstzset->dict,tmp,&znode->score);
1971                     incrRefCount(tmp); /* added to dictionary */
1972 
1973                     if (sdsEncodedObject(tmp)) {
1974                         if (sdslen(tmp->ptr) > maxelelen)
1975                             maxelelen = sdslen(tmp->ptr);
1976                     }
1977                 }
1978             }
1979             zuiClearIterator(&src[0]);
1980         }
1981     } else if (op == REDIS_OP_UNION) {
1982         for (i = 0; i < setnum; i++) {
1983             if (zuiLength(&src[i]) == 0)
1984                 continue;
1985 
1986             zuiInitIterator(&src[i]);
1987             while (zuiNext(&src[i],&zval)) {
1988                 double score, value;
1989 
1990                 /* Skip an element that when already processed */
1991                 if (dictFind(dstzset->dict,zuiObjectFromValue(&zval)) != NULL)
1992                     continue;
1993 
1994                 /* Initialize score */
1995                 score = src[i].weight * zval.score;
1996                 if (isnan(score)) score = 0;
1997 
1998                 /* We need to check only next sets to see if this element
1999                  * exists, since we process every element just one time so
2000                  * it can't exist in a previous set (otherwise it would be
2001                  * already processed). */
2002                 for (j = (i+1); j < setnum; j++) {
2003                     /* It is not safe to access the zset we are
2004                      * iterating, so explicitly check for equal object. */
2005                     if(src[j].subject == src[i].subject) {
2006                         value = zval.score*src[j].weight;
2007                         zunionInterAggregate(&score,value,aggregate);
2008                     } else if (zuiFind(&src[j],&zval,&value)) {
2009                         value *= src[j].weight;
2010                         zunionInterAggregate(&score,value,aggregate);
2011                     }
2012                 }
2013 
2014                 tmp = zuiObjectFromValue(&zval);
2015                 znode = zslInsert(dstzset->zsl,score,tmp);
2016                 incrRefCount(zval.ele); /* added to skiplist */
2017                 dictAdd(dstzset->dict,tmp,&znode->score);
2018                 incrRefCount(zval.ele); /* added to dictionary */
2019 
2020                 if (sdsEncodedObject(tmp)) {
2021                     if (sdslen(tmp->ptr) > maxelelen)
2022                         maxelelen = sdslen(tmp->ptr);
2023                 }
2024             }
2025             zuiClearIterator(&src[i]);
2026         }
2027     } else {
2028         redisPanic("Unknown operator");
2029     }
2030 
2031     if (dbDelete(c->db,dstkey)) {
2032         signalModifiedKey(c->db,dstkey);
2033         touched = 1;
2034         server.dirty++;
2035     }
2036     if (dstzset->zsl->length) {
2037         /* Convert to ziplist when in limits. */
2038         if (dstzset->zsl->length <= server.zset_max_ziplist_entries &&
2039             maxelelen <= server.zset_max_ziplist_value)
2040                 zsetConvert(dstobj,REDIS_ENCODING_ZIPLIST);
2041 
2042         dbAdd(c->db,dstkey,dstobj);
2043         addReplyLongLong(c,zsetLength(dstobj));
2044         if (!touched) signalModifiedKey(c->db,dstkey);
2045         notifyKeyspaceEvent(REDIS_NOTIFY_ZSET,
2046             (op == REDIS_OP_UNION) ? "zunionstore" : "zinterstore",
2047             dstkey,c->db->id);
2048         server.dirty++;
2049     } else {
2050         decrRefCount(dstobj);
2051         addReply(c,shared.czero);
2052         if (touched)
2053             notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"del",dstkey,c->db->id);
2054     }
2055     zfree(src);
2056 }
2057 
2058 void zunionstoreCommand(redisClient *c) {
2059     zunionInterGenericCommand(c,c->argv[1], REDIS_OP_UNION);
2060 }
2061 
2062 void zinterstoreCommand(redisClient *c) {
2063     zunionInterGenericCommand(c,c->argv[1], REDIS_OP_INTER);
2064 }
2065 
2066 void zrangeGenericCommand(redisClient *c, int reverse) {
2067     robj *key = c->argv[1];
2068     robj *zobj;
2069     int withscores = 0;
2070     long start;
2071     long end;
2072     int llen;
2073     int rangelen;
2074 
2075     if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != REDIS_OK) ||
2076         (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != REDIS_OK)) return;
2077 
2078     if (c->argc == 5 && !strcasecmp(c->argv[4]->ptr,"withscores")) {
2079         withscores = 1;
2080     } else if (c->argc >= 5) {
2081         addReply(c,shared.syntaxerr);
2082         return;
2083     }
2084 
2085     if ((zobj = lookupKeyReadOrReply(c,key,shared.emptymultibulk)) == NULL
2086          || checkType(c,zobj,REDIS_ZSET)) return;
2087 
2088     /* Sanitize indexes. */
2089     llen = zsetLength(zobj);
2090     if (start < 0) start = llen+start;
2091     if (end < 0) end = llen+end;
2092     if (start < 0) start = 0;
2093 
2094     /* Invariant: start >= 0, so this test will be true when end < 0.
2095      * The range is empty when start > end or start >= length. */
2096     if (start > end || start >= llen) {
2097         addReply(c,shared.emptymultibulk);
2098         return;
2099     }
2100     if (end >= llen) end = llen-1;
2101     rangelen = (end-start)+1;
2102 
2103     /* Return the result in form of a multi-bulk reply */
2104     addReplyMultiBulkLen(c, withscores ? (rangelen*2) : rangelen);
2105 
2106     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2107         unsigned char *zl = zobj->ptr;
2108         unsigned char *eptr, *sptr;
2109         unsigned char *vstr;
2110         unsigned int vlen;
2111         long long vlong;
2112 
2113         if (reverse)
2114             eptr = ziplistIndex(zl,-2-(2*start));
2115         else
2116             eptr = ziplistIndex(zl,2*start);
2117 
2118         redisAssertWithInfo(c,zobj,eptr != NULL);
2119         sptr = ziplistNext(zl,eptr);
2120 
2121         while (rangelen--) {
2122             redisAssertWithInfo(c,zobj,eptr != NULL && sptr != NULL);
2123             redisAssertWithInfo(c,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));
2124             if (vstr == NULL)
2125                 addReplyBulkLongLong(c,vlong);
2126             else
2127                 addReplyBulkCBuffer(c,vstr,vlen);
2128 
2129             if (withscores)
2130                 addReplyDouble(c,zzlGetScore(sptr));
2131 
2132             if (reverse)
2133                 zzlPrev(zl,&eptr,&sptr);
2134             else
2135                 zzlNext(zl,&eptr,&sptr);
2136         }
2137 
2138     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2139         zset *zs = zobj->ptr;
2140         zskiplist *zsl = zs->zsl;
2141         zskiplistNode *ln;
2142         robj *ele;
2143 
2144         /* Check if starting point is trivial, before doing log(N) lookup. */
2145         if (reverse) {
2146             ln = zsl->tail;
2147             if (start > 0)
2148                 ln = zslGetElementByRank(zsl,llen-start);
2149         } else {
2150             ln = zsl->header->level[0].forward;
2151             if (start > 0)
2152                 ln = zslGetElementByRank(zsl,start+1);
2153         }
2154 
2155         while(rangelen--) {
2156             redisAssertWithInfo(c,zobj,ln != NULL);
2157             ele = ln->obj;
2158             addReplyBulk(c,ele);
2159             if (withscores)
2160                 addReplyDouble(c,ln->score);
2161             ln = reverse ? ln->backward : ln->level[0].forward;
2162         }
2163     } else {
2164         redisPanic("Unknown sorted set encoding");
2165     }
2166 }
2167 
2168 void zrangeCommand(redisClient *c) {
2169     zrangeGenericCommand(c,0);
2170 }
2171 
2172 void zrevrangeCommand(redisClient *c) {
2173     zrangeGenericCommand(c,1);
2174 }
2175 
2176 /* This command implements ZRANGEBYSCORE, ZREVRANGEBYSCORE. */
2177 void genericZrangebyscoreCommand(redisClient *c, int reverse) {
2178     zrangespec range;
2179     robj *key = c->argv[1];
2180     robj *zobj;
2181     long offset = 0, limit = -1;
2182     int withscores = 0;
2183     unsigned long rangelen = 0;
2184     void *replylen = NULL;
2185     int minidx, maxidx;
2186 
2187     /* Parse the range arguments. */
2188     if (reverse) {
2189         /* Range is given as [max,min] */
2190         maxidx = 2; minidx = 3;
2191     } else {
2192         /* Range is given as [min,max] */
2193         minidx = 2; maxidx = 3;
2194     }
2195 
2196     if (zslParseRange(c->argv[minidx],c->argv[maxidx],&range) != REDIS_OK) {
2197         addReplyError(c,"min or max is not a float");
2198         return;
2199     }
2200 
2201     /* Parse optional extra arguments. Note that ZCOUNT will exactly have
2202      * 4 arguments, so we'll never enter the following code path. */
2203     if (c->argc > 4) {
2204         int remaining = c->argc - 4;
2205         int pos = 4;
2206 
2207         while (remaining) {
2208             if (remaining >= 1 && !strcasecmp(c->argv[pos]->ptr,"withscores")) {
2209                 pos++; remaining--;
2210                 withscores = 1;
2211             } else if (remaining >= 3 && !strcasecmp(c->argv[pos]->ptr,"limit")) {
2212                 if ((getLongFromObjectOrReply(c, c->argv[pos+1], &offset, NULL) != REDIS_OK) ||
2213                     (getLongFromObjectOrReply(c, c->argv[pos+2], &limit, NULL) != REDIS_OK)) return;
2214                 pos += 3; remaining -= 3;
2215             } else {
2216                 addReply(c,shared.syntaxerr);
2217                 return;
2218             }
2219         }
2220     }
2221 
2222     /* Ok, lookup the key and get the range */
2223     if ((zobj = lookupKeyReadOrReply(c,key,shared.emptymultibulk)) == NULL ||
2224         checkType(c,zobj,REDIS_ZSET)) return;
2225 
2226     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2227         unsigned char *zl = zobj->ptr;
2228         unsigned char *eptr, *sptr;
2229         unsigned char *vstr;
2230         unsigned int vlen;
2231         long long vlong;
2232         double score;
2233 
2234         /* If reversed, get the last node in range as starting point. */
2235         if (reverse) {
2236             eptr = zzlLastInRange(zl,&range);
2237         } else {
2238             eptr = zzlFirstInRange(zl,&range);
2239         }
2240 
2241         /* No "first" element in the specified interval. */
2242         if (eptr == NULL) {
2243             addReply(c, shared.emptymultibulk);
2244             return;
2245         }
2246 
2247         /* Get score pointer for the first element. */
2248         redisAssertWithInfo(c,zobj,eptr != NULL);
2249         sptr = ziplistNext(zl,eptr);
2250 
2251         /* We don't know in advance how many matching elements there are in the
2252          * list, so we push this object that will represent the multi-bulk
2253          * length in the output buffer, and will "fix" it later */
2254         replylen = addDeferredMultiBulkLength(c);
2255 
2256         /* If there is an offset, just traverse the number of elements without
2257          * checking the score because that is done in the next loop. */
2258         while (eptr && offset--) {
2259             if (reverse) {
2260                 zzlPrev(zl,&eptr,&sptr);
2261             } else {
2262                 zzlNext(zl,&eptr,&sptr);
2263             }
2264         }
2265 
2266         while (eptr && limit--) {
2267             score = zzlGetScore(sptr);
2268 
2269             /* Abort when the node is no longer in range. */
2270             if (reverse) {
2271                 if (!zslValueGteMin(score,&range)) break;
2272             } else {
2273                 if (!zslValueLteMax(score,&range)) break;
2274             }
2275 
2276             /* We know the element exists, so ziplistGet should always succeed */
2277             redisAssertWithInfo(c,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));
2278 
2279             rangelen++;
2280             if (vstr == NULL) {
2281                 addReplyBulkLongLong(c,vlong);
2282             } else {
2283                 addReplyBulkCBuffer(c,vstr,vlen);
2284             }
2285 
2286             if (withscores) {
2287                 addReplyDouble(c,score);
2288             }
2289 
2290             /* Move to next node */
2291             if (reverse) {
2292                 zzlPrev(zl,&eptr,&sptr);
2293             } else {
2294                 zzlNext(zl,&eptr,&sptr);
2295             }
2296         }
2297     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2298         zset *zs = zobj->ptr;
2299         zskiplist *zsl = zs->zsl;
2300         zskiplistNode *ln;
2301 
2302         /* If reversed, get the last node in range as starting point. */
2303         if (reverse) {
2304             ln = zslLastInRange(zsl,&range);
2305         } else {
2306             ln = zslFirstInRange(zsl,&range);
2307         }
2308 
2309         /* No "first" element in the specified interval. */
2310         if (ln == NULL) {
2311             addReply(c, shared.emptymultibulk);
2312             return;
2313         }
2314 
2315         /* We don't know in advance how many matching elements there are in the
2316          * list, so we push this object that will represent the multi-bulk
2317          * length in the output buffer, and will "fix" it later */
2318         replylen = addDeferredMultiBulkLength(c);
2319 
2320         /* If there is an offset, just traverse the number of elements without
2321          * checking the score because that is done in the next loop. */
2322         while (ln && offset--) {
2323             if (reverse) {
2324                 ln = ln->backward;
2325             } else {
2326                 ln = ln->level[0].forward;
2327             }
2328         }
2329 
2330         while (ln && limit--) {
2331             /* Abort when the node is no longer in range. */
2332             if (reverse) {
2333                 if (!zslValueGteMin(ln->score,&range)) break;
2334             } else {
2335                 if (!zslValueLteMax(ln->score,&range)) break;
2336             }
2337 
2338             rangelen++;
2339             addReplyBulk(c,ln->obj);
2340 
2341             if (withscores) {
2342                 addReplyDouble(c,ln->score);
2343             }
2344 
2345             /* Move to next node */
2346             if (reverse) {
2347                 ln = ln->backward;
2348             } else {
2349                 ln = ln->level[0].forward;
2350             }
2351         }
2352     } else {
2353         redisPanic("Unknown sorted set encoding");
2354     }
2355 
2356     if (withscores) {
2357         rangelen *= 2;
2358     }
2359 
2360     setDeferredMultiBulkLength(c, replylen, rangelen);
2361 }
2362 
2363 void zrangebyscoreCommand(redisClient *c) {
2364     genericZrangebyscoreCommand(c,0);
2365 }
2366 
2367 void zrevrangebyscoreCommand(redisClient *c) {
2368     genericZrangebyscoreCommand(c,1);
2369 }
2370 
2371 void zcountCommand(redisClient *c) {
2372     robj *key = c->argv[1];
2373     robj *zobj;
2374     zrangespec range;
2375     int count = 0;
2376 
2377     /* Parse the range arguments */
2378     if (zslParseRange(c->argv[2],c->argv[3],&range) != REDIS_OK) {
2379         addReplyError(c,"min or max is not a float");
2380         return;
2381     }
2382 
2383     /* Lookup the sorted set */
2384     if ((zobj = lookupKeyReadOrReply(c, key, shared.czero)) == NULL ||
2385         checkType(c, zobj, REDIS_ZSET)) return;
2386 
2387     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2388         unsigned char *zl = zobj->ptr;
2389         unsigned char *eptr, *sptr;
2390         double score;
2391 
2392         /* Use the first element in range as the starting point */
2393         eptr = zzlFirstInRange(zl,&range);
2394 
2395         /* No "first" element */
2396         if (eptr == NULL) {
2397             addReply(c, shared.czero);
2398             return;
2399         }
2400 
2401         /* First element is in range */
2402         sptr = ziplistNext(zl,eptr);
2403         score = zzlGetScore(sptr);
2404         redisAssertWithInfo(c,zobj,zslValueLteMax(score,&range));
2405 
2406         /* Iterate over elements in range */
2407         while (eptr) {
2408             score = zzlGetScore(sptr);
2409 
2410             /* Abort when the node is no longer in range. */
2411             if (!zslValueLteMax(score,&range)) {
2412                 break;
2413             } else {
2414                 count++;
2415                 zzlNext(zl,&eptr,&sptr);
2416             }
2417         }
2418     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2419         zset *zs = zobj->ptr;
2420         zskiplist *zsl = zs->zsl;
2421         zskiplistNode *zn;
2422         unsigned long rank;
2423 
2424         /* Find first element in range */
2425         zn = zslFirstInRange(zsl, &range);
2426 
2427         /* Use rank of first element, if any, to determine preliminary count */
2428         if (zn != NULL) {
2429             rank = zslGetRank(zsl, zn->score, zn->obj);
2430             count = (zsl->length - (rank - 1));
2431 
2432             /* Find last element in range */
2433             zn = zslLastInRange(zsl, &range);
2434 
2435             /* Use rank of last element, if any, to determine the actual count */
2436             if (zn != NULL) {
2437                 rank = zslGetRank(zsl, zn->score, zn->obj);
2438                 count -= (zsl->length - rank);
2439             }
2440         }
2441     } else {
2442         redisPanic("Unknown sorted set encoding");
2443     }
2444 
2445     addReplyLongLong(c, count);
2446 }
2447 
2448 void zlexcountCommand(redisClient *c) {
2449     robj *key = c->argv[1];
2450     robj *zobj;
2451     zlexrangespec range;
2452     int count = 0;
2453 
2454     /* Parse the range arguments */
2455     if (zslParseLexRange(c->argv[2],c->argv[3],&range) != REDIS_OK) {
2456         addReplyError(c,"min or max not valid string range item");
2457         return;
2458     }
2459 
2460     /* Lookup the sorted set */
2461     if ((zobj = lookupKeyReadOrReply(c, key, shared.czero)) == NULL ||
2462         checkType(c, zobj, REDIS_ZSET))
2463     {
2464         zslFreeLexRange(&range);
2465         return;
2466     }
2467 
2468     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2469         unsigned char *zl = zobj->ptr;
2470         unsigned char *eptr, *sptr;
2471 
2472         /* Use the first element in range as the starting point */
2473         eptr = zzlFirstInLexRange(zl,&range);
2474 
2475         /* No "first" element */
2476         if (eptr == NULL) {
2477             zslFreeLexRange(&range);
2478             addReply(c, shared.czero);
2479             return;
2480         }
2481 
2482         /* First element is in range */
2483         sptr = ziplistNext(zl,eptr);
2484         redisAssertWithInfo(c,zobj,zzlLexValueLteMax(eptr,&range));
2485 
2486         /* Iterate over elements in range */
2487         while (eptr) {
2488             /* Abort when the node is no longer in range. */
2489             if (!zzlLexValueLteMax(eptr,&range)) {
2490                 break;
2491             } else {
2492                 count++;
2493                 zzlNext(zl,&eptr,&sptr);
2494             }
2495         }
2496     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2497         zset *zs = zobj->ptr;
2498         zskiplist *zsl = zs->zsl;
2499         zskiplistNode *zn;
2500         unsigned long rank;
2501 
2502         /* Find first element in range */
2503         zn = zslFirstInLexRange(zsl, &range);
2504 
2505         /* Use rank of first element, if any, to determine preliminary count */
2506         if (zn != NULL) {
2507             rank = zslGetRank(zsl, zn->score, zn->obj);
2508             count = (zsl->length - (rank - 1));
2509 
2510             /* Find last element in range */
2511             zn = zslLastInLexRange(zsl, &range);
2512 
2513             /* Use rank of last element, if any, to determine the actual count */
2514             if (zn != NULL) {
2515                 rank = zslGetRank(zsl, zn->score, zn->obj);
2516                 count -= (zsl->length - rank);
2517             }
2518         }
2519     } else {
2520         redisPanic("Unknown sorted set encoding");
2521     }
2522 
2523     zslFreeLexRange(&range);
2524     addReplyLongLong(c, count);
2525 }
2526 
2527 /* This command implements ZRANGEBYLEX, ZREVRANGEBYLEX. */
2528 void genericZrangebylexCommand(redisClient *c, int reverse) {
2529     zlexrangespec range;
2530     robj *key = c->argv[1];
2531     robj *zobj;
2532     long offset = 0, limit = -1;
2533     unsigned long rangelen = 0;
2534     void *replylen = NULL;
2535     int minidx, maxidx;
2536 
2537     /* Parse the range arguments. */
2538     if (reverse) {
2539         /* Range is given as [max,min] */
2540         maxidx = 2; minidx = 3;
2541     } else {
2542         /* Range is given as [min,max] */
2543         minidx = 2; maxidx = 3;
2544     }
2545 
2546     if (zslParseLexRange(c->argv[minidx],c->argv[maxidx],&range) != REDIS_OK) {
2547         addReplyError(c,"min or max not valid string range item");
2548         return;
2549     }
2550 
2551     /* Parse optional extra arguments. Note that ZCOUNT will exactly have
2552      * 4 arguments, so we'll never enter the following code path. */
2553     if (c->argc > 4) {
2554         int remaining = c->argc - 4;
2555         int pos = 4;
2556 
2557         while (remaining) {
2558             if (remaining >= 3 && !strcasecmp(c->argv[pos]->ptr,"limit")) {
2559                 if ((getLongFromObjectOrReply(c, c->argv[pos+1], &offset, NULL) != REDIS_OK) ||
2560                     (getLongFromObjectOrReply(c, c->argv[pos+2], &limit, NULL) != REDIS_OK)) return;
2561                 pos += 3; remaining -= 3;
2562             } else {
2563                 zslFreeLexRange(&range);
2564                 addReply(c,shared.syntaxerr);
2565                 return;
2566             }
2567         }
2568     }
2569 
2570     /* Ok, lookup the key and get the range */
2571     if ((zobj = lookupKeyReadOrReply(c,key,shared.emptymultibulk)) == NULL ||
2572         checkType(c,zobj,REDIS_ZSET))
2573     {
2574         zslFreeLexRange(&range);
2575         return;
2576     }
2577 
2578     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2579         unsigned char *zl = zobj->ptr;
2580         unsigned char *eptr, *sptr;
2581         unsigned char *vstr;
2582         unsigned int vlen;
2583         long long vlong;
2584 
2585         /* If reversed, get the last node in range as starting point. */
2586         if (reverse) {
2587             eptr = zzlLastInLexRange(zl,&range);
2588         } else {
2589             eptr = zzlFirstInLexRange(zl,&range);
2590         }
2591 
2592         /* No "first" element in the specified interval. */
2593         if (eptr == NULL) {
2594             addReply(c, shared.emptymultibulk);
2595             zslFreeLexRange(&range);
2596             return;
2597         }
2598 
2599         /* Get score pointer for the first element. */
2600         redisAssertWithInfo(c,zobj,eptr != NULL);
2601         sptr = ziplistNext(zl,eptr);
2602 
2603         /* We don't know in advance how many matching elements there are in the
2604          * list, so we push this object that will represent the multi-bulk
2605          * length in the output buffer, and will "fix" it later */
2606         replylen = addDeferredMultiBulkLength(c);
2607 
2608         /* If there is an offset, just traverse the number of elements without
2609          * checking the score because that is done in the next loop. */
2610         while (eptr && offset--) {
2611             if (reverse) {
2612                 zzlPrev(zl,&eptr,&sptr);
2613             } else {
2614                 zzlNext(zl,&eptr,&sptr);
2615             }
2616         }
2617 
2618         while (eptr && limit--) {
2619             /* Abort when the node is no longer in range. */
2620             if (reverse) {
2621                 if (!zzlLexValueGteMin(eptr,&range)) break;
2622             } else {
2623                 if (!zzlLexValueLteMax(eptr,&range)) break;
2624             }
2625 
2626             /* We know the element exists, so ziplistGet should always
2627              * succeed. */
2628             redisAssertWithInfo(c,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));
2629 
2630             rangelen++;
2631             if (vstr == NULL) {
2632                 addReplyBulkLongLong(c,vlong);
2633             } else {
2634                 addReplyBulkCBuffer(c,vstr,vlen);
2635             }
2636 
2637             /* Move to next node */
2638             if (reverse) {
2639                 zzlPrev(zl,&eptr,&sptr);
2640             } else {
2641                 zzlNext(zl,&eptr,&sptr);
2642             }
2643         }
2644     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2645         zset *zs = zobj->ptr;
2646         zskiplist *zsl = zs->zsl;
2647         zskiplistNode *ln;
2648 
2649         /* If reversed, get the last node in range as starting point. */
2650         if (reverse) {
2651             ln = zslLastInLexRange(zsl,&range);
2652         } else {
2653             ln = zslFirstInLexRange(zsl,&range);
2654         }
2655 
2656         /* No "first" element in the specified interval. */
2657         if (ln == NULL) {
2658             addReply(c, shared.emptymultibulk);
2659             zslFreeLexRange(&range);
2660             return;
2661         }
2662 
2663         /* We don't know in advance how many matching elements there are in the
2664          * list, so we push this object that will represent the multi-bulk
2665          * length in the output buffer, and will "fix" it later */
2666         replylen = addDeferredMultiBulkLength(c);
2667 
2668         /* If there is an offset, just traverse the number of elements without
2669          * checking the score because that is done in the next loop. */
2670         while (ln && offset--) {
2671             if (reverse) {
2672                 ln = ln->backward;
2673             } else {
2674                 ln = ln->level[0].forward;
2675             }
2676         }
2677 
2678         while (ln && limit--) {
2679             /* Abort when the node is no longer in range. */
2680             if (reverse) {
2681                 if (!zslLexValueGteMin(ln->obj,&range)) break;
2682             } else {
2683                 if (!zslLexValueLteMax(ln->obj,&range)) break;
2684             }
2685 
2686             rangelen++;
2687             addReplyBulk(c,ln->obj);
2688 
2689             /* Move to next node */
2690             if (reverse) {
2691                 ln = ln->backward;
2692             } else {
2693                 ln = ln->level[0].forward;
2694             }
2695         }
2696     } else {
2697         redisPanic("Unknown sorted set encoding");
2698     }
2699 
2700     zslFreeLexRange(&range);
2701     setDeferredMultiBulkLength(c, replylen, rangelen);
2702 }
2703 
2704 void zrangebylexCommand(redisClient *c) {
2705     genericZrangebylexCommand(c,0);
2706 }
2707 
2708 void zrevrangebylexCommand(redisClient *c) {
2709     genericZrangebylexCommand(c,1);
2710 }
2711 
2712 void zcardCommand(redisClient *c) {
2713     robj *key = c->argv[1];
2714     robj *zobj;
2715 
2716     if ((zobj = lookupKeyReadOrReply(c,key,shared.czero)) == NULL ||
2717         checkType(c,zobj,REDIS_ZSET)) return;
2718 
2719     addReplyLongLong(c,zsetLength(zobj));
2720 }
2721 
2722 void zscoreCommand(redisClient *c) {
2723     robj *key = c->argv[1];
2724     robj *zobj;
2725     double score;
2726 
2727     if ((zobj = lookupKeyReadOrReply(c,key,shared.nullbulk)) == NULL ||
2728         checkType(c,zobj,REDIS_ZSET)) return;
2729 
2730     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2731         if (zzlFind(zobj->ptr,c->argv[2],&score) != NULL)
2732             addReplyDouble(c,score);
2733         else
2734             addReply(c,shared.nullbulk);
2735     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2736         zset *zs = zobj->ptr;
2737         dictEntry *de;
2738 
2739         c->argv[2] = tryObjectEncoding(c->argv[2]);
2740         de = dictFind(zs->dict,c->argv[2]);
2741         if (de != NULL) {
2742             score = *(double*)dictGetVal(de);
2743             addReplyDouble(c,score);
2744         } else {
2745             addReply(c,shared.nullbulk);
2746         }
2747     } else {
2748         redisPanic("Unknown sorted set encoding");
2749     }
2750 }
2751 
2752 void zrankGenericCommand(redisClient *c, int reverse) {
2753     robj *key = c->argv[1];
2754     robj *ele = c->argv[2];
2755     robj *zobj;
2756     unsigned long llen;
2757     unsigned long rank;
2758 
2759     if ((zobj = lookupKeyReadOrReply(c,key,shared.nullbulk)) == NULL ||
2760         checkType(c,zobj,REDIS_ZSET)) return;
2761     llen = zsetLength(zobj);
2762 
2763     redisAssertWithInfo(c,ele,sdsEncodedObject(ele));
2764 
2765     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2766         unsigned char *zl = zobj->ptr;
2767         unsigned char *eptr, *sptr;
2768 
2769         eptr = ziplistIndex(zl,0);
2770         redisAssertWithInfo(c,zobj,eptr != NULL);
2771         sptr = ziplistNext(zl,eptr);
2772         redisAssertWithInfo(c,zobj,sptr != NULL);
2773 
2774         rank = 1;
2775         while(eptr != NULL) {
2776             if (ziplistCompare(eptr,ele->ptr,sdslen(ele->ptr)))
2777                 break;
2778             rank++;
2779             zzlNext(zl,&eptr,&sptr);
2780         }
2781 
2782         if (eptr != NULL) {
2783             if (reverse)
2784                 addReplyLongLong(c,llen-rank);
2785             else
2786                 addReplyLongLong(c,rank-1);
2787         } else {
2788             addReply(c,shared.nullbulk);
2789         }
2790     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2791         zset *zs = zobj->ptr;
2792         zskiplist *zsl = zs->zsl;
2793         dictEntry *de;
2794         double score;
2795 
2796         ele = c->argv[2] = tryObjectEncoding(c->argv[2]);
2797         de = dictFind(zs->dict,ele);
2798         if (de != NULL) {
2799             score = *(double*)dictGetVal(de);
2800             rank = zslGetRank(zsl,score,ele);
2801             redisAssertWithInfo(c,ele,rank); /* Existing elements always have a rank. */
2802             if (reverse)
2803                 addReplyLongLong(c,llen-rank);
2804             else
2805                 addReplyLongLong(c,rank-1);
2806         } else {
2807             addReply(c,shared.nullbulk);
2808         }
2809     } else {
2810         redisPanic("Unknown sorted set encoding");
2811     }
2812 }
2813 
2814 void zrankCommand(redisClient *c) {
2815     zrankGenericCommand(c, 0);
2816 }
2817 
2818 void zrevrankCommand(redisClient *c) {
2819     zrankGenericCommand(c, 1);
2820 }
2821 
2822 void zscanCommand(redisClient *c) {
2823     robj *o;
2824     unsigned long cursor;
2825 
2826     if (parseScanCursorOrReply(c,c->argv[2],&cursor) == REDIS_ERR) return;
2827     if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == NULL ||
2828         checkType(c,o,REDIS_ZSET)) return;
2829     scanGenericCommand(c,o,cursor);
2830 }
2831