You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2014/08/28 13:59:45 UTC

[22/50] chttpd commit: updated refs/heads/master to 58020ab

Try to cancel a replication everywhere

Cancelation requests sometimes omit source and target information in
favor of a replication ID.  When that happens the logic that selects the
owner for the replication picks the wrong node, and the cancelation
fails with a not_found error.  This patch causes the request to be
submitted to all nodes in the cluster.  We report success if at least
one node reports success, otherwise we report (one of) the errors that
we received.

BugzID: 21976


Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/2c4d2b3d
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/2c4d2b3d
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/2c4d2b3d

Branch: refs/heads/master
Commit: 2c4d2b3d201ef33411f6dccde61dfdfa9a028977
Parents: d86f68d
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Wed Oct 16 13:23:14 2013 -0400
Committer: Robert Newson <rn...@apache.org>
Committed: Tue Jul 29 18:22:24 2014 +0100

----------------------------------------------------------------------
 src/chttpd_misc.erl | 42 +++++++++++++++++++++++++++++++++---------
 1 file changed, 33 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/2c4d2b3d/src/chttpd_misc.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_misc.erl b/src/chttpd_misc.erl
index cb83bc0..fcd8999 100644
--- a/src/chttpd_misc.erl
+++ b/src/chttpd_misc.erl
@@ -171,15 +171,39 @@ handle_replicate_req(Req) ->
     send_method_not_allowed(Req, "POST").
 
 replicate({Props} = PostBody, Ctx) ->
-    Node = choose_node([
-        couch_util:get_value(<<"source">>, Props),
-        couch_util:get_value(<<"target">>, Props)
-    ]),
-    case rpc:call(Node, couch_replicator, replicate, [PostBody, Ctx]) of
-    {badrpc, Reason} ->
-        erlang:error(Reason);
-    Res ->
-        Res
+    case couch_util:get_value(<<"cancel">>, Props) of
+    true ->
+        cancel_replication(PostBody, Ctx);
+    false ->
+        Node = choose_node([
+            couch_util:get_value(<<"source">>, Props),
+            couch_util:get_value(<<"target">>, Props)
+        ]),
+        case rpc:call(Node, couch_replicator, replicate, [PostBody, Ctx]) of
+        {badrpc, Reason} ->
+            erlang:error(Reason);
+        Res ->
+            Res
+        end
+    end.
+
+cancel_replication(PostBody, Ctx) ->
+    {Res, Bad} = rpc:multicall(couch_replicator, replicate, [PostBody, Ctx]),
+    case [X || {ok, {cancelled, _}} = X <- Res] of
+    [Success|_] ->
+        % Report success if at least one node canceled the replication
+        Success;
+    [] ->
+        case lists:usort(Res) of
+        [UniqueReply] ->
+            % Report a universally agreed-upon reply
+            UniqueReply;
+        [] ->
+            {error, badrpc};
+        Else ->
+            % Unclear what to do here -- pick the first error?
+            hd(Else)
+        end
     end.
 
 choose_node(Key) when is_binary(Key) ->