diff options
author | Paul J. Davis <paul.joseph.davis@gmail.com> | 2019-05-07 15:06:06 -0500 |
---|---|---|
committer | Joan Touzet <wohali@users.noreply.github.com> | 2019-05-07 16:06:06 -0400 |
commit | a4145c2947d6b6c7e29757e2e477dc81dc53702d (patch) | |
tree | e47a8552dcbf4e6a68712cce7a9ca4b07268c84f | |
parent | af26397f477e87228cfebd0c8fc583561daaf2e4 (diff) | |
download | couchdb-a4145c2947d6b6c7e29757e2e477dc81dc53702d.tar.gz |
Fix epoch mismatch errors (#2027)
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.erl | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl index ab38eb895..52c3fbb76 100644 --- a/src/couch/src/couch_db.erl +++ b/src/couch/src/couch_db.erl @@ -1560,7 +1560,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. @@ -1607,8 +1614,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) -> @@ -1986,7 +1993,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() ] }. @@ -2031,6 +2039,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}])), |