X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/9791f0f8ceb18e2e3c297a8c479307b7af0f9830..73b9e8aedfc42d4b4b9f2902969e8bc219736f3d:/src/db.c diff --git a/src/db.c b/src/db.c index 9bc299ca..354f9045 100644 --- a/src/db.c +++ b/src/db.c @@ -2,6 +2,9 @@ #include +void SlotToKeyAdd(robj *key); +void SlotToKeyDel(robj *key); + /*----------------------------------------------------------------------------- * C-level DB API *----------------------------------------------------------------------------*/ @@ -131,6 +134,7 @@ int dbAdd(redisDb *db, robj *key, robj *val) { sds copy = sdsdup(key->ptr); dictAdd(db->dict, copy, val); if (server.ds_enabled) cacheSetKeyMayExist(db,key); + if (server.cluster_enabled) SlotToKeyAdd(key); return REDIS_OK; } } @@ -146,6 +150,7 @@ int dbReplace(redisDb *db, robj *key, robj *val) { if ((oldval = dictFetchValue(db->dict,key->ptr)) == NULL) { sds copy = sdsdup(key->ptr); dictAdd(db->dict, copy, val); + if (server.cluster_enabled) SlotToKeyAdd(key); retval = 1; } else { dictReplace(db->dict, key->ptr, val); @@ -198,7 +203,12 @@ int dbDelete(redisDb *db, robj *key) { /* Deleting an entry from the expires dict will not free the sds of * the key, because it is shared with the main dictionary. */ if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr); - return dictDelete(db->dict,key->ptr) == DICT_OK; + if (dictDelete(db->dict,key->ptr) == DICT_OK) { + if (server.cluster_enabled) SlotToKeyDel(key); + return 1; + } else { + return 0; + } } /* Empty the whole database. @@ -307,6 +317,10 @@ void existsCommand(redisClient *c) { void selectCommand(redisClient *c) { int id = atoi(c->argv[1]->ptr); + if (server.cluster_enabled && id != 0) { + addReplyError(c,"SELECT is not allowed in cluster mode"); + return; + } if (selectDb(c,id) == REDIS_ERR) { addReplyError(c,"invalid DB index"); } else { @@ -428,6 +442,11 @@ void moveCommand(redisClient *c) { redisDb *src, *dst; int srcid; + if (server.cluster_enabled) { + addReplyError(c,"MOVE is not allowed in cluster mode"); + return; + } + /* Obtain source and target DB pointers */ src = c->db; srcid = c->db->id; @@ -634,8 +653,9 @@ int *getKeysUsingCommandTable(struct redisCommand *cmd,robj **argv, int argc, in keys = zmalloc(sizeof(int)*((last - cmd->firstkey)+1)); for (j = cmd->firstkey; j <= last; j += cmd->keystep) { redisAssert(j < argc); - keys[i] = j; + keys[i++] = j; } + *numkeys = i; return keys; } @@ -665,7 +685,7 @@ int *renameGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *numkeys, int *keys = zmalloc(sizeof(int)); *numkeys = 1; keys[0] = 1; - return NULL; + return keys; } else { return getKeysUsingCommandTable(cmd,argv,argc,numkeys); } @@ -683,8 +703,40 @@ int *zunionInterGetKeys(struct redisCommand *cmd,robj **argv, int argc, int *num *numkeys = 0; return NULL; } - keys = zmalloc(num); + keys = zmalloc(sizeof(int)*num); for (i = 0; i < num; i++) keys[i] = 3+i; *numkeys = num; return keys; } + +/* Slot to Key API. This is used by Redis Cluster in order to obtain in + * a fast way a key that belongs to a specified hash slot. This is useful + * while rehashing the cluster. */ +void SlotToKeyAdd(robj *key) { + unsigned int hashslot = keyHashSlot(key->ptr,sdslen(key->ptr)); + + zslInsert(server.cluster.slots_to_keys,hashslot,key); + incrRefCount(key); +} + +void SlotToKeyDel(robj *key) { + unsigned int hashslot = keyHashSlot(key->ptr,sdslen(key->ptr)); + + zslDelete(server.cluster.slots_to_keys,hashslot,key); +} + +unsigned int GetKeysInSlot(unsigned int hashslot, robj **keys, unsigned int count) { + zskiplistNode *n; + zrangespec range; + int j = 0; + + range.min = range.max = hashslot; + range.minex = range.maxex = 0; + + n = zslFirstInRange(server.cluster.slots_to_keys, range); + while(n && n->score == hashslot && count--) { + keys[j++] = n->obj; + n = n->level[0].forward; + } + return j; +}