Merge branch 'master' into remove-externals
diff --git a/src/chttpd/src/chttpd_external.erl b/src/chttpd/src/chttpd_external.erl
index fa35c6b..451d87d 100644
--- a/src/chttpd/src/chttpd_external.erl
+++ b/src/chttpd/src/chttpd_external.erl
@@ -14,7 +14,6 @@
 
 -compile(tuple_calls).
 
--export([handle_external_req/2, handle_external_req/3]).
 -export([send_external_response/2]).
 -export([json_req_obj_fields/0, json_req_obj/2, json_req_obj/3, json_req_obj/4]).
 -export([default_or_content_type/2, parse_external_response/1]).
@@ -23,41 +22,6 @@
 
 -include_lib("couch/include/couch_db.hrl").
 
-% handle_external_req/2
-% for the old type of config usage:
-% _external = {chttpd_external, handle_external_req}
-% with urls like
-% /db/_external/action/design/name
-handle_external_req(#httpd{
-                        path_parts=[_DbName, _External, UrlName | _Path]
-                    }=HttpReq, Db) ->
-    process_external_req(HttpReq, Db, UrlName);
-handle_external_req(#httpd{path_parts=[_, _]}=Req, _Db) ->
-    send_error(Req, 404, <<"external_server_error">>, <<"No server name specified.">>);
-handle_external_req(Req, _) ->
-    send_error(Req, 404, <<"external_server_error">>, <<"Broken assumption">>).
-
-% handle_external_req/3
-% for this type of config usage:
-% _action = {chttpd_external, handle_external_req, <<"action">>}
-% with urls like
-% /db/_action/design/name
-handle_external_req(HttpReq, Db, Name) ->
-    process_external_req(HttpReq, Db, Name).
-
-process_external_req(HttpReq, Db, Name) ->
-
-    Response = couch_external_manager:execute(binary_to_list(Name),
-        json_req_obj(HttpReq, Db)),
-
-    case Response of
-    {unknown_external_server, Msg} ->
-        send_error(HttpReq, 404, <<"external_server_error">>, Msg);
-    _ ->
-        send_external_response(HttpReq, Response)
-    end.
-
-
 json_req_obj(Req, Db) ->
     json_req_obj(Req, Db, null).
 json_req_obj(Req, Db, DocId) ->
diff --git a/src/couch/src/couch.app.src b/src/couch/src/couch.app.src
index 2089387..706b439 100644
--- a/src/couch/src/couch.app.src
+++ b/src/couch/src/couch.app.src
@@ -16,7 +16,6 @@
     {registered, [
         couch_db_update,
         couch_db_update_notifier_sup,
-        couch_external_manager,
         couch_httpd,
         couch_primary_services,
         couch_proc_manager,
diff --git a/src/couch/src/couch_external_manager.erl b/src/couch/src/couch_external_manager.erl
deleted file mode 100644
index f131342..0000000
--- a/src/couch/src/couch_external_manager.erl
+++ /dev/null
@@ -1,120 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-%   http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(couch_external_manager).
--behaviour(gen_server).
--vsn(3).
--behaviour(config_listener).
-
--export([start_link/0, execute/2]).
--export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]).
-
-% config_listener api
--export([handle_config_change/5, handle_config_terminate/3]).
-
--include_lib("couch/include/couch_db.hrl").
-
--define(RELISTEN_DELAY, 5000).
-
-start_link() ->
-    gen_server:start_link({local, couch_external_manager},
-        couch_external_manager, [], []).
-
-execute(UrlName, JsonReq) ->
-    Pid = gen_server:call(couch_external_manager, {get, UrlName}),
-    case Pid of
-    {error, Reason} ->
-        Reason;
-    _ ->
-        couch_external_server:execute(Pid, JsonReq)
-    end.
-
-handle_config_change("external", UrlName, _, _, _) ->
-    {ok, gen_server:call(couch_external_manager, {config, UrlName})};
-handle_config_change(_, _, _, _, _) ->
-    {ok, nil}.
-
-handle_config_terminate(_, stop, _) ->
-    ok;
-handle_config_terminate(_Server, _Reason, _State) ->
-    erlang:send_after(?RELISTEN_DELAY, whereis(?MODULE), restart_config_listener).
-
-
-% gen_server API
-
-init([]) ->
-    process_flag(trap_exit, true),
-    Handlers = ets:new(couch_external_manager_handlers, [set, private]),
-    ok = config:listen_for_changes(?MODULE, nil),
-    {ok, Handlers}.
-
-terminate(_Reason, Handlers) ->
-    ets:foldl(fun({_UrlName, Pid}, nil) ->
-        couch_external_server:stop(Pid),
-        nil
-    end, nil, Handlers),
-    ok.
-
-handle_call({get, UrlName}, _From, Handlers) ->
-    case ets:lookup(Handlers, UrlName) of
-    [] ->
-        case config:get("external", UrlName, undefined) of
-        undefined ->
-            Msg = lists:flatten(
-                io_lib:format("No server configured for ~p.", [UrlName])),
-            {reply, {error, {unknown_external_server, ?l2b(Msg)}}, 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.
-
-    % Shutdown the old handler.
-    case ets:lookup(Handlers, UrlName) of
-    [{UrlName, Pid}] ->
-        couch_external_server:stop(Pid);
-    [] ->
-        ok
-    end,
-    % Wait for next request to boot the handler.
-    {reply, ok, Handlers}.
-
-handle_cast(_Whatever, State) ->
-    {noreply, State}.
-
-handle_info({'EXIT', Pid, normal}, Handlers) ->
-    couch_log:info("EXTERNAL: Server ~p terminated normally", [Pid]),
-    % The process terminated normally without us asking - Remove Pid from the
-    % handlers table so we don't attempt to reuse it
-    ets:match_delete(Handlers, {'_', Pid}),
-    {noreply, Handlers};
-
-handle_info({'EXIT', Pid, Reason}, Handlers) ->
-    couch_log:info("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}),
-    {stop, normal, Handlers};
-
-handle_info(restart_config_listener, State) ->
-    ok = config:listen_for_changes(?MODULE, nil),
-    {noreply, State}.
-
-
-code_change(_OldVsn, State, _Extra) ->
-    {ok, State}.
diff --git a/src/couch/src/couch_external_server.erl b/src/couch/src/couch_external_server.erl
deleted file mode 100644
index e2a5022..0000000
--- a/src/couch/src/couch_external_server.erl
+++ /dev/null
@@ -1,90 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-%   http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(couch_external_server).
--behaviour(gen_server).
--vsn(3).
-
--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]).
-
--include_lib("couch/include/couch_db.hrl").
-
--define(RELISTEN_DELAY, 5000).
--define(CONFIG_SUBSCRIPTION, [{"couchdb", "os_process_timeout"}]).
-
-% External API
-
-start_link(Name, Command) ->
-    gen_server:start_link(couch_external_server, [Name, Command], []).
-
-stop(Pid) ->
-    gen_server:cast(Pid, stop).
-
-execute(Pid, JsonReq) ->
-    {json, Json} = gen_server:call(Pid, {execute, JsonReq}, infinity),
-    ?JSON_DECODE(Json).
-
-% Gen Server Handlers
-
-init([Name, Command]) ->
-    couch_log:info("EXTERNAL: Starting process for: ~s", [Name]),
-    couch_log:info("COMMAND: ~s", [Command]),
-    ok = config:subscribe_for_changes(?CONFIG_SUBSCRIPTION),
-    process_flag(trap_exit, true),
-    Timeout = list_to_integer(config:get("couchdb", "os_process_timeout",
-        "5000")),
-    {ok, Pid} = couch_os_process:start_link(Command, [{timeout, Timeout}]),
-    {ok, {Name, Command, Pid, whereis(config_event)}}.
-
-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, normal}, State) ->
-    {noreply, State};
-handle_info({'EXIT', Pid, Reason}, {Name, Command, Pid, _}) ->
-    couch_log:info("EXTERNAL: Process for ~s exiting. (reason: ~w)",
-                   [Name, Reason]),
-    {stop, Reason, {Name, Command, Pid}};
-handle_info({config_change, "couchdb", "os_process_timeout", NewTimeout, _},
-        {_Name, _Command, Pid, _} = State) ->
-    couch_os_process:set_timeout(Pid, list_to_integer(NewTimeout)),
-    {noreply, State};
-handle_info({gen_event_EXIT, _Handler, _Reason}, State) ->
-    erlang:send_after(?RELISTEN_DELAY, self(), restart_config_listener),
-    {noreply, State};
-handle_info({'EXIT', Pid, _Reason}, {_, _, _, Pid} = State) ->
-    erlang:send_after(?RELISTEN_DELAY, self(), restart_config_listener),
-    {noreply, State};
-handle_info(restart_config_listener, {Name, Command, Pid, _} = State) ->
-    case whereis(config_event) of
-        undefined ->
-            erlang:send_after(?RELISTEN_DELAY, self(), restart_config_listener),
-            {noreply, State};
-        EventMgr ->
-            ok = config:subscribe_for_changes(?CONFIG_SUBSCRIPTION),
-            {noreply, {Name, Command, Pid, EventMgr}}
-    end.
-
-handle_cast(stop, {Name, _Command, Pid, _} = State) ->
-    couch_log:info("EXTERNAL: Shutting down ~s", [Name]),
-    exit(Pid, normal),
-    {stop, normal, State};
-handle_cast(_Whatever, State) ->
-    {noreply, State}.
-
-code_change(_OldVsn, State, _Extra) ->
-    {ok, State}.
diff --git a/src/couch/src/couch_httpd_external.erl b/src/couch/src/couch_httpd_external.erl
index 684f900..d4842fb 100644
--- a/src/couch/src/couch_httpd_external.erl
+++ b/src/couch/src/couch_httpd_external.erl
@@ -14,7 +14,6 @@
 
 -compile(tuple_calls).
 
