Commit 2ed31392 authored by Vitaly Arbuzov's avatar Vitaly Arbuzov
Browse files

Add assertion that command slot is correct after command execution, and make...

Add assertion that command slot is correct after command execution, and make scripts that access multiple slots work correctly
parent 923c6c19
......@@ -240,8 +240,8 @@ void dbAdd(redisDb *db, robj *key, robj *val) {
/* Return slot-specific dictionary for key based on key's hash slot in CME, or 0 in CMD.*/
dict *getDict(redisDb *db, sds key) {
if (db->current_dict) {
return db->current_dict;
if (db->command_slot >= 0) { /* This is performance optimization, that uses pre-set slot id, in order to avoid calculating key hash. */
return db->dict[db->command_slot];
}
return db->dict[(server.cluster_enabled ? keyHashSlot(key, (int) sdslen(key)) : 0)];
}
......
......@@ -446,7 +446,10 @@ static int scriptVerifyClusterState(scriptRunCtx *run_ctx, client *c, client *or
/* If the script declared keys in advanced, the cross slot error would have
* already been thrown. This is only checking for cross slot keys being accessed
* that weren't pre-declared. */
if (hashslot != -1 && !(run_ctx->flags & SCRIPT_ALLOW_CROSS_SLOT)) {
if (hashslot != -1) {
if (run_ctx->flags & SCRIPT_ALLOW_CROSS_SLOT) {
original_c->db->command_slot = -1; /* Clear command slot for multislot scripts because script may access keys from differen slots. */
} else {
if (original_c->slot == -1) {
original_c->slot = hashslot;
} else if (original_c->slot != hashslot) {
......@@ -455,6 +458,7 @@ static int scriptVerifyClusterState(scriptRunCtx *run_ctx, client *c, client *or
return C_ERR;
}
}
}
return C_OK;
}
......
......@@ -2593,7 +2593,7 @@ void initServer(void) {
server.db[j].defrag_later = listCreate();
server.db[j].rehashing = listCreate();
server.db[j].dict_count = slotCount;
server.db[j].current_dict = NULL;
server.db[j].command_slot = -1;
listSetFreeMethod(server.db[j].defrag_later,(void (*)(void*))sdsfree);
}
evictionPoolAlloc(); /* Initialize the LRU keys pool. */
......@@ -4100,7 +4100,7 @@ int processCommand(client *c) {
return C_OK;
}
/* Set current dictionary for the command, this optimization helps avoid redundant CRC hash calculations to determine key slot. */
if (c->slot >= 0) c->db->current_dict = c->db->dict[c->slot];
c->db->command_slot = c->slot;
/* Exec the command */
if (c->flags & CLIENT_MULTI &&
c->cmd->proc != execCommand &&
......@@ -4118,7 +4118,10 @@ int processCommand(client *c) {
if (listLength(server.ready_keys))
handleClientsBlockedOnKeys();
}
c->db->current_dict = NULL;
if (c->db->command_slot != -1) {
serverAssert(c->db->command_slot == c->slot);
c->db->command_slot = -1;
}
return C_OK;
}
......
......@@ -959,7 +959,7 @@ typedef struct redisDb {
list *defrag_later; /* List of key names to attempt to defrag one by one, gradually. */
list *rehashing; /* List of dictionaries in this DB that are currently rehashing. */
int dict_count; /* Indicates total number of dictionaires owned by this DB, 1 dict per slot in cluster mode. */
dict *current_dict; /* Slot specific dictionary used in the current command, in cluster mode. */
int command_slot; /* Slot that is used by the current command that uses DB, -1 if cluster mode is disabled, or if command uses multiple slots. */
} redisDb;
/* forward declaration for functions ctx */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment