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) { ...@@ -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.*/ /* Return slot-specific dictionary for key based on key's hash slot in CME, or 0 in CMD.*/
dict *getDict(redisDb *db, sds key) { dict *getDict(redisDb *db, sds key) {
if (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->current_dict; return db->dict[db->command_slot];
} }
return db->dict[(server.cluster_enabled ? keyHashSlot(key, (int) sdslen(key)) : 0)]; return db->dict[(server.cluster_enabled ? keyHashSlot(key, (int) sdslen(key)) : 0)];
} }
......
...@@ -446,13 +446,17 @@ static int scriptVerifyClusterState(scriptRunCtx *run_ctx, client *c, client *or ...@@ -446,13 +446,17 @@ static int scriptVerifyClusterState(scriptRunCtx *run_ctx, client *c, client *or
/* If the script declared keys in advanced, the cross slot error would have /* 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 * already been thrown. This is only checking for cross slot keys being accessed
* that weren't pre-declared. */ * that weren't pre-declared. */
if (hashslot != -1 && !(run_ctx->flags & SCRIPT_ALLOW_CROSS_SLOT)) { if (hashslot != -1) {
if (original_c->slot == -1) { if (run_ctx->flags & SCRIPT_ALLOW_CROSS_SLOT) {
original_c->slot = hashslot; 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 != hashslot) { } else {
*err = sdsnew("Script attempted to access keys that do not hash to " if (original_c->slot == -1) {
"the same slot"); original_c->slot = hashslot;
return C_ERR; } else if (original_c->slot != hashslot) {
*err = sdsnew("Script attempted to access keys that do not hash to "
"the same slot");
return C_ERR;
}
} }
} }
return C_OK; return C_OK;
......
...@@ -2593,7 +2593,7 @@ void initServer(void) { ...@@ -2593,7 +2593,7 @@ void initServer(void) {
server.db[j].defrag_later = listCreate(); server.db[j].defrag_later = listCreate();
server.db[j].rehashing = listCreate(); server.db[j].rehashing = listCreate();
server.db[j].dict_count = slotCount; 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); listSetFreeMethod(server.db[j].defrag_later,(void (*)(void*))sdsfree);
} }
evictionPoolAlloc(); /* Initialize the LRU keys pool. */ evictionPoolAlloc(); /* Initialize the LRU keys pool. */
...@@ -4100,7 +4100,7 @@ int processCommand(client *c) { ...@@ -4100,7 +4100,7 @@ int processCommand(client *c) {
return C_OK; return C_OK;
} }
/* Set current dictionary for the command, this optimization helps avoid redundant CRC hash calculations to determine key slot. */ /* 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 */ /* Exec the command */
if (c->flags & CLIENT_MULTI && if (c->flags & CLIENT_MULTI &&
c->cmd->proc != execCommand && c->cmd->proc != execCommand &&
...@@ -4118,7 +4118,10 @@ int processCommand(client *c) { ...@@ -4118,7 +4118,10 @@ int processCommand(client *c) {
if (listLength(server.ready_keys)) if (listLength(server.ready_keys))
handleClientsBlockedOnKeys(); 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; return C_OK;
} }
......
...@@ -959,7 +959,7 @@ typedef struct redisDb { ...@@ -959,7 +959,7 @@ typedef struct redisDb {
list *defrag_later; /* List of key names to attempt to defrag one by one, gradually. */ 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. */ 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. */ 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; } redisDb;
/* forward declaration for functions ctx */ /* 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