./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 101 supervisor:start_link({local, ?MODULE}, ?MODULE, []).
39
40 init([]) ->
41 101 Hooks = worker_spec(gen_hook),
42 101 Instrument = worker_spec(mongoose_instrument),
43 101 Cleaner = worker_spec(mongoose_cleaner),
44 101 Router = worker_spec(ejabberd_router),
45 101 S2S = worker_spec(ejabberd_s2s),
46 101 Local = worker_spec(ejabberd_local),
47 101 MucIQ = worker_spec(mod_muc_iq),
48 101 StartIdServer = worker_spec(mongoose_start_node_id),
49 101 PG = worker_spec(pg, [mim_scope]),
50 101 SMBackendSupervisor = supervisor_spec(ejabberd_sm_backend_sup),
51 101 OutgoingPoolsSupervisor = supervisor_spec(mongoose_wpool_sup),
52 101 Listener = supervisor_spec(mongoose_listener_sup),
53 101 ShaperSup = mongoose_shaper:child_spec(),
54 101 DomainSup = supervisor_spec(mongoose_domain_sup),
55 101 ReceiverSupervisor =
56 ejabberd_tmp_sup_spec(mongoose_transport_sup, [mongoose_transport_sup, mongoose_transport]),
57 101 C2SSupervisor =
58 ejabberd_tmp_sup_spec(mongoose_c2s_sup, [mongoose_c2s_sup, mongoose_c2s]),
59 101 S2SInSupervisor =
60 ejabberd_tmp_sup_spec(ejabberd_s2s_in_sup, [ejabberd_s2s_in_sup, ejabberd_s2s_in]),
61 101 S2SOutSupervisor =
62 ejabberd_tmp_sup_spec(ejabberd_s2s_out_sup, [ejabberd_s2s_out_sup, ejabberd_s2s_out]),
63 101 ServiceSupervisor =
64 ejabberd_tmp_sup_spec(ejabberd_service_sup, [ejabberd_service_sup, ejabberd_service]),
65 101 IQSupervisor =
66 ejabberd_tmp_sup_spec(ejabberd_iq_sup, [ejabberd_iq_sup, mongoose_iq_worker]),
67 101 {ok, {{one_for_one, 10, 1},
68 [StartIdServer,
69 PG,
70 Hooks,
71 Instrument,
72 Cleaner,
73 SMBackendSupervisor,
74 OutgoingPoolsSupervisor
75 ] ++ mongoose_cets_discovery:supervisor_specs() ++ [
76 Router,
77 S2S,
78 Local,
79 ReceiverSupervisor,
80 C2SSupervisor,
81 S2SInSupervisor,
82 S2SOutSupervisor,
83 ServiceSupervisor,
84 IQSupervisor,
85 Listener,
86 MucIQ,
87 ShaperSup,
88 DomainSup]}}.
89
90 start_child(ChildSpec) ->
91 1025 start_child(ejabberd_sup, ChildSpec).
92
93 %% This function handles error results from supervisor:start_child
94 %% It does some logging
95 start_child(SupName, ChildSpec) ->
96 2403 case supervisor:start_child(SupName, ChildSpec) of
97 {ok, Pid} ->
98 2403 {ok, Pid};
99 Other ->
100
:-(
Stacktrace = element(2, erlang:process_info(self(), current_stacktrace)),
101
:-(
?LOG_ERROR(#{what => start_child_failed, spec => ChildSpec,
102 supervisor_name => SupName,
103
:-(
reason => Other, stacktrace => Stacktrace}),
104
:-(
erlang:error({start_child_failed, Other, ChildSpec})
105 end.
106
107 stop_child(Proc) ->
108 1414 supervisor:terminate_child(ejabberd_sup, Proc),
109 1414 supervisor:delete_child(ejabberd_sup, Proc),
110 1414 ok.
111
112 ejabberd_tmp_sup_spec(Name, Args) ->
113 606 {Name,
114 {ejabberd_tmp_sup, start_link, Args},
115 permanent, infinity, supervisor, [ejabberd_tmp_sup]}.
116
117 supervisor_spec(Mod) ->
118 404 {Mod, {Mod, start_link, []}, permanent, infinity, supervisor, [Mod]}.
119
120 worker_spec(Mod) ->
121 808 worker_spec(Mod, []).
122
123 worker_spec(Mod, Args) ->
124 909 {Mod, {Mod, start_link, Args}, permanent, timer:seconds(5), worker, [Mod]}.
125
126 -spec create_ets_table(atom(), list()) -> ok.
127 create_ets_table(TableName, TableOpts) ->
128 632 case does_table_exist(TableName) of
129 324 true -> ok;
130 false ->
131 308 Opts = maybe_add_heir(whereis(?MODULE), self(), TableOpts),
132 308 ets:new(TableName, Opts),
133 308 ok
134 end.
135
136 does_table_exist(TableName) ->
137 632 undefined =/= ets:info(TableName, name).
138
139 %% In tests or when module is started in run-time, we need to set heir to the
140 %% ETS table, otherwise it will be destroyed when the creator's process finishes.
141 %% When started normally during node start up, self() =:= EjdSupPid and there
142 %% is no need for setting heir
143 maybe_add_heir(EjdSupPid, EjdSupPid, BaseOpts) when is_pid(EjdSupPid) ->
144
:-(
BaseOpts;
145 maybe_add_heir(EjdSupPid, _Self, BaseOpts) when is_pid(EjdSupPid) ->
146 308 case lists:keymember(heir, 1, BaseOpts) of
147 101 true -> BaseOpts;
148 207 false -> [{heir, EjdSupPid, testing} | BaseOpts]
149 end;
150 maybe_add_heir(_, _, BaseOpts) ->
151
:-(
BaseOpts.
Line Hits Source