Return-Path: X-Original-To: apmail-couchdb-commits-archive@www.apache.org Delivered-To: apmail-couchdb-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E6BAD115B7 for ; Tue, 5 Aug 2014 21:17:46 +0000 (UTC) Received: (qmail 25071 invoked by uid 500); 5 Aug 2014 21:17:46 -0000 Delivered-To: apmail-couchdb-commits-archive@couchdb.apache.org Received: (qmail 24777 invoked by uid 500); 5 Aug 2014 21:17:46 -0000 Mailing-List: contact commits-help@couchdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@couchdb.apache.org Delivered-To: mailing list commits@couchdb.apache.org Received: (qmail 23519 invoked by uid 99); 5 Aug 2014 21:17:46 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 05 Aug 2014 21:17:46 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 085D99C069D; Tue, 5 Aug 2014 21:17:46 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: rnewson@apache.org To: commits@couchdb.apache.org Date: Tue, 05 Aug 2014 21:18:18 -0000 Message-Id: In-Reply-To: <40437750d2d14db4be991a9bb0e43dc9@git.apache.org> References: <40437750d2d14db4be991a9bb0e43dc9@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [35/36] couch commit: updated refs/heads/windsor-merge-211 to b7adb86 Revert "Add references to docs to prevent dups from being collapsed" Bulk docs requests may have duplicates or multiple docs with the same id. These were being collapsed in a dictionary as messages are passed from merge_rev_trees in couch_db_updater to collect_results in couch_db. Attaching a reference allows each to be processed correctly. Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/7f661535 Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/7f661535 Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/7f661535 Branch: refs/heads/windsor-merge-211 Commit: 7f661535824d9826c6977ace7a9935d0182b9fe6 Parents: f2368da Author: Robert Newson Authored: Tue Aug 5 20:50:18 2014 +0100 Committer: Robert Newson Committed: Tue Aug 5 20:50:34 2014 +0100 ---------------------------------------------------------------------- .rebar/erlcinfo | Bin 0 -> 996 bytes src/couch_db.erl | 126 +++++++++++++++++++----------------------- src/couch_db_updater.erl | 31 ++++++----- 3 files changed, 73 insertions(+), 84 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/7f661535/.rebar/erlcinfo ---------------------------------------------------------------------- diff --git a/.rebar/erlcinfo b/.rebar/erlcinfo new file mode 100644 index 0000000..41c3914 Binary files /dev/null and b/.rebar/erlcinfo differ http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/7f661535/src/couch_db.erl ---------------------------------------------------------------------- diff --git a/src/couch_db.erl b/src/couch_db.erl index 1487681..0b9e490 100644 --- a/src/couch_db.erl +++ b/src/couch_db.erl @@ -500,22 +500,22 @@ update_docs(Db, Docs) -> % group_alike_docs groups the sorted documents into sublist buckets, by id. % ([DocA, DocA, DocB, DocC], []) -> [[DocA, DocA], [DocB], [DocC]] group_alike_docs(Docs) -> - Sorted = lists:sort(fun({#doc{id=A},_},{#doc{id=B},_})-> A < B end, Docs), + Sorted = lists:sort(fun(#doc{id=A},#doc{id=B})-> A < B end, Docs), group_alike_docs(Sorted, []). group_alike_docs([], Buckets) -> - lists:reverse(lists:map(fun lists:reverse/1, Buckets)); + lists:reverse(Buckets); group_alike_docs([Doc|Rest], []) -> group_alike_docs(Rest, [[Doc]]); -group_alike_docs([{Doc,Ref}|Rest], [Bucket|RestBuckets]) -> - [{#doc{id=BucketId},_Ref}|_] = Bucket, +group_alike_docs([Doc|Rest], [Bucket|RestBuckets]) -> + [#doc{id=BucketId}|_] = Bucket, case Doc#doc.id == BucketId of true -> % add to existing bucket - group_alike_docs(Rest, [[{Doc,Ref}|Bucket]|RestBuckets]); + group_alike_docs(Rest, [[Doc|Bucket]|RestBuckets]); false -> % add to new bucket - group_alike_docs(Rest, [[{Doc,Ref}]|[Bucket|RestBuckets]]) + group_alike_docs(Rest, [[Doc]|[Bucket|RestBuckets]]) end. validate_doc_update(#db{}=Db, #doc{id= <<"_design/",_/binary>>}=Doc, _GetDiskDocFun) -> @@ -630,8 +630,10 @@ prep_and_validate_updates(_Db, [], [], _AllowConflict, AccPrepped, {AccPrepped, AccFatalErrors}; prep_and_validate_updates(Db, [DocBucket|RestBuckets], [not_found|RestLookups], AllowConflict, AccPrepped, AccErrors) -> + [#doc{id=Id}|_]=DocBucket, + % no existing revs are known, {PreppedBucket, AccErrors3} = lists:foldl( - fun({#doc{revs=Revs}=Doc,Ref}, {AccBucket, AccErrors2}) -> + fun(#doc{revs=Revs}=Doc, {AccBucket, AccErrors2}) -> case couch_doc:has_stubs(Doc) of true -> couch_doc:merge_stubs(Doc, #doc{}); % will throw exception @@ -641,19 +643,19 @@ prep_and_validate_updates(Db, [DocBucket|RestBuckets], [not_found|RestLookups], {0, []} -> case validate_doc_update(Db, Doc, fun() -> nil end) of ok -> - {[{Doc, Ref} | AccBucket], AccErrors2}; + {[Doc | AccBucket], AccErrors2}; Error -> - {AccBucket, [{Ref, Error} | AccErrors2]} + {AccBucket, [{{Id, {0, []}}, Error} | AccErrors2]} end; _ -> % old revs specified but none exist, a conflict - {AccBucket, [{Ref, conflict} | AccErrors2]} + {AccBucket, [{{Id, Revs}, conflict} | AccErrors2]} end end, {[], AccErrors}, DocBucket), prep_and_validate_updates(Db, RestBuckets, RestLookups, AllowConflict, - [lists:reverse(PreppedBucket) | AccPrepped], AccErrors3); + [PreppedBucket | AccPrepped], AccErrors3); prep_and_validate_updates(Db, [DocBucket|RestBuckets], [{ok, #full_doc_info{rev_tree=OldRevTree}=OldFullDocInfo}|RestLookups], AllowConflict, AccPrepped, AccErrors) -> @@ -663,14 +665,14 @@ prep_and_validate_updates(Db, [DocBucket|RestBuckets], {Leaf, {Start, [RevId | _]} = Revs} <- Leafs ]), {PreppedBucket, AccErrors3} = lists:foldl( - fun({Doc, Ref}, {Docs2Acc, AccErrors2}) -> + fun(Doc, {Docs2Acc, AccErrors2}) -> case prep_and_validate_update(Db, Doc, OldFullDocInfo, LeafRevsDict, AllowConflict) of {ok, Doc2} -> - {[{Doc2, Ref} | Docs2Acc], AccErrors2}; - {Error, #doc{}} -> + {[Doc2 | Docs2Acc], AccErrors2}; + {Error, #doc{id=Id,revs=Revs}} -> % Record the error - {Docs2Acc, [{Ref, Error} |AccErrors2]} + {Docs2Acc, [{{Id, Revs}, Error} |AccErrors2]} end end, {[], AccErrors}, DocBucket), @@ -690,7 +692,7 @@ prep_and_validate_replicated_updates(Db, [Bucket|RestBuckets], [OldInfo|RestOldI case OldInfo of not_found -> {ValidatedBucket, AccErrors3} = lists:foldl( - fun({Doc, Ref}, {AccPrepped2, AccErrors2}) -> + fun(Doc, {AccPrepped2, AccErrors2}) -> case couch_doc:has_stubs(Doc) of true -> couch_doc:merge_stubs(Doc, #doc{}); % will throw exception @@ -698,7 +700,7 @@ prep_and_validate_replicated_updates(Db, [Bucket|RestBuckets], [OldInfo|RestOldI end, case validate_doc_update(Db, Doc, fun() -> nil end) of ok -> - {[{Doc, Ref} | AccPrepped2], AccErrors2}; + {[Doc | AccPrepped2], AccErrors2}; Error -> {AccPrepped2, [{Doc, Error} | AccErrors2]} end @@ -709,7 +711,7 @@ prep_and_validate_replicated_updates(Db, [Bucket|RestBuckets], [OldInfo|RestOldI OldLeafs = couch_key_tree:get_all_leafs_full(OldTree), OldLeafsLU = [{Start, RevId} || {Start, [{RevId, _}|_]} <- OldLeafs], NewRevTree = lists:foldl( - fun({NewDoc, _Ref}, AccTree) -> + fun(NewDoc, AccTree) -> {NewTree, _} = couch_key_tree:merge(AccTree, couch_doc:to_path(NewDoc), Db#db.revs_limit), NewTree @@ -719,7 +721,7 @@ prep_and_validate_replicated_updates(Db, [Bucket|RestBuckets], [OldInfo|RestOldI LeafRevsFullDict = dict:from_list( [{{Start, RevId}, FullPath} || {Start, [{RevId, _}|_]}=FullPath <- Leafs]), {ValidatedBucket, AccErrors3} = lists:foldl( - fun({#doc{id=Id,revs={Pos, [RevId|_]}}=Doc, Ref}, {AccValidated, AccErrors2}) -> + fun(#doc{id=Id,revs={Pos, [RevId|_]}}=Doc, {AccValidated, AccErrors2}) -> IsOldLeaf = lists:member({Pos, RevId}, OldLeafsLU), case dict:find({Pos, RevId}, LeafRevsFullDict) of {ok, {Start, Path}} when not IsOldLeaf -> @@ -748,7 +750,7 @@ prep_and_validate_replicated_updates(Db, [Bucket|RestBuckets], [OldInfo|RestOldI case validate_doc_update(Db, Doc2, GetDiskDocFun) of ok -> - {[{Doc2, Ref} | AccValidated], AccErrors2}; + {[Doc2 | AccValidated], AccErrors2}; Error -> {AccValidated, [{Doc, Error} | AccErrors2]} end; @@ -780,10 +782,10 @@ new_revs([], OutBuckets, IdRevsAcc) -> {lists:reverse(OutBuckets), IdRevsAcc}; new_revs([Bucket|RestBuckets], OutBuckets, IdRevsAcc) -> {NewBucket, IdRevsAcc3} = lists:mapfoldl( - fun({#doc{revs={Start, RevIds}}=Doc, Ref}, IdRevsAcc2)-> + fun(#doc{id=Id,revs={Start, RevIds}}=Doc, IdRevsAcc2)-> NewRevId = new_revid(Doc), - {{Doc#doc{revs={Start+1, [NewRevId | RevIds]}}, Ref}, - [{Ref, {ok, {Start+1, NewRevId}}} | IdRevsAcc2]} + {Doc#doc{revs={Start+1, [NewRevId | RevIds]}}, + [{{Id, {Start, RevIds}}, {ok, {Start+1, NewRevId}}} | IdRevsAcc2]} end, IdRevsAcc, Bucket), new_revs(RestBuckets, [NewBucket|OutBuckets], IdRevsAcc3). @@ -802,17 +804,15 @@ check_dup_atts2(_) -> update_docs(Db, Docs, Options, replicated_changes) -> increment_stat(Db, {couchdb, database_writes}), - % associate reference with each doc in order to track duplicates - Docs2 = lists:map(fun(Doc) -> {Doc, make_ref()} end, Docs), - DocBuckets = before_docs_update(Db, group_alike_docs(Docs2)), + DocBuckets = before_docs_update(Db, group_alike_docs(Docs)), case (Db#db.validate_doc_funs /= []) orelse lists:any( - fun({#doc{id= <>}, _Ref}) -> true; - ({#doc{atts=Atts}, _Ref}) -> + fun(#doc{id= <>}) -> true; + (#doc{atts=Atts}) -> Atts /= [] - end, Docs2) of + end, Docs) of true -> - Ids = [Id || [{#doc{id=Id}, _Ref}|_] <- DocBuckets], + Ids = [Id || [#doc{id=Id}|_] <- DocBuckets], ExistingDocs = get_full_doc_infos(Db, Ids), {DocBuckets2, DocErrors} = @@ -822,8 +822,8 @@ update_docs(Db, Docs, Options, replicated_changes) -> DocErrors = [], DocBuckets3 = DocBuckets end, - DocBuckets4 = [[{doc_flush_atts(check_dup_atts(Doc), Db#db.fd), Ref} - || {Doc, Ref} <- Bucket] || Bucket <- DocBuckets3], + DocBuckets4 = [[doc_flush_atts(check_dup_atts(Doc), Db#db.fd) + || Doc <- Bucket] || Bucket <- DocBuckets3], {ok, []} = write_and_commit(Db, DocBuckets4, [], [merge_conflicts | Options]), {ok, DocErrors}; @@ -833,30 +833,28 @@ update_docs(Db, Docs, Options, interactive_edit) -> % go ahead and generate the new revision ids for the documents. % separate out the NonRep documents from the rest of the documents - % associate reference with each doc in order to track duplicates - Docs2 = lists:map(fun(Doc) -> {Doc, make_ref()} end,Docs), - {Docs3, NonRepDocs} = lists:foldl( - fun({#doc{id=Id},_Ref}=Doc, {DocsAcc, NonRepDocsAcc}) -> + {Docs2, NonRepDocs} = lists:foldl( + fun(#doc{id=Id}=Doc, {DocsAcc, NonRepDocsAcc}) -> case Id of <> -> {DocsAcc, [Doc | NonRepDocsAcc]}; Id-> {[Doc | DocsAcc], NonRepDocsAcc} end - end, {[], []}, Docs2), + end, {[], []}, Docs), - DocBuckets = before_docs_update(Db, group_alike_docs(Docs3)), + DocBuckets = before_docs_update(Db, group_alike_docs(Docs2)), case (Db#db.validate_doc_funs /= []) orelse lists:any( - fun({#doc{id= <>}, _Ref}) -> + fun(#doc{id= <>}) -> true; - ({#doc{atts=Atts}, _Ref}) -> + (#doc{atts=Atts}) -> Atts /= [] - end, Docs3) of + end, Docs2) of true -> % lookup the doc by id and get the most recent - Ids = [Id || [{#doc{id=Id}, _Ref}|_] <- DocBuckets], + Ids = [Id || [#doc{id=Id}|_] <- DocBuckets], ExistingDocInfos = get_full_doc_infos(Db, Ids), {DocBucketsPrepped, PreCommitFailures} = prep_and_validate_updates(Db, @@ -870,38 +868,29 @@ update_docs(Db, Docs, Options, interactive_edit) -> end, if (AllOrNothing) and (PreCommitFailures /= []) -> - {aborted, - lists:foldl(fun({#doc{id=Id,revs=Revs}, Ref},Acc) -> - case lists:keyfind(Ref,1,PreCommitFailures) of - {Ref, Error} -> - case Revs of - {Pos, [RevId|_]} -> - [{{Id,{Pos, RevId}}, Error} | Acc]; - {0, []} -> - [{{Id,{0, <<>>}}, Error} | Acc] - end; - false -> - Acc - end - end,[],Docs3)}; - + {aborted, lists:map( + fun({{Id,{Pos, [RevId|_]}}, Error}) -> + {{Id, {Pos, RevId}}, Error}; + ({{Id,{0, []}}, Error}) -> + {{Id, {0, <<>>}}, Error} + end, PreCommitFailures)}; true -> Options2 = if AllOrNothing -> [merge_conflicts]; true -> [] end ++ Options, DocBuckets3 = [[ - {doc_flush_atts(set_new_att_revpos( - check_dup_atts(Doc)), Db#db.fd), Ref} - || {Doc, Ref} <- B] || B <- DocBuckets2], + doc_flush_atts(set_new_att_revpos( + check_dup_atts(Doc)), Db#db.fd) + || Doc <- B] || B <- DocBuckets2], {DocBuckets4, IdRevs} = new_revs(DocBuckets3, [], []), {ok, CommitResults} = write_and_commit(Db, DocBuckets4, NonRepDocs, Options2), ResultsDict = dict:from_list(IdRevs ++ CommitResults ++ PreCommitFailures), {ok, lists:map( - fun({#doc{}, Ref}) -> - {ok, Result} = dict:find(Ref, ResultsDict), + fun(#doc{id=Id,revs={Pos, RevIds}}) -> + {ok, Result} = dict:find({Id, {Pos, RevIds}}, ResultsDict), Result - end, Docs2)} + end, Docs)} end. % Returns the first available document on disk. Input list is a full rev path @@ -962,7 +951,7 @@ write_and_commit(#db{main_pid=Pid, user_ctx=Ctx}=Db, DocBuckets1, % compaction. Retry by reopening the db and writing to the current file {ok, Db2} = open(Db#db.name, [{user_ctx, Ctx}]), DocBuckets2 = [ - [{doc_flush_atts(Doc, Db2#db.fd), Ref} || {Doc, Ref} <- Bucket] || + [doc_flush_atts(Doc, Db2#db.fd) || Doc <- Bucket] || Bucket <- DocBuckets1 ], % We only retry once @@ -981,7 +970,7 @@ write_and_commit(#db{main_pid=Pid, user_ctx=Ctx}=Db, DocBuckets1, prepare_doc_summaries(Db, BucketList) -> [lists:map( - fun({#doc{body = Body, atts = Atts} = Doc, Ref}) -> + fun(#doc{body = Body, atts = Atts} = Doc) -> DiskAtts = [{N, T, P, AL, DL, R, M, E} || #att{name = N, type = T, data = {_, P}, md5 = M, revpos = R, att_len = AL, disk_len = DL, encoding = E} <- Atts], @@ -992,7 +981,7 @@ prepare_doc_summaries(Db, BucketList) -> nil end, SummaryChunk = couch_db_updater:make_doc_summary(Db, {Body, DiskAtts}), - {Doc#doc{body = {summary, SummaryChunk, AttsFd}}, Ref} + Doc#doc{body = {summary, SummaryChunk, AttsFd}} end, Bucket) || Bucket <- BucketList]. @@ -1001,9 +990,8 @@ before_docs_update(#db{before_doc_update = nil}, BucketList) -> BucketList; before_docs_update(#db{before_doc_update = Fun} = Db, BucketList) -> [lists:map( - fun({Doc, Ref}) -> - NewDoc = Fun(couch_doc:with_ejson_body(Doc), Db), - {NewDoc, Ref} + fun(Doc) -> + Fun(couch_doc:with_ejson_body(Doc), Db) end, Bucket) || Bucket <- BucketList]. http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/7f661535/src/couch_db_updater.erl ---------------------------------------------------------------------- diff --git a/src/couch_db_updater.erl b/src/couch_db_updater.erl index 5cdb876..09028bd 100644 --- a/src/couch_db_updater.erl +++ b/src/couch_db_updater.erl @@ -319,11 +319,11 @@ handle_info({'DOWN', Ref, _, _, Reason}, #db{fd_monitor=Ref, name=Name} = Db) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. -merge_updates([[{_,{#doc{id=X},_}}|_]=A|RestA], [[{_,{#doc{id=X},_}}|_]=B|RestB]) -> +merge_updates([[{_,#doc{id=X}}|_]=A|RestA], [[{_,#doc{id=X}}|_]=B|RestB]) -> [A++B | merge_updates(RestA, RestB)]; -merge_updates([[{_,{#doc{id=X},_}}|_]|_]=A, [[{_,{#doc{id=Y},_}}|_]|_]=B) when X < Y -> +merge_updates([[{_,#doc{id=X}}|_]|_]=A, [[{_,#doc{id=Y}}|_]|_]=B) when X < Y -> [hd(A) | merge_updates(tl(A), B)]; -merge_updates([[{_,{#doc{id=X},_}}|_]|_]=A, [[{_,{#doc{id=Y},_}}|_]|_]=B) when X > Y -> +merge_updates([[{_,#doc{id=X}}|_]|_]=A, [[{_,#doc{id=Y}}|_]|_]=B) when X > Y -> [hd(B) | merge_updates(A, tl(B))]; merge_updates([], RestB) -> RestB; @@ -597,9 +597,9 @@ flush_trees(#db{fd = Fd} = Db, flush_trees(Db, RestUnflushed, [InfoFlushed | AccFlushed]). -send_result(Client, Ref, NewResult) -> +send_result(Client, Id, OriginalRevs, NewResult) -> % used to send a result to the client - catch(Client ! {result, self(), {Ref, NewResult}}). + catch(Client ! {result, self(), {{Id, OriginalRevs}, NewResult}}). merge_rev_trees(_Limit, _Merge, [], [], AccNewInfos, AccRemoveSeqs, AccSeq) -> {ok, lists:reverse(AccNewInfos), AccRemoveSeqs, AccSeq}; @@ -608,12 +608,12 @@ merge_rev_trees(Limit, MergeConflicts, [NewDocs|RestDocsList], #full_doc_info{id=Id,rev_tree=OldTree,deleted=OldDeleted0,update_seq=OldSeq} = OldDocInfo, {NewRevTree, _} = lists:foldl( - fun({Client, {#doc{revs={Pos,[_Rev|PrevRevs]}}=NewDoc, Ref}}, {AccTree, OldDeleted}) -> + fun({Client, #doc{revs={Pos,[_Rev|PrevRevs]}}=NewDoc}, {AccTree, OldDeleted}) -> if not MergeConflicts -> case couch_key_tree:merge(AccTree, couch_doc:to_path(NewDoc), Limit) of {_NewTree, conflicts} when (not OldDeleted) -> - send_result(Client, Ref, conflict), + send_result(Client, Id, {Pos-1,PrevRevs}, conflict), {AccTree, OldDeleted}; {NewTree, conflicts} when PrevRevs /= [] -> % Check to be sure if prev revision was specified, it's @@ -625,7 +625,7 @@ merge_rev_trees(Limit, MergeConflicts, [NewDocs|RestDocsList], if IsPrevLeaf -> {NewTree, OldDeleted}; true -> - send_result(Client, Ref, conflict), + send_result(Client, Id, {Pos-1,PrevRevs}, conflict), {AccTree, OldDeleted} end; {NewTree, no_conflicts} when AccTree == NewTree -> @@ -644,10 +644,11 @@ merge_rev_trees(Limit, MergeConflicts, [NewDocs|RestDocsList], {NewTree2, _} = couch_key_tree:merge(AccTree, couch_doc:to_path(NewDoc2), Limit), % we changed the rev id, this tells the caller we did - send_result(Client, Ref, {ok, {OldPos + 1, NewRevId}}), + send_result(Client, Id, {Pos-1,PrevRevs}, + {ok, {OldPos + 1, NewRevId}}), {NewTree2, OldDeleted}; true -> - send_result(Client, Ref, conflict), + send_result(Client, Id, {Pos-1,PrevRevs}, conflict), {AccTree, OldDeleted} end; {NewTree, _} -> @@ -700,7 +701,7 @@ update_docs_int(Db, DocsList, NonRepDocs, MergeConflicts, FullCommit) -> update_seq = LastSeq, revs_limit = RevsLimit } = Db, - Ids = [Id || [{_Client, {#doc{id=Id}, _Ref}}|_] <- 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( @@ -750,10 +751,10 @@ update_docs_int(Db, DocsList, NonRepDocs, MergeConflicts, FullCommit) -> update_local_docs(Db, []) -> {ok, Db}; update_local_docs(#db{local_tree=Btree}=Db, Docs) -> - Ids = [Id || {_Client, {#doc{id=Id}, _Ref}} <- Docs], + Ids = [Id || {_Client, #doc{id=Id}} <- Docs], OldDocLookups = couch_btree:lookup(Btree, Ids), BtreeEntries = lists:zipwith( - fun({Client, {#doc{id=Id,deleted=Delete,revs={0,PrevRevs},body=Body}, Ref}}, _OldDocLookup) -> + fun({Client, #doc{id=Id,deleted=Delete,revs={0,PrevRevs},body=Body}}, _OldDocLookup) -> case PrevRevs of [RevStr|_] -> PrevRev = list_to_integer(?b2l(RevStr)); @@ -770,11 +771,11 @@ update_local_docs(#db{local_tree=Btree}=Db, Docs) -> % true -> case Delete of false -> - send_result(Client, Ref, {ok, + send_result(Client, Id, {0, PrevRevs}, {ok, {0, ?l2b(integer_to_list(PrevRev + 1))}}), {update, {Id, {PrevRev + 1, Body}}}; true -> - send_result(Client, Ref, + send_result(Client, Id, {0, PrevRevs}, {ok, {0, <<"0">>}}), {remove, Id} end%;