diff options
| author | Tim Watson <tim@rabbitmq.com> | 2014-01-28 16:25:49 +0000 |
|---|---|---|
| committer | Tim Watson <tim@rabbitmq.com> | 2014-01-28 16:25:49 +0000 |
| commit | e3159b1f4f2977a9cf6d1e1f9beb4ff3e634e17a (patch) | |
| tree | 8483e4eaf30864351a84ba7be550cb78af63f8f9 /src | |
| parent | 81bd7f7e2600a30d7473a512487a3d33a1c8a4af (diff) | |
| download | rabbitmq-server-git-e3159b1f4f2977a9cf6d1e1f9beb4ff3e634e17a.tar.gz | |
Handle varying destinations in mcall/1
Diffstat (limited to 'src')
| -rw-r--r-- | src/gen_server2.erl | 39 | ||||
| -rw-r--r-- | src/rabbit_tests.erl | 16 |
2 files changed, 46 insertions, 9 deletions
diff --git a/src/gen_server2.erl b/src/gen_server2.erl index 0fea8dd1bc..4326a4473c 100644 --- a/src/gen_server2.erl +++ b/src/gen_server2.erl @@ -393,7 +393,10 @@ multi_call(Nodes, Name, Req, Timeout) %%% ----------------------------------------------------------------- %%% Make multiple calls to multiple servers, given pairs of servers %%% and messages. -%%% Returns: {[{Pid, Reply}], [{Pid, Error}]} +%%% Returns: {[{Dest, Reply}], [{Dest, Error}]} +%%% +%%% Dest can be pid() | RegName :: atom() | +%%% {Name :: atom(), Node :: atom()} | {global, Name :: atom()} %%% %%% A middleman process is used to avoid clogging up the callers %%% message queue. @@ -411,11 +414,35 @@ mcall(CallSpecs) -> {'DOWN', MRef, _, _, Reason} -> exit(Reason) end. -do_mcall({Pid, Request}, Dict) -> - MRef = erlang:monitor(process, Pid), - catch erlang:send(Pid, {'$gen_call', {self(), MRef}, Request}, - [noconnect]), - dict:store(MRef, Pid, Dict). +do_mcall({Dest={global, Name}, Request}, Dict) -> + %% whereis_name is simply an ets lookup, and is precisely what + %% global:send/2 does, yet we need a Ref to put in the call to the + %% server, so invoking whereis_name makes a lot more sense here. + GRef = case global:whereis_name(Name) of + Pid when is_pid(Pid) -> + MRef = erlang:monitor(process, Pid), + catch msend(Pid, MRef, Request), + MRef; + undefined -> + Ref = make_ref(), + self() ! {'DOWN', Ref, process, Dest, unknown_name}, + Ref + end, + dict:store(GRef, Dest, Dict); + +do_mcall({Dest, Request}, Dict) -> + MRef = case Dest of + {Name, Node} when is_atom(Name), is_atom(Node) -> + {_Node, Ref} = start_monitor(Node, Name), + Ref; + _PidOrRegName -> + erlang:monitor(process, Dest) + end, + catch msend(Dest, MRef, Request), + dict:store(MRef, Dest, Dict). + +msend(Dest, MRef, Request) -> + erlang:send(Dest, {'$gen_call', {self(), MRef}, Request}, [noconnect]). collect_replies(Tag, Refs, Replies, Errors) -> case dict:size(Refs) of diff --git a/src/rabbit_tests.erl b/src/rabbit_tests.erl index a5e91f67af..bb0cd42177 100644 --- a/src/rabbit_tests.erl +++ b/src/rabbit_tests.erl @@ -1370,11 +1370,21 @@ test_with_state() -> passed. test_mcall() -> - Pids = [spawn_link(fun gs2_test_listener/0) || _ <- lists:seq(1, 250)], - BadPids = [spawn(fun gs2_test_crasher/0) || _ <- lists:seq(1, 10)], + Pids1 = [spawn_link(fun gs2_test_listener/0) || _ <- lists:seq(1, 5)], + Pids2 = [spawn_link(fun() -> + register(cottontail, self()), + gs2_test_listener() + end)], + Pids = Pids1 ++ Pids2, + BadPids1 = [spawn(fun gs2_test_crasher/0) || _ <- lists:seq(1, 10)], + BadPids2 = [{global, foo}, {nonode@nohost, bar}], + BadPids = BadPids1 ++ BadPids2, {Replies, Errors} = gen_server2:mcall([{P, hello} || P <- Pids ++ BadPids]), true = lists:sort(Replies) == lists:sort([{Pid, goodbye} || Pid <- Pids]), - true = lists:sort(Errors) == lists:sort([{Pid, boom} || Pid <- BadPids]), + true = lists:sort(Errors) == + lists:sort([{Pid, boom} || Pid <- BadPids1] ++ + [{{nonode@nohost,bar},nodedown}, + {{global,foo},unknown_name}]), passed. gs2_test_crasher() -> |
