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