You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2009/11/03 21:51:05 UTC

svn commit: r832550 - in /couchdb/trunk: ./ etc/couchdb/ share/www/script/test/ src/couchdb/ test/etap/

Author: damien
Date: Tue Nov  3 20:51:04 2009
New Revision: 832550

URL: http://svn.apache.org/viewvc?rev=832550&view=rev
Log:
Added batching of multiple updating requests, to improve throughput with many writers. Also removed the couch_batch_save module, now batch requests are simply saved async as immediately, batching with outhr updates if possible.

Removed:
    couchdb/trunk/src/couchdb/couch_batch_save.erl
    couchdb/trunk/src/couchdb/couch_batch_save_sup.erl
Modified:
    couchdb/trunk/README
    couchdb/trunk/etc/couchdb/default.ini.tpl.in
    couchdb/trunk/share/www/script/test/batch_save.js
    couchdb/trunk/src/couchdb/Makefile.am
    couchdb/trunk/src/couchdb/couch.app.tpl.in
    couchdb/trunk/src/couchdb/couch_db.erl
    couchdb/trunk/src/couchdb/couch_db_updater.erl
    couchdb/trunk/src/couchdb/couch_httpd_db.erl
    couchdb/trunk/test/etap/001-load.t

Modified: couchdb/trunk/README
URL: http://svn.apache.org/viewvc/couchdb/trunk/README?rev=832550&r1=832549&r2=832550&view=diff
==============================================================================
--- couchdb/trunk/README (original)
+++ couchdb/trunk/README Tue Nov  3 20:51:04 2009
@@ -452,7 +452,7 @@
     # Current time local 2009-09-26 23:47:44
     # Using etap version "0.3.4"
     1..39
-    ok 1  - Loaded: couch_batch_save
+    ok 1  - Loaded: couch_btree
     ...
 
 Cryptographic Software Notice

Modified: couchdb/trunk/etc/couchdb/default.ini.tpl.in
URL: http://svn.apache.org/viewvc/couchdb/trunk/etc/couchdb/default.ini.tpl.in?rev=832550&r1=832549&r2=832550&view=diff
==============================================================================
--- couchdb/trunk/etc/couchdb/default.ini.tpl.in (original)
+++ couchdb/trunk/etc/couchdb/default.ini.tpl.in Tue Nov  3 20:51:04 2009
@@ -48,7 +48,6 @@
 view_manager={couch_view, start_link, []}
 external_manager={couch_external_manager, start_link, []}
 db_update_notifier={couch_db_update_notifier_sup, start_link, []}
-batch_save={couch_batch_save_sup, start_link, []}
 query_servers={couch_query_servers, start_link, []}
 httpd={couch_httpd, start_link, []}
 stats_aggregator={couch_stats_aggregator, start, []}

Modified: couchdb/trunk/share/www/script/test/batch_save.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/batch_save.js?rev=832550&r1=832549&r2=832550&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/test/batch_save.js (original)
+++ couchdb/trunk/share/www/script/test/batch_save.js Tue Nov  3 20:51:04 2009
@@ -16,45 +16,30 @@
   db.createDb();
   if (debug) debugger;
 
