Skip to content

Instantly share code, notes, and snippets.

@Vagabond
Created December 29, 2010 21:10
Show Gist options
  • Save Vagabond/759073 to your computer and use it in GitHub Desktop.
Save Vagabond/759073 to your computer and use it in GitHub Desktop.
diff --cc src/agent_manager.erl
index cb67374,692b669..0000000
--- a/src/agent_manager.erl
+++ b/src/agent_manager.erl
@@@ -346,10 -359,13 +363,13 @@@ handle_DOWN(Node, #state{agents = Agent
Node =/= node(Apid)
end,
Agents2 = dict:filter(F, Agents),
- {ok, State#state{agents = Agents2}}.
+ Routelist = gb_trees_filter(fun({_Key, {Pid, _Id, _Skills}}) ->
+ Node =/= node(Pid)
+ end, State#state.route_list),
+ {ok, State#state{agents = Agents2, route_list = Routelist}}.
%% @hidden
-handle_leader_call({exists, Agent}, From, #state{agents = Agents} = State, Election) when is_list(
+handle_leader_call({exists, Agent}, From, #state{agents = _Agents} = State, Election) when is_list
?DEBUG("Trying to determine if ~p exists", [Agent]),
case handle_leader_call({full_data, Agent}, From, State, Election) of
{reply, false, _State} = O ->
@@@ -732,10 -826,155 +835,157 @@@ rotate_based_on_list_count_test_() -
?assertEqual(Out, rotate_based_on_list_count(In))
end}].
+ ds() ->
+ spawn(fun() -> ok end).
+
+ filter_avail_agents_by_skill_test_() ->
+ [{"one in, one out",
+ fun() ->
+ Agents = [{{0, z, 1, {100, 100, 100}}, {ds(), "agent", [skill]}}],
+ ?assertEqual(Agents, filter_avail_agents_by_skill(Agents, [skill]))
+ end},
+ {"two in, one out",
+ fun() ->
+ [Out | _] = Agents = [
+ {{0, z, 1, {100, 100, 100}}, {ds(), "agent1", [skill]}},
+ {{0, z, 0, {100, 100, 100}}, {ds(), "agent2", []}}
+ ],
+ ?assertEqual([Out], filter_avail_agents_by_skill(Agents, [skill]))
+ end},
+ {"agent with all gets in",
+ fun() ->
+ Agents = [{{0, z, 1, {100, 100, 100}}, {ds(), "agent", ['_all']}}],
+ ?assertEqual(Agents, filter_avail_agents_by_skill(Agents, [skill]))
+ end},
+ {"agents get through when all passed in",
+ fun() ->
+ Agents = [
+ {{0, z, 1, {100, 100, 100}}, {ds(), "agent1", [skill]}},
+ {{0, z, 0, {100, 100, 100}}, {ds(), "agent2", []}}
+ ],
+ ?assertEqual(Agents, filter_avail_agents_by_skill(Agents, ['_all']))
+ end}].
+
+ -record(election, {
+ leader = none,
+ name,
+ leadernode = none,
+ candidate_nodes = [],
+ worker_nodes = [],
+ alive = [],
+ down = [],
+ monitored = [],
+ buffered = [],
+ status,
+ elid,
+ acks = [],
+ work_down = [],
+ cand_timer_int,
+ cand_timer,
+ pendack,
+ incarn,
+ nextel,
+ bcast_type %% all | one. When `all' each election event
+ %% will be broadcast to all candidate nodes.
+ }).
+
+ handle_cast_test_() ->
+ {setup,
+ fun() ->
+ Election = #election{
+ leader = node(),
+ leadernode = node()
+ },
+ State = #state{},
+ {State, Election}
+ end,
+ fun(_) ->
+ ok
+ end,
+ fun({Seedstate, Election}) ->
+ [{"basic now availalble",
+ fun() ->
+ Agents = dict:from_list([{"agent", {ds(), "agent", 0, []}}]),
+ State = #state{agents = Agents},
+ {noreply, Newstate} = handle_cast({now_avail, "agent"}, State, Election),
+ ?assertNot(gb_trees:is_empty(Newstate#state.route_list)),
+ ?assertMatch([{{0, z, 0, _}, {_, "agent", []}}], gb_trees:to_list(Newstate#s
+ end},
+ {"basic end avail",
+ fun() ->
+ Time = os:timestamp(),
+ Pid = ds(),
+ Agents = dict:from_list([{"agent", {Pid, "agent", Time, []}}]),
+ Routelist = gb_trees:enter({0, z, 0, Time}, {Pid, "agent", []}, gb_trees:emp
+ State = Seedstate#state{agents = Agents, route_list = Routelist},
+ {noreply, Newstate} = handle_cast({end_avail, "agent"}, State, Election),
+ ?assert(gb_trees:is_empty(Newstate#state.route_list))
+ end},
+ {"updatin' a skill list of an idle agent",
+ fun() ->
+ Pid = ds(),
+ Time = os:timestamp(),
+ Agents = dict:from_list([{"agent", {Pid, "agent", Time, []}}]),
+ Routelist = gb_trees:enter({0, z, 0, Time}, {Pid, "agent", []}, gb_trees:emp
+ State = #state{agents = Agents, route_list = Routelist},
+ {noreply, NewState} = handle_cast({update_skill_list, "agent", [skill]}, Sta
+ ?assertNot(gb_trees:is_empty(NewState#state.route_list)),
+ ?assertMatch([{{0, z, 1, _}, {Pid, "agent", [skill]}}], gb_trees:to_list(New
+ end}]
+ end}.
+
+
+
+ %handle_cast({end_avail, Nom}, #state{agents = Agents} = State, Election) ->
+ % Node = node(),
+ % F = fun({Pid, Id, _Time, Skills}) ->
+ % Out = {Pid, Id, 0, Skills},
+ %case gen_leader:leader_node(Election) of
+ % Node ->
+ % ok;
+ %_ ->
+ %gen_leader:leader_cast(?MODULE, {update_notify, Nom, Out})
+ %end,
+ %Out
+ %end,
+ %NewAgents = dict:update(Nom, F, Agents),
+ %{noreply, State#state{agents = NewAgents, lists_requested = 0}};
+ %handle_cast({update_skill_list, Login, Skills}, #state{agents = Agents} = State, Election) ->
+ % Node = node(),
+ % {Pid, Id, Time, _} = dict:fetch(Login, Agents),
+ % Out = {Pid, Id, Time, Skills},
+ % Midroutelist = clear_rotates(gb_trees_filter(fun({_, {Apid, _, _}}) ->
+ % Api
+ % end
+ % Routelist = gb_trees:enter({0, ?has_all(Skills), length(Skills), Time}, {Pid, Id, Skills}, M
+ % F = fun({Pid, Id, Time, _OldSkills}) ->
+ %case gen_leader:leader_node(Election) of
+ % Node ->
+ % ok;
+ %_ ->
+ %gen_leader:leader_cast(?MODULE, {update_notify, Login, Out})
+ %end,
+ %Out
+ %end,
+ %NewAgents = dict:update(Login, F, Agents),
+ %{noreply, State#state{agents = NewAgents, lists_requested = 0, route_list = Routelist}};
+ %handle_cast(_Request, State, _Election) ->
+ % ?DEBUG("Stub handle_cast", []),
+ % {noreply, State}.
+ %
+ %
+ %
+ %
+ %
+ %
+ %
+
+
+
single_node_test_() ->
- {foreach,
+ util:start_testnode(),
+ N = util:start_testnode(agent_manage_single_node_tests),
+ {spawn, N, {foreach,
fun() ->
Agent = #agent{login="testagent"},
mnesia:stop(),
@@@ -973,88 -1217,70 +1228,152 @@@ multi_node_test_d() -
end
]
}.
+-endif.
+
+-ifdef(PROFILE).
+
+avg(Times) ->
+ Sum = lists:foldl(fun(E, S) -> E + S end, 0, Times),
+ Sum / length(Times).
+
+adding_agents_tc_test_() ->
+ {foreach,
+ fun() ->
+ {ok, File} = file:open(?MODULE_STRING ++ "-profile.txt", [append]),
+ {ok, AM} = agent_manager:start([node()]),
+ File
+ end,
+ fun(File) ->
+ file:close(File),
+ agent_manager:stop()
+ end,
+ [fun(File) -> Name = "agents with same length skills", {timeout, 60, {Name, fun() ->
+ Agents = [#agent{
+ login = integer_to_list(X),
+ skills = [X rem 5]
+ } || X <- lists:seq(1, 1000)],
+ Times = [begin
+ {T, _} = timer:tc(agent_manager, start_agent, [A]),
+ T
+ end || A <- Agents],
+ [case agent_manager:query_agent(A#agent.login) of
+ {true, Pid} ->
+ exit(Pid, kill);
+ false ->
+ ok
+ end || A <- Agents],
+ ?INFO("Average for ~s: ~f", [Name, avg(Times)]),
+ ?assert(true),
+ io:format(File, "~p ~s:~s(~s) ~f~n", [os:timestamp(), ?MODULE, adding_agen
+ end}} end,
+ fun(File) -> Name = "agents with variable length skills", {timeout, 60, {Name, fun() ->
+ Agents = [#agent{
+ login = integer_to_list(X),
+ skills = [S || S <- lists:seq(0, X rem 10)]
+ } || X <- lists:seq(1, 1000)],
+ Times = [begin
+ {T, _} = timer:tc(agent_manager, start_agent, [A]),
+ T
+ end || A <- Agents],
+ [case agent_manager:query_agent(A#agent.login) of
+ {true, Pid} ->
+ exit(Pid, kill);
+ false ->
+ ok
+ end || A <- Agents],
+ ?INFO("Average: ~f", [avg(Times)]),
+ io:format(File, "~p ~s:~s(~s) ~f~n", [os:timestamp(), ?MODULE, adding_agen
+ ?assert(true)
+ end}} end,
+ fun(File) -> Name = "agent skill list shoved in the middle", {timeout, 60, {Name, fun() ->
+ LowAgents = [#agent{
+ login = integer_to_list(X),
+ skills = []
+ } || X <- lists:seq(1, 499)],
+ HighAgents = [#agent{
+ login = integer_to_list(X),
+ skills = [english, german]
+ } || X <- lists:seq(501, 1000)],
+ AllAgents = LowAgents ++ HighAgents,
+ [agent_manager:start_agent(A) || A <- AllAgents],
+ Times = [begin
+ {T, {_, Pid}} = timer:tc(agent_manager, start_agent, [#agent{
+ login = "500",
+ skills = [english]
+ }]),
+ exit(Pid, kill),
+ % give it a moment to clear it
+ timer:sleep(10),
+ T
+ end || _X <- lists:seq(1, 1000)],
+ ?INFO("Average: ~f", [avg(Times)]),
+ io:format(File, "~p ~s:~s(~s) ~f~n", [os:timestamp(), ?MODULE, adding_agen
+ ?assert(true)
+ end}} end]}.
+ -ifdef(PROFILE).
+
+ avg(Times) ->
+ Sum = lists:foldl(fun(E, S) -> E + S end, 0, Times),
+ Sum / length(Times).
+
+ tdiff({InMeg, InSec, InMic}, {GotMeg, GotSec, GotMic}) ->
+ In = InMeg * 1000000 + InSec + InMic / 1000000,
+ Got = GotMeg * 1000000 + GotSec + GotMic / 1000000,
+ Got - In.
+
+ adding_agents_test_() ->
+ {foreach,
+ fun() ->
+ {ok, AM} = agent_manager:start([node()]),
+ AM
+ end,
+ fun(_AM) ->
+ agent_manager:stop()
+ end,
+ [fun(_) -> {timeout, 60, {"agents with same length skills", fun() ->
+ Agents = [#agent{
+ login = integer_to_list(X),
+ skills = [X rem 5]
+ } || X <- lists:seq(1, 1000)],
+ Times = [begin
+ Start = os:timestamp(),
+ agent_manager:start_agent(A),
+ End = os:timestamp(),
+ tdiff(Start, End)
+ end || A <- Agents],
+ [case agent_manager:query_agent(A#agent.login) of
+ {true, Pid} ->
+ exit(Pid, kill);
+ false ->
+ ok
+ end || A <- Agents],
+ ?INFO("Average: ~f", [avg(Times)]),
+ ?assert(true)
+ end}} end,
+ fun(_) -> {timeout, 60, {"agents with variable length skills", fun() ->
+ Agents = [#agent{
+ login = integer_to_list(X),
+ skills = [S || S <- lists:seq(0, X rem 10)]
+ } || X <- lists:seq(1, 1000)],
+ Times = [begin
+ Start = os:timestamp(),
+ agent_manager:start_agent(A),
+ End = os:timestamp(),
+ tdiff(Start, End)
+ end || A <- Agents],
+ [case agent_manager:query_agent(A#agent.login) of
+ {true, Pid} ->
+ exit(Pid, kill);
+ false ->
+ ok
+ end || A <- Agents],
+ ?INFO("Average: ~f", [avg(Times)]),
+ ?assert(true)
+ end}} end]}.
+
+
+ -endif.
+
-endif.
diff --cc src/dispatcher.erl
index 104a9c9,c046187..0000000
--- a/src/dispatcher.erl
+++ b/src/dispatcher.erl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment