aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd.erl
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2013-07-07 02:11:01 +1000
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2013-07-07 02:19:51 +1000
commit0aca3a4585a8f2308f22f74536bd775396fcaa17 (patch)
tree33c05b865e2619f31199d2ccfc6efdee0dec1a17 /src/ejabberd.erl
parentImprove the XMPP codec, fix the test suite accordingly (diff)
Improve the applications start-up
* Check if all modules present for every application loaded. * Get rid of now obsoleted 'ejabberd_check' module.
Diffstat (limited to 'src/ejabberd.erl')
-rw-r--r--src/ejabberd.erl96
1 files changed, 81 insertions, 15 deletions
diff --git a/src/ejabberd.erl b/src/ejabberd.erl
index 7b83f19a1..78ef10089 100644
--- a/src/ejabberd.erl
+++ b/src/ejabberd.erl
@@ -27,8 +27,8 @@
-module(ejabberd).
-author('alexey@process-one.net').
--export([start/0, stop/0, start_app/1,
- get_pid_file/0]).
+-export([start/0, stop/0, start_app/1, start_app/2,
+ get_pid_file/0, check_app/1]).
-include("logger.hrl").
@@ -51,27 +51,93 @@ get_pid_file() ->
Path
end.
-start_app(App) when not is_list(App) ->
- start_app([App]);
-start_app([App|Apps]) ->
+start_app(App) ->
+ start_app(App, temporary).
+
+start_app(App, Type) ->
+ StartFlag = not is_loaded(),
+ start_app(App, Type, StartFlag).
+
+check_app(App) ->
+ StartFlag = not is_loaded(),
+ spawn(fun() -> check_app_modules(App, StartFlag) end),
+ ok.
+
+is_loaded() ->
+ Apps = application:which_applications(),
+ lists:keymember(ejabberd, 1, Apps).
+
+start_app(App, Type, StartFlag) when not is_list(App) ->
+ start_app([App], Type, StartFlag);
+start_app([App|Apps], Type, StartFlag) ->
case application:start(App) of
ok ->
- start_app(Apps);
+ spawn(fun() -> check_app_modules(App, StartFlag) end),
+ start_app(Apps, Type, StartFlag);
{error, {already_started, _}} ->
- start_app(Apps);
+ start_app(Apps, Type, StartFlag);
{error, {not_started, DepApp}} ->
case lists:member(DepApp, [App|Apps]) of
true ->
- ?CRITICAL_MSG("failed to start application '~p': "
- "circular dependency on '~p' detected",
- [App, DepApp]),
- erlang:error(application_start_failed);
+ Reason = io_lib:format(
+ "failed to start application '~p': "
+ "circular dependency on '~p' detected",
+ [App, DepApp]),
+ exit_or_halt(Reason, StartFlag);
false ->
- start_app([DepApp,App|Apps])
+ start_app([DepApp,App|Apps], Type, StartFlag)
end;
Err ->
- ?CRITICAL_MSG("failed to start application '~p': ~p", [App, Err]),
- erlang:error(application_start_failed)
+ Reason = io_lib:format("failed to start application '~p': ~p",
+ [App, Err]),
+ exit_or_halt(Reason, StartFlag)
end;
-start_app([]) ->
+start_app([], _Type, _StartFlag) ->
ok.
+
+check_app_modules(App, StartFlag) ->
+ {A, B, C} = now(),
+ random:seed(A, B, C),
+ sleep(5000),
+ case application:get_key(App, modules) of
+ {ok, Mods} ->
+ lists:foreach(
+ fun(Mod) ->
+ case code:which(Mod) of
+ non_existing ->
+ File = get_module_file(App, Mod),
+ Reason = io_lib:format(
+ "couldn't find module ~s "
+ "needed for application '~p'",
+ [File, App]),
+ exit_or_halt(Reason, StartFlag);
+ _ ->
+ sleep(10)
+ end
+ end, Mods);
+ _ ->
+ %% No modules? This is strange
+ ok
+ end.
+
+exit_or_halt(Reason, StartFlag) ->
+ ?CRITICAL_MSG(Reason, []),
+ if StartFlag ->
+ %% Wait for the critical message is written in the console/log
+ timer:sleep(1000),
+ halt(string:substr(lists:flatten(Reason), 1, 199));
+ true ->
+ erlang:error(application_start_failed)
+ end.
+
+sleep(N) ->
+ timer:sleep(random:uniform(N)).
+
+get_module_file(App, Mod) ->
+ BaseName = atom_to_list(Mod),
+ case code:lib_dir(App, ebin) of
+ {error, _} ->
+ BaseName;
+ Dir ->
+ filename:join([Dir, BaseName ++ ".beam"])
+ end.