diff options
-rw-r--r-- | src/fabric/src/fabric_db_info.erl | 9 | ||||
-rw-r--r-- | src/fabric/src/fabric_view_changes.erl | 18 | ||||
-rw-r--r-- | src/fabric/test/eunit/fabric_db_info_tests.erl | 68 |
3 files changed, 94 insertions, 1 deletions
diff --git a/src/fabric/src/fabric_db_info.erl b/src/fabric/src/fabric_db_info.erl index 40da678e5..586f282c2 100644 --- a/src/fabric/src/fabric_db_info.erl +++ b/src/fabric/src/fabric_db_info.erl @@ -77,7 +77,7 @@ handle_message(Reason, Shard, {Counters, Resps, CInfo}) -> build_final_response(CInfo, DbName, Responses) -> AccF = fabric_dict:fold(fun(Shard, Info, {Seqs, PSeqs, Infos}) -> - Seq = couch_util:get_value(update_seq, Info), + Seq = build_seq(Shard, Info), PSeq = couch_util:get_value(purge_seq, Info), {[{Shard, Seq} | Seqs], [{Shard, PSeq} | PSeqs], [Info | Infos]} end, {[], [], []}, Responses), @@ -89,6 +89,13 @@ build_final_response(CInfo, DbName, Responses) -> [{db_name, DbName}] ++ Sequences ++ MergedInfos. +build_seq(#shard{node = Node}, Info) when is_list(Info) -> + Seq = couch_util:get_value(update_seq, Info), + Uuid = couch_util:get_value(uuid, Info), + PrefixLen = fabric_util:get_uuid_prefix_len(), + {Seq, binary:part(Uuid, {0, PrefixLen}), Node}. + + merge_results(Info) -> Dict = lists:foldl(fun({K,V},D0) -> orddict:append(K,V,D0) end, orddict:new(), Info), diff --git a/src/fabric/src/fabric_view_changes.erl b/src/fabric/src/fabric_view_changes.erl index beeaecee1..5115004ad 100644 --- a/src/fabric/src/fabric_view_changes.erl +++ b/src/fabric/src/fabric_view_changes.erl @@ -18,6 +18,9 @@ %% exported for upgrade purposes. -export([keep_sending_changes/8]). +%% exported for testing and remsh debugging +-export([unpack_seqs/1]). + -include_lib("fabric/include/fabric.hrl"). -include_lib("mem3/include/mem3.hrl"). -include_lib("couch/include/couch_db.hrl"). @@ -410,6 +413,21 @@ unpack_seq_decode_term(Opaque) -> binary_to_term(couch_util:decodeBase64Url(Opaque)). +% This is used for testing and for remsh debugging +% +% Unlike unpack_seqs/2 it returns just the unpacked list of sequences from the +% `10-g1A...` format. The result might look like [{Node, [Begin, End], {SeqNum, +% Uuid, EpochNode}}, ...] or just [{Node, [Begin, End], SeqNum}, ...] +-spec unpack_seqs(binary()) -> [tuple()]. +unpack_seqs(Packed) -> + Opaque = unpack_seq_regex_match(Packed), + unpack_seq_decode_term(Opaque). + + +% Returns fabric_dict with {Shard, Seq} entries +% +-spec unpack_seqs(pos_integer() | list() | binary(), binary()) -> + orddict:orddict(). unpack_seqs(0, DbName) -> fabric_dict:init(mem3:shards(DbName), 0); diff --git a/src/fabric/test/eunit/fabric_db_info_tests.erl b/src/fabric/test/eunit/fabric_db_info_tests.erl new file mode 100644 index 000000000..0d27a54bd --- /dev/null +++ b/src/fabric/test/eunit/fabric_db_info_tests.erl @@ -0,0 +1,68 @@ +% Licensed under the Apache License, Version 2.0 (the "License"); you may not +% use this file except in compliance with the License. You may obtain a copy of +% the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +% License for the specific language governing permissions and limitations under +% the License. + +-module(fabric_db_info_tests). + + +-include_lib("couch/include/couch_eunit.hrl"). +-include_lib("couch/include/couch_db.hrl"). +-include_lib("mem3/include/mem3.hrl"). + + +-define(TDEF(A), {atom_to_list(A), fun A/0}). + + +main_test_() -> + { + setup, + fun setup/0, + fun teardown/1, + [ + ?TDEF(t_update_seq_has_uuids) + ] + }. + + +setup() -> + test_util:start_couch([fabric]). + + +teardown(Ctx) -> + meck:unload(), + test_util:stop_couch(Ctx). + + +t_update_seq_has_uuids() -> + DbName = ?tempdb(), + ok = fabric:create_db(DbName, [{q, 1}, {n, 1}]), + + {ok, Info} = fabric:get_db_info(DbName), + UpdateSeq = couch_util:get_value(update_seq, Info), + UnpackedSeq = fabric_view_changes:unpack_seqs(UpdateSeq), + + ?assertMatch([{_, _, _}], UnpackedSeq), + [{Node, Range, Seq}] = UnpackedSeq, + ?assert(is_atom(Node)), + ?assertMatch([_, _], Range), + ?assertMatch({_, _, _}, Seq), + {SeqNum, SeqUuid, EpochNode} = Seq, + ?assert(is_integer(SeqNum)), + ?assert(is_binary(SeqUuid)), + ?assert(is_atom(EpochNode)), + + {ok, UuidMap} = fabric:db_uuids(DbName), + PrefixLen = fabric_util:get_uuid_prefix_len(), + Uuids = [binary:part(Uuid, {0, PrefixLen}) || Uuid <- maps:keys(UuidMap)], + [UuidFromShard] = Uuids, + ?assertEqual(UuidFromShard, SeqUuid), + + ok = fabric:delete_db(DbName, []). |