-  // commit should work fine with no batches
-  T(db.ensureFullCommit().ok);
-
-  // PUT a doc with ?batch=ok
-  T(db.save({_id:"0",a:1,b:1},  {batch : "ok"}).ok);
-
-  // test that response is 202 Accepted
-  T(db.last_req.status == 202);
-
-  T(db.allDocs().total_rows == 0);
-
-  restartServer();
-
-  // lost the updates
-  T(db.allDocs().total_rows == 0);
-
-  T(db.save({_id:"0",a:1,b:1},  {batch : "ok"}).ok);
-  T(db.save({_id:"1",a:1,b:1},  {batch : "ok"}).ok);
-  T(db.save({_id:"2",a:1,b:1},  {batch : "ok"}).ok);
-
-  T(db.ensureFullCommit().ok);
-  T(db.allDocs().total_rows == 3);
+  var i
+  for(i=0; i < 100; i++) {
+    T(db.save({_id:i.toString(),a:i,b:i},  {batch : "ok"}).ok);
+    
+    // test that response is 202 Accepted
+    T(db.last_req.status == 202);
+  }
+  
+  for(i=0; i < 100; i++) {
+    // attempt to save the same document a bunch of times
+    T(db.save({_id:"foo",a:i,b:i},  {batch : "ok"}).ok);
+    
+    // test that response is 202 Accepted
+    T(db.last_req.status == 202);
+  }
+  
+  while(db.allDocs().total_rows != 101){};
 
   // repeat the tests for POST
-  var resp = db.request("POST", db.uri + "?batch=ok", {body: JSON.stringify({a:1})});
-  T(JSON.parse(resp.responseText).ok);
-
-  // test that response is 202 Accepted
-  T(resp.status == 202);
-
-  T(db.allDocs().total_rows == 3);
-  // restartServer();
-  // // lost the POSTed doc
-  // T(db.allDocs().total_rows == 3);
-
-  var resp = db.request("POST", db.uri + "?batch=ok", {body: JSON.stringify({a:1})});
-  T(JSON.parse(resp.responseText).ok);
-
-  T(db.ensureFullCommit().ok);
-  T(db.allDocs().total_rows == 5);
+  for(i=0; i < 100; i++) {
+    var resp = db.request("POST", db.uri + "?batch=ok", {body: JSON.stringify({a:1})});
+    T(JSON.parse(resp.responseText).ok);
+  }
+  
+  while(db.allDocs().total_rows != 201){};
 
 };

Modified: couchdb/trunk/src/couchdb/Makefile.am
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/Makefile.am?rev=832550&r1=832549&r2=832550&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/Makefile.am (original)
+++ couchdb/trunk/src/couchdb/Makefile.am Tue Nov  3 20:51:04 2009
@@ -56,8 +56,6 @@
     couch.erl \
     couch_app.erl \
     couch_btree.erl \
-    couch_batch_save.erl \
-    couch_batch_save_sup.erl \
     couch_config.erl \
     couch_config_writer.erl \
     couch_db.erl \
@@ -113,8 +111,6 @@
     couch.beam \
     couch_app.beam \
     couch_btree.beam \
-    couch_batch_save.beam \
-    couch_batch_save_sup.beam \
     couch_config.beam \
     couch_config_writer.beam \
     couch_db.beam \

