From 0f3d11e1bf91bfdfd36217727b9dc7902a00c9fb Mon Sep 17 00:00:00 2001 From: Scott Lystig Fritchie Date: Tue, 7 Jul 2015 14:28:45 +0900 Subject: [PATCH] Bugfix (part II) rare race between just-finished repair and flapping ending The prior commit wasn't sufficient: the range of transitions is wider than assumed by that commit. So, we take one of two options, with a TODO task of researching the other option. --- src/machi_chain_manager1.erl | 41 ++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/machi_chain_manager1.erl b/src/machi_chain_manager1.erl index c7e47c8..7208e8d 100644 --- a/src/machi_chain_manager1.erl +++ b/src/machi_chain_manager1.erl @@ -1417,21 +1417,48 @@ react_to_env_C100(P_newprop, P_latest, ?REACT({c100, ?LINE, [sane]}), erase(perhaps_reset_loop), react_to_env_C110(P_latest, S); - _AnyOtherReturnValue -> + {expected_author2,_ExpectedAuthor2}=_ExpectedErr -> case get(perhaps_reset_loop) of undefined -> - put(perhaps_reset_loop, 1); + put(perhaps_reset_loop, 1), + ?REACT({c100, ?LINE, [not_sane, get(why2), _ExpectedErr]}), + react_to_env_C300(P_newprop, P_latest, S); X when X > 15 -> - Msg = lists:flatten( - io_lib:format("~P", [get(react), 300])), - exit({not_supposed_to_happen, ?MODULE, ?LINE, Msg}); + %% Ha, yes, this is possible. For example: + %% outer: author=e,upi=[b,a,d],repair=[c,e] + %% inner: author=e,upi=[b,e], repair=[] + %% In this case, the transition from inner to outer by A30 + %% has chosen the wrong author. We have two choices. + %% 1. Accept this transition, because it really was the + %% safe & transition-approved UPI+repeairing that we + %% were using while we were flapping. I'm 99% certain + %% that this is safe. TODO: Verify + %% 2. I'm not yet 100% certain that #1 is safe, so instead + %% we fall back to the one thing that we know is safe: + %% the 'none' projection, which lets the chain rebuild + %% itself normally during future iterations. + #projection_v1{epoch_number=Epoch_latest, + all_members=All_list, + members_dict=MembersDict} = P_latest, + P_none0 = make_none_projection(MyName, All_list, MembersDict), + P_none1 = P_none0#projection_v1{epoch_number=Epoch_latest}, + Dbg = [{none_projection,true}], + P_none = machi_projection:update_checksum( + P_none1#projection_v1{dbg=Dbg}), +io:format(user, "YO: looping transition forced to none!\nNewProp: ~w\nLatest: ~w\nNone: ~w\n", [machi_projection:make_summary(P_newprop), machi_projection:make_summary(P_latest), machi_projection:make_summary(P_none)]), + %% Recurse to self! + react_to_env_C100(P_none, P_none, S); X -> - put(perhaps_reset_loop, X+1) - end, + put(perhaps_reset_loop, X+1), + ?REACT({c100, ?LINE, [not_sane, get(why2), _ExpectedErr]}), + react_to_env_C300(P_newprop, P_latest, S) + end; + _AnyOtherReturnValue -> %% P_latest is not sane. %% By process of elimination, P_newprop is best, %% so let's write it. ?REACT({c100, ?LINE, [not_sane, get(why2), _AnyOtherReturnValue]}), + erase(perhaps_reset_loop), react_to_env_C300(P_newprop, P_latest, S) end.