summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Vatamaniuc <vatamane@apache.org>2019-06-12 13:41:19 -0400
committerNick Vatamaniuc <vatamane@apache.org>2019-06-12 13:55:36 -0400
commitd827272c9607473277a172c22e5e0a3373a1491f (patch)
treef2b347196ac4f9bcac3d19645c78fd1df92f93e7
parent57bf82e5cc3c3ab55ad6c3e46ea2c666ac2711cc (diff)
downloadcouchdb-missing-target-in-mem3-rep.tar.gz
Make mem3_rep:go work when target shards are not yet present in shard mapmissing-target-in-mem3-rep
Before shard splitting it was possible to replicate shards even if they were not in the shard map. This commit brings back that behavior.
-rw-r--r--src/mem3/src/mem3_rep.erl34
1 files changed, 31 insertions, 3 deletions
diff --git a/src/mem3/src/mem3_rep.erl b/src/mem3/src/mem3_rep.erl
index d2edd6c4d..fd7c680a6 100644
--- a/src/mem3/src/mem3_rep.erl
+++ b/src/mem3/src/mem3_rep.erl
@@ -743,13 +743,24 @@ sync_security(#shard{} = Source, #{} = Targets) ->
targets_map(#shard{name = <<"shards/", _/binary>> = SrcName} = Src,
- #shard{name = <<"shards/", _/binary>>, node = TgtNode}) ->
+ #shard{name = <<"shards/", _/binary>>, node = TgtNode} = Tgt) ->
% Parse range from name in case the passed shard is built with a name only
SrcRange = mem3:range(SrcName),
Shards0 = mem3:shards(mem3:dbname(SrcName)),
Shards1 = [S || S <- Shards0, not shard_eq(S, Src)],
Shards2 = [S || S <- Shards1, check_overlap(SrcRange, TgtNode, S)],
- maps:from_list([{R, S} || #shard{range = R} = S <- Shards2]);
+ TMap = maps:from_list([{R, S} || #shard{range = R} = S <- Shards2]),
+ case [{R, S} || #shard{range = R} = S <- Shards2] of
+ [] ->
+ % If target map is empty, create a target map with just
+ % that one target. This is to support tooling which may be
+ % moving / copying shards using mem3:go/2,3 before the
+ % shards are present in the shard map
+ #{mem3:range(SrcName) => Tgt};
+ [_ | _] = TMapList->
+ maps:from_list(TMapList)
+ end;
+
targets_map(_Src, Tgt) ->
#{[0, ?RING_END] => Tgt}.
@@ -876,7 +887,8 @@ targets_map_test_() ->
target_not_a_shard(),
source_contained_in_target(),
multiple_targets(),
- uneven_overlap()
+ uneven_overlap(),
+ target_not_in_shard_map()
]
}.
@@ -968,4 +980,20 @@ uneven_overlap() ->
end).
+target_not_in_shard_map() ->
+ ?_test(begin
+ R0f = [16#00000000, 16#ffffffff],
+ Name = <<"shards/00000000-ffffffff/d.1551893552">>,
+ Shards = [
+ #shard{name = Name, node = 'n1', range = R0f},
+ #shard{name = Name, node = 'n2', range = R0f}
+ ],
+ meck:expect(mem3, shards, 1, Shards),
+ Src = #shard{name = Name, node = 'n1'},
+ Tgt = #shard{name = Name, node = 'n3'},
+ Map = targets_map(Src, Tgt),
+ ?assertEqual(1, map_size(Map)),
+ ?assertMatch(#{R0f := #shard{name = Name, node = 'n3'}}, Map)
+ end).
+
-endif.