WIP: rewrite make_zerf() to use new annotation scheme
This commit is contained in:
parent
28335a1310
commit
8a61a85ae0
1 changed files with 74 additions and 93 deletions
|
@ -3083,7 +3083,8 @@ full_majority_size(L) when is_list(L) ->
|
||||||
make_zerf(#projection_v1{epoch_number=OldEpochNum,
|
make_zerf(#projection_v1{epoch_number=OldEpochNum,
|
||||||
all_members=AllMembers,
|
all_members=AllMembers,
|
||||||
members_dict=MembersDict,
|
members_dict=MembersDict,
|
||||||
witnesses=OldWitness_list
|
witnesses=OldWitness_list,
|
||||||
|
flap=OldFlap
|
||||||
} = _LastProj,
|
} = _LastProj,
|
||||||
#ch_mgr{name=MyName,
|
#ch_mgr{name=MyName,
|
||||||
consistency_mode=cp_mode,
|
consistency_mode=cp_mode,
|
||||||
|
@ -3096,108 +3097,88 @@ make_zerf(#projection_v1{epoch_number=OldEpochNum,
|
||||||
throw({zerf, {not_enough_up, Up, AllMembers}});
|
throw({zerf, {not_enough_up, Up, AllMembers}});
|
||||||
true ->
|
true ->
|
||||||
make_zerf2(OldEpochNum, Up, MajoritySize, MyName,
|
make_zerf2(OldEpochNum, Up, MajoritySize, MyName,
|
||||||
AllMembers, OldWitness_list, MembersDict, S)
|
AllMembers, OldWitness_list, MembersDict, OldFlap, S)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
make_zerf2(OldEpochNum, Up, MajoritySize, MyName, AllMembers, OldWitness_list, MembersDict, S) ->
|
make_zerf2(OldEpochNum, Up, MajoritySize, MyName, AllMembers, OldWitness_list,
|
||||||
|
MembersDict, OldFlap, S) ->
|
||||||
try
|
try
|
||||||
Epochs = lists:reverse(
|
Proj = zerf_find_last_common(MajoritySize, Up, S),
|
||||||
lists:usort(
|
Proj2 =
|
||||||
lists:flatten(
|
Proj#projection_v1{flap=OldFlap}
|
||||||
[begin
|
, io:format(user, "ZERF ~w\n", [machi_projection:make_summary(Proj2)]),
|
||||||
Proxy = proxy_pid(FLU, S),
|
Proj2
|
||||||
{ok, Es} = ?FLU_PC:list_all_projections(
|
|
||||||
Proxy, private, ?TO*5),
|
|
||||||
[E || E <- Es]
|
|
||||||
end || FLU <- Up]))),
|
|
||||||
put(epochs, Epochs),
|
|
||||||
Relation = [],
|
|
||||||
Proj = zerf_find_last_common(Epochs, Relation, MajoritySize, Up, S),
|
|
||||||
Proj#projection_v1{flap=make_flapping_i()}
|
|
||||||
catch
|
catch
|
||||||
throw:{zerf,no_common} ->
|
throw:{zerf,no_common} ->
|
||||||
FirstEpoch_p = case get(epochs) of
|
%% Epoch 0 special case: make the "all" projection.
|
||||||
[0] -> true;
|
%% calc_projection2() will then filter out any FLUs that
|
||||||
[_, 0] -> true;
|
%% aren't currently up to create the first chain. If not
|
||||||
_ -> false
|
%% enough are up now, then it will fail to create a first
|
||||||
end,
|
%% chain.
|
||||||
if FirstEpoch_p ->
|
%%
|
||||||
%% Epoch 0 special case: make the "all" projection.
|
%% If epoch 0 isn't the only epoch that we've looked at,
|
||||||
%% calc_projection2() will then filter out any FLUs that
|
%% but we still couldn't find a common projection, then
|
||||||
%% aren't currently up to create the first chain. If not
|
%% we still need to default to the "all" projection and let
|
||||||
%% enough are up now, then it will fail to create a first
|
%% subsequent chain calculations do their calculations....
|
||||||
%% chain.
|
P = make_all_projection(MyName, AllMembers, OldWitness_list,
|
||||||
%%
|
MembersDict),
|
||||||
%% If epoch 0 isn't the only epoch that we've looked at,
|
P2 =
|
||||||
%% but we still couldn't find a common projection, then
|
machi_projection:update_checksum(
|
||||||
%% we still need to default to the "all" projection and let
|
P#projection_v1{epoch_number=OldEpochNum,
|
||||||
%% subsequent chain calculations do their calculations....
|
mode=cp_mode,
|
||||||
P = make_all_projection(MyName, AllMembers, OldWitness_list,
|
dbg2=[zerf_all]}),
|
||||||
MembersDict),
|
io:format(user, "ZERF ~w\n", [machi_projection:make_summary(P2)]),
|
||||||
machi_projection:update_checksum(
|
P2;
|
||||||
P#projection_v1{epoch_number=OldEpochNum,
|
|
||||||
mode=cp_mode,
|
|
||||||
dbg2=[zerf_all]});
|
|
||||||
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,
|
|
||||||
mode=cp_mode,
|
|
||||||
dbg2=[zerf_none, {es, get(epochs)},{up,Up},{maj,MajoritySize}]})
|
|
||||||
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(MajoritySize, Up, S) ->
|
||||||
throw({zerf, no_common});
|
case lists:reverse(
|
||||||
zerf_find_last_common(UnsearchedEpochs, Relation, MajoritySize, Up, S) ->
|
lists:sort(
|
||||||
{NowEpochs, NextEpochs} = my_lists_split(5, UnsearchedEpochs),
|
lists:flatten(
|
||||||
Rel2 = lists:foldl(
|
[zerf_find_last_annotated(FLU,MajoritySize,S) || FLU <- Up]))) of
|
||||||
fun({E, FLU}, Rel) ->
|
|
||||||
Proxy = proxy_pid(FLU, S),
|
|
||||||
case (catch ?FLU_PC:read_projection(Proxy, private,
|
|
||||||
E, ?TO)) of
|
|
||||||
{ok, Proj} ->
|
|
||||||
%% Sort order: we want inner = bigger.
|
|
||||||
CSum = Proj#projection_v1.epoch_csum,
|
|
||||||
OorI = case inner_projection_exists(Proj) of
|
|
||||||
true -> z_inner;
|
|
||||||
false -> a_outer
|
|
||||||
end,
|
|
||||||
K = {E, CSum, OorI, Proj#projection_v1{dbg2=[]}},
|
|
||||||
Rel2 = case lists:keyfind(K, 1, Rel) of
|
|
||||||
false ->
|
|
||||||
[{K, [FLU]}|Rel];
|
|
||||||
{K, OldV} ->
|
|
||||||
NewV = lists:usort([FLU|OldV]),
|
|
||||||
NewT = {K, NewV},
|
|
||||||
lists:keyreplace(K, 1, Rel,
|
|
||||||
NewT)
|
|
||||||
end,
|
|
||||||
Rel2;
|
|
||||||
_ ->
|
|
||||||
Rel
|
|
||||||
end
|
|
||||||
end, Relation, lists:reverse([{E, FLU} || E <- NowEpochs, FLU <- Up])),
|
|
||||||
SortedRel = lists:reverse(lists:sort(Rel2)),
|
|
||||||
case [T || T={{_E, _CSum, _OorI, Proj}, WrittenFLUs} <- SortedRel,
|
|
||||||
ordsets:is_subset(ordsets:from_list(Proj#projection_v1.upi),
|
|
||||||
ordsets:from_list(WrittenFLUs))
|
|
||||||
andalso
|
|
||||||
length(Proj#projection_v1.upi) >= MajoritySize] of
|
|
||||||
[] ->
|
[] ->
|
||||||
zerf_find_last_common(NextEpochs, Rel2, MajoritySize, Up, S);
|
throw({zerf,no_common});
|
||||||
[{{_E, _CSum, _OorI, Proj}, _WrittenFLUs}|_] ->
|
[P|_] ->
|
||||||
Proj
|
%% TODO is this simple sort really good enough?
|
||||||
|
P
|
||||||
|
end.
|
||||||
|
|
||||||
|
zerf_find_last_annotated(FLU, MajoritySize, S) ->
|
||||||
|
Proxy = proxy_pid(FLU, S),
|
||||||
|
{ok, Epochs} = ?FLU_PC:list_all_projections(Proxy, private, 60*1000),
|
||||||
|
P = lists:foldl(
|
||||||
|
fun(Epoch, #projection_v1{}=Proj) ->
|
||||||
|
Proj;
|
||||||
|
(Epoch, Acc) ->
|
||||||
|
{ok, Proj} = ?FLU_PC:read_projection(Proxy, private,
|
||||||
|
Epoch, ?TO*10),
|
||||||
|
case proplists:get_value(private_proj_is_upi_unanimous,
|
||||||
|
Proj#projection_v1.dbg2) of
|
||||||
|
undefined ->
|
||||||
|
Acc;
|
||||||
|
{{ConfEpoch, ConfCSum}, _ConfTime} ->
|
||||||
|
Px = if ConfEpoch == Epoch ->
|
||||||
|
Proj;
|
||||||
|
true ->
|
||||||
|
Proj2 = inner_projection_or_self(Proj),
|
||||||
|
%% Sanity checking
|
||||||
|
ConfEpoch = Proj2#projection_v1.epoch_number,
|
||||||
|
ConfCSum = Proj2#projection_v1.epoch_csum,
|
||||||
|
Proj2
|
||||||
|
end,
|
||||||
|
if length(Px#projection_v1.upi) >= MajoritySize ->
|
||||||
|
Px;
|
||||||
|
true ->
|
||||||
|
Acc
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, first_accumulator, Epochs),
|
||||||
|
if is_record(P, projection_v1) ->
|
||||||
|
P;
|
||||||
|
true ->
|
||||||
|
[] % lists:flatten() will destroy
|
||||||
end.
|
end.
|
||||||
|
|
||||||
my_lists_split(N, L) ->
|
my_lists_split(N, L) ->
|
||||||
|
|
Loading…
Reference in a new issue