diff --git a/apps/ejabberd/src/ejabberd_config.erl b/apps/ejabberd/src/ejabberd_config.erl index 3a09321c586..651c7d158e8 100644 --- a/apps/ejabberd/src/ejabberd_config.erl +++ b/apps/ejabberd/src/ejabberd_config.erl @@ -77,6 +77,7 @@ -record(state, {opts = [] :: list(), hosts = [] :: [host()], + odbc_pools = [] :: [atom()], override_local = false :: boolean(), override_global = false :: boolean(), override_acls = false :: boolean()}). @@ -177,10 +178,7 @@ get_ejabberd_config_path() -> %% This function will crash if finds some error in the configuration file. -spec load_file(File :: string()) -> ok. load_file(File) -> - Terms = get_plain_terms_file(File), - State = lists:foldl(fun search_hosts/2, #state{}, Terms), - TermsMacros = replace_macros(Terms), - Res = lists:foldl(fun process_term/2, State, TermsMacros), + Res = parse_file(File), set_opts(Res). @@ -220,8 +218,10 @@ get_absolute_path(File) -> end. --spec search_hosts({host|hosts, [host()] | host()}, state()) -> any(). -search_hosts(Term, State) -> +-spec search_hosts_and_pools({host|hosts, [host()] | host()} + | {pool, odbc, atom()} + | {pool, odbc, atom(), list()}, state()) -> any(). +search_hosts_and_pools(Term, State) -> case Term of {host, Host} -> case State of @@ -241,6 +241,10 @@ search_hosts(Term, State) -> "too many hosts definitions", []), exit("too many hosts definitions") end; + {pool, PoolType, PoolName, _Options} -> + search_hosts_and_pools({pool, PoolType, PoolName}, State); + {pool, odbc, PoolName} -> + add_odbc_pool_to_option(PoolName, State); _ -> State end. @@ -252,6 +256,9 @@ add_hosts_to_option(Hosts, State) -> PrepHosts = normalize_hosts(Hosts), add_option(hosts, PrepHosts, State#state{hosts = PrepHosts}). +add_odbc_pool_to_option(PoolName, State) -> + Pools = State#state.odbc_pools, + State#state{odbc_pools = [PoolName | Pools]}. -spec normalize_hosts([host()]) -> [binary() | tuple()]. normalize_hosts(Hosts) -> @@ -508,6 +515,13 @@ process_term(Term, State) -> lists:foldl(fun(T, S) -> process_host_term(T, list_to_binary(Host), S) end, State, Terms); + {pool, odbc, _PoolName} -> + State; + {pool, odbc, PoolName, Options} -> + lists:foldl(fun(T, S) -> + process_db_pool_term(T, PoolName, S) + end, + State, Options); {listen, Listeners} -> Listeners2 = lists:map( @@ -576,11 +590,20 @@ process_term(Term, State) -> {all_metrics_are_global, Value} -> add_option(all_metrics_are_global, Value, State); {_Opt, _Val} -> + process_term_for_hosts_and_pools(Term, State) + end. + +process_term_for_hosts_and_pools(Term = {Key, _Val}, State) -> + BKey = atom_to_binary(Key, utf8), + case get_key_group(BKey, Key) of + odbc -> + lists:foldl(fun(Pool, S) -> process_db_pool_term(Term, Pool, S) end, + State, State#state.odbc_pools); + _ -> lists:foldl(fun(Host, S) -> process_host_term(Term, Host, S) end, State, State#state.hosts) end. - -spec process_host_term(Term :: host_term(), Host :: acl:host(), State :: state()) -> state(). @@ -601,8 +624,8 @@ process_host_term(Term, Host, State) -> State; {hosts, _Hosts} -> State; - {odbc_server, ODBCServer} -> - add_option({odbc_server, Host}, ODBCServer, State); + {odbc_pool, Pool} when is_atom(Pool) -> + add_option({odbc_pool, Host}, Pool, State); {riak_server, RiakConfig} -> add_option(riak_server, RiakConfig, State); {cassandra_servers, CassandraConfig} -> @@ -611,6 +634,8 @@ process_host_term(Term, Host, State) -> add_option({Opt, Host}, Val, State) end. +process_db_pool_term({Opt, Val}, Pool, State) when is_atom(Pool) -> + add_option({Opt, odbc_pool, Pool}, Val, State). -spec add_option(Opt :: key(), Val :: value(), @@ -786,9 +811,11 @@ is_file_readable(Path) -> -spec parse_file(file:name()) -> state(). parse_file(ConfigFile) -> Terms = get_plain_terms_file(ConfigFile), - State = lists:foldl(fun search_hosts/2, #state{}, Terms), + State = lists:foldl(fun search_hosts_and_pools/2, #state{}, Terms), TermsWExpandedMacros = replace_macros(Terms), - lists:foldl(fun process_term/2, State, TermsWExpandedMacros). + lists:foldl(fun process_term/2, + add_option(odbc_pools, State#state.odbc_pools, State), + TermsWExpandedMacros). -spec reload_local() -> {ok, iolist()} | no_return(). reload_local() -> @@ -1047,8 +1074,6 @@ handle_local_config_change({Key, _Old, _New} = El) -> handle_local_hosts_config_add({{auth, Host}, _}) -> ejabberd_auth:start(Host); -handle_local_hosts_config_add({{odbc, Host}, _}) -> - ejabberd_rdbms:start(Host); handle_local_hosts_config_add({{ldap, _Host}, _}) -> %% ignore ldap section ok; @@ -1072,8 +1097,6 @@ handle_local_hosts_config_del({{auth, Host}, Opts}) -> M:stop(Host) end, AuthModules) end; -handle_local_hosts_config_del({{odbc, Host}, _}) -> - ejabberd_rdbms:stop_odbc(Host); handle_local_hosts_config_del({{ldap, _Host}, _I}) -> %% ignore ldap section, only appli ok; @@ -1087,15 +1110,6 @@ handle_local_hosts_config_del({{Key, _}, _} =El) -> ?WARNING_MSG("local hosts config delete option: ~p unhandled", [El]) end. -handle_local_hosts_config_change({{odbc, Host}, Old, _}) -> - %% stop rdbms - case lists:keyfind({odbc_server, Host}, 1, Old) of - false -> - ok; - #local_config{} -> - ejabberd_rdbms:stop_odbc(Host) - end, - ejabberd_rdbms:start(Host); handle_local_hosts_config_change({{auth, Host}, OldVals, _}) -> case lists:keyfind(auth_method, 1, OldVals) of false -> @@ -1149,9 +1163,10 @@ add_virtual_host(Host) -> ?DEBUG("Register host:~p", [Host]), ejabberd_local:register_host(Host). --spec can_be_ignored(Key :: atom()) -> boolean(). -can_be_ignored(Key) when is_atom(Key) -> - L = [domain_certfile, s2s, all_metrics_are_global], +-spec can_be_ignored(Key :: atom() | tuple()) -> boolean(). +can_be_ignored(Key) when is_atom(Key); + is_tuple(Key) -> + L = [domain_certfile, s2s, all_metrics_are_global, odbc], lists:member(Key, L). -spec remove_virtual_host(ejabberd:server()) -> any(). @@ -1219,11 +1234,16 @@ get_local_config() -> get_global_config() -> mnesia:dirty_match_object(config, {config, '_', '_'}). --spec is_not_host_specific(atom() | {atom(), ejabberd:server()}) -> boolean(). +-spec is_not_host_specific(atom() + | {atom(), ejabberd:server()} + | {atom(), atom(), atom()}) -> boolean(). is_not_host_specific(Key) when is_atom(Key) -> true; is_not_host_specific({Key, Host}) when is_atom(Key), is_binary(Host) -> - false. + false; +is_not_host_specific({Key, PoolType, PoolName}) + when is_atom(Key), is_atom(PoolType), is_atom(PoolName) -> + true. -spec categorize_options([term()]) -> {GlobalConfig, LocalConfig, HostsConfig} when GlobalConfig :: list(), diff --git a/apps/ejabberd/src/ejabberd_rdbms.erl b/apps/ejabberd/src/ejabberd_rdbms.erl index cdc4f89f437..06cd0e607c8 100644 --- a/apps/ejabberd/src/ejabberd_rdbms.erl +++ b/apps/ejabberd/src/ejabberd_rdbms.erl @@ -27,7 +27,7 @@ -module(ejabberd_rdbms). -author('alexey@process-one.net'). --export([start/0, start/1, stop/1, stop_odbc/1]). +-export([start/0, start_pool/1, stop_pool/1, pools/0]). -include("ejabberd.hrl"). -spec start() -> 'ok' | {'error', 'lager_not_running'}. @@ -39,63 +39,29 @@ start() -> ?INFO_MSG("MongooseIM has not been compiled with relational database support. " "Skipping database startup.", []); _ -> - %% If compiled with ODBC, start ODBC on the needed host - start_hosts() + {ok, _Pid} = start_pool_sup(), + [start_pool(Pool) || Pool <- pools()], + ok end. -%% @doc Start relationnal DB module on the nodes where it is needed --spec start_hosts() -> 'ok'. -start_hosts() -> - lists:foreach(fun start/1, ?MYHOSTS). - --spec stop(Host :: ejabberd:server()) -> 'ok'. -stop(Host) -> - case needs_odbc(Host) of - true -> stop_odbc(Host); - false -> ok - end. - --spec start(Host :: ejabberd:server()) -> 'ok'. -start(Host) -> - case needs_odbc(Host) of - true -> start_odbc(Host); - false -> ok - end. - -%% @doc Start the ODBC module on the given host --spec start_odbc(binary() | string()) -> 'ok'. -start_odbc(Host) -> - Supervisor_name = gen_mod:get_module_proc(Host, mongoose_rdbms_sup), +start_pool_sup() -> ChildSpec = - {Supervisor_name, - {mongoose_rdbms_sup, start_link, [Host]}, + {mongoose_rdbms_sup, + {mongoose_rdbms_sup, start_link, []}, transient, infinity, supervisor, [mongoose_rdbms_sup]}, - case supervisor:start_child(ejabberd_sup, ChildSpec) of - {ok, _PID} -> - ok; - _Error -> - ?ERROR_MSG("Start of supervisor ~p failed:~n~p~nRetrying...~n", - [Supervisor_name, _Error]), - start_odbc(Host) - end. + supervisor:start_child(ejabberd_sup, ChildSpec). --spec stop_odbc(binary() | string()) -> 'ok'. -stop_odbc(Host) -> - Proc = gen_mod:get_module_proc(Host, mongoose_rdbms_sup), - supervisor:terminate_child(ejabberd_sup, Proc). +pools() -> + ejabberd_config:get_local_option_or_default(odbc_pools, []). -%% @doc Returns true if we have configured odbc_server for the given host --spec needs_odbc(_) -> boolean(). -needs_odbc(Host) -> - LHost = jid:nameprep(Host), - case ejabberd_config:get_local_option({odbc_server, LHost}) of - undefined -> - false; - _ -> true - end. +start_pool(Pool) -> + mongoose_rdbms_sup:add_pool(Pool). + +stop_pool(Pool) -> + mongoose_rdbms_sup:remove_pool(Pool). compile_odbc_type_helper() -> Key = {odbc_server_type, ?MYNAME}, diff --git a/apps/ejabberd/src/mod_mam_meta.erl b/apps/ejabberd/src/mod_mam_meta.erl index 656d485d9e3..76f38271d73 100644 --- a/apps/ejabberd/src/mod_mam_meta.erl +++ b/apps/ejabberd/src/mod_mam_meta.erl @@ -159,8 +159,8 @@ add_default_odbc_opts(Opts) -> [{cache_users, true}, {async_writer, true}]). --spec parse_backend_opt(Option :: {module(), term()}, Type :: pm | muc, - module(), module(), deps()) -> deps(). +-spec parse_backend_opt(Type :: pm | muc, module(), module(), + Option :: {module(), term()}, deps()) -> deps(). parse_backend_opt(Type, ModODBCArch, ModAsyncWriter, Option, Deps) -> case Option of {cache_users, true} -> @@ -176,6 +176,8 @@ parse_backend_opt(Type, ModODBCArch, ModAsyncWriter, Option, Deps) -> {async_writer, true} -> DepsWithNoWriter = add_dep(ModODBCArch, [no_writer], Deps), add_dep(ModAsyncWriter, [Type], DepsWithNoWriter); + {async_writer_odbc_pool, PoolName} -> + add_dep(ModAsyncWriter, [{odbc_pool, PoolName}], Deps); _ -> Deps end. diff --git a/apps/ejabberd/src/mod_mam_muc_odbc_async_pool_writer.erl b/apps/ejabberd/src/mod_mam_muc_odbc_async_pool_writer.erl index 96d04ee8128..9b8f5d2c94d 100644 --- a/apps/ejabberd/src/mod_mam_muc_odbc_async_pool_writer.erl +++ b/apps/ejabberd/src/mod_mam_muc_odbc_async_pool_writer.erl @@ -89,8 +89,7 @@ worker_number(Host, ArcID) -> -spec start(ejabberd:server(), _) -> 'ok'. start(Host, Opts) -> - PoolName = gen_mod:get_module_proc(Host, ?MODULE), - {ok, _} = mongoose_rdbms_sup:add_pool(Host, ?MODULE, PoolName, worker_count(Host)), + PoolName = gen_mod:get_opt(odbc_pool, Opts, mongoose_rdbms_sup:pool(Host)), MaxSize = gen_mod:get_module_opt(Host, ?MODULE, max_packet_size, 30), mod_mam_muc_odbc_arch:prepare_insert(insert_mam_muc_message, 1), mod_mam_muc_odbc_arch:prepare_insert(insert_mam_muc_messages, MaxSize), @@ -101,8 +100,7 @@ start(Host, Opts) -> -spec stop(ejabberd:server()) -> any(). stop(Host) -> stop_muc(Host), - stop_workers(Host), - mongoose_rdbms_sup:remove_pool(Host, ?MODULE). + stop_workers(Host). %% ---------------------------------------------------------------------- %% Add hooks for mod_mam_muc diff --git a/apps/ejabberd/src/mod_mam_odbc_async_pool_writer.erl b/apps/ejabberd/src/mod_mam_odbc_async_pool_writer.erl index 45a79876f5d..daee6c23443 100644 --- a/apps/ejabberd/src/mod_mam_odbc_async_pool_writer.erl +++ b/apps/ejabberd/src/mod_mam_odbc_async_pool_writer.erl @@ -79,10 +79,7 @@ worker_number(Host, ArcID) -> start(Host, Opts) -> mongoose_metrics:ensure_metric(Host, ?PER_MESSAGE_FLUSH_TIME, histogram), - - PoolName = gen_mod:get_module_proc(Host, ?MODULE), - {ok, _} = mongoose_rdbms_sup:add_pool(Host, ?MODULE, PoolName, worker_count(Host)), - + PoolName = gen_mod:get_opt(odbc_pool, Opts, mongoose_rdbms_sup:pool(Host)), MaxSize = gen_mod:get_module_opt(Host, ?MODULE, max_packet_size, 30), mod_mam_odbc_arch:prepare_insert(insert_mam_message, 1), mod_mam_odbc_arch:prepare_insert(insert_mam_messages, MaxSize), @@ -114,8 +111,7 @@ stop(Host) -> false -> ok end, - stop_workers(Host), - mongoose_rdbms_sup:remove_pool(Host, ?MODULE). + stop_workers(Host). %% ---------------------------------------------------------------------- %% Add hooks for mod_mam diff --git a/apps/ejabberd/src/mongoose_metrics.erl b/apps/ejabberd/src/mongoose_metrics.erl index 16e8b0bd5a0..e0913cce982 100644 --- a/apps/ejabberd/src/mongoose_metrics.erl +++ b/apps/ejabberd/src/mongoose_metrics.erl @@ -24,6 +24,7 @@ init_predefined_host_metrics/1, init_subscriptions/0, create_generic_hook_metric/2, + ensure_db_pool_metric/1, update/3, ensure_metric/3, get_metric_value/1, @@ -34,7 +35,7 @@ get_aggregated_values/1, increment_generic_hook_metric/2, get_odbc_data_stats/0, - get_odbc_mam_async_stats/0, + get_odbc_data_stats/1, get_dist_data_stats/0, get_up_time/0, remove_host_metrics/1, @@ -83,6 +84,12 @@ create_generic_hook_metric(Host, Hook) -> FilteredHookName = filter_hook(Hook), do_create_generic_hook_metric(Host, FilteredHookName). +ensure_db_pool_metric(Pool) -> + ensure_metric(global, + [data, odbc, Pool], + {function, mongoose_metrics, get_odbc_data_stats, [[Pool]], proplist, + [workers | ?INET_STATS]}). + -spec update(Host :: ejabberd:lserver() | global, Name :: term() | list(), Change :: term()) -> any(). update(Host, Name, Change) when is_list(Name) -> @@ -124,22 +131,11 @@ increment_generic_hook_metric(Host, Hook) -> do_increment_generic_hook_metric(Host, FilteredHook). get_odbc_data_stats() -> - RegularODBCWorkers = [catch mongoose_rdbms_sup:get_pids(Host) || Host <- ?MYHOSTS], - get_odbc_stats(lists:flatten(RegularODBCWorkers)). - -get_odbc_mam_async_stats() -> - %% MAM async ODBC workers are organized differently... - GetChildren = fun(Host, Pool) -> - Name = gen_mod:get_module_proc(Host, Pool), - case catch mongoose_rdbms_sup:get_pids(Name) of - [_ | _] = Children -> Children; - _ -> [] - end - end, - - MamPools = [mod_mam_odbc_async_pool_writer, mod_mam_muc_odbc_async_pool_writer], - MamChildren = lists:flatten([GetChildren(Host, Pool) || Host <- ?MYHOSTS, Pool <- MamPools]), - get_odbc_stats(MamChildren). + get_odbc_data_stats(ejabberd_rdbms:pools()). + +get_odbc_data_stats(Pools) -> + ODBCWorkers = [catch mongoose_rdbms_sup:get_pids(Pool) || Pool <- Pools], + get_odbc_stats(lists:flatten(ODBCWorkers)). get_dist_data_stats() -> DistStats = [inet_stats(Port) || {_, Port} <- erlang:system_info(dist_ctrl)], diff --git a/apps/ejabberd/src/mongoose_metrics_definitions.hrl b/apps/ejabberd/src/mongoose_metrics_definitions.hrl index f05018faa59..391ccf28dd5 100644 --- a/apps/ejabberd/src/mongoose_metrics_definitions.hrl +++ b/apps/ejabberd/src/mongoose_metrics_definitions.hrl @@ -92,11 +92,7 @@ [data, xmpp, sent, xml_stanza_size]]). -define(DATA_FUN_METRICS, - [{[data, odbc, regular], - {function, mongoose_metrics, get_odbc_data_stats, [], proplist, [workers | ?INET_STATS]}}, - {[data, odbc, mam_async], - {function, mongoose_metrics, get_odbc_mam_async_stats, [], proplist, [workers | ?INET_STATS]}}, - {[data, dist], + [{[data, dist], {function, mongoose_metrics, get_dist_data_stats, [], proplist, [connections | ?INET_STATS]}}]). diff --git a/apps/ejabberd/src/rdbms/mongoose_rdbms.erl b/apps/ejabberd/src/rdbms/mongoose_rdbms.erl index a7c46db48d9..0ff9edeb4af 100644 --- a/apps/ejabberd/src/rdbms/mongoose_rdbms.erl +++ b/apps/ejabberd/src/rdbms/mongoose_rdbms.erl @@ -31,13 +31,13 @@ -behaviour(gen_server). --callback escape_format(Host :: ejabberd:server()) -> atom(). +-callback escape_format(Pool :: pool()) -> atom(). -callback connect(Args :: any(), QueryTimeout :: non_neg_integer()) -> {ok, Connection :: term()} | {error, Reason :: any()}. -callback disconnect(Connection :: term()) -> any(). -callback query(Connection :: term(), Query :: any(), Timeout :: infinity | non_neg_integer()) -> query_result(). --callback prepare(Host :: ejabberd:server(), Connection :: term(), Name :: atom(), +-callback prepare(Pool :: pool(), Connection :: term(), Name :: atom(), Table :: binary(), Fields :: [binary()], Statement :: iodata()) -> {ok, Ref :: term()} | {error, Reason :: any()}. -callback execute(Connection :: term(), Ref :: term(), Parameters :: [term()], @@ -77,9 +77,12 @@ -include("ejabberd.hrl"). +-type pool() :: atom(). +-export_type([pool/0]). + -record(state, {db_ref, db_type :: atom(), - host :: ejabberd:server(), + pool :: pool(), prepared = #{} :: #{binary() => term()} }). -type state() :: #state{}. @@ -94,8 +97,7 @@ %% the retry counter runs out. We just attempt to reduce log pollution. -define(CONNECT_RETRIES, 5). -%% Points to ODBC server process --type odbc_server() :: binary() | atom(). +-type server() :: binary() | pool(). -type odbc_msg() :: {sql_query, _} | {sql_transaction, fun()} | {sql_execute, atom(), iodata()}. -type single_query_result() :: {selected, [tuple()]} | {updated, non_neg_integer() | undefined} | @@ -123,17 +125,17 @@ prepare(Name, Table, Fields, Statement) when is_atom(Name), is_binary(Table) -> false -> {error, already_exists} end. --spec execute(HostOrPool :: odbc_server(), Name :: atom(), Parameters :: [term()]) -> +-spec execute(HostOrPool :: server(), Name :: atom(), Parameters :: [term()]) -> query_result(). execute(HostOrPool, Name, Parameters) when is_atom(Name), is_list(Parameters) -> sql_call(HostOrPool, {sql_execute, Name, Parameters}). --spec sql_query(HostOrPool :: odbc_server(), Query :: any()) -> query_result(). +-spec sql_query(HostOrPool :: server(), Query :: any()) -> query_result(). sql_query(HostOrPool, Query) -> sql_call(HostOrPool, {sql_query, Query}). %% @doc SQL transaction based on a list of queries --spec sql_transaction(odbc_server(), fun() | maybe_improper_list()) -> transaction_result(). +-spec sql_transaction(server(), fun() | maybe_improper_list()) -> transaction_result(). sql_transaction(HostOrPool, Queries) when is_list(Queries) -> F = fun() -> lists:map(fun sql_query_t/1, Queries) end, sql_transaction(HostOrPool, F); @@ -142,7 +144,7 @@ sql_transaction(HostOrPool, F) when is_function(F) -> sql_call(HostOrPool, {sql_transaction, F}). %% TODO: Better spec for RPC calls --spec sql_call(HostOrPool :: odbc_server(), Msg :: odbc_msg()) -> any(). +-spec sql_call(HostOrPool :: server(), Msg :: odbc_msg()) -> any(). sql_call(HostOrPool, Msg) -> case get(?STATE_KEY) of undefined -> sql_call0(HostOrPool, Msg); @@ -153,31 +155,27 @@ sql_call(HostOrPool, Msg) -> end. --spec sql_call0(HostOrPool :: odbc_server(), Msg :: odbc_msg()) -> any(). -sql_call0(Host, Msg) when is_binary(Host) -> - sql_call0(mongoose_rdbms_sup:default_pool(Host), Msg); -sql_call0(Pool, Msg) when is_atom(Pool) -> - case whereis(Pool) of - undefined -> {error, {no_odbc_pool, Pool}}; +-spec sql_call0(HostOrPool :: server(), Msg :: odbc_msg()) -> any(). +sql_call0(HostOrPool, Msg) -> + PoolProc = mongoose_rdbms_sup:pool_proc(HostOrPool), + case whereis(PoolProc) of + undefined -> {error, {no_odbc_pool, PoolProc}}; _ -> Timestamp = p1_time_compat:monotonic_time(milli_seconds), - wpool:call(Pool, {sql_cmd, Msg, Timestamp}, best_worker, ?TRANSACTION_TIMEOUT) + wpool:call(PoolProc, {sql_cmd, Msg, Timestamp}, best_worker, ?TRANSACTION_TIMEOUT) end. --spec get_db_info(Target :: odbc_server() | pid()) -> +-spec get_db_info(Target :: server() | pid()) -> {ok, DbType :: atom(), DbRef :: term()} | {error, any()}. -get_db_info(Host) when is_binary(Host) -> - get_db_info(mongoose_rdbms_sup:default_pool(Host)); -get_db_info(Pool) when is_atom(Pool) -> - case whereis(Pool) of - undefined -> {error, {no_odbc_pool, Pool}}; - _ -> wpool:call(Pool, get_db_info) - end; get_db_info(Pid) when is_pid(Pid) -> - wpool_process:call(Pid, get_db_info, 5000). - - + wpool_process:call(Pid, get_db_info, 5000); +get_db_info(HostOrPool) -> + PoolProc = mongoose_rdbms_sup:pool_proc(HostOrPool), + case whereis(PoolProc) of + undefined -> {error, {no_odbc_pool, PoolProc}}; + _ -> wpool:call(PoolProc, get_db_info) + end. %% This function is intended to be used from inside an sql_transaction: sql_query_t(Query) -> @@ -215,10 +213,10 @@ escape_like(S) -> rdbms_queries:escape_like_string(S). --spec escape_format(odbc_server()) -> hex | simple_escape. -escape_format(Host) -> - mongoose_rdbms_backend:escape_format(Host). - +-spec escape_format(server()) -> hex | simple_escape. +escape_format(HostOrPool) -> + Pool = mongoose_rdbms_sup:pool(HostOrPool), + mongoose_rdbms_backend:escape_format(Pool). -spec escape_binary('hex' | 'simple_escape', binary()) -> binary() | string(). escape_binary(hex, Bin) when is_binary(Bin) -> @@ -267,16 +265,16 @@ to_bool(_) -> false. %%%---------------------------------------------------------------------- %%% Callback functions from gen_server %%%---------------------------------------------------------------------- --spec init(ejabberd:server()) -> {ok, state()}. -init(Host) -> +-spec init(pool()) -> {ok, state()}. +init(Pool) -> process_flag(trap_exit, true), - backend_module:create(?MODULE, db_engine(Host), [query]), - Settings = ejabberd_config:get_local_option({odbc_server, Host}), - MaxStartInterval = get_start_interval(Host), + backend_module:create(?MODULE, db_engine(Pool), [query]), + Settings = mongoose_rdbms_sup:get_option(Pool, odbc_server), + MaxStartInterval = get_start_interval(Pool), case connect(Settings, ?CONNECT_RETRIES, 2, MaxStartInterval) of {ok, DbRef} -> - schedule_keepalive(Host), - {ok, #state{db_type = db_engine(Host), host = Host, db_ref = DbRef}}; + schedule_keepalive(Pool), + {ok, #state{db_type = db_engine(Pool), pool = Pool, db_ref = DbRef}}; Error -> {stop, Error} end. @@ -299,7 +297,7 @@ code_change(_OldVsn, State, _Extra) -> handle_info(keepalive, State) -> case sql_query_internal([?KEEPALIVE_QUERY], State) of {selected, _} -> - schedule_keepalive(State#state.host), + schedule_keepalive(State#state.pool), {noreply, State}; {error, _} = Error -> {stop, {keepalive_failed, Error}, State} @@ -426,11 +424,11 @@ sql_execute(Name, Params, State = #state{db_ref = DBRef}) -> {Res, NewState}. -spec prepare_statement(Name :: atom(), state()) -> {Ref :: term(), state()}. -prepare_statement(Name, State = #state{db_ref = DBRef, prepared = Prepared, host = Host}) -> +prepare_statement(Name, State = #state{db_ref = DBRef, prepared = Prepared, pool = Pool}) -> case maps:get(Name, Prepared, undefined) of undefined -> [{_, Table, Fields, Statement}] = ets:lookup(prepared_statements, Name), - {ok, Ref} = mongoose_rdbms_backend:prepare(Host, DBRef, Name, Table, Fields, Statement), + {ok, Ref} = mongoose_rdbms_backend:prepare(Pool, DBRef, Name, Table, Fields, Statement), {Ref, State#state{prepared = maps:put(Name, Ref, Prepared)}}; Ref -> @@ -450,13 +448,10 @@ abort_on_driver_error({{error, "Failed sending data on socket" ++ _} = Reply, St abort_on_driver_error({Reply, State}) -> {reply, Reply, State}. - --spec db_engine(Host :: odbc_server()) -> ejabberd_config:value(). -db_engine(Pool) when is_atom(Pool) -> - {ok, DbType, _} = wpool:call(Pool, get_db_info), - DbType; -db_engine(Host) when is_binary(Host) -> - case ejabberd_config:get_local_option({odbc_server, Host}) of +-spec db_engine(server()) -> ejabberd_config:value(). +db_engine(HostOrPool) -> + Pool = mongoose_rdbms_sup:pool(HostOrPool), + case mongoose_rdbms_sup:get_option(Pool, odbc_server) of SQLServer when is_list(SQLServer) -> odbc; Other when is_tuple(Other) -> @@ -482,31 +477,31 @@ connect(Settings, Retry, RetryAfter, MaxRetryDelay) -> end. --spec schedule_keepalive(ejabberd:server()) -> any(). -schedule_keepalive(Host) -> - case ejabberd_config:get_local_option({odbc_keepalive_interval, Host}) of +-spec schedule_keepalive(pool()) -> any(). +schedule_keepalive(Pool) -> + case mongoose_rdbms_sup:get_option(Pool, odbc_keepalive_interval) of KeepaliveInterval when is_integer(KeepaliveInterval) -> erlang:send_after(timer:seconds(KeepaliveInterval), self(), keepalive); undefined -> ok; _Other -> ?ERROR_MSG("Wrong odbc_keepalive_interval definition '~p'" - " for host ~p.~n", [_Other, Host]), + " for pool ~p.~n", [_Other, Pool]), ok end. --spec get_start_interval(ejabberd:server()) -> any(). -get_start_interval(Host) -> +-spec get_start_interval(pool()) -> any(). +get_start_interval(Pool) -> DefaultInterval = 30, - case ejabberd_config:get_local_option({odbc_start_interval, Host}) of + case mongoose_rdbms_sup:get_option(Pool, odbc_start_interval) of StartInterval when is_integer(StartInterval) -> StartInterval; undefined -> DefaultInterval; _Other -> ?ERROR_MSG("Wrong odbc_start_interval definition '~p'" - " for host ~p, defaulting to ~p seconds.~n", - [_Other, Host, DefaultInterval]), + " for pool ~p, defaulting to ~p seconds.~n", + [_Other, Pool, DefaultInterval]), DefaultInterval end. diff --git a/apps/ejabberd/src/rdbms/mongoose_rdbms_mysql.erl b/apps/ejabberd/src/rdbms/mongoose_rdbms_mysql.erl index 8372ae3bb41..31051e3c1e3 100644 --- a/apps/ejabberd/src/rdbms/mongoose_rdbms_mysql.erl +++ b/apps/ejabberd/src/rdbms/mongoose_rdbms_mysql.erl @@ -26,8 +26,8 @@ %% API --spec escape_format(Host :: ejabberd:server()) -> atom(). -escape_format(_Host) -> +-spec escape_format(mongoose_rdbms:pool()) -> atom(). +escape_format(_Pool) -> simple_escape. -spec connect(Args :: any(), QueryTimeout :: non_neg_integer()) -> @@ -51,10 +51,11 @@ disconnect(Connection) -> query(Connection, Query, _Timeout) -> mysql_to_odbc(mysql:query(Connection, Query), Connection). --spec prepare(Host :: ejabberd:server(), Connection :: term(), Name :: atom(), Table :: binary(), +-spec prepare(Pool :: mongoose_rdbms:pool(), + Connection :: term(), Name :: atom(), Table :: binary(), Fields :: [binary()], Statement :: iodata()) -> {ok, term()} | {error, any()}. -prepare(_Host, Connection, Name, _Table, _Fields, Statement) -> +prepare(_Pool, Connection, Name, _Table, _Fields, Statement) -> mysql:prepare(Connection, Name, Statement). -spec execute(Connection :: term(), StatementRef :: term(), Params :: [term()], diff --git a/apps/ejabberd/src/rdbms/mongoose_rdbms_odbc.erl b/apps/ejabberd/src/rdbms/mongoose_rdbms_odbc.erl index 5fd5015daad..22cf6adf224 100644 --- a/apps/ejabberd/src/rdbms/mongoose_rdbms_odbc.erl +++ b/apps/ejabberd/src/rdbms/mongoose_rdbms_odbc.erl @@ -22,10 +22,9 @@ %% API --spec escape_format(Host :: ejabberd:server()) -> atom(). -escape_format(Host) -> - Key = {odbc_server_type, Host}, - case ejabberd_config:get_local_option_or_default(Key, odbc) of +-spec escape_format(mongoose_rdbms:pool()) -> atom(). +escape_format(Pool) -> + case mongoose_rdbms_sup:get_option(Pool, odbc_server_type) of pgsql -> hex; mssql -> @@ -57,11 +56,12 @@ query(Connection, Query, Timeout) when is_binary(Query) -> query(Connection, Query, Timeout) -> parse(odbc:sql_query(Connection, Query, Timeout)). --spec prepare(Host :: ejabberd:server(), Connection :: term(), Name :: atom(), Table :: binary(), +-spec prepare(Pool :: mongoose_rdbms:pool(), + Connection :: term(), Name :: atom(), Table :: binary(), Fields :: [binary()], Statement :: iodata()) -> {ok, {[binary()], [fun((term()) -> tuple())]}}. -prepare(Host, Connection, _Name, Table, Fields, Statement) -> - BinEscapeFormat = escape_format(Host), +prepare(Pool, Connection, _Name, Table, Fields, Statement) -> + BinEscapeFormat = escape_format(Pool), {ok, TableDesc} = odbc:describe_table(Connection, unicode:characters_to_list(Table)), SplitQuery = binary:split(iolist_to_binary(Statement), <<"?">>, [global]), ParamMappers = [field_name_to_mapper(BinEscapeFormat, TableDesc, Field) || Field <- Fields], diff --git a/apps/ejabberd/src/rdbms/mongoose_rdbms_pgsql.erl b/apps/ejabberd/src/rdbms/mongoose_rdbms_pgsql.erl index 0449d65b24c..f712c45cc2b 100644 --- a/apps/ejabberd/src/rdbms/mongoose_rdbms_pgsql.erl +++ b/apps/ejabberd/src/rdbms/mongoose_rdbms_pgsql.erl @@ -26,8 +26,8 @@ %% API --spec escape_format(Host :: ejabberd:server()) -> atom(). -escape_format(_Host) -> +-spec escape_format(mongoose_rdbms:pool()) -> atom(). +escape_format(_Pool) -> hex. -spec connect(Args :: any(), QueryTimeout :: non_neg_integer()) -> @@ -51,10 +51,11 @@ disconnect(Connection) -> query(Connection, Query, _Timeout) -> pgsql_to_odbc(epgsql:squery(Connection, Query)). --spec prepare(Host :: ejabberd:server(), Connection :: term(), Name :: atom(), Table :: binary(), +-spec prepare(Pool :: mongoose_rdbms:pool(), + Connection :: term(), Name :: atom(), Table :: binary(), Fields :: [binary()], Statement :: iodata()) -> {ok, term()} | {error, any()}. -prepare(_Host, Connection, Name, _Table, _Fields, Statement) -> +prepare(_Pool, Connection, Name, _Table, _Fields, Statement) -> BinName = atom_to_binary(Name, latin1), ReplacedStatement = replace_question_marks(Statement), case epgsql:parse(Connection, BinName, ReplacedStatement, []) of diff --git a/apps/ejabberd/src/rdbms/mongoose_rdbms_sup.erl b/apps/ejabberd/src/rdbms/mongoose_rdbms_sup.erl index a015d5b2e31..f48876a2864 100644 --- a/apps/ejabberd/src/rdbms/mongoose_rdbms_sup.erl +++ b/apps/ejabberd/src/rdbms/mongoose_rdbms_sup.erl @@ -30,77 +30,75 @@ -author('konrad.zemek@erlang-solutions.com'). %% API --export([start_link/1, +-export([start_link/0, init/1, get_pids/1, - default_pool/1, - add_pool/4, - remove_pool/2 + pool_proc/1, + pool/1, + add_pool/1, + remove_pool/1, + get_option/2 ]). -include("ejabberd.hrl"). --define(POOL_NAME, odbc_pool). +-define(DEFAULT_POOL_NAME, default). -define(DEFAULT_POOL_SIZE, 10). --spec start_link(binary() | string()) -> ignore | {error, term()} | {ok, pid()}. -start_link(Host) -> - supervisor:start_link({local, gen_mod:get_module_proc(Host, ?MODULE)}, ?MODULE, Host). +-spec start_link() -> ignore | {error, term()} | {ok, pid()}. +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). - --spec init(ejabberd:server()) -> {ok, {supervisor:sup_flags(), [supervisor:child_spec()]}}. -init(Host) -> +-spec init([]) -> {ok, {supervisor:sup_flags(), [supervisor:child_spec()]}}. +init([]) -> ok = application:ensure_started(worker_pool), catch ets:new(prepared_statements, [public, named_table, {read_concurrency, true}]), - PoolSize = pool_size(Host), - PoolName = default_pool(Host), - ChildrenSpec = [pool_spec(Host, default_pool, PoolName, PoolSize)], - {ok, {{one_for_one, 5, 60}, ChildrenSpec}}. - - --spec add_pool(Host :: ejabberd:server(), Id :: supervisor:child_id(), - Name :: atom(), Size :: pos_integer()) -> supervisor:startchild_ret(). -add_pool(Host, Id, Name, Size) -> - Sup = gen_mod:get_module_proc(Host, ?MODULE), - ChildSpec = pool_spec(Host, Id, Name, Size), - supervisor:start_child(Sup, ChildSpec). + {ok, {{one_for_one, 5, 60}, []}}. +-spec add_pool(Pool :: mongoose_rdbms:pool()) -> supervisor:startchild_ret(). +add_pool(Pool) -> + Size = pool_size(Pool), + ChildSpec = pool_spec(Pool, Size), + mongoose_metrics:ensure_db_pool_metric(Pool), + supervisor:start_child(?MODULE, ChildSpec). --spec remove_pool(Host :: ejabberd:server(), Id :: supervisor:child_id()) -> ok. -remove_pool(Host, Id) -> - Sup = gen_mod:get_module_proc(Host, ?MODULE), - ok = supervisor:terminate_child(Sup, Id), - ok = supervisor:delete_child(Sup, Id). +-spec remove_pool(Pool :: mongoose_rdbms:pool()) -> ok. +remove_pool(Pool) -> + ok = supervisor:terminate_child(?MODULE, Pool), + ok = supervisor:delete_child(?MODULE, Pool). - --spec pool_spec(Host :: ejabberd:server(), Id :: supervisor:child_id(), - Name :: atom(), Size :: pos_integer()) -> supervisor:child_spec(). -pool_spec(Host, Id, Name, Size) -> - Opts = [{workers, Size}, {worker, {mongoose_rdbms, Host}}, {pool_sup_shutdown, infinity}], - {Id, {wpool, start_pool, [Name, Opts]}, transient, 2000, supervisor, dynamic}. +-spec pool_spec(Pool :: mongoose_rdbms:pool(), Size :: pos_integer()) -> supervisor:child_spec(). +pool_spec(Pool, Size) -> + Opts = [{workers, Size}, {worker, {mongoose_rdbms, Pool}}, {pool_sup_shutdown, infinity}], + {Pool, {wpool, start_pool, [pool_proc(Pool), Opts]}, transient, 2000, supervisor, dynamic}. -spec get_pids(ejabberd:server() | atom()) -> [pid()]. -get_pids(Host) when is_binary(Host) -> - get_pids(default_pool(Host)); -get_pids(PoolName) -> - case whereis(PoolName) of +get_pids(HostOrPool) -> + PoolProc = pool_proc(HostOrPool), + case whereis(PoolProc) of undefined -> []; _ -> - Stats = wpool:stats(PoolName), + Stats = wpool:stats(PoolProc), {workers, Workers} = lists:keyfind(workers, 1, Stats), - [whereis(wpool_pool:worker_name(PoolName, WorkerId)) || {WorkerId, _} <- Workers] + [whereis(wpool_pool:worker_name(PoolProc, WorkerId)) || {WorkerId, _} <- Workers] end. - --spec default_pool(Host :: ejabberd:server()) -> atom(). -default_pool(Host) -> - gen_mod:get_module_proc(Host, ?POOL_NAME). - - --spec pool_size(ejabberd:server()) -> integer(). -pool_size(Host) -> - case ejabberd_config:get_local_option({odbc_pool_size, Host}) of +-spec pool_proc(mongoose_rdbms:server()) -> atom(). +pool_proc(Host) when is_binary(Host) -> + pool_proc(pool(Host)); +pool_proc(Pool) when is_atom(Pool) -> + gen_mod:get_module_proc(atom_to_list(Pool), mongoose_rdbms_pool). + +-spec pool(mongoose_rdbms:server()) -> mongoose_rdbms:pool(). +pool(Host) when is_binary(Host) -> + ejabberd_config:get_local_option_or_default({odbc_pool, Host}, ?DEFAULT_POOL_NAME); +pool(Pool) when is_atom(Pool) -> + Pool. + +-spec pool_size(mongoose_rdbms:pool()) -> integer(). +pool_size(Pool) -> + case get_option(Pool, odbc_pool_size) of undefined -> ?DEFAULT_POOL_SIZE; Size when is_integer(Size) -> @@ -108,7 +106,14 @@ pool_size(Host) -> InvalidSize -> Size = ?DEFAULT_POOL_SIZE, ?ERROR_MSG("Wrong odbc_pool_size definition '~p' " - "for host ~p, default to ~p~n", - [InvalidSize, Host, Size]), + "for pool ~p, default to ~p~n", + [InvalidSize, Pool, Size]), Size end. + +-spec get_option(mongoose_rdbms:pool(), atom()) -> term(). +get_option(Pool, Option) -> + ejabberd_config:get_local_option(config_key(Pool, Option)). + +config_key(Pool, Option) -> + {Option, odbc_pool, Pool}. diff --git a/apps/ejabberd/test/mongoose_rdbms_SUITE.erl b/apps/ejabberd/test/mongoose_rdbms_SUITE.erl index 3f2baaccd7f..b1a56a2e86e 100644 --- a/apps/ejabberd/test/mongoose_rdbms_SUITE.erl +++ b/apps/ejabberd/test/mongoose_rdbms_SUITE.erl @@ -9,7 +9,6 @@ -define(eq(E, I), ?assertEqual(E, I)). -define(ne(E, I), ?assert(E =/= I)). --define(HOST, <<"localhost">>). -define(KEEPALIVE_INTERVAL, 1). -define(KEEPALIVE_QUERY, <<"SELECT 1;">>). @@ -61,7 +60,7 @@ end_per_testcase(_, Config) -> %% Test cases keepalive_interval(Config) -> - {ok, Pid} = gen_server:start_link(mongoose_rdbms, ?HOST, []), + {ok, Pid} = gen_server:start_link(mongoose_rdbms, default, []), true = erlang:unlink(Pid), timer:sleep(5500), ?eq(5, query_calls(Config)), @@ -69,7 +68,7 @@ keepalive_interval(Config) -> ok. keepalive_exit(Config) -> - {ok, Pid} = gen_server:start_link(mongoose_rdbms, ?HOST, []), + {ok, Pid} = gen_server:start_link(mongoose_rdbms, default, []), true = erlang:unlink(Pid), Monitor = erlang:monitor(process, Pid), timer:sleep(3500), @@ -86,11 +85,14 @@ keepalive_exit(Config) -> meck_config(Server, KeepaliveInterval) -> meck:new(ejabberd_config, [no_link]), meck:expect(ejabberd_config, get_local_option, - fun({odbc_keepalive_interval, _Host}) -> KeepaliveInterval; - ({odbc_start_interval, _Host}) -> 30; - (max_fsm_queue) -> 1024; - ({odbc_server, _}) -> server(Server); + fun(max_fsm_queue) -> 1024; (all_metrics_are_global) -> false + end), + meck:new(mongoose_rdbms_sup, [no_link, passthrough]), + meck:expect(mongoose_rdbms_sup, get_option, + fun(default, odbc_keepalive_interval) -> KeepaliveInterval; + (default, odbc_start_interval) -> 30; + (default, odbc_server) -> server(Server) end). meck_db(odbc) -> @@ -126,6 +128,7 @@ meck_error(pgsql) -> meck_unload(DbType) -> meck:unload(ejabberd_config), + meck:unload(mongoose_rdbms_sup), do_meck_unload(DbType). do_meck_unload(odbc) -> diff --git a/doc/Advanced-configuration.md b/doc/Advanced-configuration.md index 9a9b59529a0..111203346c4 100644 --- a/doc/Advanced-configuration.md +++ b/doc/Advanced-configuration.md @@ -10,7 +10,7 @@ The tuple order is important, unless the no `host_config` option is set. Retaini ## Options -* All options except `hosts`, `host` and `host_config` can be used in `host_config` tuple. +* All options except `hosts`, `host`, `host_config`, `pool` and the ODBC options can be used in `host_config` tuple. * There are two kinds of local options - those that are kept separately for each domain in config file (defined inside `host_config`) and the options local for a node in the cluster. @@ -129,7 +129,23 @@ The tuple order is important, unless the no `host_config` option is set. Retaini ### Database setup -`odbc` prefixes may be misleading. Such options apply to all kinds of DB connections, not only pure ODBC. +#### Connection pools + +* **pool** (multi, local) + * **Description:** Declares a named pool of connections to the database. At least one pool is required to connect to an SQL database. + * **Syntax:** `{pool, odbc, PoolName}.` or `{pool, odbc, PoolName, Options}.` + * **Examples:** `{pool, odbc, default}.` + +* **odbc_pool** (local) + * **Description:** Name of the default connection pool used to connect to the database. + * **Syntax:** `{odbc_pool, PoolName}` + * **Default:** `default` + +#### Connection setup + +The following options can be used to configure a connection pool. To set the options for all connection pools, put them on the top level of the configuration file. To set them for an individual pool, put them inside the `Options` list in a pool specification. Setting `odbc_server` is mandatory. + +*Note*: `odbc` prefixes may be misleading. Such options apply to all kinds of DB connections, not only pure ODBC. * **odbc_server** (local) * **Description:** SQL DB connection configuration. Currently supported DB types are `mysql` and `pgsql`. diff --git a/doc/Basic-configuration.md b/doc/Basic-configuration.md index 1069eb6c077..4ab3542603c 100644 --- a/doc/Basic-configuration.md +++ b/doc/Basic-configuration.md @@ -23,10 +23,14 @@ There are 2 types of options: params and features. Unlike params, features can b * **host_config** - feature * **Description:** List of specific options for chosen XMPP domains. They will override the global ones. Allowed keys are marked on [Advanced configuration](Advanced-configuration.md) page - -* **Syntax:** `"{host_config, \"overridden-domain\", [{key, value}]}."` + * **Syntax:** `"{host_config, \"overridden-domain\", [{key, value}]}."` * **Example:** `"{host_config, \"localhost2\", [{auth_method, anonymous}, {allow_multiple_connections, false}]}." ` +* **pool** - feature + * **Description:** A named pool of connections to an SQL DB. To enable the connection, remove '%%' prefix from value and configure it with the `odbc_server` option (see below). + * **Syntax:** `"{pool, odbc, PoolName}."` or `"{pool, odbc, PoolName, Options}."` + * **Examples:** `"{pool, odbc, default}."` + * **odbc_server** - feature * **Description:** SQL DB connection configuration. Currently supported DB types are `mysql` and `pgsql`. To enable the connection, remove '%%' prefix from value. * **Syntax:** `"{odbc_server, {Type, Host, Port, DBName, Username, Password}}."` diff --git a/rel/files/ejabberd.cfg b/rel/files/ejabberd.cfg index c3a7f98acf6..5d2ba942cca 100755 --- a/rel/files/ejabberd.cfg +++ b/rel/files/ejabberd.cfg @@ -456,6 +456,10 @@ %% %%{odbc_pool_size, 10}. +%% Enable the default database connection pool +%%{pool, odbc, default}. +{{{odbc_pools}}} + %%% ==================== %%% RIAK SETUP %%% ==================== diff --git a/test.disabled/ejabberd_tests/test.config b/test.disabled/ejabberd_tests/test.config index d915a5dba12..3aa48407829 100644 --- a/test.disabled/ejabberd_tests/test.config +++ b/test.disabled/ejabberd_tests/test.config @@ -175,6 +175,7 @@ {pgsql_mnesia, [{sm_backend, "{mnesia, []}"}, {auth_method, "odbc"}, + {odbc_pools, "{pool, odbc, default}."}, {odbc_server, "{odbc_server, {pgsql, \"localhost\", \"ejabberd\", \"ejabberd\", \"%ODBC_PASSWORD%\"}}."}, {mod_last, "{mod_last, [{backend, odbc}]},"}, {mod_privacy, "{mod_privacy, [{backend, odbc}]},"}, @@ -185,6 +186,7 @@ {odbc_pgsql_mnesia, [{sm_backend, "{mnesia, []}"}, {auth_method, "odbc"}, + {odbc_pools, "{pool, odbc, default}."}, {odbc_server, "{odbc_server, \"DSN=ejabberd-pgsql;UID=ejabberd;PWD=%ODBC_PASSWORD%\"}."}, {odbc_server_type, "{odbc_server_type, pgsql}."}, {mod_last, "{mod_last, [{backend, odbc}]},"}, @@ -196,6 +198,7 @@ {mysql_mnesia, [{sm_backend, "{mnesia, []}"}, {auth_method, "odbc"}, + {odbc_pools, "{pool, odbc, default}."}, {odbc_server, "{odbc_server, {mysql, \"localhost\", \"ejabberd\", \"ejabberd\", \"%ODBC_PASSWORD%\"}}."}, {mod_last, "{mod_last, [{backend, odbc}]},"}, {mod_privacy, "{mod_privacy, [{backend, odbc}]},"}, @@ -206,6 +209,7 @@ {mysql_redis, [{sm_backend, "{redis, [{pool_size, 3}, {worker_config, [{host, \"localhost\"}, {port, 6379}]}]}"}, {auth_method, "odbc"}, + {odbc_pools, "{pool, odbc, default}."}, {odbc_server, "{odbc_server, {mysql, \"localhost\", \"ejabberd\", \"ejabberd\", \"%ODBC_PASSWORD%\"}}."}, {mod_last, "{mod_last, [{backend, odbc}]},"}, {mod_privacy, "{mod_privacy, [{backend, odbc}]},"}, diff --git a/test.disabled/ejabberd_tests/tests/mam_SUITE.erl b/test.disabled/ejabberd_tests/tests/mam_SUITE.erl index 00d14d5574c..eb077ab921a 100644 --- a/test.disabled/ejabberd_tests/tests/mam_SUITE.erl +++ b/test.disabled/ejabberd_tests/tests/mam_SUITE.erl @@ -737,7 +737,7 @@ init_per_testcase(C=metric_incremented_when_store_message, ConfigIn) -> Config = case ?config(configuration, ConfigIn) of odbc_async_pool -> MongooseMetrics = [ - {[global, data, odbc, mam_async], + {[global, data, odbc, default], [{recv_oct, '>'}, {send_oct, '>'}]} ], [{mongoose_metrics, MongooseMetrics} | ConfigIn]; diff --git a/test.disabled/ejabberd_tests/tests/metrics_roster_SUITE.erl b/test.disabled/ejabberd_tests/tests/metrics_roster_SUITE.erl index abfeee4b8bb..f6ecd894300 100644 --- a/test.disabled/ejabberd_tests/tests/metrics_roster_SUITE.erl +++ b/test.disabled/ejabberd_tests/tests/metrics_roster_SUITE.erl @@ -63,7 +63,7 @@ init_per_suite(Config) -> MongooseMetrics = [{[global, data, xmpp, received, xml_stanza_size], changed}, {[global, data, xmpp, sent, xml_stanza_size], changed}, - {fun roster_odbc_precondition/0, [global, data, odbc, regular], + {fun roster_odbc_precondition/0, [global, data, odbc, default], [{recv_oct, '>'}, {send_oct, '>'}]}, {[global, backends, mod_roster, get_subscription_lists], changed} ],