./ct_report/coverage/ejabberd_app.COVER.html

1 %%%----------------------------------------------------------------------
2 %%% File : ejabberd_app.erl
3 %%% Author : Alexey Shchepin <alexey@process-one.net>
4 %%% Purpose : ejabberd's application callback module
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_app).
27 -author('alexey@process-one.net').
28
29 -behaviour(application).
30
31 -export([start/2, prep_stop/1, stop/1]).
32
33 -ignore_xref([prep_stop/1]).
34
35 -include("mongoose.hrl").
36
37
38 %%%
39 %%% Application API
40 %%%
41
42 start(normal, _Args) ->
43 73 mongoose_fips:notify(),
44 73 write_pid_file(),
45 73 update_status_file(starting),
46 73 db_init(),
47 73 application:start(cache_tab),
48
49 73 mongoose_graphql:init(),
50 73 translate:start(),
51 73 ejabberd_node_id:start(),
52 73 ejabberd_ctl:init(),
53 73 ejabberd_commands:init(),
54 73 mongoose_commands:init(),
55 73 mongoose_service:start(),
56 73 mongoose_config:start(),
57 73 mongoose_router:start(),
58 73 mongoose_logs:set_global_loglevel(mongoose_config:get_opt(loglevel)),
59 73 mongoose_deprecations:start(),
60 73 {ok, _} = Sup = ejabberd_sup:start_link(),
61 73 mongoose_domain_api:init(),
62 73 mongoose_wpool:ensure_started(),
63 73 mongoose_wpool:start_configured_pools(),
64 %% ejabberd_sm is started separately because it may use one of the outgoing_pools
65 %% but some outgoing_pools should be started only with ejabberd_sup already running
66 73 ejabberd_sm:start(),
67 73 ejabberd_auth:start(),
68 73 mongoose_cluster_id:start(),
69 73 start_services(),
70 73 mongoose_modules:start(),
71 73 service_mongoose_system_metrics:verify_if_configured(),
72 73 mongoose_metrics:init(),
73 73 ejabberd_listener:start_listeners(),
74 73 ejabberd_admin:start(),
75 73 update_status_file(started),
76 73 ?LOG_NOTICE(#{what => mongooseim_node_started, version => ?MONGOOSE_VERSION, node => node()}),
77 73 Sup;
78 start(_, _) ->
79
:-(
{error, badarg}.
80
81 %% @doc Prepare the application for termination.
82 %% This function is called when an application is about to be stopped,
83 %% before shutting down the processes of the application.
84 prep_stop(State) ->
85 73 mongoose_deprecations:stop(),
86 73 ejabberd_listener:stop_listeners(),
87 73 mongoose_modules:stop(),
88 73 stop_services(),
89 73 broadcast_c2s_shutdown(),
90 73 mongoose_wpool:stop(),
91 73 mongoose_metrics:remove_all_metrics(),
92 73 mongoose_config:stop(),
93 73 State.
94
95 %% All the processes were killed when this function is called
96 stop(_State) ->
97 73 ?LOG_NOTICE(#{what => mongooseim_node_stopped, version => ?MONGOOSE_VERSION, node => node()}),
98 73 delete_pid_file(),
99 73 update_status_file(stopped),
100 %%ejabberd_debug:stop(),
101 73 ok.
102
103
104 %%%
105 %%% Internal functions
106 %%%
107 db_init() ->
108 73 case mnesia:system_info(extra_db_nodes) of
109 [] ->
110 47 application:stop(mnesia),
111 47 mnesia:create_schema([node()]),
112 47 application:start(mnesia, permanent);
113 _ ->
114 26 ok
115 end,
116 73 mnesia:wait_for_tables(mnesia:system_info(local_tables), infinity).
117
118 -spec start_services() -> ok.
119 start_services() ->
120 73 lists:foreach(
121 219 fun({Service, Opts}) -> mongoose_service:ensure_loaded(Service, Opts) end,
122 mongoose_config:get_opt(services, [])
123 ).
124
125 -spec stop_services() -> ok.
126 stop_services() ->
127 73 lists:foreach(
128 215 fun({Service, _Options}) -> mongoose_service:stop_service(Service) end,
129 mongoose_service:loaded_services_with_opts()
130 ).
131
132 -spec broadcast_c2s_shutdown() -> 'ok'.
133 broadcast_c2s_shutdown() ->
134 73 Children = supervisor:which_children(ejabberd_c2s_sup),
135 73 lists:foreach(
136 fun({_, C2SPid, _, _}) ->
137
:-(
C2SPid ! system_shutdown
138 end, Children),
139 73 mongoose_lib:wait_until(
140 fun() ->
141 73 Res = supervisor:count_children(ejabberd_c2s_sup),
142 73 proplists:get_value(active, Res)
143 end, 0).
144
145 %%%
146 %%% PID file
147 %%%
148
149 -spec write_pid_file() -> 'ok' | {'error', atom()}.
150 write_pid_file() ->
151 73 case ejabberd:get_pid_file() of
152 false ->
153
:-(
ok;
154 PidFilename ->
155 73 write_pid_file(os:getpid(), PidFilename)
156 end.
157
158 -spec write_pid_file(Pid :: string(),
159 PidFilename :: nonempty_string()
160 ) -> 'ok' | {'error', atom()}.
161 write_pid_file(Pid, PidFilename) ->
162 73 case file:open(PidFilename, [write]) of
163 {ok, Fd} ->
164 73 io:format(Fd, "~s~n", [Pid]),
165 73 file:close(Fd);
166 {error, Reason} ->
167
:-(
?LOG_ERROR(#{what => cannot_write_to_pid_file,
168
:-(
pid_file => PidFilename, reason => Reason}),
169
:-(
throw({cannot_write_pid_file, PidFilename, Reason})
170 end.
171
172 update_status_file(Status) ->
173 219 case ejabberd:get_status_file() of
174 false ->
175
:-(
ok;
176 StatusFilename ->
177 219 file:write_file(StatusFilename, atom_to_list(Status))
178 end.
179
180 -spec delete_pid_file() -> 'ok' | {'error', atom()}.
181 delete_pid_file() ->
182 73 case ejabberd:get_pid_file() of
183 false ->
184
:-(
ok;
185 PidFilename ->
186 73 file:delete(PidFilename)
187 end.
Line Hits Source