summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul J. Davis <paul.joseph.davis@gmail.com>2019-05-07 15:06:06 -0500
committerJoan Touzet <joant@atypical.net>2019-05-07 16:07:00 -0400
commitbd42c853f68ef34dacc9fd6034d9c18e40cec2f5 (patch)
treec78af33ae992d5cd83e9c4eb88d43913e99e1842
parentc298091a4ce6a211208ae0e13e760a69d51d79a4 (diff)
downloadcouchdb-2.3.x-backport-epoch-fix.tar.gz
Fix epoch mismatch errors (#2027)2.3.x-backport-epoch-fix
Originally we posited that duplicate UUIDs could never be created. However due to operations interventions its possible to unintentionally copy UUIDs in ways that violate this assumption. Instead of crashing the process we just reset the seq to zero and log a warning as was done in the other instances when we have mismatches in the epoch history.
-rw-r--r--src/couch/src/couch_db.erl24
1 files changed, 20 insertions, 4 deletions
diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl
index 0ae164d9b..2cbc2976b 100644
--- a/src/couch/src/couch_db.erl
+++ b/src/couch/src/couch_db.erl
@@ -1491,7 +1491,14 @@ calculate_start_seq(Db, _Node, {Seq, Uuid, EpochNode}) ->
calculate_start_seq(Db, _Node, {replace, OriginalNode, Uuid, Seq}) ->
case is_prefix(Uuid, couch_db:get_uuid(Db)) of
true ->
- start_seq(get_epochs(Db), OriginalNode, Seq);
+ try
+ start_seq(get_epochs(Db), OriginalNode, Seq)
+ catch throw:epoch_mismatch ->
+ couch_log:warning("~p start_seq duplicate uuid on node: ~p "
+ "db: ~p, seq: ~p, uuid: ~p, epoch_node: ~p",
+ [?MODULE, node(), Db#db.name, Seq, Uuid, OriginalNode]),
+ 0
+ end;
false ->
{replace, OriginalNode, Uuid, Seq}
end.
@@ -1538,8 +1545,8 @@ start_seq([{_, NewSeq}, {OrigNode, _} | _], OrigNode, Seq) when Seq > NewSeq ->
NewSeq;
start_seq([_ | Rest], OrigNode, Seq) ->
start_seq(Rest, OrigNode, Seq);
-start_seq([], OrigNode, Seq) ->
- erlang:error({epoch_mismatch, OrigNode, Seq}).
+start_seq([], _OrigNode, _Seq) ->
+ throw(epoch_mismatch).
fold_docs(Db, UserFun, UserAcc) ->
@@ -1917,7 +1924,8 @@ calculate_start_seq_test_() ->
t_calculate_start_seq_uuid_mismatch(),
t_calculate_start_seq_is_owner(),
t_calculate_start_seq_not_owner(),
- t_calculate_start_seq_raw()
+ t_calculate_start_seq_raw(),
+ t_calculate_start_seq_epoch_mismatch()
]
}.
@@ -1962,6 +1970,14 @@ t_calculate_start_seq_raw() ->
?assertEqual(13, Seq)
end).
+t_calculate_start_seq_epoch_mismatch() ->
+ ?_test(begin
+ Db = test_util:fake_db([]),
+ SeqIn = {replace, not_this_node, get_uuid(Db), 42},
+ Seq = calculate_start_seq(Db, node1, SeqIn),
+ ?assertEqual(0, Seq)
+ end).
+
is_owner_test() ->
?assertNot(is_owner(foo, 1, [])),
?assertNot(is_owner(foo, 1, [{foo, 1}])),