diff options
author | Jérôme Sautret <jerome.sautret@process-one.net> | 2008-10-06 14:18:46 +0000 |
---|---|---|
committer | Jérôme Sautret <jerome.sautret@process-one.net> | 2008-10-06 14:18:46 +0000 |
commit | 2f8127d343c773201d3d61fa6614deaa54417820 (patch) | |
tree | 0a120e047d556a7ab5a2238191ac4e65a3cbc426 /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.erl | 15 | ||||
-rw-r--r-- | src/odbc/ejabberd_odbc.erl | 43 | ||||
-rw-r--r-- | src/odbc/ejabberd_odbc_sup.erl | 38 |
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), |