anchor.diff:          _ ->
               ok
       end.
  +
  +calculate_start_seq(_Db, Seq) when is_integer(Seq) ->
  +    Seq;
  +calculate_start_seq(Db, {Seq, Uuid, Node}) ->
  +    case couch_db:get_uuid(Db) == Uuid of
  +        true ->
  +            case 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.
  +
  +owner(Node, Seq, Epochs) ->
  +    owner(Node, Seq, Epochs, infinity).
  +
  +owner(_Node, _Seq, [], _HighSeq) ->
  +    false;
  +owner(Node, Seq, [{EpochNode, EpochSeq} | _Rest], HighSeq)
  +  when Node =:= EpochNode andalso Seq < HighSeq andalso Seq >= EpochSeq ->
  +    true;
  +owner(Node, Seq, [{_EpochNode, EpochSeq} | Rest], _HighSeq) ->
  +    owner(Node, Seq, Rest, EpochSeq).
  +
  +-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, [{uuid, uuid1}]),
  +    ?assertEqual(0, calculate_start_seq(#db{header=Hdr2}, {1, uuid2, node1})),
  +    %% 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}, {2, uuid1, node1})),
  +    %% 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}, {3, uuid1, node1})),
  +    %% return integer if we didn't get a vector.
  +    ?assertEqual(4, calculate_start_seq(#db{}, 4)).
  +
  +owner_test() ->
  +    ?assertNot(owner(foo, 1, [])),
  +    ?assert(owner(foo, 1, [{foo, 1}])),
  +    ?assert(owner(foo, 50, [{bar, 100}, {foo, 1}])),
  +    ?assert(owner(foo, 50, [{baz, 200}, {bar, 100}, {foo, 1}])),
  +    ?assert(owner(bar, 150, [{baz, 200}, {bar, 100}, {foo, 1}])).
  +
  +-endif.
  
positive.code: 
  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}.
  
  doc_member(Shard, DocInfo, Opts) ->
      case couch_db:open_doc(Shard, DocInfo, [deleted | Opts]) of
  
negative.code: 
  changes(DbName, #changes_args{} = Args, StartSeq) ->
      changes(DbName, [Args], 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, 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, couch_db:get_uuid(Db), node()}})
          after
              couch_db:close(Db)
          end;
  