Modified: couchdb/trunk/src/couchdb/couch.app.tpl.in
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch.app.tpl.in?rev=832550&r1=832549&r2=832550&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch.app.tpl.in (original)
+++ couchdb/trunk/src/couchdb/couch.app.tpl.in Tue Nov  3 20:51:04 2009
@@ -3,8 +3,6 @@
     {vsn, "@version@"},
     {modules, [@modules@]},
     {registered, [
-        couch_batch_save,
-        couch_batch_save_sup,
         couch_config,
         couch_db_update,
         couch_db_update_notifier_sup,

Modified: couchdb/trunk/src/couchdb/couch_db.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_db.erl?rev=832550&r1=832549&r2=832550&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_db.erl (original)
+++ couchdb/trunk/src/couchdb/couch_db.erl Tue Nov  3 20:51:04 2009
@@ -586,25 +586,46 @@
         [full_commit|Options]
     end.
 
+collect_results(UpdatePid, MRef, ResultsAcc) ->
+    receive
+    {result, UpdatePid, Result} ->
+        collect_results(UpdatePid, MRef, [Result | ResultsAcc]);
+    {done, UpdatePid} ->
+        {ok, ResultsAcc};
+    {retry, UpdatePid} ->
+        retry;
+    {'DOWN', MRef, _, _, Reason} ->
+        exit(Reason)
+    end.
+
 write_and_commit(#db{update_pid=UpdatePid, user_ctx=Ctx}=Db, DocBuckets,
         NonRepDocs, Options0) ->
     Options = set_commit_option(Options0),
-    case gen_server:call(UpdatePid, 
-            {update_docs, DocBuckets, NonRepDocs, Options}, infinity) of
-    {ok, Results} -> {ok, Results};
-    retry ->
-        % This can happen if the db file we wrote to was swapped out by
-        % compaction. Retry by reopening the db and writing to the current file
-        {ok, Db2} = open_ref_counted(Db#db.main_pid, Ctx),
-        DocBuckets2 = [[doc_flush_atts(Doc, Db2#db.fd) || Doc <- Bucket] || Bucket <- DocBuckets],
-        % We only retry once
-        close(Db2),
-        case gen_server:call(UpdatePid, {update_docs, DocBuckets2, NonRepDocs, Options}, infinity) of
+    MergeConflicts = lists:member(merge_conflicts, Options),
+    FullCommit = lists:member(full_commit, Options),
+    MRef = erlang:monitor(process, UpdatePid),
+    try
+        UpdatePid ! {update_docs, self(), DocBuckets, NonRepDocs, MergeConflicts, FullCommit},
+        case collect_results(UpdatePid, MRef, []) of
         {ok, Results} -> {ok, Results};
-        retry -> throw({update_error, compaction_retry})
+        retry ->
+            % This can happen if the db file we wrote to was swapped out by
+            % compaction. Retry by reopening the db and writing to the current file
+            {ok, Db2} = open_ref_counted(Db#db.main_pid, Ctx),
+            DocBuckets2 = [[doc_flush_atts(Doc, Db2#db.fd) || Doc <- Bucket] || Bucket <- DocBuckets],
+            % We only retry once
+            close(Db2),
+            UpdatePid ! {update_docs, self(), DocBuckets2, NonRepDocs, MergeConflicts, FullCommit},
+            case collect_results(UpdatePid, MRef, []) of
+            {ok, Results} -> {ok, Results};
+            retry -> throw({update_error, compaction_retry})
+            end
         end
+    after
+        erlang:demonitor(MRef, [flush])
     end.
 
+
 set_new_att_revpos(#doc{revs={RevPos,_Revs},atts=Atts}=Doc) ->
     Doc#doc{atts= lists:map(fun(#att{data={_Fd,_Sp}}=Att) ->
             % already commited to disk, do not set new rev

Modified: couchdb/trunk/src/couchdb/couch_db_updater.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_db_updater.erl?rev=832550&r1=832549&r2=832550&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_db_updater.erl (original)
+++ couchdb/trunk/src/couchdb/couch_db_updater.erl Tue Nov  3 20:51:04 2009
@@ -43,19 +43,6 @@
 
 handle_call(get_db, _From, Db) ->
     {reply, {ok, Db}, Db};
-handle_call({update_docs, GroupedDocs, NonRepDocs, Options}, _From, Db) ->
-    try update_docs_int(Db, GroupedDocs, NonRepDocs, Options) of
-    {ok, Failures, Db2} ->
-        ok = gen_server:call(Db#db.main_pid, {db_updated, Db2}),
-        if Db2#db.update_seq /= Db#db.update_seq ->
-            couch_db_update_notifier:notify({updated, Db2#db.name});
-        true -> ok
-        end,
-        {reply, {ok, Failures}, Db2}
-    catch
-        throw: retry ->
-            {reply, retry, Db}
-    end;
 handle_call(full_commit, _From, #db{waiting_delayed_commit=nil}=Db) ->
     {reply, ok, Db}; % no data waiting, return ok immediately
 handle_call(full_commit, _From,  Db) ->
@@ -192,6 +179,63 @@
         {noreply, Db2}
     end.
 
+
+merge_updates([], RestB, AccOutGroups) ->
+    lists:reverse(AccOutGroups, RestB);
+merge_updates(RestA, [], AccOutGroups) ->
+    lists:reverse(AccOutGroups, RestA);
+merge_updates([[{_, #doc{id=IdA}}|_]=GroupA | RestA],
+        [[{_, #doc{id=IdB}}|_]=GroupB | RestB], AccOutGroups) ->
+    if IdA == IdB ->
+        merge_updates(RestA, RestB, [GroupA ++ GroupB | AccOutGroups]);
+    IdA < IdB ->
+        merge_updates(RestA, [GroupB | RestB], [GroupA | AccOutGroups]);
+    true ->
+        merge_updates([GroupA | RestA], RestB, [GroupB | AccOutGroups])
+    end.
+
+collect_updates(GroupedDocsAcc, ClientsAcc, MergeConflicts, FullCommit) ->
+    receive
+        % only collect updates with the same MergeConflicts flag and without
+        % local docs. Makes it easier to avoid multiple local doc updaters.
+        {update_docs, Client, GroupedDocs, [], MergeConflicts, FullCommit2} ->
+            GroupedDocs2 = [[{Client, Doc} || Doc <- DocGroup]
+                    || DocGroup <- GroupedDocs],
+            GroupedDocsAcc2 = 
+                merge_updates(GroupedDocsAcc, GroupedDocs2, []),
+            collect_updates(GroupedDocsAcc2, [Client | ClientsAcc],
+                    MergeConflicts, (FullCommit or FullCommit2))
+    after 0 ->
+        {GroupedDocsAcc, ClientsAcc, FullCommit}
+    end.
+
+handle_info({update_docs, Client, GroupedDocs, NonRepDocs, MergeConflicts, 
+        FullCommit}, Db) ->
+    GroupedDocs2 = [[{Client, D} || D <- DocGroup] || DocGroup <- GroupedDocs],
+    if NonRepDocs == [] ->
+        {GroupedDocs3, Clients, FullCommit2} = collect_updates(GroupedDocs2, 
+                [Client], MergeConflicts, FullCommit);
+    true ->
+        GroupedDocs3 = GroupedDocs2,
+        FullCommit2 = FullCommit,
+        Clients = [Client]
+    end,
+    NonRepDocs2 = [{Client, NRDoc} || NRDoc <- NonRepDocs],
+    try update_docs_int(Db, GroupedDocs3, NonRepDocs2, MergeConflicts, 
+                FullCommit2) of
+    {ok, Db2} ->
+        ok = gen_server:call(Db#db.main_pid, {db_updated, Db2}),
+        if Db2#db.update_seq /= Db#db.update_seq ->
+            couch_db_update_notifier:notify({updated, Db2#db.name});
+        true -> ok
+        end,
+        [catch(ClientPid ! {done, self()}) || ClientPid <- Clients],
+        {noreply, Db2}
+    catch
+        throw: retry ->
+            [catch(ClientPid ! {retry, self()}) || ClientPid <- Clients],
+            {noreply, Db}
+    end;
 handle_info(delayed_commit, Db) ->
     {noreply, commit_data(Db)}.
 
@@ -399,18 +443,24 @@
         end, Unflushed),
     flush_trees(Db, RestUnflushed, [InfoUnflushed#full_doc_info{rev_tree=Flushed} | AccFlushed]).
 
-merge_rev_trees(_MergeConflicts, [], [], AccNewInfos, AccRemoveSeqs, AccConflicts, AccSeq) ->
-    {ok, lists:reverse(AccNewInfos), AccRemoveSeqs, AccConflicts, AccSeq};
+
+send_result(Client, Id, OriginalRevs, NewResult) ->
+    % used to send a result to the client
+    catch(Client ! {result, self(), {{Id, OriginalRevs}, NewResult}}).
+
+merge_rev_trees(_MergeConflicts, [], [], AccNewInfos, AccRemoveSeqs, AccSeq) ->
+    {ok, lists:reverse(AccNewInfos), AccRemoveSeqs, AccSeq};
 merge_rev_trees(MergeConflicts, [NewDocs|RestDocsList],
-        [OldDocInfo|RestOldInfo], AccNewInfos, AccRemoveSeqs, AccConflicts, AccSeq) ->
+        [OldDocInfo|RestOldInfo], AccNewInfos, AccRemoveSeqs, AccSeq) ->
     #full_doc_info{id=Id,rev_tree=OldTree,deleted=OldDeleted,update_seq=OldSeq}
             = OldDocInfo,
-    {NewRevTree, NewConflicts} = lists:foldl(
-        fun(#doc{revs={Pos,[_Rev|PrevRevs]}}=NewDoc, {AccTree, AccConflicts2}) ->
+    NewRevTree = lists:foldl(
+        fun({Client, #doc{revs={Pos,[_Rev|PrevRevs]}}=NewDoc}, AccTree) ->
             if not MergeConflicts ->
                 case couch_key_tree:merge(AccTree, [couch_db:doc_to_tree(NewDoc)]) of
                 {_NewTree, conflicts} when (not OldDeleted) ->
-                    {AccTree, [{{Id, {Pos-1,PrevRevs}}, conflict} | AccConflicts2]};
+                    send_result(Client, Id, {Pos-1,PrevRevs}, conflict),
+                    AccTree;
                 {NewTree, no_conflicts} when  AccTree == NewTree ->
                     % the tree didn't change at all
                     % meaning we are saving a rev that's already
@@ -426,26 +476,28 @@
                         NewDoc2 = NewDoc#doc{revs={OldPos + 1, [NewRevId, OldRev]}},
                         {NewTree2, _} = couch_key_tree:merge(AccTree,
                                 [couch_db:doc_to_tree(NewDoc2)]),
-                        % we changed the rev id, this tells the caller we did.
-                        {NewTree2, [{{Id, {Pos-1,PrevRevs}}, {ok, {OldPos + 1, NewRevId}}}
-                                | AccConflicts2]};
+                        % we changed the rev id, this tells the caller we did
+                        send_result(Client, Id, {Pos-1,PrevRevs}, 
+                                {ok, {OldPos + 1, NewRevId}}),
+                        NewTree2;
                     true ->
-                        {AccTree, [{{Id, {Pos-1,PrevRevs}}, conflict} | AccConflicts2]}
+                        send_result(Client, Id, {Pos-1,PrevRevs}, conflict),
+                        AccTree
                     end;
                 {NewTree, _} ->
-                    {NewTree, AccConflicts2}
+                    NewTree
                 end;
             true ->
                 {NewTree, _} = couch_key_tree:merge(AccTree,
                             [couch_db:doc_to_tree(NewDoc)]),
-                {NewTree, AccConflicts2}
+                NewTree
             end 
         end,
-        {OldTree, AccConflicts}, NewDocs),
+        OldTree, NewDocs),
     if NewRevTree == OldTree ->
         % nothing changed
         merge_rev_trees(MergeConflicts, RestDocsList, RestOldInfo, AccNewInfos,
-                AccRemoveSeqs, NewConflicts, AccSeq);
+                AccRemoveSeqs, AccSeq);
     true ->
         % we have updated the document, give it a new seq #
         NewInfo = #full_doc_info{id=Id,update_seq=AccSeq+1,rev_tree=NewRevTree},
@@ -454,7 +506,7 @@
             _ -> [OldSeq | AccRemoveSeqs]
         end,
         merge_rev_trees(MergeConflicts, RestDocsList, RestOldInfo,
-                [NewInfo|AccNewInfos], RemoveSeqs, NewConflicts, AccSeq+1)
+                [NewInfo|AccNewInfos], RemoveSeqs, AccSeq+1)
     end.
 
 
@@ -473,13 +525,13 @@
     [Info#full_doc_info{rev_tree=couch_key_tree:stem(Tree, Limit)} ||
             #full_doc_info{rev_tree=Tree}=Info <- DocInfos].
 
-update_docs_int(Db, DocsList, NonRepDocs, Options) ->
+update_docs_int(Db, DocsList, NonRepDocs, MergeConflicts, FullCommit) ->
     #db{
         fulldocinfo_by_id_btree = DocInfoByIdBTree,
         docinfo_by_seq_btree = DocInfoBySeqBTree,
         update_seq = LastSeq
         } = Db,
-    Ids = [Id || [#doc{id=Id}|_] <- DocsList],
+    Ids = [Id || [{_Client, #doc{id=Id}}|_] <- DocsList],
     % lookup up the old documents, if they exist.
     OldDocLookups = couch_btree:lookup(DocInfoByIdBTree, Ids),
     OldDocInfos = lists:zipwith(
@@ -489,17 +541,15 @@
             #full_doc_info{id=Id}
         end,
         Ids, OldDocLookups),
-
     % Merge the new docs into the revision trees.
-    {ok, NewDocInfos0, RemoveSeqs, Conflicts, NewSeq} = merge_rev_trees(
-            lists:member(merge_conflicts, Options),
-            DocsList, OldDocInfos, [], [], [], LastSeq),
+    {ok, NewDocInfos0, RemoveSeqs, NewSeq} = merge_rev_trees(
+            MergeConflicts, DocsList, OldDocInfos, [], [], LastSeq),
 
     NewFullDocInfos = stem_full_doc_infos(Db, NewDocInfos0),
 
     % All documents are now ready to write.
 
-    {ok, LocalConflicts, Db2}  = update_local_docs(Db, NonRepDocs),
+    {ok, Db2}  = update_local_docs(Db, NonRepDocs),
 
     % Write out the document summaries (the bodies are stored in the nodes of
     % the trees, the attachments are already written to disk)
@@ -526,15 +576,14 @@
         Db4 = refresh_validate_doc_funs(Db3)
     end,
 
-    {ok, LocalConflicts ++ Conflicts,
-            commit_data(Db4, not lists:member(full_commit, Options))}.
+    {ok, commit_data(Db4, not FullCommit)}.
 
 
 update_local_docs(#db{local_docs_btree=Btree}=Db, Docs) ->
-    Ids = [Id || #doc{id=Id} <- Docs],
+    Ids = [Id || {_Client, #doc{id=Id}} <- Docs],
     OldDocLookups = couch_btree:lookup(Btree, Ids),
     BtreeEntries = lists:zipwith(
-        fun(#doc{id=Id,deleted=Delete,revs={0,PrevRevs},body=Body}, OldDocLookup) ->
+        fun({Client, #doc{id=Id,deleted=Delete,revs={0,PrevRevs},body=Body}}, OldDocLookup) ->
             case PrevRevs of
             [RevStr|_] ->
                 PrevRev = list_to_integer(?b2l(RevStr));
@@ -549,28 +598,28 @@
             case OldRev == PrevRev of
             true ->
                 case Delete of
-                    false -> {update, {Id, {PrevRev + 1, PrevRevs, Body}}};
-                    true  -> {remove, Id, PrevRevs}
+                    false ->
+                        send_result(Client, Id, {0, PrevRevs}, {ok,
+                                {0, ?l2b(integer_to_list(PrevRev + 1))}}),
+                        {update, {Id, {PrevRev + 1, Body}}};
+                    true  ->
+                        send_result(Client, Id, {0, PrevRevs},
+                                {ok, {0, <<"0">>}}),
+                        {remove, Id}
                 end;
             false ->
-                {conflict, {Id, {0, PrevRevs}}}
+                send_result(Client, Id, {0, PrevRevs}, conflict),
+                ignore
             end
         end, Docs, OldDocLookups),
 
-    BtreeIdsRemove = [Id || {remove, Id, _PrevRevs} <- BtreeEntries],
-    BtreeIdsUpdate = [{Id, {NewRev, Body}} || {update, {Id, {NewRev, _OldRevs, Body}}} <- BtreeEntries],
-    Results = 
-            [{{Id, {0, PrevRevs}}, {ok, {0, <<"0">>}}}
-                || {remove, Id, PrevRevs} <- BtreeEntries] ++
-            [{{Id, {0, PrevRevs}}, {ok, {0, ?l2b(integer_to_list(NewRev))}}}
-                || {update, {Id, {NewRev, PrevRevs, _Body}}} <- BtreeEntries] ++
-            [{IdRevs, conflict}
-                || {conflict, IdRevs} <- BtreeEntries],
+    BtreeIdsRemove = [Id || {remove, Id} <- BtreeEntries],
+    BtreeIdsUpdate = [{Key, Val} || {update, {Key, Val}} <- BtreeEntries],
 
     {ok, Btree2} =
         couch_btree:add_remove(Btree, BtreeIdsUpdate, BtreeIdsRemove),
 
-    {ok, Results, Db#db{local_docs_btree = Btree2}}.
+    {ok, Db#db{local_docs_btree = Btree2}}.
 
 
 commit_data(Db) ->

Modified: couchdb/trunk/src/couchdb/couch_httpd_db.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_db.erl?rev=832550&r1=832549&r2=832550&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_httpd_db.erl (original)
+++ couchdb/trunk/src/couchdb/couch_httpd_db.erl Tue Nov  3 20:51:04 2009
@@ -349,9 +349,15 @@
     DocId = Doc2#doc.id,
     case couch_httpd:qs_value(Req, "batch") of
     "ok" ->
-        % batch
-        ok = couch_batch_save:eventually_save_doc(
-            Db#db.name, Doc2, Db#db.user_ctx),
+        % async_batching
+        spawn(fun() ->
+                case catch(couch_db:update_doc(Db, Doc2, [])) of
+                {ok, _} -> ok;
+                Error ->
+                    ?LOG_INFO("Batch doc error (~s): ~p",[DocId, Error])
+                end
+            end),
+            
         send_json(Req, 202, [], {[
             {ok, true},
             {id, DocId}
@@ -378,7 +384,6 @@
     {ok, StartTime} =
     case couch_httpd:qs_value(Req, "seq") of
     undefined ->
-        committed = couch_batch_save:commit_now(Db#db.name, Db#db.user_ctx),
         couch_db:ensure_full_commit(Db);
     RequiredStr ->
         RequiredSeq = list_to_integer(RequiredStr),
@@ -749,7 +754,14 @@
     "ok" ->
         % batch
         Doc = couch_doc_from_req(Req, DocId, Json),
-        ok = couch_batch_save:eventually_save_doc(Db#db.name, Doc, Db#db.user_ctx),
+        
+        spawn(fun() ->
+                case catch(couch_db:update_doc(Db, Doc, [])) of
+                {ok, _} -> ok;
+                Error ->
+                    ?LOG_INFO("Batch doc error (~s): ~p",[DocId, Error])
+                end
+            end),
         send_json(Req, 202, [], {[
             {ok, true},
             {id, DocId}

Modified: couchdb/trunk/test/etap/001-load.t
URL: http://svn.apache.org/viewvc/couchdb/trunk/test/etap/001-load.t?rev=832550&r1=832549&r2=832550&view=diff
==============================================================================
--- couchdb/trunk/test/etap/001-load.t (original)
+++ couchdb/trunk/test/etap/001-load.t Tue Nov  3 20:51:04 2009
@@ -21,8 +21,6 @@
     code:add_pathz("src/couchdb"),
     etap:plan(39),
     Modules = [
-        couch_batch_save,
-        couch_batch_save_sup,
         couch_btree,
         couch_config,
         couch_config_writer,