summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Watson <tim@rabbitmq.com>2012-10-26 10:30:59 +0100
committerTim Watson <tim@rabbitmq.com>2012-10-26 10:30:59 +0100
commit76c7c19899830fb2ff9bfc8d54f5ed389e30caba (patch)
treea9af9f217745085e122e065dd0108243750e915e
parent338ae4dc6e821b2211c5840458c7022439841248 (diff)
downloadrabbitmq-server-git-76c7c19899830fb2ff9bfc8d54f5ed389e30caba.tar.gz
re-order things a bit and pretend use_specs doesn't exist for now - closer diff with otp supervisor
-rw-r--r--src/supervisor2.erl209
1 files changed, 94 insertions, 115 deletions
diff --git a/src/supervisor2.erl b/src/supervisor2.erl
index a4e21e47e2..99c41aa692 100644
--- a/src/supervisor2.erl
+++ b/src/supervisor2.erl
@@ -86,44 +86,11 @@
-export([handle_cast/2]).
%%--------------------------------------------------------------------------
-%% Records - here we differ from supervisor.erl in that we do not
-%% embed type specifications directly in our records, so that -D use_specs
-%% can be used to turn this off for older versions of Erlang
-%%--------------------------------------------------------------------------
-
--record(child, {pid = undefined, % pid is undefined when child is not running
- name,
- mfa,
- restart_type,
- shutdown,
- child_type,
- modules = []}).
--define(DICT, dict).
-
--record(state, {name,
- strategy,
- children = [],
- dynamics = ?DICT:new(),
- intensity,
- period,
- restarts = [],
- module,
- args}).
+-export_type([child_spec/0, startchild_ret/0, strategy/0]).
--define(is_simple(State), State#state.strategy =:= simple_one_for_one orelse
- State#state.strategy =:= simple_one_for_one_terminate).
--define(is_terminate_simple(State),
- State#state.strategy =:= simple_one_for_one_terminate).
-
--ifdef(use_specs).
-
-%%--------------------------------------------------------------------------
-%% Types
%%--------------------------------------------------------------------------
--export_type([child_spec/0, startchild_ret/0, strategy/0, sup_name/0]).
-
-type child() :: 'undefined' | pid().
-type child_id() :: term().
-type mfargs() :: {M :: module(), F :: atom(), A :: [term()] | undefined}.
@@ -146,11 +113,19 @@
Type :: worker(),
Modules :: modules()}.
-
-type strategy() :: 'one_for_all' | 'one_for_one'
| 'rest_for_one' | 'simple_one_for_one'
| 'simple_one_for_one_terminate'.
+%%--------------------------------------------------------------------------
+
+-record(child, {pid = undefined, % pid is undefined when child is not running
+ name,
+ mfa,
+ restart_type,
+ shutdown,
+ child_type,
+ modules = []}).
-type child_rec() :: #child{pid :: child() | {restarting,pid()} | [pid()],
name :: child_id(),
mfa :: mfargs(),
@@ -159,15 +134,28 @@
child_type :: worker(),
modules :: modules()}.
+-define(DICT, dict).
+
+-record(state, {name,
+ strategy,
+ children = [],
+ dynamics = ?DICT:new(),
+ intensity,
+ period,
+ restarts = [],
+ module,
+ args}).
-type state() :: #state{strategy :: strategy(),
children :: [child_rec()],
dynamics :: ?DICT(),
intensity :: non_neg_integer(),
period :: pos_integer()}.
-%%--------------------------------------------------------------------------
-%% Callback behaviour
-%%--------------------------------------------------------------------------
+-define(is_simple(State), State#state.strategy =:= simple_one_for_one orelse
+ State#state.strategy =:= simple_one_for_one_terminate).
+
+-define(is_terminate_simple(State),
+ State#state.strategy =:= simple_one_for_one_terminate).
-callback init(Args :: term()) ->
{ok, {{RestartStrategy :: strategy(),
@@ -176,9 +164,21 @@
[ChildSpec :: child_spec()]}}
| ignore.
-%%--------------------------------------------------------------------------
-%% Specs
-%%--------------------------------------------------------------------------
+%%% ---------------------------------------------------
+%%% This is a general process supervisor built upon gen_server.erl.
+%%% Servers/processes should/could also be built using gen_server.erl.
+%%% SupName = {local, atom()} | {global, atom()}.
+%%% ---------------------------------------------------
+
+start_link(Mod, Args) ->
+ gen_server:start_link(?MODULE, {self, Mod, Args}, []).
+
+start_link(SupName, Mod, Args) ->
+ gen_server:start_link(SupName, ?MODULE, {SupName, Mod, Args}, []).
+
+%%% ---------------------------------------------------
+%%% Interface functions.
+%%% ---------------------------------------------------
-type startchild_err() :: 'already_present'
| {'already_started', Child :: child()} | term().
@@ -189,6 +189,8 @@
-spec start_child(SupRef, ChildSpec) -> startchild_ret() when
SupRef :: sup_ref(),
ChildSpec :: child_spec() | (List :: [term()]).
+start_child(Supervisor, ChildSpec) ->
+ call(Supervisor, {start_child, ChildSpec}).
-spec restart_child(SupRef, Id) -> Result when
SupRef :: sup_ref(),
@@ -197,18 +199,32 @@
| {'ok', Child :: child(), Info :: term()}
| {'error', Error},
Error :: 'running' | 'not_found' | 'simple_one_for_one' | term().
+restart_child(Supervisor, Name) ->
+ call(Supervisor, {restart_child, Name}).
-spec delete_child(SupRef, Id) -> Result when
SupRef :: sup_ref(),
Id :: child_id(),
Result :: 'ok' | {'error', Error},
Error :: 'running' | 'not_found' | 'simple_one_for_one'.
+delete_child(Supervisor, Name) ->
+ call(Supervisor, {delete_child, Name}).
+
+%%-----------------------------------------------------------------
+%% Func: terminate_child/2
+%% Returns: ok | {error, Reason}
+%% Note that the child is *always* terminated in some
+%% way (maybe killed).
+%%-----------------------------------------------------------------
-spec terminate_child(SupRef, Id) -> Result when
SupRef :: sup_ref(),
+
Id :: pid() | child_id(),
Result :: 'ok' | {'error', Error},
Error :: 'not_found' | 'simple_one_for_one'.
+terminate_child(Supervisor, Name) ->
+ call(Supervisor, {terminate_child, Name}).
-spec which_children(SupRef) -> [{Id,Child,Type,Modules}] when
SupRef :: sup_ref(),
@@ -216,86 +232,16 @@
Child :: child(),
Type :: worker(),
Modules :: modules().
-
--spec check_childspecs(ChildSpecs) -> Result when
- ChildSpecs :: [child_spec()],
- Result :: 'ok' | {'error', Error :: term()}.
-
--type init_sup_name() :: sup_name() | 'self'.
-
--type stop_rsn() :: 'shutdown' | {'bad_return', {module(),'init', term()}}
- | {'bad_start_spec', term()} | {'start_spec', term()}
- | {'supervisor_data', term()}.
-
--spec init({init_sup_name(), module(), [term()]}) ->
- {'ok', state()} | 'ignore' | {'stop', stop_rsn()}.
-
--type call() :: 'which_children'.
--spec handle_call(call(), term(), state()) -> {'reply', term(), state()}.
-
--spec handle_cast('null', state()) -> {'noreply', state()}.
-
--spec handle_info(term(), state()) ->
- {'noreply', state()} | {'stop', 'shutdown', state()}.
-
--spec terminate(term(), state()) -> 'ok'.
-
--spec code_change(term(), state(), term()) ->
- {'ok', state()} | {'error', term()}.
-
--else.
-
--export([behaviour_info/1]).
-
-behaviour_info(callbacks) ->
- [{init,1}];
-behaviour_info(_Other) ->
- undefined.
-
--endif.
-
-%%% ---------------------------------------------------
-%%% This is a general process supervisor built upon gen_server.erl.
-%%% Servers/processes should/could also be built using gen_server.erl.
-%%% SupName = {local, atom()} | {global, atom()}.
-%%% ---------------------------------------------------
-start_link(Mod, Args) ->
- gen_server:start_link(?MODULE, {self, Mod, Args}, []).
-
-start_link(SupName, Mod, Args) ->
- gen_server:start_link(SupName, ?MODULE, {SupName, Mod, Args}, []).
-
-%%% ---------------------------------------------------
-%%% Interface functions.
-%%% ---------------------------------------------------
-start_child(Supervisor, ChildSpec) ->
- call(Supervisor, {start_child, ChildSpec}).
-
-restart_child(Supervisor, Name) ->
- call(Supervisor, {restart_child, Name}).
-
-delete_child(Supervisor, Name) ->
- call(Supervisor, {delete_child, Name}).
-
-%%-----------------------------------------------------------------
-%% Func: terminate_child/2
-%% Returns: ok | {error, Reason}
-%% Note that the child is *always* terminated in some
-%% way (maybe killed).
-%%-----------------------------------------------------------------
-terminate_child(Supervisor, Name) ->
- call(Supervisor, {terminate_child, Name}).
-
which_children(Supervisor) ->
call(Supervisor, which_children).
-find_child(Supervisor, Name) ->
- [Pid || {Name1, Pid, _Type, _Modules} <- which_children(Supervisor),
- Name1 =:= Name].
-
call(Supervisor, Req) ->
gen_server:call(Supervisor, Req, infinity).
+-spec check_childspecs(ChildSpecs) -> Result when
+ ChildSpecs :: [child_spec()],
+ Result :: 'ok' | {'error', Error :: term()}.
+
check_childspecs(ChildSpecs) when is_list(ChildSpecs) ->
case check_startspec(ChildSpecs) of
{ok, _} -> ok;
@@ -303,11 +249,32 @@ check_childspecs(ChildSpecs) when is_list(ChildSpecs) ->
end;
check_childspecs(X) -> {error, {badarg, X}}.
+find_child(Supervisor, Name) ->
+ [Pid || {Name1, Pid, _Type, _Modules} <- which_children(Supervisor),
+ Name1 =:= Name].
+
+%-export([behaviour_info/1]).
+
+%behaviour_info(callbacks) ->
+% [{init,1}];
+%behaviour_info(_Other) ->
+% undefined.
+
%%% ---------------------------------------------------
%%%
%%% Initialize the supervisor.
%%%
%%% ---------------------------------------------------
+
+-type init_sup_name() :: sup_name() | 'self'.
+
+-type stop_rsn() :: 'shutdown' | {'bad_return', {module(),'init', term()}}
+ | {'bad_start_spec', term()} | {'start_spec', term()}
+ | {'supervisor_data', term()}.
+
+-spec init({init_sup_name(), module(), [term()]}) ->
+ {'ok', state()} | 'ignore' | {'stop', stop_rsn()}.
+
init({SupName, Mod, Args}) ->
process_flag(trap_exit, true),
case Mod:init(Args) of
@@ -413,6 +380,9 @@ do_start_child_i(M, F, A) ->
%%% Callback functions.
%%%
%%% ---------------------------------------------------
+-type call() :: 'which_children'.
+-spec handle_call(call(), term(), state()) -> {'reply', term(), state()}.
+
handle_call({start_child, EArgs}, _From, State) when ?is_simple(State) ->
#child{mfa = {M, F, A}} = hd(State#state.children),
Args = A ++ EArgs,
@@ -500,6 +470,7 @@ handle_call(which_children, _From, State) ->
State#state.children),
{reply, Resp, State}.
+-spec handle_cast('null', state()) -> {'noreply', state()}.
%%% Hopefully cause a function-clause as there is no API function
%%% that utilizes cast.
handle_cast(null, State) ->
@@ -508,6 +479,9 @@ handle_cast(null, State) ->
{noreply, State}.
+-spec handle_info(term(), state()) ->
+ {'noreply', state()} | {'stop', 'shutdown', state()}.
+
handle_info({delayed_restart, {RestartType, Reason, Child}}, State)
when ?is_simple(State) ->
{ok, NState} = do_restart(RestartType, Reason, Child, State),
@@ -539,6 +513,8 @@ handle_info(Msg, State) ->
%%
%% Terminate this server.
%%
+-spec terminate(term(), state()) -> 'ok'.
+
terminate(_Reason, State) when ?is_terminate_simple(State) ->
terminate_simple_children(
hd(State#state.children), State#state.dynamics, State#state.name),
@@ -556,6 +532,9 @@ terminate(_Reason, State) ->
%% NOTE: This requires that the init function of the call-back module
%% does not have any side effects.
%%
+-spec code_change(term(), state(), term()) ->
+ {'ok', state()} | {'error', term()}.
+
code_change(_, State, _) ->
case (State#state.module):init(State#state.args) of
{ok, {SupFlags, StartSpec}} ->