xref: /redis-3.2.3/src/t_zset.c (revision 3064e9bd)
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     }
209     return 0; /* not found */
210 }
211 
212 static int zslValueGteMin(double value, zrangespec *spec) {
213     return spec->minex ? (value > spec->min) : (value >= spec->min);
214 }
215 
216 static int zslValueLteMax(double value, zrangespec *spec) {
217     return spec->maxex ? (value < spec->max) : (value <= spec->max);
218 }
219 
220 /* Returns if there is a part of the zset is in range. */
221 int zslIsInRange(zskiplist *zsl, zrangespec *range) {
222     zskiplistNode *x;
223 
224     /* Test for ranges that will always be empty. */
225     if (range->min > range->max ||
226             (range->min == range->max && (range->minex || range->maxex)))
227         return 0;
228     x = zsl->tail;
229     if (x == NULL || !zslValueGteMin(x->score,range))
230         return 0;
231     x = zsl->header->level[0].forward;
232     if (x == NULL || !zslValueLteMax(x->score,range))
233         return 0;
234     return 1;
235 }
236 
237 /* Find the first node that is contained in the specified range.
238  * Returns NULL when no element is contained in the range. */
239 zskiplistNode *zslFirstInRange(zskiplist *zsl, zrangespec *range) {
240     zskiplistNode *x;
241     int i;
242 
243     /* If everything is out of range, return early. */
244     if (!zslIsInRange(zsl,range)) return NULL;
245 
246     x = zsl->header;
247     for (i = zsl->level-1; i >= 0; i--) {
248         /* Go forward while *OUT* of range. */
249         while (x->level[i].forward &&
250             !zslValueGteMin(x->level[i].forward->score,range))
251                 x = x->level[i].forward;
252     }
253 
254     /* This is an inner range, so the next node cannot be NULL. */
255     x = x->level[0].forward;
256     redisAssert(x != NULL);
257 
258     /* Check if score <= max. */
259     if (!zslValueLteMax(x->score,range)) return NULL;
260     return x;
261 }
262 
263 /* Find the last node that is contained in the specified range.
264  * Returns NULL when no element is contained in the range. */
265 zskiplistNode *zslLastInRange(zskiplist *zsl, zrangespec *range) {
266     zskiplistNode *x;
267     int i;
268 
269     /* If everything is out of range, return early. */
270     if (!zslIsInRange(zsl,range)) return NULL;
271 
272     x = zsl->header;
273     for (i = zsl->level-1; i >= 0; i--) {
274         /* Go forward while *IN* range. */
275         while (x->level[i].forward &&
276             zslValueLteMax(x->level[i].forward->score,range))
277                 x = x->level[i].forward;
278     }
279 
280     /* This is an inner range, so this node cannot be NULL. */
281     redisAssert(x != NULL);
282 
283     /* Check if score >= min. */
284     if (!zslValueGteMin(x->score,range)) return NULL;
285     return x;
286 }
287 
288 /* Delete all the elements with score between min and max from the skiplist.
289  * Min and max are inclusive, so a score >= min || score <= max is deleted.
290  * Note that this function takes the reference to the hash table view of the
291  * sorted set, in order to remove the elements from the hash table too. */
292 unsigned long zslDeleteRangeByScore(zskiplist *zsl, zrangespec *range, dict *dict) {
293     zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
294     unsigned long removed = 0;
295     int i;
296 
297     x = zsl->header;
298     for (i = zsl->level-1; i >= 0; i--) {
299         while (x->level[i].forward && (range->minex ?
300             x->level[i].forward->score <= range->min :
301             x->level[i].forward->score < range->min))
302                 x = x->level[i].forward;
303         update[i] = x;
304     }
305 
306     /* Current node is the last with score < or <= min. */
307     x = x->level[0].forward;
308 
309     /* Delete nodes while in range. */
310     while (x &&
311            (range->maxex ? x->score < range->max : x->score <= range->max))
312     {
313         zskiplistNode *next = x->level[0].forward;
314         zslDeleteNode(zsl,x,update);
315         dictDelete(dict,x->obj);
316         zslFreeNode(x);
317         removed++;
318         x = next;
319     }
320     return removed;
321 }
322 
323 unsigned long zslDeleteRangeByLex(zskiplist *zsl, zlexrangespec *range, dict *dict) {
324     zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
325     unsigned long removed = 0;
326     int i;
327 
328 
329     x = zsl->header;
330     for (i = zsl->level-1; i >= 0; i--) {
331         while (x->level[i].forward &&
332             !zslLexValueGteMin(x->level[i].forward->obj,range))
333                 x = x->level[i].forward;
334         update[i] = x;
335     }
336 
337     /* Current node is the last with score < or <= min. */
338     x = x->level[0].forward;
339 
340     /* Delete nodes while in range. */
341     while (x && zslLexValueLteMax(x->obj,range)) {
342         zskiplistNode *next = x->level[0].forward;
343         zslDeleteNode(zsl,x,update);
344         dictDelete(dict,x->obj);
345         zslFreeNode(x);
346         removed++;
347         x = next;
348     }
349     return removed;
350 }
351 
352 /* Delete all the elements with rank between start and end from the skiplist.
353  * Start and end are inclusive. Note that start and end need to be 1-based */
354 unsigned long zslDeleteRangeByRank(zskiplist *zsl, unsigned int start, unsigned int end, dict *dict) {
355     zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
356     unsigned long traversed = 0, removed = 0;
357     int i;
358 
359     x = zsl->header;
360     for (i = zsl->level-1; i >= 0; i--) {
361         while (x->level[i].forward && (traversed + x->level[i].span) < start) {
362             traversed += x->level[i].span;
363             x = x->level[i].forward;
364         }
365         update[i] = x;
366     }
367 
368     traversed++;
369     x = x->level[0].forward;
370     while (x && traversed <= end) {
371         zskiplistNode *next = x->level[0].forward;
372         zslDeleteNode(zsl,x,update);
373         dictDelete(dict,x->obj);
374         zslFreeNode(x);
375         removed++;
376         traversed++;
377         x = next;
378     }
379     return removed;
380 }
381 
382 /* Find the rank for an element by both score and key.
383  * Returns 0 when the element cannot be found, rank otherwise.
384  * Note that the rank is 1-based due to the span of zsl->header to the
385  * first element. */
386 unsigned long zslGetRank(zskiplist *zsl, double score, robj *o) {
387     zskiplistNode *x;
388     unsigned long rank = 0;
389     int i;
390 
391     x = zsl->header;
392     for (i = zsl->level-1; i >= 0; i--) {
393         while (x->level[i].forward &&
394             (x->level[i].forward->score < score ||
395                 (x->level[i].forward->score == score &&
396                 compareStringObjects(x->level[i].forward->obj,o) <= 0))) {
397             rank += x->level[i].span;
398             x = x->level[i].forward;
399         }
400 
401         /* x might be equal to zsl->header, so test if obj is non-NULL */
402         if (x->obj && equalStringObjects(x->obj,o)) {
403             return rank;
404         }
405     }
406     return 0;
407 }
408 
409 /* Finds an element by its rank. The rank argument needs to be 1-based. */
410 zskiplistNode* zslGetElementByRank(zskiplist *zsl, unsigned long rank) {
411     zskiplistNode *x;
412     unsigned long traversed = 0;
413     int i;
414 
415     x = zsl->header;
416     for (i = zsl->level-1; i >= 0; i--) {
417         while (x->level[i].forward && (traversed + x->level[i].span) <= rank)
418         {
419             traversed += x->level[i].span;
420             x = x->level[i].forward;
421         }
422         if (traversed == rank) {
423             return x;
424         }
425     }
426     return NULL;
427 }
428 
429 /* Populate the rangespec according to the objects min and max. */
430 static int zslParseRange(robj *min, robj *max, zrangespec *spec) {
431     char *eptr;
432     spec->minex = spec->maxex = 0;
433 
434     /* Parse the min-max interval. If one of the values is prefixed
435      * by the "(" character, it's considered "open". For instance
436      * ZRANGEBYSCORE zset (1.5 (2.5 will match min < x < max
437      * ZRANGEBYSCORE zset 1.5 2.5 will instead match min <= x <= max */
438     if (min->encoding == REDIS_ENCODING_INT) {
439         spec->min = (long)min->ptr;
440     } else {
441         if (((char*)min->ptr)[0] == '(') {
442             spec->min = strtod((char*)min->ptr+1,&eptr);
443             if (eptr[0] != '\0' || isnan(spec->min)) return REDIS_ERR;
444             spec->minex = 1;
445         } else {
446             spec->min = strtod((char*)min->ptr,&eptr);
447             if (eptr[0] != '\0' || isnan(spec->min)) return REDIS_ERR;
448         }
449     }
450     if (max->encoding == REDIS_ENCODING_INT) {
451         spec->max = (long)max->ptr;
452     } else {
453         if (((char*)max->ptr)[0] == '(') {
454             spec->max = strtod((char*)max->ptr+1,&eptr);
455             if (eptr[0] != '\0' || isnan(spec->max)) return REDIS_ERR;
456             spec->maxex = 1;
457         } else {
458             spec->max = strtod((char*)max->ptr,&eptr);
459             if (eptr[0] != '\0' || isnan(spec->max)) return REDIS_ERR;
460         }
461     }
462 
463     return REDIS_OK;
464 }
465 
466 /* ------------------------ Lexicographic ranges ---------------------------- */
467 
468 /* Parse max or min argument of ZRANGEBYLEX.
469   * (foo means foo (open interval)
470   * [foo means foo (closed interval)
471   * - means the min string possible
472   * + means the max string possible
473   *
474   * If the string is valid the *dest pointer is set to the redis object
475   * that will be used for the comparision, and ex will be set to 0 or 1
476   * respectively if the item is exclusive or inclusive. REDIS_OK will be
477   * returned.
478   *
479   * If the string is not a valid range REDIS_ERR is returned, and the value
480   * of *dest and *ex is undefined. */
481 int zslParseLexRangeItem(robj *item, robj **dest, int *ex) {
482     char *c = item->ptr;
483 
484     switch(c[0]) {
485     case '+':
486         if (c[1] != '\0') return REDIS_ERR;
487         *ex = 0;
488         *dest = shared.maxstring;
489         incrRefCount(shared.maxstring);
490         return REDIS_OK;
491     case '-':
492         if (c[1] != '\0') return REDIS_ERR;
493         *ex = 0;
494         *dest = shared.minstring;
495         incrRefCount(shared.minstring);
496         return REDIS_OK;
497     case '(':
498         *ex = 1;
499         *dest = createStringObject(c+1,sdslen(c)-1);
500         return REDIS_OK;
501     case '[':
502         *ex = 0;
503         *dest = createStringObject(c+1,sdslen(c)-1);
504         return REDIS_OK;
505     default:
506         return REDIS_ERR;
507     }
508 }
509 
510 /* Populate the rangespec according to the objects min and max.
511  *
512  * Return REDIS_OK on success. On error REDIS_ERR is returned.
513  * When OK is returned the structure must be freed with zslFreeLexRange(),
514  * otherwise no release is needed. */
515 static int zslParseLexRange(robj *min, robj *max, zlexrangespec *spec) {
516     /* The range can't be valid if objects are integer encoded.
517      * Every item must start with ( or [. */
518     if (min->encoding == REDIS_ENCODING_INT ||
519         max->encoding == REDIS_ENCODING_INT) return REDIS_ERR;
520 
521     spec->min = spec->max = NULL;
522     if (zslParseLexRangeItem(min, &spec->min, &spec->minex) == REDIS_ERR ||
523         zslParseLexRangeItem(max, &spec->max, &spec->maxex) == REDIS_ERR) {
524         if (spec->min) decrRefCount(spec->min);
525         if (spec->max) decrRefCount(spec->max);
526         return REDIS_ERR;
527     } else {
528         return REDIS_OK;
529     }
530 }
531 
532 /* Free a lex range structure, must be called only after zelParseLexRange()
533  * populated the structure with success (REDIS_OK returned). */
534 void zslFreeLexRange(zlexrangespec *spec) {
535     decrRefCount(spec->min);
536     decrRefCount(spec->max);
537 }
538 
539 /* This is just a wrapper to compareStringObjects() that is able to
540  * handle shared.minstring and shared.maxstring as the equivalent of
541  * -inf and +inf for strings */
542 int compareStringObjectsForLexRange(robj *a, robj *b) {
543     if (a == b) return 0; /* This makes sure that we handle inf,inf and
544                              -inf,-inf ASAP. One special case less. */
545     if (a == shared.minstring || b == shared.maxstring) return -1;
546     if (a == shared.maxstring || b == shared.minstring) return 1;
547     return compareStringObjects(a,b);
548 }
549 
550 static int zslLexValueGteMin(robj *value, zlexrangespec *spec) {
551     return spec->minex ?
552         (compareStringObjectsForLexRange(value,spec->min) > 0) :
553         (compareStringObjectsForLexRange(value,spec->min) >= 0);
554 }
555 
556 static int zslLexValueLteMax(robj *value, zlexrangespec *spec) {
557     return spec->maxex ?
558         (compareStringObjectsForLexRange(value,spec->max) < 0) :
559         (compareStringObjectsForLexRange(value,spec->max) <= 0);
560 }
561 
562 /* Returns if there is a part of the zset is in the lex range. */
563 int zslIsInLexRange(zskiplist *zsl, zlexrangespec *range) {
564     zskiplistNode *x;
565 
566     /* Test for ranges that will always be empty. */
567     if (compareStringObjectsForLexRange(range->min,range->max) > 1 ||
568             (compareStringObjects(range->min,range->max) == 0 &&
569             (range->minex || range->maxex)))
570         return 0;
571     x = zsl->tail;
572     if (x == NULL || !zslLexValueGteMin(x->obj,range))
573         return 0;
574     x = zsl->header->level[0].forward;
575     if (x == NULL || !zslLexValueLteMax(x->obj,range))
576         return 0;
577     return 1;
578 }
579 
580 /* Find the first node that is contained in the specified lex range.
581  * Returns NULL when no element is contained in the range. */
582 zskiplistNode *zslFirstInLexRange(zskiplist *zsl, zlexrangespec *range) {
583     zskiplistNode *x;
584     int i;
585 
586     /* If everything is out of range, return early. */
587     if (!zslIsInLexRange(zsl,range)) return NULL;
588 
589     x = zsl->header;
590     for (i = zsl->level-1; i >= 0; i--) {
591         /* Go forward while *OUT* of range. */
592         while (x->level[i].forward &&
593             !zslLexValueGteMin(x->level[i].forward->obj,range))
594                 x = x->level[i].forward;
595     }
596 
597     /* This is an inner range, so the next node cannot be NULL. */
598     x = x->level[0].forward;
599     redisAssert(x != NULL);
600 
601     /* Check if score <= max. */
602     if (!zslLexValueLteMax(x->obj,range)) return NULL;
603     return x;
604 }
605 
606 /* Find the last node that is contained in the specified range.
607  * Returns NULL when no element is contained in the range. */
608 zskiplistNode *zslLastInLexRange(zskiplist *zsl, zlexrangespec *range) {
609     zskiplistNode *x;
610     int i;
611 
612     /* If everything is out of range, return early. */
613     if (!zslIsInLexRange(zsl,range)) return NULL;
614 
615     x = zsl->header;
616     for (i = zsl->level-1; i >= 0; i--) {
617         /* Go forward while *IN* range. */
618         while (x->level[i].forward &&
619             zslLexValueLteMax(x->level[i].forward->obj,range))
620                 x = x->level[i].forward;
621     }
622 
623     /* This is an inner range, so this node cannot be NULL. */
624     redisAssert(x != NULL);
625 
626     /* Check if score >= min. */
627     if (!zslLexValueGteMin(x->obj,range)) return NULL;
628     return x;
629 }
630 
631 /*-----------------------------------------------------------------------------
632  * Ziplist-backed sorted set API
633  *----------------------------------------------------------------------------*/
634 
635 double zzlGetScore(unsigned char *sptr) {
636     unsigned char *vstr;
637     unsigned int vlen;
638     long long vlong;
639     char buf[128];
640     double score;
641 
642     redisAssert(sptr != NULL);
643     redisAssert(ziplistGet(sptr,&vstr,&vlen,&vlong));
644 
645     if (vstr) {
646         memcpy(buf,vstr,vlen);
647         buf[vlen] = '\0';
648         score = strtod(buf,NULL);
649     } else {
650         score = vlong;
651     }
652 
653     return score;
654 }
655 
656 /* Return a ziplist element as a Redis string object.
657  * This simple abstraction can be used to simplifies some code at the
658  * cost of some performance. */
659 robj *ziplistGetObject(unsigned char *sptr) {
660     unsigned char *vstr;
661     unsigned int vlen;
662     long long vlong;
663 
664     redisAssert(sptr != NULL);
665     redisAssert(ziplistGet(sptr,&vstr,&vlen,&vlong));
666 
667     if (vstr) {
668         return createStringObject((char*)vstr,vlen);
669     } else {
670         return createStringObjectFromLongLong(vlong);
671     }
672 }
673 
674 /* Compare element in sorted set with given element. */
675 int zzlCompareElements(unsigned char *eptr, unsigned char *cstr, unsigned int clen) {
676     unsigned char *vstr;
677     unsigned int vlen;
678     long long vlong;
679     unsigned char vbuf[32];
680     int minlen, cmp;
681 
682     redisAssert(ziplistGet(eptr,&vstr,&vlen,&vlong));
683     if (vstr == NULL) {
684         /* Store string representation of long long in buf. */
685         vlen = ll2string((char*)vbuf,sizeof(vbuf),vlong);
686         vstr = vbuf;
687     }
688 
689     minlen = (vlen < clen) ? vlen : clen;
690     cmp = memcmp(vstr,cstr,minlen);
691     if (cmp == 0) return vlen-clen;
692     return cmp;
693 }
694 
695 unsigned int zzlLength(unsigned char *zl) {
696     return ziplistLen(zl)/2;
697 }
698 
699 /* Move to next entry based on the values in eptr and sptr. Both are set to
700  * NULL when there is no next entry. */
701 void zzlNext(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) {
702     unsigned char *_eptr, *_sptr;
703     redisAssert(*eptr != NULL && *sptr != NULL);
704 
705     _eptr = ziplistNext(zl,*sptr);
706     if (_eptr != NULL) {
707         _sptr = ziplistNext(zl,_eptr);
708         redisAssert(_sptr != NULL);
709     } else {
710         /* No next entry. */
711         _sptr = NULL;
712     }
713 
714     *eptr = _eptr;
715     *sptr = _sptr;
716 }
717 
718 /* Move to the previous entry based on the values in eptr and sptr. Both are
719  * set to NULL when there is no next entry. */
720 void zzlPrev(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) {
721     unsigned char *_eptr, *_sptr;
722     redisAssert(*eptr != NULL && *sptr != NULL);
723 
724     _sptr = ziplistPrev(zl,*eptr);
725     if (_sptr != NULL) {
726         _eptr = ziplistPrev(zl,_sptr);
727         redisAssert(_eptr != NULL);
728     } else {
729         /* No previous entry. */
730         _eptr = NULL;
731     }
732 
733     *eptr = _eptr;
734     *sptr = _sptr;
735 }
736 
737 /* Returns if there is a part of the zset is in range. Should only be used
738  * internally by zzlFirstInRange and zzlLastInRange. */
739 int zzlIsInRange(unsigned char *zl, zrangespec *range) {
740     unsigned char *p;
741     double score;
742 
743     /* Test for ranges that will always be empty. */
744     if (range->min > range->max ||
745             (range->min == range->max && (range->minex || range->maxex)))
746         return 0;
747 
748     p = ziplistIndex(zl,-1); /* Last score. */
749     if (p == NULL) return 0; /* Empty sorted set */
750     score = zzlGetScore(p);
751     if (!zslValueGteMin(score,range))
752         return 0;
753 
754     p = ziplistIndex(zl,1); /* First score. */
755     redisAssert(p != NULL);
756     score = zzlGetScore(p);
757     if (!zslValueLteMax(score,range))
758         return 0;
759 
760     return 1;
761 }
762 
763 /* Find pointer to the first element contained in the specified range.
764  * Returns NULL when no element is contained in the range. */
765 unsigned char *zzlFirstInRange(unsigned char *zl, zrangespec *range) {
766     unsigned char *eptr = ziplistIndex(zl,0), *sptr;
767     double score;
768 
769     /* If everything is out of range, return early. */
770     if (!zzlIsInRange(zl,range)) return NULL;
771 
772     while (eptr != NULL) {
773         sptr = ziplistNext(zl,eptr);
774         redisAssert(sptr != NULL);
775 
776         score = zzlGetScore(sptr);
777         if (zslValueGteMin(score,range)) {
778             /* Check if score <= max. */
779             if (zslValueLteMax(score,range))
780                 return eptr;
781             return NULL;
782         }
783 
784         /* Move to next element. */
785         eptr = ziplistNext(zl,sptr);
786     }
787 
788     return NULL;
789 }
790 
791 /* Find pointer to the last element contained in the specified range.
792  * Returns NULL when no element is contained in the range. */
793 unsigned char *zzlLastInRange(unsigned char *zl, zrangespec *range) {
794     unsigned char *eptr = ziplistIndex(zl,-2), *sptr;
795     double score;
796 
797     /* If everything is out of range, return early. */
798     if (!zzlIsInRange(zl,range)) return NULL;
799 
800     while (eptr != NULL) {
801         sptr = ziplistNext(zl,eptr);
802         redisAssert(sptr != NULL);
803 
804         score = zzlGetScore(sptr);
805         if (zslValueLteMax(score,range)) {
806             /* Check if score >= min. */
807             if (zslValueGteMin(score,range))
808                 return eptr;
809             return NULL;
810         }
811 
812         /* Move to previous element by moving to the score of previous element.
813          * When this returns NULL, we know there also is no element. */
814         sptr = ziplistPrev(zl,eptr);
815         if (sptr != NULL)
816             redisAssert((eptr = ziplistPrev(zl,sptr)) != NULL);
817         else
818             eptr = NULL;
819     }
820 
821     return NULL;
822 }
823 
824 static int zzlLexValueGteMin(unsigned char *p, zlexrangespec *spec) {
825     robj *value = ziplistGetObject(p);
826     int res = zslLexValueGteMin(value,spec);
827     decrRefCount(value);
828     return res;
829 }
830 
831 static int zzlLexValueLteMax(unsigned char *p, zlexrangespec *spec) {
832     robj *value = ziplistGetObject(p);
833     int res = zslLexValueLteMax(value,spec);
834     decrRefCount(value);
835     return res;
836 }
837 
838 /* Returns if there is a part of the zset is in range. Should only be used
839  * internally by zzlFirstInRange and zzlLastInRange. */
840 int zzlIsInLexRange(unsigned char *zl, zlexrangespec *range) {
841     unsigned char *p;
842 
843     /* Test for ranges that will always be empty. */
844     if (compareStringObjectsForLexRange(range->min,range->max) > 1 ||
845             (compareStringObjects(range->min,range->max) == 0 &&
846             (range->minex || range->maxex)))
847         return 0;
848 
849     p = ziplistIndex(zl,-2); /* Last element. */
850     if (p == NULL) return 0;
851     if (!zzlLexValueGteMin(p,range))
852         return 0;
853 
854     p = ziplistIndex(zl,0); /* First element. */
855     redisAssert(p != NULL);
856     if (!zzlLexValueLteMax(p,range))
857         return 0;
858 
859     return 1;
860 }
861 
862 /* Find pointer to the first element contained in the specified lex range.
863  * Returns NULL when no element is contained in the range. */
864 unsigned char *zzlFirstInLexRange(unsigned char *zl, zlexrangespec *range) {
865     unsigned char *eptr = ziplistIndex(zl,0), *sptr;
866 
867     /* If everything is out of range, return early. */
868     if (!zzlIsInLexRange(zl,range)) return NULL;
869 
870     while (eptr != NULL) {
871         if (zzlLexValueGteMin(eptr,range)) {
872             /* Check if score <= max. */
873             if (zzlLexValueLteMax(eptr,range))
874                 return eptr;
875             return NULL;
876         }
877 
878         /* Move to next element. */
879         sptr = ziplistNext(zl,eptr); /* This element score. Skip it. */
880         redisAssert(sptr != NULL);
881         eptr = ziplistNext(zl,sptr); /* Next element. */
882     }
883 
884     return NULL;
885 }
886 
887 /* Find pointer to the last element contained in the specified lex range.
888  * Returns NULL when no element is contained in the range. */
889 unsigned char *zzlLastInLexRange(unsigned char *zl, zlexrangespec *range) {
890     unsigned char *eptr = ziplistIndex(zl,-2), *sptr;
891 
892     /* If everything is out of range, return early. */
893     if (!zzlIsInLexRange(zl,range)) return NULL;
894 
895     while (eptr != NULL) {
896         if (zzlLexValueLteMax(eptr,range)) {
897             /* Check if score >= min. */
898             if (zzlLexValueGteMin(eptr,range))
899                 return eptr;
900             return NULL;
901         }
902 
903         /* Move to previous element by moving to the score of previous element.
904          * When this returns NULL, we know there also is no element. */
905         sptr = ziplistPrev(zl,eptr);
906         if (sptr != NULL)
907             redisAssert((eptr = ziplistPrev(zl,sptr)) != NULL);
908         else
909             eptr = NULL;
910     }
911 
912     return NULL;
913 }
914 
915 unsigned char *zzlFind(unsigned char *zl, robj *ele, double *score) {
916     unsigned char *eptr = ziplistIndex(zl,0), *sptr;
917 
918     ele = getDecodedObject(ele);
919     while (eptr != NULL) {
920         sptr = ziplistNext(zl,eptr);
921         redisAssertWithInfo(NULL,ele,sptr != NULL);
922 
923         if (ziplistCompare(eptr,ele->ptr,sdslen(ele->ptr))) {
924             /* Matching element, pull out score. */
925             if (score != NULL) *score = zzlGetScore(sptr);
926             decrRefCount(ele);
927             return eptr;
928         }
929 
930         /* Move to next element. */
931         eptr = ziplistNext(zl,sptr);
932     }
933 
934     decrRefCount(ele);
935     return NULL;
936 }
937 
938 /* Delete (element,score) pair from ziplist. Use local copy of eptr because we
939  * don't want to modify the one given as argument. */
940 unsigned char *zzlDelete(unsigned char *zl, unsigned char *eptr) {
941     unsigned char *p = eptr;
942 
943     /* TODO: add function to ziplist API to delete N elements from offset. */
944     zl = ziplistDelete(zl,&p);
945     zl = ziplistDelete(zl,&p);
946     return zl;
947 }
948 
949 unsigned char *zzlInsertAt(unsigned char *zl, unsigned char *eptr, robj *ele, double score) {
950     unsigned char *sptr;
951     char scorebuf[128];
952     int scorelen;
953     size_t offset;
954 
955     redisAssertWithInfo(NULL,ele,sdsEncodedObject(ele));
956     scorelen = d2string(scorebuf,sizeof(scorebuf),score);
957     if (eptr == NULL) {
958         zl = ziplistPush(zl,ele->ptr,sdslen(ele->ptr),ZIPLIST_TAIL);
959         zl = ziplistPush(zl,(unsigned char*)scorebuf,scorelen,ZIPLIST_TAIL);
960     } else {
961         /* Keep offset relative to zl, as it might be re-allocated. */
962         offset = eptr-zl;
963         zl = ziplistInsert(zl,eptr,ele->ptr,sdslen(ele->ptr));
964         eptr = zl+offset;
965 
966         /* Insert score after the element. */
967         redisAssertWithInfo(NULL,ele,(sptr = ziplistNext(zl,eptr)) != NULL);
968         zl = ziplistInsert(zl,sptr,(unsigned char*)scorebuf,scorelen);
969     }
970 
971     return zl;
972 }
973 
974 /* Insert (element,score) pair in ziplist. This function assumes the element is
975  * not yet present in the list. */
976 unsigned char *zzlInsert(unsigned char *zl, robj *ele, double score) {
977     unsigned char *eptr = ziplistIndex(zl,0), *sptr;
978     double s;
979 
980     ele = getDecodedObject(ele);
981     while (eptr != NULL) {
982         sptr = ziplistNext(zl,eptr);
983         redisAssertWithInfo(NULL,ele,sptr != NULL);
984         s = zzlGetScore(sptr);
985 
986         if (s > score) {
987             /* First element with score larger than score for element to be
988              * inserted. This means we should take its spot in the list to
989              * maintain ordering. */
990             zl = zzlInsertAt(zl,eptr,ele,score);
991             break;
992         } else if (s == score) {
993             /* Ensure lexicographical ordering for elements. */
994             if (zzlCompareElements(eptr,ele->ptr,sdslen(ele->ptr)) > 0) {
995                 zl = zzlInsertAt(zl,eptr,ele,score);
996                 break;
997             }
998         }
999 
1000         /* Move to next element. */
1001         eptr = ziplistNext(zl,sptr);
1002     }
1003 
1004     /* Push on tail of list when it was not yet inserted. */
1005     if (eptr == NULL)
1006         zl = zzlInsertAt(zl,NULL,ele,score);
1007 
1008     decrRefCount(ele);
1009     return zl;
1010 }
1011 
1012 unsigned char *zzlDeleteRangeByScore(unsigned char *zl, zrangespec *range, unsigned long *deleted) {
1013     unsigned char *eptr, *sptr;
1014     double score;
1015     unsigned long num = 0;
1016 
1017     if (deleted != NULL) *deleted = 0;
1018 
1019     eptr = zzlFirstInRange(zl,range);
1020     if (eptr == NULL) return zl;
1021 
1022     /* When the tail of the ziplist is deleted, eptr will point to the sentinel
1023      * byte and ziplistNext will return NULL. */
1024     while ((sptr = ziplistNext(zl,eptr)) != NULL) {
1025         score = zzlGetScore(sptr);
1026         if (zslValueLteMax(score,range)) {
1027             /* Delete both the element and the score. */
1028             zl = ziplistDelete(zl,&eptr);
1029             zl = ziplistDelete(zl,&eptr);
1030             num++;
1031         } else {
1032             /* No longer in range. */
1033             break;
1034         }
1035     }
1036 
1037     if (deleted != NULL) *deleted = num;
1038     return zl;
1039 }
1040 
1041 unsigned char *zzlDeleteRangeByLex(unsigned char *zl, zlexrangespec *range, unsigned long *deleted) {
1042     unsigned char *eptr, *sptr;
1043     unsigned long num = 0;
1044 
1045     if (deleted != NULL) *deleted = 0;
1046 
1047     eptr = zzlFirstInLexRange(zl,range);
1048     if (eptr == NULL) return zl;
1049 
1050     /* When the tail of the ziplist is deleted, eptr will point to the sentinel
1051      * byte and ziplistNext will return NULL. */
1052     while ((sptr = ziplistNext(zl,eptr)) != NULL) {
1053         if (zzlLexValueLteMax(eptr,range)) {
1054             /* Delete both the element and the score. */
1055             zl = ziplistDelete(zl,&eptr);
1056             zl = ziplistDelete(zl,&eptr);
1057             num++;
1058         } else {
1059             /* No longer in range. */
1060             break;
1061         }
1062     }
1063 
1064     if (deleted != NULL) *deleted = num;
1065     return zl;
1066 }
1067 
1068 /* Delete all the elements with rank between start and end from the skiplist.
1069  * Start and end are inclusive. Note that start and end need to be 1-based */
1070 unsigned char *zzlDeleteRangeByRank(unsigned char *zl, unsigned int start, unsigned int end, unsigned long *deleted) {
1071     unsigned int num = (end-start)+1;
1072     if (deleted) *deleted = num;
1073     zl = ziplistDeleteRange(zl,2*(start-1),2*num);
1074     return zl;
1075 }
1076 
1077 /*-----------------------------------------------------------------------------
1078  * Common sorted set API
1079  *----------------------------------------------------------------------------*/
1080 
1081 unsigned int zsetLength(robj *zobj) {
1082     int length = -1;
1083     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
1084         length = zzlLength(zobj->ptr);
1085     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
1086         length = ((zset*)zobj->ptr)->zsl->length;
1087     } else {
1088         redisPanic("Unknown sorted set encoding");
1089     }
1090     return length;
1091 }
1092 
1093 void zsetConvert(robj *zobj, int encoding) {
1094     zset *zs;
1095     zskiplistNode *node, *next;
1096     robj *ele;
1097     double score;
1098 
1099     if (zobj->encoding == encoding) return;
1100     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
1101         unsigned char *zl = zobj->ptr;
1102         unsigned char *eptr, *sptr;
1103         unsigned char *vstr;
1104         unsigned int vlen;
1105         long long vlong;
1106 
1107         if (encoding != REDIS_ENCODING_SKIPLIST)
1108             redisPanic("Unknown target encoding");
1109 
1110         zs = zmalloc(sizeof(*zs));
1111         zs->dict = dictCreate(&zsetDictType,NULL);
1112         zs->zsl = zslCreate();
1113 
1114         eptr = ziplistIndex(zl,0);
1115         redisAssertWithInfo(NULL,zobj,eptr != NULL);
1116         sptr = ziplistNext(zl,eptr);
1117         redisAssertWithInfo(NULL,zobj,sptr != NULL);
1118 
1119         while (eptr != NULL) {
1120             score = zzlGetScore(sptr);
1121             redisAssertWithInfo(NULL,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));
1122             if (vstr == NULL)
1123                 ele = createStringObjectFromLongLong(vlong);
1124             else
1125                 ele = createStringObject((char*)vstr,vlen);
1126 
1127             /* Has incremented refcount since it was just created. */
1128             node = zslInsert(zs->zsl,score,ele);
1129             redisAssertWithInfo(NULL,zobj,dictAdd(zs->dict,ele,&node->score) == DICT_OK);
1130             incrRefCount(ele); /* Added to dictionary. */
1131             zzlNext(zl,&eptr,&sptr);
1132         }
1133 
1134         zfree(zobj->ptr);
1135         zobj->ptr = zs;
1136         zobj->encoding = REDIS_ENCODING_SKIPLIST;
1137     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
1138         unsigned char *zl = ziplistNew();
1139 
1140         if (encoding != REDIS_ENCODING_ZIPLIST)
1141             redisPanic("Unknown target encoding");
1142 
1143         /* Approach similar to zslFree(), since we want to free the skiplist at
1144          * the same time as creating the ziplist. */
1145         zs = zobj->ptr;
1146         dictRelease(zs->dict);
1147         node = zs->zsl->header->level[0].forward;
1148         zfree(zs->zsl->header);
1149         zfree(zs->zsl);
1150 
1151         while (node) {
1152             ele = getDecodedObject(node->obj);
1153             zl = zzlInsertAt(zl,NULL,ele,node->score);
1154             decrRefCount(ele);
1155 
1156             next = node->level[0].forward;
1157             zslFreeNode(node);
1158             node = next;
1159         }
1160 
1161         zfree(zs);
1162         zobj->ptr = zl;
1163         zobj->encoding = REDIS_ENCODING_ZIPLIST;
1164     } else {
1165         redisPanic("Unknown sorted set encoding");
1166     }
1167 }
1168 
1169 /*-----------------------------------------------------------------------------
1170  * Sorted set commands
1171  *----------------------------------------------------------------------------*/
1172 
1173 /* This generic command implements both ZADD and ZINCRBY. */
1174 void zaddGenericCommand(redisClient *c, int incr) {
1175     static char *nanerr = "resulting score is not a number (NaN)";
1176     robj *key = c->argv[1];
1177     robj *ele;
1178     robj *zobj;
1179     robj *curobj;
1180     double score = 0, *scores = NULL, curscore = 0.0;
1181     int j, elements = (c->argc-2)/2;
1182     int added = 0, updated = 0;
1183 
1184     if (c->argc % 2) {
1185         addReply(c,shared.syntaxerr);
1186         return;
1187     }
1188 
1189     /* Start parsing all the scores, we need to emit any syntax error
1190      * before executing additions to the sorted set, as the command should
1191      * either execute fully or nothing at all. */
1192     scores = zmalloc(sizeof(double)*elements);
1193     for (j = 0; j < elements; j++) {
1194         if (getDoubleFromObjectOrReply(c,c->argv[2+j*2],&scores[j],NULL)
1195             != REDIS_OK) goto cleanup;
1196     }
1197 
1198     /* Lookup the key and create the sorted set if does not exist. */
1199     zobj = lookupKeyWrite(c->db,key);
1200     if (zobj == NULL) {
1201         if (server.zset_max_ziplist_entries == 0 ||
1202             server.zset_max_ziplist_value < sdslen(c->argv[3]->ptr))
1203         {
1204             zobj = createZsetObject();
1205         } else {
1206             zobj = createZsetZiplistObject();
1207         }
1208         dbAdd(c->db,key,zobj);
1209     } else {
1210         if (zobj->type != REDIS_ZSET) {
1211             addReply(c,shared.wrongtypeerr);
1212             goto cleanup;
1213         }
1214     }
1215 
1216     for (j = 0; j < elements; j++) {
1217         score = scores[j];
1218 
1219         if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
1220             unsigned char *eptr;
1221 
1222             /* Prefer non-encoded element when dealing with ziplists. */
1223             ele = c->argv[3+j*2];
1224             if ((eptr = zzlFind(zobj->ptr,ele,&curscore)) != NULL) {
1225                 if (incr) {
1226                     score += curscore;
1227                     if (isnan(score)) {
1228                         addReplyError(c,nanerr);
1229                         goto cleanup;
1230                     }
1231                 }
1232 
1233                 /* Remove and re-insert when score changed. */
1234                 if (score != curscore) {
1235                     zobj->ptr = zzlDelete(zobj->ptr,eptr);
1236                     zobj->ptr = zzlInsert(zobj->ptr,ele,score);
1237                     server.dirty++;
1238                     updated++;
1239                 }
1240             } else {
1241                 /* Optimize: check if the element is too large or the list
1242                  * becomes too long *before* executing zzlInsert. */
1243                 zobj->ptr = zzlInsert(zobj->ptr,ele,score);
1244                 if (zzlLength(zobj->ptr) > server.zset_max_ziplist_entries)
1245                     zsetConvert(zobj,REDIS_ENCODING_SKIPLIST);
1246                 if (sdslen(ele->ptr) > server.zset_max_ziplist_value)
1247                     zsetConvert(zobj,REDIS_ENCODING_SKIPLIST);
1248                 server.dirty++;
1249                 added++;
1250             }
1251         } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
1252             zset *zs = zobj->ptr;
1253             zskiplistNode *znode;
1254             dictEntry *de;
1255 
1256             ele = c->argv[3+j*2] = tryObjectEncoding(c->argv[3+j*2]);
1257             de = dictFind(zs->dict,ele);
1258             if (de != NULL) {
1259                 curobj = dictGetKey(de);
1260                 curscore = *(double*)dictGetVal(de);
1261 
1262                 if (incr) {
1263                     score += curscore;
1264                     if (isnan(score)) {
1265                         addReplyError(c,nanerr);
1266                         /* Don't need to check if the sorted set is empty
1267                          * because we know it has at least one element. */
1268                         goto cleanup;
1269                     }
1270                 }
1271 
1272                 /* Remove and re-insert when score changed. We can safely
1273                  * delete the key object from the skiplist, since the
1274                  * dictionary still has a reference to it. */
1275                 if (score != curscore) {
1276                     redisAssertWithInfo(c,curobj,zslDelete(zs->zsl,curscore,curobj));
1277                     znode = zslInsert(zs->zsl,score,curobj);
1278                     incrRefCount(curobj); /* Re-inserted in skiplist. */
1279                     dictGetVal(de) = &znode->score; /* Update score ptr. */
1280                     server.dirty++;
1281                     updated++;
1282                 }
1283             } else {
1284                 znode = zslInsert(zs->zsl,score,ele);
1285                 incrRefCount(ele); /* Inserted in skiplist. */
1286                 redisAssertWithInfo(c,NULL,dictAdd(zs->dict,ele,&znode->score) == DICT_OK);
1287                 incrRefCount(ele); /* Added to dictionary. */
1288                 server.dirty++;
1289                 added++;
1290             }
1291         } else {
1292             redisPanic("Unknown sorted set encoding");
1293         }
1294     }
1295     if (incr) /* ZINCRBY */
1296         addReplyDouble(c,score);
1297     else /* ZADD */
1298         addReplyLongLong(c,added);
1299 
1300 cleanup:
1301     zfree(scores);
1302     if (added || updated) {
1303         signalModifiedKey(c->db,key);
1304         notifyKeyspaceEvent(REDIS_NOTIFY_ZSET,
1305             incr ? "zincr" : "zadd", key, c->db->id);
1306     }
1307 }
1308 
1309 void zaddCommand(redisClient *c) {
1310     zaddGenericCommand(c,0);
1311 }
1312 
1313 void zincrbyCommand(redisClient *c) {
1314     zaddGenericCommand(c,1);
1315 }
1316 
1317 void zremCommand(redisClient *c) {
1318     robj *key = c->argv[1];
1319     robj *zobj;
1320     int deleted = 0, keyremoved = 0, j;
1321 
1322     if ((zobj = lookupKeyWriteOrReply(c,key,shared.czero)) == NULL ||
1323         checkType(c,zobj,REDIS_ZSET)) return;
1324 
1325     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
1326         unsigned char *eptr;
1327 
1328         for (j = 2; j < c->argc; j++) {
1329             if ((eptr = zzlFind(zobj->ptr,c->argv[j],NULL)) != NULL) {
1330                 deleted++;
1331                 zobj->ptr = zzlDelete(zobj->ptr,eptr);
1332                 if (zzlLength(zobj->ptr) == 0) {
1333                     dbDelete(c->db,key);
1334                     keyremoved = 1;
1335                     break;
1336                 }
1337             }
1338         }
1339     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
1340         zset *zs = zobj->ptr;
1341         dictEntry *de;
1342         double score;
1343 
1344         for (j = 2; j < c->argc; j++) {
1345             de = dictFind(zs->dict,c->argv[j]);
1346             if (de != NULL) {
1347                 deleted++;
1348 
1349                 /* Delete from the skiplist */
1350                 score = *(double*)dictGetVal(de);
1351                 redisAssertWithInfo(c,c->argv[j],zslDelete(zs->zsl,score,c->argv[j]));
1352 
1353                 /* Delete from the hash table */
1354                 dictDelete(zs->dict,c->argv[j]);
1355                 if (htNeedsResize(zs->dict)) dictResize(zs->dict);
1356                 if (dictSize(zs->dict) == 0) {
1357                     dbDelete(c->db,key);
1358                     keyremoved = 1;
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         dict *accumulator = dictCreate(&setDictType,NULL);
1983         dictIterator *di;
1984         dictEntry *de;
1985         double score;
1986 
1987         if (setnum) {
1988             /* Our union is at least as large as the largest set.
1989              * Resize the dictionary ASAP to avoid useless rehashing. */
1990             dictExpand(accumulator,zuiLength(&src[setnum-1]));
1991         }
1992 
1993         /* Step 1: Create a dictionary of elements -> aggregated-scores
1994          * by iterating one sorted set after the other. */
1995         for (i = 0; i < setnum; i++) {
1996             if (zuiLength(&src[i]) == 0) continue;
1997 
1998             zuiInitIterator(&src[i]);
1999             while (zuiNext(&src[i],&zval)) {
2000                 /* Initialize value */
2001                 score = src[i].weight * zval.score;
2002                 if (isnan(score)) score = 0;
2003 
2004                 /* Search for this element in the accumulating dictionary. */
2005                 de = dictFind(accumulator,zuiObjectFromValue(&zval));
2006                 /* If we don't have it, we need to create a new entry. */
2007                 if (de == NULL) {
2008                     tmp = zuiObjectFromValue(&zval);
2009                     /* Remember the longest single element encountered,
2010                      * to understand if it's possible to convert to ziplist
2011                      * at the end. */
2012                     if (sdsEncodedObject(tmp)) {
2013                         if (sdslen(tmp->ptr) > maxelelen)
2014                             maxelelen = sdslen(tmp->ptr);
2015                     }
2016                     /* Add the element with its initial score. */
2017                     de = dictAddRaw(accumulator,tmp);
2018                     incrRefCount(tmp);
2019                     dictSetDoubleVal(de,score);
2020                 } else {
2021                     /* Update the score with the score of the new instance
2022                      * of the element found in the current sorted set.
2023                      *
2024                      * Here we access directly the dictEntry double
2025                      * value inside the union as it is a big speedup
2026                      * compared to using the getDouble/setDouble API. */
2027                     zunionInterAggregate(&de->v.d,score,aggregate);
2028                 }
2029             }
2030             zuiClearIterator(&src[i]);
2031         }
2032 
2033         /* Step 2: convert the dictionary into the final sorted set. */
2034         di = dictGetIterator(accumulator);
2035 
2036         /* We now are aware of the final size of the resulting sorted set,
2037          * let's resize the dictionary embedded inside the sorted set to the
2038          * right size, in order to save rehashing time. */
2039         dictExpand(dstzset->dict,dictSize(accumulator));
2040 
2041         while((de = dictNext(di)) != NULL) {
2042             robj *ele = dictGetKey(de);
2043             score = dictGetDoubleVal(de);
2044             znode = zslInsert(dstzset->zsl,score,ele);
2045             incrRefCount(ele); /* added to skiplist */
2046             dictAdd(dstzset->dict,ele,&znode->score);
2047             incrRefCount(ele); /* added to dictionary */
2048         }
2049         dictReleaseIterator(di);
2050 
2051         /* We can free the accumulator dictionary now. */
2052         dictRelease(accumulator);
2053     } else {
2054         redisPanic("Unknown operator");
2055     }
2056 
2057     if (dbDelete(c->db,dstkey)) {
2058         signalModifiedKey(c->db,dstkey);
2059         touched = 1;
2060         server.dirty++;
2061     }
2062     if (dstzset->zsl->length) {
2063         /* Convert to ziplist when in limits. */
2064         if (dstzset->zsl->length <= server.zset_max_ziplist_entries &&
2065             maxelelen <= server.zset_max_ziplist_value)
2066                 zsetConvert(dstobj,REDIS_ENCODING_ZIPLIST);
2067 
2068         dbAdd(c->db,dstkey,dstobj);
2069         addReplyLongLong(c,zsetLength(dstobj));
2070         if (!touched) signalModifiedKey(c->db,dstkey);
2071         notifyKeyspaceEvent(REDIS_NOTIFY_ZSET,
2072             (op == REDIS_OP_UNION) ? "zunionstore" : "zinterstore",
2073             dstkey,c->db->id);
2074         server.dirty++;
2075     } else {
2076         decrRefCount(dstobj);
2077         addReply(c,shared.czero);
2078         if (touched)
2079             notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"del",dstkey,c->db->id);
2080     }
2081     zfree(src);
2082 }
2083 
2084 void zunionstoreCommand(redisClient *c) {
2085     zunionInterGenericCommand(c,c->argv[1], REDIS_OP_UNION);
2086 }
2087 
2088 void zinterstoreCommand(redisClient *c) {
2089     zunionInterGenericCommand(c,c->argv[1], REDIS_OP_INTER);
2090 }
2091 
2092 void zrangeGenericCommand(redisClient *c, int reverse) {
2093     robj *key = c->argv[1];
2094     robj *zobj;
2095     int withscores = 0;
2096     long start;
2097     long end;
2098     int llen;
2099     int rangelen;
2100 
2101     if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != REDIS_OK) ||
2102         (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != REDIS_OK)) return;
2103 
2104     if (c->argc == 5 && !strcasecmp(c->argv[4]->ptr,"withscores")) {
2105         withscores = 1;
2106     } else if (c->argc >= 5) {
2107         addReply(c,shared.syntaxerr);
2108         return;
2109     }
2110 
2111     if ((zobj = lookupKeyReadOrReply(c,key,shared.emptymultibulk)) == NULL
2112          || checkType(c,zobj,REDIS_ZSET)) return;
2113 
2114     /* Sanitize indexes. */
2115     llen = zsetLength(zobj);
2116     if (start < 0) start = llen+start;
2117     if (end < 0) end = llen+end;
2118     if (start < 0) start = 0;
2119 
2120     /* Invariant: start >= 0, so this test will be true when end < 0.
2121      * The range is empty when start > end or start >= length. */
2122     if (start > end || start >= llen) {
2123         addReply(c,shared.emptymultibulk);
2124         return;
2125     }
2126     if (end >= llen) end = llen-1;
2127     rangelen = (end-start)+1;
2128 
2129     /* Return the result in form of a multi-bulk reply */
2130     addReplyMultiBulkLen(c, withscores ? (rangelen*2) : rangelen);
2131 
2132     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2133         unsigned char *zl = zobj->ptr;
2134         unsigned char *eptr, *sptr;
2135         unsigned char *vstr;
2136         unsigned int vlen;
2137         long long vlong;
2138 
2139         if (reverse)
2140             eptr = ziplistIndex(zl,-2-(2*start));
2141         else
2142             eptr = ziplistIndex(zl,2*start);
2143 
2144         redisAssertWithInfo(c,zobj,eptr != NULL);
2145         sptr = ziplistNext(zl,eptr);
2146 
2147         while (rangelen--) {
2148             redisAssertWithInfo(c,zobj,eptr != NULL && sptr != NULL);
2149             redisAssertWithInfo(c,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));
2150             if (vstr == NULL)
2151                 addReplyBulkLongLong(c,vlong);
2152             else
2153                 addReplyBulkCBuffer(c,vstr,vlen);
2154 
2155             if (withscores)
2156                 addReplyDouble(c,zzlGetScore(sptr));
2157 
2158             if (reverse)
2159                 zzlPrev(zl,&eptr,&sptr);
2160             else
2161                 zzlNext(zl,&eptr,&sptr);
2162         }
2163 
2164     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2165         zset *zs = zobj->ptr;
2166         zskiplist *zsl = zs->zsl;
2167         zskiplistNode *ln;
2168         robj *ele;
2169 
2170         /* Check if starting point is trivial, before doing log(N) lookup. */
2171         if (reverse) {
2172             ln = zsl->tail;
2173             if (start > 0)
2174                 ln = zslGetElementByRank(zsl,llen-start);
2175         } else {
2176             ln = zsl->header->level[0].forward;
2177             if (start > 0)
2178                 ln = zslGetElementByRank(zsl,start+1);
2179         }
2180 
2181         while(rangelen--) {
2182             redisAssertWithInfo(c,zobj,ln != NULL);
2183             ele = ln->obj;
2184             addReplyBulk(c,ele);
2185             if (withscores)
2186                 addReplyDouble(c,ln->score);
2187             ln = reverse ? ln->backward : ln->level[0].forward;
2188         }
2189     } else {
2190         redisPanic("Unknown sorted set encoding");
2191     }
2192 }
2193 
2194 void zrangeCommand(redisClient *c) {
2195     zrangeGenericCommand(c,0);
2196 }
2197 
2198 void zrevrangeCommand(redisClient *c) {
2199     zrangeGenericCommand(c,1);
2200 }
2201 
2202 /* This command implements ZRANGEBYSCORE, ZREVRANGEBYSCORE. */
2203 void genericZrangebyscoreCommand(redisClient *c, int reverse) {
2204     zrangespec range;
2205     robj *key = c->argv[1];
2206     robj *zobj;
2207     long offset = 0, limit = -1;
2208     int withscores = 0;
2209     unsigned long rangelen = 0;
2210     void *replylen = NULL;
2211     int minidx, maxidx;
2212 
2213     /* Parse the range arguments. */
2214     if (reverse) {
2215         /* Range is given as [max,min] */
2216         maxidx = 2; minidx = 3;
2217     } else {
2218         /* Range is given as [min,max] */
2219         minidx = 2; maxidx = 3;
2220     }
2221 
2222     if (zslParseRange(c->argv[minidx],c->argv[maxidx],&range) != REDIS_OK) {
2223         addReplyError(c,"min or max is not a float");
2224         return;
2225     }
2226 
2227     /* Parse optional extra arguments. Note that ZCOUNT will exactly have
2228      * 4 arguments, so we'll never enter the following code path. */
2229     if (c->argc > 4) {
2230         int remaining = c->argc - 4;
2231         int pos = 4;
2232 
2233         while (remaining) {
2234             if (remaining >= 1 && !strcasecmp(c->argv[pos]->ptr,"withscores")) {
2235                 pos++; remaining--;
2236                 withscores = 1;
2237             } else if (remaining >= 3 && !strcasecmp(c->argv[pos]->ptr,"limit")) {
2238                 if ((getLongFromObjectOrReply(c, c->argv[pos+1], &offset, NULL) != REDIS_OK) ||
2239                     (getLongFromObjectOrReply(c, c->argv[pos+2], &limit, NULL) != REDIS_OK)) return;
2240                 pos += 3; remaining -= 3;
2241             } else {
2242                 addReply(c,shared.syntaxerr);
2243                 return;
2244             }
2245         }
2246     }
2247 
2248     /* Ok, lookup the key and get the range */
2249     if ((zobj = lookupKeyReadOrReply(c,key,shared.emptymultibulk)) == NULL ||
2250         checkType(c,zobj,REDIS_ZSET)) return;
2251 
2252     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2253         unsigned char *zl = zobj->ptr;
2254         unsigned char *eptr, *sptr;
2255         unsigned char *vstr;
2256         unsigned int vlen;
2257         long long vlong;
2258         double score;
2259 
2260         /* If reversed, get the last node in range as starting point. */
2261         if (reverse) {
2262             eptr = zzlLastInRange(zl,&range);
2263         } else {
2264             eptr = zzlFirstInRange(zl,&range);
2265         }
2266 
2267         /* No "first" element in the specified interval. */
2268         if (eptr == NULL) {
2269             addReply(c, shared.emptymultibulk);
2270             return;
2271         }
2272 
2273         /* Get score pointer for the first element. */
2274         redisAssertWithInfo(c,zobj,eptr != NULL);
2275         sptr = ziplistNext(zl,eptr);
2276 
2277         /* We don't know in advance how many matching elements there are in the
2278          * list, so we push this object that will represent the multi-bulk
2279          * length in the output buffer, and will "fix" it later */
2280         replylen = addDeferredMultiBulkLength(c);
2281 
2282         /* If there is an offset, just traverse the number of elements without
2283          * checking the score because that is done in the next loop. */
2284         while (eptr && offset--) {
2285             if (reverse) {
2286                 zzlPrev(zl,&eptr,&sptr);
2287             } else {
2288                 zzlNext(zl,&eptr,&sptr);
2289             }
2290         }
2291 
2292         while (eptr && limit--) {
2293             score = zzlGetScore(sptr);
2294 
2295             /* Abort when the node is no longer in range. */
2296             if (reverse) {
2297                 if (!zslValueGteMin(score,&range)) break;
2298             } else {
2299                 if (!zslValueLteMax(score,&range)) break;
2300             }
2301 
2302             /* We know the element exists, so ziplistGet should always succeed */
2303             redisAssertWithInfo(c,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));
2304 
2305             rangelen++;
2306             if (vstr == NULL) {
2307                 addReplyBulkLongLong(c,vlong);
2308             } else {
2309                 addReplyBulkCBuffer(c,vstr,vlen);
2310             }
2311 
2312             if (withscores) {
2313                 addReplyDouble(c,score);
2314             }
2315 
2316             /* Move to next node */
2317             if (reverse) {
2318                 zzlPrev(zl,&eptr,&sptr);
2319             } else {
2320                 zzlNext(zl,&eptr,&sptr);
2321             }
2322         }
2323     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2324         zset *zs = zobj->ptr;
2325         zskiplist *zsl = zs->zsl;
2326         zskiplistNode *ln;
2327 
2328         /* If reversed, get the last node in range as starting point. */
2329         if (reverse) {
2330             ln = zslLastInRange(zsl,&range);
2331         } else {
2332             ln = zslFirstInRange(zsl,&range);
2333         }
2334 
2335         /* No "first" element in the specified interval. */
2336         if (ln == NULL) {
2337             addReply(c, shared.emptymultibulk);
2338             return;
2339         }
2340 
2341         /* We don't know in advance how many matching elements there are in the
2342          * list, so we push this object that will represent the multi-bulk
2343          * length in the output buffer, and will "fix" it later */
2344         replylen = addDeferredMultiBulkLength(c);
2345 
2346         /* If there is an offset, just traverse the number of elements without
2347          * checking the score because that is done in the next loop. */
2348         while (ln && offset--) {
2349             if (reverse) {
2350                 ln = ln->backward;
2351             } else {
2352                 ln = ln->level[0].forward;
2353             }
2354         }
2355 
2356         while (ln && limit--) {
2357             /* Abort when the node is no longer in range. */
2358             if (reverse) {
2359                 if (!zslValueGteMin(ln->score,&range)) break;
2360             } else {
2361                 if (!zslValueLteMax(ln->score,&range)) break;
2362             }
2363 
2364             rangelen++;
2365             addReplyBulk(c,ln->obj);
2366 
2367             if (withscores) {
2368                 addReplyDouble(c,ln->score);
2369             }
2370 
2371             /* Move to next node */
2372             if (reverse) {
2373                 ln = ln->backward;
2374             } else {
2375                 ln = ln->level[0].forward;
2376             }
2377         }
2378     } else {
2379         redisPanic("Unknown sorted set encoding");
2380     }
2381 
2382     if (withscores) {
2383         rangelen *= 2;
2384     }
2385 
2386     setDeferredMultiBulkLength(c, replylen, rangelen);
2387 }
2388 
2389 void zrangebyscoreCommand(redisClient *c) {
2390     genericZrangebyscoreCommand(c,0);
2391 }
2392 
2393 void zrevrangebyscoreCommand(redisClient *c) {
2394     genericZrangebyscoreCommand(c,1);
2395 }
2396 
2397 void zcountCommand(redisClient *c) {
2398     robj *key = c->argv[1];
2399     robj *zobj;
2400     zrangespec range;
2401     int count = 0;
2402 
2403     /* Parse the range arguments */
2404     if (zslParseRange(c->argv[2],c->argv[3],&range) != REDIS_OK) {
2405         addReplyError(c,"min or max is not a float");
2406         return;
2407     }
2408 
2409     /* Lookup the sorted set */
2410     if ((zobj = lookupKeyReadOrReply(c, key, shared.czero)) == NULL ||
2411         checkType(c, zobj, REDIS_ZSET)) return;
2412 
2413     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2414         unsigned char *zl = zobj->ptr;
2415         unsigned char *eptr, *sptr;
2416         double score;
2417 
2418         /* Use the first element in range as the starting point */
2419         eptr = zzlFirstInRange(zl,&range);
2420 
2421         /* No "first" element */
2422         if (eptr == NULL) {
2423             addReply(c, shared.czero);
2424             return;
2425         }
2426 
2427         /* First element is in range */
2428         sptr = ziplistNext(zl,eptr);
2429         score = zzlGetScore(sptr);
2430         redisAssertWithInfo(c,zobj,zslValueLteMax(score,&range));
2431 
2432         /* Iterate over elements in range */
2433         while (eptr) {
2434             score = zzlGetScore(sptr);
2435 
2436             /* Abort when the node is no longer in range. */
2437             if (!zslValueLteMax(score,&range)) {
2438                 break;
2439             } else {
2440                 count++;
2441                 zzlNext(zl,&eptr,&sptr);
2442             }
2443         }
2444     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2445         zset *zs = zobj->ptr;
2446         zskiplist *zsl = zs->zsl;
2447         zskiplistNode *zn;
2448         unsigned long rank;
2449 
2450         /* Find first element in range */
2451         zn = zslFirstInRange(zsl, &range);
2452 
2453         /* Use rank of first element, if any, to determine preliminary count */
2454         if (zn != NULL) {
2455             rank = zslGetRank(zsl, zn->score, zn->obj);
2456             count = (zsl->length - (rank - 1));
2457 
2458             /* Find last element in range */
2459             zn = zslLastInRange(zsl, &range);
2460 
2461             /* Use rank of last element, if any, to determine the actual count */
2462             if (zn != NULL) {
2463                 rank = zslGetRank(zsl, zn->score, zn->obj);
2464                 count -= (zsl->length - rank);
2465             }
2466         }
2467     } else {
2468         redisPanic("Unknown sorted set encoding");
2469     }
2470 
2471     addReplyLongLong(c, count);
2472 }
2473 
2474 void zlexcountCommand(redisClient *c) {
2475     robj *key = c->argv[1];
2476     robj *zobj;
2477     zlexrangespec range;
2478     int count = 0;
2479 
2480     /* Parse the range arguments */
2481     if (zslParseLexRange(c->argv[2],c->argv[3],&range) != REDIS_OK) {
2482         addReplyError(c,"min or max not valid string range item");
2483         return;
2484     }
2485 
2486     /* Lookup the sorted set */
2487     if ((zobj = lookupKeyReadOrReply(c, key, shared.czero)) == NULL ||
2488         checkType(c, zobj, REDIS_ZSET))
2489     {
2490         zslFreeLexRange(&range);
2491         return;
2492     }
2493 
2494     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2495         unsigned char *zl = zobj->ptr;
2496         unsigned char *eptr, *sptr;
2497 
2498         /* Use the first element in range as the starting point */
2499         eptr = zzlFirstInLexRange(zl,&range);
2500 
2501         /* No "first" element */
2502         if (eptr == NULL) {
2503             zslFreeLexRange(&range);
2504             addReply(c, shared.czero);
2505             return;
2506         }
2507 
2508         /* First element is in range */
2509         sptr = ziplistNext(zl,eptr);
2510         redisAssertWithInfo(c,zobj,zzlLexValueLteMax(eptr,&range));
2511 
2512         /* Iterate over elements in range */
2513         while (eptr) {
2514             /* Abort when the node is no longer in range. */
2515             if (!zzlLexValueLteMax(eptr,&range)) {
2516                 break;
2517             } else {
2518                 count++;
2519                 zzlNext(zl,&eptr,&sptr);
2520             }
2521         }
2522     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2523         zset *zs = zobj->ptr;
2524         zskiplist *zsl = zs->zsl;
2525         zskiplistNode *zn;
2526         unsigned long rank;
2527 
2528         /* Find first element in range */
2529         zn = zslFirstInLexRange(zsl, &range);
2530 
2531         /* Use rank of first element, if any, to determine preliminary count */
2532         if (zn != NULL) {
2533             rank = zslGetRank(zsl, zn->score, zn->obj);
2534             count = (zsl->length - (rank - 1));
2535 
2536             /* Find last element in range */
2537             zn = zslLastInLexRange(zsl, &range);
2538 
2539             /* Use rank of last element, if any, to determine the actual count */
2540             if (zn != NULL) {
2541                 rank = zslGetRank(zsl, zn->score, zn->obj);
2542                 count -= (zsl->length - rank);
2543             }
2544         }
2545     } else {
2546         redisPanic("Unknown sorted set encoding");
2547     }
2548 
2549     zslFreeLexRange(&range);
2550     addReplyLongLong(c, count);
2551 }
2552 
2553 /* This command implements ZRANGEBYLEX, ZREVRANGEBYLEX. */
2554 void genericZrangebylexCommand(redisClient *c, int reverse) {
2555     zlexrangespec range;
2556     robj *key = c->argv[1];
2557     robj *zobj;
2558     long offset = 0, limit = -1;
2559     unsigned long rangelen = 0;
2560     void *replylen = NULL;
2561     int minidx, maxidx;
2562 
2563     /* Parse the range arguments. */
2564     if (reverse) {
2565         /* Range is given as [max,min] */
2566         maxidx = 2; minidx = 3;
2567     } else {
2568         /* Range is given as [min,max] */
2569         minidx = 2; maxidx = 3;
2570     }
2571 
2572     if (zslParseLexRange(c->argv[minidx],c->argv[maxidx],&range) != REDIS_OK) {
2573         addReplyError(c,"min or max not valid string range item");
2574         return;
2575     }
2576 
2577     /* Parse optional extra arguments. Note that ZCOUNT will exactly have
2578      * 4 arguments, so we'll never enter the following code path. */
2579     if (c->argc > 4) {
2580         int remaining = c->argc - 4;
2581         int pos = 4;
2582 
2583         while (remaining) {
2584             if (remaining >= 3 && !strcasecmp(c->argv[pos]->ptr,"limit")) {
2585                 if ((getLongFromObjectOrReply(c, c->argv[pos+1], &offset, NULL) != REDIS_OK) ||
2586                     (getLongFromObjectOrReply(c, c->argv[pos+2], &limit, NULL) != REDIS_OK)) return;
2587                 pos += 3; remaining -= 3;
2588             } else {
2589                 zslFreeLexRange(&range);
2590                 addReply(c,shared.syntaxerr);
2591                 return;
2592             }
2593         }
2594     }
2595 
2596     /* Ok, lookup the key and get the range */
2597     if ((zobj = lookupKeyReadOrReply(c,key,shared.emptymultibulk)) == NULL ||
2598         checkType(c,zobj,REDIS_ZSET))
2599     {
2600         zslFreeLexRange(&range);
2601         return;
2602     }
2603 
2604     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2605         unsigned char *zl = zobj->ptr;
2606         unsigned char *eptr, *sptr;
2607         unsigned char *vstr;
2608         unsigned int vlen;
2609         long long vlong;
2610 
2611         /* If reversed, get the last node in range as starting point. */
2612         if (reverse) {
2613             eptr = zzlLastInLexRange(zl,&range);
2614         } else {
2615             eptr = zzlFirstInLexRange(zl,&range);
2616         }
2617 
2618         /* No "first" element in the specified interval. */
2619         if (eptr == NULL) {
2620             addReply(c, shared.emptymultibulk);
2621             zslFreeLexRange(&range);
2622             return;
2623         }
2624 
2625         /* Get score pointer for the first element. */
2626         redisAssertWithInfo(c,zobj,eptr != NULL);
2627         sptr = ziplistNext(zl,eptr);
2628 
2629         /* We don't know in advance how many matching elements there are in the
2630          * list, so we push this object that will represent the multi-bulk
2631          * length in the output buffer, and will "fix" it later */
2632         replylen = addDeferredMultiBulkLength(c);
2633 
2634         /* If there is an offset, just traverse the number of elements without
2635          * checking the score because that is done in the next loop. */
2636         while (eptr && offset--) {
2637             if (reverse) {
2638                 zzlPrev(zl,&eptr,&sptr);
2639             } else {
2640                 zzlNext(zl,&eptr,&sptr);
2641             }
2642         }
2643 
2644         while (eptr && limit--) {
2645             /* Abort when the node is no longer in range. */
2646             if (reverse) {
2647                 if (!zzlLexValueGteMin(eptr,&range)) break;
2648             } else {
2649                 if (!zzlLexValueLteMax(eptr,&range)) break;
2650             }
2651 
2652             /* We know the element exists, so ziplistGet should always
2653              * succeed. */
2654             redisAssertWithInfo(c,zobj,ziplistGet(eptr,&vstr,&vlen,&vlong));
2655 
2656             rangelen++;
2657             if (vstr == NULL) {
2658                 addReplyBulkLongLong(c,vlong);
2659             } else {
2660                 addReplyBulkCBuffer(c,vstr,vlen);
2661             }
2662 
2663             /* Move to next node */
2664             if (reverse) {
2665                 zzlPrev(zl,&eptr,&sptr);
2666             } else {
2667                 zzlNext(zl,&eptr,&sptr);
2668             }
2669         }
2670     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2671         zset *zs = zobj->ptr;
2672         zskiplist *zsl = zs->zsl;
2673         zskiplistNode *ln;
2674 
2675         /* If reversed, get the last node in range as starting point. */
2676         if (reverse) {
2677             ln = zslLastInLexRange(zsl,&range);
2678         } else {
2679             ln = zslFirstInLexRange(zsl,&range);
2680         }
2681 
2682         /* No "first" element in the specified interval. */
2683         if (ln == NULL) {
2684             addReply(c, shared.emptymultibulk);
2685             zslFreeLexRange(&range);
2686             return;
2687         }
2688 
2689         /* We don't know in advance how many matching elements there are in the
2690          * list, so we push this object that will represent the multi-bulk
2691          * length in the output buffer, and will "fix" it later */
2692         replylen = addDeferredMultiBulkLength(c);
2693 
2694         /* If there is an offset, just traverse the number of elements without
2695          * checking the score because that is done in the next loop. */
2696         while (ln && offset--) {
2697             if (reverse) {
2698                 ln = ln->backward;
2699             } else {
2700                 ln = ln->level[0].forward;
2701             }
2702         }
2703 
2704         while (ln && limit--) {
2705             /* Abort when the node is no longer in range. */
2706             if (reverse) {
2707                 if (!zslLexValueGteMin(ln->obj,&range)) break;
2708             } else {
2709                 if (!zslLexValueLteMax(ln->obj,&range)) break;
2710             }
2711 
2712             rangelen++;
2713             addReplyBulk(c,ln->obj);
2714 
2715             /* Move to next node */
2716             if (reverse) {
2717                 ln = ln->backward;
2718             } else {
2719                 ln = ln->level[0].forward;
2720             }
2721         }
2722     } else {
2723         redisPanic("Unknown sorted set encoding");
2724     }
2725 
2726     zslFreeLexRange(&range);
2727     setDeferredMultiBulkLength(c, replylen, rangelen);
2728 }
2729 
2730 void zrangebylexCommand(redisClient *c) {
2731     genericZrangebylexCommand(c,0);
2732 }
2733 
2734 void zrevrangebylexCommand(redisClient *c) {
2735     genericZrangebylexCommand(c,1);
2736 }
2737 
2738 void zcardCommand(redisClient *c) {
2739     robj *key = c->argv[1];
2740     robj *zobj;
2741 
2742     if ((zobj = lookupKeyReadOrReply(c,key,shared.czero)) == NULL ||
2743         checkType(c,zobj,REDIS_ZSET)) return;
2744 
2745     addReplyLongLong(c,zsetLength(zobj));
2746 }
2747 
2748 void zscoreCommand(redisClient *c) {
2749     robj *key = c->argv[1];
2750     robj *zobj;
2751     double score;
2752 
2753     if ((zobj = lookupKeyReadOrReply(c,key,shared.nullbulk)) == NULL ||
2754         checkType(c,zobj,REDIS_ZSET)) return;
2755 
2756     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2757         if (zzlFind(zobj->ptr,c->argv[2],&score) != NULL)
2758             addReplyDouble(c,score);
2759         else
2760             addReply(c,shared.nullbulk);
2761     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2762         zset *zs = zobj->ptr;
2763         dictEntry *de;
2764 
2765         c->argv[2] = tryObjectEncoding(c->argv[2]);
2766         de = dictFind(zs->dict,c->argv[2]);
2767         if (de != NULL) {
2768             score = *(double*)dictGetVal(de);
2769             addReplyDouble(c,score);
2770         } else {
2771             addReply(c,shared.nullbulk);
2772         }
2773     } else {
2774         redisPanic("Unknown sorted set encoding");
2775     }
2776 }
2777 
2778 void zrankGenericCommand(redisClient *c, int reverse) {
2779     robj *key = c->argv[1];
2780     robj *ele = c->argv[2];
2781     robj *zobj;
2782     unsigned long llen;
2783     unsigned long rank;
2784 
2785     if ((zobj = lookupKeyReadOrReply(c,key,shared.nullbulk)) == NULL ||
2786         checkType(c,zobj,REDIS_ZSET)) return;
2787     llen = zsetLength(zobj);
2788 
2789     redisAssertWithInfo(c,ele,sdsEncodedObject(ele));
2790 
2791     if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
2792         unsigned char *zl = zobj->ptr;
2793         unsigned char *eptr, *sptr;
2794 
2795         eptr = ziplistIndex(zl,0);
2796         redisAssertWithInfo(c,zobj,eptr != NULL);
2797         sptr = ziplistNext(zl,eptr);
2798         redisAssertWithInfo(c,zobj,sptr != NULL);
2799 
2800         rank = 1;
2801         while(eptr != NULL) {
2802             if (ziplistCompare(eptr,ele->ptr,sdslen(ele->ptr)))
2803                 break;
2804             rank++;
2805             zzlNext(zl,&eptr,&sptr);
2806         }
2807 
2808         if (eptr != NULL) {
2809             if (reverse)
2810                 addReplyLongLong(c,llen-rank);
2811             else
2812                 addReplyLongLong(c,rank-1);
2813         } else {
2814             addReply(c,shared.nullbulk);
2815         }
2816     } else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
2817         zset *zs = zobj->ptr;
2818         zskiplist *zsl = zs->zsl;
2819         dictEntry *de;
2820         double score;
2821 
2822         ele = c->argv[2] = tryObjectEncoding(c->argv[2]);
2823         de = dictFind(zs->dict,ele);
2824         if (de != NULL) {
2825             score = *(double*)dictGetVal(de);
2826             rank = zslGetRank(zsl,score,ele);
2827             redisAssertWithInfo(c,ele,rank); /* Existing elements always have a rank. */
2828             if (reverse)
2829                 addReplyLongLong(c,llen-rank);
2830             else
2831                 addReplyLongLong(c,rank-1);
2832         } else {
2833             addReply(c,shared.nullbulk);
2834         }
2835     } else {
2836         redisPanic("Unknown sorted set encoding");
2837     }
2838 }
2839 
2840 void zrankCommand(redisClient *c) {
2841     zrankGenericCommand(c, 0);
2842 }
2843 
2844 void zrevrankCommand(redisClient *c) {
2845     zrankGenericCommand(c, 1);
2846 }
2847 
2848 void zscanCommand(redisClient *c) {
2849     robj *o;
2850     unsigned long cursor;
2851 
2852     if (parseScanCursorOrReply(c,c->argv[2],&cursor) == REDIS_ERR) return;
2853     if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptyscan)) == NULL ||
2854         checkType(c,o,REDIS_ZSET)) return;
2855     scanGenericCommand(c,o,cursor);
2856 }
2857