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