summaryrefslogtreecommitdiff
path: root/src/couch_inets/httpd_sup.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/couch_inets/httpd_sup.erl')
-rw-r--r--src/couch_inets/httpd_sup.erl137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/couch_inets/httpd_sup.erl b/src/couch_inets/httpd_sup.erl
new file mode 100644
index 00000000..94573394
--- /dev/null
+++ b/src/couch_inets/httpd_sup.erl
@@ -0,0 +1,137 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id$
+%%
+%%----------------------------------------------------------------------
+%% Purpose: The top supervisor for the http server (httpd) hangs under
+%% inets_sup.
+%%----------------------------------------------------------------------
+
+-module(httpd_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/1]).
+-export([start_child/1, stop_child/2]).
+
+%% Supervisor callback
+-export([init/1]).
+
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+start_link(HttpdServices) ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, [HttpdServices]).
+
+start_child(ConfigFile) ->
+ {ok, Spec} = httpd_child_spec(ConfigFile, 15000, []),
+ supervisor:start_child(?MODULE, Spec).
+
+stop_child(Addr, Port) ->
+ Name = {httpd_instance_sup, Addr, Port},
+ case supervisor:terminate_child(?MODULE, Name) of
+ ok ->
+ supervisor:delete_child(?MODULE, Name);
+ Error ->
+ Error
+ end.
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init([HttpdServices]) ->
+ RestartStrategy = one_for_one,
+ MaxR = 10,
+ MaxT = 3600,
+ Children = child_spec(HttpdServices, []),
+ {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
+%% The format of the httpd service is:
+%% httpd_service() -> {httpd,httpd()}
+%% httpd() -> [httpd_config()] | file()
+%% httpd_config() -> {file,file()} |
+%% {debug,debug()} |
+%% {accept_timeout,integer()}
+%% debug() -> disable | [debug_options()]
+%% debug_options() -> {all_functions,modules()} |
+%% {exported_functions,modules()} |
+%% {disable,modules()}
+%% modules() -> [atom()]
+child_spec([], Acc) ->
+ Acc;
+child_spec([{httpd, HttpdService} | Rest], Acc) ->
+ NewHttpdService = mk_tuple_list(HttpdService),
+ %% Acc2 = child_spec2(NewHttpdService,Acc),
+ NewAcc=
+ case catch child_spec2(NewHttpdService) of
+ {ok,Acc2} ->
+ [Acc2|Acc];
+ {error,Reason} ->
+ error_msg("failed to create child spec for ~n~p~ndue to: ~p",
+ [HttpdService,Reason]),
+% exit({error,Reason})
+ Acc
+ end,
+ child_spec(Rest,NewAcc).
+
+child_spec2(HttpdService) ->
+ Debug = http_util:key1search(HttpdService,debug,[]),
+ AcceptTimeout = http_util:key1search(HttpdService,accept_timeout,15000),
+ ConfigFile =
+ case http_util:key1search(HttpdService,file) of
+ undefined -> throw({error,{mandatory_conf_file_missed}});
+ File -> File
+ end,
+ httpd_util:valid_options(Debug,AcceptTimeout,ConfigFile),
+ httpd_child_spec(ConfigFile,AcceptTimeout,Debug).
+
+
+httpd_child_spec(ConfigFile,AcceptTimeout,Debug) ->
+ case httpd_conf:load(ConfigFile) of
+ {ok, ConfigList} ->
+ Port = httpd_util:key1search(ConfigList, port, 80),
+ Addr = httpd_util:key1search(ConfigList, bind_address),
+ {ok, httpd_child_spec(ConfigFile, AcceptTimeout,
+ Debug, Addr, Port)};
+ Error ->
+ Error
+ end.
+
+httpd_child_spec(ConfigFile, AcceptTimeout, Debug, Addr, Port) ->
+ Name = {httpd_instance_sup, Addr, Port},
+ StartFunc = {httpd_instance_sup, start_link,
+ [ConfigFile,AcceptTimeout,Debug]},
+ Restart = permanent,
+ Shutdown = infinity,
+ Modules = [httpd_instance_sup],
+ Type = supervisor,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+
+mk_tuple_list([]) ->
+ [];
+mk_tuple_list([H={_,_}|T]) ->
+ [H|mk_tuple_list(T)];
+mk_tuple_list(F) ->
+ [{file,F}].
+
+error_msg(F, A) ->
+ error_logger:error_msg(F ++ "~n", A).