Slot 'slot' was found to be in importing or migrating state in one or * more nodes. This function fixes this condition by migrating keys where * it seems more sensible. */
| 4886 | * more nodes. This function fixes this condition by migrating keys where |
| 4887 | * it seems more sensible. */ |
| 4888 | static int clusterManagerFixOpenSlot(int slot) { |
| 4889 | int force_fix = config.cluster_manager_command.flags & |
| 4890 | CLUSTER_MANAGER_CMD_FLAG_FIX_WITH_UNREACHABLE_MASTERS; |
| 4891 | |
| 4892 | if (cluster_manager.unreachable_masters > 0 && !force_fix) { |
| 4893 | clusterManagerLogWarn("*** Fixing open slots with %d unreachable masters is dangerous: redis-cli will assume that slots about masters that are not reachable are not covered, and will try to reassign them to the reachable nodes. This can cause data loss and is rarely what you want to do. If you really want to proceed use the --cluster-fix-with-unreachable-masters option.\n", cluster_manager.unreachable_masters); |
| 4894 | exit(1); |
| 4895 | } |
| 4896 | |
| 4897 | clusterManagerLogInfo(">>> Fixing open slot %d\n", slot); |
| 4898 | /* Try to obtain the current slot owner, according to the current |
| 4899 | * nodes configuration. */ |
| 4900 | int success = 1; |
| 4901 | list *owners = listCreate(); /* List of nodes claiming some ownership. |
| 4902 | it could be stating in the configuration |
| 4903 | to have the node ownership, or just |
| 4904 | holding keys for such slot. */ |
| 4905 | list *migrating = listCreate(); |
| 4906 | list *importing = listCreate(); |
| 4907 | sds migrating_str = sdsempty(); |
| 4908 | sds importing_str = sdsempty(); |
| 4909 | clusterManagerNode *owner = NULL; /* The obvious slot owner if any. */ |
| 4910 | |
| 4911 | /* Iterate all the nodes, looking for potential owners of this slot. */ |
| 4912 | listIter li; |
| 4913 | listNode *ln; |
| 4914 | listRewind(cluster_manager.nodes, &li); |
| 4915 | while ((ln = listNext(&li)) != NULL) { |
| 4916 | clusterManagerNode *n = ln->value; |
| 4917 | if (n->flags & CLUSTER_MANAGER_FLAG_SLAVE) continue; |
| 4918 | if (n->slots[slot]) { |
| 4919 | listAddNodeTail(owners, n); |
| 4920 | } else { |
| 4921 | redisReply *r = CLUSTER_MANAGER_COMMAND(n, |
| 4922 | "CLUSTER COUNTKEYSINSLOT %d", slot); |
| 4923 | success = clusterManagerCheckRedisReply(n, r, NULL); |
| 4924 | if (success && r->integer > 0) { |
| 4925 | clusterManagerLogWarn("*** Found keys about slot %d " |
| 4926 | "in non-owner node %s:%d!\n", slot, |
| 4927 | n->ip, n->port); |
| 4928 | listAddNodeTail(owners, n); |
| 4929 | } |
| 4930 | if (r) freeReplyObject(r); |
| 4931 | if (!success) goto cleanup; |
| 4932 | } |
| 4933 | } |
| 4934 | |
| 4935 | /* If we have only a single potential owner for this slot, |
| 4936 | * set it as "owner". */ |
| 4937 | if (listLength(owners) == 1) owner = listFirst(owners)->value; |
| 4938 | |
| 4939 | /* Scan the list of nodes again, in order to populate the |
| 4940 | * list of nodes in importing or migrating state for |
| 4941 | * this slot. */ |
| 4942 | listRewind(cluster_manager.nodes, &li); |
| 4943 | while ((ln = listNext(&li)) != NULL) { |
| 4944 | clusterManagerNode *n = ln->value; |
| 4945 | if (n->flags & CLUSTER_MANAGER_FLAG_SLAVE) continue; |
no test coverage detected