Yeah, nearly there. AP fails occasionally in multiple-asymmetric-partition sequence

This commit is contained in:
Scott Lystig Fritchie 2015-09-09 23:10:39 +09:00
parent 72141c8ecb
commit b7aa33c617
3 changed files with 90 additions and 38 deletions

View file

@ -1202,13 +1202,37 @@ react_to_env_A29(Retries, P_latest, LatestUnanimousP, _ReadExtra,
end.
react_to_env_A30(Retries, P_latest, LatestUnanimousP, P_current_calc,
#ch_mgr{name=MyName} = S) ->
#ch_mgr{name=MyName, consistency_mode=CMode} = S) ->
?REACT(a30),
AllHosed = get_unfit_list(S#ch_mgr.fitness_svr),
?REACT({a30, ?LINE, [{all_hosed, AllHosed}]}),
?REACT({a30, ?LINE,
[{current, machi_projection:make_summary(S#ch_mgr.proj)},
{calc_current, machi_projection:make_summary(P_current_calc)},
{latest, machi_projection:make_summary(P_latest)},
{all_hosed, AllHosed}
]}),
?REACT({a30, ?LINE, []}),
case lists:member(MyName, AllHosed) of
true ->
react_to_env_A50(P_latest, [{i_am_hosed, AllHosed}], S);
io:format(user, "AmHosed: ~w, ", [MyName]),
#projection_v1{epoch_number=Epoch, all_members=All_list,
witnesses=Witness_list,
members_dict=MembersDict} = P_latest,
P = #projection_v1{down=Down} =
make_none_projection(Epoch + 1, MyName, All_list,
Witness_list, MembersDict),
P_newprop = if CMode == ap_mode ->
%% Not really none proj: just myself, AP style
machi_projection:update_checksum(
P#projection_v1{upi=[MyName],
down=Down -- [MyName],
dbg=[{hosed_list,AllHosed}]});
CMode == cp_mode ->
machi_projection:update_checksum(
P#projection_v1{dbg=[{hosed_list,AllHosed}]})
end,
react_to_env_A40(Retries, P_newprop, P_latest, LatestUnanimousP,
true, S);
false ->
react_to_env_A31(Retries, P_latest, LatestUnanimousP,
P_current_calc, AllHosed, S)
@ -1217,12 +1241,8 @@ react_to_env_A30(Retries, P_latest, LatestUnanimousP, P_current_calc,
react_to_env_A31(Retries, P_latest, LatestUnanimousP, P_current_calc,
AllHosed, #ch_mgr{name=MyName} = S) ->
{P_newprop1, S2,_Up} = calc_projection(S, MyName, AllHosed, P_current_calc),
?REACT({a30, ?LINE,
[{current, machi_projection:make_summary(S#ch_mgr.proj)},
{calc_current, machi_projection:make_summary(P_current_calc)},
{latest, machi_projection:make_summary(P_latest)},
{newprop1, machi_projection:make_summary(P_newprop1)}
]}),
?REACT({a31, ?LINE,
[{newprop1, machi_projection:make_summary(P_newprop1)}]}),
{P_newprop2, S3} = {P_newprop1, S2},
@ -1231,14 +1251,14 @@ react_to_env_A31(Retries, P_latest, LatestUnanimousP, P_current_calc,
#projection_v1{epoch_number=Epoch_latest}=P_latest,
NewEpoch = erlang:max(Epoch_newprop2, Epoch_latest) + 1,
P_newprop3 = P_newprop2#projection_v1{epoch_number=NewEpoch},
?REACT({a30, ?LINE, [{newprop3, machi_projection:make_summary(P_newprop3)}]}),
?REACT({a31, ?LINE, [{newprop3, machi_projection:make_summary(P_newprop3)}]}),
{P_newprop10, S10} = {P_newprop3, S3},
P_newprop11 = machi_projection:update_checksum(P_newprop10),
?REACT({a30, ?LINE, [{newprop11, machi_projection:make_summary(P_newprop11)}]}),
?REACT({a31, ?LINE, [{newprop11, machi_projection:make_summary(P_newprop11)}]}),
react_to_env_A40(Retries, P_newprop11, P_latest,
LatestUnanimousP, S10).
react_to_env_A40(Retries, P_newprop11, P_latest, LatestUnanimousP,
false, S10).
a40_latest_author_down(#projection_v1{author_server=LatestAuthor}=_P_latest,
#projection_v1{upi=[], repairing=[],
@ -1253,7 +1273,7 @@ a40_latest_author_down(#projection_v1{author_server=LatestAuthor}=_P_latest,
#projection_v1{down=NewPropDown}=_P_newprop, _S) ->
lists:member(LatestAuthor, NewPropDown).
react_to_env_A40(Retries, P_newprop, P_latest, LatestUnanimousP,
react_to_env_A40(Retries, P_newprop, P_latest, LatestUnanimousP, AmHosedP,
#ch_mgr{name=MyName, proj=P_current}=S) ->
?REACT(a40),
[{Rank_newprop, _}] = rank_projections([P_newprop], P_current),
@ -1268,6 +1288,33 @@ react_to_env_A40(Retries, P_newprop, P_latest, LatestUnanimousP,
{author_is_down_p, LatestAuthorDownP}]}),
if
AmHosedP ->
if P_current#projection_v1.upi /= []
andalso
P_newprop#projection_v1.upi == [] ->
io:format(user, "TODO this clause needs more review!\n",[]),
%% This is a cp_mode case only.
%% I am hosed. I need to shut up and quit disturbing my
%% peers. If P_latest is the none projection that I wrote
%% on a previous iteration and it's also unanimous, then
%% go to B10 so that I can adopt it. Otherwise, tell the
%% world my intention via C300.
if P_latest#projection_v1.author_server == MyName andalso
P_latest#projection_v1.upi == [] andalso
LatestUnanimousP ->
?REACT({a40, ?LINE, []}),
react_to_env_B10(Retries, P_newprop, P_latest,
LatestUnanimousP,
AmHosedP, Rank_newprop, Rank_latest, S);
true ->
?REACT({a40, ?LINE, []}),
react_to_env_C300(P_newprop, P_latest, S)
end;
true ->
?REACT({a40, ?LINE, []}),
react_to_env_A50(P_latest, [], S)
end;
%% Epoch == 0 is reserved for first-time, just booting conditions.
(Rank_newprop > 0 orelse (Rank_newprop == ?RANK_CP_MINORITY_QUORUM))
andalso
@ -1282,7 +1329,7 @@ react_to_env_A40(Retries, P_newprop, P_latest, LatestUnanimousP,
{latest_unanimous_p, LatestUnanimousP}]}),
react_to_env_B10(Retries, P_newprop, P_latest, LatestUnanimousP,
Rank_newprop, Rank_latest, S);
AmHosedP, Rank_newprop, Rank_latest, S);
Rank_newprop > 0
andalso
@ -1313,7 +1360,7 @@ react_to_env_A40(Retries, P_newprop, P_latest, LatestUnanimousP,
%% I'm keeping this 'if' clause just in case the local FLU
%% projection store assumption changes.
react_to_env_B10(Retries, P_newprop, P_latest, LatestUnanimousP,
Rank_newprop, Rank_latest, S);
AmHosedP, Rank_newprop, Rank_latest, S);
%% A40a (see flowchart)
Rank_newprop > Rank_latest ->
@ -1417,8 +1464,7 @@ react_to_env_A50(P_latest, FinalProps, #ch_mgr{proj=P_current}=S) ->
{{no_change, FinalProps, P_current#projection_v1.epoch_number}, S}.
react_to_env_B10(Retries, P_newprop, P_latest, LatestUnanimousP,
Rank_newprop, Rank_latest,
#ch_mgr{name=MyName}=S)->
AmHosedP, Rank_newprop, Rank_latest, #ch_mgr{name=MyName}=S) ->
?REACT(b10),
?REACT({b10,?LINE,[{newprop_epoch,P_newprop#projection_v1.epoch_number}]}),

View file

@ -67,6 +67,7 @@ send_fitness_update_spam(Pid, FromName, Dict) ->
init([{MyFluName}|_Args]) ->
RegName = machi_flu_psup:make_fitness_regname(MyFluName),
register(RegName, self()),
timer:send_interval(1000, dump),
{ok, #state{my_flu_name=MyFluName, reg_name=RegName}}.
handle_call({get_unfit_list}, _From, #state{active_unfit=ActiveUnfit}=S) ->
@ -98,6 +99,7 @@ handle_info({adjust_down_list, FLU}, #state{active_unfit=ActiveUnfit}=S) ->
NewUnfit = make_unfit_list(S),
Added_to_new = NewUnfit -- ActiveUnfit,
Dropped_from_new = ActiveUnfit -- NewUnfit,
io:format(user, "adjust_down_list: ~w: adjust ~w: add ~p drop ~p\n", [S#state.my_flu_name, FLU, Added_to_new, Dropped_from_new]),
case {lists:member(FLU,Added_to_new), lists:member(FLU,Dropped_from_new)} of
{true, true} ->
error({bad, ?MODULE, ?LINE, FLU, ActiveUnfit, NewUnfit});
@ -108,6 +110,10 @@ handle_info({adjust_down_list, FLU}, #state{active_unfit=ActiveUnfit}=S) ->
{false, false} ->
{noreply, S}
end;
handle_info(dump, #state{my_flu_name=MyFluName,active_unfit=ActiveUnfit,
pending_map=Map}=S) ->
io:format(user, "DUMP: ~w: ~p ~w\n", [MyFluName, ActiveUnfit, map_value(Map)]),
{noreply, S};
handle_info(_Info, S) ->
{noreply, S}.

View file

@ -380,28 +380,28 @@ convergence_demo_testfun(NumFLUs, MgrOpts0) ->
%% Uncomment *one* of the following make_partition_list() bodies.
make_partition_list(All_list) ->
Island1 = [hd(All_list), lists:last(All_list)],
Island2 = All_list -- Island1,
[
[{X,Y} || X <- Island1, Y <- Island2]
++
[{X,Y} || X <- Island2, Y <- Island1]
].
%% Island1 = [hd(All_list), lists:last(All_list)],
%% Island2 = All_list -- Island1,
%% [
%% [{X,Y} || X <- Island1, Y <- Island2]
%% ++
%% [{X,Y} || X <- Island2, Y <- Island1]
%% ].
%% _X_Ys1 = [[{X,Y}] || X <- All_list, Y <- All_list, X /= Y],
%% _X_Ys2 = [[{X,Y}, {A,B}] || X <- All_list, Y <- All_list, X /= Y,
%% A <- All_list, B <- All_list, A /= B,
%% X /= A],
%% _X_Ys3 = [[{X,Y}, {A,B}, {C,D}] || X <- All_list, Y <- All_list, X /= Y,
%% A <- All_list, B <- All_list, A /= B,
%% C <- All_list, D <- All_list, C /= D,
%% X /= A, X /= C, A /= C],
_X_Ys1 = [[{X,Y}] || X <- All_list, Y <- All_list, X /= Y],
_X_Ys2 = [[{X,Y}, {A,B}] || X <- All_list, Y <- All_list, X /= Y,
A <- All_list, B <- All_list, A /= B,
X /= A],
_X_Ys3 = [[{X,Y}, {A,B}, {C,D}] || X <- All_list, Y <- All_list, X /= Y,
A <- All_list, B <- All_list, A /= B,
C <- All_list, D <- All_list, C /= D,
X /= A, X /= C, A /= C],
%% Concat = _X_Ys1,
%% %% Concat = _X_Ys2,
%% %% Concat = _X_Ys1 ++ _X_Ys2,
%% %% %% Concat = _X_Ys3,
%% %% Concat = _X_Ys1 ++ _X_Ys2 ++ _X_Ys3,
%% random_sort(lists:usort([lists:sort(L) || L <- Concat])).
%% Concat = _X_Ys2,
%% Concat = _X_Ys1 ++ _X_Ys2,
%% %% Concat = _X_Ys3,
Concat = _X_Ys1 ++ _X_Ys2 ++ _X_Ys3,
random_sort(lists:usort([lists:sort(L) || L <- Concat])).
%% %% for len=5 and 2 witnesses
%% [