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