Created
December 29, 2010 21:10
-
-
Save Vagabond/759073 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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