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