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 00:18:20 UTC

[18/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

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/0e78ae2f
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/0e78ae2f
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/0e78ae2f

Branch: refs/heads/windsor-merge-102
Commit: 0e78ae2ff7a28cea5353dae05dc1432f1dfbe4fa
Parents: 814eadc
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Mon Jun 3 13:24:02 2013 -0400
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 18:39:47 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/0e78ae2f/src/couch_proc_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_proc_manager.erl b/src/couch_proc_manager.erl
index e0f03e5..93c53cb 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),
@@ -134,14 +138,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}.
 
@@ -153,14 +163,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)
                     };
@@ -323,6 +326,15 @@ export_proc(#proc_int{} = ProcInt) ->
     [_ | Data] = lists:sublist(record_info(size, proc), tuple_to_list(ProcInt)),
     list_to_tuple([proc | Data]).
 
+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.
+
 proc_with_ddoc(DDoc, DDocKey, Procs) ->
     Filter = fun(#proc_int{ddoc_keys=Keys}) -> not lists:member(DDocKey, Keys) end,
     case lists:dropwhile(Filter, Procs) of
@@ -382,8 +394,7 @@ return_proc(State, #proc{pid=Pid, lang=Lang} = Proc) ->
             nil ->
                 [ProcInt] = ets:lookup(Tab, Pid),
                 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, Proc#proc{client=nil})