Rewrite the boot procedure for the couch app We had a lot of historical cruft lying around from before people knew hot OTP worked. This does some cleanup to make things a bit more tidy through this section but we still have a long ways to go.
Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/44713866 Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/44713866 Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/44713866 Branch: refs/heads/import Commit: 4471386621acdd9bf7fc336c9a027aee58de2e39 Parents: bafb960 Author: Paul J. Davis <[email protected]> Authored: Mon Mar 11 16:13:14 2013 -0500 Committer: Paul J. Davis <[email protected]> Committed: Fri Jan 17 16:44:31 2014 -0800 ---------------------------------------------------------------------- Makefile.am | 5 +- src/couch.app.tpl.in | 2 +- src/couch.erl | 48 ++++++++-- src/couch_app.erl | 37 ++------ src/couch_httpd_misc_handlers.erl | 2 +- src/couch_proc_manager.erl | 3 + src/couch_secondary_sup.erl | 2 +- src/couch_server_sup.erl | 153 ------------------------------- src/couch_sup.erl | 159 +++++++++++++++++++++++++++++++++ 9 files changed, 214 insertions(+), 197 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/44713866/Makefile.am ---------------------------------------------------------------------- diff --git a/Makefile.am b/Makefile.am index 63c557e..9a656f7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -70,10 +70,10 @@ source_files = \ src/couch_query_servers.erl \ src/couch_secondary_sup.erl \ src/couch_server.erl \ - src/couch_server_sup.erl \ src/couch_stats_aggregator.erl \ src/couch_stats_collector.erl \ src/couch_stream.erl \ + src/couch_sup.erl \ src/couch_task_status.erl \ src/couch_users_db.erl \ src/couch_util.erl \ @@ -131,10 +131,10 @@ compiled_files = \ ebin/couch_query_servers.beam \ ebin/couch_secondary_sup.beam \ ebin/couch_server.beam \ - ebin/couch_server_sup.beam \ ebin/couch_stats_aggregator.beam \ ebin/couch_stats_collector.beam \ ebin/couch_stream.beam \ + ebin/couch_sup.beam \ ebin/couch_task_status.beam \ ebin/couch_users_db.beam \ ebin/couch_util.beam \ @@ -167,7 +167,6 @@ compiled_files = \ # couch_rep.html \ # couch_rep_sup.html \ # couch_server.html \ -# couch_server_sup.html \ # couch_stream.html \ # couch_util.html http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/44713866/src/couch.app.tpl.in ---------------------------------------------------------------------- diff --git a/src/couch.app.tpl.in b/src/couch.app.tpl.in index 1cd0154..9b7536b 100644 --- a/src/couch.app.tpl.in +++ b/src/couch.app.tpl.in @@ -12,7 +12,7 @@ couch_proc_manager, couch_secondary_services, couch_server, - couch_server_sup, + couch_sup, couch_stats_aggregator, couch_stats_collector, couch_task_status http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/44713866/src/couch.erl ---------------------------------------------------------------------- diff --git a/src/couch.erl b/src/couch.erl index 7d53d0c..15cffbc 100644 --- a/src/couch.erl +++ b/src/couch.erl @@ -14,18 +14,52 @@ -compile(export_all). + +deps() -> + [ + sasl, + inets, + os_mon, + crypto, + public_key, + ssl, + oauth, + ibrowse, + mochiweb, + config, + twig + ]. + + start() -> - ok = application:start(couch). + catch erlang:system_flag(scheduler_bind_type, default_bind), + case start_apps(deps()) of + ok -> + ok = application:start(couch); + Else -> + throw(Else) + end. + stop() -> application:stop(couch). + restart() -> - case stop() of + init:restart(). + + +start_apps([]) -> + ok; +start_apps([App|Rest]) -> + case application:start(App) of ok -> - start(); - {error, {not_started,couch}} -> - start(); - {error, Reason} -> - {error, Reason} + start_apps(Rest); + {error, {already_started, App}} -> + start_apps(Rest); + {error, _Reason} when App =:= public_key -> + % ignore on R12B5 + start_apps(Rest); + {error, _Reason} -> + {error, {app_would_not_start, App}} end. http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/44713866/src/couch_app.erl ---------------------------------------------------------------------- diff --git a/src/couch_app.erl b/src/couch_app.erl index 3120a1f..d284c2b 100644 --- a/src/couch_app.erl +++ b/src/couch_app.erl @@ -18,39 +18,14 @@ -export([start/2, stop/1]). -start(_Type, DefaultIniFiles) -> - IniFiles = get_ini_files(DefaultIniFiles), - case start_apps([crypto, public_key, sasl, inets, oauth, ssl, ibrowse, mochiweb, os_mon]) of - ok -> - couch_server_sup:start_link(IniFiles); - {error, Reason} -> - {error, Reason} +start(_Type, _) -> + case couch_sup:start_link() of + {ok, _} = Resp -> + Resp; + Else -> + throw(Else) end. stop(_) -> ok. -get_ini_files(Default) -> - case init:get_argument(couch_ini) of - error -> - Default; - {ok, [[]]} -> - Default; - {ok, [Values]} -> - Values - end. - -start_apps([]) -> - ok; -start_apps([App|Rest]) -> - case application:start(App) of - ok -> - start_apps(Rest); - {error, {already_started, App}} -> - start_apps(Rest); - {error, _Reason} when App =:= public_key -> - % ignore on R12B5 - start_apps(Rest); - {error, _Reason} -> - {error, {app_would_not_start, App}} - end. http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/44713866/src/couch_httpd_misc_handlers.erl ---------------------------------------------------------------------- diff --git a/src/couch_httpd_misc_handlers.erl b/src/couch_httpd_misc_handlers.erl index e46dee3..b8f59cd 100644 --- a/src/couch_httpd_misc_handlers.erl +++ b/src/couch_httpd_misc_handlers.erl @@ -98,7 +98,7 @@ handle_restart_req(#httpd{method='POST'}=Req) -> couch_httpd:validate_ctype(Req, "application/json"), ok = couch_httpd:verify_is_server_admin(Req), Result = send_json(Req, 202, {[{ok, true}]}), - couch_server_sup:restart_core_server(), + couch:restart(), Result; handle_restart_req(Req) -> send_method_not_allowed(Req, "POST"). http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/44713866/src/couch_proc_manager.erl ---------------------------------------------------------------------- diff --git a/src/couch_proc_manager.erl b/src/couch_proc_manager.erl index 6130fc9..45b334f 100644 --- a/src/couch_proc_manager.erl +++ b/src/couch_proc_manager.erl @@ -127,6 +127,9 @@ handle_cast(_Msg, State) -> {noreply, State}. +handle_info(shutdown, State) -> + {stop, shutdown, State}; + handle_info({'EXIT', _, {ok, Proc0, {Client,_} = From}}, State) -> link(Proc0#proc.pid), Proc = assign_proc(State#state.tab, Client, Proc0), http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/44713866/src/couch_secondary_sup.erl ---------------------------------------------------------------------- diff --git a/src/couch_secondary_sup.erl b/src/couch_secondary_sup.erl index 4f2d1c8..d0ed0c2 100644 --- a/src/couch_secondary_sup.erl +++ b/src/couch_secondary_sup.erl @@ -39,4 +39,4 @@ init([]) -> end || {Name, SpecStr} <- config:get("daemons"), SpecStr /= ""], - {ok, {{one_for_one, 10, 3600}, Children}}. + {ok, {{one_for_one, 50, 3600}, Children}}. http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/44713866/src/couch_server_sup.erl ---------------------------------------------------------------------- diff --git a/src/couch_server_sup.erl b/src/couch_server_sup.erl deleted file mode 100644 index c42bcfb..0000000 --- a/src/couch_server_sup.erl +++ /dev/null @@ -1,153 +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_server_sup). --behaviour(supervisor). --behaviour(config_listener). - - --export([start_link/1,stop/0, restart_core_server/0]). - --include_lib("couch/include/couch_db.hrl"). - -%% supervisor callbacks --export([init/1]). - -% config_listener api --export([handle_config_change/5]). - -start_link(IniFiles) -> - case whereis(couch_server_sup) of - undefined -> - start_server(IniFiles); - _Else -> - {error, already_started} - end. - -restart_core_server() -> - init:restart(). - -start_server(IniFiles) -> - case init:get_argument(pidfile) of - {ok, [PidFile]} -> - case file:write_file(PidFile, os:getpid()) of - ok -> ok; - {error, Reason} -> - io:format("Failed to write PID file ~s: ~s", - [PidFile, file:format_error(Reason)]) - end; - _ -> ok - end, - - LogLevel = config:get("log", "level", "info"), - % announce startup - io:format("Apache CouchDB ~s (LogLevel=~s) is starting.~n", [ - couch_server:get_version(), - LogLevel - ]), - case LogLevel of - "debug" -> - io:format("Configuration Settings ~p:~n", [IniFiles]), - [io:format(" [~s] ~s=~p~n", [Module, Variable, Value]) - || {{Module, Variable}, Value} <- config:all()]; - _ -> ok - end, - - BaseChildSpecs = - {{one_for_one, 10, 60}, [ - {couch_primary_services, - {couch_primary_sup, start_link, []}, - permanent, - infinity, - supervisor, - [couch_primary_sup]}, - {couch_secondary_services, - {couch_secondary_sup, start_link, []}, - permanent, - infinity, - supervisor, - [couch_secondary_sup]} - ]}, - - % ensure these applications are running - application:start(ibrowse), - application:start(crypto), - - {ok, Pid} = supervisor:start_link( - {local, couch_server_sup}, couch_server_sup, BaseChildSpecs), - - ok = config:listen_for_changes(?MODULE, nil), - - Ip = config:get("httpd", "bind_address"), - io:format("Apache CouchDB has started. Time to relax.~n"), - Uris = [get_uri(Name, Ip) || Name <- [couch_httpd, https]], - [begin - case Uri of - undefined -> ok; - Uri -> ?LOG_INFO("Apache CouchDB has started on ~s", [Uri]) - end - end - || Uri <- Uris], - case config:get("couchdb", "uri_file", null) of - null -> ok; - UriFile -> - Lines = [begin case Uri of - undefined -> []; - Uri -> io_lib:format("~s~n", [Uri]) - end end || Uri <- Uris], - case file:write_file(UriFile, Lines) of - ok -> ok; - {error, Reason2} = Error -> - ?LOG_ERROR("Failed to write to URI file ~s: ~s", - [UriFile, file:format_error(Reason2)]), - throw(Error) - end - end, - - {ok, Pid}. - -stop() -> - catch exit(whereis(couch_server_sup), normal). - - -handle_config_change("daemons", _, _, _, _) -> - exit(whereis(couch_server_sup), shutdown), - remove_handler; -handle_config_change("couchdb", "util_driver_dir", _, _, _) -> - [Pid] = [P || {collation_driver, P, _, _} - <- supervisor:which_children(couch_primary_services)], - Pid ! reload_driver, - {ok, nil}; -handle_config_change(_, _, _, _, _) -> - {ok, nil}. - -init(ChildSpecs) -> - {ok, ChildSpecs}. - -get_uri(Name, Ip) -> - case get_port(Name) of - undefined -> - undefined; - Port -> - io_lib:format("~s://~s:~w/", [get_scheme(Name), Ip, Port]) - end. - -get_scheme(couch_httpd) -> "http"; -get_scheme(https) -> "https". - -get_port(Name) -> - try - mochiweb_socket_server:get(Name, port) - catch - exit:{noproc, _}-> - undefined - end. http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/44713866/src/couch_sup.erl ---------------------------------------------------------------------- diff --git a/src/couch_sup.erl b/src/couch_sup.erl new file mode 100644 index 0000000..3508d4f --- /dev/null +++ b/src/couch_sup.erl @@ -0,0 +1,159 @@ +% 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_sup). +-behaviour(supervisor). +-behaviour(config_listener). + + +-export([ + start_link/0, + init/1, + handle_config_change/5 +]). + + +-include_lib("couch/include/couch_db.hrl"). + + +start_link() -> + write_pidfile(), + notify_starting(), + + case supervisor:start_link({local, ?MODULE}, ?MODULE, []) of + {ok, _} = Resp -> + notify_started(), + notify_uris(), + write_uris(), + ok = config:listen_for_changes(?MODULE, nil), + Resp; + Else -> + notify_error(Else), + Else + end. + + +init(_Args) -> + twig:log(info, "Starting ~s", [?MODULE]), + {ok, {{one_for_one,10, 60}, [ + { + couch_primary_services, + {couch_primary_sup, start_link, []}, + permanent, + infinity, + supervisor, + [couch_primary_sup] + }, + { + couch_secondary_services, + {couch_secondary_sup, start_link, []}, + permanent, + infinity, + supervisor, + [couch_secondary_sup] + } + ]}}. + + +handle_config_change("daemons", _, _, _, _) -> + exit(whereis(couch_server_sup), shutdown), + remove_handler; +handle_config_change("couchdb", "util_driver_dir", _, _, _) -> + [Pid] = [P || {collation_driver, P, _, _} + <- supervisor:which_children(couch_primary_services)], + Pid ! reload_driver, + {ok, nil}; +handle_config_change(_, _, _, _, _) -> + {ok, nil}. + + +notify_starting() -> + io:format("Apache CouchDB ~s (LogLevel=~s) is starting.~n", [ + couch_server:get_version(), + config:get("log", "level", "info") + ]). + + +notify_started() -> + io:format("Apache CouchDB has started. Time to relax.~n"). + + +notify_error(Error) -> + io:format("Error starting Apache CouchDB:~n~n ~p~n~n", [Error]). + + +notify_uris() -> + lists:foreach(fun(Uri) -> + ?LOG_INFO("Apache CouchDB has started on ~s", [Uri]) + end, get_uris()). + + +write_pidfile() -> + case init:get_argument(pidfile) of + {ok, [PidFile]} -> + write_file(PidFile, os:getpid()); + _ -> + ok + end. + + +write_uris() -> + case config:get("couchdb", "uri_file", null) of + null -> + ok; + UriFile -> + Lines = [io_lib:format("~s~n", [Uri]) || Uri <- get_uris()], + write_file(UriFile, Lines) + end. + + +get_uris() -> + Ip = config:get("httpd", "bind_address"), + lists:flatmap(fun(Uri) -> + case get_uri(Uri, Ip) of + undefined -> []; + Else -> [Else] + end + end, [couch_httpd, https]). + + +get_uri(Name, Ip) -> + case get_port(Name) of + undefined -> + undefined; + Port -> + io_lib:format("~s://~s:~w/", [get_scheme(Name), Ip, Port]) + end. + + +get_scheme(couch_httpd) -> "http"; +get_scheme(https) -> "https". + + +get_port(Name) -> + try + mochiweb_socket_server:get(Name, port) + catch + exit:{noproc, _} -> + undefined + end. + + +write_file(FileName, Contents) -> + case file:write_file(FileName, Contents) of + ok -> + ok; + {error, Reason} -> + Args = [FileName, file:format_error(Reason)], + io:format(standard_error, "Failed ot write ~s :: ~s", Args), + throw({error, Reason}) + end.
