couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rnew...@apache.org
Subject [17/50] fabric commit: updated refs/heads/windsor-merge-121 to 79e6e2f
Date Fri, 01 Aug 2014 09:12:05 GMT
Include uuid in since values

BugzID: 21658


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

Branch: refs/heads/windsor-merge-121
Commit: d9cf9463ee4f187e5ef20e8373a8f023191f6c18
Parents: 674c211
Author: Robert Newson <robert.newson@cloudant.com>
Authored: Wed Sep 11 16:26:34 2013 +0100
Committer: Robert Newson <rnewson@apache.org>
Committed: Thu Jul 31 11:12:24 2014 +0100

----------------------------------------------------------------------
 src/fabric_rpc.erl          | 92 +++++++++++++++++++++++++++++++++++++---
 src/fabric_view_changes.erl |  6 +--
 2 files changed, 88 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fabric/blob/d9cf9463/src/fabric_rpc.erl
----------------------------------------------------------------------
diff --git a/src/fabric_rpc.erl b/src/fabric_rpc.erl
index c6ac263..20d7a5a 100644
--- a/src/fabric_rpc.erl
+++ b/src/fabric_rpc.erl
@@ -29,18 +29,19 @@
 
 changes(DbName, #changes_args{} = Args, StartSeq) ->
     changes(DbName, [Args], StartSeq);
-changes(DbName, Options, StartSeq) ->
+changes(DbName, Options, StartVector) ->
     erlang:put(io_priority, {interactive, DbName}),
     #changes_args{dir=Dir} = Args = lists:keyfind(changes_args, 1, Options),
     case get_or_create_db(DbName, []) of
     {ok, Db} ->
+        StartSeq = calculate_start_seq(Db, node(), StartVector),
         Enum = fun changes_enumerator/2,
         Opts = [{dir,Dir}],
         Acc0 = {Db, StartSeq, Args, Options},
         try
             {ok, {_, LastSeq, _, _}} =
                 couch_db:changes_since(Db, StartSeq, Enum, Opts, Acc0),
-            rexi:reply({complete, LastSeq})
+            rexi:reply({complete, {LastSeq, uuid(Db)}})
         after
             couch_db:close(Db)
         end;
@@ -278,11 +279,11 @@ changes_enumerator(DocInfo, {Db, _Seq, Args, Options}) ->
 
 changes_row(Db, #doc_info{id=Id, high_seq=Seq}=DI, Results, Del, true, Opts) ->
     Doc = doc_member(Db, DI, Opts),
-    #change{key=Seq, id=Id, value=Results, doc=Doc, deleted=Del};
-changes_row(_, #doc_info{id=Id, high_seq=Seq}, Results, true, _, _) ->
-    #change{key=Seq, id=Id, value=Results, deleted=true};
-changes_row(_, #doc_info{id=Id, high_seq=Seq}, Results, _, _, _) ->
-    #change{key=Seq, id=Id, value=Results}.
+    #change{key={Seq, uuid(Db)}, id=Id, value=Results, doc=Doc, deleted=Del};
+changes_row(Db, #doc_info{id=Id, high_seq=Seq}, Results, true, _, _) ->
+    #change{key={Seq, uuid(Db)}, id=Id, value=Results, deleted=true};
+changes_row(Db, #doc_info{id=Id, high_seq=Seq}, Results, _, _, _) ->
+    #change{key={Seq, uuid(Db)}, id=Id, value=Results}.
 
 doc_member(Shard, DocInfo, Opts) ->
     case couch_db:open_doc(Shard, DocInfo, [deleted | Opts]) of
@@ -363,3 +364,80 @@ set_io_priority(DbName, Options) ->
         _ ->
             ok
     end.
+
+calculate_start_seq(_Db, _Node, Seq) when is_integer(Seq) ->
+    Seq;
+calculate_start_seq(Db, Node, {Seq, Uuid}) ->
+    case is_prefix(Uuid, couch_db:get_uuid(Db)) of
+        true ->
+            case is_owner(Node, Seq, couch_db:get_epochs(Db)) of
+                true -> Seq;
+                false -> 0
+            end;
+        false ->
+            %% The file was rebuilt, most likely in a different
+            %% order, so rewind.
+            0
+    end.
+
+is_prefix(Pattern, Subject) ->
+     binary:longest_common_prefix([Pattern, Subject]) == size(Pattern).
+
+is_owner(Node, Seq, Epochs) ->
+    validate_epochs(Epochs),
+    Node =:= owner_of(Seq, Epochs).
+
+owner_of(_Seq, []) ->
+    undefined;
+owner_of(Seq, [{EpochNode, EpochSeq} | _Rest]) when Seq > EpochSeq ->
+    EpochNode;
+owner_of(Seq, [_ | Rest]) ->
+    owner_of(Seq, Rest).
+
+validate_epochs(Epochs) ->
+    %% Assert uniqueness.
+    case length(Epochs) == length(lists:ukeysort(2, Epochs)) of
+        true  -> ok;
+        false -> erlang:error(duplicate_epoch)
+    end,
+    %% Assert order.
+    case Epochs == lists:sort(fun({_, A}, {_, B}) -> B =< A end, Epochs) of
+        true  -> ok;
+        false -> erlang:error(epoch_order)
+    end.
+
+uuid(Db) ->
+    Uuid = couch_db:get_uuid(Db),
+    binary:part(Uuid, {0, uuid_prefix_len()}).
+
+uuid_prefix_len() ->
+    list_to_integer(config:get("fabric", "uuid_prefix_len", "7")).
+
+-ifdef(TEST).
+-include_lib("eunit/include/eunit.hrl").
+
+calculate_start_seq_test() ->
+    %% uuid mismatch is always a rewind.
+    Hdr1 = couch_db_header:new(),
+    Hdr2 = couch_db_header:set(Hdr1, [{epochs, [{node1, 1}]}, {uuid, <<"uuid1">>}]),
+    ?assertEqual(0, calculate_start_seq(#db{header=Hdr2}, node1, {1, <<"uuid2">>})),
+    %% uuid matches and seq is owned by node.
+    Hdr3 = couch_db_header:set(Hdr2, [{epochs, [{node1, 1}]}]),
+    ?assertEqual(2, calculate_start_seq(#db{header=Hdr3}, node1, {2, <<"uuid1">>})),
+    %% uuids match but seq is not owned by node.
+    Hdr4 = couch_db_header:set(Hdr2, [{epochs, [{node2, 2}, {node1, 1}]}]),
+    ?assertEqual(0, calculate_start_seq(#db{header=Hdr4}, node1, {3, <<"uuid1">>})),
+    %% return integer if we didn't get a vector.
+    ?assertEqual(4, calculate_start_seq(#db{}, foo, 4)).
+
+is_owner_test() ->
+    ?assertNot(is_owner(foo, 1, [])),
+    ?assertNot(is_owner(foo, 1, [{foo, 1}])),
+    ?assert(is_owner(foo, 2, [{foo, 1}])),
+    ?assert(is_owner(foo, 50, [{bar, 100}, {foo, 1}])),
+    ?assert(is_owner(foo, 50, [{baz, 200}, {bar, 100}, {foo, 1}])),
+    ?assert(is_owner(bar, 150, [{baz, 200}, {bar, 100}, {foo, 1}])),
+    ?assertError(duplicate_epoch, is_owner(foo, 1, [{foo, 1}, {bar, 1}])),
+    ?assertError(epoch_order, is_owner(foo, 1, [{foo, 100}, {bar, 200}])).
+
+-endif.

http://git-wip-us.apache.org/repos/asf/couchdb-fabric/blob/d9cf9463/src/fabric_view_changes.erl
----------------------------------------------------------------------
diff --git a/src/fabric_view_changes.erl b/src/fabric_view_changes.erl
index 293541e..4e0cd9e 100644
--- a/src/fabric_view_changes.erl
+++ b/src/fabric_view_changes.erl
@@ -297,8 +297,8 @@ pack_seqs(Workers) ->
     Opaque = couch_util:encodeBase64Url(term_to_binary(SeqList, [compressed])),
     [SeqSum, Opaque].
 
-seq({Seq, _Uuid, _Node}) -> Seq;
-seq(Seq)                 -> Seq.
+seq({Seq, _Uuid}) -> Seq;
+seq(Seq)          -> Seq.
 
 unpack_seqs(0, DbName) ->
     fabric_dict:init(mem3:shards(DbName), 0);
@@ -339,7 +339,7 @@ do_unpack_seqs(Opaque, DbName) ->
     Unpacked = lists:flatmap(fun({Node, [A,B], Seq}) ->
         case mem3:get_shard(DbName, Node, [A,B]) of
         {ok, Shard} ->
-            [{Shard, seq(Seq)}];
+            [{Shard, Seq}];
         {error, not_found} ->
             []
         end


Mime
View raw message