diff options
author | Nick Vatamaniuc <vatamane@apache.org> | 2019-06-12 13:41:19 -0400 |
---|---|---|
committer | Nick Vatamaniuc <nickva@users.noreply.github.com> | 2019-06-12 16:14:10 -0400 |
commit | 64eb390a197f54a1bb36a4809861f6f3dcd6dc4e (patch) | |
tree | f2b347196ac4f9bcac3d19645c78fd1df92f93e7 | |
parent | 57bf82e5cc3c3ab55ad6c3e46ea2c666ac2711cc (diff) | |
download | couchdb-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.erl | 34 |
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. |