Skip to content

Commit

Permalink
Make modules loading in a dependent order (#1191)
Browse files Browse the repository at this point in the history
  • Loading branch information
zinid committed Jul 6, 2016
1 parent de9f80f commit 4220a2b
Show file tree
Hide file tree
Showing 47 changed files with 248 additions and 98 deletions.
68 changes: 52 additions & 16 deletions src/gen_mod.erl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
-callback start(binary(), opts()) -> any().
-callback stop(binary()) -> any().
-callback mod_opt_type(atom()) -> fun((term()) -> term()) | [atom()].
-callback depends(binary(), opts()) -> [{module(), hard | soft}].

-export_type([opts/0]).
-export_type([db_type/0]).
Expand All @@ -77,18 +78,49 @@ start_modules() ->

get_modules_options(Host) ->
ejabberd_config:get_option(
{modules, Host},
fun(Mods) ->
lists:map(
{modules, Host},
fun(Mods) ->
lists:map(
fun({M, A}) when is_atom(M), is_list(A) ->
{M, A}
{M, A}
end, Mods)
end, []).
end, []).

sort_modules(Host, ModOpts) ->
G = digraph:new([acyclic]),
lists:foreach(
fun({Mod, Opts}) ->
digraph:add_vertex(G, Mod, Opts),
Deps = try Mod:depends(Host, Opts) catch _:undef -> [] end,
lists:foreach(
fun({DepMod, Type}) ->
case lists:keyfind(DepMod, 1, ModOpts) of
false when Type == hard ->
ErrTxt = io_lib:format(
"failed to load module '~s' "
"because it depends on module '~s' "
"which is not found in the config",
[Mod, DepMod]),
?ERROR_MSG(ErrTxt, []),
digraph:del_vertex(G, Mod),
maybe_halt_ejabberd(ErrTxt);
false when Type == soft ->
?WARNING_MSG("module '~s' is recommended for "
"module '~s' but is not found in "
"the config",
[DepMod, Mod]);
{DepMod, DepOpts} ->
digraph:add_vertex(G, DepMod, DepOpts),
digraph:add_edge(G, DepMod, Mod)
end
end, Deps)
end, ModOpts),
[digraph:vertex(G, V) || V <- digraph_utils:topsort(G)].

-spec start_modules(binary()) -> any().

start_modules(Host) ->
Modules = get_modules_options(Host),
Modules = sort_modules(Host, get_modules_options(Host)),
lists:foreach(
fun({Module, Opts}) ->
start_module(Host, Module, Opts)
Expand Down Expand Up @@ -121,16 +153,20 @@ start_module(Host, Module, Opts0) ->
[Module, Host, Opts, Class, Reason,
erlang:get_stacktrace()]),
?CRITICAL_MSG(ErrorText, []),
case is_app_running(ejabberd) of
true ->
erlang:raise(Class, Reason, erlang:get_stacktrace());
false ->
?CRITICAL_MSG("ejabberd initialization was aborted "
"because a module start failed.",
[]),
timer:sleep(3000),
erlang:halt(string:substr(lists:flatten(ErrorText), 1, 199))
end
maybe_halt_ejabberd(ErrorText),
erlang:raise(Class, Reason, erlang:get_stacktrace())
end.

maybe_halt_ejabberd(ErrorText) ->
case is_app_running(ejabberd) of
false ->
?CRITICAL_MSG("ejabberd initialization was aborted "
"because a module start failed.",
[]),
timer:sleep(3000),
erlang:halt(string:substr(lists:flatten(ErrorText), 1, 199));
true ->
ok
end.

is_app_running(AppName) ->
Expand Down
5 changes: 4 additions & 1 deletion src/mod_adhoc.erl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
process_sm_iq/3, get_local_commands/5,
get_local_identity/5, get_local_features/5,
get_sm_commands/5, get_sm_identity/5, get_sm_features/5,
ping_item/4, ping_command/4, mod_opt_type/1]).
ping_item/4, ping_command/4, mod_opt_type/1, depends/2]).

-include("ejabberd.hrl").
-include("logger.hrl").
Expand Down Expand Up @@ -284,6 +284,9 @@ ping_command(_Acc, _From, _To,
end;
ping_command(Acc, _From, _To, _Request) -> Acc.

depends(_Host, _Opts) ->
[].

mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
mod_opt_type(report_commands_node) ->
fun (B) when is_boolean(B) -> B end;
Expand Down
4 changes: 3 additions & 1 deletion src/mod_admin_extra.erl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
srg_delete/2, srg_list/1, srg_get_info/2,
srg_get_members/2, srg_user_add/4, srg_user_del/4,
send_message/5, send_stanza/3, send_stanza_c2s/4, privacy_set/3,
stats/1, stats/2, mod_opt_type/1, get_commands_spec/0]).
stats/1, stats/2, mod_opt_type/1, get_commands_spec/0, depends/2]).


