diff options
author | Evgeniy Khramtsov <ekhramtsov@process-one.net> | 2013-07-07 02:11:01 +1000 |
---|---|---|
committer | Evgeniy Khramtsov <ekhramtsov@process-one.net> | 2013-07-07 02:19:51 +1000 |
commit | 0aca3a4585a8f2308f22f74536bd775396fcaa17 (patch) | |
tree | 33c05b865e2619f31199d2ccfc6efdee0dec1a17 /src/ejabberd.erl | |
parent | Improve 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.erl | 96 |
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. |