anchor.diff:          ?JSON_DECODE(ResponseBody)
       end.
   
  -enum_docs0(_InFun, [], Acc) ->
  -    Acc;
  -enum_docs0(InFun, [DocInfo | Rest], Acc) ->
  -    case InFun(DocInfo, 0, Acc) of
  -    {ok, Acc2} -> enum_docs0(InFun, Rest, Acc2);
  -    {stop, Acc2} -> Acc2
  -    end.
  +save_docs_buffer(DbTarget, DocsBuffer, []) ->
  +    receive
  +    {Src, shutdown} ->
  +        ok = update_docs(DbTarget, lists:reverse(DocsBuffer), [], false),
  +        Src ! {done, self(), [{<<"docs_written">>, length(DocsBuffer)}]}
  +    end;
  +save_docs_buffer(DbTarget, DocsBuffer, UpdateSequences) ->
  +    [NextSeq|Rest] = UpdateSequences,
  +    receive
  +    {Src, skip, NextSeq} ->
  +        Src ! got_it,
  +        save_docs_buffer(DbTarget, DocsBuffer, Rest);
  +    {Src, docs, {NextSeq, Docs}} ->
  +        Src ! got_it,
  +        case couch_util:should_flush() of
  +            true ->
  +                ok = update_docs(DbTarget, lists:reverse(Docs++DocsBuffer), [], 
  +                    false),
  +                save_docs_buffer(DbTarget, [], Rest);
  +            false ->
  +                save_docs_buffer(DbTarget, Docs++DocsBuffer, Rest)
  +        end;
  +        {Src, shutdown} ->
  +        ?LOG_ERROR("received shutdown while waiting for more update_seqs", []),
  +        ok = update_docs(DbTarget, lists:reverse(DocsBuffer), [], false),
  +        Src ! {done, self(), [{<<"docs_written">>, length(DocsBuffer)}]}
  +    end.
  +
  +pmap(F,List) ->
  +    [wait_result(Worker) || Worker <- [spawn_worker(self(),F,E) || E <- List]].
  +
  +spawn_worker(Parent, F, E) ->
  +    erlang:spawn_monitor(fun() -> Parent ! {self(), F(E)} end).
  +
  +wait_result({Pid,Ref}) ->
  +    receive
  +    {'DOWN', Ref, _, _, normal} -> receive {Pid,Result} -> Result end;
  +    {'DOWN', Ref, _, _, Reason} -> exit(Reason)
  +end.
  +
  +enum_docs_parallel(DbS, DbT, DocInfoList) ->
  +    UpdateSeqs = [D#doc_info.update_seq || D <- DocInfoList],
  +    SaveDocsPid = spawn_link(fun() -> save_docs_buffer(DbT,[],UpdateSeqs) end),
  +    
  +    Stats = pmap(fun(SrcDocInfo) ->
  +        #doc_info{id=Id,
  +            rev=Rev,
  +            conflict_revs=Conflicts,
  +            deleted_conflict_revs=DelConflicts,
  +            update_seq=Seq} = SrcDocInfo,
  +        SrcRevs = [Rev | Conflicts] ++ DelConflicts,
  +        
  +        case get_missing_revs(DbT, [{Id, SrcRevs}]) of
  +        {ok, [{Id, MissingRevs}]} ->
  +            {ok, DocResults} = open_doc_revs(DbS, Id, MissingRevs, [latest]),
  +            
  +            % only save successful reads
  +            Docs = [RevDoc || {ok, RevDoc} <- DocResults],
  +            
  +            % include update_seq so we save docs in order
  +            SaveDocsPid ! {self(), docs, {Seq, Docs}},
  +            receive got_it -> ok end,
  +            [{missing_checked, length(SrcRevs)},
  +             {missing_found, length(MissingRevs)},
  +             {docs_read, length(Docs)}];
  +        {ok, []} ->
  +            SaveDocsPid ! {self(), skip, Seq},
  +            receive got_it -> ok end,
  +            [{missing_checked, length(SrcRevs)}]
  +        end    
  +    end, DocInfoList),
  +    
  +    SaveDocsPid ! {self(), shutdown},
  +    
  +    {MissingChecked, MissingFound, DocsRead} = lists:foldl(fun(S, {C, F, R}) ->
  +        C1 = C + proplists:get_value(missing_checked, S, 0),
  +        F1 = F + proplists:get_value(missing_found, S, 0),
  +        R1 = R + proplists:get_value(docs_read, S, 0),
  +        {C1, F1, R1}
  +    end, {0, 0, 0}, Stats),
  +    
  +    receive
  +        {done, SaveDocsPid, [{<<"docs_written">>, DocsWritten}]} -> ok
  +    end,
  +    
  +    [ {<<"missing_checked">>, MissingChecked},
  +      {<<"missing_found">>, MissingFound}, 
  +      {<<"docs_read">>, DocsRead},
  +      {<<"docs_written">>, DocsWritten} ].
   
   fix_url(UrlBin) ->
       Url = binary_to_list(UrlBin),
  
positive.code:                 proplists:get_value(<<"conflicts">>, RowValueProps, []),
              deleted_conflict_revs =
                  proplists:get_value(<<"deleted_conflicts">>, RowValueProps, []),
              deleted = proplists:get_value(<<"deleted">>, RowValueProps, false)}
          end, proplists:get_value(<<"rows">>, Results)),
      case DocInfoList of
      [] ->
          {ok, InAcc};
      _ ->
          Acc2 = enum_docs0(InFun, DocInfoList, InAcc),
          #doc_info{update_seq=LastSeq} = lists:last(DocInfoList),
          enum_docs_since(Db, LastSeq, InFun, Acc2)
      end;
  enum_docs_since(DbSource, StartSeq, Fun, Acc) ->
      couch_db:enum_docs_since(DbSource, StartSeq, Fun, Acc).
  
  get_missing_revs(#http_db{uri=DbUrl, headers=Headers}, DocIdRevsList) ->
      {ResponseMembers} = do_http_request(DbUrl ++ "_missing_revs", post, Headers,
  
negative.code: close_db(Db)->
      couch_db:close(Db).
  
  get_doc_info_list(#http_db{uri=DbUrl, headers=Headers}, StartSeq) ->
      Url = DbUrl ++ "_all_docs_by_seq?count=100&startkey=" 
          ++ integer_to_list(StartSeq),
      {Results} = do_http_request(Url, get, Headers),
      lists:map(fun({RowInfoList}) ->
          {RowValueProps} = proplists:get_value(<<"value">>, RowInfoList),
          #doc_info{
  