Return-Path: X-Original-To: apmail-couchdb-commits-archive@www.apache.org Delivered-To: apmail-couchdb-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 6EA19C6EC for ; Thu, 7 Aug 2014 15:37:26 +0000 (UTC) Received: (qmail 86951 invoked by uid 500); 7 Aug 2014 15:37:25 -0000 Delivered-To: apmail-couchdb-commits-archive@couchdb.apache.org Received: (qmail 86785 invoked by uid 500); 7 Aug 2014 15:37:25 -0000 Mailing-List: contact commits-help@couchdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@couchdb.apache.org Delivered-To: mailing list commits@couchdb.apache.org Received: (qmail 86486 invoked by uid 99); 7 Aug 2014 15:37:25 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 07 Aug 2014 15:37:25 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 0D3409C29A6; Thu, 7 Aug 2014 15:37:24 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: rnewson@apache.org To: commits@couchdb.apache.org Date: Thu, 07 Aug 2014 15:37:32 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [10/50] couch commit: updated refs/heads/windsor-merge to 6e60cbe 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 Commit: acb80abc56eb85aa910736d913e7dcb4f8b05682 Parents: 3bf3cbd Author: Adam Kocoloski Authored: Mon Jun 3 13:24:02 2013 -0400 Committer: Robert Newson 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)),