This function is called when we receive a master configuration via a * PING, PONG or UPDATE packet. What we receive is a node, a configEpoch of the * node, and the set of slots claimed under this configEpoch. * * What we do is to rebind the slots with newer configuration compared to our * local configuration, and if needed, we turn ourself into a replica of the * node (see the function comme
| 1678 | * Sometimes it is not actually the "Sender" of the information, like in the |
| 1679 | * case we receive the info via an UPDATE packet. */ |
| 1680 | void clusterUpdateSlotsConfigWith(clusterNode *sender, uint64_t senderConfigEpoch, unsigned char *slots) { |
| 1681 | int j; |
| 1682 | clusterNode *curmaster = NULL, *newmaster = NULL; |
| 1683 | /* The dirty slots list is a list of slots for which we lose the ownership |
| 1684 | * while having still keys inside. This usually happens after a failover |
| 1685 | * or after a manual cluster reconfiguration operated by the admin. |
| 1686 | * |
| 1687 | * If the update message is not able to demote a master to slave (in this |
| 1688 | * case we'll resync with the master updating the whole key space), we |
| 1689 | * need to delete all the keys in the slots we lost ownership. */ |
| 1690 | uint16_t dirty_slots[CLUSTER_SLOTS]; |
| 1691 | int dirty_slots_count = 0; |
| 1692 | |
| 1693 | /* We should detect if sender is new master of our shard. |
| 1694 | * We will know it if all our slots were migrated to sender, and sender |
| 1695 | * has no slots except ours */ |
| 1696 | int sender_slots = 0; |
| 1697 | int migrated_our_slots = 0; |
| 1698 | |
| 1699 | /* Here we set curmaster to this node or the node this node |
| 1700 | * replicates to if it's a slave. In the for loop we are |
| 1701 | * interested to check if slots are taken away from curmaster. */ |
| 1702 | curmaster = nodeIsMaster(myself) ? myself : myself->slaveof; |
| 1703 | |
| 1704 | if (sender == myself) { |
| 1705 | serverLog(LL_WARNING,"Discarding UPDATE message about myself."); |
| 1706 | return; |
| 1707 | } |
| 1708 | |
| 1709 | for (j = 0; j < CLUSTER_SLOTS; j++) { |
| 1710 | if (bitmapTestBit(slots,j)) { |
| 1711 | sender_slots++; |
| 1712 | |
| 1713 | /* The slot is already bound to the sender of this message. */ |
| 1714 | if (g_pserver->cluster->slots[j] == sender) continue; |
| 1715 | |
| 1716 | /* The slot is in importing state, it should be modified only |
| 1717 | * manually via keydb-trib (example: a resharding is in progress |
| 1718 | * and the migrating side slot was already closed and is advertising |
| 1719 | * a new config. We still want the slot to be closed manually). */ |
| 1720 | if (g_pserver->cluster->importing_slots_from[j]) continue; |
| 1721 | |
| 1722 | /* We rebind the slot to the new node claiming it if: |
| 1723 | * 1) The slot was unassigned or the new node claims it with a |
| 1724 | * greater configEpoch. |
| 1725 | * 2) We are not currently importing the slot. */ |
| 1726 | if (g_pserver->cluster->slots[j] == NULL || |
| 1727 | g_pserver->cluster->slots[j]->configEpoch < senderConfigEpoch) |
| 1728 | { |
| 1729 | /* Was this slot mine, and still contains keys? Mark it as |
| 1730 | * a dirty slot. */ |
| 1731 | if (g_pserver->cluster->slots[j] == myself && |
| 1732 | countKeysInSlot(j) && |
| 1733 | sender != myself) |
| 1734 | { |
| 1735 | dirty_slots[dirty_slots_count] = j; |
| 1736 | dirty_slots_count++; |
| 1737 | } |
no test coverage detected