diff options
author | Simon MacMullen <simon@rabbitmq.com> | 2012-04-17 12:32:11 +0100 |
---|---|---|
committer | Simon MacMullen <simon@rabbitmq.com> | 2012-04-17 12:32:11 +0100 |
commit | 690b4035e81a546cc20fe240fdb9192cf0f2175c (patch) | |
tree | faaa1b4b793cb604e7077bc717dce9852ba6efdd /src | |
parent | 17e3aba9d96b99b8ec394fa10378f937e0a98da0 (diff) | |
parent | 44dfd96de05e3e1df655093502e0fe6f8e38dbfd (diff) | |
download | rabbitmq-server-690b4035e81a546cc20fe240fdb9192cf0f2175c.tar.gz |
Merge bug 24871 (as foretold in prophecy^W bug 20337 comment 199)
Diffstat (limited to 'src')
-rw-r--r-- | src/gen_server2.erl | 65 | ||||
-rw-r--r-- | src/gm.erl | 103 | ||||
-rw-r--r-- | src/mirrored_supervisor.erl | 76 | ||||
-rw-r--r-- | src/rabbit_auth_backend.erl | 83 | ||||
-rw-r--r-- | src/rabbit_auth_backend_internal.erl | 2 | ||||
-rw-r--r-- | src/rabbit_auth_mechanism.erl | 56 | ||||
-rw-r--r-- | src/rabbit_auth_mechanism_amqplain.erl | 2 | ||||
-rw-r--r-- | src/rabbit_auth_mechanism_cr_demo.erl | 2 | ||||
-rw-r--r-- | src/rabbit_auth_mechanism_plain.erl | 2 | ||||
-rw-r--r-- | src/rabbit_backing_queue.erl | 348 | ||||
-rw-r--r-- | src/rabbit_exchange_type.erl | 66 | ||||
-rw-r--r-- | src/rabbit_exchange_type_direct.erl | 1 | ||||
-rw-r--r-- | src/rabbit_exchange_type_fanout.erl | 1 | ||||
-rw-r--r-- | src/rabbit_exchange_type_headers.erl | 1 | ||||
-rw-r--r-- | src/rabbit_exchange_type_invalid.erl | 1 | ||||
-rw-r--r-- | src/rabbit_exchange_type_topic.erl | 1 | ||||
-rw-r--r-- | src/rabbit_mirror_queue_master.erl | 4 | ||||
-rw-r--r-- | src/rabbit_msg_store_ets_index.erl | 4 | ||||
-rw-r--r-- | src/rabbit_msg_store_index.erl | 27 | ||||
-rw-r--r-- | src/rabbit_variable_queue.erl | 4 | ||||
-rw-r--r-- | src/supervisor2.erl | 135 |
21 files changed, 611 insertions, 373 deletions
diff --git a/src/gen_server2.erl b/src/gen_server2.erl index f8537487..78bbbe06 100644 --- a/src/gen_server2.erl +++ b/src/gen_server2.erl @@ -31,13 +31,13 @@ %% handle_pre_hibernate/1 then the default action is to hibernate. %% %% 6) init can return a 4th arg, {backoff, InitialTimeout, -%% MinimumTimeout, DesiredHibernatePeriod} (all in -%% milliseconds). Then, on all callbacks which can return a timeout -%% (including init), timeout can be 'hibernate'. When this is the -%% case, the current timeout value will be used (initially, the -%% InitialTimeout supplied from init). After this timeout has -%% occurred, hibernation will occur as normal. Upon awaking, a new -%% current timeout value will be calculated. +%% MinimumTimeout, DesiredHibernatePeriod} (all in milliseconds, +%% 'infinity' does not make sense here). Then, on all callbacks which +%% can return a timeout (including init), timeout can be +%% 'hibernate'. When this is the case, the current timeout value will +%% be used (initially, the InitialTimeout supplied from init). After +%% this timeout has occurred, hibernation will occur as normal. Upon +%% awaking, a new current timeout value will be calculated. %% %% The purpose is that the gen_server2 takes care of adjusting the %% current timeout value such that the process will increase the @@ -135,9 +135,10 @@ %%% Reason = normal | shutdown | Term, terminate(State) is called %%% %%% terminate(Reason, State) Let the user module clean up +%%% Reason = normal | shutdown | {shutdown, Term} | Term %%% always called when server terminates %%% -%%% ==> ok +%%% ==> ok | Term %%% %%% handle_pre_hibernate(State) %%% @@ -182,8 +183,6 @@ multi_call/2, multi_call/3, multi_call/4, enter_loop/3, enter_loop/4, enter_loop/5, enter_loop/6, wake_hib/1]). --export([behaviour_info/1]). - %% System exports -export([system_continue/3, system_terminate/4, @@ -200,12 +199,12 @@ timeout_state, queue, debug, prioritise_call, prioritise_cast, prioritise_info}). +-ifdef(use_specs). + %%%========================================================================= %%% Specs. These exist only to shut up dialyzer's warnings %%%========================================================================= --ifdef(use_specs). - -type(gs2_state() :: #gs2_state{}). -spec(handle_common_termination/3 :: @@ -214,18 +213,58 @@ -spec(pre_hibernate/1 :: (gs2_state()) -> no_return()). -spec(system_terminate/4 :: (_, _, _, gs2_state()) -> no_return()). --endif. +-type(millis() :: non_neg_integer()). %%%========================================================================= %%% API %%%========================================================================= +-callback init(Args :: term()) -> + {ok, State :: term()} | + {ok, State :: term(), timeout() | hibernate} | + {ok, State :: term(), timeout() | hibernate, + {backoff, millis(), millis(), millis()}} | + ignore | + {stop, Reason :: term()}. +-callback handle_call(Request :: term(), From :: {pid(), Tag :: term()}, + State :: term()) -> + {reply, Reply :: term(), NewState :: term()} | + {reply, Reply :: term(), NewState :: term(), timeout() | hibernate} | + {noreply, NewState :: term()} | + {noreply, NewState :: term(), timeout() | hibernate} | + {stop, Reason :: term(), + Reply :: term(), NewState :: term()}. +-callback handle_cast(Request :: term(), State :: term()) -> + {noreply, NewState :: term()} | + {noreply, NewState :: term(), timeout() | hibernate} | + {stop, Reason :: term(), NewState :: term()}. +-callback handle_info(Info :: term(), State :: term()) -> + {noreply, NewState :: term()} | + {noreply, NewState :: term(), timeout() | hibernate} | + {stop, Reason :: term(), NewState :: term()}. +-callback terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()), + State :: term()) -> + ok | term(). +-callback code_change(OldVsn :: (term() | {down, term()}), State :: term(), + Extra :: term()) -> + {ok, NewState :: term()} | {error, Reason :: term()}. + +%% It's not possible to define "optional" -callbacks, so putting specs +%% for handle_pre_hibernate/1 and handle_post_hibernate/1 will result +%% in warnings (the same applied for the behaviour_info before). + +-else. + +-export([behaviour_info/1]). + behaviour_info(callbacks) -> [{init,1},{handle_call,3},{handle_cast,2},{handle_info,2}, {terminate,2},{code_change,3}]; behaviour_info(_Other) -> undefined. +-endif. + %%% ----------------------------------------------------------------- %%% Starts a generic server. %%% start(Mod, Args, Options) @@ -57,8 +57,8 @@ %% you wish to be passed into the callback module's functions. The %% joined/2 function will be called when we have joined the group, %% with the arguments passed to start_link and a list of the current -%% members of the group. See the comments in behaviour_info/1 below -%% for further details of the callback functions. +%% members of the group. See the callbacks specs and the comments +%% below for further details of the callback functions. %% %% leave/1 %% Provide the Pid. Removes the Pid from the group. The callback @@ -378,7 +378,9 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, prioritise_info/2]). +-ifndef(use_specs). -export([behaviour_info/1]). +-endif. -export([table_definitions/0]). @@ -431,56 +433,63 @@ -spec(confirmed_broadcast/2 :: (pid(), any()) -> 'ok'). -spec(group_members/1 :: (pid()) -> [pid()]). --endif. +%% The joined, members_changed and handle_msg callbacks can all +%% return any of the following terms: +%% +%% 'ok' - the callback function returns normally +%% +%% {'stop', Reason} - the callback indicates the member should +%% stop with reason Reason and should leave the group. +%% +%% {'become', Module, Args} - the callback indicates that the +%% callback module should be changed to Module and that the +%% callback functions should now be passed the arguments +%% Args. This allows the callback module to be dynamically +%% changed. + +%% Called when we've successfully joined the group. Supplied with +%% Args provided in start_link, plus current group members. +-callback joined(Args :: term(), Members :: [pid()]) -> + ok | {stop, Reason :: term()} | {become, Module :: atom(), Args :: any()}. + +%% Supplied with Args provided in start_link, the list of new +%% members and the list of members previously known to us that +%% have since died. Note that if a member joins and dies very +%% quickly, it's possible that we will never see that member +%% appear in either births or deaths. However we are guaranteed +%% that (1) we will see a member joining either in the births +%% here, or in the members passed to joined/2 before receiving +%% any messages from it; and (2) we will not see members die that +%% we have not seen born (or supplied in the members to +%% joined/2). +-callback members_changed(Args :: term(), Births :: [pid()], + Deaths :: [pid()]) -> + ok | {stop, Reason :: term()} | {become, Module :: atom(), Args :: any()}. + +%% Supplied with Args provided in start_link, the sender, and the +%% message. This does get called for messages injected by this +%% member, however, in such cases, there is no special +%% significance of this invocation: it does not indicate that the +%% message has made it to any other members, let alone all other +%% members. +-callback handle_msg(Args :: term(), From :: pid(), Message :: term()) -> + ok | {stop, Reason :: term()} | {become, Module :: atom(), Args :: any()}. + +%% Called on gm member termination as per rules in gen_server, +%% with the Args provided in start_link plus the termination +%% Reason. +-callback terminate(Args :: term(), Reason :: term()) -> + ok | term(). + +-else. behaviour_info(callbacks) -> - [ - %% The joined, members_changed and handle_msg callbacks can all - %% return any of the following terms: - %% - %% 'ok' - the callback function returns normally - %% - %% {'stop', Reason} - the callback indicates the member should - %% stop with reason Reason and should leave the group. - %% - %% {'become', Module, Args} - the callback indicates that the - %% callback module should be changed to Module and that the - %% callback functions should now be passed the arguments - %% Args. This allows the callback module to be dynamically - %% changed. - - %% Called when we've successfully joined the group. Supplied with - %% Args provided in start_link, plus current group members. - {joined, 2}, - - %% Supplied with Args provided in start_link, the list of new - %% members and the list of members previously known to us that - %% have since died. Note that if a member joins and dies very - %% quickly, it's possible that we will never see that member - %% appear in either births or deaths. However we are guaranteed - %% that (1) we will see a member joining either in the births - %% here, or in the members passed to joined/2 before receiving - %% any messages from it; and (2) we will not see members die that - %% we have not seen born (or supplied in the members to - %% joined/2). - {members_changed, 3}, - - %% Supplied with Args provided in start_link, the sender, and the - %% message. This does get called for messages injected by this - %% member, however, in such cases, there is no special - %% significance of this invocation: it does not indicate that the - %% message has made it to any other members, let alone all other - %% members. - {handle_msg, 3}, - - %% Called on gm member termination as per rules in gen_server, - %% with the Args provided in start_link plus the termination - %% Reason. - {terminate, 2} - ]; + [{joined, 2}, {members_changed, 3}, {handle_msg, 3}, {terminate, 2}]; behaviour_info(_Other) -> undefined. +-endif. + create_tables() -> create_tables([?TABLE]). diff --git a/src/mirrored_supervisor.erl b/src/mirrored_supervisor.erl index a599effa..221f6a87 100644 --- a/src/mirrored_supervisor.erl +++ b/src/mirrored_supervisor.erl @@ -120,8 +120,6 @@ delete_child/2, terminate_child/2, which_children/1, count_children/1, check_childspecs/1]). --export([behaviour_info/1]). - -behaviour(?GEN_SERVER). -behaviour(?SUPERVISOR). @@ -142,15 +140,20 @@ -ifdef(use_specs). --type child() :: pid() | 'undefined'. --type child_id() :: term(). --type modules() :: [module()] | 'dynamic'. --type worker() :: 'worker' | 'supervisor'. --type sup_name() :: {'local', Name :: atom()} | {'global', Name :: atom()}. --type sup_ref() :: (Name :: atom()) - | {Name :: atom(), Node :: node()} - | {'global', Name :: atom()} - | pid(). +%%-------------------------------------------------------------------------- +%% Callback behaviour +%%-------------------------------------------------------------------------- + +-callback init(Args :: term()) -> + {ok, {{RestartStrategy :: supervisor2:strategy(), + MaxR :: non_neg_integer(), + MaxT :: non_neg_integer()}, + [ChildSpec :: supervisor2:child_spec()]}} + | ignore. + +%%-------------------------------------------------------------------------- +%% Specs +%%-------------------------------------------------------------------------- -type startlink_err() :: {'already_started', pid()} | 'shutdown' | term(). -type startlink_ret() :: {'ok', pid()} | 'ignore' | {'error', startlink_err()}. @@ -163,54 +166,26 @@ Args :: term(). -spec start_link(SupName, GroupName, Module, Args) -> startlink_ret() when - SupName :: sup_name(), + SupName :: supervisor2:sup_name(), GroupName :: group_name(), Module :: module(), Args :: term(). --spec start_child(SupRef, ChildSpec) -> supervisor:startchild_ret() when - SupRef :: sup_ref(), - ChildSpec :: supervisor:child_spec() | (List :: [term()]). - --spec restart_child(SupRef, Id) -> Result when - SupRef :: sup_ref(), - Id :: child_id(), - Result :: {'ok', Child :: child()} - | {'ok', Child :: child(), Info :: term()} - | {'error', Error}, - Error :: 'running' | 'not_found' | 'simple_one_for_one' | term(). - --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'. - --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'. - --spec which_children(SupRef) -> [{Id,Child,Type,Modules}] when - SupRef :: sup_ref(), - Id :: child_id() | 'undefined', - Child :: child(), - Type :: worker(), - Modules :: modules(). - --spec check_childspecs(ChildSpecs) -> Result when - ChildSpecs :: [supervisor:child_spec()], - Result :: 'ok' | {'error', Error :: term()}. - -spec start_internal(Group, ChildSpecs) -> Result when Group :: group_name(), - ChildSpecs :: [supervisor:child_spec()], - Result :: startlink_ret(). + ChildSpecs :: [supervisor2:child_spec()], + Result :: supervisor2:startlink_ret(). -spec create_tables() -> Result when Result :: 'ok'. +-else. + +-export([behaviour_info/1]). + +behaviour_info(callbacks) -> [{init,1}]; +behaviour_info(_Other) -> undefined. + -endif. %%---------------------------------------------------------------------------- @@ -250,9 +225,6 @@ which_children(Sup) -> fold(which_children, Sup, fun lists:append/2). count_children(Sup) -> fold(count_children, Sup, fun add_proplists/2). check_childspecs(Specs) -> ?SUPERVISOR:check_childspecs(Specs). -behaviour_info(callbacks) -> [{init,1}]; -behaviour_info(_Other) -> undefined. - call(Sup, Msg) -> ?GEN_SERVER:call(child(Sup, mirroring), Msg, infinity). diff --git a/src/rabbit_auth_backend.erl b/src/rabbit_auth_backend.erl index e0e252b8..e89951e7 100644 --- a/src/rabbit_auth_backend.erl +++ b/src/rabbit_auth_backend.erl @@ -16,42 +16,57 @@ -module(rabbit_auth_backend). +-ifdef(use_specs). + +%% A description proplist as with auth mechanisms, +%% exchanges. Currently unused. +-callback description() -> [proplist:property()]. + +%% Check a user can log in, given a username and a proplist of +%% authentication information (e.g. [{password, Password}]). +%% +%% Possible responses: +%% {ok, User} +%% Authentication succeeded, and here's the user record. +%% {error, Error} +%% Something went wrong. Log and die. +%% {refused, Msg, Args} +%% Client failed authentication. Log and die. +-callback check_user_login(rabbit_types:username(), [term()]) -> + {'ok', rabbit_types:user()} | + {'refused', string(), [any()]} | + {'error', any()}. + +%% Given #user and vhost, can a user log in to a vhost? +%% Possible responses: +%% true +%% false +%% {error, Error} +%% Something went wrong. Log and die. +-callback check_vhost_access(rabbit_types:user(), rabbit_types:vhost()) -> + boolean() | {'error', any()}. + + +%% Given #user, resource and permission, can a user access a resource? +%% +%% Possible responses: +%% true +%% false +%% {error, Error} +%% Something went wrong. Log and die. +-callback check_resource_access(rabbit_types:user(), + rabbit_types:r(atom()), + rabbit_access_control:permission_atom()) -> + boolean() | {'error', any()}. + +-else. + -export([behaviour_info/1]). behaviour_info(callbacks) -> - [ - %% A description proplist as with auth mechanisms, - %% exchanges. Currently unused. - {description, 0}, - - %% Check a user can log in, given a username and a proplist of - %% authentication information (e.g. [{password, Password}]). - %% - %% Possible responses: - %% {ok, User} - %% Authentication succeeded, and here's the user record. - %% {error, Error} - %% Something went wrong. Log and die. - %% {refused, Msg, Args} - %% Client failed authentication. Log and die. - {check_user_login, 2}, - - %% Given #user and vhost, can a user log in to a vhost? - %% Possible responses: - %% true - %% false - %% {error, Error} - %% Something went wrong. Log and die. - {check_vhost_access, 2}, - - %% Given #user, resource and permission, can a user access a resource? - %% - %% Possible responses: - %% true - %% false - %% {error, Error} - %% Something went wrong. Log and die. - {check_resource_access, 3} - ]; + [{description, 0}, {check_user_login, 2}, {check_vhost_access, 2}, + {check_resource_access, 3}]; behaviour_info(_Other) -> undefined. + +-endif. diff --git a/src/rabbit_auth_backend_internal.erl b/src/rabbit_auth_backend_internal.erl index 3ef81d32..7b9df81e 100644 --- a/src/rabbit_auth_backend_internal.erl +++ b/src/rabbit_auth_backend_internal.erl @@ -32,8 +32,6 @@ vhost_perms_info_keys/0, user_perms_info_keys/0, user_vhost_perms_info_keys/0]). --include("rabbit_auth_backend_spec.hrl"). - -ifdef(use_specs). -type(regexp() :: binary()). diff --git a/src/rabbit_auth_mechanism.erl b/src/rabbit_auth_mechanism.erl index 0c8251b8..eda6a743 100644 --- a/src/rabbit_auth_mechanism.erl +++ b/src/rabbit_auth_mechanism.erl @@ -16,31 +16,41 @@ -module(rabbit_auth_mechanism). +-ifdef(use_specs). + +%% A description. +-callback description() -> [proplist:property()]. + +%% If this mechanism is enabled, should it be offered for a given socket? +%% (primarily so EXTERNAL can be SSL-only) +-callback should_offer(rabbit_net:socket()) -> boolean(). + +%% Called before authentication starts. Should create a state +%% object to be passed through all the stages of authentication. +-callback init(rabbit_net:socket()) -> any(). + +%% Handle a stage of authentication. Possible responses: +%% {ok, User} +%% Authentication succeeded, and here's the user record. +%% {challenge, Challenge, NextState} +%% Another round is needed. Here's the state I want next time. +%% {protocol_error, Msg, Args} +%% Client got the protocol wrong. Log and die. +%% {refused, Msg, Args} +%% Client failed authentication. Log and die. +-callback handle_response(binary(), any()) -> + {'ok', rabbit_types:user()} | + {'challenge', binary(), any()} | + {'protocol_error', string(), [any()]} | + {'refused', string(), [any()]}. + +-else. + -export([behaviour_info/1]). behaviour_info(callbacks) -> - [ - %% A description. - {description, 0}, - - %% If this mechanism is enabled, should it be offered for a given socket? - %% (primarily so EXTERNAL can be SSL-only) - {should_offer, 1}, - - %% Called before authentication starts. Should create a state - %% object to be passed through all the stages of authentication. - {init, 1}, - - %% Handle a stage of authentication. Possible responses: - %% {ok, User} - %% Authentication succeeded, and here's the user record. - %% {challenge, Challenge, NextState} - %% Another round is needed. Here's the state I want next time. - %% {protocol_error, Msg, Args} - %% Client got the protocol wrong. Log and die. - %% {refused, Msg, Args} - %% Client failed authentication. Log and die. - {handle_response, 2} - ]; + [{description, 0}, {should_offer, 1}, {init, 1}, {handle_response, 2}]; behaviour_info(_Other) -> undefined. + +-endif. diff --git a/src/rabbit_auth_mechanism_amqplain.erl b/src/rabbit_auth_mechanism_amqplain.erl index 3de6e7a6..c0d86cd1 100644 --- a/src/rabbit_auth_mechanism_amqplain.erl +++ b/src/rabbit_auth_mechanism_amqplain.erl @@ -21,8 +21,6 @@ -export([description/0, should_offer/1, init/1, handle_response/2]). --include("rabbit_auth_mechanism_spec.hrl"). - -rabbit_boot_step({?MODULE, [{description, "auth mechanism amqplain"}, {mfa, {rabbit_registry, register, diff --git a/src/rabbit_auth_mechanism_cr_demo.erl b/src/rabbit_auth_mechanism_cr_demo.erl index 64b01d8e..5df1d5d7 100644 --- a/src/rabbit_auth_mechanism_cr_demo.erl +++ b/src/rabbit_auth_mechanism_cr_demo.erl @@ -21,8 +21,6 @@ -export([description/0, should_offer/1, init/1, handle_response/2]). --include("rabbit_auth_mechanism_spec.hrl"). - -rabbit_boot_step({?MODULE, [{description, "auth mechanism cr-demo"}, {mfa, {rabbit_registry, register, diff --git a/src/rabbit_auth_mechanism_plain.erl b/src/rabbit_auth_mechanism_plain.erl index 19fb5875..423170e1 100644 --- a/src/rabbit_auth_mechanism_plain.erl +++ b/src/rabbit_auth_mechanism_plain.erl @@ -21,8 +21,6 @@ -export([description/0, should_offer/1, init/1, handle_response/2]). --include("rabbit_auth_mechanism_spec.hrl"). - -rabbit_boot_step({?MODULE, [{description, "auth mechanism plain"}, {mfa, {rabbit_registry, register, diff --git a/src/rabbit_backing_queue.erl b/src/rabbit_backing_queue.erl index 42627aae..6cc1c3fd 100644 --- a/src/rabbit_backing_queue.erl +++ b/src/rabbit_backing_queue.erl @@ -16,164 +16,200 @@ -module(rabbit_backing_queue). +-ifdef(use_specs). + +%% We can't specify a per-queue ack/state with callback signatures +-type(ack() :: any()). +-type(state() :: any()). + +-type(fetch_result(Ack) :: + ('empty' | + %% Message, IsDelivered, AckTag, Remaining_Len + {rabbit_types:basic_message(), boolean(), Ack, non_neg_integer()})). +-type(is_durable() :: boolean()). +-type(attempt_recovery() :: boolean()). +-type(purged_msg_count() :: non_neg_integer()). +-type(confirm_required() :: boolean()). +-type(async_callback() :: fun ((atom(), fun ((atom(), state()) -> state())) -> 'ok')). +-type(duration() :: ('undefined' | 'infinity' | number())). + +-type(msg_fun() :: fun((rabbit_types:basic_message(), ack()) -> 'ok') | + 'undefined'). + +%% Called on startup with a list of durable queue names. The queues +%% aren't being started at this point, but this call allows the +%% backing queue to perform any checking necessary for the consistency +%% of those queues, or initialise any other shared resources. +-callback start([rabbit_amqqueue:name()]) -> 'ok'. + +%% Called to tear down any state/resources. NB: Implementations should +%% not depend on this function being called on shutdown and instead +%% should hook into the rabbit supervision hierarchy. +-callback stop() -> 'ok'. + +%% Initialise the backing queue and its state. +%% +%% Takes +%% 1. the amqqueue record +%% 2. a boolean indicating whether the queue is an existing queue that +%% should be recovered +%% 3. an asynchronous callback which accepts a function of type +%% backing-queue-state to backing-queue-state. This callback +%% function can be safely invoked from any process, which makes it +%% useful for passing messages back into the backing queue, +%% especially as the backing queue does not have control of its own +%% mailbox. +-callback init(rabbit_types:amqqueue(), attempt_recovery(), + async_callback()) -> state(). + +%% Called on queue shutdown when queue isn't being deleted. +-callback terminate(any(), state()) -> state(). + +%% Called when the queue is terminating and needs to delete all its +%% content. +-callback delete_and_terminate(any(), state()) -> state(). + +%% Remove all messages in the queue, but not messages which have been +%% fetched and are pending acks. +-callback purge(state()) -> {purged_msg_count(), state()}. + +%% Publish a message. +-callback publish(rabbit_types:basic_message(), + rabbit_types:message_properties(), pid(), state()) -> + state(). + +%% Called for messages which have already been passed straight +%% out to a client. The queue will be empty for these calls +%% (i.e. saves the round trip through the backing queue). +-callback publish_delivered(true, rabbit_types:basic_message(), + rabbit_types:message_properties(), pid(), state()) + -> {ack(), state()}; + (false, rabbit_types:basic_message(), + rabbit_types:message_properties(), pid(), state()) + -> {undefined, state()}. + +%% Return ids of messages which have been confirmed since the last +%% invocation of this function (or initialisation). +%% +%% Message ids should only appear in the result of drain_confirmed +%% under the following circumstances: +%% +%% 1. The message appears in a call to publish_delivered/4 and the +%% first argument (ack_required) is false; or +%% 2. The message is fetched from the queue with fetch/2 and the first +%% argument (ack_required) is false; or +%% 3. The message is acked (ack/2 is called for the message); or +%% 4. The message is fully fsync'd to disk in such a way that the +%% recovery of the message is guaranteed in the event of a crash of +%% this rabbit node (excluding hardware failure). +%% +%% In addition to the above conditions, a message id may only appear +%% in the result of drain_confirmed if +%% #message_properties.needs_confirming = true when the msg was +%% published (through whichever means) to the backing queue. +%% +%% It is legal for the same message id to appear in the results of +%% multiple calls to drain_confirmed, which means that the backing +%% queue is not required to keep track of which messages it has +%% already confirmed. The confirm will be issued to the publisher the +%% first time the message id appears in the result of +%% drain_confirmed. All subsequent appearances of that message id will +%% be ignored. +-callback drain_confirmed(state()) -> {[rabbit_guid:guid()], state()}. + +%% Drop messages from the head of the queue while the supplied +%% predicate returns true. A callback function is supplied allowing +%% callers access to messages that are about to be dropped. +-callback dropwhile(fun ((rabbit_types:message_properties()) -> boolean()), msg_fun(), + state()) + -> state(). + +%% Produce the next message. +-callback fetch(true, state()) -> {fetch_result(ack()), state()}; + (false, state()) -> {fetch_result(undefined), state()}. + +%% Acktags supplied are for messages which can now be forgotten +%% about. Must return 1 msg_id per Ack, in the same order as Acks. +-callback ack([ack()], state()) -> {[rabbit_guid:guid()], state()}. + +%% Acktags supplied are for messages which should be processed. The +%% provided callback function is called with each message. +-callback fold(msg_fun(), state(), [ack()]) -> state(). + +%% Reinsert messages into the queue which have already been delivered +%% and were pending acknowledgement. +-callback requeue([ack()], state()) -> {[rabbit_guid:guid()], state()}. + +%% How long is my queue? +-callback len(state()) -> non_neg_integer(). + +%% Is my queue empty? +-callback is_empty(state()) -> boolean(). + +%% For the next three functions, the assumption is that you're +%% monitoring something like the ingress and egress rates of the +%% queue. The RAM duration is thus the length of time represented by +%% the messages held in RAM given the current rates. If you want to +%% ignore all of this stuff, then do so, and return 0 in +%% ram_duration/1. + +%% The target is to have no more messages in RAM than indicated by the +%% duration and the current queue rates. +-callback set_ram_duration_target(duration(), state()) -> state(). + +%% Optionally recalculate the duration internally (likely to be just +%% update your internal rates), and report how many seconds the +%% messages in RAM represent given the current rates of the queue. +-callback ram_duration(state()) -> {duration(), state()}. + +%% Should 'timeout' be called as soon as the queue process can manage +%% (either on an empty mailbox, or when a timer fires)? +-callback needs_timeout(state()) -> 'false' | 'timed' | 'idle'. + +%% Called (eventually) after needs_timeout returns 'idle' or 'timed'. +%% Note this may be called more than once for each 'idle' or 'timed' +%% returned from needs_timeout +-callback timeout(state()) -> state(). + +%% Called immediately before the queue hibernates. +-callback handle_pre_hibernate(state()) -> state(). + +%% Exists for debugging purposes, to be able to expose state via +%% rabbitmqctl list_queues backing_queue_status +-callback status(state()) -> [{atom(), any()}]. + +%% Passed a function to be invoked with the relevant backing queue's +%% state. Useful for when the backing queue or other components need +%% to pass functions into the backing queue. +-callback invoke(atom(), fun ((atom(), A) -> A), state()) -> state(). + +%% Called prior to a publish or publish_delivered call. Allows the BQ +%% to signal that it's already seen this message (and in what capacity +%% - i.e. was it published previously or discarded previously) and +%% thus the message should be dropped. +-callback is_duplicate(rabbit_types:basic_message(), state()) + -> {'false'|'published'|'discarded', state()}. + +%% Called to inform the BQ about messages which have reached the +%% queue, but are not going to be further passed to BQ for some +%% reason. Note that this is may be invoked for messages for which +%% BQ:is_duplicate/2 has already returned {'published' | 'discarded', +%% BQS}. +-callback discard(rabbit_types:basic_message(), pid(), state()) -> state(). + +-else. + -export([behaviour_info/1]). behaviour_info(callbacks) -> - [ - %% Called on startup with a list of durable queue names. The - %% queues aren't being started at this point, but this call - %% allows the backing queue to perform any checking necessary for - %% the consistency of those queues, or initialise any other - %% shared resources. - {start, 1}, - - %% Called to tear down any state/resources. NB: Implementations - %% should not depend on this function being called on shutdown - %% and instead should hook into the rabbit supervision hierarchy. - {stop, 0}, - - %% Initialise the backing queue and its state. - %% - %% Takes - %% 1. the amqqueue record - %% 2. a boolean indicating whether the queue is an existing queue - %% that should be recovered - %% 3. an asynchronous callback which accepts a function of type - %% backing-queue-state to backing-queue-state. This callback - %% function can be safely invoked from any process, which - %% makes it useful for passing messages back into the backing - %% queue, especially as the backing queue does not have - %% control of its own mailbox. - {init, 3}, - - %% Called on queue shutdown when queue isn't being deleted. - {terminate, 2}, - - %% Called when the queue is terminating and needs to delete all - %% its content. - {delete_and_terminate, 2}, - - %% Remove all messages in the queue, but not messages which have - %% been fetched and are pending acks. - {purge, 1}, - - %% Publish a message. - {publish, 4}, - - %% Called for messages which have already been passed straight - %% out to a client. The queue will be empty for these calls - %% (i.e. saves the round trip through the backing queue). - {publish_delivered, 5}, - - %% Return ids of messages which have been confirmed since - %% the last invocation of this function (or initialisation). - %% - %% Message ids should only appear in the result of - %% drain_confirmed under the following circumstances: - %% - %% 1. The message appears in a call to publish_delivered/4 and - %% the first argument (ack_required) is false; or - %% 2. The message is fetched from the queue with fetch/2 and the - %% first argument (ack_required) is false; or - %% 3. The message is acked (ack/2 is called for the message); or - %% 4. The message is fully fsync'd to disk in such a way that the - %% recovery of the message is guaranteed in the event of a - %% crash of this rabbit node (excluding hardware failure). - %% - %% In addition to the above conditions, a message id may only - %% appear in the result of drain_confirmed if - %% #message_properties.needs_confirming = true when the msg was - %% published (through whichever means) to the backing queue. - %% - %% It is legal for the same message id to appear in the results - %% of multiple calls to drain_confirmed, which means that the - %% backing queue is not required to keep track of which messages - %% it has already confirmed. The confirm will be issued to the - %% publisher the first time the message id appears in the result - %% of drain_confirmed. All subsequent appearances of that message - %% id will be ignored. - {drain_confirmed, 1}, - - %% Drop messages from the head of the queue while the supplied - %% predicate returns true. A callback function is supplied - %% allowing callers access to messages that are about to be - %% dropped. - {dropwhile, 3}, - - %% Produce the next message. - {fetch, 2}, - - %% Acktags supplied are for messages which can now be forgotten - %% about. Must return 1 msg_id per Ack, in the same order as - %% Acks. - {ack, 2}, - - %% Acktags supplied are for messages which should be - %% processed. The provided callback function is called with each - %% message. - {fold, 3}, - - %% Reinsert messages into the queue which have already been - %% delivered and were pending acknowledgement. - {requeue, 2}, - - %% How long is my queue? - {len, 1}, - - %% Is my queue empty? - {is_empty, 1}, - - %% For the next three functions, the assumption is that you're - %% monitoring something like the ingress and egress rates of the - %% queue. The RAM duration is thus the length of time represented - %% by the messages held in RAM given the current rates. If you - %% want to ignore all of this stuff, then do so, and return 0 in - %% ram_duration/1. - - %% The target is to have no more messages in RAM than indicated - %% by the duration and the current queue rates. - {set_ram_duration_target, 2}, - - %% Optionally recalculate the duration internally (likely to be - %% just update your internal rates), and report how many seconds - %% the messages in RAM represent given the current rates of the - %% queue. - {ram_duration, 1}, - - %% Should 'timeout' be called as soon as the queue process - %% can manage (either on an empty mailbox, or when a timer - %% fires)? - {needs_timeout, 1}, - - %% Called (eventually) after needs_timeout returns 'idle' or - %% 'timed'. Note this may be called more than once for each - %% 'idle' or 'timed' returned from needs_timeout. - {timeout, 1}, - - %% Called immediately before the queue hibernates. - {handle_pre_hibernate, 1}, - - %% Exists for debugging purposes, to be able to expose state via - %% rabbitmqctl list_queues backing_queue_status - {status, 1}, - - %% Passed a function to be invoked with the relevant backing - %% queue's state. Useful for when the backing queue or other - %% components need to pass functions into the backing queue. - {invoke, 3}, - - %% Called prior to a publish or publish_delivered call. Allows - %% the BQ to signal that it's already seen this message (and in - %% what capacity - i.e. was it published previously or discarded - %% previously) and thus the message should be dropped. - {is_duplicate, 2}, - - %% Called to inform the BQ about messages which have reached the - %% queue, but are not going to be further passed to BQ for some - %% reason. Note that this is may be invoked for messages for - %% which BQ:is_duplicate/2 has already returned {'published' | - %% 'discarded', BQS}. - {discard, 3} - ]; + [{start, 1}, {stop, 0}, {init, 3}, {terminate, 2}, + {delete_and_terminate, 2}, {purge, 1}, {publish, 4}, + {publish_delivered, 5}, {drain_confirmed, 1}, {dropwhile, 3}, + {fetch, 2}, {ack, 2}, {fold, 3}, {requeue, 2}, {len, 1}, + {is_empty, 1}, {set_ram_duration_target, 2}, {ram_duration, 1}, + {needs_timeout, 1}, {timeout, 1}, {handle_pre_hibernate, 1}, + {status, 1}, {invoke, 3}, {is_duplicate, 2}, {discard, 3}]; behaviour_info(_Other) -> undefined. + +-endif. diff --git a/src/rabbit_exchange_type.erl b/src/rabbit_exchange_type.erl index 44a08e24..1027570c 100644 --- a/src/rabbit_exchange_type.erl +++ b/src/rabbit_exchange_type.erl @@ -16,39 +16,57 @@ -module(rabbit_exchange_type). --export([behaviour_info/1]). +-ifdef(use_specs). -behaviour_info(callbacks) -> - [ - {description, 0}, +-type(tx() :: 'transaction' | 'none'). +-type(serial() :: pos_integer() | tx()). + +-callback description() -> [proplist:property()]. + +%% Should Rabbit ensure that all binding events that are +%% delivered to an individual exchange can be serialised? (they +%% might still be delivered out of order, but there'll be a +%% serial number). +-callback serialise_events() -> boolean(). - %% Should Rabbit ensure that all binding events that are - %% delivered to an individual exchange can be serialised? (they - %% might still be delivered out of order, but there'll be a - %% serial number). - {serialise_events, 0}, +%% The no_return is there so that we can have an "invalid" exchange +%% type (see rabbit_exchange_type_invalid). +-callback route(rabbit_types:exchange(), rabbit_types:delivery()) -> + rabbit_router:match_result(). - {route, 2}, +%% called BEFORE declaration, to check args etc; may exit with #amqp_error{} +-callback validate(rabbit_types:exchange()) -> 'ok'. - %% called BEFORE declaration, to check args etc; may exit with #amqp_error{} - {validate, 1}, +%% called after declaration and recovery +-callback create(tx(), rabbit_types:exchange()) -> 'ok'. - %% called after declaration and recovery - {create, 2}, +%% called after exchange (auto)deletion. +-callback delete(tx(), rabbit_types:exchange(), [rabbit_types:binding()]) -> + 'ok'. - %% called after exchange (auto)deletion. - {delete, 3}, +%% called after a binding has been added or recovered +-callback add_binding(serial(), rabbit_types:exchange(), + rabbit_types:binding()) -> 'ok'. - %% called after a binding has been added or recovered - {add_binding, 3}, +%% called after bindings have been deleted. +-callback remove_bindings(serial(), rabbit_types:exchange(), + [rabbit_types:binding()]) -> 'ok'. - %% called after bindings have been deleted. - {remove_bindings, 3}, +%% called when comparing exchanges for equivalence - should return ok or +%% exit with #amqp_error{} +-callback assert_args_equivalence (rabbit_types:exchange(), + rabbit_framing:amqp_table()) -> + 'ok' | rabbit_types:connection_exit(). - %% called when comparing exchanges for equivalence - should return ok or - %% exit with #amqp_error{} - {assert_args_equivalence, 2} +-else. - ]; +-export([behaviour_info/1]). + +behaviour_info(callbacks) -> + [{description, 0}, {serialise_events, 0}, {route, 2}, {validate, 1}, + {create, 2}, {delete, 3}, {add_binding, 3}, {remove_bindings, 3}, + {assert_args_equivalence, 2}]; behaviour_info(_Other) -> undefined. + +-endif. diff --git a/src/rabbit_exchange_type_direct.erl b/src/rabbit_exchange_type_direct.erl index 4bce42d4..cdec1cb9 100644 --- a/src/rabbit_exchange_type_direct.erl +++ b/src/rabbit_exchange_type_direct.erl @@ -22,7 +22,6 @@ -export([description/0, serialise_events/0, route/2]). -export([validate/1, create/2, delete/3, add_binding/3, remove_bindings/3, assert_args_equivalence/2]). --include("rabbit_exchange_type_spec.hrl"). -rabbit_boot_step({?MODULE, [{description, "exchange type direct"}, diff --git a/src/rabbit_exchange_type_fanout.erl b/src/rabbit_exchange_type_fanout.erl index cc3fb87c..a64f2c29 100644 --- a/src/rabbit_exchange_type_fanout.erl +++ b/src/rabbit_exchange_type_fanout.erl @@ -22,7 +22,6 @@ -export([description/0, serialise_events/0, route/2]). -export([validate/1, create/2, delete/3, add_binding/3, remove_bindings/3, assert_args_equivalence/2]). --include("rabbit_exchange_type_spec.hrl"). -rabbit_boot_step({?MODULE, [{description, "exchange type fanout"}, diff --git a/src/rabbit_exchange_type_headers.erl b/src/rabbit_exchange_type_headers.erl index de9979b4..61917d8f 100644 --- a/src/rabbit_exchange_type_headers.erl +++ b/src/rabbit_exchange_type_headers.erl @@ -23,7 +23,6 @@ -export([description/0, serialise_events/0, route/2]). -export([validate/1, create/2, delete/3, add_binding/3, remove_bindings/3, assert_args_equivalence/2]). --include("rabbit_exchange_type_spec.hrl"). -rabbit_boot_step({?MODULE, [{description, "exchange type headers"}, diff --git a/src/rabbit_exchange_type_invalid.erl b/src/rabbit_exchange_type_invalid.erl index 8f60f7d8..82d27960 100644 --- a/src/rabbit_exchange_type_invalid.erl +++ b/src/rabbit_exchange_type_invalid.erl @@ -22,7 +22,6 @@ -export([description/0, serialise_events/0, route/2]). -export([validate/1, create/2, delete/3, add_binding/3, remove_bindings/3, assert_args_equivalence/2]). --include("rabbit_exchange_type_spec.hrl"). description() -> [{name, <<"invalid">>}, diff --git a/src/rabbit_exchange_type_topic.erl b/src/rabbit_exchange_type_topic.erl index 84f4f8a9..3160fdf4 100644 --- a/src/rabbit_exchange_type_topic.erl +++ b/src/rabbit_exchange_type_topic.erl @@ -23,7 +23,6 @@ -export([description/0, serialise_events/0, route/2]). -export([validate/1, create/2, delete/3, add_binding/3, remove_bindings/3, assert_args_equivalence/2]). --include("rabbit_exchange_type_spec.hrl"). -rabbit_boot_step({?MODULE, [{description, "exchange type topic"}, diff --git a/src/rabbit_mirror_queue_master.erl b/src/rabbit_mirror_queue_master.erl index 5db0fa2f..04b7514f 100644 --- a/src/rabbit_mirror_queue_master.erl +++ b/src/rabbit_mirror_queue_master.erl @@ -59,10 +59,6 @@ known_senders :: set() }). --type(ack() :: non_neg_integer()). --type(state() :: master_state()). --include("rabbit_backing_queue_spec.hrl"). - -spec(promote_backing_queue_state/6 :: (pid(), atom(), any(), pid(), dict(), [pid()]) -> master_state()). -spec(sender_death_fun/0 :: () -> death_fun()). diff --git a/src/rabbit_msg_store_ets_index.erl b/src/rabbit_msg_store_ets_index.erl index 9c31439f..3defeaaf 100644 --- a/src/rabbit_msg_store_ets_index.erl +++ b/src/rabbit_msg_store_ets_index.erl @@ -16,6 +16,8 @@ -module(rabbit_msg_store_ets_index). +-include("rabbit_msg_store.hrl"). + -behaviour(rabbit_msg_store_index). -export([new/1, recover/1, @@ -25,8 +27,6 @@ -define(MSG_LOC_NAME, rabbit_msg_store_ets_index). -define(FILENAME, "msg_store_index.ets"). --include("rabbit_msg_store_index.hrl"). - -record(state, { table, dir }). new(Dir) -> diff --git a/src/rabbit_msg_store_index.erl b/src/rabbit_msg_store_index.erl index 2f36256c..6cc0b2a7 100644 --- a/src/rabbit_msg_store_index.erl +++ b/src/rabbit_msg_store_index.erl @@ -16,6 +16,31 @@ -module(rabbit_msg_store_index). +-include("rabbit_msg_store.hrl"). + +-ifdef(use_specs). + +-type(dir() :: any()). +-type(index_state() :: any()). +-type(keyvalue() :: any()). +-type(fieldpos() :: non_neg_integer()). +-type(fieldvalue() :: any()). + +-callback new(dir()) -> index_state(). +-callback recover(dir()) -> rabbit_types:ok_or_error2(index_state(), any()). +-callback lookup(rabbit_types:msg_id(), index_state()) -> ('not_found' | keyvalue()). +-callback insert(keyvalue(), index_state()) -> 'ok'. +-callback update(keyvalue(), index_state()) -> 'ok'. +-callback update_fields(rabbit_types:msg_id(), ({fieldpos(), fieldvalue()} | + [{fieldpos(), fieldvalue()}]), + index_state()) -> 'ok'. +-callback delete(rabbit_types:msg_id(), index_state()) -> 'ok'. +-callback delete_object(keyvalue(), index_state()) -> 'ok'. +-callback delete_by_file(fieldvalue(), index_state()) -> 'ok'. +-callback terminate(index_state()) -> any(). + +-else. + -export([behaviour_info/1]). behaviour_info(callbacks) -> @@ -30,3 +55,5 @@ behaviour_info(callbacks) -> {terminate, 1}]; behaviour_info(_Other) -> undefined. + +-endif. diff --git a/src/rabbit_variable_queue.erl b/src/rabbit_variable_queue.erl index 64d3b05c..0bfec2fd 100644 --- a/src/rabbit_variable_queue.erl +++ b/src/rabbit_variable_queue.erl @@ -351,7 +351,7 @@ durable :: boolean(), transient_threshold :: non_neg_integer(), - async_callback :: async_callback(), + async_callback :: rabbit_backing_queue:async_callback(), len :: non_neg_integer(), persistent_count :: non_neg_integer(), @@ -370,8 +370,6 @@ ack_in_counter :: non_neg_integer(), ack_rates :: rates() }). --include("rabbit_backing_queue_spec.hrl"). - -spec(multiple_routing_keys/0 :: () -> 'ok'). -endif. diff --git a/src/supervisor2.erl b/src/supervisor2.erl index 8dd8aba8..f1b74878 100644 --- a/src/supervisor2.erl +++ b/src/supervisor2.erl @@ -81,8 +81,6 @@ which_children/1, find_child/2, check_childspecs/1]). --export([behaviour_info/1]). - %% Internal exports -export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3]). -export([handle_cast/2]). @@ -112,11 +110,144 @@ -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}. +-type modules() :: [module()] | 'dynamic'. +-type delay() :: non_neg_integer(). +-type restart() :: 'permanent' | 'transient' | 'temporary' | 'intrinsic' + | {'permanent', delay()} | {'transient', delay()} + | {'intrinsic', delay()}. +-type shutdown() :: 'brutal_kill' | timeout(). +-type worker() :: 'worker' | 'supervisor'. +-type sup_name() :: {'local', Name :: atom()} | {'global', Name :: atom()}. +-type sup_ref() :: (Name :: atom()) + | {Name :: atom(), Node :: node()} + | {'global', Name :: atom()} + | pid(). +-type child_spec() :: {Id :: child_id(), + StartFunc :: mfargs(), + Restart :: restart(), + Shutdown :: shutdown(), + Type :: worker(), + Modules :: modules()}. + + +-type strategy() :: 'one_for_all' | 'one_for_one' + | 'rest_for_one' | 'simple_one_for_one' + | 'simple_one_for_one_terminate'. + +-type child_rec() :: #child{pid :: child() | {restarting,pid()} | [pid()], + name :: child_id(), + mfa :: mfargs(), + restart_type :: restart(), + shutdown :: shutdown(), + child_type :: worker(), + modules :: modules()}. + +-type state() :: #state{strategy :: strategy(), + children :: [child_rec()], + dynamics :: ?DICT(), + intensity :: non_neg_integer(), + period :: pos_integer()}. + +%%-------------------------------------------------------------------------- +%% Callback behaviour +%%-------------------------------------------------------------------------- + +-callback init(Args :: term()) -> + {ok, {{RestartStrategy :: strategy(), + MaxR :: non_neg_integer(), + MaxT :: non_neg_integer()}, + [ChildSpec :: child_spec()]}} + | ignore. + +%%-------------------------------------------------------------------------- +%% Specs +%%-------------------------------------------------------------------------- + +-type startchild_err() :: 'already_present' + | {'already_started', Child :: child()} | term(). +-type startchild_ret() :: {'ok', Child :: child()} + | {'ok', Child :: child(), Info :: term()} + | {'error', startchild_err()}. + +-spec start_child(SupRef, ChildSpec) -> startchild_ret() when + SupRef :: sup_ref(), + ChildSpec :: child_spec() | (List :: [term()]). + +-spec restart_child(SupRef, Id) -> Result when + SupRef :: sup_ref(), + Id :: child_id(), + Result :: {'ok', Child :: child()} + | {'ok', Child :: child(), Info :: term()} + | {'error', Error}, + Error :: 'running' | 'not_found' | 'simple_one_for_one' | term(). + +-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'. + +-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'. + +-spec which_children(SupRef) -> [{Id,Child,Type,Modules}] when + SupRef :: sup_ref(), + Id :: child_id() | 'undefined', + 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. |