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)
+    ]}}.

Reply via email to