Return the pointer to the cluster node that is able to serve the command. * For the function to succeed the command should only target either: * * 1) A single key (even multiple times like LPOPRPUSH mylist mylist). * 2) Multiple keys in the same hash slot, while the slot is stable (no * resharding in progress). * * On success the function returns the node that is able to serve the reques
| 5738 | * CLUSTER_REDIR_DOWN_STATE and CLUSTER_REDIR_DOWN_RO_STATE if the cluster is |
| 5739 | * down but the user attempts to execute a command that addresses one or more keys. */ |
| 5740 | clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *error_code) { |
| 5741 | clusterNode *n = NULL; |
| 5742 | robj *firstkey = NULL; |
| 5743 | int multiple_keys = 0; |
| 5744 | multiState *ms, _ms; |
| 5745 | multiCmd mc; |
| 5746 | int i, slot = 0, migrating_slot = 0, importing_slot = 0, missing_keys = 0; |
| 5747 | |
| 5748 | /* Allow any key to be set if a module disabled cluster redirections. */ |
| 5749 | if (server.cluster_module_flags & CLUSTER_MODULE_FLAG_NO_REDIRECTION) |
| 5750 | return myself; |
| 5751 | |
| 5752 | /* Set error code optimistically for the base case. */ |
| 5753 | if (error_code) *error_code = CLUSTER_REDIR_NONE; |
| 5754 | |
| 5755 | /* Modules can turn off Redis Cluster redirection: this is useful |
| 5756 | * when writing a module that implements a completely different |
| 5757 | * distributed system. */ |
| 5758 | |
| 5759 | /* We handle all the cases as if they were EXEC commands, so we have |
| 5760 | * a common code path for everything */ |
| 5761 | if (cmd->proc == execCommand) { |
| 5762 | /* If CLIENT_MULTI flag is not set EXEC is just going to return an |
| 5763 | * error. */ |
| 5764 | if (!(c->flags & CLIENT_MULTI)) return myself; |
| 5765 | ms = &c->mstate; |
| 5766 | } else { |
| 5767 | /* In order to have a single codepath create a fake Multi State |
| 5768 | * structure if the client is not in MULTI/EXEC state, this way |
| 5769 | * we have a single codepath below. */ |
| 5770 | ms = &_ms; |
| 5771 | _ms.commands = &mc; |
| 5772 | _ms.count = 1; |
| 5773 | mc.argv = argv; |
| 5774 | mc.argc = argc; |
| 5775 | mc.cmd = cmd; |
| 5776 | } |
| 5777 | |
| 5778 | /* Check that all the keys are in the same hash slot, and obtain this |
| 5779 | * slot and the node associated. */ |
| 5780 | for (i = 0; i < ms->count; i++) { |
| 5781 | struct redisCommand *mcmd; |
| 5782 | robj **margv; |
| 5783 | int margc, *keyindex, numkeys, j; |
| 5784 | |
| 5785 | mcmd = ms->commands[i].cmd; |
| 5786 | margc = ms->commands[i].argc; |
| 5787 | margv = ms->commands[i].argv; |
| 5788 | |
| 5789 | getKeysResult result = GETKEYS_RESULT_INIT; |
| 5790 | numkeys = getKeysFromCommand(mcmd,margv,margc,&result); |
| 5791 | keyindex = result.keys; |
| 5792 | |
| 5793 | for (j = 0; j < numkeys; j++) { |
| 5794 | robj *thiskey = margv[keyindex[j]]; |
| 5795 | int thisslot = keyHashSlot((char*)thiskey->ptr, |
| 5796 | sdslen(thiskey->ptr)); |
| 5797 |
no test coverage detected