Fix witness calculation projections, part I
This commit is contained in:
parent
91496c656b
commit
f43a5ca96d
1 changed files with 55 additions and 56 deletions
|
@ -325,7 +325,6 @@ handle_info(tick_check_environment, #ch_mgr{ignore_timer=true}=S) ->
|
||||||
{noreply, S};
|
{noreply, S};
|
||||||
handle_info(tick_check_environment, S) ->
|
handle_info(tick_check_environment, S) ->
|
||||||
{{_Delta, Props, _Epoch}, S1} = do_react_to_env(S),
|
{{_Delta, Props, _Epoch}, S1} = do_react_to_env(S),
|
||||||
io:format(user, "tick ~p ~p ~p\n~p\n", [S#ch_mgr.name, _Delta, _Epoch, get(react)]),
|
|
||||||
S2 = sanitize_repair_state(S1),
|
S2 = sanitize_repair_state(S1),
|
||||||
S3 = perhaps_start_repair(S2),
|
S3 = perhaps_start_repair(S2),
|
||||||
case proplists:get_value(throttle_seconds, Props) of
|
case proplists:get_value(throttle_seconds, Props) of
|
||||||
|
@ -504,7 +503,9 @@ rank_and_sort_projections_with_extra(All_queried_list, FLUsRs, ProjectionType,
|
||||||
if All_queried_list == []
|
if All_queried_list == []
|
||||||
orelse
|
orelse
|
||||||
length(UnwrittenRs) == length(FLUsRs) ->
|
length(UnwrittenRs) == length(FLUsRs) ->
|
||||||
NoneProj = make_none_projection(MyName, [], orddict:new()),
|
Witness_list = CurrentProj#projection_v1.witnesses,
|
||||||
|
NoneProj = make_none_projection(MyName, [], Witness_list,
|
||||||
|
orddict:new()),
|
||||||
Extra2 = [{all_members_replied, true},
|
Extra2 = [{all_members_replied, true},
|
||||||
{all_queried_list, All_queried_list},
|
{all_queried_list, All_queried_list},
|
||||||
{flus_rs, FLUsRs},
|
{flus_rs, FLUsRs},
|
||||||
|
@ -601,7 +602,11 @@ calc_projection(_OldThreshold, _NoPartitionThreshold, LastProj,
|
||||||
NewUp = Up -- LastUp,
|
NewUp = Up -- LastUp,
|
||||||
Down = AllMembers -- Up,
|
Down = AllMembers -- Up,
|
||||||
|
|
||||||
NewUPI_list = [X || X <- OldUPI_list, lists:member(X, Up)],
|
NewUPI_list =
|
||||||
|
[W || W <- Up, lists:member(W, OldWitness_list)]
|
||||||
|
++
|
||||||
|
[X || X <- OldUPI_list, lists:member(X, Up) andalso
|
||||||
|
not lists:member(X, OldWitness_list)],
|
||||||
#projection_v1{upi=CurrentUPI_list} = CurrentProj,
|
#projection_v1{upi=CurrentUPI_list} = CurrentProj,
|
||||||
LastInCurrentUPI = case CurrentUPI_list of
|
LastInCurrentUPI = case CurrentUPI_list of
|
||||||
[] -> does_not_exist_because_upi_is_empty;
|
[] -> does_not_exist_because_upi_is_empty;
|
||||||
|
@ -611,7 +616,9 @@ calc_projection(_OldThreshold, _NoPartitionThreshold, LastProj,
|
||||||
[] -> does_not_exist_because_upi_is_empty;
|
[] -> does_not_exist_because_upi_is_empty;
|
||||||
[_|_] -> lists:last(NewUPI_list)
|
[_|_] -> lists:last(NewUPI_list)
|
||||||
end,
|
end,
|
||||||
Repairing_list2 = [X || X <- OldRepairing_list, lists:member(X, Up)],
|
Repairing_list2 = [X || X <- OldRepairing_list,
|
||||||
|
lists:member(X, Up),
|
||||||
|
not lists:member(X, OldWitness_list)],
|
||||||
Simulator_p = proplists:get_value(use_partition_simulator, RunEnv2, false),
|
Simulator_p = proplists:get_value(use_partition_simulator, RunEnv2, false),
|
||||||
SimRepair_p = proplists:get_value(simulate_repair, RunEnv2, true),
|
SimRepair_p = proplists:get_value(simulate_repair, RunEnv2, true),
|
||||||
{NewUPI_list3, Repairing_list3, RunEnv3} =
|
{NewUPI_list3, Repairing_list3, RunEnv3} =
|
||||||
|
@ -651,32 +658,30 @@ calc_projection(_OldThreshold, _NoPartitionThreshold, LastProj,
|
||||||
[] -> Repairing_list3;
|
[] -> Repairing_list3;
|
||||||
NewUp -> Repairing_list3 ++ NewUp
|
NewUp -> Repairing_list3 ++ NewUp
|
||||||
end,
|
end,
|
||||||
Repairing_list5 = Repairing_list4 -- Down,
|
Repairing_list5 = (Repairing_list4 -- Down) -- OldWitness_list,
|
||||||
|
|
||||||
TentativeUPI = NewUPI_list3,
|
TentativeUPI = NewUPI_list3,
|
||||||
TentativeRepairing = Repairing_list5,
|
TentativeRepairing = Repairing_list5,
|
||||||
|
|
||||||
|
AllTentativeUPI_witnesses_p =
|
||||||
|
lists:all(fun(X) -> lists:member(X, OldWitness_list) end,
|
||||||
|
TentativeUPI),
|
||||||
{NewUPI, NewRepairing} =
|
{NewUPI, NewRepairing} =
|
||||||
if TentativeUPI == [] andalso TentativeRepairing /= [] ->
|
if (TentativeUPI == [] orelse AllTentativeUPI_witnesses_p)
|
||||||
|
andalso TentativeRepairing /= [] ->
|
||||||
|
%% UPI is empty or all in UPI are witnesses, so grab
|
||||||
|
%% the first from the repairing list and make it the
|
||||||
|
%% only non-witness in the UPI.
|
||||||
[FirstRepairing|TailRepairing] = TentativeRepairing,
|
[FirstRepairing|TailRepairing] = TentativeRepairing,
|
||||||
{[FirstRepairing], TailRepairing};
|
{TentativeUPI ++ [FirstRepairing], TailRepairing};
|
||||||
true ->
|
true ->
|
||||||
{TentativeUPI, TentativeRepairing}
|
{TentativeUPI, TentativeRepairing}
|
||||||
end,
|
end,
|
||||||
|
|
||||||
P = case NewUPI -- OldWitness_list of
|
P = machi_projection:new(OldEpochNum + 1,
|
||||||
[] ->
|
MyName, MembersDict, Down, NewUPI, NewRepairing,
|
||||||
io:format(user, "\nNONE proj ~p\n", [OldEpochNum+1]),
|
|
||||||
NP = make_none_projection(MyName, OldAll_list, OldWitness_list,
|
|
||||||
MembersDict),
|
|
||||||
NP#projection_v1{epoch_number=OldEpochNum + 1};
|
|
||||||
_ ->
|
|
||||||
machi_projection:new(OldEpochNum + 1,
|
|
||||||
MyName, MembersDict,
|
|
||||||
Down, NewUPI, NewRepairing,
|
|
||||||
D_foo ++
|
D_foo ++
|
||||||
Dbg ++ [{ps, Partitions},{nodes_up, Up}])
|
Dbg ++ [{ps, Partitions},{nodes_up, Up}]),
|
||||||
end,
|
|
||||||
P2 = machi_projection:update_checksum(
|
P2 = machi_projection:update_checksum(
|
||||||
P#projection_v1{witnesses=OldWitness_list}),
|
P#projection_v1{witnesses=OldWitness_list}),
|
||||||
{P2, S#ch_mgr{runenv=RunEnv3}}.
|
{P2, S#ch_mgr{runenv=RunEnv3}}.
|
||||||
|
@ -793,28 +798,18 @@ rank_projections(Projs, CurrentProj) ->
|
||||||
rank_projection(#projection_v1{upi=[]}, _MemberRank, _N) ->
|
rank_projection(#projection_v1{upi=[]}, _MemberRank, _N) ->
|
||||||
-100;
|
-100;
|
||||||
rank_projection(#projection_v1{author_server=_Author,
|
rank_projection(#projection_v1{author_server=_Author,
|
||||||
|
witnesses=Witness_list,
|
||||||
upi=UPI_list,
|
upi=UPI_list,
|
||||||
repairing=Repairing_list}, _MemberRank, N) ->
|
repairing=Repairing_list}, _MemberRank, N) ->
|
||||||
%% It's possible that there's "cross-talk" across projection
|
|
||||||
%% stores. For example, we were a chain of [a,b], then the
|
|
||||||
%% administrator sets a's members_dict to include only a.
|
|
||||||
%% However, b is still running and has written a public projection
|
|
||||||
%% suggestion to a, and a has seen it. (Or perhaps b has old
|
|
||||||
%% chain information from one/many configurations ago, and its
|
|
||||||
%% projection store was not wiped clean, then b was restarted &
|
|
||||||
%% begins using its local outdated projection information.)
|
|
||||||
%%
|
|
||||||
%% Server b is no longer a member of a's MemberRank scheme, so we
|
|
||||||
%% need to compensate for this by giving b an extremely low author
|
|
||||||
%% ranking.
|
|
||||||
AuthorRank = 0,
|
AuthorRank = 0,
|
||||||
%% AuthorRank = case orddict:find(Author, MemberRank) of
|
case UPI_list -- Witness_list of
|
||||||
%% {ok, Rank} -> Rank;
|
[] ->
|
||||||
%% error -> -(N*N*N*N)
|
-100;
|
||||||
%% end,
|
_ ->
|
||||||
AuthorRank +
|
AuthorRank +
|
||||||
( N * length(Repairing_list)) +
|
( N * length(Repairing_list)) +
|
||||||
(N*N * length(UPI_list)).
|
(N*N * length(UPI_list))
|
||||||
|
end.
|
||||||
|
|
||||||
do_set_chain_members_dict(MembersDict, #ch_mgr{proxies_dict=OldProxiesDict}=S)->
|
do_set_chain_members_dict(MembersDict, #ch_mgr{proxies_dict=OldProxiesDict}=S)->
|
||||||
_ = ?FLU_PC:stop_proxies(OldProxiesDict),
|
_ = ?FLU_PC:stop_proxies(OldProxiesDict),
|
||||||
|
@ -1194,15 +1189,18 @@ react_to_env_A40(Retries, P_newprop, P_latest, LatestUnanimousP,
|
||||||
[{Rank_newprop, _}] = rank_projections([P_newprop], P_current),
|
[{Rank_newprop, _}] = rank_projections([P_newprop], P_current),
|
||||||
[{Rank_latest, _}] = rank_projections([P_latest], P_current),
|
[{Rank_latest, _}] = rank_projections([P_latest], P_current),
|
||||||
LatestAuthorDownP = lists:member(P_latest#projection_v1.author_server,
|
LatestAuthorDownP = lists:member(P_latest#projection_v1.author_server,
|
||||||
P_newprop#projection_v1.down),
|
P_newprop#projection_v1.down)
|
||||||
|
andalso P_latest#projection_v1.author_server /= MyName,
|
||||||
|
|
||||||
if
|
if
|
||||||
%% Epoch == 0 is reserved for first-time, just booting conditions.
|
%% Epoch == 0 is reserved for first-time, just booting conditions.
|
||||||
(P_current#projection_v1.epoch_number > 0
|
Rank_newprop > 0
|
||||||
|
andalso
|
||||||
|
((P_current#projection_v1.epoch_number > 0
|
||||||
andalso
|
andalso
|
||||||
P_latest#projection_v1.epoch_number > P_current#projection_v1.epoch_number)
|
P_latest#projection_v1.epoch_number > P_current#projection_v1.epoch_number)
|
||||||
orelse
|
orelse
|
||||||
not LatestUnanimousP ->
|
not LatestUnanimousP) ->
|
||||||
?REACT({a40, ?LINE,
|
?REACT({a40, ?LINE,
|
||||||
[{latest_epoch, P_latest#projection_v1.epoch_number},
|
[{latest_epoch, P_latest#projection_v1.epoch_number},
|
||||||
{current_epoch, P_current#projection_v1.epoch_number},
|
{current_epoch, P_current#projection_v1.epoch_number},
|
||||||
|
@ -1214,9 +1212,11 @@ react_to_env_A40(Retries, P_newprop, P_latest, LatestUnanimousP,
|
||||||
react_to_env_B10(Retries, P_newprop, P_latest, LatestUnanimousP,
|
react_to_env_B10(Retries, P_newprop, P_latest, LatestUnanimousP,
|
||||||
Rank_newprop, Rank_latest, S);
|
Rank_newprop, Rank_latest, S);
|
||||||
|
|
||||||
P_latest#projection_v1.epoch_number < P_current#projection_v1.epoch_number
|
Rank_newprop > 0
|
||||||
|
andalso
|
||||||
|
(P_latest#projection_v1.epoch_number < P_current#projection_v1.epoch_number
|
||||||
orelse
|
orelse
|
||||||
P_latest /= P_current ->
|
P_latest /= P_current) ->
|
||||||
?REACT({a40, ?LINE,
|
?REACT({a40, ?LINE,
|
||||||
[{latest_epoch, P_latest#projection_v1.epoch_number},
|
[{latest_epoch, P_latest#projection_v1.epoch_number},
|
||||||
{current_epoch, P_current#projection_v1.epoch_number},
|
{current_epoch, P_current#projection_v1.epoch_number},
|
||||||
|
@ -1261,6 +1261,8 @@ react_to_env_A40(Retries, P_newprop, P_latest, LatestUnanimousP,
|
||||||
react_to_env_C300(P_newprop, P_latest, S);
|
react_to_env_C300(P_newprop, P_latest, S);
|
||||||
|
|
||||||
%% A40b (see flowchart)
|
%% A40b (see flowchart)
|
||||||
|
Rank_newprop > 0
|
||||||
|
andalso
|
||||||
P_latest#projection_v1.author_server == MyName
|
P_latest#projection_v1.author_server == MyName
|
||||||
andalso
|
andalso
|
||||||
(P_newprop#projection_v1.upi /= P_latest#projection_v1.upi
|
(P_newprop#projection_v1.upi /= P_latest#projection_v1.upi
|
||||||
|
@ -1677,11 +1679,6 @@ react_to_env_C300(#projection_v1{epoch_number=_Epoch_newprop}=P_newprop,
|
||||||
#projection_v1{epoch_number=_Epoch_latest}=_P_latest, S) ->
|
#projection_v1{epoch_number=_Epoch_latest}=_P_latest, S) ->
|
||||||
?REACT(c300),
|
?REACT(c300),
|
||||||
|
|
||||||
%% This logic moved to A30.
|
|
||||||
%% NewEpoch = erlang:max(Epoch_newprop, Epoch_latest) + 1,
|
|
||||||
%% P_newprop2 = P_newprop#projection_v1{epoch_number=NewEpoch},
|
|
||||||
%% react_to_env_C310(update_checksum(P_newprop2), S).
|
|
||||||
|
|
||||||
react_to_env_C310(machi_projection:update_checksum(P_newprop), S).
|
react_to_env_C310(machi_projection:update_checksum(P_newprop), S).
|
||||||
|
|
||||||
react_to_env_C310(P_newprop, S) ->
|
react_to_env_C310(P_newprop, S) ->
|
||||||
|
@ -2161,7 +2158,8 @@ perhaps_start_repair(S) ->
|
||||||
S.
|
S.
|
||||||
|
|
||||||
do_repair(#ch_mgr{name=MyName,
|
do_repair(#ch_mgr{name=MyName,
|
||||||
proj=#projection_v1{upi=UPI,
|
proj=#projection_v1{witnesses=Witness_list,
|
||||||
|
upi=UPI0,
|
||||||
repairing=[_|_]=Repairing,
|
repairing=[_|_]=Repairing,
|
||||||
members_dict=MembersDict}}=S,
|
members_dict=MembersDict}}=S,
|
||||||
Opts, ap_mode=RepairMode) ->
|
Opts, ap_mode=RepairMode) ->
|
||||||
|
@ -2187,8 +2185,9 @@ do_repair(#ch_mgr{name=MyName,
|
||||||
RepairId = proplists:get_value(repair_id, Opts, id1),
|
RepairId = proplists:get_value(repair_id, Opts, id1),
|
||||||
error_logger:info_msg(
|
error_logger:info_msg(
|
||||||
"Repair start: tail ~p of ~p -> ~p, ~p ID ~w\n",
|
"Repair start: tail ~p of ~p -> ~p, ~p ID ~w\n",
|
||||||
[MyName, UPI, Repairing, RepairMode, RepairId]),
|
[MyName, UPI0, Repairing, RepairMode, RepairId]),
|
||||||
|
|
||||||
|
UPI = UPI0 -- Witness_list,
|
||||||
Res = machi_chain_repair:repair(ap_mode, MyName, Repairing, UPI,
|
Res = machi_chain_repair:repair(ap_mode, MyName, Repairing, UPI,
|
||||||
MembersDict, ETS, Opts),
|
MembersDict, ETS, Opts),
|
||||||
T2 = os:timestamp(),
|
T2 = os:timestamp(),
|
||||||
|
@ -2201,7 +2200,7 @@ do_repair(#ch_mgr{name=MyName,
|
||||||
error_logger:info_msg(
|
error_logger:info_msg(
|
||||||
"Repair ~s: tail ~p of ~p finished ~p repair ID ~w: "
|
"Repair ~s: tail ~p of ~p finished ~p repair ID ~w: "
|
||||||
"~p\nStats ~p\n",
|
"~p\nStats ~p\n",
|
||||||
[Summary, MyName, UPI, RepairMode, RepairId,
|
[Summary, MyName, UPI0, RepairMode, RepairId,
|
||||||
Res, Stats]),
|
Res, Stats]),
|
||||||
ets:delete(ETS),
|
ets:delete(ETS),
|
||||||
exit({repair_final_status, Res});
|
exit({repair_final_status, Res});
|
||||||
|
|
Loading…
Reference in a new issue