mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-26 17:38:45 +01:00
* src/ejabberd_rdbms.erl: fix SQL database reconnection
issues (EJAB-764) and add odbc_start_interval configuration directive (default to 30 seconds). * src/odbc/ejabberd_odbc.erl: likewise. * src/odbc/ejabberd_odbc_sup.erl: likewise. * doc/guide.tex: likewise. SVN Revision: 1600
This commit is contained in:
parent
a2340ea8b8
commit
2f8127d343
@ -1,3 +1,12 @@
|
||||
2008-10-06 Jerome Sautret <jerome.sautret@process-one.net>
|
||||
|
||||
* src/ejabberd_rdbms.erl: fix SQL database reconnection
|
||||
issues (EJAB-764) and add odbc_start_interval configuration
|
||||
directive (default to 30 seconds).
|
||||
* src/odbc/ejabberd_odbc.erl: likewise.
|
||||
* src/odbc/ejabberd_odbc_sup.erl: likewise.
|
||||
* doc/guide.tex: likewise.
|
||||
|
||||
2008-10-03 Jerome Sautret <jerome.sautret@process-one.net>
|
||||
|
||||
* src/odbc/odbc_queries.erl: Fix empty query that fail on MySQL.
|
||||
|
@ -1617,6 +1617,13 @@ Specify in seconds: for example 28800 means 8 hours.
|
||||
{odbc_keepalive_interval, undefined}.
|
||||
\end{verbatim}
|
||||
|
||||
If the connection to the database fails, \ejabberd{} waits 30 seconds before retrying.
|
||||
You can modify this interval with this option:
|
||||
\begin{verbatim}
|
||||
{odbc_start_interval, 30}.
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
\makesubsubsection{compilemysql}{Driver Compilation}
|
||||
\ind{MySQL!Driver Compilation}
|
||||
|
||||
|
@ -52,14 +52,21 @@ start_hosts() ->
|
||||
|
||||
%% Start the ODBC module on the given host
|
||||
start_odbc(Host) ->
|
||||
Supervisor_name = gen_mod:get_module_proc(Host, ejabberd_odbc_sup),
|
||||
ChildSpec =
|
||||
{gen_mod:get_module_proc(Host, ejabberd_odbc_sup),
|
||||
{Supervisor_name,
|
||||
{ejabberd_odbc_sup, start_link, [Host]},
|
||||
temporary,
|
||||
transient,
|
||||
infinity,
|
||||
supervisor,
|
||||
[ejabberd_odbc_sup]},
|
||||
supervisor:start_child(ejabberd_sup, ChildSpec).
|
||||
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.
|
||||
|
||||
%% Returns true if we have configured odbc_server for the given host
|
||||
needs_odbc(Host) ->
|
||||
|
@ -30,7 +30,7 @@
|
||||
-behaviour(gen_server).
|
||||
|
||||
%% External exports
|
||||
-export([start/1, start_link/1,
|
||||
-export([start/1, start_link/2,
|
||||
sql_query/2,
|
||||
sql_query_t/1,
|
||||
sql_transaction/2,
|
||||
@ -63,8 +63,8 @@
|
||||
start(Host) ->
|
||||
gen_server:start(ejabberd_odbc, [Host], []).
|
||||
|
||||
start_link(Host) ->
|
||||
gen_server:start_link(ejabberd_odbc, [Host], []).
|
||||
start_link(Host, StartInterval) ->
|
||||
gen_server:start_link(ejabberd_odbc, [Host, StartInterval], []).
|
||||
|
||||
sql_query(Host, Query) ->
|
||||
gen_server:call(ejabberd_odbc_sup:get_random_pid(Host),
|
||||
@ -131,10 +131,10 @@ escape_like(C) -> odbc_queries:escape(C).
|
||||
%% ignore |
|
||||
%% {stop, Reason}
|
||||
%%----------------------------------------------------------------------
|
||||
init([Host]) ->
|
||||
init([Host, StartInterval]) ->
|
||||
case ejabberd_config:get_local_option({odbc_keepalive_interval, Host}) of
|
||||
Interval when is_integer(Interval) ->
|
||||
timer:apply_interval(Interval*1000, ?MODULE, keep_alive, [self()]);
|
||||
KeepaliveInterval when is_integer(KeepaliveInterval) ->
|
||||
timer:apply_interval(KeepaliveInterval*1000, ?MODULE, keep_alive, [self()]);
|
||||
undefined ->
|
||||
ok;
|
||||
_Other ->
|
||||
@ -144,16 +144,16 @@ init([Host]) ->
|
||||
case SQLServer of
|
||||
%% Default pgsql port
|
||||
{pgsql, Server, DB, Username, Password} ->
|
||||
pgsql_connect(Server, ?PGSQL_PORT, DB, Username, Password);
|
||||
pgsql_connect(Server, ?PGSQL_PORT, DB, Username, Password, StartInterval);
|
||||
{pgsql, Server, Port, DB, Username, Password} when is_integer(Port) ->
|
||||
pgsql_connect(Server, Port, DB, Username, Password);
|
||||
pgsql_connect(Server, Port, DB, Username, Password, StartInterval);
|
||||
%% Default mysql port
|
||||
{mysql, Server, DB, Username, Password} ->
|
||||
mysql_connect(Server, ?MYSQL_PORT, DB, Username, Password);
|
||||
mysql_connect(Server, ?MYSQL_PORT, DB, Username, Password, StartInterval);
|
||||
{mysql, Server, Port, DB, Username, Password} when is_integer(Port) ->
|
||||
mysql_connect(Server, Port, DB, Username, Password);
|
||||
mysql_connect(Server, Port, DB, Username, Password, StartInterval);
|
||||
_ when is_list(SQLServer) ->
|
||||
odbc_connect(SQLServer)
|
||||
odbc_connect(SQLServer, StartInterval)
|
||||
end.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
@ -259,7 +259,7 @@ execute_transaction(State, F, NRestarts) ->
|
||||
|
||||
%% part of init/1
|
||||
%% Open an ODBC database connection
|
||||
odbc_connect(SQLServer) ->
|
||||
odbc_connect(SQLServer, StartInterval) ->
|
||||
application:start(odbc),
|
||||
case odbc:connect(SQLServer,[{scrollable_cursors, off}]) of
|
||||
{ok, Ref} ->
|
||||
@ -268,8 +268,8 @@ odbc_connect(SQLServer) ->
|
||||
{error, Reason} ->
|
||||
?ERROR_MSG("ODBC connection (~s) failed: ~p~n",
|
||||
[SQLServer, Reason]),
|
||||
%% If we can't connect we wait for 30 seconds before retrying
|
||||
timer:sleep(30000),
|
||||
%% If we can't connect we wait before retrying
|
||||
timer:sleep(StartInterval),
|
||||
{stop, odbc_connection_failed}
|
||||
end.
|
||||
|
||||
@ -278,15 +278,15 @@ odbc_connect(SQLServer) ->
|
||||
|
||||
%% part of init/1
|
||||
%% Open a database connection to PostgreSQL
|
||||
pgsql_connect(Server, Port, DB, Username, Password) ->
|
||||
pgsql_connect(Server, Port, DB, Username, Password, StartInterval) ->
|
||||
case pgsql:connect(Server, DB, Username, Password, Port) of
|
||||
{ok, Ref} ->
|
||||
erlang:monitor(process, Ref),
|
||||
{ok, #state{db_ref = Ref, db_type = pgsql}};
|
||||
{error, Reason} ->
|
||||
?ERROR_MSG("PostgreSQL connection failed: ~p~n", [Reason]),
|
||||
%% If we can't connect we wait for 30 seconds before retrying
|
||||
timer:sleep(30000),
|
||||
%% If we can't connect we wait before retrying
|
||||
timer:sleep(StartInterval),
|
||||
{stop, pgsql_connection_failed}
|
||||
end.
|
||||
|
||||
@ -317,7 +317,7 @@ pgsql_item_to_odbc(_) ->
|
||||
|
||||
%% part of init/1
|
||||
%% Open a database connection to MySQL
|
||||
mysql_connect(Server, Port, DB, Username, Password) ->
|
||||
mysql_connect(Server, Port, DB, Username, Password, StartInterval) ->
|
||||
NoLogFun = fun(_Level,_Format,_Argument) -> ok end,
|
||||
case mysql_conn:start(Server, Port, Username, Password, DB, NoLogFun) of
|
||||
{ok, Ref} ->
|
||||
@ -330,9 +330,10 @@ mysql_connect(Server, Port, DB, Username, Password) ->
|
||||
"SERIALIZABLE;"], self()),
|
||||
{ok, #state{db_ref = Ref, db_type = mysql}};
|
||||
{error, Reason} ->
|
||||
?ERROR_MSG("MySQL connection failed: ~p~n", [Reason]),
|
||||
%% If we can't connect we wait for 30 seconds before retrying
|
||||
timer:sleep(30000),
|
||||
?ERROR_MSG("MySQL connection failed: ~p~nWaiting ~p seconds before retrying...~n",
|
||||
[Reason, StartInterval div 1000]),
|
||||
%% If we can't connect we wait before retrying
|
||||
timer:sleep(StartInterval),
|
||||
{stop, mysql_connection_failed}
|
||||
end.
|
||||
|
||||
|
@ -37,13 +37,14 @@
|
||||
-include("ejabberd.hrl").
|
||||
|
||||
-define(DEFAULT_POOL_SIZE, 10).
|
||||
-define(DEFAULT_ODBC_START_INTERVAL, 30). % 30 seconds
|
||||
|
||||
start_link(Host) ->
|
||||
supervisor:start_link({local, gen_mod:get_module_proc(Host, ?MODULE)},
|
||||
?MODULE, [Host]).
|
||||
|
||||
init([Host]) ->
|
||||
N = case ejabberd_config:get_local_option({odbc_pool_size, Host}) of
|
||||
PoolSize = case ejabberd_config:get_local_option({odbc_pool_size, Host}) of
|
||||
I when is_integer(I) ->
|
||||
I;
|
||||
undefined ->
|
||||
@ -53,16 +54,27 @@ init([Host]) ->
|
||||
[Other, Host, ?DEFAULT_POOL_SIZE]),
|
||||
?DEFAULT_POOL_SIZE
|
||||
end,
|
||||
{ok, {{one_for_one, 10, 6},
|
||||
StartInterval = case ejabberd_config:get_local_option({odbc_start_interval, Host}) of
|
||||
Interval when is_integer(Interval) ->
|
||||
Interval;
|
||||
undefined ->
|
||||
?DEFAULT_ODBC_START_INTERVAL;
|
||||
_Other2 ->
|
||||
?ERROR_MSG("Wrong odbc_start_interval definition '~p' for host ~p"
|
||||
", defaulting to ~p~n",
|
||||
[_Other2, Host, ?DEFAULT_ODBC_START_INTERVAL]),
|
||||
?DEFAULT_ODBC_START_INTERVAL
|
||||
end,
|
||||
{ok, {{one_for_one, PoolSize+1, StartInterval},
|
||||
lists:map(
|
||||
fun(I) ->
|
||||
{I,
|
||||
{ejabberd_odbc, start_link, [Host]},
|
||||
{ejabberd_odbc, start_link, [Host, StartInterval*1000]},
|
||||
transient,
|
||||
brutal_kill,
|
||||
worker,
|
||||
[?MODULE]}
|
||||
end, lists:seq(1, N))}}.
|
||||
end, lists:seq(1, PoolSize))}}.
|
||||
|
||||
get_pids(Host) ->
|
||||
Proc = gen_mod:get_module_proc(Host, ?MODULE),
|
||||
|
Loading…
Reference in New Issue
Block a user