diff options
author | Damien F. Katz <damien@apache.org> | 2009-03-21 12:27:40 +0000 |
---|---|---|
committer | Damien F. Katz <damien@apache.org> | 2009-03-21 12:27:40 +0000 |
commit | cc3cd646a64e2cd6e4c318532ba469b152defb41 (patch) | |
tree | 0d6179a51074f107cee37f418f2c0a0f29029722 /src/couchdb | |
parent | 13c7fee8168769542bba96a5f06e00110d00a81a (diff) |
Fix for COUCHDB-300. Old seq were being removed when a conflict. An old bug, but recent changes made it much more likely to happen.
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@756925 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/couchdb')
-rw-r--r-- | src/couchdb/couch_db_updater.erl | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/src/couchdb/couch_db_updater.erl b/src/couchdb/couch_db_updater.erl index 7752a577..969a79d4 100644 --- a/src/couchdb/couch_db_updater.erl +++ b/src/couchdb/couch_db_updater.erl @@ -357,11 +357,12 @@ flush_trees(#db{fd=Fd}=Db, [InfoUnflushed | RestUnflushed], AccFlushed) -> end, Unflushed), flush_trees(Db, RestUnflushed, [InfoUnflushed#full_doc_info{rev_tree=Flushed} | AccFlushed]). -merge_rev_trees(_MergeConflicts, [], [], AccNewInfos, AccConflicts, AccSeq) -> - {ok, lists:reverse(AccNewInfos), AccConflicts, AccSeq}; +merge_rev_trees(_MergeConflicts, [], [], AccNewInfos, AccRemoveSeqs, AccConflicts, AccSeq) -> + {ok, lists:reverse(AccNewInfos), AccRemoveSeqs, AccConflicts, AccSeq}; merge_rev_trees(MergeConflicts, [NewDocs|RestDocsList], - [OldDocInfo|RestOldInfo], AccNewInfos, AccConflicts, AccSeq) -> - #full_doc_info{id=Id,rev_tree=OldTree,deleted=OldDeleted}=OldDocInfo, + [OldDocInfo|RestOldInfo], AccNewInfos, AccRemoveSeqs, AccConflicts, AccSeq) -> + #full_doc_info{id=Id,rev_tree=OldTree,deleted=OldDeleted,update_seq=OldSeq} + = OldDocInfo, {NewRevTree, NewConflicts} = lists:foldl( fun(#doc{revs={Pos,[Rev|_]}}=NewDoc, {AccTree, AccConflicts2}) -> case couch_key_tree:merge(AccTree, [couch_db:doc_to_tree(NewDoc)]) of @@ -376,12 +377,16 @@ merge_rev_trees(MergeConflicts, [NewDocs|RestDocsList], if NewRevTree == OldTree -> % nothing changed merge_rev_trees(MergeConflicts, RestDocsList, RestOldInfo, AccNewInfos, - NewConflicts, AccSeq); + AccRemoveSeqs, NewConflicts, 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}, - merge_rev_trees(MergeConflicts, RestDocsList,RestOldInfo, - [NewInfo|AccNewInfos], NewConflicts, AccSeq+1) + RemoveSeqs = case OldSeq of + 0 -> AccRemoveSeqs; + _ -> [OldSeq | AccRemoveSeqs] + end, + merge_rev_trees(MergeConflicts, RestDocsList, RestOldInfo, + [NewInfo|AccNewInfos], RemoveSeqs, NewConflicts, AccSeq+1) end. new_index_entries([], AccById, AccBySeq) -> @@ -428,15 +433,12 @@ update_docs_int(Db, DocsList, Options) -> Ids, OldDocLookups), % Merge the new docs into the revision trees. - {ok, NewDocInfos0, Conflicts, NewSeq} = merge_rev_trees( + {ok, NewDocInfos0, RemoveSeqs, Conflicts, NewSeq} = merge_rev_trees( lists:member(merge_conflicts, Options), - DocsList2, OldDocInfos, [], [], LastSeq), + DocsList2, OldDocInfos, [], [], [], LastSeq), NewDocInfos = stem_full_doc_infos(Db, NewDocInfos0), - RemoveSeqs = - [OldSeq || {ok, #full_doc_info{update_seq=OldSeq}} <- OldDocLookups], - % All documents are now ready to write. {ok, LocalConflicts, Db2} = update_local_docs(Db, NonRepDocs), |