WIP: chain manager simulation test
This commit is contained in:
parent
b8c87b23ad
commit
410c8ff7ce
2 changed files with 103 additions and 66 deletions
|
@ -51,21 +51,24 @@
|
||||||
all_members :: [m_server()],
|
all_members :: [m_server()],
|
||||||
active_upi :: [m_server()],
|
active_upi :: [m_server()],
|
||||||
active_repairing:: [m_server()],
|
active_repairing:: [m_server()],
|
||||||
dbg :: list()%proplist()
|
dbg :: list() %proplist()
|
||||||
}).
|
}).
|
||||||
|
|
||||||
-record(state, {
|
-record(state, {
|
||||||
name :: m_server(),
|
name :: m_server(),
|
||||||
proj :: #projection{},
|
proj :: #projection{},
|
||||||
seed :: timestamp(),
|
last_up :: list(m_server()),
|
||||||
last_up :: list(m_server())
|
%%
|
||||||
|
runenv :: list() %proplist()
|
||||||
}).
|
}).
|
||||||
|
|
||||||
make_initial_state(MyName, All_list, Seed) ->
|
make_initial_state(MyName, All_list, Seed) ->
|
||||||
|
RunEnv = [{seed, Seed},
|
||||||
|
{network_partitions, []}],
|
||||||
#state{name=MyName,
|
#state{name=MyName,
|
||||||
proj=make_initial_projection(MyName, All_list, All_list, [], []),
|
proj=make_initial_projection(MyName, All_list, All_list, [], []),
|
||||||
seed=Seed,
|
last_up=All_list,
|
||||||
last_up=All_list}.
|
runenv=RunEnv}.
|
||||||
|
|
||||||
make_initial_projection(MyName, All_list, UPI_list, Repairing_list, Ps) ->
|
make_initial_projection(MyName, All_list, UPI_list, Repairing_list, Ps) ->
|
||||||
make_projection(1, 0, <<>>,
|
make_projection(1, 0, <<>>,
|
||||||
|
@ -86,41 +89,103 @@ make_projection(EpochNum, PrevEpochNum, PrevEpochCSum,
|
||||||
CSum = crypto:hash(sha, term_to_binary(P)),
|
CSum = crypto:hash(sha, term_to_binary(P)),
|
||||||
P#projection{epoch_csum=CSum}.
|
P#projection{epoch_csum=CSum}.
|
||||||
|
|
||||||
calc_projection(CurrentInfo, #state{name=MyName, proj=OldProj} = S) ->
|
calc_projection(OldThreshold, NoPartitionThreshold,
|
||||||
{UpNodes, S2} = calc_up_nodes(CurrentInfo, S),
|
#state{name=MyName, last_up=_LastUp, proj=LastProj,
|
||||||
|
runenv=RunEnv1} = S) ->
|
||||||
#projection{epoch_number=OldEpochNum,
|
#projection{epoch_number=OldEpochNum,
|
||||||
epoch_csum=OldEpochCsum,
|
epoch_csum=OldEpochCsum,
|
||||||
all_members=All_list
|
all_members=All_list
|
||||||
%% active_upi=UPI_list,
|
} = LastProj,
|
||||||
%% active_repairing=Repairing_list,
|
|
||||||
%% dbg=Ps
|
|
||||||
} = OldProj,
|
|
||||||
P = make_projection(OldEpochNum + 1, OldEpochNum, OldEpochCsum,
|
|
||||||
MyName, All_list, UpNodes, [], [{fubar,true}]),
|
|
||||||
{P, S2}.
|
|
||||||
|
|
||||||
calc_up_nodes(CurrentInfo,
|
|
||||||
#state{name=MyName, seed=Seed, last_up=LastUp} = S) ->
|
|
||||||
AllMembers = (S#state.proj)#projection.all_members,
|
AllMembers = (S#state.proj)#projection.all_members,
|
||||||
{F, Seed2} = random:uniform_s(Seed),
|
{Up, RunEnv2} = calc_up_nodes(MyName, OldThreshold, NoPartitionThreshold,
|
||||||
Cutoff = trunc(F * 100),
|
AllMembers, RunEnv1),
|
||||||
if LastUp == undefined orelse Cutoff rem 3 == 0 ->
|
P = make_projection(OldEpochNum + 1, OldEpochNum, OldEpochCsum,
|
||||||
Up = calc_new_up_nodes(MyName, AllMembers, CurrentInfo, Cutoff),
|
MyName, All_list, Up, [], [{fubar,true}]),
|
||||||
{Up, S#state{seed=Seed2, last_up=Up}};
|
{P, S#state{runenv=RunEnv2}}.
|
||||||
|
|
||||||
|
calc_up_nodes(MyName, OldThreshold, NoPartitionThreshold,
|
||||||
|
AllMembers, RunEnv1) ->
|
||||||
|
Seed1 = proplists:get_value(seed, RunEnv1),
|
||||||
|
Partitions1 = proplists:get_value(network_partitions, RunEnv1),
|
||||||
|
{Seed2, Partitions2} =
|
||||||
|
calc_network_partitions(AllMembers, Seed1, Partitions1,
|
||||||
|
OldThreshold, NoPartitionThreshold),
|
||||||
|
UpNodes = lists:sort(
|
||||||
|
[Node || Node <- AllMembers,
|
||||||
|
not lists:member({MyName, Node}, Partitions2),
|
||||||
|
not lists:member({Node, MyName}, Partitions2)]),
|
||||||
|
RunEnv2 = replace(RunEnv1,
|
||||||
|
[{seed, Seed2}, {network_partitions, Partitions2}]),
|
||||||
|
{UpNodes, RunEnv2}.
|
||||||
|
|
||||||
|
|
||||||
|
calc_network_partitions(Nodes, Seed1, OldPartition,
|
||||||
|
OldThreshold, NoPartitionThreshold) ->
|
||||||
|
{F2, Seed2} = random:uniform_s(Seed1),
|
||||||
|
Cutoff2 = trunc(F2 * 100),
|
||||||
|
if Cutoff2 < OldThreshold ->
|
||||||
|
{F3, Seed3} = random:uniform_s(Seed1),
|
||||||
|
Cutoff3 = trunc(F3 * 100),
|
||||||
|
if Cutoff3 < NoPartitionThreshold ->
|
||||||
|
{Seed3, []};
|
||||||
|
true ->
|
||||||
|
make_network_partition_locations(Nodes, Seed3)
|
||||||
|
end;
|
||||||
true ->
|
true ->
|
||||||
{LastUp, S#state{seed=Seed2}}
|
{Seed2, OldPartition}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
calc_new_up_nodes(MyName, Nodes, CurrentInfo, Cutoff) ->
|
replace(PropList, Items) ->
|
||||||
C_weights = proplists:get_value(communicating_weights, CurrentInfo),
|
lists:foldl(fun({Key, Val}, Ps) ->
|
||||||
lists:usort([MyName] ++
|
lists:keyreplace(Key, 1, Ps, {Key,Val})
|
||||||
[Node || Node <- Nodes,
|
end, PropList, Items).
|
||||||
Node /= MyName,
|
|
||||||
Weight_to <- [element(1,
|
make_projection_summary(#projection{epoch_number=EpochNum,
|
||||||
lists:keyfind({MyName, Node},
|
all_members=All_list,
|
||||||
2, C_weights))],
|
active_upi=UPI_list,
|
||||||
Weight_from <- [element(1,
|
active_repairing=Repairing_list}) ->
|
||||||
lists:keyfind({Node, MyName},
|
[{epoch,EpochNum},{all,All_list},{upi,UPI_list},{repair,Repairing_list}].
|
||||||
2, C_weights))],
|
|
||||||
Weight_to =< Cutoff,
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
Weight_from =< Cutoff]).
|
|
||||||
|
make_network_partition_locations(Nodes, Seed1) ->
|
||||||
|
Pairs = make_all_pairs(Nodes),
|
||||||
|
Num = length(Pairs),
|
||||||
|
{Seed2, Weights} = lists:foldl(
|
||||||
|
fun(_, {Seeda, Acc}) ->
|
||||||
|
{F, Seedb} = random:uniform_s(Seeda),
|
||||||
|
Cutoff = trunc(F * 100),
|
||||||
|
{Seedb, [Cutoff|Acc]}
|
||||||
|
end, {Seed1, []}, lists:seq(1, Num)),
|
||||||
|
{F3, Seed3} = random:uniform_s(Seed2),
|
||||||
|
Cutoff3 = trunc(F3 * 100),
|
||||||
|
{Seed3, [X || {Weight, X} <- lists:zip(Weights, Pairs),
|
||||||
|
Weight < Cutoff3]}.
|
||||||
|
|
||||||
|
make_all_pairs(L) ->
|
||||||
|
lists:flatten(make_all_pairs2(lists:usort(L))).
|
||||||
|
|
||||||
|
make_all_pairs2([]) ->
|
||||||
|
[];
|
||||||
|
make_all_pairs2([_]) ->
|
||||||
|
[];
|
||||||
|
make_all_pairs2([H1|T]) ->
|
||||||
|
[[{H1, X}, {X, H1}] || X <- T] ++ make_all_pairs(T).
|
||||||
|
|
||||||
|
-ifdef(TEST).
|
||||||
|
|
||||||
|
smoke0_test() ->
|
||||||
|
S0 = ?MODULE:make_initial_state(a, [a,b,c], {4,5,6}),
|
||||||
|
lists:foldl(fun(_, S) ->
|
||||||
|
{P1, S1} = calc_projection(555, 0, S),
|
||||||
|
io:format(user, "~p\n", [make_projection_summary(P1)]),
|
||||||
|
S1#state{proj=P1}
|
||||||
|
end, S0, lists:seq(1,10)).
|
||||||
|
%% [begin
|
||||||
|
%% %%io:format(user, "S0 ~p\n", [S0]),
|
||||||
|
%% {P1, _S1} = calc_projection(555, 0, S0),
|
||||||
|
%% io:format(user, "P1 ~p\n", [P1]),
|
||||||
|
%% ok % io:format(user, "S1 ~p\n", [S1]).
|
||||||
|
%% end || X <- lists:seq(1, 10)].
|
||||||
|
|
||||||
|
-endif. %TEST
|
||||||
|
|
|
@ -36,8 +36,7 @@
|
||||||
|
|
||||||
-record(s, {
|
-record(s, {
|
||||||
step = 0 :: non_neg_integer(),
|
step = 0 :: non_neg_integer(),
|
||||||
seed :: {integer(), integer(), integer()},
|
seed :: {integer(), integer(), integer()}
|
||||||
comm_weights = [] :: list()
|
|
||||||
}).
|
}).
|
||||||
|
|
||||||
gen_all_nodes() ->
|
gen_all_nodes() ->
|
||||||
|
@ -50,23 +49,6 @@ gen_num() ->
|
||||||
?LET(I, oneof([int(), largeint()]),
|
?LET(I, oneof([int(), largeint()]),
|
||||||
erlang:abs(I)).
|
erlang:abs(I)).
|
||||||
|
|
||||||
gen_communicating_weights(Nodes) ->
|
|
||||||
Pairs = make_all_pairs(Nodes),
|
|
||||||
Num = length(Pairs),
|
|
||||||
?LET(Weights, vector(Num, choose(1, 100)),
|
|
||||||
lists:zip(Weights, Pairs)).
|
|
||||||
|
|
||||||
%% gen_communicating_nodes(Nodes) ->
|
|
||||||
%% ?LET(Pairs, make_all_pairs(Nodes),
|
|
||||||
%% frequency([{10, Pairs},
|
|
||||||
%% { 8, gen_take_some(Pairs)}])).
|
|
||||||
|
|
||||||
%% gen_take_some(L) ->
|
|
||||||
%% Num = length(L),
|
|
||||||
%% ?LET({Weights, Cutoff}, {vector(Num, choose(1, 100)), choose(1, 100)},
|
|
||||||
%% [X || {Weight, X} <- lists:zip(Weights, L),
|
|
||||||
%% Weight < Cutoff]).
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
initial_state() ->
|
initial_state() ->
|
||||||
|
@ -74,7 +56,7 @@ initial_state() ->
|
||||||
|
|
||||||
command(#s{step=0}) ->
|
command(#s{step=0}) ->
|
||||||
L = gen_all_nodes(),
|
L = gen_all_nodes(),
|
||||||
{call, ?MODULE, init_run, [gen_rand_seed(), gen_communicating_weights(L)]};
|
{call, ?MODULE, init_run, [gen_rand_seed(), L]};
|
||||||
command(_S) ->
|
command(_S) ->
|
||||||
foo.
|
foo.
|
||||||
|
|
||||||
|
@ -88,13 +70,3 @@ prop_m() ->
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
make_all_pairs(L) ->
|
|
||||||
lists:flatten(make_all_pairs2(lists:usort(L))).
|
|
||||||
|
|
||||||
make_all_pairs2([]) ->
|
|
||||||
[];
|
|
||||||
make_all_pairs2([_]) ->
|
|
||||||
[];
|
|
||||||
make_all_pairs2([H1|T]) ->
|
|
||||||
[[{H1, X}, {X, H1}] || X <- T] ++ make_all_pairs(T).
|
|
||||||
%% [{H1, H2}, {H2, H1}|make_all_pairs([H2|T])].
|
|
||||||
|
|
Loading…
Reference in a new issue