diff --git a/src/ejabberd_option.erl b/src/ejabberd_option.erl index 88f7ccbee..b0a6adfe8 100644 --- a/src/ejabberd_option.erl +++ b/src/ejabberd_option.erl @@ -975,10 +975,10 @@ sql_start_interval() -> sql_start_interval(Host) -> ejabberd_config:get_option({sql_start_interval, Host}). --spec sql_type() -> 'mssql' | 'mysql' | 'odbc' | 'pgsql' | 'sqlite' | 'undefined'. +-spec sql_type() -> 'mssql' | 'mysql' | 'odbc' | 'pgsql' | 'sqlite'. sql_type() -> sql_type(global). --spec sql_type(global | binary()) -> 'mssql' | 'mysql' | 'odbc' | 'pgsql' | 'sqlite' | 'undefined'. +-spec sql_type(global | binary()) -> 'mssql' | 'mysql' | 'odbc' | 'pgsql' | 'sqlite'. sql_type(Host) -> ejabberd_config:get_option({sql_type, Host}). diff --git a/src/ejabberd_options.erl b/src/ejabberd_options.erl index e2250a333..f7025fe7f 100644 --- a/src/ejabberd_options.erl +++ b/src/ejabberd_options.erl @@ -599,7 +599,7 @@ options() -> fun(Host) -> ejabberd_config:default_ram_db(Host, ejabberd_sm) end}, {sm_use_cache, fun(Host) -> ejabberd_config:get_option({use_cache, Host}) end}, - {sql_type, undefined}, + {sql_type, odbc}, {sql_connect_timeout, timer:seconds(5)}, {sql_database, undefined}, {sql_keepalive_interval, undefined}, diff --git a/src/ejabberd_rdbms.erl b/src/ejabberd_rdbms.erl deleted file mode 100644 index b3cbe6ec1..000000000 --- a/src/ejabberd_rdbms.erl +++ /dev/null @@ -1,122 +0,0 @@ -%%%---------------------------------------------------------------------- -%%% File : ejabberd_rdbms.erl -%%% Author : Mickael Remond -%%% Purpose : Manage the start of the database modules when needed -%%% Created : 31 Jan 2003 by Alexey Shchepin -%%% -%%% -%%% ejabberd, Copyright (C) 2002-2019 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_rdbms). - --behaviour(supervisor). - --author('alexey@process-one.net'). - --export([start_link/0, init/1, stop/0, - config_reloaded/0, start_host/1, stop_host/1]). - --include("logger.hrl"). - -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, config_reloaded, 20), - {ok, {{one_for_one, 10, 1}, get_specs()}}. - -stop() -> - ejabberd_hooks:delete(host_up, ?MODULE, start_host, 20), - ejabberd_hooks:delete(host_down, ?MODULE, stop_host, 90), - ejabberd_hooks:delete(config_reloaded, ?MODULE, config_reloaded, 20), - ejabberd_sup:stop_child(?MODULE). - --spec get_specs() -> [supervisor:child_spec()]. -get_specs() -> - lists:flatmap( - fun(Host) -> - case get_spec(Host) of - {ok, Spec} -> [Spec]; - undefined -> [] - end - end, ejabberd_option:hosts()). - --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. - --spec config_reloaded() -> ok. -config_reloaded() -> - lists:foreach(fun reload_host/1, ejabberd_option:hosts()). - --spec start_host(binary()) -> ok. -start_host(Host) -> - 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 | {error, atom()}. -stop_host(Host) -> - SupName = gen_mod:get_module_proc(Host, ejabberd_sql_sup), - case supervisor:terminate_child(?MODULE, SupName) of - ok -> supervisor:delete_child(?MODULE, SupName); - Err -> Err - end. - --spec reload_host(binary()) -> ok. -reload_host(Host) -> - case needs_sql(Host) of - {true, _} -> ejabberd_sql_sup:reload(Host); - false -> ok - end. - -%% Returns {true, App} if we have configured sql for the given host -needs_sql(Host) -> - LHost = jid:nameprep(Host), - case ejabberd_option:sql_type(LHost) of - mysql -> {true, p1_mysql}; - pgsql -> {true, p1_pgsql}; - sqlite -> {true, sqlite3}; - mssql -> {true, odbc}; - odbc -> {true, odbc}; - undefined -> false - end. diff --git a/src/ejabberd_sql.erl b/src/ejabberd_sql.erl index d085d3ee4..92642e7b7 100644 --- a/src/ejabberd_sql.erl +++ b/src/ejabberd_sql.erl @@ -141,8 +141,8 @@ sql_call(Host, Msg) -> Timeout = query_timeout(Host), case get(?STATE_KEY) of undefined -> - Proc = get_worker(Host), - sync_send_event(Proc, {sql_cmd, Msg, current_time() + Timeout}, + sync_send_event(Host, + {sql_cmd, Msg, current_time() + Timeout}, Timeout); _State -> nested_op(Msg) @@ -161,6 +161,14 @@ keep_alive(Host, Proc) -> sync_send_event(Proc, force_timeout, Timeout) end. +sync_send_event(Host, Msg, Timeout) when is_binary(Host) -> + case ejabberd_sql_sup:start(Host) of + ok -> + Proc = get_worker(Host), + sync_send_event(Proc, Msg, Timeout); + {error, _} = Err -> + Err + end; sync_send_event(Proc, Msg, Timeout) -> try p1_fsm:sync_send_event(Proc, Msg, Timeout) catch _:{Reason, {p1_fsm, _, _}} -> @@ -993,10 +1001,7 @@ log(Level, Format, Args) -> end. db_opts(Host) -> - Type = case ejabberd_option:sql_type(Host) of - undefined -> odbc; - T -> T - end, + Type = ejabberd_option:sql_type(Host), Server = ejabberd_option:sql_server(Host), Timeout = ejabberd_option:sql_connect_timeout(Host), Transport = case ejabberd_option:sql_ssl(Host) of diff --git a/src/ejabberd_sql_sup.erl b/src/ejabberd_sql_sup.erl index 6d1e63b48..782cc37d4 100644 --- a/src/ejabberd_sql_sup.erl +++ b/src/ejabberd_sql_sup.erl @@ -27,15 +27,67 @@ -author('alexey@process-one.net'). --export([start_link/1, init/1, reload/1, is_started/1]). +-export([start/1, stop/1, stop/0]). +-export([start_link/0, start_link/1]). +-export([init/1, reload/1, config_reloaded/0, is_started/1]). -include("logger.hrl"). +start(Host) -> + case is_started(Host) of + true -> ok; + false -> + App = case ejabberd_option:sql_type(Host) of + mysql -> p1_mysql; + pgsql -> p1_pgsql; + sqlite -> sqlite3; + _ -> odbc + end, + ejabberd:start_app(App), + Spec = #{id => gen_mod:get_module_proc(Host, ?MODULE), + start => {ejabberd_sql_sup, start_link, [Host]}, + restart => transient, + shutdown => infinity, + type => supervisor, + modules => [?MODULE]}, + case supervisor:start_child(ejabberd_db_sup, Spec) of + {ok, _} -> ok; + {error, {already_started, _}} -> ok; + {error, Why} = Err -> + ?ERROR_MSG("Failed to start ~s: ~p", [?MODULE, Why]), + Err + end + end. + +stop(Host) -> + Proc = gen_mod:get_module_proc(Host, ?MODULE), + case supervisor:terminate_child(ejabberd_db_sup, Proc) of + ok -> supervisor:delete_child(ejabberd_db_sup, Proc); + Err -> Err + end. + + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + start_link(Host) -> supervisor:start_link({local, gen_mod:get_module_proc(Host, ?MODULE)}, ?MODULE, [Host]). +stop() -> + ejabberd_hooks:delete(host_up, ?MODULE, start, 20), + ejabberd_hooks:delete(host_down, ?MODULE, stop, 90), + ejabberd_hooks:delete(config_reloaded, ?MODULE, config_reloaded, 20). + +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, 20), + ejabberd_hooks:add(host_down, ?MODULE, stop, 90), + ejabberd_hooks:add(config_reloaded, ?MODULE, config_reloaded, 20), + ignore; init([Host]) -> Type = ejabberd_option:sql_type(Host), PoolSize = get_pool_size(Type, Host), @@ -49,6 +101,10 @@ init([Host]) -> end, {ok, {{one_for_one, PoolSize * 10, 1}, child_specs(Host, PoolSize)}}. +-spec config_reloaded() -> ok. +config_reloaded() -> + lists:foreach(fun reload/1, ejabberd_option:hosts()). + -spec reload(binary()) -> ok. reload(Host) -> case is_started(Host) of diff --git a/src/ejabberd_sup.erl b/src/ejabberd_sup.erl index cb8c3fa86..00b84eebb 100644 --- a/src/ejabberd_sup.erl +++ b/src/ejabberd_sup.erl @@ -51,7 +51,7 @@ init([]) -> worker(ejabberd_shaper), supervisor(ejabberd_db_sup), supervisor(ejabberd_backend_sup), - supervisor(ejabberd_rdbms), + supervisor(ejabberd_sql_sup), worker(ejabberd_iq), worker(ejabberd_router), worker(ejabberd_router_multicast),