-include("ejabberd.hrl").
Expand All @@ -66,6 +66,8 @@ start(_Host, _Opts) ->
stop(_Host) ->
ejabberd_commands:unregister_commands(get_commands_spec()).

depends(_Host, _Opts) ->
[].

%%%
%%% Register commands
Expand Down
5 changes: 4 additions & 1 deletion src/mod_announce.erl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

-export([start/2, init/0, stop/1, export/1, import/1,
import/3, announce/3, send_motd/1, disco_identity/5,
disco_features/5, disco_items/5,
disco_features/5, disco_items/5, depends/2,
send_announcement_to_all/3, announce_commands/4,
announce_items/4, mod_opt_type/1]).

Expand Down Expand Up @@ -74,6 +74,9 @@ start(Host, Opts) ->
register(gen_mod:get_module_proc(Host, ?PROCNAME),
proc_lib:spawn(?MODULE, init, [])).

depends(_Host, _Opts) ->
[{mod_adhoc, hard}].

init() ->
loop().

Expand Down
5 changes: 4 additions & 1 deletion src/mod_blocking.erl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
-protocol({xep, 191, '1.2'}).

-export([start/2, stop/1, process_iq/3,
process_iq_set/4, process_iq_get/5, mod_opt_type/1]).
process_iq_set/4, process_iq_get/5, mod_opt_type/1, depends/2]).

-include("ejabberd.hrl").
-include("logger.hrl").
Expand Down Expand Up @@ -63,6 +63,9 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
?NS_BLOCKING).

depends(_Host, _Opts) ->
[{mod_privacy, hard}].

process_iq(_From, _To, IQ) ->
SubEl = IQ#iq.sub_el,
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}.
Expand Down
5 changes: 4 additions & 1 deletion src/mod_caps.erl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
import_start/2, import_stop/2]).

%% gen_mod callbacks
-export([start/2, start_link/2, stop/1]).
-export([start/2, start_link/2, stop/1, depends/2]).

%% gen_server callbacks
-export([init/1, handle_info/2, handle_call/3,
Expand Down Expand Up @@ -306,6 +306,9 @@ c2s_broadcast_recipients(InAcc, Host, C2SState,
end;
c2s_broadcast_recipients(Acc, _, _, _, _, _) -> Acc.

depends(_Host, _Opts) ->
[].

init([Host, Opts]) ->
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
Mod:init(Host, Opts),
Expand Down
6 changes: 5 additions & 1 deletion src/mod_configure.erl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
get_local_features/5, get_local_items/5,
adhoc_local_items/4, adhoc_local_commands/4,
get_sm_identity/5, get_sm_features/5, get_sm_items/5,
adhoc_sm_items/4, adhoc_sm_commands/4, mod_opt_type/1]).
adhoc_sm_items/4, adhoc_sm_commands/4, mod_opt_type/1,
depends/2]).

-include("ejabberd.hrl").
-include("logger.hrl").
Expand Down Expand Up @@ -95,6 +96,9 @@ stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host,
?NS_COMMANDS).

depends(_Host, _Opts) ->
[{mod_adhoc, hard}, {mod_last, soft}].

%%%-----------------------------------------------------------------------

-define(INFO_IDENTITY(Category, Type, Name, Lang),
Expand Down
5 changes: 4 additions & 1 deletion src/mod_configure2.erl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
-behaviour(gen_mod).

-export([start/2, stop/1, process_local_iq/3,
mod_opt_type/1, opt_type/1]).
mod_opt_type/1, opt_type/1, depends/2]).

-include("ejabberd.hrl").
-include("logger.hrl").
Expand Down Expand Up @@ -201,6 +201,9 @@ process_get(#xmlel{name = <<"last">>, attrs = Attrs}, Lang) ->
%% {result, };
process_get(_, _) -> {error, ?ERR_BAD_REQUEST}.

depends(_Host, _Opts) ->
[].

mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
mod_opt_type(_) -> [iqdisc].

Expand Down
5 changes: 4 additions & 1 deletion src/mod_disco.erl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
get_sm_identity/5, get_sm_features/5, get_sm_items/5,
get_info/5, register_feature/2, unregister_feature/2,
register_extra_domain/2, unregister_extra_domain/2,
transform_module_options/1, mod_opt_type/1]).
transform_module_options/1, mod_opt_type/1, depends/2]).

-include("ejabberd.hrl").
-include("logger.hrl").
Expand Down Expand Up @@ -534,6 +534,9 @@ values_to_xml(Values) ->
end,
Values).

depends(_Host, _Opts) ->
[].

mod_opt_type(extra_domains) ->
fun (Hs) -> [iolist_to_binary(H) || H <- Hs] end;
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
Expand Down
5 changes: 4 additions & 1 deletion src/mod_echo.erl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3,
mod_opt_type/1]).
mod_opt_type/1, depends/2]).

