WIP: egadz, a refactoring mess, but finally AP mode not sucky

This commit is contained in:
Scott Lystig Fritchie 2015-08-20 17:32:46 +09:00
parent a71e9543fe
commit 4e7d1f2310

View file

@ -65,7 +65,7 @@
timer :: 'undefined' | timer:tref(), timer :: 'undefined' | timer:tref(),
ignore_timer :: boolean(), ignore_timer :: boolean(),
proj_history :: queue:queue(), proj_history :: queue:queue(),
flap_count=0 :: integer(), flap_count=0 :: non_neg_integer(), % I am flapping if > 0.
flap_start=?NOT_FLAPPING_START flap_start=?NOT_FLAPPING_START
:: {{'epk', integer()}, erlang:timestamp()}, :: {{'epk', integer()}, erlang:timestamp()},
flap_last_up=[] :: list(), flap_last_up=[] :: list(),
@ -1120,6 +1120,7 @@ react_to_env_A30(Retries, P_latest, LatestUnanimousP, _ReadExtra,
#ch_mgr{name=MyName, proj=P_current, #ch_mgr{name=MyName, proj=P_current,
consistency_mode=CMode, flap_limit=FlapLimit} = S) -> consistency_mode=CMode, flap_limit=FlapLimit} = S) ->
?REACT(a30), ?REACT(a30),
case length(get(react)) of XX when XX > 500 -> io:format(user, "A30! ~w: ~P\n", [MyName, get(react), 140]), timer:sleep(500); _ -> ok end,
{P_newprop1, S2, Up} = calc_projection(S, MyName), {P_newprop1, S2, Up} = calc_projection(S, MyName),
?REACT({a30, ?LINE, [{current, machi_projection:make_summary(S#ch_mgr.proj)}]}), ?REACT({a30, ?LINE, [{current, machi_projection:make_summary(S#ch_mgr.proj)}]}),
?REACT({a30, ?LINE, [{newprop1, machi_projection:make_summary(P_newprop1)}]}), ?REACT({a30, ?LINE, [{newprop1, machi_projection:make_summary(P_newprop1)}]}),
@ -1160,6 +1161,7 @@ react_to_env_A30(Retries, P_latest, LatestUnanimousP, _ReadExtra,
{flap_limit, FlapLimit}]}), {flap_limit, FlapLimit}]}),
{P_newprop3, S3} {P_newprop3, S3}
end, end,
?REACT({a30, ?LINE, [{newprop10, machi_projection:make_summary(P_newprop10)}]}),
%% Here's a more common reason for moving from inner projection to %% Here's a more common reason for moving from inner projection to
%% a normal projection: the old proj has an inner but the newprop %% a normal projection: the old proj has an inner but the newprop
@ -1267,32 +1269,36 @@ react_to_env_A30(Retries, P_latest, LatestUnanimousP, _ReadExtra,
a30_make_inner_projection(P_current, P_newprop3, P_latest, Up, a30_make_inner_projection(P_current, P_newprop3, P_latest, Up,
#ch_mgr{name=MyName, consistency_mode=CMode} = S) -> #ch_mgr{name=MyName, consistency_mode=CMode} = S) ->
AllHosed = get_all_hosed(P_newprop3), AllHosed = get_all_hosed(P_newprop3),
P_current_inner = inner_projection_or_self(P_current), P_current_has_inner_p = inner_projection_exists(P_current),
{P_i, S_i, _Up} = calc_projection2(P_current_inner, P_current_ios = inner_projection_or_self(P_current),
NewEpochOuter = erlang:max(P_latest#projection_v1.epoch_number + 1,
P_newprop3#projection_v1.epoch_number),
{P_i1, S_i, _Up} = calc_projection2(P_current_ios,
MyName, AllHosed, [], S), MyName, AllHosed, [], S),
?REACT({a30, ?LINE, [{raw_all_hosed,get_all_hosed(P_newprop3)}, ?REACT({a30, ?LINE, [{raw_all_hosed,get_all_hosed(P_newprop3)},
{up, Up}, {up, Up},
{all_hosed, AllHosed}, {all_hosed, AllHosed},
{p_c_i, machi_projection:make_summary(P_current_inner)}, {p_c_i, machi_projection:make_summary(P_current_ios)},
{p_i,machi_projection:make_summary(P_i)}]}), {p_i1, machi_projection:make_summary(P_i1)}]}),
%% The inner projection will have a fake author, which %% The inner projection will have a fake author, which
%% everyone will agree is the largest UPI member's %% everyone will agree is the largest UPI member's
%% name. %% name.
BiggestUPIMember = BiggestUPIMember =
if P_i#projection_v1.upi == [] -> if P_i1#projection_v1.upi == [] ->
%% Oops, ok, fall back to author %% Oops, ok, fall back to author
P_i#projection_v1.author_server; P_i1#projection_v1.author_server;
true -> true ->
lists:last(lists:sort(P_i#projection_v1.upi)) lists:last(lists:sort(P_i1#projection_v1.upi))
end, end,
P_i2 = P_i#projection_v1{author_server=BiggestUPIMember}, P_i2 = P_i1#projection_v1{author_server=BiggestUPIMember},
P_inner = case lists:member(MyName, AllHosed) P_i3 = case lists:member(MyName, AllHosed)
andalso andalso
CMode == ap_mode CMode == ap_mode
of of
false -> false ->
P_i2; P_i2;
true -> true ->
%% Fall back to a safe AP mode chain: just me.
P_i2#projection_v1{ P_i2#projection_v1{
upi=[MyName], upi=[MyName],
repairing=[], repairing=[],
@ -1301,38 +1307,59 @@ a30_make_inner_projection(P_current, P_newprop3, P_latest, Up,
end, end,
#projection_v1{epoch_number=Epoch_p_inner, #projection_v1{epoch_number=Epoch_p_inner,
upi=UPI_p_inner, upi=UPI_p_inner,
repairing=Repairing_p_inner} = P_inner, repairing=Repairing_p_inner} = P_i3,
LatestHasCompatibleInner = HasCompatibleInner =
case inner_projection_exists(P_latest) of case inner_projection_exists(P_latest) of
true -> true ->
P_latest_i = inner_projection_or_self(P_latest), P_latest_i = inner_projection_or_self(P_latest),
#projection_v1{epoch_number=___Epoch_current_x,
upi=UPI_current_x,
repairing=Repairing_current_x} = P_current_ios,
#projection_v1{epoch_number=Epoch_latest_i, #projection_v1{epoch_number=Epoch_latest_i,
upi=UPI_latest_i, upi=UPI_latest_i,
repairing=Repairing_latest_i} = P_latest_i, repairing=Repairing_latest_i} = P_latest_i,
?REACT({a30, ?LINE, [{epoch_latest_i, Epoch_latest_i}, ?REACT({a30, ?LINE, [{epoch_latest_i, Epoch_latest_i},
{upi_latest_i, UPI_latest_i}, {upi_latest_i, UPI_latest_i},
{repairing_latest_i}]}), {repairing_latest_i}]}),
%io:format(user, "INNER: ~p line ~p ~p\n", [{epoch_latest_i, Epoch_latest_i}, {epoch_final_inner, FinalInnerEpoch}, {upi_latest_i, UPI_latest_i}, {repairing_latest_i}]), SameEnough_p =
if %% TODO yo delete? Epoch_latest_i > FinalInnerEpoch UPI_latest_i == P_current_ios#projection_v1.upi
%% TODO yo delete? andalso
UPI_p_inner == UPI_latest_i
andalso andalso
Repairing_p_inner == Repairing_latest_i -> Repairing_latest_i == P_current_ios#projection_v1.repairing
%% Use latest's inner projection instead! andalso
Epoch_latest_i >= P_current_ios#projection_v1.epoch_number,
CurrentInner_and_Disjoint_p =
P_current_has_inner_p
andalso
ordsets:is_disjoint(
ordsets:from_list(UPI_current_x ++ Repairing_current_x),
ordsets:from_list(UPI_latest_i ++ Repairing_latest_i)),
if SameEnough_p ->
?REACT({a30, ?LINE, []}), ?REACT({a30, ?LINE, []}),
%io:format(user, "INNER: ~p line ~p\n", [MyName, ?LINE]), P_latest_i;
machi_projection:update_checksum( CurrentInner_and_Disjoint_p ->
P_inner#projection_v1{inner=P_latest_i}); ?REACT({a30, ?LINE, []}),
P_current_ios;
true -> true ->
?REACT({a30, ?LINE, []}), ?REACT({a30, ?LINE, []}),
false false
end; end;
false -> false ->
#projection_v1{upi=UPI_i3,
repairing=Repairing_i3} = P_i3,
if P_current_has_inner_p,
UPI_i3 == P_current_ios#projection_v1.upi,
Repairing_i3 == P_current_ios#projection_v1.repairing ->
?REACT({a30, ?LINE, []}),
P_current_ios;
true ->
?REACT({a30, ?LINE, []}), ?REACT({a30, ?LINE, []}),
false false
end
end, end,
if LatestHasCompatibleInner /= false -> if HasCompatibleInner /= false ->
{LatestHasCompatibleInner, S_i}; P_newprop4 = machi_projection:update_checksum(
P_newprop3#projection_v1{inner=HasCompatibleInner}),
{P_newprop4, S_i};
true -> true ->
FinalInnerEpoch = FinalInnerEpoch =
case inner_projection_exists(P_current) of case inner_projection_exists(P_current) of
@ -1340,49 +1367,25 @@ a30_make_inner_projection(P_current, P_newprop3, P_latest, Up,
?REACT({a30xyzxyz, ?LINE, [P_newprop3#projection_v1.epoch_number]}), ?REACT({a30xyzxyz, ?LINE, [P_newprop3#projection_v1.epoch_number]}),
FinalCreation = P_newprop3#projection_v1.creation_time, FinalCreation = P_newprop3#projection_v1.creation_time,
P_newprop3#projection_v1.epoch_number; P_newprop3#projection_v1.epoch_number;
%% AllFlapCounts_epk =
%% [Epk || {{Epk,_FlTime}, _FlCount} <-
%% get_all_flap_counts(P_newprop3)],
%% case AllFlapCounts_epk of
%% [] ->
%% ?REACT({a30xyzxyz, ?LINE, [P_newprop3#projection_v1.epoch_number]}),
%% P_newprop3#projection_v1.epoch_number;
%% [_|_] ->
%% ?REACT({a30xyzxyz, ?LINE, [AllFlapCounts_epk]}),
%% lists:max(AllFlapCounts_epk)
%% end;
true -> true ->
P_oldinner = inner_projection_or_self(P_current), P_oldinner = inner_projection_or_self(P_current),
if P_oldinner#projection_v1.upi ==
P_inner#projection_v1.upi
andalso
P_oldinner#projection_v1.repairing ==
P_inner#projection_v1.repairing
andalso
P_oldinner#projection_v1.down ==
P_inner#projection_v1.down ->
?REACT({a30xyzxyz, ?LINE, [P_oldinner#projection_v1.epoch_number]}),
FinalCreation = P_oldinner#projection_v1.creation_time,
P_oldinner#projection_v1.epoch_number;
true ->
?REACT({a30xyzxyz, ?LINE, [P_oldinner#projection_v1.epoch_number + 1]}), ?REACT({a30xyzxyz, ?LINE, [P_oldinner#projection_v1.epoch_number + 1]}),
FinalCreation = P_newprop3#projection_v1.creation_time, FinalCreation = P_newprop3#projection_v1.creation_time,
P_oldinner#projection_v1.epoch_number + 1 P_oldinner#projection_v1.epoch_number + 1
end
end, end,
%% TODO: When we implement the real chain repair function, we %% TODO: When we implement the real chain repair function, we
%% need to keep in mind that an inner projection with %% need to keep in mind that an inner projection with
%% up nodes > 1, repair is required there! In the %% up nodes > 1, repair is required there! In the
%% current simulator, repair is not simulated and %% current simulator, repair is not simulated and
%% finished (and then growing the UPI list). Fix. %% finished (and then growing the UPI list). Fix.
P_inner2 = machi_projection:update_checksum( P_i4 = machi_projection:update_checksum(
P_inner#projection_v1{epoch_number=FinalInnerEpoch, P_i3#projection_v1{epoch_number=FinalInnerEpoch,
creation_time=FinalCreation}), creation_time=FinalCreation}),
?REACT({a30, ?LINE, [{inner_summary, ?REACT({a30, ?LINE, [{inner_summary,
machi_projection:make_summary(P_inner2)}]}), machi_projection:make_summary(P_i4)}]}),
%% Put it all together. %% Put it all together.
P_newprop4 = machi_projection:update_checksum( P_newprop4 = machi_projection:update_checksum(
P_newprop3#projection_v1{inner=P_inner2}), P_newprop3#projection_v1{inner=P_i4}),
{P_newprop4, S_i} {P_newprop4, S_i}
end. end.
@ -1410,7 +1413,9 @@ react_to_env_A40(Retries, P_newprop, P_latest, LatestUnanimousP,
P_latest#projection_v1.author_server /= MyName, P_latest#projection_v1.author_server /= MyName,
?REACT({a40, ?LINE, ?REACT({a40, ?LINE,
[{latest_author, P_latest#projection_v1.author_server}, [{latest_author, P_latest#projection_v1.author_server},
{author_is_down_p, LatestAuthorDownP}]}), {author_is_down_p, LatestAuthorDownP},
{latest_flap, P_latest#projection_v1.flap},
{newprop_flap, P_newprop#projection_v1.flap}]}),
if if
%% Epoch == 0 is reserved for first-time, just booting conditions. %% Epoch == 0 is reserved for first-time, just booting conditions.
@ -1542,7 +1547,10 @@ react_to_env_B10(Retries, P_newprop, P_latest, LatestUnanimousP,
#ch_mgr{name=MyName, flap_limit=FlapLimit, proj=P_current}=S)-> #ch_mgr{name=MyName, flap_limit=FlapLimit, proj=P_current}=S)->
?REACT(b10), ?REACT(b10),
{_P_newprop_flap_time, P_newprop_flap_count} = get_flap_count(P_newprop), {P_newprop_flap_time, P_newprop_flap_count} = get_flap_count(P_newprop),
?REACT({b10, ?LINE, [{newprop_epoch, P_newprop#projection_v1.epoch_number},
{newprop_flap_time, P_newprop_flap_time},
{newprop_flap_count, P_newprop_flap_count}]}),
UnanimousLatestInnerNotRelevant_p = UnanimousLatestInnerNotRelevant_p =
case inner_projection_exists(P_latest) of case inner_projection_exists(P_latest) of
true when P_latest#projection_v1.author_server /= MyName -> true when P_latest#projection_v1.author_server /= MyName ->
@ -2011,16 +2019,16 @@ calculate_flaps(P_newprop, P_latest, _P_current, CurrentUp, _FlapLimit,
?REACT({calculate_flaps, ?LINE, [{queue_len, queue:len(H)}, ?REACT({calculate_flaps, ?LINE, [{queue_len, queue:len(H)},
{uniques, UniqueProposalSummaries}]}), {uniques, UniqueProposalSummaries}]}),
P_latest_Flap = get_raw_flapping_i(P_latest), P_latest_Flap = get_raw_flapping_i(P_latest),
AmFlapping_or_StartingFlapping_p = AmFlappingNow_p = not (FlapStart == ?NOT_FLAPPING_START orelse
FlapStart == undefined),
StartFlapping_p =
case {queue:len(H), UniqueProposalSummaries} of case {queue:len(H), UniqueProposalSummaries} of
_ when not (FlapStart == ?NOT_FLAPPING_START orelse _ when AmFlappingNow_p ->
FlapStart == undefined) ->
%% ?REACT({calculate_flaps,?LINE,[{am_flapping,stay_flapping}]}),
?REACT({calculate_flaps,?LINE,[{flap_start,FlapStart}]}), ?REACT({calculate_flaps,?LINE,[{flap_start,FlapStart}]}),
true; %% I'm already flapping, therefore don't start again.
false;
{N, _} when N >= 3, {N, _} when N >= 3,
P_latest_Flap#flap_i.flap_count /= ?NOT_FLAPPING_START -> P_latest_Flap#flap_i.flap_count /= ?NOT_FLAPPING_START->
%%io:format(user, "CALC_FLAP: ~w: ~w\n", [MyName, machi_projection:make_summary(P_latest)]),
?REACT({calculate_flaps,?LINE,[{manifesto_clause,2}]}), ?REACT({calculate_flaps,?LINE,[{manifesto_clause,2}]}),
true; true;
{N, [_]} when N >= 3 -> {N, [_]} when N >= 3 ->
@ -2031,42 +2039,66 @@ calculate_flaps(P_newprop, P_latest, _P_current, CurrentUp, _FlapLimit,
false false
end, end,
LeaveFlapping_p = LeaveFlapping_p =
if FlapLastUp /= [], CurrentUp /= FlapLastUp -> if
StartFlapping_p ->
%% If we're starting flapping on this iteration, don't ignore
%% that intent.
false;
AmFlappingNow_p andalso
FlapLastUp /= [] andalso CurrentUp /= FlapLastUp ->
?REACT({calculate_flaps,?LINE,[{manifesto_clause,1}]}), ?REACT({calculate_flaps,?LINE,[{manifesto_clause,1}]}),
true; true;
true -> AmFlappingNow_p ->
P_latest_LastStartTime = P_latest_LastStartTime =
search_flap_counts(P_latest#projection_v1.author_server, search_last_flap_counts(
FlapCountsLast), P_latest#projection_v1.author_server, FlapCountsLast),
case get_flap_count(P_latest) of case get_flap_count(P_latest) of
{?NOT_FLAPPING_START, _Count} {?NOT_FLAPPING_START, _Count}
when P_latest_LastStartTime == undefined -> when P_latest_LastStartTime == undefined ->
%% latest proj not flapping & not flapping last time
?REACT({calculate_flaps,?LINE,[]}), ?REACT({calculate_flaps,?LINE,[]}),
false; false;
{Time, _Count} when Time == P_latest_LastStartTime -> {Curtime, _Count} when Curtime == P_latest_LastStartTime ->
%% latest proj flapping & flapping last time
?REACT({calculate_flaps,?LINE,[]}), ?REACT({calculate_flaps,?LINE,[]}),
false; false;
{Time, _Count} when Time > P_latest_LastStartTime, {Curtime, _Count} when Curtime > P_latest_LastStartTime,
P_latest_LastStartTime /= undefined -> P_latest_LastStartTime /= undefined,
P_latest_LastStartTime /= ?NOT_FLAPPING_START ->
%% latest proj flapping & older flapping last time:
%% we didn't see this author flip out of its older
%% flapping state. So we will leave flapping and then,
%% if necessary, re-flap sometime later.
?REACT({calculate_flaps,?LINE, ?REACT({calculate_flaps,?LINE,
[{manifesto_clause,3}, [{manifesto_clause,3},
{p_latest, machi_projection:make_summary(P_latest)}, {p_latest, machi_projection:make_summary(P_latest)},
{time, Time}, {curtime, Curtime},
{flap_counts_last, FlapCountsLast}, {flap_counts_last, FlapCountsLast},
{laststart_time, P_latest_LastStartTime}]}), {laststart_time, P_latest_LastStartTime}]}),
true; true;
{0, 0} when P_latest_LastStartTime /= undefined -> {0=Curtime, 0} when P_latest_LastStartTime /= undefined,
?REACT({calculate_flaps,?LINE,[{manifesto_clause,2}]}), P_latest_LastStartTime /= ?NOT_FLAPPING_START ->
?REACT({calculate_flaps,?LINE,
[{manifesto_clause,2},
{p_latest, machi_projection:make_summary(P_latest)},
{curtime, Curtime},
{flap_counts_last, FlapCountsLast},
{laststart_time, P_latest_LastStartTime}]}),
%% latest proj not flapping & flapping last time:
%% this author
true; true;
_ -> _ ->
?REACT({calculate_flaps,?LINE,[]}),
false
end;
true ->
?REACT({calculate_flaps,?LINE,[]}),
false false
end
end, end,
%%io:format(user, "CALC_FLAP: ~w: am_or_start ~w leave ~w: ~p\n", [MyName, AmFlapping_or_StartingFlapping_p, LeaveFlapping_p, [X || X={calculate_flaps,_,_} <- get(react)]]), if LeaveFlapping_p -> io:format(user, "CALC_FLAP: ~w: flapping_now ~w start ~w leave ~w: ~p\n", [MyName, AmFlappingNow_p, StartFlapping_p, LeaveFlapping_p, [X || X={calculate_flaps,_,_} <- lists:sublist(get(react), 3)]]); true -> ok end,
%%io:format(user, "CALC_FLAP: ~w: am_or_start ~w leave ~w\n", [MyName, AmFlapping_or_StartingFlapping_p, LeaveFlapping_p]),
if LeaveFlapping_p -> io:format(user, "CALC_FLAP: ~w: am_or_start ~w leave ~w: ~p\n", [MyName, AmFlapping_or_StartingFlapping_p, LeaveFlapping_p, [X || X={calculate_flaps,_,_} <- lists:sublist(get(react), 3)]]); true -> ok end,
AmFlapping_p = if LeaveFlapping_p -> false; AmFlapping_p = if LeaveFlapping_p -> false;
true -> AmFlapping_or_StartingFlapping_p true -> AmFlappingNow_p orelse StartFlapping_p
end, end,
if AmFlapping_p -> if AmFlapping_p ->
@ -2094,8 +2126,10 @@ if LeaveFlapping_p -> io:format(user, "CALC_FLAP: ~w: am_or_start ~w leave ~w: ~
AllHosed = [] AllHosed = []
end, end,
AllFlapCounts_with_my_new =
[{MyName, NewFlapStart}|lists:keydelete(MyName, 1, AllFlapCounts)],
FlappingI = make_flapping_i(NewFlapStart, NewFlapCount, AllHosed, FlappingI = make_flapping_i(NewFlapStart, NewFlapCount, AllHosed,
AllFlapCounts, BadFLUs), AllFlapCounts_with_my_new, BadFLUs),
%% NOTE: Just because we increment flaps here, there's no correlation %% NOTE: Just because we increment flaps here, there's no correlation
%% to successful public proj store writes! For example, %% to successful public proj store writes! For example,
%% if we loop through states C2xx a few times, we would incr %% if we loop through states C2xx a few times, we would incr
@ -3022,10 +3056,5 @@ calc_magic_down([H|T], G) ->
[H|calc_magic_down(T, G)] [H|calc_magic_down(T, G)]
end. end.
search_flap_counts(_FLU, []) -> search_last_flap_counts(FLU, FlapCountsLast) ->
undefined; proplists:get_value(FLU, FlapCountsLast, undefined).
search_flap_counts(FLU, [{FLU, {EpkTime, _Count}}|_]) ->
EpkTime;
search_flap_counts(FLU, [_|Tail]) ->
search_flap_counts(FLU, Tail).