aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJérôme Sautret <jerome.sautret@process-one.net>2008-10-06 14:18:46 +0000
committerJérôme Sautret <jerome.sautret@process-one.net>2008-10-06 14:18:46 +0000
commit2f8127d343c773201d3d61fa6614deaa54417820 (patch)
tree0a120e047d556a7ab5a2238191ac4e65a3cbc426 /src
parent* src/odbc/odbc_queries.erl: Fix empty query that fail on MySQL. (diff)
* 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
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_rdbms.erl15
-rw-r--r--src/odbc/ejabberd_odbc.erl43
-rw-r--r--src/odbc/ejabberd_odbc_sup.erl38
3 files changed, 58 insertions, 38 deletions
diff --git a/src/ejabberd_rdbms.erl b/src/ejabberd_rdbms.erl
index 0eff6c3ca..fcbe16cbb 100644
--- a/src/ejabberd_rdbms.erl
+++ b/src/ejabberd_rdbms.erl
@@ -16,7 +16,7 @@
%%% 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., 59 Temple Place, Suite 330, Boston, MA
@@ -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) ->
diff --git a/src/odbc/ejabberd_odbc.erl b/src/odbc/ejabberd_odbc.erl
index a373cc2d1..da1b01e2c 100644
--- a/src/odbc/ejabberd_odbc.erl
+++ b/src/odbc/ejabberd_odbc.erl
@@ -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.
diff --git a/src/odbc/ejabberd_odbc_sup.erl b/src/odbc/ejabberd_odbc_sup.erl
index c007da527..80f0a36ca 100644
--- a/src/odbc/ejabberd_odbc_sup.erl
+++ b/src/odbc/ejabberd_odbc_sup.erl
@@ -16,7 +16,7 @@
%%% 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., 59 Temple Place, Suite 330, Boston, MA
@@ -37,32 +37,44 @@
-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
- I when is_integer(I) ->
- I;
+ PoolSize = case ejabberd_config:get_local_option({odbc_pool_size, Host}) of
+ I when is_integer(I) ->
+ I;
undefined ->
- ?DEFAULT_POOL_SIZE;
- Other ->
- ?ERROR_MSG("Wrong odbc_pool_size definition '~p' for host ~p, default to ~p~n",
- [Other, Host, ?DEFAULT_POOL_SIZE]),
- ?DEFAULT_POOL_SIZE
- end,
- {ok, {{one_for_one, 10, 6},
+ ?DEFAULT_POOL_SIZE;
+ Other ->
+ ?ERROR_MSG("Wrong odbc_pool_size definition '~p' for host ~p, default to ~p~n",
+ [Other, Host, ?DEFAULT_POOL_SIZE]),
+ ?DEFAULT_POOL_SIZE
+ end,
+ 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),