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 14:23:04 UTC

[44/50] mem3 commit: updated refs/heads/master to 64c0c74

Fast forward internal repl. between file copies

In the case where two files have the same UUID we can analyze epoch
information to determine the safe start sequence.

BugzID: 27753


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

Branch: refs/heads/master
Commit: 866520183220a90f29c74319c7bc548fc9f39d48
Parents: fd3c7b5
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Tue Feb 4 15:44:14 2014 -0500
Committer: Robert Newson <rn...@apache.org>
Committed: Wed Jul 23 18:51:40 2014 +0100

----------------------------------------------------------------------
 src/mem3_rep.erl | 11 ++++++++++-
 src/mem3_rpc.erl | 45 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mem3/blob/86652018/src/mem3_rep.erl
----------------------------------------------------------------------
diff --git a/src/mem3_rep.erl b/src/mem3_rep.erl
index 2186fa3..339bd66 100644
--- a/src/mem3_rep.erl
+++ b/src/mem3_rep.erl
@@ -216,9 +216,18 @@ calculate_start_seq(Acc) ->
             end,
             Acc1#acc{seq = Seq, history = History};
         {not_found, _} ->
-            Acc1
+            compare_epochs(Acc1)
     end.
 
+compare_epochs(Acc) ->
+    #acc{
+        source = Db,
+        target = #shard{node=Node, name=Name}
+    } = Acc,
+    UUID = couch_db:get_uuid(Db),
+    Epochs = couch_db:get_epochs(Db),
+    Seq = mem3_rpc:find_common_seq(Node, Name, UUID, Epochs),
+    Acc#acc{seq = Seq, history = {[]}}.
 
 changes_enumerator(#doc_info{id=DocId}, Reds, #acc{db=Db}=Acc) ->
     {ok, FDI} = couch_db:get_full_doc_info(Db, DocId),

http://git-wip-us.apache.org/repos/asf/couchdb-mem3/blob/86652018/src/mem3_rpc.erl
----------------------------------------------------------------------
diff --git a/src/mem3_rpc.erl b/src/mem3_rpc.erl
index 10294a7..9507f5b 100644
--- a/src/mem3_rpc.erl
+++ b/src/mem3_rpc.erl
@@ -16,6 +16,7 @@
 
 
 -export([
+    find_common_seq/4,
     get_missing_revs/4,
     update_docs/4,
     load_checkpoint/4,
@@ -24,6 +25,7 @@
 
 % Private RPC callbacks
 -export([
+    find_common_seq_rpc/3,
     load_checkpoint_rpc/3,
     save_checkpoint_rpc/5
 ]).
@@ -54,6 +56,11 @@ save_checkpoint(Node, DbName, DocId, Seq, Entry, History) ->
     rexi_call(Node, {mem3_rpc, save_checkpoint_rpc, Args}).
 
 
+find_common_seq(Node, DbName, SourceUUID, SourceEpochs) ->
+    Args = [DbName, SourceUUID, SourceEpochs],
+    rexi_call(Node, {mem3_rpc, find_common_seq_rpc, Args}).
+
+
 load_checkpoint_rpc(DbName, SourceNode, SourceUUID) ->
     erlang:put(io_priority, {internal_repl, DbName}),
     case couch_db:open_int(DbName, [{user_ctx, ?CTX}]) of
@@ -107,6 +114,44 @@ save_checkpoint_rpc(DbName, Id, SourceSeq, NewEntry0, History0) ->
             rexi:reply(Error)
     end.
 
+find_common_seq_rpc(DbName, SourceUUID, SourceEpochs) ->
+    erlang:put(io_priority, {internal_repl, DbName}),
+    case couch_db:open_int(DbName, [{user_ctx, ?CTX}]) of
+    {ok, Db} ->
+        case couch_db:get_uuid(Db) of
+        SourceUUID ->
+            TargetEpochs = couch_db:get_epochs(Db),
+            Seq = compare_epochs(SourceEpochs, TargetEpochs),
+            rexi:reply({ok, Seq});
+        _Else ->
+            rexi:reply({ok, 0})
+        end;
+    Error ->
+        rexi:reply(Error)
+    end.
+
+
+%% @doc Return the sequence where two files with the same UUID diverged.
+compare_epochs(SourceEpochs, TargetEpochs) ->
+    compare_rev_epochs(
+        lists:reverse(SourceEpochs),
+        lists:reverse(TargetEpochs)
+    ).
+
+
+compare_rev_epochs([{Node, Seq} | SourceRest], [{Node, Seq} | TargetRest]) ->
+    % Common history, fast-forward
+    compare_epochs(SourceRest, TargetRest);
+compare_rev_epochs([], [{_, TargetSeq} | _]) ->
+    % Source has not moved, start from seq just before the target took over
+    TargetSeq - 1;
+compare_rev_epochs([{_, SourceSeq} | _], []) ->
+    % Target has not moved, start from seq where source diverged
+    SourceSeq;
+compare_rev_epochs([{_, SourceSeq} | _], [{_, TargetSeq} | _]) ->
+    % The source was moved to a new location independently, take the minimum
+    erlang:min(SourceSeq, TargetSeq) - 1.
+
 
 %% @doc This adds a new update sequence checkpoint to the replication
 %%      history. Checkpoints are keyed by the source node so that we