diff options
| -rw-r--r-- | src/mirrored_supervisor.erl | 46 | ||||
| -rw-r--r-- | src/mirrored_supervisor_tests.erl | 24 |
2 files changed, 52 insertions, 18 deletions
diff --git a/src/mirrored_supervisor.erl b/src/mirrored_supervisor.erl index add2c1208b..877efe4f6b 100644 --- a/src/mirrored_supervisor.erl +++ b/src/mirrored_supervisor.erl @@ -45,7 +45,7 @@ -export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3, handle_cast/2]). --export([start_internal/2]). +-export([start_internal/4]). -export([create_tables/0, table_definitions/0]). -record(mirrored_sup_childspec, {id, mirroring_pid, childspec}). @@ -59,8 +59,12 @@ start_link(_Group, _Mod, _Args) -> exit(mirrored_supervisors_must_be_locally_named). start_link({local, SupName}, Group, Mod, Args) -> - ?SUPERVISOR:start_link({local, SupName}, ?MODULE, - {overall, SupName, Group, Mod, Args}); + R = ?SUPERVISOR:start_link({local, SupName}, ?MODULE, + {overall, SupName, Group, Mod, Args, self()}), + receive + started -> ok + end, + R; start_link({global, _SupName}, _Group, _Mod, _Args) -> exit(mirrored_supervisors_must_be_locally_named). @@ -84,20 +88,27 @@ child(Sup, Name) -> %%---------------------------------------------------------------------------- -start_internal(Sup, Group) -> +start_internal(Sup, Group, ChildSpecs, Notify) -> ?GEN_SERVER:start_link( - ?MODULE, {mirroring, Sup, Group}, [{timeout, infinity}]). + ?MODULE, {mirroring, Sup, Group, ChildSpecs, Notify}, + [{timeout, infinity}]). %%---------------------------------------------------------------------------- -init({overall, SupName, Group, Mod, Args}) -> - Delegate = {delegate, {?SUPERVISOR, start_link, [Mod, Args]}, +init({overall, SupName, Group, Mod, Args, Notify}) -> + {ok, {Restart, ChildSpecs}} = Mod:init(Args), + Delegate = {delegate, {?SUPERVISOR, start_link, + [?MODULE, {delegate, Restart}]}, transient, 16#ffffffff, supervisor, [?SUPERVISOR]}, - Mirroring = {mirroring, {?MODULE, start_internal, [SupName, Group]}, + Mirroring = {mirroring, {?MODULE, start_internal, + [SupName, Group, ChildSpecs, Notify]}, transient, 16#ffffffff, worker, [?MODULE]}, {ok, {{one_for_all, 0, 1}, [Delegate, Mirroring]}}; -init({mirroring, Sup, Group}) -> +init({delegate, Restart}) -> + {ok, {Restart, []}}; + +init({mirroring, Sup, Group, ChildSpecs, Notify}) -> pg2_fixed:create(Group), [begin gen_server2:call(Pid, {hello, self()}, infinity), @@ -105,14 +116,12 @@ init({mirroring, Sup, Group}) -> end || Pid <- pg2_fixed:get_members(Group)], ok = pg2_fixed:join(Group, self()), + ?GEN_SERVER:cast(self(), {start_initial_children, ChildSpecs, Notify}), {ok, #state{overall = Sup, group = Group}}. handle_call({start_child, ChildSpec}, _From, State = #state{overall = Overall}) -> - {reply, case mnesia:transaction(fun() -> check_start(ChildSpec) end) of - {atomic, start} -> start(Overall, ChildSpec); - {atomic, Pid} -> {ok, Pid} - end, State}; + {reply, maybe_start(Overall, ChildSpec), State}; handle_call({delete_child, Id}, _From, State = #state{overall = Overall}) -> @@ -132,6 +141,12 @@ handle_call(overall_supervisor, _From, State = #state{overall = Sup}) -> handle_call(Msg, _From, State) -> {stop, {unexpected_call, Msg}, State}. +handle_cast({start_initial_children, ChildSpecs, Notify}, + State = #state{overall = Overall}) -> + [maybe_start(Overall, S) || S <- ChildSpecs], + Notify ! started, + {noreply, State}; + handle_cast(Msg, State) -> {stop, {unexpected_cast, Msg}, State}. @@ -160,6 +175,11 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. %%---------------------------------------------------------------------------- +maybe_start(Overall, ChildSpec) -> + case mnesia:transaction(fun() -> check_start(ChildSpec) end) of + {atomic, start} -> start(Overall, ChildSpec); + {atomic, Pid} -> {ok, Pid} + end. check_start(ChildSpec) -> case mnesia:wread({?TABLE, id(ChildSpec)}) of diff --git a/src/mirrored_supervisor_tests.erl b/src/mirrored_supervisor_tests.erl index 7f69fb45d8..5a587df463 100644 --- a/src/mirrored_supervisor_tests.erl +++ b/src/mirrored_supervisor_tests.erl @@ -34,6 +34,7 @@ all_tests() -> passed = test_already_there(), passed = test_delete_restart(), passed = test_large_group(), + passed = test_childspecs_at_init(), passed. %% Simplest test @@ -91,6 +92,16 @@ test_large_group() -> false = (Pid1 =:= Pid2) end, [a, b, c, d]). +%% Do childspecs work when returned from init? +test_childspecs_at_init() -> + S = childspec(worker), + with_sups(fun([A, _]) -> + Pid1 = pid_of(worker), + kill(A), + Pid2 = pid_of(worker), + false = (Pid1 =:= Pid2) + end, [{a, [S]}, {b, [S]}]). + %% --------------------------------------------------------------------------- with_sups(Fun, Sups) -> @@ -99,16 +110,19 @@ with_sups(Fun, Sups) -> [kill(Pid) || Pid <- Pids, is_process_alive(Pid)], passed. -start_sup(Name) -> - start_sup(Name, group). +start_sup(Spec) -> + start_sup(Spec, group). -start_sup(Name, Group) -> +start_sup({Name, ChildSpecs}, Group) -> {ok, Pid} = mirrored_supervisor:start_link({local, Name}, Group, - ?MODULE, []), + ?MODULE, ChildSpecs), %% We are not a supervisor, when we kill the supervisor we do not %% want to die! unlink(Pid), - {ok, Pid}. + {ok, Pid}; + +start_sup(Name, Group) -> + start_sup({Name, []}, Group). childspec(Id) -> {Id, {?MODULE, start_gs, [Id]}, transient, 16#ffffffff, worker, [?MODULE]}. |
