Skip to content

Commit

Permalink
via davisp: external server launches on request to avoid runaway errors.
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.apache.org/repos/asf/couchdb/trunk@739681 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
jchris committed Feb 1, 2009
1 parent b21b16d commit 7840145
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 33 deletions.
42 changes: 19 additions & 23 deletions src/couchdb/couch_external_manager.erl
Expand Up @@ -19,7 +19,8 @@
-include("couch_db.hrl").

start_link() ->
gen_server:start_link({local, couch_external_manager}, couch_external_manager, [], []).
gen_server:start_link({local, couch_external_manager},
couch_external_manager, [], []).

execute(UrlName, JsonReq) ->
Pid = gen_server:call(couch_external_manager, {get, UrlName}),
Expand All @@ -37,10 +38,6 @@ config_change("external", UrlName) ->

init([]) ->
Handlers = ets:new(couch_external_manager_handlers, [set, private]),
lists:foreach(fun({UrlName, Command}) ->
{ok, Pid} = couch_external_server:start_link(UrlName, Command),
true = ets:insert(Handlers, {UrlName, Pid})
end, couch_config:get("external")),
couch_config:register(fun config_change/2),
{ok, Handlers}.

Expand All @@ -52,14 +49,21 @@ terminate(_Reason, Handlers) ->
ok.

handle_call({get, UrlName}, _From, Handlers) ->
Resp = case ets:lookup(Handlers, UrlName) of
[{UrlName, Pid}] ->
Pid;
case ets:lookup(Handlers, UrlName) of
[] ->
Mesg = lists:flatten(io_lib:format("No server configured for ~p.", [UrlName])),
{error, {unknown_external_server, Mesg}}
end,
{reply, Resp, Handlers};
case couch_config:get("external", UrlName, nil) of
nil ->
Mesg = lists:flatten(
io_lib:format("No server configured for ~p.", [UrlName])),
{reply, {error, {unknown_external_server, Mesg}}, Handlers};
Command ->
{ok, NewPid} = couch_external_server:start_link(UrlName, Command),
true = ets:insert(Handlers, {UrlName, NewPid}),
{reply, NewPid, Handlers}
end;
[{UrlName, Pid}] ->
{reply, Pid, Handlers}
end;
handle_call({config, UrlName}, _From, Handlers) ->
% A newly added handler and a handler that had it's command
% changed are treated exactly the same.
Expand All @@ -68,25 +72,17 @@ handle_call({config, UrlName}, _From, Handlers) ->
case ets:lookup(Handlers, UrlName) of
[{UrlName, Pid}] ->
couch_external_server:stop(Pid);
_ ->
[] ->
ok
end,
case couch_config:get("external", UrlName, nil) of
% Handler no longer exists
nil ->
ok;
% New handler start up.
Command ->
{ok, NewPid} = couch_external_server:start_link(UrlName, Command),
true = ets:insert(Handlers, {Command, NewPid})
end,
% Wait for next request to boot the handler.
{reply, ok, Handlers}.

handle_cast(_Whatever, State) ->
{noreply, State}.

handle_info({'EXIT', Reason, Pid}, Handlers) ->
?LOG_DEBUG("External server ~p died. (reason: ~p)", [Pid, Reason]),
?LOG_DEBUG("EXTERNAL: Server ~p died. (reason: ~p)", [Pid, Reason]),
% Remove Pid from the handlers table so we don't try closing
% it a second time in terminate/2.
ets:match_delete(Handlers, {'_', Pid}),
Expand Down
19 changes: 9 additions & 10 deletions src/couchdb/couch_external_server.erl
Expand Up @@ -16,8 +16,6 @@
-export([start_link/2, stop/1, execute/2]).
-export([init/1, terminate/2, handle_call/3, handle_cast/2, handle_info/2, code_change/3]).

-define(TIMEOUT, 5000).

-include("couch_db.hrl").

% External API
Expand All @@ -34,25 +32,26 @@ execute(Pid, JsonReq) ->
% Gen Server Handlers

init([Name, Command]) ->
?LOG_INFO("Starting process for: ~s", [Name]),
?LOG_INFO("EXTERNAL: Starting process for: ~s", [Name]),
?LOG_INFO("COMMAND: ~s", [Command]),
{ok, Pid} = couch_os_process:start_link(Command),
{ok, {Name, Command, Pid}}.

terminate(_Reason, {Name, _Command, Pid}) ->
?LOG_INFO("External Process Terminating: ~p: ~p", [Name, Pid]),
terminate(_Reason, {_Name, _Command, Pid}) ->
couch_os_process:stop(Pid),
ok.

handle_call({execute, JsonReq}, _From, {Name, Command, Pid}) ->
{reply, couch_os_process:prompt(Pid, JsonReq), {Name, Command, Pid}}.

handle_info({'EXIT', Pid, Reason}, {Name, Command, Pid}) ->
?LOG_INFO("EXTERNAL: Restarting process for ~s (reason: ~w)", [Name, Reason]),
{ok, Pid} = couch_os_process:start_link(Command),
{noreply, {Name, Command, Pid}}.
?LOG_INFO("EXTERNAL: Process for ~s exiting. (reason: ~w)", [Name, Reason]),
{stop, normal, {Name, Command, Pid}}.

handle_cast(stop, State) ->
{stop, normal, State};
handle_cast(stop, {Name, Command, Pid}) ->
?LOG_INFO("EXTERNAL: Shutting down ~s", [Name]),
exit(Pid, normal),
{stop, normal, {Name, Command, Pid}};
handle_cast(_Whatever, State) ->
{noreply, State}.

Expand Down

0 comments on commit 7840145

Please sign in to comment.