]> granicus.if.org Git - ejabberd/commitdiff
Improve startup procedure
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>
Fri, 24 Feb 2017 09:05:47 +0000 (12:05 +0300)
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>
Fri, 24 Feb 2017 09:05:47 +0000 (12:05 +0300)
23 files changed:
src/acl.erl
src/ejabberd_app.erl
src/ejabberd_auth.erl
src/ejabberd_auth_ldap.erl
src/ejabberd_backend_sup.erl [new file with mode: 0644]
src/ejabberd_listener.erl
src/ejabberd_oauth.erl
src/ejabberd_rdbms.erl
src/ejabberd_redis.erl
src/ejabberd_riak_sup.erl
src/ejabberd_router.erl
src/ejabberd_router_multicast.erl
src/ejabberd_sm.erl
src/ejabberd_sup.erl
src/gen_mod.erl
src/mod_bosh.erl
src/mod_irc.erl
src/mod_proxy65.erl
src/mod_proxy65_mnesia.erl
src/mod_sip.erl
src/mod_vcard_ldap.erl
src/randoms.erl
src/shaper.erl

index 99c8e17eb7c74c8b2824f6e6300dde0dd1be5705..40ab682e5dea98a38d83d1a56211ef65b8486237 100644 (file)
 
 -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().
 
 -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) ->
index 1340607cd34453a620b1aaa91013e8ef5b952442..e51c31cd0c388356c4b549249316411d9fc9e11e 100644 (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(),
index fd5b6b2444fb65eba854a1184cc5b63fa5eb3dc8..1639a3a54fae3ef4ca6b3e9955db600084083895 100644 (file)
 
 -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,
         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]).
 -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),
index 18770a512d45f065c5ccb68643c79119af2654f5..059a66e7ba6ba205256ba2cf1633ef7369f83c4f 100644 (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),
diff --git a/src/ejabberd_backend_sup.erl b/src/ejabberd_backend_sup.erl
new file mode 100644 (file)
index 0000000..c9492be
--- /dev/null
@@ -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
+%%%===================================================================
index bad1da134c87f4fec5acca779c2ce397e68eb580..97dd88582d0b4d35fdc92e60de23445fecc3906b 100644 (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} ->
index 61944a79d614f83d75478328862632a2ff7bde1c..a4e8bb6ca1dce420998a7da55e1dbf09b4bbc46a 100644 (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,
 
 -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}.
 
index 5fc73c624f31322823d1cfd6fe9f463702727e50..0f89e333ed38bba41f753ef231c3bf51ab7dbbda 100644 (file)
 
 -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),
index 6a853737d1eb3c520f1b9d3ce02d8edadcc00767..f349baac534fcad972cd8e002bf4771f38b84a9d 100644 (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
 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) ->
index d1ab126f8b2e066434251679195dfdc2afc19dfe..12b701b476833c802a1a81971307c08ec0ab80ef 100644 (file)
 
 -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").
 % 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
+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 ->
-           stop()
+           ok
     end.
 
-stop() ->
-    supervisor:terminate_child(ejabberd_sup, ?MODULE),
-    supervisor:delete_child(ejabberd_sup, ?MODULE),
-    ok.
-
-host_up(Host) ->
-    case is_riak_configured(Host) of
+config_reloaded() ->
+    case is_riak_configured() of
        true ->
            ejabberd:start_app(riakc),
-            do_start();
+           lists:foreach(
+             fun(Spec) ->
+                     supervisor:start_child(?MODULE, Spec)
+             end, get_specs());
        false ->
-           ok
+           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(
index 075becad0e15743e6a900981df9a8a890d4cf80b..17b43c15de60cdad481c2d738faa92cb04614ebf 100644 (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]).
 %%====================================================================
 %% 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, [], []).
 
index bb2442b4ffd6ea8ba9b28b5e64db8112e7c688d6..ff2862a72c18b848175cd4b04cf6c1889a50be39 100644 (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,
 %% 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, [], []).
 
index aa7c1d080057d0066d0add00635883d27083e0d2..173b9a2ad6d0976747c9eca7c929f5cad3a9d7a4 100644 (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,
 %%====================================================================
 -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, [], []).
 
index f9a48be4d767c03d60f19f935c12004959d84010..d8f93ce02a1e33079d436cda3378b21aa6be5941 100644 (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]}}.
index 77edb0e906f43995a61a3765439004f02c40a54d..63bfa314b6344215a9536f21c60a16175528af74 100644 (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,
 -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),
index 049504ee4b7a41e831e5c16180629817965d548f..abe3c2f16a75c8579bc5b8d13f68df5a7de29ad1 100644 (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),
index 37d54954b84897ff6dc394caa1c2a69a444b2886..c7af2834b1f6387f5e24bbbf6c0924758950fee7 100644 (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),
index e8183b21fb33400b9100d973cac117c772eb8a43..d7793115e12aee9af71f3031873b4b564253a852 100644 (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),
index 6e36436067361b7ead91e607b480b32b0809a469..2763fab6aa734a67bbab5cc8729084dcff8dbcfa 100644 (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 () ->
index c34a90795a9535b1f35ba9d597bb63adf8e0f193..eb5cbe5453af5993239cba2849b5708a280ad918 100644 (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) ->
index aa669897e7c83b8982ca5f2027efdd61f73f2b0b..eb9f584efa5ec467938d2befdbd799a7a3f25ca5 100644 (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) ->
index 90cc34f1003f3e4d4948c4e102ee0dbb288bc90d..a5e33becdbb3041c88ec7e51cf00a255a78e7be2 100644 (file)
 
 -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).
index a2f76b1c49da067ceda1fe58b002eaa80e2659bb..cc1923f86c02a113b33bbc72887e86bbf4a611b1 100644 (file)
 
 -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").
 -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() ->