diff options
| -rw-r--r-- | src/rabbit_mirror_queue_misc.erl | 10 | ||||
| -rw-r--r-- | src/rabbit_tests.erl | 45 |
2 files changed, 37 insertions, 18 deletions
diff --git a/src/rabbit_mirror_queue_misc.erl b/src/rabbit_mirror_queue_misc.erl index 453f2f2c68..150b089970 100644 --- a/src/rabbit_mirror_queue_misc.erl +++ b/src/rabbit_mirror_queue_misc.erl @@ -265,16 +265,24 @@ suggested_queue_nodes(<<"nodes">>, Nodes0, {MNode, _SNodes}, All) -> false -> promote_slave(Available) end end; +%% When we need to add nodes, we randomise our candidate list as a +%% crude form of load-balancing. TODO it would also be nice to +%% randomise when we have too many - but that would fail to take +%% account of synchronisation... suggested_queue_nodes(<<"exactly">>, Count, {MNode, SNodes}, All) -> SCount = Count - 1, {MNode, case SCount > length(SNodes) of - true -> Cand = (All -- [MNode]) -- SNodes, + true -> Cand = shuffle((All -- [MNode]) -- SNodes), SNodes ++ lists:sublist(Cand, SCount - length(SNodes)); false -> lists:sublist(SNodes, SCount) end}; suggested_queue_nodes(_, _, {MNode, _}, _) -> {MNode, []}. +shuffle(L) -> + {_, L1} = lists:unzip(lists:keysort(1, [{random:uniform(), N} || N <- L])), + L1. + actual_queue_nodes(#amqqueue{pid = MPid, slave_pids = SPids}) -> {case MPid of none -> none; diff --git a/src/rabbit_tests.erl b/src/rabbit_tests.erl index 11f280bb7f..df89de89d4 100644 --- a/src/rabbit_tests.erl +++ b/src/rabbit_tests.erl @@ -886,38 +886,49 @@ test_arguments_parser() -> test_dynamic_mirroring() -> %% Just unit tests of the node selection logic, see multi node %% tests for the rest... - Test = fun ({NewM, NewSs}, Policy, Params, {OldM, OldSs}, All) -> + Test = fun ({NewM, NewSs, ExtraSs}, Policy, Params, {OldM, OldSs}, All) -> {NewM, NewSs0} = rabbit_mirror_queue_misc:suggested_queue_nodes( Policy, Params, {OldM, OldSs}, All), - NewSs = lists:sort(NewSs0) + NewSs1 = lists:sort(NewSs0), + case dm_list_match(NewSs, NewSs1, ExtraSs) of + ok -> ok; + error -> exit({no_match, NewSs, NewSs1, ExtraSs}) + end end, - Test({a,[b,c]},<<"all">>,'_',{a,[]}, [a,b,c]), - Test({a,[b,c]},<<"all">>,'_',{a,[b,c]},[a,b,c]), - Test({a,[b,c]},<<"all">>,'_',{a,[d]}, [a,b,c]), + Test({a,[b,c],0},<<"all">>,'_',{a,[]}, [a,b,c]), + Test({a,[b,c],0},<<"all">>,'_',{a,[b,c]},[a,b,c]), + Test({a,[b,c],0},<<"all">>,'_',{a,[d]}, [a,b,c]), %% Add a node - Test({a,[b,c]},<<"nodes">>,[<<"a">>,<<"b">>,<<"c">>],{a,[b]},[a,b,c,d]), - Test({b,[a,c]},<<"nodes">>,[<<"a">>,<<"b">>,<<"c">>],{b,[a]},[a,b,c,d]), + Test({a,[b,c],0},<<"nodes">>,[<<"a">>,<<"b">>,<<"c">>],{a,[b]},[a,b,c,d]), + Test({b,[a,c],0},<<"nodes">>,[<<"a">>,<<"b">>,<<"c">>],{b,[a]},[a,b,c,d]), %% Add two nodes and drop one - Test({a,[b,c]},<<"nodes">>,[<<"a">>,<<"b">>,<<"c">>],{a,[d]},[a,b,c,d]), + Test({a,[b,c],0},<<"nodes">>,[<<"a">>,<<"b">>,<<"c">>],{a,[d]},[a,b,c,d]), %% Promote slave to master by policy - Test({a,[b,c]},<<"nodes">>,[<<"a">>,<<"b">>,<<"c">>],{d,[a]},[a,b,c,d]), + Test({a,[b,c],0},<<"nodes">>,[<<"a">>,<<"b">>,<<"c">>],{d,[a]},[a,b,c,d]), %% Don't try to include nodes that are not running - Test({a,[b]}, <<"nodes">>,[<<"a">>,<<"b">>,<<"f">>],{a,[b]},[a,b,c,d]), + Test({a,[b], 0},<<"nodes">>,[<<"a">>,<<"b">>,<<"f">>],{a,[b]},[a,b,c,d]), %% If we can't find any of the nodes listed then just keep the master - Test({a,[]}, <<"nodes">>,[<<"f">>,<<"g">>,<<"h">>],{a,[b]},[a,b,c,d]), + Test({a,[], 0},<<"nodes">>,[<<"f">>,<<"g">>,<<"h">>],{a,[b]},[a,b,c,d]), - Test({a,[b]}, <<"exactly">>,2,{a,[]}, [a,b,c,d]), - Test({a,[b,c]},<<"exactly">>,3,{a,[]}, [a,b,c,d]), - Test({a,[c]}, <<"exactly">>,2,{a,[c]}, [a,b,c,d]), - Test({a,[b,c]},<<"exactly">>,3,{a,[c]}, [a,b,c,d]), - Test({a,[c]}, <<"exactly">>,2,{a,[c,d]},[a,b,c,d]), - Test({a,[c,d]},<<"exactly">>,3,{a,[c,d]},[a,b,c,d]), + Test({a,[], 1},<<"exactly">>,2,{a,[]}, [a,b,c,d]), + Test({a,[], 2},<<"exactly">>,3,{a,[]}, [a,b,c,d]), + Test({a,[c], 0},<<"exactly">>,2,{a,[c]}, [a,b,c,d]), + Test({a,[c], 1},<<"exactly">>,3,{a,[c]}, [a,b,c,d]), + Test({a,[c], 0},<<"exactly">>,2,{a,[c,d]},[a,b,c,d]), + Test({a,[c,d],0},<<"exactly">>,3,{a,[c,d]},[a,b,c,d]), passed. +%% Does the first list match the second where the second is required +%% to have exactly Extra superfluous items? +dm_list_match([], [], 0) -> ok; +dm_list_match(_, [], _Extra) -> error; +dm_list_match([H|T1], [H |T2], Extra) -> dm_list_match(T1, T2, Extra); +dm_list_match(L1, [H2|T2], Extra) -> dm_list_match(L1, T2, Extra - 1). + test_user_management() -> %% lots if stuff that should fail |
