Start a dedicated process to manage config changes
Also, restart chttpd only if the setting actually changed.
BugzID: 13179
Conflicts:
src/chttpd.erl
Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/22e0a3e3
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/22e0a3e3
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/22e0a3e3
Branch: refs/heads/import
Commit: 22e0a3e38de870c6ae76f31eed3506b194b7f7cf
Parents: 76a2f2b
Author: Adam Kocoloski <[email protected]>
Authored: Wed Feb 27 10:24:40 2013 -0500
Committer: Robert Newson <[email protected]>
Committed: Wed Mar 6 12:22:38 2013 -0600
----------------------------------------------------------------------
src/chttpd.erl | 13 +------
src/chttpd_config_listener.erl | 68 +++++++++++++++++++++++++++++++++++++
src/chttpd_sup.erl | 10 ++++--
3 files changed, 76 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/22e0a3e3/src/chttpd.erl
----------------------------------------------------------------------
diff --git a/src/chttpd.erl b/src/chttpd.erl
index 749f42b..aeb97b3 100644
--- a/src/chttpd.erl
+++ b/src/chttpd.erl
@@ -12,10 +12,9 @@
-module(chttpd).
-include_lib("couch/include/couch_db.hrl").
--behaviour(config_listener).
-export([start_link/0, start_link/1, start_link/2,
- stop/0, handle_request/1, handle_config_change/5,
+ stop/0, handle_request/1,
primary_header_value/2, header_value/2, header_value/3, qs_value/2,
qs_value/3, qs/1, qs_json_value/3, path/1, absolute_uri/2, body_length/1,
verify_is_server_admin/1, unquote/1, quote/1, recv/2, recv_chunked/4,
@@ -115,22 +114,12 @@ start_link(Name, Options) ->
Options2 = lists:keymerge(1, lists:sort(Options1), lists:sort(ServerOpts)),
case mochiweb_http:start(Options2) of
{ok, Pid} ->
- ok = config:listen_for_changes(?MODULE, nil),
{ok, Pid};
{error, Reason} ->
io:format("Failure to start Mochiweb: ~s~n", [Reason]),
{error, Reason}
end.
-handle_config_change("chttpd", "bind_address", _, _, _) ->
- ?MODULE:stop();
-handle_config_change("chttpd", "port", _, _, _) ->
- ?MODULE:stop();
-handle_config_change("chttpd", "backlog", _, _, _) ->
- ?MODULE:stop();
-handle_config_change("chttpd", "server_options", _, _, _) ->
- ?MODULE:stop().
-
stop() ->
catch mochiweb_http:stop(https),
mochiweb_http:stop(?MODULE).
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/22e0a3e3/src/chttpd_config_listener.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_config_listener.erl b/src/chttpd_config_listener.erl
new file mode 100644
index 0000000..874553d
--- /dev/null
+++ b/src/chttpd_config_listener.erl
@@ -0,0 +1,68 @@
+-module(chttpd_config_listener).
+-behaviour(gen_server).
+-behaviour(config_listener).
+
+% public interface
+-export([start_link/0]).
+
+% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ code_change/3, terminate/2]).
+
+% config_listener callback
+-export([handle_config_change/5]).
+
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+init([]) ->
+ Settings = [
+ {bind_address, config:get("chttpd", "bind_address")},
+ {port, config:get("chttpd", "port")},
+ {backlog, config:get("chttpd", "backlog")},
+ {server_options, config:get("chttpd", "server_options")}
+ ],
+ ok = config:listen_for_changes(?MODULE, Settings),
+ {ok, Settings}.
+
+handle_config_change("chttpd", "bind_address", Value, _, Settings) ->
+ maybe_replace(bind_address, Value, Settings);
+handle_config_change("chttpd", "port", Value, _, Settings) ->
+ maybe_replace(port, Value, Settings);
+handle_config_change("chttpd", "backlog", Value, _, Settings) ->
+ maybe_replace(backlog, Value, Settings);
+handle_config_change("chttpd", "server_options", Value, _, Settings) ->
+ maybe_replace(server_options, Value, Settings);
+handle_config_change(_, _, _, _, Settings) ->
+ {ok, Settings}.
+
+handle_call(_, _, State) ->
+ {reply, ignored, State}.
+
+handle_cast(_, State) ->
+ {noreply, State}.
+
+handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
+ erlang:send_after(5000, self(), restart_config_listener),
+ {noreply, State};
+handle_info(restart_config_listener, State) ->
+ ok = config:listen_for_changes(?MODULE, State),
+ {noreply, State};
+handle_info(_Msg, State) ->
+ {noreply, State}.
+
+terminate(_, _State) ->
+ ok.
+
+code_change(_, State, _) ->
+ {ok, State}.
+
+% private
+maybe_replace(Key, Value, Settings) ->
+ case couch_util:get_value(Key, Settings) of
+ Value ->
+ {ok, Settings};
+ _ ->
+ chttpd:stop(),
+ {ok, lists:keyreplace(Key, 1, {Key, Value}, Settings)}
+ end.
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/22e0a3e3/src/chttpd_sup.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_sup.erl b/src/chttpd_sup.erl
index bfe6be9..69283a9 100644
--- a/src/chttpd_sup.erl
+++ b/src/chttpd_sup.erl
@@ -16,10 +16,14 @@
-export([start_link/1]).
+%% Helper macro for declaring children of supervisor
+-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 100, Type, [I]}).
+
start_link(Args) ->
supervisor:start_link({local,?MODULE}, ?MODULE, Args).
init([]) ->
- Mod = chttpd,
- Spec = {Mod, {Mod,start_link,[]}, permanent, 100, worker, [Mod]},
- {ok, {{one_for_one, 3, 10}, [Spec]}}.
+ {ok, {{one_for_one, 3, 10}, [
+ ?CHILD(chttpd, worker),
+ ?CHILD(chttpd_config_listener, worker)
+ ]}}.