Skip to content

Commit

Permalink
Fix partition issue in ensemble_sync
Browse files Browse the repository at this point in the history
It was previously possible for the 'minority' network partition to
become the majority network partition by a naive network partitioning
strategy. Previously, when a preference list of 5 keyspace partitions
was created on only four distinct nodes, it became possible for a 2 node
'minority' network partition group to actually have a majority of
keyspace partitions because 2 keyspace partitions were assigned to 1
node in the 'minority' group. This was fixed so that the 'majority'
group now always has a majority of keyspace partitions by preventing
nodes with greater than 1 keyspace partition from becoming part of the
'minority' group.
  • Loading branch information
andrewjstone authored and John Burwell committed Jan 6, 2015
1 parent dfc4d04 commit 554eb0e
Showing 1 changed file with 22 additions and 8 deletions.
30 changes: 22 additions & 8 deletions tests/ensemble_sync.erl
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,37 @@ confirm() ->
[ok = run_scenario(Nodes, NVal, Scenario) || Scenario <- Scenarios],
pass.

-spec partition(non_neg_integer(), node(), list()) -> {[{non_neg_integer(), node()}], [node()]}.
partition(Minority, ContactNode, PL) ->
All = [VN || {VN, _} <- PL],
Other = [VN || {VN={_, Owner}, _} <- PL,
Owner =/= ContactNode],
NodeCounts = lists:foldl(fun({_, Node}, Acc) ->
orddict:update_counter(Node, 1, Acc)
end, orddict:new(), Other),
Partitioned = lists:foldl(fun({Node, Count}, Acc) ->
case Count =:= 1 andalso length(Acc) < Minority of
true ->
[Node | Acc];
false ->
Acc
end
end, [], NodeCounts),
PartitionedVN = [VN || {_, Node}=VN <- Other, lists:member(Node, Partitioned)],
Valid = All -- PartitionedVN,
{Valid, Partitioned}.

run_scenario(Nodes, NVal, {NumKill, NumSuspend, NumValid, _, Name, Expect}) ->
Node = hd(Nodes),
Quorum = NVal div 2 + 1,
Minority = NVal - Quorum,
Bucket = {<<"strong">>, Name},
Keys = [<<N:64/integer>> || N <- lists:seq(1,1000)],

Key1 = hd(Keys),
DocIdx = rpc:call(Node, riak_core_util, chash_std_keyfun, [{Bucket, Key1}]),
PL = rpc:call(Node, riak_core_apl, get_primary_apl, [DocIdx, NVal, riak_kv]),
All = [VN || {VN, _} <- PL],
Other = [VN || {VN={_, Owner}, _} <- PL,
Owner =/= Node],

Minority = NVal - Quorum,
PartitionedVN = lists:sublist(Other, Minority),
Partitioned = [VNode || {_, VNode} <- PartitionedVN],
Valid = All -- PartitionedVN,
{Valid, Partitioned} = partition(Minority, Node, PL),

{KillVN, Valid2} = lists:split(NumKill, Valid),
{SuspendVN, Valid3} = lists:split(NumSuspend, Valid2),
Expand Down

0 comments on commit 554eb0e

Please sign in to comment.