--export([handle_external_req/2, handle_external_req/3]).
 -export([send_external_response/2, json_req_obj/2, json_req_obj/3]).
 -export([default_or_content_type/2, parse_external_response/1]).
 
@@ -22,39 +21,6 @@
 
 -include_lib("couch/include/couch_db.hrl").
 
-% handle_external_req/2
-% for the old type of config usage:
-% _external = {couch_httpd_external, handle_external_req}
-% with urls like
-% /db/_external/action/design/name
-handle_external_req(#httpd{
-                        path_parts=[_DbName, _External, UrlName | _Path]
-                    }=HttpReq, Db) ->
-    process_external_req(HttpReq, Db, UrlName);
-handle_external_req(#httpd{path_parts=[_, _]}=Req, _Db) ->
-    send_error(Req, 404, <<"external_server_error">>, <<"No server name specified.">>);
-handle_external_req(Req, _) ->
-    send_error(Req, 404, <<"external_server_error">>, <<"Broken assumption">>).
-
-% handle_external_req/3
-% for this type of config usage:
-% _action = {couch_httpd_external, handle_external_req, <<"action">>}
-% with urls like
-% /db/_action/design/name
-handle_external_req(HttpReq, Db, Name) ->
-    process_external_req(HttpReq, Db, Name).
-
-process_external_req(HttpReq, Db, Name) ->
-
-    Response = couch_external_manager:execute(binary_to_list(Name),
-        json_req_obj(HttpReq, Db)),
-
-    case Response of
-    {unknown_external_server, Msg} ->
-        send_error(HttpReq, 404, <<"external_server_error">>, Msg);
-    _ ->
-        send_external_response(HttpReq, Response)
-    end.
 json_req_obj(Req, Db) -> json_req_obj(Req, Db, null).
 json_req_obj(#httpd{mochi_req=Req,
                method=Method,