WIP: it's ugly, but CP+witnesses is mostly working?
This commit is contained in:
parent
4e66d7bd91
commit
5aff775383
1 changed files with 58 additions and 24 deletions
|
@ -102,6 +102,9 @@
|
||||||
%% This rank is used if a majority quorum is not available.
|
%% This rank is used if a majority quorum is not available.
|
||||||
-define(RANK_CP_MINORITY_QUORUM, -99).
|
-define(RANK_CP_MINORITY_QUORUM, -99).
|
||||||
|
|
||||||
|
%% Amount of epoch number skip-ahead for set_chain_members call
|
||||||
|
-define(SET_CHAIN_MEMBERS_EPOCH_SKIP, 1111).
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([start_link/2, start_link/3, stop/1, ping/1,
|
-export([start_link/2, start_link/3, stop/1, ping/1,
|
||||||
set_chain_members/2, set_chain_members/3, set_active/2,
|
set_chain_members/2, set_chain_members/3, set_active/2,
|
||||||
|
@ -290,7 +293,7 @@ handle_call({set_chain_members, MembersDict, Witness_list}, _From,
|
||||||
MissingInNew = OldAll_list -- All_list,
|
MissingInNew = OldAll_list -- All_list,
|
||||||
NewUPI = OldUPI -- MissingInNew,
|
NewUPI = OldUPI -- MissingInNew,
|
||||||
NewDown = All_list -- NewUPI,
|
NewDown = All_list -- NewUPI,
|
||||||
NewEpoch = OldEpoch + 1111,
|
NewEpoch = OldEpoch + ?SET_CHAIN_MEMBERS_EPOCH_SKIP,
|
||||||
CMode = if Witness_list == [] ->
|
CMode = if Witness_list == [] ->
|
||||||
ap_mode;
|
ap_mode;
|
||||||
Witness_list /= [] ->
|
Witness_list /= [] ->
|
||||||
|
@ -691,7 +694,7 @@ calc_projection2(LastProj, RelativeToServer, AllHosed, Dbg,
|
||||||
{NewUPI_list3, Repairing_list3, RunEnv3} =
|
{NewUPI_list3, Repairing_list3, RunEnv3} =
|
||||||
case {NewUp, Repairing_list2} of
|
case {NewUp, Repairing_list2} of
|
||||||
{[], []} ->
|
{[], []} ->
|
||||||
D_foo=[],
|
D_foo=[d_foo1],
|
||||||
{NewUPI_list, [], RunEnv2};
|
{NewUPI_list, [], RunEnv2};
|
||||||
{[], [H|T]} when RelativeToServer == LastInNewUPI ->
|
{[], [H|T]} when RelativeToServer == LastInNewUPI ->
|
||||||
%% The author is tail of the UPI list. Let's see if
|
%% The author is tail of the UPI list. Let's see if
|
||||||
|
@ -706,6 +709,7 @@ calc_projection2(LastProj, RelativeToServer, AllHosed, Dbg,
|
||||||
S#ch_mgr.proj, Partitions, S),
|
S#ch_mgr.proj, Partitions, S),
|
||||||
if Simulator_p andalso SimRepair_p andalso
|
if Simulator_p andalso SimRepair_p andalso
|
||||||
SameEpoch_p andalso RelativeToServer == LastInCurrentUPI ->
|
SameEpoch_p andalso RelativeToServer == LastInCurrentUPI ->
|
||||||
|
io:format(user, "CONFIRM ~p repair done during epoch ~p of ~p, obnoxious mostly-race-avoiding sleep now...\n", [MyName, OldEpochNum, H]), timer:sleep(543),
|
||||||
D_foo=[{repair_airquote_done, {we_agree, (S#ch_mgr.proj)#projection_v1.epoch_number}}],
|
D_foo=[{repair_airquote_done, {we_agree, (S#ch_mgr.proj)#projection_v1.epoch_number}}],
|
||||||
{NewUPI_list ++ [H], T, RunEnv2};
|
{NewUPI_list ++ [H], T, RunEnv2};
|
||||||
not (Simulator_p andalso SimRepair_p)
|
not (Simulator_p andalso SimRepair_p)
|
||||||
|
@ -714,13 +718,15 @@ calc_projection2(LastProj, RelativeToServer, AllHosed, Dbg,
|
||||||
D_foo=[{repair_done, {repair_final_status, ok, (S#ch_mgr.proj)#projection_v1.epoch_number}}],
|
D_foo=[{repair_done, {repair_final_status, ok, (S#ch_mgr.proj)#projection_v1.epoch_number}}],
|
||||||
{NewUPI_list ++ Repairing_list2, [], RunEnv2};
|
{NewUPI_list ++ Repairing_list2, [], RunEnv2};
|
||||||
true ->
|
true ->
|
||||||
D_foo=[],
|
D_foo=[d_foo2],
|
||||||
{NewUPI_list, OldRepairing_list, RunEnv2}
|
{NewUPI_list, OldRepairing_list, RunEnv2}
|
||||||
end;
|
end;
|
||||||
{_, _} ->
|
{_, _} ->
|
||||||
D_foo=[],
|
D_foo=[d_foo3, {new_upi_list, NewUPI_list}, {new_up, NewUp}, {repairing_list3, OldRepairing_list}],
|
||||||
{NewUPI_list, OldRepairing_list, RunEnv2}
|
{NewUPI_list, OldRepairing_list, RunEnv2}
|
||||||
end,
|
end,
|
||||||
|
?REACT({calc,?LINE,
|
||||||
|
[{newupi_list3, NewUPI_list3},{repairing_list3, Repairing_list3}]}),
|
||||||
Repairing_list4 = case NewUp of
|
Repairing_list4 = case NewUp of
|
||||||
[] -> Repairing_list3;
|
[] -> Repairing_list3;
|
||||||
NewUp -> Repairing_list3 ++ NewUp
|
NewUp -> Repairing_list3 ++ NewUp
|
||||||
|
@ -729,9 +735,14 @@ calc_projection2(LastProj, RelativeToServer, AllHosed, Dbg,
|
||||||
|
|
||||||
TentativeUPI = NewUPI_list3,
|
TentativeUPI = NewUPI_list3,
|
||||||
TentativeRepairing = Repairing_list5,
|
TentativeRepairing = Repairing_list5,
|
||||||
|
?REACT({calc,?LINE,[{tent, TentativeUPI},{tent_rep, TentativeRepairing}]}),
|
||||||
|
|
||||||
{NewUPI, NewRepairing} =
|
{NewUPI, NewRepairing} =
|
||||||
if TentativeUPI == [] andalso TentativeRepairing /= [] ->
|
if (CMode == ap_mode
|
||||||
|
orelse
|
||||||
|
(CMode == cp_mode andalso OldEpochNum == 0))
|
||||||
|
andalso
|
||||||
|
TentativeUPI == [] andalso TentativeRepairing /= [] ->
|
||||||
%% UPI is empty (not including witnesses), so grab
|
%% UPI is empty (not including witnesses), so grab
|
||||||
%% the first from the repairing list and make it the
|
%% the first from the repairing list and make it the
|
||||||
%% only non-witness in the UPI.
|
%% only non-witness in the UPI.
|
||||||
|
@ -740,6 +751,7 @@ calc_projection2(LastProj, RelativeToServer, AllHosed, Dbg,
|
||||||
true ->
|
true ->
|
||||||
{TentativeUPI, TentativeRepairing}
|
{TentativeUPI, TentativeRepairing}
|
||||||
end,
|
end,
|
||||||
|
?REACT({calc,?LINE,[{new_upi, NewUPI},{new_rep, NewRepairing}]}),
|
||||||
|
|
||||||
P = machi_projection:new(OldEpochNum + 1,
|
P = machi_projection:new(OldEpochNum + 1,
|
||||||
MyName, MembersDict, Down, NewUPI, NewRepairing,
|
MyName, MembersDict, Down, NewUPI, NewRepairing,
|
||||||
|
@ -751,6 +763,7 @@ calc_projection2(LastProj, RelativeToServer, AllHosed, Dbg,
|
||||||
Majority = full_majority_size(AllMembers),
|
Majority = full_majority_size(AllMembers),
|
||||||
SoFar = length(NewUPI),
|
SoFar = length(NewUPI),
|
||||||
if SoFar >= Majority ->
|
if SoFar >= Majority ->
|
||||||
|
?REACT({calc,?LINE,[]}),
|
||||||
P;
|
P;
|
||||||
true ->
|
true ->
|
||||||
Need = Majority - SoFar,
|
Need = Majority - SoFar,
|
||||||
|
@ -758,15 +771,18 @@ calc_projection2(LastProj, RelativeToServer, AllHosed, Dbg,
|
||||||
lists:member(W, OldWitness_list)],
|
lists:member(W, OldWitness_list)],
|
||||||
if length(UpWitnesses) >= Need ->
|
if length(UpWitnesses) >= Need ->
|
||||||
Ws = lists:sublist(UpWitnesses, Need),
|
Ws = lists:sublist(UpWitnesses, Need),
|
||||||
|
?REACT({calc,?LINE,[{ws, Ws}]}),
|
||||||
machi_projection:update_checksum(
|
machi_projection:update_checksum(
|
||||||
P#projection_v1{upi=Ws++NewUPI});
|
P#projection_v1{upi=Ws++NewUPI});
|
||||||
true ->
|
true ->
|
||||||
|
?REACT({calc,?LINE,[]}),
|
||||||
P_none0 = make_none_projection(
|
P_none0 = make_none_projection(
|
||||||
MyName, AllMembers, OldWitness_list,
|
MyName, AllMembers, OldWitness_list,
|
||||||
MembersDict),
|
MembersDict),
|
||||||
P_none1 = P_none0#projection_v1{
|
P_none1 = P_none0#projection_v1{
|
||||||
epoch_number=OldEpochNum + 1,
|
epoch_number=OldEpochNum + 1,
|
||||||
dbg=[{none_projection,true},
|
dbg=[{none_projection,true},
|
||||||
|
{up0, Up0},
|
||||||
{up, Up},
|
{up, Up},
|
||||||
{all_hosed, AllHosed},
|
{all_hosed, AllHosed},
|
||||||
{not_enough_witnesses,true}]},
|
{not_enough_witnesses,true}]},
|
||||||
|
@ -774,10 +790,12 @@ calc_projection2(LastProj, RelativeToServer, AllHosed, Dbg,
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
CMode == ap_mode ->
|
CMode == ap_mode ->
|
||||||
|
?REACT({calc,?LINE,[]}),
|
||||||
P
|
P
|
||||||
end,
|
end,
|
||||||
P3 = machi_projection:update_checksum(
|
P3 = machi_projection:update_checksum(
|
||||||
P2#projection_v1{mode=CMode, witnesses=OldWitness_list}),
|
P2#projection_v1{mode=CMode, witnesses=OldWitness_list}),
|
||||||
|
?REACT({xxx,?LINE,[machi_projection:make_summary(P3)]}),
|
||||||
{P3, S#ch_mgr{runenv=RunEnv3}, Up}.
|
{P3, S#ch_mgr{runenv=RunEnv3}, Up}.
|
||||||
|
|
||||||
check_latest_private_projections_same_epoch(FLUs, MyProj, Partitions, S) ->
|
check_latest_private_projections_same_epoch(FLUs, MyProj, Partitions, S) ->
|
||||||
|
@ -2647,10 +2665,18 @@ make_zerf2(OldEpochNum, Up, MajoritySize, MyName, AllMembers, OldWitness_list, M
|
||||||
Proxy, private, ?TO*5),
|
Proxy, private, ?TO*5),
|
||||||
[E || E <- Es]
|
[E || E <- Es]
|
||||||
end || FLU <- Up]))),
|
end || FLU <- Up]))),
|
||||||
|
put(epochs, Epochs),
|
||||||
Relation = [],
|
Relation = [],
|
||||||
|
put(xxx_epoch, OldEpochNum),
|
||||||
zerf_find_last_common(Epochs, Relation, MajoritySize, Up, S)
|
zerf_find_last_common(Epochs, Relation, MajoritySize, Up, S)
|
||||||
catch
|
catch
|
||||||
throw:{zerf,no_common} ->
|
throw:{zerf,no_common} ->
|
||||||
|
FirstEpoch_p = case get(epochs) of
|
||||||
|
[0] -> true;
|
||||||
|
[?SET_CHAIN_MEMBERS_EPOCH_SKIP, 0] -> true;
|
||||||
|
_ -> false
|
||||||
|
end,
|
||||||
|
if FirstEpoch_p ->
|
||||||
%% Epoch 0 special case: make the "all" projection.
|
%% Epoch 0 special case: make the "all" projection.
|
||||||
%% calc_projection2() will then filter out any FLUs that
|
%% calc_projection2() will then filter out any FLUs that
|
||||||
%% aren't currently up to create the first chain. If not
|
%% aren't currently up to create the first chain. If not
|
||||||
|
@ -2665,21 +2691,31 @@ make_zerf2(OldEpochNum, Up, MajoritySize, MyName, AllMembers, OldWitness_list, M
|
||||||
MembersDict),
|
MembersDict),
|
||||||
machi_projection:update_checksum(
|
machi_projection:update_checksum(
|
||||||
P#projection_v1{epoch_number=OldEpochNum});
|
P#projection_v1{epoch_number=OldEpochNum});
|
||||||
|
true ->
|
||||||
|
%% Make it appear like nobody is up now: we'll have to
|
||||||
|
%% wait until the Up list changes so that
|
||||||
|
%% zerf_find_last_common() can confirm a common stable
|
||||||
|
%% last stable epoch.
|
||||||
|
P = make_none_projection(MyName, AllMembers,OldWitness_list,
|
||||||
|
MembersDict),
|
||||||
|
machi_projection:update_checksum(
|
||||||
|
P#projection_v1{epoch_number=OldEpochNum})
|
||||||
|
end;
|
||||||
_X:_Y ->
|
_X:_Y ->
|
||||||
throw({zerf, {damn_exception, Up, _X, _Y, erlang:get_stacktrace()}})
|
throw({zerf, {damn_exception, Up, _X, _Y, erlang:get_stacktrace()}})
|
||||||
|
after
|
||||||
|
erase(epochs)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
zerf_find_last_common([], _Relation, _MajoritySize, _Up, _S) ->
|
zerf_find_last_common([], _Relation, _MajoritySize, _Up, _S) ->
|
||||||
throw({zerf, no_common});
|
throw({zerf, no_common});
|
||||||
zerf_find_last_common(UnsearchedEpochs, Relation, MajoritySize, Up, S) ->
|
zerf_find_last_common(UnsearchedEpochs, Relation, MajoritySize, Up, S) ->
|
||||||
{NowEpochs, NextEpochs} = my_lists_split(5, UnsearchedEpochs),
|
{NowEpochs, NextEpochs} = my_lists_split(5, UnsearchedEpochs),
|
||||||
%%io:format(user, "zerf_find_last_common now_es ~p\n", [NowEpochs]),
|
|
||||||
Rel2 = lists:foldl(
|
Rel2 = lists:foldl(
|
||||||
fun({E, FLU}, Rel) ->
|
fun({E, FLU}, Rel) ->
|
||||||
Proxy = proxy_pid(FLU, S),
|
Proxy = proxy_pid(FLU, S),
|
||||||
case ?FLU_PC:read_projection(Proxy, private, E, ?TO) of
|
case ?FLU_PC:read_projection(Proxy, private, E, ?TO) of
|
||||||
{ok, Proj} ->
|
{ok, Proj} ->
|
||||||
%%io:format(user, "fold ~p ~p ok\n", [E, FLU]),
|
|
||||||
%% Sort order: we want inner = bigger.
|
%% Sort order: we want inner = bigger.
|
||||||
OorI = case inner_projection_exists(Proj) of
|
OorI = case inner_projection_exists(Proj) of
|
||||||
true -> z_inner;
|
true -> z_inner;
|
||||||
|
@ -2697,12 +2733,10 @@ zerf_find_last_common(UnsearchedEpochs, Relation, MajoritySize, Up, S) ->
|
||||||
end,
|
end,
|
||||||
Rel2;
|
Rel2;
|
||||||
{error, not_written} ->
|
{error, not_written} ->
|
||||||
%%io:format(user, "fold ~p ~p not_written\n", [E, FLU]),
|
|
||||||
Rel
|
Rel
|
||||||
end
|
end
|
||||||
end, Relation, [{E, FLU} || E <- NowEpochs, FLU <- Up]),
|
end, Relation, lists:reverse([{E, FLU} || E <- NowEpochs, FLU <- Up])),
|
||||||
SortedRel = lists:reverse(lists:sort(Rel2)),
|
SortedRel = lists:reverse(lists:sort(Rel2)),
|
||||||
%%io:format(user, "zerf_find_last_common rel ~p\n", [SortedRel]),
|
|
||||||
case [T || T={{E, OorI, Proj}, WrittenFLUs} <- SortedRel,
|
case [T || T={{E, OorI, Proj}, WrittenFLUs} <- SortedRel,
|
||||||
lists:sort(Proj#projection_v1.upi) == lists:sort(WrittenFLUs)
|
lists:sort(Proj#projection_v1.upi) == lists:sort(WrittenFLUs)
|
||||||
andalso
|
andalso
|
||||||
|
|
Loading…
Reference in a new issue