25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-22 17:28:25 +01:00

Improve startup procedure

This commit is contained in:
Evgeniy Khramtsov 2017-02-24 12:05:47 +03:00
parent 5b112c86bf
commit 67d6ca9f10
23 changed files with 405 additions and 316 deletions

View File

@ -25,12 +25,13 @@
-module(acl).
-behaviour(gen_server).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-export([add_access/3, clear/0]).
-export([start/0, add/3, add_list/3, add_local/3, add_list_local/3,
-export([start_link/0, add/3, add_list/3, add_local/3, add_list_local/3,
load_from_config/0, match_rule/3, any_rules_allowed/3,
transform_options/1, opt_type/1, acl_rule_matches/3,
acl_rule_verify/1, access_matches/3,
@ -38,6 +39,9 @@
parse_ip_netmask/1,
access_rules_validator/1, shaper_rules_validator/1,
normalize_spec/1, resolve_access/2]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include("ejabberd.hrl").
-include("logger.hrl").
@ -46,6 +50,7 @@
-record(acl, {aclname, aclspec}).
-record(access, {name :: aclname(),
rules = [] :: [access_rule()]}).
-record(state, {}).
-type regexp() :: binary().
-type iprange() :: {inet:ip_address(), integer()} | binary().
@ -75,7 +80,10 @@
-export_type([acl/0]).
start() ->
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init([]) ->
ejabberd_mnesia:create(?MODULE, acl,
[{ram_copies, [node()]}, {type, bag},
{local_content, true},
@ -88,8 +96,24 @@ start() ->
mnesia:add_table_copy(access, node(), ram_copies),
ejabberd_hooks:add(config_reloaded, ?MODULE, load_from_config, 20),
load_from_config(),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
-spec add(binary(), aclname(), aclspec()) -> ok | {error, any()}.
add(Host, ACLName, ACLSpec) ->

View File

@ -30,8 +30,7 @@
-behaviour(application).
-export([start/2, prep_stop/1, stop/1,
init/0, opt_type/1]).
-export([start/2, prep_stop/1, stop/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@ -46,9 +45,7 @@ start(normal, _Args) ->
start_apps(),
start_elixir_application(),
ejabberd:check_app(ejabberd),
randoms:start(),
db_init(),
start(),
translate:start(),
ejabberd_access_permissions:start_link(),
ejabberd_ctl:init(),
@ -57,25 +54,11 @@ start(normal, _Args) ->
setup_if_elixir_conf_used(),
ejabberd_config:start(),
set_settings_from_config(),
maybe_add_nameservers(),
cyrsasl:start(),
connect_nodes(),
Sup = ejabberd_sup:start_link(),
acl:start(),
shaper:start(),
ejabberd_rdbms:start(),
ejabberd_riak_sup:start(),
ejabberd_redis:start(),
ejabberd_router:start(),
ejabberd_router_multicast:start(),
ejabberd_local:start(),
ejabberd_sm:start(),
cyrsasl:start(),
gen_mod:start(),
ext_mod:start(),
maybe_add_nameservers(),
ejabberd_auth:start(),
ejabberd_oauth:start(),
gen_mod:start_modules(),
ejabberd_listener:start_listeners(),
register_elixir_config_hooks(),
?INFO_MSG("ejabberd ~s is started in the node ~p", [?VERSION, node()]),
Sup;
@ -105,19 +88,6 @@ stop(_State) ->
%%% Internal functions
%%%
start() ->
spawn_link(?MODULE, init, []).
init() ->
register(ejabberd, self()),
loop().
loop() ->
receive
_ ->
loop()
end.
db_init() ->
ejabberd_config:env_binary_to_list(mnesia, dir),
MyNode = node(),

View File

@ -27,12 +27,13 @@
-module(ejabberd_auth).
-behaviour(gen_server).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
%% External exports
-export([start/0, start/1, stop/1, set_password/3, check_password/4,
-export([start_link/0, start/1, stop/1, set_password/3, check_password/4,
check_password/6, check_password_with_authmodule/4,
check_password_with_authmodule/6, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
@ -43,12 +44,17 @@
is_user_exists/2, is_user_exists_in_other_modules/3,
remove_user/2, remove_user/3, plain_password_required/1,
store_type/1, entropy/1, backend_type/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-export([auth_modules/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-record(state, {}).
-type scrammed_password() :: {binary(), binary(), binary(), non_neg_integer()}.
-type password() :: binary() | scrammed_password().
-export_type([password/0]).
@ -81,11 +87,34 @@
-callback get_password(binary(), binary()) -> false | password().
-callback get_password_s(binary(), binary()) -> password().
start() ->
-spec start_link() -> {ok, pid()} | {error, any()}.
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init([]) ->
ets:new(ejabberd_auth_modules, [named_table, public]),
ejabberd_hooks:add(host_up, ?MODULE, start, 30),
ejabberd_hooks:add(host_down, ?MODULE, stop, 80),
lists:foreach(fun start/1, ?MYHOSTS).
lists:foreach(fun start/1, ?MYHOSTS),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ejabberd_hooks:delete(host_up, ?MODULE, start, 30),
ejabberd_hooks:delete(host_down, ?MODULE, stop, 80),
lists:foreach(fun stop/1, ?MYHOSTS).
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
start(Host) ->
Modules = auth_modules_from_config(Host),

View File

@ -86,12 +86,12 @@ start(Host) ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),
ChildSpec = {Proc, {?MODULE, start_link, [Host]},
transient, 1000, worker, [?MODULE]},
supervisor:start_child(ejabberd_sup, ChildSpec).
supervisor:start_child(ejabberd_backend_sup, ChildSpec).
stop(Host) ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),
supervisor:terminate_child(ejabberd_sup, Proc),
supervisor:delete_child(ejabberd_sup, Proc).
supervisor:terminate_child(ejabberd_backend_sup, Proc),
supervisor:delete_child(ejabberd_backend_sup, Proc).
start_link(Host) ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),

View File

@ -0,0 +1,46 @@
%%%-------------------------------------------------------------------
%%% Created : 24 Feb 2017 by Evgeny Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2017 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
%%% published by the Free Software Foundation; either version 2 of the
%%% License, or (at your option) any later version.
%%%
%%% This program is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License along
%%% with this program; if not, write to the Free Software Foundation, Inc.,
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%%%
%%%-------------------------------------------------------------------
-module(ejabberd_backend_sup).
-behaviour(supervisor).
%% API
-export([start_link/0]).
%% Supervisor callbacks
-export([init/1]).
%%%===================================================================
%%% API functions
%%%===================================================================
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
%%%===================================================================
%%% Supervisor callbacks
%%%===================================================================
init([]) ->
{ok, {{one_for_one, 10, 1}, []}}.
%%%===================================================================
%%% Internal functions
%%%===================================================================

View File

@ -45,58 +45,29 @@ start_link() ->
init(_) ->
ets:new(listen_sockets, [named_table, public]),
bind_tcp_ports(),
{ok, {{one_for_one, 10, 1}, []}}.
{ok, {{one_for_one, 10, 1}, listeners_childspec()}}.
bind_tcp_ports() ->
listeners_childspec() ->
case ejabberd_config:get_option(listen, fun validate_cfg/1) of
undefined ->
ignore;
[];
Ls ->
lists:foreach(
fun({Port, Module, Opts}) ->
case Module:socket_type() of
independent -> ok;
_ ->
bind_tcp_port(Port, Module, Opts)
end
end, Ls)
end.
bind_tcp_port(PortIP, Module, RawOpts) ->
try check_listener_options(RawOpts) of
ok ->
{Port, IPT, IPS, IPV, Proto, OptsClean} = parse_listener_portip(PortIP, RawOpts),
{_Opts, SockOpts} = prepare_opts(IPT, IPV, OptsClean),
case Proto of
udp -> ok;
_ ->
ListenSocket = listen_tcp(PortIP, Module, SockOpts, Port, IPS),
ets:insert(listen_sockets, {PortIP, ListenSocket}),
ok
end
catch
throw:{error, Error} ->
?ERROR_MSG(Error, [])
Specs = lists:map(
fun({Port, Module, Opts}) ->
maybe_start_sip(Module),
{Port,
{?MODULE, start, [Port, Module, Opts]},
transient,
brutal_kill,
worker,
[?MODULE]}
end, Ls),
report_duplicated_portips(Ls),
Specs
end.
start_listeners() ->
case ejabberd_config:get_option(listen, fun validate_cfg/1) of
undefined ->
ignore;
Ls ->
Ls2 = lists:map(
fun({Port, Module, Opts}) ->
case start_listener(Port, Module, Opts) of
{ok, _Pid} = R -> R;
{error, Error} ->
throw(Error)
end
end, Ls),
report_duplicated_portips(Ls),
{ok, {{one_for_one, 10, 1}, Ls2}}
end.
ok.
report_duplicated_portips(L) ->
LKeys = [Port || {Port, _, _} <- L],
@ -144,6 +115,9 @@ init_udp(PortIP, Module, Opts, SockOpts, Port, IPS) ->
{ok, Socket} ->
%% Inform my parent that this port was opened succesfully
proc_lib:init_ack({ok, self()}),
start_module_sup(Port, Module),
?INFO_MSG("Start accepting UDP connections at ~s for ~p",
[format_portip(PortIP), Module]),
case erlang:function_exported(Module, udp_init, 2) of
false ->
udp_recv(Socket, Module, Opts);
@ -166,6 +140,9 @@ init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) ->
ListenSocket = listen_tcp(PortIP, Module, SockOpts, Port, IPS),
%% Inform my parent that this port was opened succesfully
proc_lib:init_ack({ok, self()}),
start_module_sup(Port, Module),
?INFO_MSG("Start accepting TCP connections at ~s for ~p",
[format_portip(PortIP), Module]),
case erlang:function_exported(Module, tcp_init, 2) of
false ->
accept(ListenSocket, Module, Opts);
@ -182,29 +159,20 @@ init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) ->
end.
listen_tcp(PortIP, Module, SockOpts, Port, IPS) ->
case ets:lookup(listen_sockets, PortIP) of
[{PortIP, ListenSocket}] ->
{_, _, Transport} = PortIP,
?INFO_MSG("Reusing listening ~s port ~p at ~s",
[Transport, Port, IPS]),
ets:delete(listen_sockets, PortIP),
Res = gen_tcp:listen(Port, [binary,
{packet, 0},
{active, false},
{reuseaddr, true},
{nodelay, true},
{send_timeout, ?TCP_SEND_TIMEOUT},
{send_timeout_close, true},
{keepalive, true} |
SockOpts]),
case Res of
{ok, ListenSocket} ->
ListenSocket;
_ ->
Res = gen_tcp:listen(Port, [binary,
{packet, 0},
{active, false},
{reuseaddr, true},
{nodelay, true},
{send_timeout, ?TCP_SEND_TIMEOUT},
{send_timeout_close, true},
{keepalive, true} |
SockOpts]),
case Res of
{ok, ListenSocket} ->
ListenSocket;
{error, Reason} ->
socket_error(Reason, PortIP, Module, SockOpts, Port, IPS)
end
{error, Reason} ->
socket_error(Reason, PortIP, Module, SockOpts, Port, IPS)
end.
%% @spec (PortIP, Opts) -> {Port, IPT, IPS, IPV, OptsClean}
@ -388,7 +356,6 @@ start_listener2(Port, Module, Opts) ->
%% But it doesn't hurt to attempt to start it for any listener.
%% So, it's normal (and harmless) that in most cases this call returns: {error, {already_started, pid()}}
maybe_start_sip(Module),
start_module_sup(Port, Module),
start_listener_sup(Port, Module, Opts).
start_module_sup(_Port, Module) ->
@ -578,6 +545,13 @@ format_error(Reason) ->
ReasonStr
end.
format_portip({Port, IP, _Transport}) ->
IPStr = case tuple_size(IP) of
4 -> inet:ntoa(IP);
8 -> "[" ++ inet:ntoa(IP) ++ "]"
end,
IPStr ++ ":" ++ integer_to_list(Port).
check_rate_limit(Interval) ->
NewInterval = receive
{rate_limit, AcceptInterval} ->

View File

@ -32,8 +32,7 @@
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3]).
-export([start/0,
start_link/0,
-export([start_link/0,
get_client_identity/2,
verify_redirection_uri/3,
authenticate_user/2,
@ -70,32 +69,6 @@
-define(EXPIRE, 4294967).
start() ->
DBMod = get_db_backend(),
DBMod:init(),
MaxSize =
ejabberd_config:get_option(
oauth_cache_size,
fun(I) when is_integer(I), I>0 -> I end,
1000),
LifeTime =
ejabberd_config:get_option(
oauth_cache_life_time,
fun(I) when is_integer(I), I>0 -> I end,
timer:hours(1) div 1000),
cache_tab:new(oauth_token,
[{max_size, MaxSize}, {life_time, LifeTime}]),
Expire = expire(),
application:set_env(oauth2, backend, ejabberd_oauth),
application:set_env(oauth2, expiry_time, Expire),
application:start(oauth2),
ChildSpec = {?MODULE, {?MODULE, start_link, []},
transient, 1000, worker, [?MODULE]},
supervisor:start_child(ejabberd_sup, ChildSpec),
ejabberd_commands:register_commands(get_commands_spec()),
ok.
get_commands_spec() ->
[
#ejabberd_commands{name = oauth_issue_token, tags = [oauth],
@ -173,6 +146,25 @@ start_link() ->
init([]) ->
DBMod = get_db_backend(),
DBMod:init(),
MaxSize =
ejabberd_config:get_option(
oauth_cache_size,
fun(I) when is_integer(I), I>0 -> I end,
1000),
LifeTime =
ejabberd_config:get_option(
oauth_cache_life_time,
fun(I) when is_integer(I), I>0 -> I end,
timer:hours(1) div 1000),
cache_tab:new(oauth_token,
[{max_size, MaxSize}, {life_time, LifeTime}]),
Expire = expire(),
application:set_env(oauth2, backend, ejabberd_oauth),
application:set_env(oauth2, expiry_time, Expire),
application:start(oauth2),
ejabberd_commands:register_commands(get_commands_spec()),
erlang:send_after(expire() * 1000, self(), clean),
{ok, ok}.

View File

@ -25,67 +25,78 @@
-module(ejabberd_rdbms).
-behaviour(supervisor).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-export([start/0, opt_type/1, start_hosts/0, start_host/1, stop_host/1]).
-export([start_link/0, init/1, opt_type/1,
config_reloaded/0, start_host/1, stop_host/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
start() ->
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init([]) ->
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 ->
start_hosts();
false ->
ok
ejabberd_hooks:add(config_reloaded, ?MODULE, config_reloaded, 20),
{ok, {{one_for_one, 10, 1}, get_specs()}}.
-spec get_specs() -> [supervisor:child_spec()].
get_specs() ->
lists:flatmap(
fun(Host) ->
case get_spec(Host) of
{ok, Spec} -> [Spec];
undefined -> []
end
end, ?MYHOSTS).
-spec get_spec(binary()) -> {ok, supervisor:child_spec()} | undefined.
get_spec(Host) ->
case needs_sql(Host) of
{true, App} ->
ejabberd:start_app(App),
SupName = gen_mod:get_module_proc(Host, ejabberd_sql_sup),
{ok, {SupName, {ejabberd_sql_sup, start_link, [Host]},
transient, infinity, supervisor, [ejabberd_sql_sup]}};
false ->
undefined
end.
%% Start relationnal DB module on the nodes where it is needed
start_hosts() ->
-spec config_reloaded() -> ok.
config_reloaded() ->
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
case get_spec(Host) of
{ok, Spec} ->
case supervisor:start_child(?MODULE, Spec) of
{ok, _PID} ->
ok;
{error, {already_started, _}} ->
ok;
{error, _} = Err ->
erlang:error(Err)
end;
undefined ->
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),
supervisor:terminate_child(?MODULE, SupName),
supervisor:delete_child(?MODULE, SupName),
ok.
%% Start the SQL module on the given host
start_sql(Host, App) ->
ejabberd:start_app(App),
Supervisor_name = gen_mod:get_module_proc(Host,
ejabberd_sql_sup),
ChildSpec = {Supervisor_name,
{ejabberd_sql_sup, start_link, [Host]}, transient,
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.
%% Returns {true, App} if we have configured sql for the given host
needs_sql(Host) ->
LHost = jid:nameprep(Host),

View File

@ -28,7 +28,7 @@
-behaviour(ejabberd_config).
%% API
-export([start/0, stop/0, start_link/0, q/1, qp/1, host_up/1, opt_type/1]).
-export([start_link/0, q/1, qp/1, config_reloaded/0, opt_type/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@ -40,7 +40,7 @@
-include("logger.hrl").
-include("ejabberd.hrl").
-record(state, {}).
-record(state, {connection :: {pid(), reference()} | undefined}).
%%%===================================================================
%%% API
@ -48,19 +48,6 @@
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 ->
do_start();
false ->
stop()
end.
q(Command) ->
try eredis:q(?PROCNAME, Command)
catch _:Reason -> {error, Reason}
@ -71,22 +58,21 @@ 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
config_reloaded() ->
case is_redis_configured() of
true ->
?MODULE ! connect;
false ->
?MODULE ! disconnect
end.
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
init([]) ->
ejabberd_hooks:add(config_reloaded, ?MODULE, config_reloaded, 20),
process_flag(trap_exit, true),
connect(),
self() ! connect,
{ok, #state{}}.
handle_call(_Request, _From, State) ->
@ -96,13 +82,35 @@ handle_call(_Request, _From, State) ->
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(connect, #state{connection = undefined} = State) ->
NewState = case is_redis_configured() of
true ->
case connect() of
{ok, Connection} ->
State#state{connection = Connection};
{error, _} ->
State
end;
false ->
State
end,
{noreply, NewState};
handle_info(connect, State) ->
connect(),
%% Already connected
{noreply, State};
handle_info({'DOWN', _MRef, _Type, _Pid, Reason}, State) ->
handle_info(disconnect, #state{connection = {Pid, MRef}} = State) ->
?INFO_MSG("Disconnecting from Redis server", []),
erlang:demonitor(MRef, [flush]),
eredis:stop(Pid),
{noreply, State#state{connection = undefined}};
handle_info(disconnect, State) ->
%% Not connected
{noreply, State};
handle_info({'DOWN', MRef, _Type, Pid, Reason},
#state{connection = {Pid, MRef}} = State) ->
?INFO_MSG("Redis connection has failed: ~p", [Reason]),
connect(),
{noreply, State};
{noreply, State#state{connection = undefined}};
handle_info({'EXIT', _, _}, State) ->
{noreply, State};
handle_info(Info, State) ->
@ -110,7 +118,7 @@ handle_info(Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
ejabberd_hooks:delete(config_reloaded, ?MODULE, config_reloaded, 20).
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
@ -118,10 +126,8 @@ 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() ->
lists:any(fun is_redis_configured/1, ?MYHOSTS).
is_redis_configured(Host) ->
ServerConfigured = ejabberd_config:has_option({redis_server, Host}),
@ -181,9 +187,9 @@ connect() ->
{ok, Client} ->
?INFO_MSG("Connected to Redis at ~s:~p", [Server, Port]),
unlink(Client),
erlang:monitor(process, Client),
MRef = erlang:monitor(process, Client),
register(?PROCNAME, Client),
{ok, Client};
{ok, {Client, MRef}};
{error, Why} ->
erlang:error(Why)
end
@ -192,7 +198,8 @@ connect() ->
?ERROR_MSG("Redis connection at ~s:~p has failed: ~p; "
"reconnecting in ~p seconds",
[Server, Port, Reason, Timeout]),
erlang:send_after(timer:seconds(Timeout), self(), connect)
erlang:send_after(timer:seconds(Timeout), self(), connect),
{error, Reason}
end.
opt_type(redis_connect_timeout) ->

View File

@ -25,12 +25,13 @@
-module(ejabberd_riak_sup).
-behaviour(supervisor).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-export([start/0, stop/0, start_link/0, init/1, get_pids/0,
-export([start_link/0, init/1, get_pids/0,
transform_options/1, get_random_pid/0, get_random_pid/1,
host_up/1, opt_type/1]).
host_up/1, config_reloaded/0, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@ -44,34 +45,37 @@
% a timeout error to the request
-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)
end, ?MYHOSTS) of
true ->
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();
lists:foreach(
fun(Spec) ->
supervisor:start_child(?MODULE, Spec)
end, get_specs());
false ->
ok
end.
config_reloaded() ->
case is_riak_configured() of
true ->
ejabberd:start_app(riakc),
lists:foreach(
fun(Spec) ->
supervisor:start_child(?MODULE, Spec)
end, get_specs());
false ->
lists:foreach(
fun({Id, _, _, _}) ->
supervisor:terminate_child(?MODULE, Id),
supervisor:delete_child(?MODULE, Id)
end, supervisor:which_children(?MODULE))
end.
is_riak_configured() ->
lists:any(fun is_riak_configured/1, ?MYHOSTS).
is_riak_configured(Host) ->
ServerConfigured = ejabberd_config:get_option(
{riak_server, Host},
@ -92,30 +96,23 @@ is_riak_configured(Host) ->
ServerConfigured or PortConfigured
or AuthConfigured or ModuleWithRiakDBConfigured.
do_start() ->
ChildSpec =
{?MODULE,
{?MODULE, start_link, []},
transient,
infinity,
supervisor,
[?MODULE]},
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",
[?MODULE, _Error]),
timer:sleep(5000),
start()
end.
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init([]) ->
ejabberd_hooks:add(config_reloaded, ?MODULE, config_reloaded, 20),
ejabberd_hooks:add(host_up, ?MODULE, host_up, 20),
Specs = case is_riak_configured() of
true ->
ejabberd:start_app(riakc),
get_specs();
false ->
[]
end,
{ok, {{one_for_one, 500, 1}, Specs}}.
-spec get_specs() -> [supervisor:child_spec()].
get_specs() ->
PoolSize = get_pool_size(),
StartInterval = get_start_interval(),
Server = get_riak_server(),
@ -133,16 +130,14 @@ init([]) ->
if (Username /= nil) and (Password /= nil) ->
{credentials, Username, Password};
true -> nil
end
]),
{ok, {{one_for_one, PoolSize*10, 1},
lists:map(
fun(I) ->
{ejabberd_riak:get_proc(I),
{ejabberd_riak, start_link,
[I, Server, Port, StartInterval*1000, Options]},
transient, 2000, worker, [?MODULE]}
end, lists:seq(1, PoolSize))}}.
end]),
lists:map(
fun(I) ->
{ejabberd_riak:get_proc(I),
{ejabberd_riak, start_link,
[I, Server, Port, StartInterval*1000, Options]},
transient, 2000, worker, [?MODULE]}
end, lists:seq(1, PoolSize)).
get_start_interval() ->
ejabberd_config:get_option(

View File

@ -49,7 +49,7 @@
is_my_host/1,
get_backend/0]).
-export([start/0, start_link/0]).
-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3, opt_type/1]).
@ -78,11 +78,6 @@
%%====================================================================
%% API
%%====================================================================
start() ->
ChildSpec = {?MODULE, {?MODULE, start_link, []},
transient, 1000, worker, [?MODULE]},
supervisor:start_child(ejabberd_sup, ChildSpec).
start_link() ->
?GEN_SERVER:start_link({local, ?MODULE}, ?MODULE, [], []).

View File

@ -35,7 +35,7 @@
unregister_route/1
]).
-export([start/0, start_link/0]).
-export([start_link/0]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@ -56,11 +56,6 @@
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
%% Description: Starts the server
%%--------------------------------------------------------------------
start() ->
ChildSpec = {?MODULE, {?MODULE, start_link, []},
transient, 1000, worker, [?MODULE]},
supervisor:start_child(ejabberd_sup, ChildSpec).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

View File

@ -35,9 +35,7 @@
-behaviour(?GEN_SERVER).
%% API
-export([start/0,
stop/0,
start_link/0,
-export([start_link/0,
route/1,
route/2,
process_iq/1,
@ -110,17 +108,6 @@
%%====================================================================
-export_type([sid/0, info/0]).
start() ->
ChildSpec = {?MODULE, {?MODULE, start_link, []},
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, [], []).

View File

@ -101,8 +101,40 @@ init([]) ->
infinity,
supervisor,
[ejabberd_tmp_sup]},
BackendSupervisor = {ejabberd_backend_sup,
{ejabberd_backend_sup, start_link, []},
permanent, infinity, supervisor,
[ejabberd_backend_sup]},
ACL = {acl, {acl, start_link, []},
permanent, 5000, worker, [acl]},
Shaper = {shaper, {shaper, start_link, []},
permanent, 5000, worker, [shaper]},
SQLSupervisor = {ejabberd_rdbms,
{ejabberd_rdbms, start_link, []},
permanent, infinity, supervisor, [ejabberd_rdbms]},
RiakSupervisor = {ejabberd_riak_sup,
{ejabberd_riak_sup, start_link, []},
permanent, infinity, supervisor, [ejabberd_riak_sup]},
Redis = {ejabberd_redis, {ejabberd_redis, start_link, []},
permanent, 5000, worker, [ejabberd_redis]},
Router = {ejabberd_router, {ejabberd_router, start_link, []},
permanent, 5000, worker, [ejabberd_router]},
RouterMulticast = {ejabberd_router_multicast,
{ejabberd_router_multicast, start_link, []},
permanent, 5000, worker, [ejabberd_router_multicast]},
Local = {ejabberd_local, {ejabberd_local, start_link, []},
permanent, 5000, worker, [ejabberd_local]},
SM = {ejabberd_sm, {ejabberd_sm, start_link, []},
permanent, 5000, worker, [ejabberd_sm]},
GenModSupervisor = {ejabberd_gen_mod_sup, {gen_mod, start_link, []},
permanent, infinity, supervisor, [gen_mod]},
Auth = {ejabberd_auth, {ejabberd_auth, start_link, []},
permanent, 5000, worker, [ejabberd_auth]},
OAuth = {ejabberd_oauth, {ejabberd_oauth, start_link, []},
permanent, 5000, worker, [ejabberd_oauth]},
{ok, {{one_for_one, 10, 1},
[Hooks,
Listener,
SystemMonitor,
S2S,
Captcha,
@ -110,4 +142,16 @@ init([]) ->
S2SOutSupervisor,
ServiceSupervisor,
IQSupervisor,
Listener]}}.
ACL,
Shaper,
BackendSupervisor,
SQLSupervisor,
RiakSupervisor,
Redis,
Router,
RouterMulticast,
Local,
SM,
GenModSupervisor,
Auth,
OAuth]}}.

View File

@ -32,7 +32,7 @@
-export([init/1, start_link/0, start_child/3, start_child/4,
stop_child/1, stop_child/2, config_reloaded/0]).
-export([start/0, start_module/2, start_module/3,
-export([start_module/2, start_module/3,
stop_module/2, stop_module_keep_config/2, get_opt/3,
get_opt/4, get_opt_host/3, opt_type/1, is_equal_opt/5,
get_module_opt/4, get_module_opt/5, get_module_opt_host/3,
@ -70,13 +70,14 @@
-define(GEN_SERVER, gen_server).
-endif.
start() ->
Spec = {ejabberd_gen_mod_sup, {?MODULE, start_link, []},
permanent, infinity, supervisor, [?MODULE]},
supervisor:start_child(ejabberd_sup, Spec).
start_link() ->
supervisor:start_link({local, ejabberd_gen_mod_sup}, ?MODULE, []).
case supervisor:start_link({local, ejabberd_gen_mod_sup}, ?MODULE, []) of
{ok, Pid} ->
gen_mod:start_modules(),
{ok, Pid};
Err ->
Err
end.
init([]) ->
ejabberd_hooks:add(config_reloaded, ?MODULE, config_reloaded, 50),

View File

@ -96,12 +96,12 @@ start(Host, Opts) ->
TmpSupSpec = {TmpSup,
{ejabberd_tmp_sup, start_link, [TmpSup, ejabberd_bosh]},
permanent, infinity, supervisor, [ejabberd_tmp_sup]},
supervisor:start_child(ejabberd_sup, TmpSupSpec).
supervisor:start_child(ejabberd_gen_mod_sup, TmpSupSpec).
stop(Host) ->
TmpSup = gen_mod:get_module_proc(Host, ?MODULE),
supervisor:terminate_child(ejabberd_sup, TmpSup),
supervisor:delete_child(ejabberd_sup, TmpSup).
supervisor:terminate_child(ejabberd_gen_mod_sup, TmpSup),
supervisor:delete_child(ejabberd_gen_mod_sup, TmpSup).
reload(_Host, NewOpts, _OldOpts) ->
start_jiffy(NewOpts),

View File

@ -237,13 +237,13 @@ start_supervisor(Host) ->
{ejabberd_tmp_sup, start_link,
[Proc, mod_irc_connection]},
permanent, infinity, supervisor, [ejabberd_tmp_sup]},
supervisor:start_child(ejabberd_sup, ChildSpec).
supervisor:start_child(ejabberd_gen_mod_sup, ChildSpec).
stop_supervisor(Host) ->
Proc = gen_mod:get_module_proc(Host,
ejabberd_mod_irc_sup),
supervisor:terminate_child(ejabberd_sup, Proc),
supervisor:delete_child(ejabberd_sup, Proc).
supervisor:terminate_child(ejabberd_gen_mod_sup, Proc),
supervisor:delete_child(ejabberd_gen_mod_sup, Proc).
do_route(Host, ServerHost, Access, Packet) ->
#jid{luser = LUser, lresource = LResource} = xmpp:get_to(Packet),

View File

@ -59,14 +59,14 @@ start(Host, Opts) ->
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]},
transient, infinity, supervisor, [?MODULE]},
supervisor:start_child(ejabberd_sup, ChildSpec)
supervisor:start_child(ejabberd_gen_mod_sup, ChildSpec)
end.
stop(Host) ->
mod_proxy65_service:delete_listener(Host),
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
supervisor:terminate_child(ejabberd_sup, Proc),
supervisor:delete_child(ejabberd_sup, Proc).
supervisor:terminate_child(ejabberd_gen_mod_sup, Proc),
supervisor:delete_child(ejabberd_gen_mod_sup, Proc).
reload(Host, NewOpts, OldOpts) ->
Mod = gen_mod:ram_db_mod(global, ?MODULE),

View File

@ -50,7 +50,7 @@ start_link() ->
init() ->
Spec = {?MODULE, {?MODULE, start_link, []}, transient,
5000, worker, [?MODULE]},
supervisor:start_child(ejabberd_sup, Spec).
supervisor:start_child(ejabberd_backend_sup, Spec).
register_stream(SHA1, StreamPid) ->
F = fun () ->

View File

@ -55,8 +55,8 @@ start(_Host, _Opts) ->
{ejabberd_tmp_sup, start_link,
[mod_sip_proxy_sup, mod_sip_proxy]},
permanent, infinity, supervisor, [ejabberd_tmp_sup]},
supervisor:start_child(ejabberd_sup, Spec),
supervisor:start_child(ejabberd_sup, TmpSupSpec),
supervisor:start_child(ejabberd_gen_mod_sup, Spec),
supervisor:start_child(ejabberd_gen_mod_sup, TmpSupSpec),
ok.
stop(_Host) ->

View File

@ -81,12 +81,12 @@ init(Host, Opts) ->
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]},
transient, 1000, worker, [?MODULE]},
supervisor:start_child(ejabberd_sup, ChildSpec).
supervisor:start_child(ejabberd_backend_sup, ChildSpec).
stop(Host) ->
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
supervisor:terminate_child(ejabberd_sup, Proc),
supervisor:delete_child(ejabberd_sup, Proc),
supervisor:terminate_child(ejabberd_backend_sup, Proc),
supervisor:delete_child(ejabberd_backend_sup, Proc),
ok.
is_search_supported(_LServer) ->

View File

@ -29,13 +29,8 @@
-export([get_string/0, uniform/0, uniform/1, bytes/1]).
-export([start/0]).
-define(THRESHOLD, 16#10000000000000000).
start() ->
ok.
get_string() ->
R = crypto:rand_uniform(0, ?THRESHOLD),
integer_to_binary(R).

View File

@ -25,13 +25,17 @@
-module(shaper).
-behaviour(gen_server).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-export([start/0, new/1, new1/1, update/2,
-export([start_link/0, new/1, new1/1, update/2,
get_max_rate/1, transform_options/1, load_from_config/0,
opt_type/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include("ejabberd.hrl").
-include("logger.hrl").
@ -43,13 +47,17 @@
-record(shaper, {name :: {atom(), global},
maxrate :: integer()}).
-record(state, {}).
-type shaper() :: none | #maxrate{}.
-export_type([shaper/0]).
-spec start() -> ok.
-spec start_link() -> {ok, pid()} | {error, any()}.
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
start() ->
init([]) ->
ejabberd_mnesia:create(?MODULE, shaper,
[{ram_copies, [node()]},
{local_content, true},
@ -57,8 +65,24 @@ start() ->
mnesia:add_table_copy(shaper, node(), ram_copies),
ejabberd_hooks:add(config_reloaded, ?MODULE, load_from_config, 20),
load_from_config(),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
-spec load_from_config() -> ok | {error, any()}.
load_from_config() ->