From commits-return-7635-apmail-couchdb-commits-archive=couchdb.apache.org@couchdb.apache.org Fri Dec 16 00:47:40 2011 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 316C37EC9 for ; Fri, 16 Dec 2011 00:47:40 +0000 (UTC) Received: (qmail 74407 invoked by uid 500); 16 Dec 2011 00:47:40 -0000 Delivered-To: apmail-couchdb-commits-archive@couchdb.apache.org Received: (qmail 74354 invoked by uid 500); 16 Dec 2011 00:47:39 -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 74347 invoked by uid 99); 16 Dec 2011 00:47:39 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 16 Dec 2011 00:47:39 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.114] (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 16 Dec 2011 00:47:36 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id C5C7C5697F; Fri, 16 Dec 2011 00:47:13 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: randall@apache.org To: commits@couchdb.apache.org X-Mailer: ASF-Git Admin Mailer Subject: git commit: Fix COUCHDB-1363 - race condition in couch_changes Message-Id: <20111216004713.C5C7C5697F@tyr.zones.apache.org> Date: Fri, 16 Dec 2011 00:47:13 +0000 (UTC) X-Virus-Checked: Checked by ClamAV on apache.org Updated Branches: refs/heads/master 2d90a1249 -> 573a7bb90 Fix COUCHDB-1363 - race condition in couch_changes It's necessary to re-open the #db after subscribing to notifications so that updates are not lost. In practice, this is rarely problematic because the next change will cause everything to catch up, but if a quick burst of changes happens while replication is starting the replication can go stale. Detected by intermittent replicator_db js test failures. Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/573a7bb9 Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/573a7bb9 Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/573a7bb9 Branch: refs/heads/master Commit: 573a7bb90bb86fac6143abbd0f46e1487136f7b7 Parents: 2d90a12 Author: Randall Leeds Authored: Wed Dec 14 20:12:08 2011 -0800 Committer: Randall Leeds Committed: Thu Dec 15 16:45:33 2011 -0800 ---------------------------------------------------------------------- src/couchdb/couch_changes.erl | 22 ++++++++++++++-------- 1 files changed, 14 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb/blob/573a7bb9/src/couchdb/couch_changes.erl ---------------------------------------------------------------------- diff --git a/src/couchdb/couch_changes.erl b/src/couchdb/couch_changes.erl index 72ee346..aec7873 100644 --- a/src/couchdb/couch_changes.erl +++ b/src/couchdb/couch_changes.erl @@ -35,7 +35,7 @@ }). %% @type Req -> #httpd{} | {json_req, JsonObj()} -handle_changes(Args1, Req, Db) -> +handle_changes(Args1, Req, Db0) -> #changes_args{ style = Style, filter = FilterName, @@ -43,13 +43,17 @@ handle_changes(Args1, Req, Db) -> dir = Dir, since = Since } = Args1, - {FilterFun, FilterArgs} = make_filter_fun(FilterName, Style, Req, Db), + {FilterFun, FilterArgs} = make_filter_fun(FilterName, Style, Req, Db0), Args = Args1#changes_args{filter_fun = FilterFun, filter_args = FilterArgs}, - StartSeq = case Dir of - rev -> - couch_db:get_update_seq(Db); - fwd -> - Since + Start = fun() -> + {ok, Db} = couch_db:reopen(Db0), + StartSeq = case Dir of + rev -> + couch_db:get_update_seq(Db); + fwd -> + Since + end, + {Db, StartSeq} end, % begin timer to deal with heartbeat when filter function fails case Args#changes_args.heartbeat of @@ -64,12 +68,13 @@ handle_changes(Args1, Req, Db) -> {Callback, UserAcc} = get_callback_acc(CallbackAcc), Self = self(), {ok, Notify} = couch_db_update_notifier:start_link( - fun({_, DbName}) when DbName == Db#db.name -> + fun({_, DbName}) when Db0#db.name == DbName -> Self ! db_updated; (_) -> ok end ), + {Db, StartSeq} = Start(), UserAcc2 = start_sending_changes(Callback, UserAcc, Feed), {Timeout, TimeoutFun} = get_changes_timeout(Args, Callback), Acc0 = build_acc(Args, Callback, UserAcc2, Db, StartSeq, @@ -89,6 +94,7 @@ handle_changes(Args1, Req, Db) -> {Callback, UserAcc} = get_callback_acc(CallbackAcc), UserAcc2 = start_sending_changes(Callback, UserAcc, Feed), {Timeout, TimeoutFun} = get_changes_timeout(Args, Callback), + {Db, StartSeq} = Start(), Acc0 = build_acc(Args#changes_args{feed="normal"}, Callback, UserAcc2, Db, StartSeq, <<>>, Timeout, TimeoutFun), {ok, #changes_acc{seq = LastSeq, user_acc = UserAcc3}} =