You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2014/08/05 23:18:03 UTC

[20/36] couch commit: updated refs/heads/windsor-merge-211 to b7adb86

Allow operator to forcibly terminate stale procs

This patch adds a new terminate_stale_procs/0 command which kills off
any OS processes with spawn times older than the current threshold time,
regardless of whether the process has a client.  It also refactors the
internals to use the same logic to terminate a process in every case.

BugzID: 19529


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/acb80abc
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/acb80abc
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/acb80abc

Branch: refs/heads/windsor-merge-211
Commit: acb80abc56eb85aa910736d913e7dcb4f8b05682
Parents: 3bf3cbd
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Mon Jun 3 13:24:02 2013 -0400
Committer: Robert Newson <rn...@apache.org>
Committed: Tue Aug 5 12:03:15 2014 +0100

----------------------------------------------------------------------
 src/couch_proc_manager.erl | 37 ++++++++++++++++++++++++-------------
 1 file changed, 24 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/acb80abc/src/couch_proc_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_proc_manager.erl b/src/couch_proc_manager.erl
index d06e7b9..8cb53cb 100644
--- a/src/couch_proc_manager.erl
+++ b/src/couch_proc_manager.erl
@@ -22,7 +22,8 @@
     get_proc_count/0,
     get_stale_proc_count/0,
     new_proc/1,
-    reload/0
+    reload/0,
+    terminate_stale_procs/0
 ]).
 
 % config_listener api
@@ -69,6 +70,9 @@ get_stale_proc_count() ->
 reload() ->
     gen_server:call(?MODULE, bump_threshold_ts).
 
+terminate_stale_procs() ->
+    gen_server:call(?MODULE, terminate_stale_procs).
+
 init([]) ->
     process_flag(trap_exit, true),
     ok = config:listen_for_changes(?MODULE, nil),
@@ -133,14 +137,20 @@ handle_call({ret_proc, #proc{client=Ref, lang=Lang0} = Proc}, _From, State) ->
 
 handle_call(bump_threshold_ts, _From, #state{tab = Tab} = State) ->
     FoldFun = fun(#proc_int{client = nil, pid = Pid}, _) ->
-        gen_server:cast(Pid, stop),
-        ets:delete(Tab, Pid);
+        remove_proc(Tab, Pid);
     (_, _) ->
         ok
     end,
     ets:foldl(FoldFun, nil, Tab),
     {reply, ok, State#state{threshold_ts = os:timestamp()}};
 
+handle_call(terminate_stale_procs, _From, State) ->
+    #state{tab = Tab, threshold_ts = T0} = State,
+    MatchHead = #proc_int{pid = '$1', t0 = '$2', _ = '_'},
+    MatchSpec = [{MatchHead, [{'<', '$2', T0}], ['$1']}],
+    lists:foreach(fun(P) -> remove_proc(Tab,P) end, ets:select(Tab, MatchSpec)),
+    {reply, ok, State};
+
 handle_call(_Call, _From, State) ->
     {reply, ignored, State}.
 
@@ -152,14 +162,7 @@ handle_cast({os_proc_idle, Pid}, #state{tab=Tab, proc_counts=Counts}=State0) ->
             case dict:find(Lang, Counts) of
                 {ok, Count} when Count > Limit ->
                     ?LOG_INFO("Closing idle OS Process: ~p", [Pid]),
-                    ets:delete(Tab, Pid),
-                    case is_process_alive(Pid) of
-                        true ->
-                            unlink(Pid),
-                            gen_server:cast(Pid, stop);
-                        _ ->
-                            ok
-                    end,
+                    remove_proc(Tab, Pid),
                     State0#state{
                         proc_counts=dict:update_counter(Lang, -1, Counts)
                     };
@@ -394,8 +397,7 @@ return_proc(#state{} = State, #proc_int{} = ProcInt) ->
         case get_waiting_client(Waiting, Lang) of
             nil ->
                 if ProcInt#proc_int.t0 < T0 ->
-                    gen_server:cast(Pid, stop),
-                    ets:delete(Tab, Pid);
+                    remove_proc(Tab, Pid);
                 true ->
                     gen_server:cast(Pid, garbage_collect),
                     ets:insert(Tab, ProcInt#proc_int{client=nil})
@@ -417,6 +419,15 @@ return_proc(#state{} = State, #proc_int{} = ProcInt) ->
         end
     end.
 
+remove_proc(Tab, Pid) ->
+    ets:delete(Tab, Pid),
+    case is_process_alive(Pid) of true ->
+        unlink(Pid),
+        gen_server:cast(Pid, stop);
+    false ->
+        ok
+    end.
+
 -spec export_proc(#proc_int{}) -> #proc{}.
 export_proc(#proc_int{} = ProcInt) ->
     [_ | Data] = lists:sublist(record_info(size, proc), tuple_to_list(ProcInt)),