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 73AA5DB3A for ; Tue, 14 Aug 2012 20:19:01 +0000 (UTC) Received: (qmail 13293 invoked by uid 500); 14 Aug 2012 20:19:01 -0000 Delivered-To: apmail-couchdb-commits-archive@couchdb.apache.org Received: (qmail 13259 invoked by uid 500); 14 Aug 2012 20:19:01 -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 13249 invoked by uid 99); 14 Aug 2012 20:19:01 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 14 Aug 2012 20:19:01 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id DA6CE1D27F; Tue, 14 Aug 2012 20:19:00 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: davisp@apache.org To: commits@couchdb.apache.org X-Mailer: ASF-Git Admin Mailer Subject: git commit: COUCHDB-1444 Broken couch_view_group Message-Id: <20120814201900.DA6CE1D27F@tyr.zones.apache.org> Date: Tue, 14 Aug 2012 20:19:00 +0000 (UTC) Updated Branches: refs/heads/1.2.x bb8397707 -> 53490d915 COUCHDB-1444 Broken couch_view_group It appears that exit signals were propogating between couch_view_updater processes through couch_os_process and friends. This changes the use of the 'EXIT' signal to a '$gen_cast' message. Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/53490d91 Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/53490d91 Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/53490d91 Branch: refs/heads/1.2.x Commit: 53490d915038c04ed47f0c8a00b771583c483b0e Parents: bb83977 Author: Paul Joseph Davis Authored: Fri Aug 10 10:45:03 2012 -0500 Committer: Paul Joseph Davis Committed: Fri Aug 10 11:41:12 2012 -0500 ---------------------------------------------------------------------- src/couchdb/couch_view_compactor.erl | 26 +++++++++--- src/couchdb/couch_view_group.erl | 63 ++++++++++++++--------------- src/couchdb/couch_view_updater.erl | 8 ++- 3 files changed, 56 insertions(+), 41 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb/blob/53490d91/src/couchdb/couch_view_compactor.erl ---------------------------------------------------------------------- diff --git a/src/couchdb/couch_view_compactor.erl b/src/couchdb/couch_view_compactor.erl index 58600c8..a7dc68c 100644 --- a/src/couchdb/couch_view_compactor.erl +++ b/src/couchdb/couch_view_compactor.erl @@ -117,13 +117,27 @@ maybe_retry_compact(#db{name = DbName} = Db, GroupId, NewGroup) -> couch_db:close(Db); update -> {ok, Db2} = couch_db:reopen(Db), - {_, Ref} = erlang:spawn_monitor(fun() -> - couch_view_updater:update(nil, NewGroup, Db2) + Self = self(), + {MPid, MRef} = erlang:spawn_monitor(fun() -> + couch_view_updater:update(Self, NewGroup, Db2) end), - receive - {'DOWN', Ref, _, _, {new_group, NewGroup2}} -> - maybe_retry_compact(Db2, GroupId, NewGroup2) - end + NewGroup1 = get_new_group(MPid, MRef), + erlang:demonitor(MRef, [flush]), + maybe_retry_compact(Db2, GroupId, NewGroup1) + end. + +get_new_group(Pid, Ref) -> + receive + {'DOWN', Ref, _, _, {new_group, NewGroup}} -> + NewGroup; + {'DOWN', Ref, _, _, Reason} -> + erlang:error({view_compaction_error, Reason}); + {'$gen_cast', {Pid, new_group, NewGroup}} -> + NewGroup; + {'$gen_cast', {partial_update, _, _}} -> + get_new_group(Pid, Ref); + Else -> + erlang:error({view_compaction_error, Else}) end. %% @spec compact_view(View, EmptyView, Retry, Acc) -> {CompactView, NewAcc} http://git-wip-us.apache.org/repos/asf/couchdb/blob/53490d91/src/couchdb/couch_view_group.erl ---------------------------------------------------------------------- diff --git a/src/couchdb/couch_view_group.erl b/src/couchdb/couch_view_group.erl index fee2547..5f83c05 100644 --- a/src/couchdb/couch_view_group.erl +++ b/src/couchdb/couch_view_group.erl @@ -271,6 +271,37 @@ handle_cast({partial_update, Pid, #group{sig=GroupSig}=NewGroup}, #group_state{u handle_cast({partial_update, _, _}, State) -> %% message from an old (probably pre-compaction) updater; ignore {noreply, State}; +handle_cast({FromPid, new_group, #group{sig=GroupSig} = Group}, + #group_state{db_name=DbName, + group=#group{sig=GroupSig}, + updater_pid=UpPid, + ref_counter=RefCounter, + waiting_list=WaitList, + shutdown=Shutdown, + waiting_commit=WaitingCommit}=State) when UpPid == FromPid -> + if not WaitingCommit -> + erlang:send_after(1000, self(), delayed_commit); + true -> ok + end, + case reply_with_group(Group, WaitList, [], RefCounter) of + [] -> + case Shutdown of + true -> + {stop, normal, State}; + false -> + {noreply, State#group_state{waiting_commit=true, waiting_list=[], + group=Group, updater_pid=nil}} + end; + StillWaiting -> + % we still have some waiters, reopen the database and reupdate the index + Owner = self(), + Pid = spawn_link(fun() -> couch_view_updater:update(Owner, Group, DbName) end), + {noreply, State#group_state{waiting_commit=true, + waiting_list=StillWaiting, updater_pid=Pid}} + end; +handle_cast({_, new_group, _}, State) -> + %% message from an old (probably pre-compaction) updater; ignore + {noreply, State}; handle_cast(ddoc_updated, State) -> #group_state{ db_name = DbName, @@ -317,38 +348,6 @@ handle_info(delayed_commit, #group_state{db_name=DbName,group=Group}=State) -> {noreply, State#group_state{waiting_commit=true}} end; -handle_info({'EXIT', FromPid, {new_group, #group{sig=GroupSig} = Group}}, - #group_state{db_name=DbName, - group=#group{sig=GroupSig}, - updater_pid=UpPid, - ref_counter=RefCounter, - waiting_list=WaitList, - shutdown=Shutdown, - waiting_commit=WaitingCommit}=State) when UpPid == FromPid -> - if not WaitingCommit -> - erlang:send_after(1000, self(), delayed_commit); - true -> ok - end, - case reply_with_group(Group, WaitList, [], RefCounter) of - [] -> - case Shutdown of - true -> - {stop, normal, State}; - false -> - {noreply, State#group_state{waiting_commit=true, waiting_list=[], - group=Group, updater_pid=nil}} - end; - StillWaiting -> - % we still have some waiters, reopen the database and reupdate the index - Owner = self(), - Pid = spawn_link(fun() -> couch_view_updater:update(Owner, Group, DbName) end), - {noreply, State#group_state{waiting_commit=true, - waiting_list=StillWaiting, updater_pid=Pid}} - end; -handle_info({'EXIT', _, {new_group, _}}, State) -> - %% message from an old (probably pre-compaction) updater; ignore - {noreply, State}; - handle_info({'EXIT', UpPid, reset}, #group_state{init_args=InitArgs, updater_pid=UpPid} = State) -> case prepare_group(InitArgs, true) of http://git-wip-us.apache.org/repos/asf/couchdb/blob/53490d91/src/couchdb/couch_view_updater.erl ---------------------------------------------------------------------- diff --git a/src/couchdb/couch_view_updater.erl b/src/couchdb/couch_view_updater.erl index 4aee586..6a5530e 100644 --- a/src/couchdb/couch_view_updater.erl +++ b/src/couchdb/couch_view_updater.erl @@ -92,9 +92,11 @@ update(Owner, Group, #db{name = DbName} = Db) -> end, ok, []), couch_work_queue:close(MapQueue), - receive {new_group, NewGroup} -> - exit({new_group, - NewGroup#group{current_seq=couch_db:get_update_seq(Db)}}) + receive {new_group, NewGroup0} -> + NewGroup = NewGroup0#group{ + current_seq=couch_db:get_update_seq(Db) + }, + gen_server:cast(Owner, {self(), new_group, NewGroup}) end.