summaryrefslogtreecommitdiff
path: root/src/couchdb/couch_server_sup.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/couchdb/couch_server_sup.erl')
-rw-r--r--src/couchdb/couch_server_sup.erl185
1 files changed, 185 insertions, 0 deletions
diff --git a/src/couchdb/couch_server_sup.erl b/src/couchdb/couch_server_sup.erl
new file mode 100644
index 00000000..8b9889e7
--- /dev/null
+++ b/src/couchdb/couch_server_sup.erl
@@ -0,0 +1,185 @@
+% 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).
+
+-define(DEFAULT_INI, "couch.ini").
+
+-export([start_link/1,stop/0]).
+
+%% supervisor callbacks
+-export([init/1]).
+
+start_link(IniFilename) ->
+ case whereis(couch_server_sup) of
+ undefined ->
+ start_server(IniFilename);
+ _Else ->
+ {error, already_started}
+ end.
+
+start_server("") ->
+ % no ini file specified, check the command line args
+ IniFile =
+ case init:get_argument(couchini) of
+ {ok, [CmdLineIniFilename]} ->
+ CmdLineIniFilename;
+ _Else ->
+ ?DEFAULT_INI
+ end,
+ start_server(IniFile);
+start_server(InputIniFilename) ->
+
+ case init:get_argument(pidfile) of
+ {ok, [PidFile]} ->
+ case file:write_file(PidFile, os:getpid()) of
+ ok -> ok;
+ Error -> io:format("Failed to write PID file ~s, error: ~p", [PidFile, Error])
+ end;
+ _ -> ok
+ end,
+
+ {ok, Cwd} = file:get_cwd(),
+ IniFilename = couch_util:abs_pathname(InputIniFilename),
+ IniBin =
+ case file:read_file(IniFilename) of
+ {ok, IniBin0} ->
+ IniBin0;
+ {error, enoent} ->
+ Msg = io_lib:format("Couldn't find server configuration file ~s.", [InputIniFilename]),
+ io:format("~s~n", [Msg]),
+ throw({startup_error, Msg})
+ end,
+ {ok, Ini} = couch_util:parse_ini(binary_to_list(IniBin)),
+
+ ConsoleStartupMsg = proplists:get_value({"Couch", "ConsoleStartupMsg"}, Ini, "Apache CouchDB is starting."),
+ LogLevel = list_to_atom(proplists:get_value({"Couch", "LogLevel"}, Ini, "error")),
+ DbRootDir = proplists:get_value({"Couch", "DbRootDir"}, Ini, "."),
+ HttpConfigFile = proplists:get_value({"Couch", "HttpConfigFile"}, Ini, "couch_httpd.conf"),
+ LogFile = proplists:get_value({"Couch", "LogFile"}, Ini, "couchdb.log"),
+ UtilDriverDir = proplists:get_value({"Couch", "UtilDriverDir"}, Ini, ""),
+ UpdateNotifierExes = proplists:get_all_values({"Couch", "DbUpdateNotificationProcess"}, Ini),
+ FtSearchQueryServer = proplists:get_value({"Couch", "FullTextSearchQueryServer"}, Ini, ""),
+ RemoteRestart = list_to_atom(proplists:get_value({"Couch", "AllowRemoteRestart"}, Ini, "undefined")),
+ ServerOptions = [{remote_restart, RemoteRestart}],
+ QueryServers = [{Lang, QueryExe} || {{"Couch Query Servers", Lang}, QueryExe} <- Ini],
+
+ ChildProcesses =
+ [{couch_log,
+ {couch_log, start_link, [LogFile, LogLevel]},
+ permanent,
+ brutal_kill,
+ worker,
+ [couch_server]},
+ {couch_db_update_event,
+ {gen_event, start_link, [{local, couch_db_update}]},
+ permanent,
+ 1000,
+ supervisor,
+ dynamic},
+ {couch_server,
+ {couch_server, sup_start_link, [DbRootDir, ServerOptions]},
+ permanent,
+ brutal_kill,
+ worker,
+ [couch_server]},
+ {couch_util,
+ {couch_util, start_link, [UtilDriverDir]},
+ permanent,
+ brutal_kill,
+ worker,
+ [couch_util]},
+ {couch_query_servers,
+ {couch_query_servers, start_link, [QueryServers]},
+ permanent,
+ brutal_kill,
+ worker,
+ [couch_query_servers]},
+ {couch_view,
+ {couch_view, start_link, [DbRootDir]},
+ permanent,
+ brutal_kill,
+ worker,
+ [couch_view]},
+ {httpd,
+ {httpd, start_link, [HttpConfigFile]},
+ permanent,
+ 1000,
+ supervisor,
+ [httpd]}
+ ] ++
+ lists:map(fun(UpdateNotifierExe) ->
+ {UpdateNotifierExe,
+ {couch_db_update_notifier, start_link, [UpdateNotifierExe]},
+ permanent,
+ 1000,
+ supervisor,
+ [couch_db_update_notifier]}
+ end, UpdateNotifierExes)
+ ++
+ case FtSearchQueryServer of
+ "" ->
+ [];
+ _ ->
+ [{couch_ft_query,
+ {couch_ft_query, start_link, [FtSearchQueryServer]},
+ permanent,
+ 1000,
+ supervisor,
+ [httpd]}]
+ end,
+
+ io:format("couch ~s (LogLevel=~s)~n", [couch_server:get_version(), LogLevel]),
+ io:format("~s~n", [ConsoleStartupMsg]),
+
+ process_flag(trap_exit, true),
+ StartResult = (catch supervisor:start_link(
+ {local, couch_server_sup}, couch_server_sup, ChildProcesses)),
+
+ ConfigInfo = io_lib:format("Config Info ~s:~n\tCurrentWorkingDir=~s~n" ++
+ "\tDbRootDir=~s~n" ++
+ "\tHttpConfigFile=~s~n" ++
+ "\tLogFile=~s~n" ++
+ "\tUtilDriverDir=~s~n" ++
+ "\tDbUpdateNotificationProcesses=~s~n" ++
+ "\tFullTextSearchQueryServer=~s~n" ++
+ "~s",
+ [IniFilename,
+ Cwd,
+ DbRootDir,
+ HttpConfigFile,
+ LogFile,
+ UtilDriverDir,
+ UpdateNotifierExes,
+ FtSearchQueryServer,
+ [lists:flatten(io_lib:format("\t~s=~s~n", [Lang, QueryExe])) || {Lang, QueryExe} <- QueryServers]]),
+ couch_log:debug("~s", [ConfigInfo]),
+
+ case StartResult of
+ {ok,_} ->
+ % only output when startup was successful
+ io:format("Apache CouchDB has started. Time to relax.~n");
+ _ ->
+ % Since we failed startup, unconditionally dump configuration data to console
+ io:format("~s", [ConfigInfo]),
+ ok
+ end,
+ process_flag(trap_exit, false),
+ StartResult.
+
+stop() ->
+ catch exit(whereis(couch_server_sup), normal),
+ couch_log:stop().
+
+init(ChildProcesses) ->
+ {ok, {{one_for_one, 10, 3600}, ChildProcesses}}.