You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by mi...@apache.org on 2015/06/05 18:42:57 UTC

[01/11] couch-replicator commit: updated refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork to 80708a9

Repository: couchdb-couch-replicator
Updated Branches:
  refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork 7e72e97c4 -> 80708a99e (forced update)


Verify that url really points to a database

This is a cherry-pick of:

https://github.com/cloudant/couch_replicator/commit/e73714196936c345d54158e674ab36cab20beeec


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/commit/362b3fd4
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/tree/362b3fd4
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/diff/362b3fd4

Branch: refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork
Commit: 362b3fd490d00015ea13fe24b62b925c1acb6ea5
Parents: 2e6d5c1
Author: Robert Newson <rn...@apache.org>
Authored: Wed Dec 3 11:41:48 2014 +0000
Committer: Mike Wallace <mi...@apache.org>
Committed: Fri Jun 5 17:20:07 2015 +0100

----------------------------------------------------------------------
 src/couch_replicator_api_wrap.erl | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/362b3fd4/src/couch_replicator_api_wrap.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator_api_wrap.erl b/src/couch_replicator_api_wrap.erl
index 504a3d1..96947de 100644
--- a/src/couch_replicator_api_wrap.erl
+++ b/src/couch_replicator_api_wrap.erl
@@ -83,9 +83,20 @@ db_open(#httpdb{} = Db1, _Options, Create) ->
                     ok
                 end)
         end,
