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 D8C84710F for ; Fri, 16 Dec 2011 01:00:53 +0000 (UTC) Received: (qmail 82649 invoked by uid 500); 16 Dec 2011 01:00:53 -0000 Delivered-To: apmail-couchdb-commits-archive@couchdb.apache.org Received: (qmail 82522 invoked by uid 500); 16 Dec 2011 01:00:53 -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 82506 invoked by uid 99); 16 Dec 2011 01:00:53 -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 01:00:53 +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 01:00:50 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 1909156997; Fri, 16 Dec 2011 01:00:29 +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: [1/3] git commit: Fix COUCHDB-1363 - race condition in couch_changes Message-Id: <20111216010029.1909156997@tyr.zones.apache.org> Date: Fri, 16 Dec 2011 01:00:29 +0000 (UTC) X-Virus-Checked: Checked by ClamAV on apache.org Updated Branches: refs/heads/1.0.x 9c377a1af -> e82a0c989 refs/heads/1.1.x c9b20f290 -> 6a04e3336 refs/heads/1.2.x 7f9376ce6 -> 1bbe61973 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/e82a0c98 Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/e82a0c98 Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/e82a0c98 Branch: refs/heads/1.0.x Commit: e82a0c98924b999b91eaadfd9106c153c9ed4b64 Parents: 9c377a1 Author: Randall Leeds Authored: Wed Dec 14 20:12:08 2011 -0800 Committer: Randall Leeds Committed: Thu Dec 15 16:55:28 2011 -0800 ---------------------------------------------------------------------- src/couchdb/couch_changes.erl | 18 ++++++++++++------ 1 files changed, 12 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb/blob/e82a0c98/src/couchdb/couch_changes.erl ---------------------------------------------------------------------- diff --git a/src/couchdb/couch_changes.erl b/src/couchdb/couch_changes.erl index c0bc7ad..0cc284d 100644 --- a/src/couchdb/couch_changes.erl +++ b/src/couchdb/couch_changes.erl @@ -19,23 +19,28 @@ handle_changes(#changes_args{style=Style}=Args1, Req, Db) -> Args = Args1#changes_args{filter= make_filter_fun(Args1#changes_args.filter, Style, Req, Db)}, - StartSeq = case Args#changes_args.dir of - rev -> - couch_db:get_update_seq(Db); - fwd -> - Args#changes_args.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, if Args#changes_args.feed == "continuous" orelse Args#changes_args.feed == "longpoll" -> fun(Callback) -> 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(), start_sending_changes(Callback, Args#changes_args.feed), {Timeout, TimeoutFun} = get_changes_timeout(Args, Callback), try @@ -55,6 +60,7 @@ handle_changes(#changes_args{style=Style}=Args1, Req, Db) -> end; true -> fun(Callback) -> + {Db, StartSeq} = Start(), start_sending_changes(Callback, Args#changes_args.feed), {ok, {_, LastSeq, _Prepend, _, _, _, _, _, _}} = send_changes(