summaryrefslogtreecommitdiff
path: root/src/couchdb
diff options
context:
space:
mode:
authorDamien F. Katz <damien@apache.org>2009-03-21 12:27:40 +0000
committerDamien F. Katz <damien@apache.org>2009-03-21 12:27:40 +0000
commitcc3cd646a64e2cd6e4c318532ba469b152defb41 (patch)
tree0d6179a51074f107cee37f418f2c0a0f29029722 /src/couchdb
parent13c7fee8168769542bba96a5f06e00110d00a81a (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.erl26
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),