]> git.saurik.com Git - redis.git/blobdiff - src/db.c
Lua scripts max execution time
[redis.git] / src / db.c
index 5bab42afd981e01515e5087c756a90ae9ea6cc28..354f904569b71a47ce693aaa2ea1f4a47949a9c8 100644 (file)
--- a/src/db.c
+++ b/src/db.c
@@ -2,6 +2,9 @@
 
 #include <signal.h>
 
+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;
@@ -666,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);
     }
@@ -684,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;
+}