summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul J. Davis <paul.joseph.davis@gmail.com>2019-01-14 18:32:34 -0600
committerPaul J. Davis <paul.joseph.davis@gmail.com>2019-01-14 18:32:45 -0600
commitfcdd7e8c5d7761bf6690e14173601a80c2fb57f2 (patch)
treea059a7348873b132ac3665c0366fba9a9cc0d438
parentc6b095b2ad716b917d260c8a0a56f3d4676ced7f (diff)
downloadcouchdb-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.erl57
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").