summaryrefslogtreecommitdiff
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
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
-rw-r--r--etc/couchdb/local_dev.ini2
-rw-r--r--share/www/script/test/conflicts.js4
-rw-r--r--src/couchdb/couch_db_updater.erl26
3 files changed, 19 insertions, 13 deletions
diff --git a/etc/couchdb/local_dev.ini b/etc/couchdb/local_dev.ini
index 54c75bde..876295b1 100644
--- a/etc/couchdb/local_dev.ini
+++ b/etc/couchdb/local_dev.ini
@@ -12,7 +12,7 @@
;bind_address = 127.0.0.1
[log]
-; level = debug
+level = error
[update_notification]
;unique notifier name=/full/path/to/exe -with "cmd line arg"
diff --git a/share/www/script/test/conflicts.js b/share/www/script/test/conflicts.js
index 02e50035..dfd7e8b6 100644
--- a/share/www/script/test/conflicts.js
+++ b/share/www/script/test/conflicts.js
@@ -41,6 +41,10 @@ couchTests.conflicts = function(debug) {
} catch (e) {
T(e.error == "conflict");
}
+
+ var bySeq = db.allDocsBySeq();
+
+ T( bySeq.rows.length == 1)
// Now clear out the _rev member and save. This indicates this document is
// new, not based on an existing revision.
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),