1 /* 2 * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * * Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * * Neither the name of Redis nor the names of its contributors may be used 14 * to endorse or promote products derived from this software without 15 * specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "redis.h" 31 #include "cluster.h" 32 33 #include <signal.h> 34 #include <ctype.h> 35 36 void slotToKeyAdd(robj *key); 37 void slotToKeyDel(robj *key); 38 void slotToKeyFlush(void); 39 40 /*----------------------------------------------------------------------------- 41 * C-level DB API 42 *----------------------------------------------------------------------------*/ 43 44 robj *lookupKey(redisDb *db, robj *key) { 45 dictEntry *de = dictFind(db->dict,key->ptr); 46 if (de) { 47 robj *val = dictGetVal(de); 48 49 /* Update the access time for the ageing algorithm. 50 * Don't do it if we have a saving child, as this will trigger 51 * a copy on write madness. */ 52 if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) 53 val->lru = LRU_CLOCK(); 54 return val; 55 } else { 56 return NULL; 57 } 58 } 59 60 robj *lookupKeyRead(redisDb *db, robj *key) { 61 robj *val; 62 63 expireIfNeeded(db,key); 64 val = lookupKey(db,key); 65 if (val == NULL) 66 server.stat_keyspace_misses++; 67 else 68 server.stat_keyspace_hits++; 69 return val; 70 } 71 72 robj *lookupKeyWrite(redisDb *db, robj *key) { 73 expireIfNeeded(db,key); 74 return lookupKey(db,key); 75 } 76 77 robj *lookupKeyReadOrReply(redisClient *c, robj *key, robj *reply) { 78 robj *o = lookupKeyRead(c->db, key); 79 if (!o) addReply(c,reply); 80 return o; 81 } 82 83 robj *lookupKeyWriteOrReply(redisClient *c, robj *key, robj *reply) { 84 robj *o = lookupKeyWrite(c->db, key); 85 if (!o) addReply(c,reply); 86 return o; 87 } 88 89 /* Add the key to the DB. It's up to the caller to increment the reference 90 * counter of the value if needed. 91 * 92 * The program is aborted if the key already exists. */ 93 void dbAdd(redisDb *db, robj *key, robj *val) { 94 sds copy = sdsdup(key->ptr); 95 int retval = dictAdd(db->dict, copy, val); 96 97 redisAssertWithInfo(NULL,key,retval == REDIS_OK); 98 if (server.cluster_enabled) slotToKeyAdd(key); 99 } 100 101 /* Overwrite an existing key with a new value. Incrementing the reference 102 * count of the new value is up to the caller. 103 * This function does not modify the expire time of the existing key. 104 * 105 * The program is aborted if the key was not already present. */ 106 void dbOverwrite(redisDb *db, robj *key, robj *val) { 107 dictEntry *de = dictFind(db->dict,key->ptr); 108 109 redisAssertWithInfo(NULL,key,de != NULL); 110 dictReplace(db->dict, key->ptr, val); 111 } 112 113 /* High level Set operation. This function can be used in order to set 114 * a key, whatever it was existing or not, to a new object. 115 * 116 * 1) The ref count of the value object is incremented. 117 * 2) clients WATCHing for the destination key notified. 118 * 3) The expire time of the key is reset (the key is made persistent). */ 119 void setKey(redisDb *db, robj *key, robj *val) { 120 if (lookupKeyWrite(db,key) == NULL) { 121 dbAdd(db,key,val); 122 } else { 123 dbOverwrite(db,key,val); 124 } 125 incrRefCount(val); 126 removeExpire(db,key); 127 signalModifiedKey(db,key); 128 } 129 130 int dbExists(redisDb *db, robj *key) { 131 return dictFind(db->dict,key->ptr) != NULL; 132 } 133 134 /* Return a random key, in form of a Redis object. 135 * If there are no keys, NULL is returned. 136 * 137 * The function makes sure to return keys not already expired. */ 138 robj *dbRandomKey(redisDb *db) { 139 dictEntry *de; 140 141 while(1) { 142 sds key; 143 robj *keyobj; 144 145 de = dictGetRandomKey(db->dict); 146 if (de == NULL) return NULL; 147 148 key = dictGetKey(de); 149 keyobj = createStringObject(key,sdslen(key)); 150 if (dictFind(db->expires,key)) { 151 if (expireIfNeeded(db,keyobj)) { 152 decrRefCount(keyobj); 153 continue; /* search for another key. This expired. */ 154 } 155 } 156 return keyobj; 157 } 158 } 159 160 /* Delete a key, value, and associated expiration entry if any, from the DB */ 161 int dbDelete(redisDb *db, robj *key) { 162 /* Deleting an entry from the expires dict will not free the sds of 163 * the key, because it is shared with the main dictionary. */ 164 if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr); 165 if (dictDelete(db->dict,key->ptr) == DICT_OK) { 166 if (server.cluster_enabled) slotToKeyDel(key); 167 return 1; 168 } else { 169 return 0; 170 } 171 } 172 173 long long emptyDb(void(callback)(void*)) { 174 int j; 175 long long removed = 0; 176 177 for (j = 0; j < server.dbnum; j++) { 178 removed += dictSize(server.db[j].dict); 179 dictEmpty(server.db[j].dict,callback); 180 dictEmpty(server.db[j].expires,callback); 181 } 182 if (server.cluster_enabled) slotToKeyFlush(); 183 return removed; 184 } 185 186 int selectDb(redisClient *c, int id) { 187 if (id < 0 || id >= server.dbnum) 188 return REDIS_ERR; 189 c->db = &server.db[id]; 190 return REDIS_OK; 191 } 192 193 /*----------------------------------------------------------------------------- 194 * Hooks for key space changes. 195 * 196 * Every time a key in the database is modified the function 197 * signalModifiedKey() is called. 198 * 199 * Every time a DB is flushed the function signalFlushDb() is called. 200 *----------------------------------------------------------------------------*/ 201 202 void signalModifiedKey(redisDb *db, robj *key) { 203 touchWatchedKey(db,key); 204 } 205 206 void signalFlushedDb(int dbid) { 207 touchWatchedKeysOnFlush(dbid); 208 } 209 210 /*----------------------------------------------------------------------------- 211 * Type agnostic commands operating on the key space 212 *----------------------------------------------------------------------------*/ 213 214 void flushdbCommand(redisClient *c) { 215 server.dirty += dictSize(c->db->dict); 216 signalFlushedDb(c->db->id); 217 dictEmpty(c->db->dict,NULL); 218 dictEmpty(c->db->expires,NULL); 219 if (server.cluster_enabled) slotToKeyFlush(); 220 addReply(c,shared.ok); 221 } 222 223 void flushallCommand(redisClient *c) { 224 signalFlushedDb(-1); 225 server.dirty += emptyDb(NULL); 226 addReply(c,shared.ok); 227 if (server.rdb_child_pid != -1) { 228 kill(server.rdb_child_pid,SIGUSR1); 229 rdbRemoveTempFile(server.rdb_child_pid); 230 } 231 if (server.saveparamslen > 0) { 232 /* Normally rdbSave() will reset dirty, but we don't want this here 233 * as otherwise FLUSHALL will not be replicated nor put into the AOF. */ 234 int saved_dirty = server.dirty; 235 rdbSave(server.rdb_filename); 236 server.dirty = saved_dirty; 237 } 238 server.dirty++; 239 } 240 241 void delCommand(redisClient *c) { 242 int deleted = 0, j; 243 244 for (j = 1; j < c->argc; j++) { 245 if (dbDelete(c->db,c->argv[j])) { 246 signalModifiedKey(c->db,c->argv[j]); 247 notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC, 248 "del",c->argv[j],c->db->id); 249 server.dirty++; 250 deleted++; 251 } 252 } 253 addReplyLongLong(c,deleted); 254 } 255 256 void existsCommand(redisClient *c) { 257 expireIfNeeded(c->db,c->argv[1]); 258 if (dbExists(c->db,c->argv[1])) { 259 addReply(c, shared.cone); 260 } else { 261 addReply(c, shared.czero); 262 } 263 } 264 265 void selectCommand(redisClient *c) { 266 long id; 267 268 if (getLongFromObjectOrReply(c, c->argv[1], &id, 269 "invalid DB index") != REDIS_OK) 270 return; 271 272 if (server.cluster_enabled && id != 0) { 273 addReplyError(c,"SELECT is not allowed in cluster mode"); 274 return; 275 } 276 if (selectDb(c,id) == REDIS_ERR) { 277 addReplyError(c,"invalid DB index"); 278 } else { 279 addReply(c,shared.ok); 280 } 281 } 282 283 void randomkeyCommand(redisClient *c) { 284 robj *key; 285 286 if ((key = dbRandomKey(c->db)) == NULL) { 287 addReply(c,shared.nullbulk); 288 return; 289 } 290 291 addReplyBulk(c,key); 292 decrRefCount(key); 293 } 294 295 void keysCommand(redisClient *c) { 296 dictIterator *di; 297 dictEntry *de; 298 sds pattern = c->argv[1]->ptr; 299 int plen = sdslen(pattern), allkeys; 300 unsigned long numkeys = 0; 301 void *replylen = addDeferredMultiBulkLength(c); 302 303 di = dictGetSafeIterator(c->db->dict); 304 allkeys = (pattern[0] == '*' && pattern[1] == '\0'); 305 while((de = dictNext(di)) != NULL) { 306 sds key = dictGetKey(de); 307 robj *keyobj; 308 309 if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) { 310 keyobj = createStringObject(key,sdslen(key)); 311 if (expireIfNeeded(c->db,keyobj) == 0) { 312 addReplyBulk(c,keyobj); 313 numkeys++; 314 } 315 decrRefCount(keyobj); 316 } 317 } 318 dictReleaseIterator(di); 319 setDeferredMultiBulkLength(c,replylen,numkeys); 320 } 321 322 /* This callback is used by scanGenericCommand in order to collect elements 323 * returned by the dictionary iterator into a list. */ 324 void scanCallback(void *privdata, const dictEntry *de) { 325 void **pd = (void**) privdata; 326 list *keys = pd[0]; 327 robj *o = pd[1]; 328 robj *key, *val = NULL; 329 330 if (o == NULL) { 331 sds sdskey = dictGetKey(de); 332 key = createStringObject(sdskey, sdslen(sdskey)); 333 } else if (o->type == REDIS_SET) { 334 key = dictGetKey(de); 335 incrRefCount(key); 336 } else if (o->type == REDIS_HASH) { 337 key = dictGetKey(de); 338 incrRefCount(key); 339 val = dictGetVal(de); 340 incrRefCount(val); 341 } else if (o->type == REDIS_ZSET) { 342 key = dictGetKey(de); 343 incrRefCount(key); 344 val = createStringObjectFromLongDouble(*(double*)dictGetVal(de)); 345 } else { 346 redisPanic("Type not handled in SCAN callback."); 347 } 348 349 listAddNodeTail(keys, key); 350 if (val) listAddNodeTail(keys, val); 351 } 352 353 /* Try to parse a SCAN cursor stored at object 'o': 354 * if the cursor is valid, store it as unsigned integer into *cursor and 355 * returns REDIS_OK. Otherwise return REDIS_ERR and send an error to the 356 * client. */ 357 int parseScanCursorOrReply(redisClient *c, robj *o, unsigned long *cursor) { 358 char *eptr; 359 360 /* Use strtoul() because we need an *unsigned* long, so 361 * getLongLongFromObject() does not cover the whole cursor space. */ 362 errno = 0; 363 *cursor = strtoul(o->ptr, &eptr, 10); 364 if (isspace(((char*)o->ptr)[0]) || eptr[0] != '\0' || errno == ERANGE) 365 { 366 addReplyError(c, "invalid cursor"); 367 return REDIS_ERR; 368 } 369 return REDIS_OK; 370 } 371 372 /* This command implements SCAN, HSCAN and SSCAN commands. 373 * If object 'o' is passed, then it must be a Hash or Set object, otherwise 374 * if 'o' is NULL the command will operate on the dictionary associated with 375 * the current database. 376 * 377 * When 'o' is not NULL the function assumes that the first argument in 378 * the client arguments vector is a key so it skips it before iterating 379 * in order to parse options. 380 * 381 * In the case of a Hash object the function returns both the field and value 382 * of every element on the Hash. */ 383 void scanGenericCommand(redisClient *c, robj *o, unsigned long cursor) { 384 int rv; 385 int i, j; 386 char buf[REDIS_LONGSTR_SIZE]; 387 list *keys = listCreate(); 388 listNode *node, *nextnode; 389 long count = 10; 390 sds pat; 391 int patlen, use_pattern = 0; 392 dict *ht; 393 394 /* Object must be NULL (to iterate keys names), or the type of the object 395 * must be Set, Sorted Set, or Hash. */ 396 redisAssert(o == NULL || o->type == REDIS_SET || o->type == REDIS_HASH || 397 o->type == REDIS_ZSET); 398 399 /* Set i to the first option argument. The previous one is the cursor. */ 400 i = (o == NULL) ? 2 : 3; /* Skip the key argument if needed. */ 401 402 /* Step 1: Parse options. */ 403 while (i < c->argc) { 404 j = c->argc - i; 405 if (!strcasecmp(c->argv[i]->ptr, "count") && j >= 2) { 406 if (getLongFromObjectOrReply(c, c->argv[i+1], &count, NULL) 407 != REDIS_OK) 408 { 409 goto cleanup; 410 } 411 412 if (count < 1) { 413 addReply(c,shared.syntaxerr); 414 goto cleanup; 415 } 416 417 i += 2; 418 } else if (!strcasecmp(c->argv[i]->ptr, "match") && j >= 2) { 419 pat = c->argv[i+1]->ptr; 420 patlen = sdslen(pat); 421 422 /* The pattern always matches if it is exactly "*", so it is 423 * equivalent to disabling it. */ 424 use_pattern = !(pat[0] == '*' && patlen == 1); 425 426 i += 2; 427 } else { 428 addReply(c,shared.syntaxerr); 429 goto cleanup; 430 } 431 } 432 433 /* Step 2: Iterate the collection. 434 * 435 * Note that if the object is encoded with a ziplist, intset, or any other 436 * representation that is not a hash table, we are sure that it is also 437 * composed of a small number of elements. So to avoid taking state we 438 * just return everything inside the object in a single call, setting the 439 * cursor to zero to signal the end of the iteration. */ 440 441 /* Handle the case of a hash table. */ 442 ht = NULL; 443 if (o == NULL) { 444 ht = c->db->dict; 445 } else if (o->type == REDIS_SET && o->encoding == REDIS_ENCODING_HT) { 446 ht = o->ptr; 447 } else if (o->type == REDIS_HASH && o->encoding == REDIS_ENCODING_HT) { 448 ht = o->ptr; 449 count *= 2; /* We return key / value for this type. */ 450 } else if (o->type == REDIS_ZSET && o->encoding == REDIS_ENCODING_SKIPLIST) { 451 zset *zs = o->ptr; 452 ht = zs->dict; 453 count *= 2; /* We return key / value for this type. */ 454 } 455 456 if (ht) { 457 void *privdata[2]; 458 459 /* We pass two pointers to the callback: the list to which it will 460 * add new elements, and the object containing the dictionary so that 461 * it is possible to fetch more data in a type-dependent way. */ 462 privdata[0] = keys; 463 privdata[1] = o; 464 do { 465 cursor = dictScan(ht, cursor, scanCallback, privdata); 466 } while (cursor && listLength(keys) < count); 467 } else if (o->type == REDIS_SET) { 468 int pos = 0; 469 int64_t ll; 470 471 while(intsetGet(o->ptr,pos++,&ll)) 472 listAddNodeTail(keys,createStringObjectFromLongLong(ll)); 473 cursor = 0; 474 } else if (o->type == REDIS_HASH || o->type == REDIS_ZSET) { 475 unsigned char *p = ziplistIndex(o->ptr,0); 476 unsigned char *vstr; 477 unsigned int vlen; 478 long long vll; 479 480 while(p) { 481 ziplistGet(p,&vstr,&vlen,&vll); 482 listAddNodeTail(keys, 483 (vstr != NULL) ? createStringObject((char*)vstr,vlen) : 484 createStringObjectFromLongLong(vll)); 485 p = ziplistNext(o->ptr,p); 486 } 487 cursor = 0; 488 } else { 489 redisPanic("Not handled encoding in SCAN."); 490 } 491 492 /* Step 3: Filter elements. */ 493 node = listFirst(keys); 494 while (node) { 495 robj *kobj = listNodeValue(node); 496 nextnode = listNextNode(node); 497 int filter = 0; 498 499 /* Filter element if it does not match the pattern. */ 500 if (!filter && use_pattern) { 501 if (sdsEncodedObject(kobj)) { 502 if (!stringmatchlen(pat, patlen, kobj->ptr, sdslen(kobj->ptr), 0)) 503 filter = 1; 504 } else { 505 char buf[REDIS_LONGSTR_SIZE]; 506 int len; 507 508 redisAssert(kobj->encoding == REDIS_ENCODING_INT); 509 len = ll2string(buf,sizeof(buf),(long)kobj->ptr); 510 if (!stringmatchlen(pat, patlen, buf, len, 0)) filter = 1; 511 } 512 } 513 514 /* Filter element if it is an expired key. */ 515 if (!filter && o == NULL && expireIfNeeded(c->db, kobj)) filter = 1; 516 517 /* Remove the element and its associted value if needed. */ 518 if (filter) { 519 decrRefCount(kobj); 520 listDelNode(keys, node); 521 } 522 523 /* If this is a hash or a sorted set, we have a flat list of 524 * key-value elements, so if this element was filtered, remove the 525 * value, or skip it if it was not filtered: we only match keys. */ 526 if (o && (o->type == REDIS_ZSET || o->type == REDIS_HASH)) { 527 node = nextnode; 528 nextnode = listNextNode(node); 529 if (filter) { 530 kobj = listNodeValue(node); 531 decrRefCount(kobj); 532 listDelNode(keys, node); 533 } 534 } 535 node = nextnode; 536 } 537 538 /* Step 4: Reply to the client. */ 539 addReplyMultiBulkLen(c, 2); 540 rv = snprintf(buf, sizeof(buf), "%lu", cursor); 541 redisAssert(rv < sizeof(buf)); 542 addReplyBulkCBuffer(c, buf, rv); 543 544 addReplyMultiBulkLen(c, listLength(keys)); 545 while ((node = listFirst(keys)) != NULL) { 546 robj *kobj = listNodeValue(node); 547 addReplyBulk(c, kobj); 548 decrRefCount(kobj); 549 listDelNode(keys, node); 550 } 551 552 cleanup: 553 listSetFreeMethod(keys,decrRefCountVoid); 554 listRelease(keys); 555 } 556 557 /* The SCAN command completely relies on scanGenericCommand. */ 558 void scanCommand(redisClient *c) { 559 unsigned long cursor; 560 if (parseScanCursorOrReply(c,c->argv[1],&cursor) == REDIS_ERR) return; 561 scanGenericCommand(c,NULL,cursor); 562 } 563 564 void dbsizeCommand(redisClient *c) { 565 addReplyLongLong(c,dictSize(c->db->dict)); 566 } 567 568 void lastsaveCommand(redisClient *c) { 569 addReplyLongLong(c,server.lastsave); 570 } 571 572 void typeCommand(redisClient *c) { 573 robj *o; 574 char *type; 575 576 o = lookupKeyRead(c->db,c->argv[1]); 577 if (o == NULL) { 578 type = "none"; 579 } else { 580 switch(o->type) { 581 case REDIS_STRING: type = "string"; break; 582 case REDIS_LIST: type = "list"; break; 583 case REDIS_SET: type = "set"; break; 584 case REDIS_ZSET: type = "zset"; break; 585 case REDIS_HASH: type = "hash"; break; 586 default: type = "unknown"; break; 587 } 588 } 589 addReplyStatus(c,type); 590 } 591 592 void shutdownCommand(redisClient *c) { 593 int flags = 0; 594 595 if (c->argc > 2) { 596 addReply(c,shared.syntaxerr); 597 return; 598 } else if (c->argc == 2) { 599 if (!strcasecmp(c->argv[1]->ptr,"nosave")) { 600 flags |= REDIS_SHUTDOWN_NOSAVE; 601 } else if (!strcasecmp(c->argv[1]->ptr,"save")) { 602 flags |= REDIS_SHUTDOWN_SAVE; 603 } else { 604 addReply(c,shared.syntaxerr); 605 return; 606 } 607 } 608 /* When SHUTDOWN is called while the server is loading a dataset in 609 * memory we need to make sure no attempt is performed to save 610 * the dataset on shutdown (otherwise it could overwrite the current DB 611 * with half-read data). 612 * 613 * Also when in Sentinel mode clear the SAVE flag and force NOSAVE. */ 614 if (server.loading || server.sentinel_mode) 615 flags = (flags & ~REDIS_SHUTDOWN_SAVE) | REDIS_SHUTDOWN_NOSAVE; 616 if (prepareForShutdown(flags) == REDIS_OK) exit(0); 617 addReplyError(c,"Errors trying to SHUTDOWN. Check logs."); 618 } 619 620 void renameGenericCommand(redisClient *c, int nx) { 621 robj *o; 622 long long expire; 623 624 /* To use the same key as src and dst is probably an error */ 625 if (sdscmp(c->argv[1]->ptr,c->argv[2]->ptr) == 0) { 626 addReply(c,shared.sameobjecterr); 627 return; 628 } 629 630 if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr)) == NULL) 631 return; 632 633 incrRefCount(o); 634 expire = getExpire(c->db,c->argv[1]); 635 if (lookupKeyWrite(c->db,c->argv[2]) != NULL) { 636 if (nx) { 637 decrRefCount(o); 638 addReply(c,shared.czero); 639 return; 640 } 641 /* Overwrite: delete the old key before creating the new one 642 * with the same name. */ 643 dbDelete(c->db,c->argv[2]); 644 } 645 dbAdd(c->db,c->argv[2],o); 646 if (expire != -1) setExpire(c->db,c->argv[2],expire); 647 dbDelete(c->db,c->argv[1]); 648 signalModifiedKey(c->db,c->argv[1]); 649 signalModifiedKey(c->db,c->argv[2]); 650 notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"rename_from", 651 c->argv[1],c->db->id); 652 notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"rename_to", 653 c->argv[2],c->db->id); 654 server.dirty++; 655 addReply(c,nx ? shared.cone : shared.ok); 656 } 657 658 void renameCommand(redisClient *c) { 659 renameGenericCommand(c,0); 660 } 661 662 void renamenxCommand(redisClient *c) { 663 renameGenericCommand(c,1); 664 } 665 666 void moveCommand(redisClient *c) { 667 robj *o; 668 redisDb *src, *dst; 669 int srcid; 670 671 if (server.cluster_enabled) { 672 addReplyError(c,"MOVE is not allowed in cluster mode"); 673 return; 674 } 675 676 /* Obtain source and target DB pointers */ 677 src = c->db; 678 srcid = c->db->id; 679 if (selectDb(c,atoi(c->argv[2]->ptr)) == REDIS_ERR) { 680 addReply(c,shared.outofrangeerr); 681 return; 682 } 683 dst = c->db; 684 selectDb(c,srcid); /* Back to the source DB */ 685 686 /* If the user is moving using as target the same 687 * DB as the source DB it is probably an error. */ 688 if (src == dst) { 689 addReply(c,shared.sameobjecterr); 690 return; 691 } 692 693 /* Check if the element exists and get a reference */ 694 o = lookupKeyWrite(c->db,c->argv[1]); 695 if (!o) { 696 addReply(c,shared.czero); 697 return; 698 } 699 700 /* Return zero if the key already exists in the target DB */ 701 if (lookupKeyWrite(dst,c->argv[1]) != NULL) { 702 addReply(c,shared.czero); 703 return; 704 } 705 dbAdd(dst,c->argv[1],o); 706 incrRefCount(o); 707 708 /* OK! key moved, free the entry in the source DB */ 709 dbDelete(src,c->argv[1]); 710 server.dirty++; 711 addReply(c,shared.cone); 712 } 713 714 /*----------------------------------------------------------------------------- 715 * Expires API 716 *----------------------------------------------------------------------------*/ 717 718 int removeExpire(redisDb *db, robj *key) { 719 /* An expire may only be removed if there is a corresponding entry in the 720 * main dict. Otherwise, the key will never be freed. */ 721 redisAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr) != NULL); 722 return dictDelete(db->expires,key->ptr) == DICT_OK; 723 } 724 725 void setExpire(redisDb *db, robj *key, long long when) { 726 dictEntry *kde, *de; 727 728 /* Reuse the sds from the main dict in the expire dict */ 729 kde = dictFind(db->dict,key->ptr); 730 redisAssertWithInfo(NULL,key,kde != NULL); 731 de = dictReplaceRaw(db->expires,dictGetKey(kde)); 732 dictSetSignedIntegerVal(de,when); 733 } 734 735 /* Return the expire time of the specified key, or -1 if no expire 736 * is associated with this key (i.e. the key is non volatile) */ 737 long long getExpire(redisDb *db, robj *key) { 738 dictEntry *de; 739 740 /* No expire? return ASAP */ 741 if (dictSize(db->expires) == 0 || 742 (de = dictFind(db->expires,key->ptr)) == NULL) return -1; 743 744 /* The entry was found in the expire dict, this means it should also 745 * be present in the main dict (safety check). */ 746 redisAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr) != NULL); 747 return dictGetSignedIntegerVal(de); 748 } 749 750 /* Propagate expires into slaves and the AOF file. 751 * When a key expires in the master, a DEL operation for this key is sent 752 * to all the slaves and the AOF file if enabled. 753 * 754 * This way the key expiry is centralized in one place, and since both 755 * AOF and the master->slave link guarantee operation ordering, everything 756 * will be consistent even if we allow write operations against expiring 757 * keys. */ 758 void propagateExpire(redisDb *db, robj *key) { 759 robj *argv[2]; 760 761 argv[0] = shared.del; 762 argv[1] = key; 763 incrRefCount(argv[0]); 764 incrRefCount(argv[1]); 765 766 if (server.aof_state != REDIS_AOF_OFF) 767 feedAppendOnlyFile(server.delCommand,db->id,argv,2); 768 replicationFeedSlaves(server.slaves,db->id,argv,2); 769 770 decrRefCount(argv[0]); 771 decrRefCount(argv[1]); 772 } 773 774 int expireIfNeeded(redisDb *db, robj *key) { 775 mstime_t when = getExpire(db,key); 776 mstime_t now; 777 778 if (when < 0) return 0; /* No expire for this key */ 779 780 /* Don't expire anything while loading. It will be done later. */ 781 if (server.loading) return 0; 782 783 /* If we are in the context of a Lua script, we claim that time is 784 * blocked to when the Lua script started. This way a key can expire 785 * only the first time it is accessed and not in the middle of the 786 * script execution, making propagation to slaves / AOF consistent. 787 * See issue #1525 on Github for more information. */ 788 now = server.lua_caller ? server.lua_time_start : mstime(); 789 790 /* If we are running in the context of a slave, return ASAP: 791 * the slave key expiration is controlled by the master that will 792 * send us synthesized DEL operations for expired keys. 793 * 794 * Still we try to return the right information to the caller, 795 * that is, 0 if we think the key should be still valid, 1 if 796 * we think the key is expired at this time. */ 797 if (server.masterhost != NULL) return now > when; 798 799 /* Return when this key has not expired */ 800 if (now <= when) return 0; 801 802 /* Delete the key */ 803 server.stat_expiredkeys++; 804 propagateExpire(db,key); 805 notifyKeyspaceEvent(REDIS_NOTIFY_EXPIRED, 806 "expired",key,db->id); 807 return dbDelete(db,key); 808 } 809 810 /*----------------------------------------------------------------------------- 811 * Expires Commands 812 *----------------------------------------------------------------------------*/ 813 814 /* This is the generic command implementation for EXPIRE, PEXPIRE, EXPIREAT 815 * and PEXPIREAT. Because the commad second argument may be relative or absolute 816 * the "basetime" argument is used to signal what the base time is (either 0 817 * for *AT variants of the command, or the current time for relative expires). 818 * 819 * unit is either UNIT_SECONDS or UNIT_MILLISECONDS, and is only used for 820 * the argv[2] parameter. The basetime is always specified in milliseconds. */ 821 void expireGenericCommand(redisClient *c, long long basetime, int unit) { 822 robj *key = c->argv[1], *param = c->argv[2]; 823 long long when; /* unix time in milliseconds when the key will expire. */ 824 825 if (getLongLongFromObjectOrReply(c, param, &when, NULL) != REDIS_OK) 826 return; 827 828 if (unit == UNIT_SECONDS) when *= 1000; 829 when += basetime; 830 831 /* No key, return zero. */ 832 if (lookupKeyRead(c->db,key) == NULL) { 833 addReply(c,shared.czero); 834 return; 835 } 836 837 /* EXPIRE with negative TTL, or EXPIREAT with a timestamp into the past 838 * should never be executed as a DEL when load the AOF or in the context 839 * of a slave instance. 840 * 841 * Instead we take the other branch of the IF statement setting an expire 842 * (possibly in the past) and wait for an explicit DEL from the master. */ 843 if (when <= mstime() && !server.loading && !server.masterhost) { 844 robj *aux; 845 846 redisAssertWithInfo(c,key,dbDelete(c->db,key)); 847 server.dirty++; 848 849 /* Replicate/AOF this as an explicit DEL. */ 850 aux = createStringObject("DEL",3); 851 rewriteClientCommandVector(c,2,aux,key); 852 decrRefCount(aux); 853 signalModifiedKey(c->db,key); 854 notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"del",key,c->db->id); 855 addReply(c, shared.cone); 856 return; 857 } else { 858 setExpire(c->db,key,when); 859 addReply(c,shared.cone); 860 signalModifiedKey(c->db,key); 861 notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"expire",key,c->db->id); 862 server.dirty++; 863 return; 864 } 865 } 866 867 void expireCommand(redisClient *c) { 868 expireGenericCommand(c,mstime(),UNIT_SECONDS); 869 } 870 871 void expireatCommand(redisClient *c) { 872 expireGenericCommand(c,0,UNIT_SECONDS); 873 } 874 875 void pexpireCommand(redisClient *c) { 876 expireGenericCommand(c,mstime(),UNIT_MILLISECONDS); 877 } 878 879 void pexpireatCommand(redisClient *c) { 880 expireGenericCommand(c,0,UNIT_MILLISECONDS); 881 } 882 883 void ttlGenericCommand(redisClient *c, int output_ms) { 884 long long expire, ttl = -1; 885 886 /* If the key does not exist at all, return -2 */ 887 if (lookupKeyRead(c->db,c->argv[1]) == NULL) { 888 addReplyLongLong(c,-2); 889 return; 890 } 891 /* The key exists. Return -1 if it has no expire, or the actual 892 * TTL value otherwise. */ 893 expire = getExpire(c->db,c->argv[1]); 894 if (expire != -1) { 895 ttl = expire-mstime(); 896 if (ttl < 0) ttl = 0; 897 } 898 if (ttl == -1) { 899 addReplyLongLong(c,-1); 900 } else { 901 addReplyLongLong(c,output_ms ? ttl : ((ttl+500)/1000)); 902 } 903 } 904 905 void ttlCommand(redisClient *c) { 906 ttlGenericCommand(c, 0); 907 } 908 909 void pttlCommand(redisClient *c) { 910 ttlGenericCommand(c, 1); 911 } 912 913 void persistCommand(redisClient *c) { 914 dictEntry *de; 915 916 de = dictFind(c->db->dict,c->argv[1]->ptr); 917 if (de == NULL) { 918 addReply(c,shared.czero); 919 } else { 920 if (removeExpire(c->db,c->argv[1])) { 921 addReply(c,shared.cone); 922 server.dirty++; 923 } else { 924 addReply(c,shared.czero); 925 } 926 } 927 } 928 929 /* ----------------------------------------------------------------------------- 930 * API to get key arguments from commands 931 * ---------------------------------------------------------------------------*/ 932 933 /* The base case is to use the keys position as given in the command table 934 * (firstkey, lastkey, step). */ 935 int *getKeysUsingCommandTable(struct redisCommand *cmd,robj **argv, int argc, int *numkeys) { 936 int j, i = 0, last, *keys; 937 REDIS_NOTUSED(argv); 938 939 if (cmd->firstkey == 0) { 940 *numkeys = 0; 941 return NULL; 942 } 943 last = cmd->lastkey; 944 if (last < 0) last = argc+last; 945 keys = zmalloc(sizeof(int)*((last - cmd->firstkey)+1)); 946 for (j = cmd->firstkey; j <= last; j += cmd->keystep) { 947 redisAssert(j < argc); 948 keys[i++] = j; 949 } 950 *numkeys = i; 951 return keys; 952 } 953 954 /* Return all the arguments that are keys in the command passed via argc / argv. 955 * 956 * The command returns the positions of all the key arguments inside the array, 957 * so the actual return value is an heap allocated array of integers. The 958 * length of the array is returned by reference into *numkeys. 959 * 960 * 'cmd' must be point to the corresponding entry into the redisCommand 961 * table, according to the command name in argv[0]. 962 * 963 * This function uses the command table if a command-specific helper function 964 * is not required, otherwise it calls the command-specific function. */ 965 int *getKeysFromCommand(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) { 966 if (cmd->getkeys_proc) { 967 return cmd->getkeys_proc(cmd,argv,argc,numkeys); 968 } else { 969 return getKeysUsingCommandTable(cmd,argv,argc,numkeys); 970 } 971 } 972 973 /* Free the result of getKeysFromCommand. */ 974 void getKeysFreeResult(int *result) { 975 zfree(result); 976 } 977 978 /* Helper function to extract keys from following commands: 979 * ZUNIONSTORE <destkey> <num-keys> <key> <key> ... <key> <options> 980 * ZINTERSTORE <destkey> <num-keys> <key> <key> ... <key> <options> */ 981 int *zunionInterGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) { 982 int i, num, *keys; 983 REDIS_NOTUSED(cmd); 984 985 num = atoi(argv[2]->ptr); 986 /* Sanity check. Don't return any key if the command is going to 987 * reply with syntax error. */ 988 if (num > (argc-3)) { 989 *numkeys = 0; 990 return NULL; 991 } 992 993 /* Keys in z{union,inter}store come from two places: 994 * argv[1] = storage key, 995 * argv[3...n] = keys to intersect */ 996 keys = zmalloc(sizeof(int)*(num+1)); 997 998 /* Add all key positions for argv[3...n] to keys[] */ 999 for (i = 0; i < num; i++) keys[i] = 3+i; 1000 1001 /* Finally add the argv[1] key position (the storage key target). */ 1002 keys[num] = 1; 1003 *numkeys = num+1; /* Total keys = {union,inter} keys + storage key */ 1004 return keys; 1005 } 1006 1007 /* Helper function to extract keys from the following commands: 1008 * EVAL <script> <num-keys> <key> <key> ... <key> [more stuff] 1009 * EVALSHA <script> <num-keys> <key> <key> ... <key> [more stuff] */ 1010 int *evalGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) { 1011 int i, num, *keys; 1012 REDIS_NOTUSED(cmd); 1013 1014 num = atoi(argv[2]->ptr); 1015 /* Sanity check. Don't return any key if the command is going to 1016 * reply with syntax error. */ 1017 if (num > (argc-3)) { 1018 *numkeys = 0; 1019 return NULL; 1020 } 1021 1022 keys = zmalloc(sizeof(int)*num); 1023 *numkeys = num; 1024 1025 /* Add all key positions for argv[3...n] to keys[] */ 1026 for (i = 0; i < num; i++) keys[i] = 3+i; 1027 1028 return keys; 1029 } 1030 1031 /* Helper function to extract keys from the SORT command. 1032 * 1033 * SORT <sort-key> ... STORE <store-key> ... 1034 * 1035 * The first argument of SORT is always a key, however a list of options 1036 * follow in SQL-alike style. Here we parse just the minimum in order to 1037 * correctly identify keys in the "STORE" option. */ 1038 int *sortGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) { 1039 int i, j, num, *keys; 1040 REDIS_NOTUSED(cmd); 1041 1042 num = 0; 1043 keys = zmalloc(sizeof(int)*2); /* Alloc 2 places for the worst case. */ 1044 1045 keys[num++] = 1; /* <sort-key> is always present. */ 1046 1047 /* Search for STORE option. By default we consider options to don't 1048 * have arguments, so if we find an unknown option name we scan the 1049 * next. However there are options with 1 or 2 arguments, so we 1050 * provide a list here in order to skip the right number of args. */ 1051 struct { 1052 char *name; 1053 int skip; 1054 } skiplist[] = { 1055 {"limit", 2}, 1056 {"get", 1}, 1057 {"by", 1}, 1058 {NULL, 0} /* End of elements. */ 1059 }; 1060 1061 for (i = 2; i < argc; i++) { 1062 for (j = 0; skiplist[j].name != NULL; j++) { 1063 if (!strcasecmp(argv[i]->ptr,skiplist[j].name)) { 1064 i += skiplist[j].skip; 1065 break; 1066 } else if (!strcasecmp(argv[i]->ptr,"store") && i+1 < argc) { 1067 /* Note: we don't increment "num" here and continue the loop 1068 * to be sure to process the *last* "STORE" option if multiple 1069 * ones are provided. This is same behavior as SORT. */ 1070 keys[num] = i+1; /* <store-key> */ 1071 break; 1072 } 1073 } 1074 } 1075 *numkeys = num; 1076 return keys; 1077 } 1078 1079 /* Slot to Key API. This is used by Redis Cluster in order to obtain in 1080 * a fast way a key that belongs to a specified hash slot. This is useful 1081 * while rehashing the cluster. */ 1082 void slotToKeyAdd(robj *key) { 1083 unsigned int hashslot = keyHashSlot(key->ptr,sdslen(key->ptr)); 1084 1085 zslInsert(server.cluster->slots_to_keys,hashslot,key); 1086 incrRefCount(key); 1087 } 1088 1089 void slotToKeyDel(robj *key) { 1090 unsigned int hashslot = keyHashSlot(key->ptr,sdslen(key->ptr)); 1091 1092 zslDelete(server.cluster->slots_to_keys,hashslot,key); 1093 } 1094 1095 void slotToKeyFlush(void) { 1096 zslFree(server.cluster->slots_to_keys); 1097 server.cluster->slots_to_keys = zslCreate(); 1098 } 1099 1100 unsigned int getKeysInSlot(unsigned int hashslot, robj **keys, unsigned int count) { 1101 zskiplistNode *n; 1102 zrangespec range; 1103 int j = 0; 1104 1105 range.min = range.max = hashslot; 1106 range.minex = range.maxex = 0; 1107 1108 n = zslFirstInRange(server.cluster->slots_to_keys, range); 1109 while(n && n->score == hashslot && count--) { 1110 keys[j++] = n->obj; 1111 n = n->level[0].forward; 1112 } 1113 return j; 1114 } 1115 1116 unsigned int countKeysInSlot(unsigned int hashslot) { 1117 zskiplist *zsl = server.cluster->slots_to_keys; 1118 zskiplistNode *zn; 1119 zrangespec range; 1120 int rank, count = 0; 1121 1122 range.min = range.max = hashslot; 1123 range.minex = range.maxex = 0; 1124 1125 /* Find first element in range */ 1126 zn = zslFirstInRange(zsl, range); 1127 1128 /* Use rank of first element, if any, to determine preliminary count */ 1129 if (zn != NULL) { 1130 rank = zslGetRank(zsl, zn->score, zn->obj); 1131 count = (zsl->length - (rank - 1)); 1132 1133 /* Find last element in range */ 1134 zn = zslLastInRange(zsl, range); 1135 1136 /* Use rank of last element, if any, to determine the actual count */ 1137 if (zn != NULL) { 1138 rank = zslGetRank(zsl, zn->score, zn->obj); 1139 count -= (zsl->length - rank); 1140 } 1141 } 1142 return count; 1143 } 1144