summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Vatamaniuc <vatamane@apache.org>2018-09-19 15:56:55 -0400
committerNick Vatamaniuc <nickva@users.noreply.github.com>2018-09-19 17:51:48 -0400
commit52ed7fbf48b953c3cd0dd5c058186a6af01dbc64 (patch)
tree0270b34b3a6bcb55f0810b7013d240b8614d8967
parentb4bfc529efdba4b971cd8351dc1fa6b552089744 (diff)
downloadcouchdb-52ed7fbf48b953c3cd0dd5c058186a6af01dbc64.tar.gz
Ignore local nodes in read repair filtering
Previosly local node revisions were causing `badmatch` failures in read repair filter. Node sequences already filtered out local nodes while NodeRevs didn't, so during matching `{Node, NodeSeq} = lists:keyfind(Node, 1, NodeSeqs)` Node would not be found in the list and crash. Example of crash: ``` fabric_rpc:update_docs/3 error:{badmatch,false} [{fabric_rpc,'-read_repair_filter/3-fun-1-',4,[{file,"src/fabric_rpc.erl"},{line,360}]}, ```
-rw-r--r--src/fabric/src/fabric_rpc.erl5
-rw-r--r--src/fabric/test/fabric_rpc_purge_tests.erl24
2 files changed, 26 insertions, 3 deletions
diff --git a/src/fabric/src/fabric_rpc.erl b/src/fabric/src/fabric_rpc.erl
index c68422969..11e675464 100644
--- a/src/fabric/src/fabric_rpc.erl
+++ b/src/fabric/src/fabric_rpc.erl
@@ -347,7 +347,8 @@ read_repair_filter(DbName, Docs, NodeRevs, Options) ->
% as the read_repair option to update_docs.
read_repair_filter(Db, Docs, NodeRevs) ->
[#doc{id = DocId} | _] = Docs,
- Nodes = lists:usort([Node || {Node, _} <- NodeRevs, Node /= node()]),
+ NonLocalNodeRevs = [NR || {N, _} = NR <- NodeRevs, N /= node()],
+ Nodes = lists:usort([Node || {Node, _} <- NonLocalNodeRevs]),
NodeSeqs = get_node_seqs(Db, Nodes),
DbPSeq = couch_db:get_purge_seq(Db),
@@ -360,7 +361,7 @@ read_repair_filter(Db, Docs, NodeRevs) ->
{Node, NodeSeq} = lists:keyfind(Node, 1, NodeSeqs),
NodeSeq >= DbPSeq - Lag
end,
- RecentNodeRevs = lists:filter(NodeFiltFun, NodeRevs),
+ RecentNodeRevs = lists:filter(NodeFiltFun, NonLocalNodeRevs),
% For each node we scan the purge infos to filter out any
% revisions that have been locally purged since we last
diff --git a/src/fabric/test/fabric_rpc_purge_tests.erl b/src/fabric/test/fabric_rpc_purge_tests.erl
index 26507cf0b..4eafb2bc4 100644
--- a/src/fabric/test/fabric_rpc_purge_tests.erl
+++ b/src/fabric/test/fabric_rpc_purge_tests.erl
@@ -46,6 +46,7 @@ main_test_() ->
lists:map(fun wrap/1, [
?TDEF(t_filter),
?TDEF(t_filter_unknown_node),
+ ?TDEF(t_filter_local_node),
?TDEF(t_no_filter_old_node),
?TDEF(t_no_filter_different_node),
?TDEF(t_no_filter_after_repl)
@@ -58,6 +59,7 @@ main_test_() ->
lists:map(fun wrap/1, [
?TDEF(t_filter),
?TDEF(t_filter_unknown_node),
+ ?TDEF(t_filter_local_node),
?TDEF(t_no_filter_old_node),
?TDEF(t_no_filter_different_node),
?TDEF(t_no_filter_after_repl)
@@ -172,6 +174,26 @@ t_no_filter_different_node({DbName, DocId, OldDoc, PSeq}) ->
?assertEqual({ok, OldDoc}, open_doc(DbName, DocId)).
+t_filter_local_node({DbName, DocId, OldDoc, PSeq}) ->
+ ?assertEqual({not_found, missing}, open_doc(DbName, DocId)),
+ create_purge_checkpoint(DbName, PSeq),
+
+ % Create a valid purge for a different node
+ TgtNode = list_to_binary(atom_to_list('notfoo@127.0.0.1')),
+ create_purge_checkpoint(DbName, 0, TgtNode),
+
+ % Add a local node rev to the list of node revs. It should
+ % be filtered out
+ {Pos, [Rev | _]} = OldDoc#doc.revs,
+ RROpts = [{read_repair, [
+ {tgt_node(), [{Pos, Rev}]},
+ {node(), [{1, <<"123">>}]}
+ ]}],
+ rpc_update_doc(DbName, OldDoc, RROpts),
+
+ ?assertEqual({ok, OldDoc}, open_doc(DbName, DocId)).
+
+
t_no_filter_after_repl({DbName, DocId, OldDoc, PSeq}) ->
?assertEqual({not_found, missing}, open_doc(DbName, DocId)),
create_purge_checkpoint(DbName, PSeq),
@@ -282,4 +304,4 @@ tgt_node() ->
tgt_node_bin() ->
- iolist_to_binary(atom_to_list(tgt_node())). \ No newline at end of file
+ iolist_to_binary(atom_to_list(tgt_node())).