-        send_req(Db, [{method, head}],
-            fun(200, _, _) ->
-                {ok, Db};
+        send_req(Db, [{method, get}],
+            fun(200, _, {Props}) ->
+                UpdateSeq = get_value(<<"update_seq">>, Props),
+                InstanceStart = get_value(<<"instance_start_time">>, Props),
+                case {UpdateSeq, InstanceStart} of
+                    {undefined, _} ->
+                        throw({db_not_found, ?l2b(db_uri(Db))});
+                    {_, undefined} ->
+                        throw({db_not_found, ?l2b(db_uri(Db))});
+                    _ ->
+                        {ok, Db}
+                end;
+            (200, _, _Body) ->
+                 throw({db_not_found, ?l2b(db_uri(Db))});
             (401, _, _) ->
                 throw({unauthorized, ?l2b(db_uri(Db))});
             (_, _, _) ->


[08/11] couch-replicator commit: updated refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork to 80708a9

Posted by mi...@apache.org.
Be more explicit on values of ?STREAM_STATUS

Also I should add a note about how the changes ending due to a throw
when processing the last_seq leads to the un-consumed stream messages.

This is a cherry-pick of:

https://github.com/cloudant/couch_replicator/commit/20d11c7d342ea77ffd5384d75e9cd570cbcbf5ba


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/commit/8a3af420
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/tree/8a3af420
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/diff/8a3af420

Branch: refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork
Commit: 8a3af420a79a1a071647450a8e9e1d2f8cf3532e
Parents: 5ee42e1
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed May 20 17:26:59 2015 -0500
Committer: Mike Wallace <mi...@apache.org>
Committed: Fri Jun 5 17:20:26 2015 +0100

----------------------------------------------------------------------
 src/couch_replicator_httpc.erl | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/8a3af420/src/couch_replicator_httpc.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator_httpc.erl b/src/couch_replicator_httpc.erl
index e61fba5..544c2ef 100644
--- a/src/couch_replicator_httpc.erl
+++ b/src/couch_replicator_httpc.erl
@@ -36,7 +36,7 @@ setup(#httpdb{httpc_pool = nil, url = Url, http_connections = MaxConns} = Db) ->
 
 
 send_req(HttpDb, Params1, Callback) ->
-    put(STREAM_STATUS, init),
+    put(?STREAM_STATUS, init),
     couch_stats:increment_counter([couch_replicator, requests]),
     Params2 = ?replace(Params1, qs,
         [{K, ?b2l(iolist_to_binary(V))} || {K, V} <- get_value(qs, Params1, [])]),
@@ -134,7 +134,7 @@ process_stream_response(ReqId, Worker, HttpDb, Params, Callback) ->
             StreamDataFun = fun() ->
                 stream_data_self(HttpDb, Params, Worker, ReqId, Callback)
             end,
-            put(STREAM_STATUS, streaming),
+            put(?STREAM_STATUS, streaming),
             ibrowse:stream_next(ReqId),
             try
                 Ret = Callback(Ok, Headers, StreamDataFun),
@@ -170,22 +170,22 @@ process_stream_response(ReqId, Worker, HttpDb, Params, Callback) ->
 % messages for the given ReqId on the floor since we're
 % no longer in the HTTP request.
 clean_mailbox({ibrowse_req_id, ReqId}) ->
-    case get(STREAM_STATUS) of
+    case get(?STREAM_STATUS) of
         streaming ->
             ibrowse:stream_next(ReqId),
             receive
                 {ibrowse_async_response, ReqId, _} ->
                     clean_mailbox({ibrowse_req_id, ReqId});
                 {ibrowse_async_response_end, ReqId} ->
-                    put(STREAM_STATUS, ended),
+                    put(?STREAM_STATUS, ended),
                     ok
             end;
-        _ ->
+        Status when Status == init; Status == ended ->
             receive
                 {ibrowse_async_response, ReqId, _} ->
                     clean_mailbox({ibrowse_req_id, ReqId});
                 {ibrowse_async_response_end, ReqId} ->
-                    put(STREAM_STATUS, ended),
+                    put(?STREAM_STATUS, ended),
                     ok
             end
     end;
@@ -236,7 +236,7 @@ stream_data_self(#httpdb{timeout = T} = HttpDb, Params, Worker, ReqId, Cb) ->
         ibrowse:stream_next(ReqId),
         {Data, fun() -> stream_data_self(HttpDb, Params, Worker, ReqId, Cb) end};
     {Data, ibrowse_async_response_end} ->
-        put(STREAM_STATUS, ended),
+        put(?STREAM_STATUS, ended),
         {Data, fun() -> throw({maybe_retry_req, more_data_expected}) end}
     end.
 


[02/11] couch-replicator commit: updated refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork to 80708a9

Posted by mi...@apache.org.
delay and splay replication starts

This is a cherry-pick of:

https://github.com/cloudant/couch_replicator/commit/d279150d959cfd46cbd77c5dd17f14d6dc3d0291


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/commit/5b630ff8
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/tree/5b630ff8
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/diff/5b630ff8

Branch: refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork
Commit: 5b630ff82b35b713941db094bef7a7beb6af66f1
Parents: 362b3fd
Author: Robert Newson <rn...@apache.org>
Authored: Wed Dec 3 12:14:10 2014 +0000
Committer: Mike Wallace <mi...@apache.org>
Committed: Fri Jun 5 17:20:15 2015 +0100

----------------------------------------------------------------------
 src/couch_replicator_manager.erl | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/5b630ff8/src/couch_replicator_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator_manager.erl b/src/couch_replicator_manager.erl
index 17c766e..eefa0cd 100644
--- a/src/couch_replicator_manager.erl
+++ b/src/couch_replicator_manager.erl
@@ -454,7 +454,14 @@ maybe_start_replication(State, DbName, DocId, RepDoc) ->
         true = ets:insert(?DOC_TO_REP, {{DbName, DocId}, RepId}),
         couch_log:notice("Attempting to start replication `~s` (document `~s`).",
             [pp_rep_id(RepId), DocId]),
-        Pid = spawn_link(?MODULE, start_replication, [Rep, 0]),
+        StartDelaySecs = erlang:max(0,
+            config:get_integer("replicator", "start_delay", 10)),
+        StartSplaySecs = erlang:max(1,
+            config:get_integer("replicator", "start_splay", 50)),
+        DelaySecs = StartDelaySecs + random:uniform(StartSplaySecs),
+        couch_log:notice("Delaying replication `~s` start by ~p seconds.",
+            [pp_rep_id(RepId), DelaySecs]),
+        Pid = spawn_link(?MODULE, start_replication, [Rep, DelaySecs]),
         State#state{rep_start_pids = [Pid | State#state.rep_start_pids]};
     #rep_state{rep = #rep{doc_id = DocId}} ->
         State;


[10/11] couch-replicator commit: updated refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork to 80708a9

Posted by mi...@apache.org.
Ensure that ibrowse streams are ended properly

I found a situation where we had live lock on a running application due
to an ibrowse request that hadn't been properly terminated. This
manifested as a cesation of updates to the _active_tasks information.
Debugging this lead me to see that the main couch_replicator pid was
stuck on a call to get_pending_changes. This call was stuck because the
ibrowse_http_client process being used was stuck waiting for a changes
request to complete.

This changes request as it turns out had been abandoned by the
couch_replicator_changes_reader. The changes reader was then stuck
trying to do a gen_server:call/2 back to the main couch_replicator
process with the report_seq_done message.

Given all this, it became apparent that the changes feed improperly
ending its ibrowse streams was the underlying culprit. Issuing a call to
ibrowse:stream_next/1 with the abandoned ibrowse stream id resulted in
the replication resuming.

This bug was introduced in this commit:
bfa020b43be20c54ab166c51f5c6e55c34d844c2

BugzId: 47306

This is a cherry-pick of:

https://github.com/cloudant/couch_replicator/commit/f9db37a9b293f5f078681e7539fd35a92eb3adec


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/commit/5ee42e16
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/tree/5ee42e16
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/diff/5ee42e16

Branch: refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork
Commit: 5ee42e16b60c39135b7540cd23ab070aa1cd062a
Parents: ce1934f
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed May 20 17:04:31 2015 -0500
Committer: Mike Wallace <mi...@apache.org>
Committed: Fri Jun 5 17:20:26 2015 +0100

----------------------------------------------------------------------
 src/couch_replicator_httpc.erl | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/5ee42e16/src/couch_replicator_httpc.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator_httpc.erl b/src/couch_replicator_httpc.erl
index 9a6213a..e61fba5 100644
--- a/src/couch_replicator_httpc.erl
+++ b/src/couch_replicator_httpc.erl
@@ -27,6 +27,7 @@
 
 -define(replace(L, K, V), lists:keystore(K, 1, L, {K, V})).
 -define(MAX_WAIT, 5 * 60 * 1000).
+-define(STREAM_STATUS, ibrowse_stream_status).
 
 
 setup(#httpdb{httpc_pool = nil, url = Url, http_connections = MaxConns} = Db) ->
@@ -35,6 +36,7 @@ setup(#httpdb{httpc_pool = nil, url = Url, http_connections = MaxConns} = Db) ->
 
 
 send_req(HttpDb, Params1, Callback) ->
+    put(STREAM_STATUS, init),
     couch_stats:increment_counter([couch_replicator, requests]),
     Params2 = ?replace(Params1, qs,
         [{K, ?b2l(iolist_to_binary(V))} || {K, V} <- get_value(qs, Params1, [])]),
@@ -132,6 +134,7 @@ process_stream_response(ReqId, Worker, HttpDb, Params, Callback) ->
             StreamDataFun = fun() ->
                 stream_data_self(HttpDb, Params, Worker, ReqId, Callback)
             end,
+            put(STREAM_STATUS, streaming),
             ibrowse:stream_next(ReqId),
             try
                 Ret = Callback(Ok, Headers, StreamDataFun),
@@ -167,13 +170,24 @@ process_stream_response(ReqId, Worker, HttpDb, Params, Callback) ->
 % messages for the given ReqId on the floor since we're
 % no longer in the HTTP request.
 clean_mailbox({ibrowse_req_id, ReqId}) ->
-    receive
-    {ibrowse_async_response, ReqId, _} ->
-        clean_mailbox({ibrowse_req_id, ReqId});
-    {ibrowse_async_response_end, ReqId} ->
-        clean_mailbox({ibrowse_req_id, ReqId})
-    after 0 ->
-        ok
+    case get(STREAM_STATUS) of
+        streaming ->
+            ibrowse:stream_next(ReqId),
+            receive
+                {ibrowse_async_response, ReqId, _} ->
+                    clean_mailbox({ibrowse_req_id, ReqId});
+                {ibrowse_async_response_end, ReqId} ->
+                    put(STREAM_STATUS, ended),
+                    ok
+            end;
+        _ ->
+            receive
+                {ibrowse_async_response, ReqId, _} ->
+                    clean_mailbox({ibrowse_req_id, ReqId});
+                {ibrowse_async_response_end, ReqId} ->
+                    put(STREAM_STATUS, ended),
+                    ok
+            end
     end;
 clean_mailbox(_) ->
     ok.
@@ -222,6 +236,7 @@ stream_data_self(#httpdb{timeout = T} = HttpDb, Params, Worker, ReqId, Cb) ->
         ibrowse:stream_next(ReqId),
         {Data, fun() -> stream_data_self(HttpDb, Params, Worker, ReqId, Cb) end};
     {Data, ibrowse_async_response_end} ->
+        put(STREAM_STATUS, ended),
         {Data, fun() -> throw({maybe_retry_req, more_data_expected}) end}
     end.
 


[03/11] couch-replicator commit: updated refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork to 80708a9

Posted by mi...@apache.org.
Return owner to improve logging output

This is a cherry-pick of:

https://github.com/cloudant/couch_replicator/commit/3287da36a24b5d061a64cc93814f2f4580fdd4f9

Conflicts:
	src/couch_replicator_manager.erl


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/commit/89363ae5
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/tree/89363ae5
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/diff/89363ae5

Branch: refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork
Commit: 89363ae52e06f8f7e5a82d2ebe106dc41622ce01
Parents: 8d69019
Author: Robert Newson <rn...@apache.org>
Authored: Fri May 15 16:30:34 2015 +0100
Committer: Mike Wallace <mi...@apache.org>
Committed: Fri Jun 5 17:20:20 2015 +0100

----------------------------------------------------------------------
 src/couch_replicator_manager.erl | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/89363ae5/src/couch_replicator_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator_manager.erl b/src/couch_replicator_manager.erl
index 5369ad5..4f32ede 100644
--- a/src/couch_replicator_manager.erl
+++ b/src/couch_replicator_manager.erl
@@ -17,6 +17,7 @@
 
 % public API
 -export([replication_started/1, replication_completed/2, replication_error/2]).
+-export([owner/1]).
 
 -export([before_doc_update/2, after_doc_read/2]).
 
@@ -120,6 +121,10 @@ replication_error(#rep{id = {BaseId, _} = RepId}, Error) ->
     end.
 
 
+owner(RepId) ->
+    gen_server:call(?MODULE, {owner, RepId}).
+
+
 handle_config_change("replicator", "db", _, _, S) ->
     ok = gen_server:call(S, rep_db_changed),
     remove_handler;
@@ -159,6 +164,13 @@ init(_) ->
         live = Live
     }}.
 
+handle_call({owner, RepId}, _From, State) ->
+    case rep_state(RepId) of
+    nil ->
+        false;
+    #rep_state{dbname = DbName, rep = #rep{doc_id = DocId}} ->
+        {reply, owner(DbName, DocId, State#state.live), State}
+    end;
 
 handle_call({rep_db_update, DbName, {ChangeProps} = Change}, _From, State) ->
     NewState = try
@@ -392,9 +404,11 @@ process_update(State, DbName, {Change}) ->
     {_, true} ->
         rep_doc_deleted(DbName, DocId),
         State;
-    {false, false} ->
+    {Owner, false} when Owner /= node() ->
+        couch_log:notice("Not starting '~s' as owner is ~s.", [DocId, Owner]),
         State;
-    {true, false} ->
+    {_Owner, false} ->
+        couch_log:notice("Maybe starting '~s' as I'm the owner", [DocId]),
         case get_json_value(<<"_replication_state">>, RepProps) of
         undefined ->
             maybe_start_replication(State, DbName, DocId, JsonRepDoc);
@@ -416,9 +430,9 @@ process_update(State, DbName, {Change}) ->
 owner(<<"shards/", _/binary>> = DbName, DocId, Live) ->
     Nodes = lists:sort([N || #shard{node=N} <- mem3:shards(mem3:dbname(DbName), DocId),
 			     lists:member(N, Live)]),
-    node() =:= hd(mem3_util:rotate_list({DbName, DocId}, Nodes));
+    hd(mem3_util:rotate_list({DbName, DocId}, Nodes));
 owner(_DbName, _DocId, _Live) ->
-    true.
+    node().
 
 rep_db_update_error(Error, DbName, DocId) ->
     case Error of


[06/11] couch-replicator commit: updated refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork to 80708a9

Posted by mi...@apache.org.
Log when node up/down events occur

This is a cherry-pick of:

https://github.com/cloudant/couch_replicator/commit/d40bb6f2e603a7c81f777cc1c4c200ad34c3db42


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/commit/fb4da8d3
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/tree/fb4da8d3
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/diff/fb4da8d3

Branch: refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork
Commit: fb4da8d3fec9874f3f96db2cf6fb631ce4aee92d
Parents: 89363ae
Author: Robert Newson <rn...@apache.org>
Authored: Fri May 15 16:30:55 2015 +0100
Committer: Mike Wallace <mi...@apache.org>
Committed: Fri Jun 5 17:20:26 2015 +0100

----------------------------------------------------------------------
 src/couch_replicator_manager.erl | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/fb4da8d3/src/couch_replicator_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator_manager.erl b/src/couch_replicator_manager.erl
index 4f32ede..6e83879 100644
--- a/src/couch_replicator_manager.erl
+++ b/src/couch_replicator_manager.erl
@@ -237,10 +237,12 @@ handle_cast(Msg, State) ->
     {stop, {error, {unexpected_cast, Msg}}, State}.
 
 handle_info({nodeup, Node}, State) ->
+    couch_log:notice("Rescanning replicator dbs as ~s came up.", [Node]),
     Live = lists:usort([Node | State#state.live]),
     {noreply, rescan(State#state{live=Live})};
 
 handle_info({nodedown, Node}, State) ->
+    couch_log:notice("Rescanning replicator dbs ~s went down.", [Node]),
     Live = State#state.live -- [Node],
     {noreply, rescan(State#state{live=Live})};
 


[05/11] couch-replicator commit: updated refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork to 80708a9

Posted by mi...@apache.org.
Fix stream cleanup timeouts

The first part of this is adding the `after 0` clause. The issue here is
that ibrowse sends the `ibrowse_async_response_end` message without
waiting for a call to `ibrowse:stream_next/1`. This means that the
continuous changes feed may or may not get this message in
`couch_replicator_httpc:accumulate_messages/3`. If it does then we would
end up on an infinite timeout waiting for it. This was a typo in the
original patch in that I meant to include it but forgot.

The second timeout is so that we don't end up halted waiting for a
changes request to finish. If it takes longer than 30s we just crash the
replication and let the manager restart things.

BugzId: 47306

This is a cherry-pick of:

https://github.com/cloudant/couch_replicator/commit/2caf39040e4e50c38a7758d4d09e7a8b22ea92d4


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/commit/86d77169
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/tree/86d77169
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/diff/86d77169

Branch: refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork
Commit: 86d7716985d92b2d1b9a6c070a87464f917c4aa9
Parents: 8a3af42
Author: Paul J. Davis <pa...@gmail.com>
Authored: Thu May 21 10:02:53 2015 -0500
Committer: Mike Wallace <mi...@apache.org>
Committed: Fri Jun 5 17:20:26 2015 +0100

----------------------------------------------------------------------
 src/couch_replicator_httpc.erl | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/86d77169/src/couch_replicator_httpc.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator_httpc.erl b/src/couch_replicator_httpc.erl
index 544c2ef..e591601 100644
--- a/src/couch_replicator_httpc.erl
+++ b/src/couch_replicator_httpc.erl
@@ -179,6 +179,8 @@ clean_mailbox({ibrowse_req_id, ReqId}) ->
                 {ibrowse_async_response_end, ReqId} ->
                     put(?STREAM_STATUS, ended),
                     ok
+                after 30000 ->
+                    exit({timeout, ibrowse_stream_cleanup})
             end;
         Status when Status == init; Status == ended ->
             receive
@@ -187,6 +189,8 @@ clean_mailbox({ibrowse_req_id, ReqId}) ->
                 {ibrowse_async_response_end, ReqId} ->
                     put(?STREAM_STATUS, ended),
                     ok
+                after 0 ->
+                    ok
             end
     end;
 clean_mailbox(_) ->


[07/11] couch-replicator commit: updated refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork to 80708a9

Posted by mi...@apache.org.
Cleanly stop replication at checkpoint time if no longer owner

This is a cherry-pick of:

https://github.com/cloudant/couch_replicator/commit/e5ef7c8a0ee2566b9cd4c02397ee94883d015fa0


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/commit/ce1934f0
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/tree/ce1934f0
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/diff/ce1934f0

Branch: refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork
Commit: ce1934f080387bfba287c1c2863b611e1d030f00
Parents: fb4da8d
Author: Robert Newson <rn...@apache.org>
Authored: Fri May 15 16:31:24 2015 +0100
Committer: Mike Wallace <mi...@apache.org>
Committed: Fri Jun 5 17:20:26 2015 +0100

----------------------------------------------------------------------
 src/couch_replicator.erl         | 21 ++++++++++++++-------
 src/couch_replicator_manager.erl | 13 ++++++++++++-
 2 files changed, 26 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/ce1934f0/src/couch_replicator.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator.erl b/src/couch_replicator.erl
index 6e86a8f..3a744cd 100644
--- a/src/couch_replicator.erl
+++ b/src/couch_replicator.erl
@@ -475,13 +475,20 @@ handle_cast({db_compacted, DbName},
     {noreply, State#rep_state{target = NewTarget}};
 
 handle_cast(checkpoint, State) ->
-    case do_checkpoint(State) of
-    {ok, NewState} ->
-        couch_stats:increment_counter([couch_replicator, checkpoints, success]),
-        {noreply, NewState#rep_state{timer = start_timer(State)}};
-    Error ->
-        couch_stats:increment_counter([couch_replicator, checkpoints, failure]),
-        {stop, Error, State}
+    #rep_state{rep_details = #rep{id = RepId} = Rep} = State,
+    case couch_replicator_manager:owner(RepId) of
+    Owner when Owner == node() ->
+        case do_checkpoint(State) of
+        {ok, NewState} ->
+            couch_stats:increment_counter([couch_replicator, checkpoints, success]),
+            {noreply, NewState#rep_state{timer = start_timer(State)}};
+        Error ->
+            couch_stats:increment_counter([couch_replicator, checkpoints, failure]),
+            {stop, Error, State}
+        end;
+    Owner ->
+        couch_replicator_manager:replication_usurped(Rep, Owner),
+        {stop, shutdown, State}
     end;
 
 handle_cast({report_seq, Seq},

http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/ce1934f0/src/couch_replicator_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator_manager.erl b/src/couch_replicator_manager.erl
index 6e83879..7bb5078 100644
--- a/src/couch_replicator_manager.erl
+++ b/src/couch_replicator_manager.erl
@@ -17,7 +17,7 @@
 
 % public API
 -export([replication_started/1, replication_completed/2, replication_error/2]).
--export([owner/1]).
+-export([owner/1, replication_usurped/2]).
 
 -export([before_doc_update/2, after_doc_read/2]).
 
@@ -108,6 +108,17 @@ replication_completed(#rep{id = RepId}, Stats) ->
     end.
 
 
+replication_usurped(#rep{id = RepId}, By) ->
+    case rep_state(RepId) of
+    nil ->
+        ok;
+    #rep_state{rep = #rep{doc_id = DocId}} ->
+        ok = gen_server:call(?MODULE, {rep_complete, RepId}, infinity),
+        couch_log:notice("Replication `~s` usurped by ~s (triggered by document `~s`)",
+            [pp_rep_id(RepId), By, DocId])
+    end.
+
+
 replication_error(#rep{id = {BaseId, _} = RepId}, Error) ->
     case rep_state(RepId) of
     nil ->


[04/11] couch-replicator commit: updated refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork to 80708a9

Posted by mi...@apache.org.
Ensure Live node set is consistent with up/down messages

BugzID: 46617

This is a cherry-pick of:

https://github.com/cloudant/couch_replicator/commit/2418c26b0fa7cffb97c2d8348654c42d6a0f1a06

Conflicts:
	src/couch_replicator_manager.erl


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/commit/8d69019b
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/tree/8d69019b
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/diff/8d69019b

Branch: refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork
Commit: 8d69019b1e4fbaaf425fec8a30542dfee41a5cf1
Parents: 5b630ff
Author: Robert Newson <rn...@apache.org>
Authored: Wed May 13 19:40:55 2015 +0100
Committer: Mike Wallace <mi...@apache.org>
Committed: Fri Jun 5 17:20:20 2015 +0100

----------------------------------------------------------------------
 src/couch_replicator_manager.erl | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/8d69019b/src/couch_replicator_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator_manager.erl b/src/couch_replicator_manager.erl
index eefa0cd..5369ad5 100644
--- a/src/couch_replicator_manager.erl
+++ b/src/couch_replicator_manager.erl
@@ -68,7 +68,8 @@
     event_listener = nil,
     scan_pid = nil,
     rep_start_pids = [],
-    max_retries
+    max_retries,
+    live = []
 }).
 
 start_link() ->
@@ -138,6 +139,7 @@ handle_config_terminate(Self, _, _) ->
 init(_) ->
     process_flag(trap_exit, true),
     net_kernel:monitor_nodes(true),
+    Live = [node() | nodes()],
     ?DOC_TO_REP = ets:new(?DOC_TO_REP, [named_table, set, public]),
     ?REP_TO_STATE = ets:new(?REP_TO_STATE, [named_table, set, public]),
     ?DB_TO_SEQ = ets:new(?DB_TO_SEQ, [named_table, set, public]),
@@ -153,7 +155,8 @@ init(_) ->
         scan_pid = ScanPid,
         max_retries = retries_value(
             config:get("replicator", "max_replication_retry_count", "10")),
-        rep_start_pids = [Pid]
+        rep_start_pids = [Pid],
+        live = Live
     }}.
 
 
@@ -221,11 +224,13 @@ handle_cast(Msg, State) ->
     couch_log:error("Replication manager received unexpected cast ~p", [Msg]),
     {stop, {error, {unexpected_cast, Msg}}, State}.
 
-handle_info({nodeup, _Node}, State) ->
-    {noreply, rescan(State)};
+handle_info({nodeup, Node}, State) ->
+    Live = lists:usort([Node | State#state.live]),
+    {noreply, rescan(State#state{live=Live})};
 
-handle_info({nodedown, _Node}, State) ->
-    {noreply, rescan(State)};
+handle_info({nodedown, Node}, State) ->
+    Live = State#state.live -- [Node],
+    {noreply, rescan(State#state{live=Live})};
 
 handle_info({'EXIT', From, normal}, #state{scan_pid = From} = State) ->
     couch_log:debug("Background scan has completed.", []),
@@ -286,6 +291,8 @@ terminate(_Reason, State) ->
     couch_event:stop_listener(Listener).
 
 
+code_change(1, State, _Extra) ->
+    {ok, erlang:append_element(State, [node() | nodes()])};
 code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
 
@@ -381,7 +388,7 @@ rescan(#state{scan_pid = ScanPid} = State) ->
 process_update(State, DbName, {Change}) ->
     {RepProps} = JsonRepDoc = get_json_value(doc, Change),
     DocId = get_json_value(<<"_id">>, RepProps),
-    case {owner(DbName, DocId), get_json_value(deleted, Change, false)} of
+    case {owner(DbName, DocId, State#state.live), get_json_value(deleted, Change, false)} of
     {_, true} ->
         rep_doc_deleted(DbName, DocId),
         State;
@@ -406,12 +413,11 @@ process_update(State, DbName, {Change}) ->
         end
     end.
 
-owner(<<"shards/", _/binary>> = DbName, DocId) ->
-    Live = [node()|nodes()],
+owner(<<"shards/", _/binary>> = DbName, DocId, Live) ->
     Nodes = lists:sort([N || #shard{node=N} <- mem3:shards(mem3:dbname(DbName), DocId),
 			     lists:member(N, Live)]),
     node() =:= hd(mem3_util:rotate_list({DbName, DocId}, Nodes));
-owner(_DbName, _DocId) ->
+owner(_DbName, _DocId, _Live) ->
     true.
 
 rep_db_update_error(Error, DbName, DocId) ->


[09/11] couch-replicator commit: updated refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork to 80708a9

Posted by mi...@apache.org.
continue jobs that aren't _replicator docs

This is a cherry-pick of:

https://github.com/cloudant/couch_replicator/commit/ff1ab1b840019601c3e3e04a1d931db6f2ccd2d1


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/commit/9d010db1
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/tree/9d010db1
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/diff/9d010db1

Branch: refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork
Commit: 9d010db16eb172a066c3fa5dc08b904516581dd7
Parents: 86d7716
Author: Robert Newson <rn...@apache.org>
Authored: Thu May 21 14:08:42 2015 +0100
Committer: Mike Wallace <mi...@apache.org>
Committed: Fri Jun 5 17:20:26 2015 +0100

----------------------------------------------------------------------
 src/couch_replicator.erl         |  8 ++++----
 src/couch_replicator_manager.erl | 12 +++++++-----
 2 files changed, 11 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/9d010db1/src/couch_replicator.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator.erl b/src/couch_replicator.erl
index 3a744cd..f8a3e65 100644
--- a/src/couch_replicator.erl
+++ b/src/couch_replicator.erl
@@ -475,9 +475,9 @@ handle_cast({db_compacted, DbName},
     {noreply, State#rep_state{target = NewTarget}};
 
 handle_cast(checkpoint, State) ->
-    #rep_state{rep_details = #rep{id = RepId} = Rep} = State,
-    case couch_replicator_manager:owner(RepId) of
-    Owner when Owner == node() ->
+    #rep_state{rep_details = #rep{} = Rep} = State,
+    case couch_replicator_manager:continue(Rep) of
+    {true, _} ->
         case do_checkpoint(State) of
         {ok, NewState} ->
             couch_stats:increment_counter([couch_replicator, checkpoints, success]),
@@ -486,7 +486,7 @@ handle_cast(checkpoint, State) ->
             couch_stats:increment_counter([couch_replicator, checkpoints, failure]),
             {stop, Error, State}
         end;
-    Owner ->
+    {false, Owner} ->
         couch_replicator_manager:replication_usurped(Rep, Owner),
         {stop, shutdown, State}
     end;

http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/9d010db1/src/couch_replicator_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator_manager.erl b/src/couch_replicator_manager.erl
index 7bb5078..b74ba41 100644
--- a/src/couch_replicator_manager.erl
+++ b/src/couch_replicator_manager.erl
@@ -17,7 +17,7 @@
 
 % public API
 -export([replication_started/1, replication_completed/2, replication_error/2]).
--export([owner/1, replication_usurped/2]).
+-export([continue/1, replication_usurped/2]).
 
 -export([before_doc_update/2, after_doc_read/2]).
 
@@ -131,9 +131,11 @@ replication_error(#rep{id = {BaseId, _} = RepId}, Error) ->
         ok = gen_server:call(?MODULE, {rep_error, RepId, Error}, infinity)
     end.
 
-
-owner(RepId) ->
-    gen_server:call(?MODULE, {owner, RepId}).
+continue(#rep{doc_id = null}) ->
+    {true, no_owner};
+continue(#rep{id = RepId}) ->
+    Owner = gen_server:call(?MODULE, {owner, RepId}),
+    {node() == Owner, Owner}.
 
 
 handle_config_change("replicator", "db", _, _, S) ->
@@ -178,7 +180,7 @@ init(_) ->
 handle_call({owner, RepId}, _From, State) ->
     case rep_state(RepId) of
     nil ->
-        false;
+        {reply, nonode, State};
     #rep_state{dbname = DbName, rep = #rep{doc_id = DocId}} ->
         {reply, owner(DbName, DocId, State#state.live), State}
     end;


[11/11] couch-replicator commit: updated refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork to 80708a9

Posted by mi...@apache.org.
Infinity timeout, just like all the others :(

This is a cherry-pick of:

https://github.com/cloudant/couch_replicator/commit/e947b392db1eb2de22aac4a4fa12da118fe114b3


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/commit/80708a99
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/tree/80708a99
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/diff/80708a99

Branch: refs/heads/2707-merge-couch_replicator-fixes-from-cloudant-fork
Commit: 80708a99e2bc82868c26de89b7a4d86c0c4167af
Parents: 9d010db
Author: Robert Newson <rn...@apache.org>
Authored: Tue May 26 16:04:24 2015 +0100
Committer: Mike Wallace <mi...@apache.org>
Committed: Fri Jun 5 17:20:26 2015 +0100

----------------------------------------------------------------------
 src/couch_replicator_manager.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/80708a99/src/couch_replicator_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_replicator_manager.erl b/src/couch_replicator_manager.erl
index b74ba41..972d8ed 100644
--- a/src/couch_replicator_manager.erl
+++ b/src/couch_replicator_manager.erl
@@ -134,7 +134,7 @@ replication_error(#rep{id = {BaseId, _} = RepId}, Error) ->
 continue(#rep{doc_id = null}) ->
     {true, no_owner};
 continue(#rep{id = RepId}) ->
-    Owner = gen_server:call(?MODULE, {owner, RepId}),
+    Owner = gen_server:call(?MODULE, {owner, RepId}, infinity),
     {node() == Owner, Owner}.