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
| 5895 | * CLUSTER_REDIR_DOWN_STATE and CLUSTER_REDIR_DOWN_RO_STATE if the cluster is |
| 5896 | * down but the user attempts to execute a command that addresses one or more keys. */ |
| 5897 | clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *error_code) { |
| 5898 | clusterNode *n = NULL; |
| 5899 | robj *firstkey = NULL; |
| 5900 | int multiple_keys = 0; |
| 5901 | multiState *ms, _ms; |
| 5902 | multiCmd mc; |
| 5903 | int i, slot = 0, migrating_slot = 0, importing_slot = 0, missing_keys = 0; |
| 5904 | serverAssert((c->cmd->flags & CMD_ASYNC_OK) || GlobalLocksAcquired()); |
| 5905 | |
| 5906 | /* Allow any key to be set if a module disabled cluster redirections. */ |
| 5907 | if (g_pserver->cluster_module_flags & CLUSTER_MODULE_FLAG_NO_REDIRECTION) |
| 5908 | return myself; |
| 5909 | |
| 5910 | /* Allow any key to be set if a module disabled cluster redirections. */ |
| 5911 | if (g_pserver->cluster_module_flags & CLUSTER_MODULE_FLAG_NO_REDIRECTION) |
| 5912 | return myself; |
| 5913 | |
| 5914 | /* Set error code optimistically for the base case. */ |
| 5915 | if (error_code) *error_code = CLUSTER_REDIR_NONE; |
| 5916 | |
| 5917 | /* Modules can turn off Redis Cluster redirection: this is useful |
| 5918 | * when writing a module that implements a completely different |
| 5919 | * distributed system. */ |
| 5920 | |
| 5921 | /* We handle all the cases as if they were EXEC commands, so we have |
| 5922 | * a common code path for everything */ |
| 5923 | if (cmd->proc == execCommand) { |
| 5924 | /* If CLIENT_MULTI flag is not set EXEC is just going to return an |
| 5925 | * error. */ |
| 5926 | if (!(c->flags & CLIENT_MULTI)) return myself; |
| 5927 | ms = &c->mstate; |
| 5928 | } else { |
| 5929 | /* In order to have a single codepath create a fake Multi State |
| 5930 | * structure if the client is not in MULTI/EXEC state, this way |
| 5931 | * we have a single codepath below. */ |
| 5932 | ms = &_ms; |
| 5933 | _ms.commands = &mc; |
| 5934 | _ms.count = 1; |
| 5935 | mc.argv = argv; |
| 5936 | mc.argc = argc; |
| 5937 | mc.cmd = cmd; |
| 5938 | } |
| 5939 | |
| 5940 | /* Check that all the keys are in the same hash slot, and obtain this |
| 5941 | * slot and the node associated. */ |
| 5942 | for (i = 0; i < ms->count; i++) { |
| 5943 | struct redisCommand *mcmd; |
| 5944 | robj **margv; |
| 5945 | int margc, *keyindex, numkeys, j; |
| 5946 | |
| 5947 | mcmd = ms->commands[i].cmd; |
| 5948 | margc = ms->commands[i].argc; |
| 5949 | margv = ms->commands[i].argv; |
| 5950 | |
| 5951 | getKeysResult result = GETKEYS_RESULT_INIT; |
| 5952 | numkeys = getKeysFromCommand(mcmd,margv,margc,&result); |
| 5953 | keyindex = result.keys; |
| 5954 |
no test coverage detected