./ct_report/coverage/ejabberd_sup.COVER.html

1 %%%----------------------------------------------------------------------
2 %%% File : ejabberd_sup.erl
3 %%% Author : Alexey Shchepin <alexey@process-one.net>
4 %%% Purpose : Erlang/OTP supervisor
5 %%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
6 %%%
7 %%%
8 %%% ejabberd, Copyright (C) 2002-2011 ProcessOne
9 %%%
10 %%% This program is free software; you can redistribute it and/or
11 %%% modify it under the terms of the GNU General Public License as
12 %%% published by the Free Software Foundation; either version 2 of the
13 %%% License, or (at your option) any later version.
14 %%%
15 %%% This program is distributed in the hope that it will be useful,
16 %%% but WITHOUT ANY WARRANTY; without even the implied warranty of
17 %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 %%% General Public License for more details.
19 %%%
20 %%% You should have received a copy of the GNU General Public License
21 %%% along with this program; if not, write to the Free Software
22 %%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 %%%
24 %%%----------------------------------------------------------------------
25
26 -module(ejabberd_sup).
27 -author('alexey@process-one.net').
28
29 -behaviour(supervisor).
30
31 -export([start_link/0, init/1]).
32 -export([start_child/1, start_child/2, stop_child/1]).
33 -export([create_ets_table/2]).
34
35 -include("mongoose_logger.hrl").
36
37 start_link() ->
38 53 supervisor:start_link({local, ?MODULE}, ?MODULE, []).
39
40 init([]) ->
41 53 DistBlocker = worker_spec(cets_dist_blocker),
42 53 Hooks = worker_spec(gen_hook),
43 53 Instrument = worker_spec(mongoose_instrument),
44 53 Cleaner = worker_spec(mongoose_cleaner),
45 53 Router = worker_spec(ejabberd_router),
46 53 S2S = worker_spec(ejabberd_s2s),
47 53 Local = worker_spec(ejabberd_local),
48 53 MucIQ = worker_spec(mod_muc_iq),
49 53 StartIdServer = worker_spec(mongoose_start_node_id),
50 53 PG = worker_spec(pg, [mim_scope]),
51 53 SMBackendSupervisor = supervisor_spec(ejabberd_sm_backend_sup),
52 53 OutgoingPoolsSupervisor = supervisor_spec(mongoose_wpool_sup),
53 53 Listener = supervisor_spec(mongoose_listener_sup),
54 53 ShaperSup = mongoose_shaper:child_spec(),
55 53 DomainSup = supervisor_spec(mongoose_domain_sup),
56 53 ReceiverSupervisor =
57 ejabberd_tmp_sup_spec(mongoose_transport_sup, [mongoose_transport_sup, mongoose_transport]),
58 53 C2SSupervisor =
59 ejabberd_tmp_sup_spec(mongoose_c2s_sup, [mongoose_c2s_sup, mongoose_c2s]),
60 53 S2SInSupervisor =
61 ejabberd_tmp_sup_spec(ejabberd_s2s_in_sup, [ejabberd_s2s_in_sup, ejabberd_s2s_in]),
62 53 S2SOutSupervisor =
63 ejabberd_tmp_sup_spec(ejabberd_s2s_out_sup, [ejabberd_s2s_out_sup, ejabberd_s2s_out]),
64 53 ServiceSupervisor =
65 ejabberd_tmp_sup_spec(ejabberd_service_sup, [ejabberd_service_sup, ejabberd_service]),
66 53 IQSupervisor =
67 ejabberd_tmp_sup_spec(ejabberd_iq_sup, [ejabberd_iq_sup, mongoose_iq_worker]),
68 53 {ok, {{one_for_one, 10, 1},
69 [DistBlocker,
70 StartIdServer,
71 PG,
72 Hooks,
73 Instrument,
74 Cleaner,
75 SMBackendSupervisor,
76 OutgoingPoolsSupervisor
77 ] ++ mongoose_cets_discovery:supervisor_specs() ++ [
78 Router,
79 S2S,
80 Local,
81 ReceiverSupervisor,
82 C2SSupervisor,
83 S2SInSupervisor,
84 S2SOutSupervisor,
85 ServiceSupervisor,
86 IQSupervisor,
87 Listener,
88 MucIQ,
89 ShaperSup,
90 DomainSup]}}.
91
92 start_child(ChildSpec) ->
93 949 start_child(ejabberd_sup, ChildSpec).
94
95 %% This function handles error results from supervisor:start_child
96 %% It does some logging
97 start_child(SupName, ChildSpec) ->
98 1716 case supervisor:start_child(SupName, ChildSpec) of
99 {ok, Pid} ->
100 1716 {ok, Pid};
101 Other ->
102
:-(
Stacktrace = element(2, erlang:process_info(self(), current_stacktrace)),
103
:-(
?LOG_ERROR(#{what => start_child_failed, spec => ChildSpec,
104 supervisor_name => SupName,
105
:-(
reason => Other, stacktrace => Stacktrace}),
106
:-(
erlang:error({start_child_failed, Other, ChildSpec})
107 end.
108
109 stop_child(Proc) ->
110 1198 supervisor:terminate_child(ejabberd_sup, Proc),
111 1198 supervisor:delete_child(ejabberd_sup, Proc),
112 1198 ok.
113
114 ejabberd_tmp_sup_spec(Name, Args) ->
115 318 {Name,
116 {ejabberd_tmp_sup, start_link, Args},
117 permanent, infinity, supervisor, [ejabberd_tmp_sup]}.
118
119 supervisor_spec(Mod) ->
120 212 {Mod, {Mod, start_link, []}, permanent, infinity, supervisor, [Mod]}.
121
122 worker_spec(Mod) ->
123 477 worker_spec(Mod, []).
124
125 worker_spec(Mod, Args) ->
126 530 {Mod, {Mod, start_link, Args}, permanent, timer:seconds(5), worker, [Mod]}.
127
128 -spec create_ets_table(atom(), list()) -> ok.
129 create_ets_table(TableName, TableOpts) ->
130 448 case does_table_exist(TableName) of
131 181 true -> ok;
132 false ->
133 267 Opts = maybe_add_heir(whereis(?MODULE), self(), TableOpts),
134 267 ets:new(TableName, Opts),
135 267 ok
136 end.
137
138 does_table_exist(TableName) ->
139 448 undefined =/= ets:info(TableName, name).
140
141 %% In tests or when module is started in run-time, we need to set heir to the
142 %% ETS table, otherwise it will be destroyed when the creator's process finishes.
143 %% When started normally during node start up, self() =:= EjdSupPid and there
144 %% is no need for setting heir
145 maybe_add_heir(EjdSupPid, EjdSupPid, BaseOpts) when is_pid(EjdSupPid) ->
146
:-(
BaseOpts;
147 maybe_add_heir(EjdSupPid, _Self, BaseOpts) when is_pid(EjdSupPid) ->
148 267 case lists:keymember(heir, 1, BaseOpts) of
149 53 true -> BaseOpts;
150 214 false -> [{heir, EjdSupPid, testing} | BaseOpts]
151 end;
152 maybe_add_heir(_, _, BaseOpts) ->
153
:-(
BaseOpts.
Line Hits Source