-include("ejabberd.hrl").
-include("logger.hrl").
Expand Down Expand Up @@ -200,5 +200,8 @@ do_client_version(enabled, From, To) ->
?INFO_MSG("Information of the client: ~s~s",
[ToS, Values_string2]).

depends(_Host, _Opts) ->
[].

mod_opt_type(host) -> fun iolist_to_binary/1;
mod_opt_type(_) -> [host].
5 changes: 4 additions & 1 deletion src/mod_fail2ban.erl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3,
mod_opt_type/1]).
mod_opt_type/1, depends/2]).

-include_lib("stdlib/include/ms_transform.hrl").
-include("ejabberd.hrl").
Expand Down Expand Up @@ -120,6 +120,9 @@ stop(Host) ->
supervisor:terminate_child(ejabberd_sup, Proc),
supervisor:delete_child(ejabberd_sup, Proc).

depends(_Host, _Opts) ->
[].

%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
Expand Down
5 changes: 4 additions & 1 deletion src/mod_http_api.erl
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@

-behaviour(gen_mod).

-export([start/2, stop/1, process/2, mod_opt_type/1]).
-export([start/2, stop/1, process/2, mod_opt_type/1, depends/2]).

-include("ejabberd.hrl").
-include("jlib.hrl").
Expand Down Expand Up @@ -123,6 +123,9 @@ start(_Host, _Opts) ->
stop(_Host) ->
ok.

depends(_Host, _Opts) ->
[].

%% ----------
%% basic auth
%% ----------
Expand Down
4 changes: 3 additions & 1 deletion src/mod_http_bind.erl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

-behaviour(gen_mod).

-export([start/2, stop/1, process/2, mod_opt_type/1]).
-export([start/2, stop/1, process/2, mod_opt_type/1, depends/2]).

-include("ejabberd.hrl").
-include("logger.hrl").
Expand Down Expand Up @@ -109,6 +109,8 @@ mod_opt_type(max_pause) ->
fun (I) when is_integer(I), I > 0 -> I end;
mod_opt_type(_) -> [max_inactivity, max_pause].

depends(_Host, _Opts) ->
[].

%%%----------------------------------------------------------------------
%%% Help Web Page
Expand Down
5 changes: 4 additions & 1 deletion src/mod_http_fileserver.erl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
%% utility for other http modules
-export([content_type/3]).

-export([reopen_log/1, mod_opt_type/1]).
-export([reopen_log/1, mod_opt_type/1, depends/2]).

-include("ejabberd.hrl").
-include("logger.hrl").
Expand Down Expand Up @@ -109,6 +109,9 @@ stop(Host) ->
supervisor:terminate_child(ejabberd_sup, Proc),
supervisor:delete_child(ejabberd_sup, Proc).

depends(_Host, _Opts) ->
[].

%%====================================================================
%% API
%%====================================================================
Expand Down
6 changes: 6 additions & 0 deletions src/mod_http_upload.erl
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
-export([start_link/3,
start/2,
stop/1,
depends/2,
mod_opt_type/1]).

%% gen_server callbacks.
Expand Down Expand Up @@ -222,6 +223,11 @@ mod_opt_type(_) ->
dir_mode, docroot, put_url, get_url, service_url, custom_headers,
rm_on_unregister, thumbnail].

-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}].

depends(_Host, _Opts) ->
[].

%%--------------------------------------------------------------------
%% gen_server callbacks.
%%--------------------------------------------------------------------
Expand Down
6 changes: 6 additions & 0 deletions src/mod_http_upload_quota.erl
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
-export([start_link/3,
start/2,
stop/1,
depends/2,
mod_opt_type/1]).

%% gen_server callbacks.
Expand Down Expand Up @@ -109,6 +110,11 @@ mod_opt_type(max_days) ->
mod_opt_type(_) ->
[access_soft_quota, access_hard_quota, max_days].

-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}].

depends(_Host, _Opts) ->
[].

%%--------------------------------------------------------------------
%% gen_server callbacks.
%%--------------------------------------------------------------------
Expand Down
5 changes: 4 additions & 1 deletion src/mod_ip_blacklist.erl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

-export([update_bl_c2s/0]).

-export([is_ip_in_c2s_blacklist/3, mod_opt_type/1]).
-export([is_ip_in_c2s_blacklist/3, mod_opt_type/1, depends/2]).

-include("ejabberd.hrl").
-include("logger.hrl").
Expand Down Expand Up @@ -65,6 +65,9 @@ preinit(Parent, State) ->
error:_ -> Parent ! {ok, Pid, true}
end.

depends(_Host, _Opts) ->
[].

%% TODO:
stop(_Host) -> ok.

Expand Down
Loading

0 comments on commit 4220a2b

Please sign in to comment.