summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mirrored_supervisor.erl12
-rw-r--r--src/mirrored_supervisor_tests.erl101
-rw-r--r--src/rabbit.erl6
-rw-r--r--src/rabbit_tests.erl1
4 files changed, 113 insertions, 7 deletions
diff --git a/src/mirrored_supervisor.erl b/src/mirrored_supervisor.erl
index b94b0144e0..106a888b98 100644
--- a/src/mirrored_supervisor.erl
+++ b/src/mirrored_supervisor.erl
@@ -48,7 +48,7 @@
handle_cast/2]).
-export([start_internal/3]).
--export([create_tables/0, table_definitions/0]).
+-export([init/0, create_tables/0, table_definitions/0]).
-record(mirrored_sup_childspec, {id, sup_pid, childspec}).
@@ -88,15 +88,13 @@ call(Sup, Msg) ->
%%----------------------------------------------------------------------------
+init() ->
+ ets:new(?ETS_TABLE, [named_table, public]).
+
start_internal(Sup, Group, Args) ->
{ok, Pid} = ?GEN_SERVER:start_link(?MODULE, {Sup, Group, Args},
[{timeout, infinity}]),
- Ins = fun() -> true = ets:insert(?ETS_TABLE, {Sup, Pid}) end,
- try
- Ins()
- catch error:badarg -> ets:new(?ETS_TABLE, [named_table]),
- Ins()
- end,
+ ets:insert(?ETS_TABLE, {Sup, Pid}),
{ok, Pid}.
%%----------------------------------------------------------------------------
diff --git a/src/mirrored_supervisor_tests.erl b/src/mirrored_supervisor_tests.erl
new file mode 100644
index 0000000000..3adc9300af
--- /dev/null
+++ b/src/mirrored_supervisor_tests.erl
@@ -0,0 +1,101 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License at
+%% http://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+%% License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developer of the Original Code is VMware, Inc.
+%% Copyright (c) 2007-2011 VMware, Inc. All rights reserved.
+%%
+
+-module(mirrored_supervisor_tests).
+
+-compile([export_all]).
+
+-export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3,
+ handle_cast/2]).
+
+-behaviour(gen_server).
+-behaviour(mirrored_supervisor).
+
+%% ---------------------------------------------------------------------------
+%% Functional tests
+%% ---------------------------------------------------------------------------
+
+all_tests() ->
+ passed = test_simple(),
+ passed.
+
+test_simple() ->
+ {ok, A} = start_sup(a),
+ {ok, B} = start_sup(b),
+ mirrored_supervisor:start_child(a, childspec(worker)),
+ Pid1 = pid_of(worker),
+ kill(A),
+ Pid2 = pid_of(worker),
+ false = (Pid1 =:= Pid2),
+ kill(B),
+ passed.
+
+%% ---------------------------------------------------------------------------
+
+start_sup(Name) ->
+ start_sup(Name, group).
+
+start_sup(Name, Group) ->
+ mirrored_supervisor:start_link({local, Name}, Group, ?MODULE, []).
+
+childspec(Id) ->
+ {Id, {?MODULE, start_gs, [Id]}, transient, 16#ffffffff, worker, [?MODULE]}.
+
+start_gs(Id) ->
+ gen_server:start_link({local, Id}, ?MODULE, [], []).
+
+pid_of(Id) ->
+ {received, Pid, ping} = call(Id, ping),
+ {ok, Pid}.
+
+call(Id, Msg) -> call(Id, Msg, 100, 10).
+
+call(Id, Msg, 0, Decr) ->
+ exit({timeout_waiting_for_server, Id, Msg});
+
+call(Id, Msg, MaxDelay, Decr) ->
+ try
+ gen_server:call(Id, Msg, infinity)
+ catch exit:{shutdown, _} -> timer:sleep(Decr),
+ call(Id, Msg, MaxDelay - Decr, Decr)
+ end.
+
+kill(Pid) -> exit(Pid, bang).
+
+%% ---------------------------------------------------------------------------
+%% Dumb gen_server we can supervise
+%% ---------------------------------------------------------------------------
+
+%% Cheeky: this is used for both the gen_server and supervisor
+%% behaviours. So our gen server has a weird-looking state. But we
+%% don't care.
+init(ChildSpecs) ->
+ {ok, {{one_for_one, 3, 10}, ChildSpecs}}.
+
+handle_call(Msg, _From, State) ->
+ {reply, {received, self(), Msg}, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
diff --git a/src/rabbit.erl b/src/rabbit.erl
index 6ef816c0f1..61df20679b 100644
--- a/src/rabbit.erl
+++ b/src/rabbit.erl
@@ -57,6 +57,12 @@
{requires, pre_boot},
{enables, external_infrastructure}]}).
+-rabbit_boot_step({mirrored_supervisor,
+ [{description, "mirrored supervisor"},
+ {mfa, {mirrored_supervisor, init, []}},
+ {requires, pre_boot},
+ {enables, external_infrastructure}]}).
+
-rabbit_boot_step({external_infrastructure,
[{description, "external infrastructure ready"}]}).
diff --git a/src/rabbit_tests.erl b/src/rabbit_tests.erl
index 3ee71a6de8..cd1a9e703c 100644
--- a/src/rabbit_tests.erl
+++ b/src/rabbit_tests.erl
@@ -36,6 +36,7 @@ test_content_prop_roundtrip(Datum, Binary) ->
all_tests() ->
passed = gm_tests:all_tests(),
+ passed = mirrored_supervisor_tests:all_tests(),
application:set_env(rabbit, file_handles_high_watermark, 10, infinity),
ok = file_handle_cache:set_limit(10),
passed = test_file_handle_cache(),