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