summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Vatamaniuc <vatamane@apache.org>2019-06-12 13:41:19 -0400
committerNick Vatamaniuc <nickva@users.noreply.github.com>2019-06-12 16:14:10 -0400
commit64eb390a197f54a1bb36a4809861f6f3dcd6dc4e (patch)
treef2b347196ac4f9bcac3d19645c78fd1df92f93e7
parent57bf82e5cc3c3ab55ad6c3e46ea2c666ac2711cc (diff)
downloadcouchdb-64eb390a197f54a1bb36a4809861f6f3dcd6dc4e.tar.gz
Make mem3_rep:go work when target shards are not yet present in shard map
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.