WIP: much better structure for inner projection sanity checking
This commit is contained in:
parent
8241d1f600
commit
920c0fc610
2 changed files with 46 additions and 37 deletions
|
@ -1049,9 +1049,13 @@ react_to_env_A30(Retries, P_latest, LatestUnanimousP, _ReadExtra,
|
||||||
%% guarantee (yet?) that the [c,d] chain will be the UPI basis
|
%% guarantee (yet?) that the [c,d] chain will be the UPI basis
|
||||||
%% for repairs when the partition is healed: the quickest author
|
%% for repairs when the partition is healed: the quickest author
|
||||||
%% after the healing will make that choice for everyone.
|
%% after the healing will make that choice for everyone.
|
||||||
|
%%
|
||||||
%% TODO: Perhaps that quickest author should consult all of the
|
%% TODO: Perhaps that quickest author should consult all of the
|
||||||
%% other private stores, check their inner, and if there is a
|
%% other private stores, check their inner, and if there is a
|
||||||
%% higher rank there, then goto C200 for a wait-and-see cycle?
|
%% higher rank there, then goto C200 for a wait-and-see cycle?
|
||||||
|
%% TODO: 2015-07-04 The suggestion in TODO above appears very good.
|
||||||
|
%% Also, at least some of the time, MyName is included
|
||||||
|
%% in the down list, quite odd! Go investigate that.
|
||||||
|
|
||||||
P_inner2A = inner_projection_or_self(P_current),
|
P_inner2A = inner_projection_or_self(P_current),
|
||||||
P_inner2B =
|
P_inner2B =
|
||||||
|
@ -1337,37 +1341,13 @@ react_to_env_C100(P_newprop, P_latest,
|
||||||
I_am_UPI_in_newprop_p = lists:member(MyName, P_newprop#projection_v1.upi),
|
I_am_UPI_in_newprop_p = lists:member(MyName, P_newprop#projection_v1.upi),
|
||||||
I_am_Repairing_in_latest_p = lists:member(MyName,
|
I_am_Repairing_in_latest_p = lists:member(MyName,
|
||||||
P_latest#projection_v1.repairing),
|
P_latest#projection_v1.repairing),
|
||||||
Sane_p = fun(X, Y) ->
|
Sane = projection_transition_is_sane(P_current, P_latest, MyName),
|
||||||
case projection_transition_is_sane(X, Y, MyName) of
|
|
||||||
true -> true;
|
|
||||||
_ -> false
|
|
||||||
end end,
|
|
||||||
Current_sane_p = Sane_p(P_current, P_latest),
|
|
||||||
%% Inner = fun(P) -> case inner_projection_exists(P) of true -> t;
|
|
||||||
%% false -> f
|
|
||||||
%% end end,
|
|
||||||
%% io:format(user, "~w:~w.~w,", [MyName, Inner(P_current), Inner(P_latest)]), timer:sleep(50),
|
|
||||||
Inner_sane_p =
|
|
||||||
case inner_projection_exists(P_current)
|
|
||||||
andalso
|
|
||||||
inner_projection_exists(P_latest) of
|
|
||||||
true ->
|
|
||||||
P_currentIx = inner_projection_or_self(P_current),
|
|
||||||
P_currentIxE = P_currentIx#projection_v1.epoch_number,
|
|
||||||
P_currentI = P_currentIx#projection_v1{epoch_number=P_currentIxE-1},
|
|
||||||
P_latestI = inner_projection_or_self(P_latest),
|
|
||||||
io:format(user, "i=~w>?i=~w,", [P_currentI#projection_v1.epoch_number, P_latestI#projection_v1.epoch_number]),
|
|
||||||
Sane_p(P_currentI, P_latestI);
|
|
||||||
false ->
|
|
||||||
true
|
|
||||||
end,
|
|
||||||
put(xxx_hack, [{p_current, machi_projection:make_summary(P_current)},
|
put(xxx_hack, [{p_current, machi_projection:make_summary(P_current)},
|
||||||
{epoch_compare, P_latest#projection_v1.epoch_number > P_current#projection_v1.epoch_number},
|
{epoch_compare, P_latest#projection_v1.epoch_number > P_current#projection_v1.epoch_number},
|
||||||
{i_am_upi_in_newprop_p, I_am_UPI_in_newprop_p},
|
{i_am_upi_in_newprop_p, I_am_UPI_in_newprop_p},
|
||||||
{i_am_repairing_in_latest_p, I_am_Repairing_in_latest_p},
|
{i_am_repairing_in_latest_p, I_am_Repairing_in_latest_p},
|
||||||
{current_sane_p, Current_sane_p},
|
{sane_p, Sane}]),
|
||||||
{inner_sane_p, Inner_sane_p}]),
|
case Sane of
|
||||||
case Current_sane_p andalso Inner_sane_p of
|
|
||||||
_ when P_current#projection_v1.epoch_number == 0 ->
|
_ when P_current#projection_v1.epoch_number == 0 ->
|
||||||
%% Epoch == 0 is reserved for first-time, just booting conditions.
|
%% Epoch == 0 is reserved for first-time, just booting conditions.
|
||||||
?REACT({c100, ?LINE, [first_write]}),
|
?REACT({c100, ?LINE, [first_write]}),
|
||||||
|
@ -1643,27 +1623,51 @@ projection_transitions_are_sane([P1, P2|T], RelativeToServer, RetrospectiveP) ->
|
||||||
Else
|
Else
|
||||||
end.
|
end.
|
||||||
|
|
||||||
projection_transition_is_sane(P1, P2, RelativeToServer) ->
|
|
||||||
projection_transition_is_sane(P1, P2, RelativeToServer, false).
|
|
||||||
|
|
||||||
-ifdef(TEST).
|
-ifdef(TEST).
|
||||||
projection_transition_is_sane_retrospective(P1, P2, RelativeToServer) ->
|
projection_transition_is_sane_retrospective(P1, P2, RelativeToServer) ->
|
||||||
projection_transition_is_sane(P1, P2, RelativeToServer, true).
|
projection_transition_is_sane(P1, P2, RelativeToServer, true).
|
||||||
-endif. % TEST
|
-endif. % TEST
|
||||||
|
|
||||||
projection_transition_is_sane(
|
projection_transition_is_sane(P1, P2, RelativeToServer) ->
|
||||||
|
projection_transition_is_sane(P1, P2, RelativeToServer, false).
|
||||||
|
|
||||||
|
projection_transition_is_sane(P1, P2, RelativeToServer, RetrospectiveP) ->
|
||||||
|
case projection_transition_is_sane_with_si_epoch(
|
||||||
|
P1, P2, RelativeToServer, RetrospectiveP) of
|
||||||
|
true ->
|
||||||
|
HasInner1 = inner_projection_exists(P1),
|
||||||
|
HasInner2 = inner_projection_exists(P2),
|
||||||
|
if HasInner1 orelse HasInner2 ->
|
||||||
|
Inner1 = inner_projection_or_self(P1),
|
||||||
|
Inner2 = inner_projection_or_self(P2),
|
||||||
|
if HasInner1 andalso HasInner2 ->
|
||||||
|
projection_transition_is_sane_except_si_epoch(
|
||||||
|
Inner1, Inner2, RelativeToServer, RetrospectiveP);
|
||||||
|
true ->
|
||||||
|
projection_transition_is_sane_with_si_epoch(
|
||||||
|
Inner1, Inner2, RelativeToServer, RetrospectiveP)
|
||||||
|
end;
|
||||||
|
true ->
|
||||||
|
true
|
||||||
|
end;
|
||||||
|
Else ->
|
||||||
|
Else
|
||||||
|
end.
|
||||||
|
|
||||||
|
projection_transition_is_sane_with_si_epoch(
|
||||||
#projection_v1{epoch_number=Epoch1} = P1,
|
#projection_v1{epoch_number=Epoch1} = P1,
|
||||||
#projection_v1{epoch_number=Epoch2} = P2,
|
#projection_v1{epoch_number=Epoch2} = P2,
|
||||||
RelativeToServer, RetrospectiveP) ->
|
RelativeToServer, RetrospectiveP) ->
|
||||||
case projection_transition_is_sane_except_epoch(
|
case projection_transition_is_sane_except_si_epoch(
|
||||||
P1, P2, RelativeToServer, RetrospectiveP) of
|
P1, P2, RelativeToServer, RetrospectiveP) of
|
||||||
true ->
|
true ->
|
||||||
|
%% Must be a strictly increasing epoch.
|
||||||
Epoch2 > Epoch1;
|
Epoch2 > Epoch1;
|
||||||
Else ->
|
Else ->
|
||||||
Else
|
Else
|
||||||
end.
|
end.
|
||||||
|
|
||||||
projection_transition_is_sane_except_epoch(
|
projection_transition_is_sane_except_si_epoch(
|
||||||
#projection_v1{epoch_number=Epoch1,
|
#projection_v1{epoch_number=Epoch1,
|
||||||
epoch_csum=CSum1,
|
epoch_csum=CSum1,
|
||||||
creation_time=CreationTime1,
|
creation_time=CreationTime1,
|
||||||
|
@ -1702,7 +1706,9 @@ projection_transition_is_sane_except_epoch(
|
||||||
true = is_list(Repairing_list1) andalso is_list(Repairing_list2),
|
true = is_list(Repairing_list1) andalso is_list(Repairing_list2),
|
||||||
true = is_list(Dbg1) andalso is_list(Dbg2),
|
true = is_list(Dbg1) andalso is_list(Dbg2),
|
||||||
|
|
||||||
All_list1 = All_list2, % todo will probably change
|
%% Don't check for strictly increasing epoch here: that's the job of
|
||||||
|
%% projection_transition_is_sane_with_si_epoch().
|
||||||
|
true = Epoch2 >= Epoch1,
|
||||||
|
|
||||||
%% No duplicates
|
%% No duplicates
|
||||||
true = lists:sort(Down_list2) == lists:usort(Down_list2),
|
true = lists:sort(Down_list2) == lists:usort(Down_list2),
|
||||||
|
@ -1710,6 +1716,7 @@ projection_transition_is_sane_except_epoch(
|
||||||
true = lists:sort(Repairing_list2) == lists:usort(Repairing_list2),
|
true = lists:sort(Repairing_list2) == lists:usort(Repairing_list2),
|
||||||
|
|
||||||
%% Disjoint-ness
|
%% Disjoint-ness
|
||||||
|
All_list1 = All_list2, % todo will probably change
|
||||||
true = lists:sort(All_list2) == lists:sort(Down_list2 ++ UPI_list2 ++
|
true = lists:sort(All_list2) == lists:sort(Down_list2 ++ UPI_list2 ++
|
||||||
Repairing_list2),
|
Repairing_list2),
|
||||||
[] = [X || X <- Down_list2, not lists:member(X, All_list2)],
|
[] = [X || X <- Down_list2, not lists:member(X, All_list2)],
|
||||||
|
@ -2012,12 +2019,14 @@ chain_state_transition_is_sane(Author1, UPI1, Repair1, Author2, UPI2) ->
|
||||||
%% the judgement of simple_chain_state_transition_is_sane().
|
%% the judgement of simple_chain_state_transition_is_sane().
|
||||||
if ToSelfOnly_p ->
|
if ToSelfOnly_p ->
|
||||||
%% The transition is to UPI2=[Author2].
|
%% The transition is to UPI2=[Author2].
|
||||||
%% For AP mode, this transition is always safe.
|
%% For AP mode, this transition is always safe (though not
|
||||||
|
%% always optimal for highest availability).
|
||||||
?RETURN2(true);
|
?RETURN2(true);
|
||||||
Disjoint_UPIs ->
|
Disjoint_UPIs ->
|
||||||
%% The transition from UPI1 -> UPI2 where the two are
|
%% The transition from UPI1 -> UPI2 where the two are
|
||||||
%% disjoint/no FLUs in common.
|
%% disjoint/no FLUs in common.
|
||||||
%% For AP mode, this transition is always safe.
|
%% For AP mode, this transition is always safe (though not
|
||||||
|
%% always optimal for highest availability).
|
||||||
?RETURN2(true);
|
?RETURN2(true);
|
||||||
true ->
|
true ->
|
||||||
simple_chain_state_transition_is_sane(Author1, UPI1, Repair1,
|
simple_chain_state_transition_is_sane(Author1, UPI1, Repair1,
|
||||||
|
|
|
@ -150,7 +150,7 @@ make_summary(#projection_v1{epoch_number=EpochNum,
|
||||||
dbg=Dbg, dbg2=Dbg2}) ->
|
dbg=Dbg, dbg2=Dbg2}) ->
|
||||||
[{epoch,EpochNum},{author,Author},
|
[{epoch,EpochNum},{author,Author},
|
||||||
{upi,UPI_list},{repair,Repairing_list},{down,Down_list},
|
{upi,UPI_list},{repair,Repairing_list},{down,Down_list},
|
||||||
{d,Dbg}, {d2,Dbg2}, {csum4, _CSum4}].
|
{d,Dbg}, {d2,Dbg2}].
|
||||||
|
|
||||||
%% @doc Make a `p_srvr_dict()' out of a list of `p_srvr()' or out of a
|
%% @doc Make a `p_srvr_dict()' out of a list of `p_srvr()' or out of a
|
||||||
%% `p_srvr_dict()'.
|
%% `p_srvr_dict()'.
|
||||||
|
|
Loading…
Reference in a new issue