Bug fixes: model and real bugs, thanks PULSE and converge_demo both!
This commit is contained in:
parent
0cf9627f26
commit
be62300b3b
4 changed files with 88 additions and 53 deletions
|
@ -1352,6 +1352,7 @@ react_to_env_C100(P_newprop, P_latest,
|
||||||
react_to_env_C110(P_latest, #ch_mgr{name=MyName} = S) ->
|
react_to_env_C110(P_latest, #ch_mgr{name=MyName} = S) ->
|
||||||
?REACT(c110),
|
?REACT(c110),
|
||||||
Extra_todo = [],
|
Extra_todo = [],
|
||||||
|
%% Extra_todo = [{hee, lists:reverse(get(react))}],
|
||||||
P_latest2 = machi_projection:update_dbg2(P_latest, Extra_todo),
|
P_latest2 = machi_projection:update_dbg2(P_latest, Extra_todo),
|
||||||
|
|
||||||
MyNamePid = proxy_pid(MyName, S),
|
MyNamePid = proxy_pid(MyName, S),
|
||||||
|
@ -1446,6 +1447,7 @@ react_to_env_C310(P_newprop, S) ->
|
||||||
?REACT({c310, ?LINE,
|
?REACT({c310, ?LINE,
|
||||||
[{newprop, machi_projection:make_summary(P_newprop)},
|
[{newprop, machi_projection:make_summary(P_newprop)},
|
||||||
{write_result, WriteRes}]}),
|
{write_result, WriteRes}]}),
|
||||||
|
%% io:format(user, "HEE310 ~w ~w ~w\n", [S#ch_mgr.name, self(), lists:reverse(get(react))]),
|
||||||
react_to_env_A10(S2).
|
react_to_env_A10(S2).
|
||||||
|
|
||||||
calculate_flaps(P_newprop, _P_current, _FlapLimit,
|
calculate_flaps(P_newprop, _P_current, _FlapLimit,
|
||||||
|
@ -1721,6 +1723,35 @@ projection_transition_is_sane(
|
||||||
not (lists:member(RelativeToServer, Down_list2) orelse
|
not (lists:member(RelativeToServer, Down_list2) orelse
|
||||||
lists:member(RelativeToServer, Repairing_list2)),
|
lists:member(RelativeToServer, Repairing_list2)),
|
||||||
|
|
||||||
|
UPIs_are_disjointP = ordsets:is_disjoint(ordsets:from_list(UPI_list1),
|
||||||
|
ordsets:from_list(UPI_list2)),
|
||||||
|
case UPI_2_suffix -- UPI_list1 of
|
||||||
|
[] ->
|
||||||
|
true;
|
||||||
|
[_|_] = _Added_by_2 ->
|
||||||
|
if RetrospectiveP ->
|
||||||
|
%% Any servers added to the UPI must be added from the
|
||||||
|
%% repairing list ... but in retrospective mode (where
|
||||||
|
%% we're checking only the transitions where all
|
||||||
|
%% UPI+repairing participants have unanimous private
|
||||||
|
%% projections!), and if we're under asymmetric
|
||||||
|
%% partition/churn, then we may not see the repairing
|
||||||
|
%% list. So we will not check that condition here.
|
||||||
|
true;
|
||||||
|
not RetrospectiveP ->
|
||||||
|
%% We're not retrospective. So, if some server was
|
||||||
|
%% added by to the UPI, then that means that it was
|
||||||
|
%% added by repair. And repair is coordinated by the
|
||||||
|
%% UPI tail/last.
|
||||||
|
%io:format(user, "g: UPI_list1=~w, UPI_list2=~w, UPI_2_suffix=~w, ",
|
||||||
|
% [UPI_list1, UPI_list2, UPI_2_suffix]),
|
||||||
|
%io:format(user, "g", []),
|
||||||
|
true = UPI_list1 == [] orelse
|
||||||
|
UPIs_are_disjointP orelse
|
||||||
|
(lists:last(UPI_list1) == AuthorServer2)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
if not MoreCheckingP ->
|
if not MoreCheckingP ->
|
||||||
ok;
|
ok;
|
||||||
MoreCheckingP ->
|
MoreCheckingP ->
|
||||||
|
@ -1788,16 +1819,26 @@ projection_transition_is_sane(
|
||||||
%% The retrospective view by
|
%% The retrospective view by
|
||||||
%% machi_chain_manager1_pulse.erl just can't
|
%% machi_chain_manager1_pulse.erl just can't
|
||||||
%% reason correctly about this situation. We
|
%% reason correctly about this situation. We
|
||||||
%% will instead rely on the non-introspective
|
%% will instead rely on the non-retrospective
|
||||||
%% sanity checking that each FLU does before it
|
%% sanity checking that each FLU does before it
|
||||||
%% writes to its private projection store and
|
%% writes to its private projection store and
|
||||||
%% then adopts that projection (and unwedges
|
%% then adopts that projection (and unwedges
|
||||||
%% itself, etc etc).
|
%% itself, etc etc).
|
||||||
|
|
||||||
exit({todo, revisit, ?MODULE, ?LINE}),
|
if UPIs_are_disjointP ->
|
||||||
|
true;
|
||||||
|
true ->
|
||||||
|
exit({todo, revisit, ?MODULE, ?LINE,
|
||||||
|
[
|
||||||
|
{oops_check_UPI_2_suffix, Oops_check_UPI_2_suffix},
|
||||||
|
{upi_2_suffix, UPI_2_suffix},
|
||||||
|
{upi_2_concat, UPI_2_concat},
|
||||||
|
{retrospectivep, RetrospectiveP}
|
||||||
|
]}),
|
||||||
io:format(user, "|~p,~p TODO revisit|",
|
io:format(user, "|~p,~p TODO revisit|",
|
||||||
[?MODULE, ?LINE]),
|
[?MODULE, ?LINE]),
|
||||||
ok;
|
ok
|
||||||
|
end;
|
||||||
true ->
|
true ->
|
||||||
%% The following is OK: We're shifting from a
|
%% The following is OK: We're shifting from a
|
||||||
%% normal projection to an inner one. The old
|
%% normal projection to an inner one. The old
|
||||||
|
@ -1843,7 +1884,13 @@ projection_transition_is_sane(
|
||||||
true;
|
true;
|
||||||
SecondCase_p ->
|
SecondCase_p ->
|
||||||
true;
|
true;
|
||||||
not RetrospectiveP ->
|
UPIs_are_disjointP ->
|
||||||
|
%% If there's no overlap at all between
|
||||||
|
%% UPI_list1 & UPI_list2, then we're OK
|
||||||
|
%% here.
|
||||||
|
io:format(user, "QQQ Oops_check_UPI_2_suffix=~w, ", [Oops_check_UPI_2_suffix]),
|
||||||
|
true;
|
||||||
|
true ->
|
||||||
exit({upi_2_suffix_error, UPI_2_suffix})
|
exit({upi_2_suffix_error, UPI_2_suffix})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -251,35 +251,21 @@ convergence_demo_testfun(NumFLUs) ->
|
||||||
%% unique chains are disjoint.
|
%% unique chains are disjoint.
|
||||||
true = machi_chain_manager1_test:all_reports_are_disjoint(Report),
|
true = machi_chain_manager1_test:all_reports_are_disjoint(Report),
|
||||||
|
|
||||||
%% Given the report, we flip it around so that we observe the
|
|
||||||
%% sets of chain transitions relative to each FLU.
|
|
||||||
%% R_Chains's type is: list({RelativeFlu, list({Epoch, UPI, Repairing})})
|
|
||||||
%% For example:
|
|
||||||
%% [{a,[{3,[a],[b,c]},
|
|
||||||
%% {7,[a,b],[c]},
|
|
||||||
%% {14,[a,b,c],[]},
|
|
||||||
%% {83,[a],[]},
|
|
||||||
%% {164,[c],[a,b]},
|
|
||||||
%% {218,[a],[]},
|
|
||||||
%% {226,[a],[b,c]},
|
|
||||||
%% {228,[a],[b,c]},
|
|
||||||
%% ....
|
|
||||||
R_Chains = [machi_chain_manager1_test:extract_chains_relative_to_flu(
|
|
||||||
FLU, Report) || FLU <- All_list],
|
|
||||||
%% ?D(R_Chains),
|
|
||||||
R_Projs = [{FLU, [machi_chain_manager1_test:chain_to_projection(
|
|
||||||
FLU, Epoch, UPI, Repairing, All_list) ||
|
|
||||||
{Epoch, UPI, Repairing} <- E_Chains]} ||
|
|
||||||
{FLU, E_Chains} <- R_Chains],
|
|
||||||
|
|
||||||
%% For each chain transition experienced by a particular FLU,
|
%% For each chain transition experienced by a particular FLU,
|
||||||
%% confirm that each state transition is OK.
|
%% confirm that each state transition is OK.
|
||||||
|
PrivProjs = [{Name, begin
|
||||||
|
{ok, Ps9} = ?FLU_PC:get_all_projections(FLU,
|
||||||
|
private),
|
||||||
|
[P || P <- Ps9,
|
||||||
|
P#projection_v1.epoch_number /= 0]
|
||||||
|
end} || {Name, FLU} <- Namez],
|
||||||
try
|
try
|
||||||
[{FLU, true} = {FLU, ?MGR:projection_transitions_are_sane(Psx, FLU)} ||
|
[{FLU, true} = {FLU, ?MGR:projection_transitions_are_sane_retrospective(Psx, FLU)} ||
|
||||||
{FLU, Psx} <- R_Projs],
|
{FLU, Psx} <- PrivProjs],
|
||||||
io:format(user, "\nAll sanity checks pass, hooray!\n", [])
|
io:format(user, "\nAll sanity checks pass, hooray!\n", [])
|
||||||
catch _Err:_What ->
|
catch _Err:_What ->
|
||||||
io:format(user, "Report ~p\n", [Report]),
|
io:format(user, "Report ~p\n", [Report]),
|
||||||
|
io:format(user, "PrivProjs ~p\n", [PrivProjs]),
|
||||||
exit({line, ?LINE, _Err, _What})
|
exit({line, ?LINE, _Err, _What})
|
||||||
end,
|
end,
|
||||||
%% ?D(R_Projs),
|
%% ?D(R_Projs),
|
||||||
|
@ -311,9 +297,10 @@ make_partition_list(All_list) ->
|
||||||
A <- All_list, B <- All_list, A /= B,
|
A <- All_list, B <- All_list, A /= B,
|
||||||
C <- All_list, D <- All_list, C /= D,
|
C <- All_list, D <- All_list, C /= D,
|
||||||
X /= A, X /= C, A /= C],
|
X /= A, X /= C, A /= C],
|
||||||
%% _X_Ys1 ++ _X_Ys2.
|
%% Concat = _X_Ys1 ++ _X_Ys2.
|
||||||
%% _X_Ys3.
|
%% Concat = _X_Ys3.
|
||||||
_X_Ys1 ++ _X_Ys2 ++ _X_Ys3.
|
Concat = _X_Ys1 ++ _X_Ys2 ++ _X_Ys3,
|
||||||
|
lists:usort([lists:sort(L) || L <- Concat]).
|
||||||
|
|
||||||
%% [ [{a,b},{b,d},{c,b}],
|
%% [ [{a,b},{b,d},{c,b}],
|
||||||
%% [{a,b},{b,d},{c,b}, {a,b},{b,a},{a,c},{c,a},{a,d},{d,a}],
|
%% [{a,b},{b,d},{c,b}, {a,b},{b,a},{a,c},{c,a},{a,d},{d,a}],
|
||||||
|
|
|
@ -110,10 +110,10 @@ all_list_extra() ->
|
||||||
props=[{chmgr, b_chmgr}]}, "./data.pulse.b"}
|
props=[{chmgr, b_chmgr}]}, "./data.pulse.b"}
|
||||||
, {#p_srvr{name=c, address="localhost", port=7402,
|
, {#p_srvr{name=c, address="localhost", port=7402,
|
||||||
props=[{chmgr, c_chmgr}]}, "./data.pulse.c"}
|
props=[{chmgr, c_chmgr}]}, "./data.pulse.c"}
|
||||||
, {#p_srvr{name=d, address="localhost", port=7403,
|
%% , {#p_srvr{name=d, address="localhost", port=7403,
|
||||||
props=[{chmgr, d_chmgr}]}, "./data.pulse.d"}
|
%% props=[{chmgr, d_chmgr}]}, "./data.pulse.d"}
|
||||||
, {#p_srvr{name=e, address="localhost", port=7404,
|
%% , {#p_srvr{name=e, address="localhost", port=7404,
|
||||||
props=[{chmgr, e_chmgr}]}, "./data.pulse.e"}
|
%% props=[{chmgr, e_chmgr}]}, "./data.pulse.e"}
|
||||||
].
|
].
|
||||||
|
|
||||||
all_list() ->
|
all_list() ->
|
||||||
|
@ -261,11 +261,21 @@ dump_state() ->
|
||||||
%% || {FLUName, _FLU} <- Namez]
|
%% || {FLUName, _FLU} <- Namez]
|
||||||
%% || Epoch <- UniquePrivateEs],
|
%% || Epoch <- UniquePrivateEs],
|
||||||
|
|
||||||
|
PrivProjs = [{Name, begin
|
||||||
|
{ok, Ps} = ?FLU_PC:get_all_projections(Proxy,
|
||||||
|
private),
|
||||||
|
[P || P <- Ps,
|
||||||
|
P#projection_v1.epoch_number /= 0]
|
||||||
|
end} || {Name, Proxy} <- ProxiesDict],
|
||||||
|
|
||||||
?QC_FMT(")", []),
|
?QC_FMT(")", []),
|
||||||
Diag1 = Diag2 = "skip_diags",
|
Diag1 = Diag2 = "skip_diags",
|
||||||
{Report, lists:flatten([Diag1, Diag2])}
|
{Report, PrivProjs, lists:flatten([Diag1, Diag2])}
|
||||||
catch XX:YY ->
|
catch XX:YY ->
|
||||||
?QC_FMT("OUCH: ~p ~p @ ~p\n", [XX, YY, erlang:get_stacktrace()])
|
?QC_FMT("OUCH: ~p ~p @ ~p\n", [XX, YY, erlang:get_stacktrace()]),
|
||||||
|
?QC_FMT("Exiting now to move to manual post-mortem....\n", []),
|
||||||
|
erlang:halt(0),
|
||||||
|
false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
prop_pulse() ->
|
prop_pulse() ->
|
||||||
|
@ -296,8 +306,6 @@ prop_pulse() ->
|
||||||
{_H, _S, _R} = run_commands(?MODULE, Cmds)
|
{_H, _S, _R} = run_commands(?MODULE, Cmds)
|
||||||
end, [{seed, Seed},
|
end, [{seed, Seed},
|
||||||
{strategy, unfair}]),
|
{strategy, unfair}]),
|
||||||
ok = shutdown_hard(),
|
|
||||||
|
|
||||||
%% ?QC_FMT("S2 ~p\n", [S2]),
|
%% ?QC_FMT("S2 ~p\n", [S2]),
|
||||||
case S2#state.dump_state of
|
case S2#state.dump_state of
|
||||||
undefined ->
|
undefined ->
|
||||||
|
@ -305,7 +313,7 @@ prop_pulse() ->
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
{Report, Diag} = S2#state.dump_state,
|
{Report, PrivProjs, Diag} = S2#state.dump_state,
|
||||||
|
|
||||||
%% Report is ordered by Epoch. For each private projection
|
%% Report is ordered by Epoch. For each private projection
|
||||||
%% written during any given epoch, confirm that all chain
|
%% written during any given epoch, confirm that all chain
|
||||||
|
@ -313,21 +321,12 @@ prop_pulse() ->
|
||||||
%% unique chains are disjoint.
|
%% unique chains are disjoint.
|
||||||
AllDisjointP = ?MGRTEST:all_reports_are_disjoint(Report),
|
AllDisjointP = ?MGRTEST:all_reports_are_disjoint(Report),
|
||||||
|
|
||||||
%% Given the report, we flip it around so that we observe the
|
|
||||||
%% sets of chain transitions relative to each FLU.
|
|
||||||
R_Chains = [?MGRTEST:extract_chains_relative_to_flu(FLU, Report) ||
|
|
||||||
FLU <- all_list()],
|
|
||||||
R_Projs = [{FLU, [?MGRTEST:chain_to_projection(
|
|
||||||
FLU, Epoch, UPI, Repairing, all_list()) ||
|
|
||||||
{Epoch, UPI, Repairing} <- E_Chains]} ||
|
|
||||||
{FLU, E_Chains} <- R_Chains],
|
|
||||||
|
|
||||||
%% For each chain transition experienced by a particular FLU,
|
%% For each chain transition experienced by a particular FLU,
|
||||||
%% confirm that each state transition is OK.
|
%% confirm that each state transition is OK.
|
||||||
Sane =
|
Sane =
|
||||||
[{FLU,_SaneRes} = {FLU,?MGR:projection_transitions_are_sane_retrospective(
|
[{FLU,_SaneRes} = {FLU,?MGR:projection_transitions_are_sane_retrospective(
|
||||||
Ps, FLU)} ||
|
Ps, FLU)} ||
|
||||||
{FLU, Ps} <- R_Projs],
|
{FLU, Ps} <- PrivProjs],
|
||||||
SaneP = lists:all(fun({_FLU, SaneRes}) -> SaneRes == true end, Sane),
|
SaneP = lists:all(fun({_FLU, SaneRes}) -> SaneRes == true end, Sane),
|
||||||
|
|
||||||
%% The final report item should say that all are agreed_membership.
|
%% The final report item should say that all are agreed_membership.
|
||||||
|
@ -342,12 +341,14 @@ prop_pulse() ->
|
||||||
LastRepXs
|
LastRepXs
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
ok = shutdown_hard(),
|
||||||
?WHENFAIL(
|
?WHENFAIL(
|
||||||
begin
|
begin
|
||||||
?QC_FMT("Cmds = ~p\n", [Cmds]),
|
?QC_FMT("Cmds = ~p\n", [Cmds]),
|
||||||
?QC_FMT("Res = ~p\n", [Res]),
|
?QC_FMT("Res = ~p\n", [Res]),
|
||||||
?QC_FMT("Diag = ~s\n", [Diag]),
|
?QC_FMT("Diag = ~s\n", [Diag]),
|
||||||
?QC_FMT("Report = ~p\n", [Report]),
|
?QC_FMT("Report = ~p\n", [Report]),
|
||||||
|
?QC_FMT("PrivProjs = ~p\n", [PrivProjs]),
|
||||||
?QC_FMT("Sane = ~p\n", [Sane]),
|
?QC_FMT("Sane = ~p\n", [Sane]),
|
||||||
?QC_FMT("SingleChainNoRepair failure =\n ~p\n", [SingleChainNoRepair])
|
?QC_FMT("SingleChainNoRepair failure =\n ~p\n", [SingleChainNoRepair])
|
||||||
,erlang:halt(0)
|
,erlang:halt(0)
|
||||||
|
|
|
@ -99,7 +99,7 @@ unanimous_report(Epoch, Namez) ->
|
||||||
{not_agreed, {UPI, Repairing}, Else2}
|
{not_agreed, {UPI, Repairing}, Else2}
|
||||||
end;
|
end;
|
||||||
_Else ->
|
_Else ->
|
||||||
exit({UPI, not_unique, Epoch, _Else})
|
{not_agreed, {undefined, undefined}, Projs}
|
||||||
end
|
end
|
||||||
end || UPI <- UniqueUPIs],
|
end || UPI <- UniqueUPIs],
|
||||||
AgreedResUPI_Rs = [UPI++Repairing ||
|
AgreedResUPI_Rs = [UPI++Repairing ||
|
||||||
|
@ -128,7 +128,7 @@ chain_to_projection(MyName, Epoch, UPI_list, Repairing_list, All_list) ->
|
||||||
FLU <- All_list]),
|
FLU <- All_list]),
|
||||||
machi_projection:new(Epoch, MyName, MemberDict,
|
machi_projection:new(Epoch, MyName, MemberDict,
|
||||||
All_list -- (UPI_list ++ Repairing_list),
|
All_list -- (UPI_list ++ Repairing_list),
|
||||||
UPI_list, Repairing_list, []).
|
UPI_list, Repairing_list, [{artificial_by, ?MODULE}]).
|
||||||
|
|
||||||
-ifndef(PULSE).
|
-ifndef(PULSE).
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue