diff options
author | Paul J. Davis <paul.joseph.davis@gmail.com> | 2019-01-14 18:32:34 -0600 |
---|---|---|
committer | Paul J. Davis <paul.joseph.davis@gmail.com> | 2019-01-14 18:32:45 -0600 |
commit | fcdd7e8c5d7761bf6690e14173601a80c2fb57f2 (patch) | |
tree | a059a7348873b132ac3665c0366fba9a9cc0d438 | |
parent | c6b095b2ad716b917d260c8a0a56f3d4676ced7f (diff) | |
download | couchdb-fix-open-doc-revs-read-repair.tar.gz |
TODO - write this commit messagefix-open-doc-revs-read-repair
-rw-r--r-- | src/fabric/src/fabric_doc_open_revs.erl | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/src/fabric/src/fabric_doc_open_revs.erl b/src/fabric/src/fabric_doc_open_revs.erl index 15b8eacb9..91426cff1 100644 --- a/src/fabric/src/fabric_doc_open_revs.erl +++ b/src/fabric/src/fabric_doc_open_revs.erl @@ -243,8 +243,7 @@ format_reply(true, Replies, _) -> tree_format_replies(Replies); format_reply(false, Replies, _) -> - Filtered = filter_reply(Replies), - dict_format_replies(Filtered). + dict_format_replies(Replies). tree_format_replies(RevTree) -> @@ -260,22 +259,44 @@ tree_format_replies(RevTree) -> dict_format_replies(Dict) -> - lists:sort([Reply || {_, {Reply, _}} <- Dict]). - -filter_reply(Replies) -> - AllFoundRevs = lists:foldl(fun - ({{{not_found, missing}, _}, _}, Acc) -> - Acc; - ({{_, {Pos, [Rev | _]}}, _}, Acc) -> - [{Pos, Rev} | Acc] - end, [], Replies), - %% keep not_found replies only for the revs that don't also have doc reply - lists:filter(fun - ({{{not_found, missing}, Rev}, _}) -> - not lists:member(Rev, AllFoundRevs); - (_) -> - true - end, Replies). + Replies0 = [Reply || {_, {Reply, _}} <- Dict], + + AllFoundRevs = lists:foldl(fun(Reply, Acc) -> + case Reply of + {ok, #doc{revs = {Pos, [RevId | _]}}} -> + [{Pos, RevId} | Acc]; + _ -> + Acc + end + end, [], Replies0), + + %% Drop any not_found replies for which we + %% found the revision on a different node. + Replies1 = lists:filter(fun(Reply) -> + case Reply of + {{not_found, missing}, Rev} -> + not lists:member(Rev, AllFoundRevs); + _ -> + true + end + end, + + Replies2 = lists:sort(Replies1), + collapse_duplicate_revs(Replies2). + + +collapse_duplicate_revs([{ok, Doc1}, {ok, Doc2} | Rest]) -> + {D1, R1} = Doc1#doc.revs, + {D2, R2} = Doc2#doc.revs, + Head = case D1 == D2 and lists:prefix(R1, R2) of + true -> []; + false -> [{ok, Doc1}] + end, + Head ++ collapse_duplicate_revs([{ok, Doc2} | Rest]), + +collapse_duplicate_revs([Reply | Rest]) -> + [Reply | collapse_duplicate_revs(Rest)]. + -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). |