summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Bruce <me@andrewbruce.net>2016-10-05 15:21:47 +0100
committerAndrew Bruce <me@andrewbruce.net>2016-10-05 15:21:47 +0100
commitc1c56a29b098b7c5ad0915a340a2a039e61a22a3 (patch)
tree4f5fb822ed7e359a264920650e0522ebc2be6013 /src
parent75795f977c8b96fa580d58cd9bda049e312b2044 (diff)
downloadrabbitmq-server-git-c1c56a29b098b7c5ad0915a340a2a039e61a22a3.tar.gz
Choose master from intersection of sync slaves and policy nodes
Previously, when applying an HA policy with the 'nodes' type, if the current master was not part of the new policy, then the first synchronised slave was chosen as the new master. This would happen even if the node was not part of the new policy. For example, if we began with: Master A Slaves [B, C] Then requested a new policy of just [C], we'd end up with: Master B Slaves [C] Instead, choose the master from the intersection of (nodes in the policy) and (synchronised slaves). Issue #990 [#126767013]
Diffstat (limited to 'src')
-rw-r--r--src/rabbit_mirror_queue_mode_nodes.erl36
1 files changed, 22 insertions, 14 deletions
diff --git a/src/rabbit_mirror_queue_mode_nodes.erl b/src/rabbit_mirror_queue_mode_nodes.erl
index e63f340373..31c55722a5 100644
--- a/src/rabbit_mirror_queue_mode_nodes.erl
+++ b/src/rabbit_mirror_queue_mode_nodes.erl
@@ -32,29 +32,37 @@
description() ->
[{description, <<"Mirror queue to specified nodes">>}].
-suggested_queue_nodes(Nodes0, MNode, _SNodes, SSNodes, Poss) ->
- Nodes1 = [list_to_atom(binary_to_list(Node)) || Node <- Nodes0],
+suggested_queue_nodes(PolicyNodes0, CurrentMaster, _SNodes, SSNodes, NodesRunningRabbitMQ) ->
+ PolicyNodes1 = [list_to_atom(binary_to_list(Node)) || Node <- PolicyNodes0],
%% If the current master is not in the nodes specified, then what we want
%% to do depends on whether there are any synchronised slaves. If there
%% are then we can just kill the current master - the admin has asked for
%% a migration and we should give it to them. If there are not however
%% then we must keep the master around so as not to lose messages.
- Nodes = case SSNodes of
- [] -> lists:usort([MNode | Nodes1]);
- _ -> Nodes1
- end,
- Unavailable = Nodes -- Poss,
- Available = Nodes -- Unavailable,
- case Available of
+
+ PolicyNodes = case SSNodes of
+ [] -> lists:usort([CurrentMaster | PolicyNodes1]);
+ _ -> PolicyNodes1
+ end,
+ Unavailable = PolicyNodes -- NodesRunningRabbitMQ,
+ AvailablePolicyNodes = PolicyNodes -- Unavailable,
+ case AvailablePolicyNodes of
[] -> %% We have never heard of anything? Not much we can do but
%% keep the master alive.
- {MNode, []};
- _ -> case lists:member(MNode, Available) of
- true -> {MNode, Available -- [MNode]};
+ {CurrentMaster, []};
+ _ -> case lists:member(CurrentMaster, AvailablePolicyNodes) of
+ true -> {CurrentMaster,
+ AvailablePolicyNodes -- [CurrentMaster]};
false -> %% Make sure the new master is synced! In order to
%% get here SSNodes must not be empty.
- [NewMNode | _] = SSNodes,
- {NewMNode, Available -- [NewMNode]}
+ SyncPolicyNodes = [Node ||
+ Node <- AvailablePolicyNodes,
+ lists:member(Node, SSNodes)],
+ NewMaster = case SyncPolicyNodes of
+ [Node | _] -> Node;
+ [] -> erlang:hd(SSNodes)
+ end,
+ {NewMaster, AvailablePolicyNodes -- [NewMaster]}
end
end.