aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2017-02-23 10:12:19 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2017-02-23 10:12:19 +0300
commit7d6811226536fe260d83617a16fd741edb2d97f3 (patch)
tree4a0745ff2168078cf83233bcb68bafcf6cbd4e01 /src
parentRemove unused macro (diff)
Start/stop virtual hosts when reloading configuration file
Diffstat (limited to 'src')
-rw-r--r--src/acl.erl1
-rw-r--r--src/ejabberd_app.erl16
-rw-r--r--src/ejabberd_c2s.erl19
-rw-r--r--src/ejabberd_config.erl10
-rw-r--r--src/ejabberd_local.erl29
-rw-r--r--src/ejabberd_rdbms.erl29
-rw-r--r--src/ejabberd_redis.erl25
-rw-r--r--src/ejabberd_riak_sup.erl27
-rw-r--r--src/ejabberd_s2s.erl31
-rw-r--r--src/ejabberd_s2s_in.erl37
-rw-r--r--src/ejabberd_s2s_out.erl42
-rw-r--r--src/ejabberd_sm.erl71
-rw-r--r--src/ejabberd_system_monitor.erl8
-rw-r--r--src/gen_mod.erl10
14 files changed, 248 insertions, 107 deletions
diff --git a/src/acl.erl b/src/acl.erl
index 0feabfb32..99c8e17eb 100644
--- a/src/acl.erl
+++ b/src/acl.erl
@@ -86,6 +86,7 @@ start() ->
{attributes, record_info(fields, access)}]),
mnesia:add_table_copy(acl, node(), ram_copies),
mnesia:add_table_copy(access, node(), ram_copies),
+ ejabberd_hooks:add(config_reloaded, ?MODULE, load_from_config, 20),
load_from_config(),
ok.
diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl
index 493600afc..1340607cd 100644
--- a/src/ejabberd_app.erl
+++ b/src/ejabberd_app.erl
@@ -57,10 +57,10 @@ start(normal, _Args) ->
setup_if_elixir_conf_used(),
ejabberd_config:start(),
set_settings_from_config(),
- acl:start(),
- shaper:start(),
connect_nodes(),
Sup = ejabberd_sup:start_link(),
+ acl:start(),
+ shaper:start(),
ejabberd_rdbms:start(),
ejabberd_riak_sup:start(),
ejabberd_redis:start(),
@@ -88,7 +88,7 @@ start(_, _) ->
prep_stop(State) ->
ejabberd_listener:stop_listeners(),
ejabberd_admin:stop(),
- broadcast_c2s_shutdown(),
+ ejabberd_sm:stop(),
gen_mod:stop_modules(),
timer:sleep(5000),
State.
@@ -164,16 +164,6 @@ add_windows_nameservers() ->
?INFO_MSG("Adding machine's DNS IPs to Erlang system:~n~p", [IPTs]),
lists:foreach(fun(IPT) -> inet_db:add_ns(IPT) end, IPTs).
-
-broadcast_c2s_shutdown() ->
- Children = ejabberd_sm:get_all_pids(),
- lists:foreach(
- fun(C2SPid) when node(C2SPid) == node() ->
- ejabberd_c2s:send(C2SPid, xmpp:serr_system_shutdown());
- (_) ->
- ok
- end, Children).
-
%%%
%%% PID file
%%%
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 59b5c32a9..daf9c85a1 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -48,7 +48,8 @@
%% API
-export([get_presence/1, get_subscription/2, get_subscribed/1,
open_session/1, call/3, send/2, close/1, close/2, stop/1,
- reply/2, copy_state/2, set_timeout/2, route/2, add_hooks/1]).
+ reply/2, copy_state/2, set_timeout/2, route/2,
+ host_up/1, host_down/1]).
-include("ejabberd.hrl").
-include("xmpp.hrl").
@@ -145,8 +146,8 @@ route(Pid, Term) ->
set_timeout(State, Timeout) ->
xmpp_stream_in:set_timeout(State, Timeout).
--spec add_hooks(binary()) -> ok.
-add_hooks(Host) ->
+-spec host_up(binary()) -> ok.
+host_up(Host) ->
ejabberd_hooks:add(c2s_closed, Host, ?MODULE, process_closed, 100),
ejabberd_hooks:add(c2s_terminated, Host, ?MODULE,
process_terminated, 100),
@@ -157,6 +158,18 @@ add_hooks(Host) ->
ejabberd_hooks:add(c2s_handle_cast, Host, ?MODULE,
handle_unexpected_cast, 100).
+-spec host_down(binary()) -> ok.
+host_down(Host) ->
+ ejabberd_hooks:delete(c2s_closed, Host, ?MODULE, process_closed, 100),
+ ejabberd_hooks:delete(c2s_terminated, Host, ?MODULE,
+ process_terminated, 100),
+ ejabberd_hooks:delete(c2s_unauthenticated_packet, Host, ?MODULE,
+ reject_unauthenticated_packet, 100),
+ ejabberd_hooks:delete(c2s_handle_info, Host, ?MODULE,
+ process_info, 100),
+ ejabberd_hooks:delete(c2s_handle_cast, Host, ?MODULE,
+ handle_unexpected_cast, 100).
+
%% Copies content of one c2s state to another.
%% This is needed for session migration from one pid to another.
-spec copy_state(state(), state()) -> state().
diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl
index ff0f7b3e8..c79c0cd27 100644
--- a/src/ejabberd_config.erl
+++ b/src/ejabberd_config.erl
@@ -194,7 +194,17 @@ load_file(File) ->
reload_file() ->
Config = get_ejabberd_config_path(),
+ OldHosts = get_myhosts(),
load_file(Config),
+ NewHosts = get_myhosts(),
+ lists:foreach(
+ fun(Host) ->
+ ejabberd_hooks:run(host_up, [Host])
+ end, NewHosts -- OldHosts),
+ lists:foreach(
+ fun(Host) ->
+ ejabberd_hooks:run(host_down, [Host])
+ end, OldHosts -- NewHosts),
ejabberd_hooks:run(config_reloaded, []).
-spec convert_to_yaml(file:filename()) -> ok | {error, any()}.
diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl
index 2095dfc78..7a9034563 100644
--- a/src/ejabberd_local.erl
+++ b/src/ejabberd_local.erl
@@ -36,7 +36,8 @@
process_iq_reply/1, get_features/1,
register_iq_handler/5, register_iq_response_handler/4,
register_iq_response_handler/5, unregister_iq_handler/2,
- unregister_iq_response_handler/2, bounce_resource_packet/1]).
+ unregister_iq_response_handler/2, bounce_resource_packet/1,
+ host_up/1, host_down/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2,
@@ -196,16 +197,9 @@ get_features(_, _, XMLNSs) ->
%%====================================================================
init([]) ->
- lists:foreach(fun (Host) ->
- ejabberd_router:register_route(Host,
- Host,
- {apply, ?MODULE,
- route}),
- ejabberd_hooks:add(local_send_to_resource_hook, Host,
- ?MODULE, bounce_resource_packet,
- 100)
- end,
- ?MYHOSTS),
+ lists:foreach(fun host_up/1, ?MYHOSTS),
+ ejabberd_hooks:add(host_up, ?MODULE, host_up, 10),
+ ejabberd_hooks:add(host_down, ?MODULE, host_down, 100),
catch ets:new(?IQTABLE, [named_table, public, ordered_set]),
update_table(),
ejabberd_mnesia:create(?MODULE, iq_response,
@@ -245,6 +239,9 @@ handle_info(Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
+ lists:foreach(fun host_down/1, ?MYHOSTS),
+ ejabberd_hooks:delete(host_up, ?MODULE, host_up, 10),
+ ejabberd_hooks:delete(host_down, ?MODULE, host_down, 100),
ok.
code_change(_OldVsn, State, _Extra) ->
@@ -281,6 +278,16 @@ update_table() ->
ok
end.
+host_up(Host) ->
+ ejabberd_router:register_route(Host, Host, {apply, ?MODULE, route}),
+ ejabberd_hooks:add(local_send_to_resource_hook, Host,
+ ?MODULE, bounce_resource_packet, 100).
+
+host_down(Host) ->
+ ejabberd_router:unregister_route(Host),
+ ejabberd_hooks:delete(local_send_to_resource_hook, Host,
+ ?MODULE, bounce_resource_packet, 100).
+
-spec get_iq_callback(binary()) -> {ok, module(), atom() | function()} | error.
get_iq_callback(ID) ->
case mnesia:dirty_read(iq_response, ID) of
diff --git a/src/ejabberd_rdbms.erl b/src/ejabberd_rdbms.erl
index e3a211f8e..5fc73c624 100644
--- a/src/ejabberd_rdbms.erl
+++ b/src/ejabberd_rdbms.erl
@@ -29,7 +29,7 @@
-author('alexey@process-one.net').
--export([start/0, opt_type/1]).
+-export([start/0, opt_type/1, start_hosts/0, start_host/1, stop_host/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -38,6 +38,9 @@ start() ->
file:delete(ejabberd_sql:freetds_config()),
file:delete(ejabberd_sql:odbc_config()),
file:delete(ejabberd_sql:odbcinst_config()),
+ ejabberd_hooks:add(host_up, ?MODULE, start_host, 20),
+ ejabberd_hooks:add(host_down, ?MODULE, stop_host, 90),
+ ejabberd_hooks:add(config_reloaded, ?MODULE, start_hosts, 20),
case lists:any(fun(H) -> needs_sql(H) /= false end,
?MYHOSTS) of
true ->
@@ -48,13 +51,21 @@ start() ->
%% Start relationnal DB module on the nodes where it is needed
start_hosts() ->
- lists:foreach(fun (Host) ->
- case needs_sql(Host) of
- {true, App} -> start_sql(Host, App);
- false -> ok
- end
- end,
- ?MYHOSTS).
+ lists:foreach(fun start_host/1, ?MYHOSTS).
+
+-spec start_host(binary()) -> ok.
+start_host(Host) ->
+ case needs_sql(Host) of
+ {true, App} -> start_sql(Host, App);
+ false -> ok
+ end.
+
+-spec stop_host(binary()) -> ok.
+stop_host(Host) ->
+ SupName = gen_mod:get_module_proc(Host, ejabberd_sql_sup),
+ supervisor:terminate_child(ejabberd_sup, SupName),
+ supervisor:delete_child(ejabberd_sup, SupName),
+ ok.
%% Start the SQL module on the given host
start_sql(Host, App) ->
@@ -66,10 +77,12 @@ start_sql(Host, App) ->
infinity, supervisor, [ejabberd_sql_sup]},
case supervisor:start_child(ejabberd_sup, ChildSpec) of
{ok, _PID} -> ok;
+ {error, {already_started, _}} -> ok;
_Error ->
?ERROR_MSG("Start of supervisor ~p failed:~n~p~nRetrying."
"..~n",
[Supervisor_name, _Error]),
+ timer:sleep(5000),
start_sql(Host, App)
end.
diff --git a/src/ejabberd_redis.erl b/src/ejabberd_redis.erl
index 9d4264df3..6a853737d 100644
--- a/src/ejabberd_redis.erl
+++ b/src/ejabberd_redis.erl
@@ -28,7 +28,7 @@
-behaviour(ejabberd_config).
%% API
--export([start/0, start_link/0, q/1, qp/1, opt_type/1]).
+-export([start/0, stop/0, start_link/0, q/1, qp/1, host_up/1, opt_type/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@@ -49,16 +49,16 @@ start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
start() ->
+ ejabberd_hooks:add(config_reloaded, ?MODULE, start, 20),
+ ejabberd_hooks:add(host_up, ?MODULE, host_up, 20),
case lists:any(
fun(Host) ->
is_redis_configured(Host)
end, ?MYHOSTS) of
true ->
- Spec = {?MODULE, {?MODULE, start_link, []},
- permanent, 2000, worker, [?MODULE]},
- supervisor:start_child(ejabberd_sup, Spec);
+ do_start();
false ->
- ok
+ stop()
end.
q(Command) ->
@@ -71,6 +71,16 @@ qp(Pipeline) ->
catch _:Reason -> {error, Reason}
end.
+stop() ->
+ supervisor:terminate_child(ejabberd_sup, ?MODULE),
+ supervisor:delete_child(ejabberd_sup, ?MODULE).
+
+host_up(Host) ->
+ case is_redis_configured(Host) of
+ true -> do_start();
+ false -> ok
+ end.
+
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
@@ -108,6 +118,11 @@ code_change(_OldVsn, State, _Extra) ->
%%%===================================================================
%%% Internal functions
%%%===================================================================
+do_start() ->
+ Spec = {?MODULE, {?MODULE, start_link, []},
+ permanent, 5000, worker, [?MODULE]},
+ supervisor:start_child(ejabberd_sup, Spec).
+
is_redis_configured(Host) ->
ServerConfigured = ejabberd_config:has_option({redis_server, Host}),
PortConfigured = ejabberd_config:has_option({redis_port, Host}),
diff --git a/src/ejabberd_riak_sup.erl b/src/ejabberd_riak_sup.erl
index 840de29b5..d1ab126f8 100644
--- a/src/ejabberd_riak_sup.erl
+++ b/src/ejabberd_riak_sup.erl
@@ -28,9 +28,9 @@
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
--export([start/0, start_link/0, init/1, get_pids/0,
+-export([start/0, stop/0, start_link/0, init/1, get_pids/0,
transform_options/1, get_random_pid/0, get_random_pid/1,
- opt_type/1]).
+ host_up/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -45,6 +45,8 @@
-define(CONNECT_TIMEOUT, 500). % milliseconds
start() ->
+ ejabberd_hooks:add(config_reloaded, ?MODULE, start, 20),
+ ejabberd_hooks:add(host_up, ?MODULE, host_up, 20),
case lists:any(
fun(Host) ->
is_riak_configured(Host)
@@ -53,6 +55,20 @@ start() ->
ejabberd:start_app(riakc),
do_start();
false ->
+ stop()
+ end.
+
+stop() ->
+ supervisor:terminate_child(ejabberd_sup, ?MODULE),
+ supervisor:delete_child(ejabberd_sup, ?MODULE),
+ ok.
+
+host_up(Host) ->
+ case is_riak_configured(Host) of
+ true ->
+ ejabberd:start_app(riakc),
+ do_start();
+ false ->
ok
end.
@@ -77,9 +93,8 @@ is_riak_configured(Host) ->
or AuthConfigured or ModuleWithRiakDBConfigured.
do_start() ->
- SupervisorName = ?MODULE,
ChildSpec =
- {SupervisorName,
+ {?MODULE,
{?MODULE, start_link, []},
transient,
infinity,
@@ -88,9 +103,11 @@ do_start() ->
case supervisor:start_child(ejabberd_sup, ChildSpec) of
{ok, _PID} ->
ok;
+ {error, {already_started, _}} ->
+ ok;
_Error ->
?ERROR_MSG("Start of supervisor ~p failed:~n~p~nRetrying...~n",
- [SupervisorName, _Error]),
+ [?MODULE, _Error]),
timer:sleep(5000),
start()
end.
diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl
index 73004a06b..76fb522f0 100644
--- a/src/ejabberd_s2s.erl
+++ b/src/ejabberd_s2s.erl
@@ -44,7 +44,8 @@
list_temporarily_blocked_hosts/0,
external_host_overloaded/1, is_temporarly_blocked/1,
get_commands_spec/0, zlib_enabled/1, get_idle_timeout/1,
- tls_required/1, tls_verify/1, tls_enabled/1, tls_options/2]).
+ tls_required/1, tls_verify/1, tls_enabled/1, tls_options/2,
+ host_up/1, host_down/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2,
@@ -300,8 +301,9 @@ init([]) ->
ejabberd_mnesia:create(?MODULE, temporarily_blocked,
[{ram_copies, [node()]},
{attributes, record_info(fields, temporarily_blocked)}]),
- ejabberd_s2s_in:add_hooks(),
- ejabberd_s2s_out:add_hooks(),
+ ejabberd_hooks:add(host_up, ?MODULE, host_up, 50),
+ ejabberd_hooks:add(host_down, ?MODULE, host_down, 60),
+ lists:foreach(fun host_up/1, ?MYHOSTS),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
@@ -320,6 +322,9 @@ handle_info(_Info, State) -> {noreply, State}.
terminate(_Reason, _State) ->
ejabberd_commands:unregister_commands(get_commands_spec()),
+ lists:foreach(fun host_down/1, ?MYHOSTS),
+ ejabberd_hooks:delete(host_up, ?MODULE, host_up, 50),
+ ejabberd_hooks:delete(host_down, ?MODULE, host_down, 60),
ok.
code_change(_OldVsn, State, _Extra) ->
@@ -328,6 +333,26 @@ code_change(_OldVsn, State, _Extra) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+host_up(Host) ->
+ ejabberd_s2s_in:host_up(Host),
+ ejabberd_s2s_out:host_up(Host).
+
+host_down(Host) ->
+ lists:foreach(
+ fun(#s2s{fromto = {From, _}, pid = Pid}) when node(Pid) == node() ->
+ case ejabberd_router:host_of_route(From) of
+ Host ->
+ ejabberd_s2s_out:send(Pid, xmpp:serr_system_shutdown()),
+ ejabberd_s2s_out:stop(Pid);
+ _ ->
+ ok
+ end;
+ (_) ->
+ ok
+ end, ets:tab2list(s2s)),
+ ejabberd_s2s_in:host_down(Host),
+ ejabberd_s2s_out:host_down(Host).
+
-spec clean_table_from_bad_node(node()) -> any().
clean_table_from_bad_node(Node) ->
F = fun() ->
diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl
index f9d9e6f85..4289a8b34 100644
--- a/src/ejabberd_s2s_in.erl
+++ b/src/ejabberd_s2s_in.erl
@@ -42,7 +42,8 @@
-export([handle_unexpected_info/2, handle_unexpected_cast/2,
reject_unauthenticated_packet/2, process_closed/2]).
%% API
--export([stop/1, close/1, send/2, update_state/2, establish/1, add_hooks/0]).
+-export([stop/1, close/1, send/2, update_state/2, establish/1,
+ host_up/1, host_down/1]).
-include("ejabberd.hrl").
-include("xmpp.hrl").
@@ -90,19 +91,27 @@ establish(State) ->
update_state(Ref, Callback) ->
xmpp_stream_in:cast(Ref, {update_state, Callback}).
--spec add_hooks() -> ok.
-add_hooks() ->
- lists:foreach(
- fun(Host) ->
- ejabberd_hooks:add(s2s_in_closed, Host, ?MODULE,
- process_closed, 100),
- ejabberd_hooks:add(s2s_in_unauthenticated_packet, Host, ?MODULE,
- reject_unauthenticated_packet, 100),
- ejabberd_hooks:add(s2s_in_handle_info, Host, ?MODULE,
- handle_unexpected_info, 100),
- ejabberd_hooks:add(s2s_in_handle_cast, Host, ?MODULE,
- handle_unexpected_cast, 100)
- end, ?MYHOSTS).
+-spec host_up(binary()) -> ok.
+host_up(Host) ->
+ ejabberd_hooks:add(s2s_in_closed, Host, ?MODULE,
+ process_closed, 100),
+ ejabberd_hooks:add(s2s_in_unauthenticated_packet, Host, ?MODULE,
+ reject_unauthenticated_packet, 100),
+ ejabberd_hooks:add(s2s_in_handle_info, Host, ?MODULE,
+ handle_unexpected_info, 100),
+ ejabberd_hooks:add(s2s_in_handle_cast, Host, ?MODULE,
+ handle_unexpected_cast, 100).
+
+-spec host_down(binary()) -> ok.
+host_down(Host) ->
+ ejabberd_hooks:delete(s2s_in_closed, Host, ?MODULE,
+ process_closed, 100),
+ ejabberd_hooks:delete(s2s_in_unauthenticated_packet, Host, ?MODULE,
+ reject_unauthenticated_packet, 100),
+ ejabberd_hooks:delete(s2s_in_handle_info, Host, ?MODULE,
+ handle_unexpected_info, 100),
+ ejabberd_hooks:delete(s2s_in_handle_cast, Host, ?MODULE,
+ handle_unexpected_cast, 100).
%%%===================================================================
%%% Hooks
diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl
index 32dda56ad..77f555475 100644
--- a/src/ejabberd_s2s_out.erl
+++ b/src/ejabberd_s2s_out.erl
@@ -40,7 +40,7 @@
handle_unexpected_cast/2, process_downgraded/2]).
%% API
-export([start/3, start_link/3, connect/1, close/1, stop/1, send/2,
- route/2, establish/1, update_state/2, add_hooks/0]).
+ route/2, establish/1, update_state/2, host_up/1, host_down/1]).
-include("ejabberd.hrl").
-include("xmpp.hrl").
@@ -99,21 +99,31 @@ establish(State) ->
update_state(Ref, Callback) ->
xmpp_stream_out:cast(Ref, {update_state, Callback}).
--spec add_hooks() -> ok.
-add_hooks() ->
- lists:foreach(
- fun(Host) ->
- ejabberd_hooks:add(s2s_out_auth_result, Host, ?MODULE,
- process_auth_result, 100),
- ejabberd_hooks:add(s2s_out_closed, Host, ?MODULE,
- process_closed, 100),
- ejabberd_hooks:add(s2s_out_handle_info, Host, ?MODULE,
- handle_unexpected_info, 100),
- ejabberd_hooks:add(s2s_out_handle_cast, Host, ?MODULE,
- handle_unexpected_cast, 100),
- ejabberd_hooks:add(s2s_out_downgraded, Host, ?MODULE,
- process_downgraded, 100)
- end, ?MYHOSTS).
+-spec host_up(binary()) -> ok.
+host_up(Host) ->
+ ejabberd_hooks:add(s2s_out_auth_result, Host, ?MODULE,
+ process_auth_result, 100),
+ ejabberd_hooks:add(s2s_out_closed, Host, ?MODULE,
+ process_closed, 100),
+ ejabberd_hooks:add(s2s_out_handle_info, Host, ?MODULE,
+ handle_unexpected_info, 100),
+ ejabberd_hooks:add(s2s_out_handle_cast, Host, ?MODULE,
+ handle_unexpected_cast, 100),
+ ejabberd_hooks:add(s2s_out_downgraded, Host, ?MODULE,
+ process_downgraded, 100).
+
+-spec host_down(binary()) -> ok.
+host_down(Host) ->
+ ejabberd_hooks:delete(s2s_out_auth_result, Host, ?MODULE,
+ process_auth_result, 100),
+ ejabberd_hooks:delete(s2s_out_closed, Host, ?MODULE,
+ process_closed, 100),
+ ejabberd_hooks:delete(s2s_out_handle_info, Host, ?MODULE,
+ handle_unexpected_info, 100),
+ ejabberd_hooks:delete(s2s_out_handle_cast, Host, ?MODULE,
+ handle_unexpected_cast, 100),
+ ejabberd_hooks:delete(s2s_out_downgraded, Host, ?MODULE,
+ process_downgraded, 100).
%%%===================================================================
%%% Hooks
diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl
index eaa1ab4ae..ab6f59639 100644
--- a/src/ejabberd_sm.erl
+++ b/src/ejabberd_sm.erl
@@ -36,6 +36,7 @@
%% API
-export([start/0,
+ stop/0,
start_link/0,
route/1,
route/2,
@@ -74,6 +75,8 @@
is_existing_resource/3,
get_commands_spec/0,
c2s_handle_info/2,
+ host_up/1,
+ host_down/1,
make_sid/0
]).
@@ -109,9 +112,15 @@
start() ->
ChildSpec = {?MODULE, {?MODULE, start_link, []},
- transient, 1000, worker, [?MODULE]},
+ transient, 5000, worker, [?MODULE]},
supervisor:start_child(ejabberd_sup, ChildSpec).
+-spec stop() -> ok.
+stop() ->
+ supervisor:terminate_child(ejabberd_sup, ?MODULE),
+ supervisor:delete_child(ejabberd_sup, ?MODULE),
+ ok.
+
start_link() ->
?GEN_SERVER:start_link({local, ?MODULE}, ?MODULE, [], []).
@@ -388,20 +397,12 @@ c2s_handle_info(State, _) ->
%%====================================================================
init([]) ->
+ process_flag(trap_exit, true),
lists:foreach(fun(Mod) -> Mod:init() end, get_sm_backends()),
ets:new(sm_iqtable, [named_table, public]),
- lists:foreach(
- fun(Host) ->
- ejabberd_hooks:add(c2s_handle_info, Host,
- ejabberd_sm, c2s_handle_info, 50),
- ejabberd_hooks:add(roster_in_subscription, Host,
- ejabberd_sm, check_in_subscription, 20),
- ejabberd_hooks:add(offline_message_hook, Host,
- ejabberd_sm, bounce_offline_message, 100),
- ejabberd_hooks:add(remove_user, Host,
- ejabberd_sm, disconnect_removed_user, 100),
- ejabberd_c2s:add_hooks(Host)
- end, ?MYHOSTS),
+ ejabberd_hooks:add(host_up, ?MODULE, host_up, 50),
+ ejabberd_hooks:add(host_down, ?MODULE, host_down, 60),
+ lists:foreach(fun host_up/1, ?MYHOSTS),
ejabberd_commands:register_commands(get_commands_spec()),
{ok, #state{}}.
@@ -433,17 +434,9 @@ handle_info(Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
- lists:foreach(
- fun(Host) ->
- ejabberd_hooks:delete(c2s_handle_info, Host,
- ejabberd_sm, c2s_handle_info, 50),
- ejabberd_hooks:delete(roster_in_subscription, Host,
- ejabberd_sm, check_in_subscription, 20),
- ejabberd_hooks:delete(offline_message_hook, Host,
- ejabberd_sm, bounce_offline_message, 100),
- ejabberd_hooks:delete(remove_user, Host,
- ejabberd_sm, disconnect_removed_user, 100)
- end, ?MYHOSTS),
+ lists:foreach(fun host_down/1, ?MYHOSTS),
+ ejabberd_hooks:delete(host_up, ?MODULE, host_up, 50),
+ ejabberd_hooks:delete(host_down, ?MODULE, host_down, 60),
ejabberd_commands:unregister_commands(get_commands_spec()),
ok.
@@ -452,6 +445,36 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+-spec host_up(binary()) -> ok.
+host_up(Host) ->
+ ejabberd_hooks:add(c2s_handle_info, Host,
+ ejabberd_sm, c2s_handle_info, 50),
+ ejabberd_hooks:add(roster_in_subscription, Host,
+ ejabberd_sm, check_in_subscription, 20),
+ ejabberd_hooks:add(offline_message_hook, Host,
+ ejabberd_sm, bounce_offline_message, 100),
+ ejabberd_hooks:add(remove_user, Host,
+ ejabberd_sm, disconnect_removed_user, 100),
+ ejabberd_c2s:host_up(Host).
+
+-spec host_down(binary()) -> ok.
+host_down(Host) ->
+ Mod = get_sm_backend(Host),
+ lists:foreach(
+ fun(#session{sid = {_, Pid}}) when node(Pid) == node() ->
+ ejabberd_c2s:send(Pid, xmpp:serr_system_shutdown());
+ (_) ->
+ ok
+ end, Mod:get_sessions(Host)),
+ ejabberd_hooks:delete(c2s_handle_info, Host,
+ ejabberd_sm, c2s_handle_info, 50),
+ ejabberd_hooks:delete(roster_in_subscription, Host,
+ ejabberd_sm, check_in_subscription, 20),
+ ejabberd_hooks:delete(offline_message_hook, Host,
+ ejabberd_sm, bounce_offline_message, 100),
+ ejabberd_hooks:delete(remove_user, Host,
+ ejabberd_sm, disconnect_removed_user, 100),
+ ejabberd_c2s:host_down(Host).
-spec set_session(sid(), binary(), binary(), binary(),
prio(), info()) -> ok.
diff --git a/src/ejabberd_system_monitor.erl b/src/ejabberd_system_monitor.erl
index d160afd72..e4c8f4ef7 100644
--- a/src/ejabberd_system_monitor.erl
+++ b/src/ejabberd_system_monitor.erl
@@ -33,7 +33,7 @@
%% API
-export([start_link/0, process_command/1, register_hook/1,
- process_remote_command/1]).
+ unregister_hook/1, process_remote_command/1]).
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3, opt_type/1]).
@@ -86,6 +86,10 @@ register_hook(Host) ->
ejabberd_hooks:add(local_send_to_resource_hook, Host,
?MODULE, process_command, 50).
+unregister_hook(Host) ->
+ ejabberd_hooks:delete(local_send_to_resource_hook, Host,
+ ?MODULE, process_command, 50).
+
%%====================================================================
%% gen_server callbacks
%%====================================================================
@@ -101,6 +105,8 @@ init(Opts) ->
LH = proplists:get_value(large_heap, Opts),
process_flag(priority, high),
erlang:system_monitor(self(), [{large_heap, LH}]),
+ ejabberd_hooks:add(host_up, ?MODULE, register_hook, 50),
+ ejabberd_hooks:add(host_down, ?MODULE, unregister_hook, 60),
lists:foreach(fun register_hook/1, ?MYHOSTS),
{ok, #state{}}.
diff --git a/src/gen_mod.erl b/src/gen_mod.erl
index b74d1555d..178fccb1f 100644
--- a/src/gen_mod.erl
+++ b/src/gen_mod.erl
@@ -80,6 +80,8 @@ start_link() ->
init([]) ->
ejabberd_hooks:add(config_reloaded, ?MODULE, config_reloaded, 50),
+ ejabberd_hooks:add(host_up, ?MODULE, start_modules, 40),
+ ejabberd_hooks:add(host_down, ?MODULE, stop_modules, 80),
ets:new(ejabberd_modules,
[named_table, public,
{keypos, #ejabberd_module.module_host}]),
@@ -162,7 +164,7 @@ sort_modules(Host, ModOpts) ->
end, ModOpts),
[digraph:vertex(G, V) || V <- digraph_utils:topsort(G)].
--spec start_modules(binary()) -> any().
+-spec start_modules(binary()) -> ok.
start_modules(Host) ->
Modules = sort_modules(Host, get_modules_options(Host)),
@@ -171,7 +173,7 @@ start_modules(Host) ->
start_module(Host, Module, Opts)
end, Modules).
--spec start_module(binary(), atom()) -> any().
+-spec start_module(binary(), atom()) -> ok | {ok, pid()} | {error, not_found_in_config}.
start_module(Host, Module) ->
Modules = get_modules_options(Host),
@@ -293,7 +295,7 @@ is_app_running(AppName) ->
lists:keymember(AppName, 1,
application:which_applications(Timeout)).
--spec stop_modules() -> any().
+-spec stop_modules() -> ok.
stop_modules() ->
lists:foreach(
@@ -301,7 +303,7 @@ stop_modules() ->
stop_modules(Host)
end, ?MYHOSTS).
--spec stop_modules(binary()) -> any().
+-spec stop_modules(binary()) -> ok.
stop_modules(Host) ->
Modules = get_modules_options(Host),