You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ra...@apache.org on 2011/12/16 01:47:13 UTC
git commit: Fix COUCHDB-1363 - race condition in couch_changes
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 <ra...@apache.org>
Authored: Wed Dec 14 20:12:08 2011 -0800
Committer: Randall Leeds <ra...@apache.org>
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}} =