| 4684 | } |
| 4685 | |
| 4686 | static int clusterManagerFixSlotsCoverage(char *all_slots) { |
| 4687 | int force_fix = config.cluster_manager_command.flags & |
| 4688 | CLUSTER_MANAGER_CMD_FLAG_FIX_WITH_UNREACHABLE_MASTERS; |
| 4689 | |
| 4690 | if (cluster_manager.unreachable_masters > 0 && !force_fix) { |
| 4691 | clusterManagerLogWarn("*** Fixing slots coverage 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); |
| 4692 | exit(1); |
| 4693 | } |
| 4694 | |
| 4695 | int i, fixed = 0; |
| 4696 | list *none = NULL, *single = NULL, *multi = NULL; |
| 4697 | clusterManagerLogInfo(">>> Fixing slots coverage...\n"); |
| 4698 | for (i = 0; i < CLUSTER_MANAGER_SLOTS; i++) { |
| 4699 | int covered = all_slots[i]; |
| 4700 | if (!covered) { |
| 4701 | sds slot = sdsfromlonglong((long long) i); |
| 4702 | list *slot_nodes = listCreate(); |
| 4703 | sds slot_nodes_str = sdsempty(); |
| 4704 | listIter li; |
| 4705 | listNode *ln; |
| 4706 | listRewind(cluster_manager.nodes, &li); |
| 4707 | while ((ln = listNext(&li)) != NULL) { |
| 4708 | clusterManagerNode *n = ln->value; |
| 4709 | if (n->flags & CLUSTER_MANAGER_FLAG_SLAVE || n->replicate) |
| 4710 | continue; |
| 4711 | redisReply *reply = CLUSTER_MANAGER_COMMAND(n, |
| 4712 | "CLUSTER GETKEYSINSLOT %d %d", i, 1); |
| 4713 | if (!clusterManagerCheckRedisReply(n, reply, NULL)) { |
| 4714 | fixed = -1; |
| 4715 | if (reply) freeReplyObject(reply); |
| 4716 | goto cleanup; |
| 4717 | } |
| 4718 | assert(reply->type == REDIS_REPLY_ARRAY); |
| 4719 | if (reply->elements > 0) { |
| 4720 | listAddNodeTail(slot_nodes, n); |
| 4721 | if (listLength(slot_nodes) > 1) |
| 4722 | slot_nodes_str = sdscat(slot_nodes_str, ", "); |
| 4723 | slot_nodes_str = sdscatfmt(slot_nodes_str, |
| 4724 | "%s:%u", n->ip, n->port); |
| 4725 | } |
| 4726 | freeReplyObject(reply); |
| 4727 | } |
| 4728 | sdsfree(slot_nodes_str); |
| 4729 | dictAdd(clusterManagerUncoveredSlots, slot, slot_nodes); |
| 4730 | } |
| 4731 | } |
| 4732 | |
| 4733 | /* For every slot, take action depending on the actual condition: |
| 4734 | * 1) No node has keys for this slot. |
| 4735 | * 2) A single node has keys for this slot. |
| 4736 | * 3) Multiple nodes have keys for this slot. */ |
| 4737 | none = listCreate(); |
| 4738 | single = listCreate(); |
| 4739 | multi = listCreate(); |
| 4740 | dictIterator *iter = dictGetIterator(clusterManagerUncoveredSlots); |
| 4741 | dictEntry *entry; |
| 4742 | while ((entry = dictNext(iter)) != NULL) { |
| 4743 | sds slot = (sds) dictGetKey(entry); |
no test coverage detected