summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul J. Davis <paul.joseph.davis@gmail.com>2019-05-07 15:06:06 -0500
committerJan Lehnardt <jan@apache.org>2020-08-19 12:51:18 +0200
commit4aed3c0582f2cf5edeff8e664bac8bace5a6e4f7 (patch)
tree2e71fd37b3e7529d80b76f176f991a48f5c78838
parent8ff673a3c7b3948c56f154a68829b404150e8b35 (diff)
downloadcouchdb-2.3.1+jiffy+epoch.tar.gz
Fix epoch mismatch errors (#2027)archive/2.3.1+jiffy+epoch2.3.1+jiffy+epoch
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}])),